Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
authorLinus Torvalds <torvalds@g5.osdl.org>
Sun, 1 Oct 2006 07:40:55 +0000 (00:40 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 1 Oct 2006 07:40:55 +0000 (00:40 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart:
  [AGPGART] printk fixups.
  [AGPGART] Use pci_get_slot not pci_find_slot

2929 files changed:
CREDITS
Documentation/CodingStyle
Documentation/DocBook/kernel-api.tmpl
Documentation/DocBook/usb.tmpl
Documentation/HOWTO
Documentation/IPMI.txt
Documentation/SubmitChecklist
Documentation/SubmittingDrivers
Documentation/SubmittingPatches
Documentation/accounting/getdelays.c
Documentation/accounting/taskstats-struct.txt [new file with mode: 0644]
Documentation/cpusets.txt
Documentation/devices.txt
Documentation/fb/intelfb.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/Locking
Documentation/filesystems/proc.txt
Documentation/filesystems/vfs.txt
Documentation/hwmon/it87
Documentation/hwmon/k8temp [new file with mode: 0644]
Documentation/hwmon/vt1211 [new file with mode: 0644]
Documentation/hwmon/w83627ehf [new file with mode: 0644]
Documentation/hwmon/w83791d
Documentation/i2c/busses/i2c-viapro
Documentation/i2c/i2c-stub
Documentation/kernel-parameters.txt
Documentation/lockdep-design.txt
Documentation/networking/bonding.txt
Documentation/networking/pktgen.txt
Documentation/nommu-mmap.txt
Documentation/pcieaer-howto.txt [new file with mode: 0644]
Documentation/rt-mutex-design.txt
Documentation/seclvl.txt [deleted file]
Documentation/sh/new-machine.txt
Documentation/sh/register-banks.txt [new file with mode: 0644]
Documentation/usb/error-codes.txt
Documentation/usb/usb-serial.txt
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/bttv/Insmod-options
Documentation/video4linux/cx2341x/README.hm12 [new file with mode: 0644]
Documentation/video4linux/cx2341x/README.vbi [new file with mode: 0644]
Documentation/x86_64/boot-options.txt
MAINTAINERS
Makefile
arch/alpha/kernel/proto.h
arch/alpha/kernel/time.c
arch/alpha/mm/Makefile
arch/alpha/mm/fault.c
arch/alpha/mm/remap.c [deleted file]
arch/arm/Kconfig
arch/arm/Kconfig-nommu
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/misc.c
arch/arm/common/icst307.c
arch/arm/common/icst525.c
arch/arm/common/locomo.c
arch/arm/common/sharpsl_pm.c
arch/arm/configs/ep80219_defconfig [deleted file]
arch/arm/configs/ep93xx_defconfig
arch/arm/configs/iop32x_defconfig [new file with mode: 0644]
arch/arm/configs/iop33x_defconfig [new file with mode: 0644]
arch/arm/configs/iq31244_defconfig [deleted file]
arch/arm/configs/iq80321_defconfig [deleted file]
arch/arm/configs/iq80331_defconfig [deleted file]
arch/arm/configs/iq80332_defconfig [deleted file]
arch/arm/configs/s3c2410_defconfig
arch/arm/kernel/apm.c
arch/arm/kernel/debug.S
arch/arm/kernel/ecard.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/head-nommu.S
arch/arm/kernel/module.c
arch/arm/kernel/process.c
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/mach-at91rm9200/at91rm9200.c
arch/arm/mach-at91rm9200/board-1arm.c
arch/arm/mach-at91rm9200/board-carmeva.c
arch/arm/mach-at91rm9200/board-csb337.c
arch/arm/mach-at91rm9200/board-csb637.c
arch/arm/mach-at91rm9200/board-dk.c
arch/arm/mach-at91rm9200/board-eb9200.c
arch/arm/mach-at91rm9200/board-ek.c
arch/arm/mach-at91rm9200/board-kafa.c
arch/arm/mach-at91rm9200/board-kb9202.c
arch/arm/mach-at91rm9200/clock.c
arch/arm/mach-at91rm9200/clock.h [new file with mode: 0644]
arch/arm/mach-at91rm9200/devices.c
arch/arm/mach-at91rm9200/generic.h
arch/arm/mach-at91rm9200/gpio.c
arch/arm/mach-at91rm9200/irq.c
arch/arm/mach-at91rm9200/pm.c
arch/arm/mach-ep93xx/Kconfig
arch/arm/mach-ep93xx/Makefile
arch/arm/mach-ep93xx/edb9312.c [new file with mode: 0644]
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-iop32x/Kconfig [new file with mode: 0644]
arch/arm/mach-iop32x/Makefile [new file with mode: 0644]
arch/arm/mach-iop32x/Makefile.boot [new file with mode: 0644]
arch/arm/mach-iop32x/glantank.c [new file with mode: 0644]
arch/arm/mach-iop32x/iq31244.c [new file with mode: 0644]
arch/arm/mach-iop32x/iq80321.c [new file with mode: 0644]
arch/arm/mach-iop32x/irq.c [new file with mode: 0644]
arch/arm/mach-iop32x/n2100.c [new file with mode: 0644]
arch/arm/mach-iop33x/Kconfig [new file with mode: 0644]
arch/arm/mach-iop33x/Makefile [new file with mode: 0644]
arch/arm/mach-iop33x/Makefile.boot [new file with mode: 0644]
arch/arm/mach-iop33x/iq80331.c [new file with mode: 0644]
arch/arm/mach-iop33x/iq80332.c [new file with mode: 0644]
arch/arm/mach-iop33x/irq.c [new file with mode: 0644]
arch/arm/mach-iop33x/uart.c [new file with mode: 0644]
arch/arm/mach-iop3xx/Kconfig [deleted file]
arch/arm/mach-iop3xx/Makefile [deleted file]
arch/arm/mach-iop3xx/Makefile.boot [deleted file]
arch/arm/mach-iop3xx/common.c [deleted file]
arch/arm/mach-iop3xx/iop321-irq.c [deleted file]
arch/arm/mach-iop3xx/iop321-pci.c [deleted file]
arch/arm/mach-iop3xx/iop321-setup.c [deleted file]
arch/arm/mach-iop3xx/iop321-time.c [deleted file]
arch/arm/mach-iop3xx/iop331-irq.c [deleted file]
arch/arm/mach-iop3xx/iop331-pci.c [deleted file]
arch/arm/mach-iop3xx/iop331-setup.c [deleted file]
arch/arm/mach-iop3xx/iop331-time.c [deleted file]
arch/arm/mach-iop3xx/iq31244-mm.c [deleted file]
arch/arm/mach-iop3xx/iq31244-pci.c [deleted file]
arch/arm/mach-iop3xx/iq80321-mm.c [deleted file]
arch/arm/mach-iop3xx/iq80321-pci.c [deleted file]
arch/arm/mach-iop3xx/iq80331-mm.c [deleted file]
arch/arm/mach-iop3xx/iq80331-pci.c [deleted file]
arch/arm/mach-iop3xx/iq80332-mm.c [deleted file]
arch/arm/mach-iop3xx/iq80332-pci.c [deleted file]
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-omap1/board-fsample.c
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-perseus2.c
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap1/clock.h
arch/arm/mach-omap1/mux.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/prcm.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/Makefile
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/cpu.c
arch/arm/mach-s3c2410/devs.h
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/dma.h [new file with mode: 0644]
arch/arm/mach-s3c2410/gpio.c
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-amlm5900.c [new file with mode: 0644]
arch/arm/mach-s3c2410/mach-anubis.c
arch/arm/mach-s3c2410/mach-smdk2440.c
arch/arm/mach-s3c2410/mach-vstms.c [new file with mode: 0644]
arch/arm/mach-s3c2410/pm-simtec.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2410/pm.h
arch/arm/mach-s3c2410/s3c2410-dma.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2410-irq.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2410-pm.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2410-sleep.S [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/s3c2412-dma.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2412-irq.c
arch/arm/mach-s3c2410/s3c2412-pm.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2412.c
arch/arm/mach-s3c2410/s3c2440-dma.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2440-dsc.c
arch/arm/mach-s3c2410/s3c2440-irq.c
arch/arm/mach-s3c2410/s3c244x-irq.c
arch/arm/mach-s3c2410/sleep.S
arch/arm/mach-s3c2410/usb-simtec.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-versatile/pci.c
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/mm/abort-lv4t.S
arch/arm/mm/abort-nommu.S [new file with mode: 0644]
arch/arm/mm/alignment.c
arch/arm/mm/cache-v4.S
arch/arm/mm/context.c [new file with mode: 0644]
arch/arm/mm/copypage-v4mc.c
arch/arm/mm/copypage-v6.c
arch/arm/mm/copypage-xscale.c
arch/arm/mm/fault.c
arch/arm/mm/fault.h
arch/arm/mm/flush.c
arch/arm/mm/init.c
arch/arm/mm/mm-armv.c [deleted file]
arch/arm/mm/mm.h [new file with mode: 0644]
arch/arm/mm/mmap.c
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/pgd.c [new file with mode: 0644]
arch/arm/mm/proc-arm740.S [new file with mode: 0644]
arch/arm/mm/proc-arm7tdmi.S [new file with mode: 0644]
arch/arm/mm/proc-arm940.S [new file with mode: 0644]
arch/arm/mm/proc-arm946.S [new file with mode: 0644]
arch/arm/mm/proc-arm9tdmi.S [new file with mode: 0644]
arch/arm/mm/proc-xscale.S
arch/arm/oprofile/op_model_xscale.c
arch/arm/plat-iop/Makefile [new file with mode: 0644]
arch/arm/plat-iop/gpio.c [new file with mode: 0644]
arch/arm/plat-iop/i2c.c [new file with mode: 0644]
arch/arm/plat-iop/pci.c [new file with mode: 0644]
arch/arm/plat-iop/setup.c [new file with mode: 0644]
arch/arm/plat-iop/time.c [new file with mode: 0644]
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/pm.c [deleted file]
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/timer32k.c
arch/arm/plat-omap/usb.c
arch/arm/tools/mach-types
arch/arm/vfp/vfp.h
arch/arm/vfp/vfpdouble.c
arch/arm/vfp/vfpinstr.h
arch/arm/vfp/vfpmodule.c
arch/arm/vfp/vfpsingle.c
arch/arm26/kernel/time.c
arch/arm26/mm/fault.c
arch/avr32/kernel/time.c
arch/avr32/mm/ioremap.c
arch/avr32/mm/tlb.c
arch/cris/arch-v10/kernel/time.c
arch/cris/arch-v32/kernel/time.c
arch/cris/kernel/time.c
arch/cris/mm/ioremap.c
arch/frv/kernel/time.c
arch/h8300/kernel/time.c
arch/i386/Kconfig
arch/i386/boot/video.S
arch/i386/defconfig
arch/i386/kernel/apm.c
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/crash.c
arch/i386/kernel/efi.c
arch/i386/kernel/i8237.c
arch/i386/kernel/microcode.c
arch/i386/kernel/nmi.c
arch/i386/kernel/process.c
arch/i386/kernel/setup.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/srat.c
arch/i386/kernel/time.c
arch/i386/kernel/traps.c
arch/i386/lib/delay.c
arch/i386/lib/usercopy.c
arch/i386/mach-voyager/voyager_smp.c
arch/i386/mm/discontig.c
arch/i386/mm/fault.c
arch/i386/mm/highmem.c
arch/i386/mm/init.c
arch/i386/mm/ioremap.c
arch/i386/oprofile/op_model_ppro.c
arch/i386/pci/mmconfig.c
arch/ia64/Kconfig
arch/ia64/hp/sim/simeth.c
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/Makefile
arch/ia64/kernel/entry.S
arch/ia64/kernel/esi.c [new file with mode: 0644]
arch/ia64/kernel/esi_stub.S [new file with mode: 0644]
arch/ia64/kernel/ia64_ksyms.c
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/mca_drv.h
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/fault.c
arch/ia64/mm/init.c
arch/ia64/mm/numa.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/bte.c
arch/ia64/sn/pci/pcibr/pcibr_ate.c
arch/ia64/sn/pci/pcibr/pcibr_dma.c
arch/m32r/kernel/time.c
arch/m32r/mm/fault.c
arch/m32r/mm/ioremap.c
arch/m68k/kernel/time.c
arch/m68k/mm/fault.c
arch/m68k/sun3/sun3ints.c
arch/m68knommu/kernel/time.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/au1000/common/time.c
arch/mips/au1000/db1x00/Makefile
arch/mips/au1000/db1x00/mirage_ts.c [deleted file]
arch/mips/basler/excite/excite_device.c
arch/mips/basler/excite/excite_fpga.h [deleted file]
arch/mips/configs/atlas_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/cobalt_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1100_defconfig
arch/mips/configs/db1200_defconfig
arch/mips/configs/db1500_defconfig
arch/mips/configs/db1550_defconfig
arch/mips/configs/ddb5477_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/emma2rh_defconfig
arch/mips/configs/ev64120_defconfig
arch/mips/configs/ev96100_defconfig [deleted file]
arch/mips/configs/excite_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/it8172_defconfig
arch/mips/configs/ivr_defconfig
arch/mips/configs/jaguar-atx_defconfig
arch/mips/configs/jmr3927_defconfig
arch/mips/configs/lasat200_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/mipssim_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/ocelot_3_defconfig
arch/mips/configs/ocelot_c_defconfig
arch/mips/configs/ocelot_defconfig
arch/mips/configs/ocelot_g_defconfig
arch/mips/configs/pb1100_defconfig
arch/mips/configs/pb1500_defconfig
arch/mips/configs/pb1550_defconfig
arch/mips/configs/pnx8550-jbs_defconfig
arch/mips/configs/pnx8550-v2pci_defconfig
arch/mips/configs/qemu_defconfig
arch/mips/configs/rbhma4500_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/sb1250-swarm_defconfig
arch/mips/configs/sead_defconfig
arch/mips/configs/tb0226_defconfig
arch/mips/configs/tb0229_defconfig
arch/mips/configs/tb0287_defconfig
arch/mips/configs/workpad_defconfig
arch/mips/configs/wrppmc_defconfig
arch/mips/configs/yosemite_defconfig
arch/mips/defconfig
arch/mips/galileo-boards/ev96100/Makefile [deleted file]
arch/mips/galileo-boards/ev96100/init.c [deleted file]
arch/mips/galileo-boards/ev96100/irq.c [deleted file]
arch/mips/galileo-boards/ev96100/puts.c [deleted file]
arch/mips/galileo-boards/ev96100/reset.c [deleted file]
arch/mips/galileo-boards/ev96100/setup.c [deleted file]
arch/mips/galileo-boards/ev96100/time.c [deleted file]
arch/mips/gt64120/common/time.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/linux32.c
arch/mips/kernel/process.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smtc-asm.S
arch/mips/kernel/syscall.c
arch/mips/kernel/time.c
arch/mips/kernel/traps.c
arch/mips/kernel/vpe.c
arch/mips/mips-boards/atlas/atlas_int.c
arch/mips/mips-boards/atlas/atlas_setup.c
arch/mips/mips-boards/generic/time.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-sb1.c
arch/mips/mm/c-tx39.c
arch/mips/mm/cache.c
arch/mips/mm/fault.c
arch/mips/mm/tlb-r4k.c
arch/mips/momentum/ocelot_g/gt-irq.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-atlas.c
arch/mips/pci/fixup-ev96100.c [deleted file]
arch/mips/pci/ops-au1000.c
arch/mips/pci/ops-gt96100.c [deleted file]
arch/mips/pci/pci-ev96100.c [deleted file]
arch/mips/pci/pci-ip27.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/sb1250/irq.c
arch/parisc/kernel/firmware.c
arch/parisc/kernel/module.c
arch/parisc/kernel/time.c
arch/powerpc/Kconfig
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/time.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/powermac/cpufreq_64.c
arch/powerpc/platforms/powermac/nvram.c
arch/powerpc/platforms/pseries/hvCall_inst.c
arch/powerpc/platforms/pseries/ras.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/mpic.c
arch/ppc/Kconfig
arch/ppc/kernel/setup.c
arch/ppc/kernel/time.c
arch/ppc/kernel/traps.c
arch/ppc/mm/fault.c
arch/ppc/mm/init.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/appldata/appldata_base.c
arch/s390/crypto/crypt_s390.h
arch/s390/hypfs/hypfs_diag.c
arch/s390/hypfs/inode.c
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/cpcmd.c
arch/s390/kernel/debug.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/process.c
arch/s390/kernel/reipl.S
arch/s390/kernel/reipl64.S
arch/s390/kernel/relocate_kernel.S
arch/s390/kernel/relocate_kernel64.S
arch/s390/kernel/semaphore.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/time.c
arch/s390/kernel/traps.c
arch/s390/lib/Makefile
arch/s390/lib/delay.c
arch/s390/lib/div64.c [new file with mode: 0644]
arch/s390/lib/spinlock.c
arch/s390/lib/uaccess_mvcos.c
arch/s390/lib/uaccess_std.c
arch/s390/math-emu/math.c
arch/s390/math-emu/sfp-util.h
arch/s390/mm/extmem.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/sh/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/adx/Makefile [deleted file]
arch/sh/boards/adx/irq.c [deleted file]
arch/sh/boards/adx/irq_maskreg.c [deleted file]
arch/sh/boards/adx/setup.c [deleted file]
arch/sh/boards/bigsur/irq.c
arch/sh/boards/bigsur/setup.c
arch/sh/boards/cat68701/Makefile [deleted file]
arch/sh/boards/cat68701/irq.c [deleted file]
arch/sh/boards/cat68701/setup.c [deleted file]
arch/sh/boards/cqreek/Makefile [deleted file]
arch/sh/boards/cqreek/irq.c [deleted file]
arch/sh/boards/cqreek/setup.c [deleted file]
arch/sh/boards/dmida/Makefile [deleted file]
arch/sh/boards/dmida/mach.c [deleted file]
arch/sh/boards/dreamcast/irq.c
arch/sh/boards/dreamcast/rtc.c
arch/sh/boards/dreamcast/setup.c
arch/sh/boards/ec3104/setup.c
arch/sh/boards/harp/Makefile [deleted file]
arch/sh/boards/harp/irq.c [deleted file]
arch/sh/boards/harp/led.c [deleted file]
arch/sh/boards/harp/mach.c [deleted file]
arch/sh/boards/harp/pcidma.c [deleted file]
arch/sh/boards/harp/setup.c [deleted file]
arch/sh/boards/hp6xx/Makefile
arch/sh/boards/hp6xx/hp6xx_apm.c [new file with mode: 0644]
arch/sh/boards/hp6xx/pm.c [new file with mode: 0644]
arch/sh/boards/hp6xx/pm_wakeup.S [new file with mode: 0644]
arch/sh/boards/hp6xx/setup.c
arch/sh/boards/landisk/Makefile [new file with mode: 0644]
arch/sh/boards/landisk/io.c [new file with mode: 0644]
arch/sh/boards/landisk/irq.c [new file with mode: 0644]
arch/sh/boards/landisk/landisk_pwb.c [new file with mode: 0644]
arch/sh/boards/landisk/rtc.c [new file with mode: 0644]
arch/sh/boards/landisk/setup.c [new file with mode: 0644]
arch/sh/boards/mpc1211/rtc.c
arch/sh/boards/mpc1211/setup.c
arch/sh/boards/overdrive/Makefile [deleted file]
arch/sh/boards/overdrive/fpga.c [deleted file]
arch/sh/boards/overdrive/galileo.c [deleted file]
arch/sh/boards/overdrive/io.c [deleted file]
arch/sh/boards/overdrive/irq.c [deleted file]
arch/sh/boards/overdrive/led.c [deleted file]
arch/sh/boards/overdrive/mach.c [deleted file]
arch/sh/boards/overdrive/pcidma.c [deleted file]
arch/sh/boards/overdrive/setup.c [deleted file]
arch/sh/boards/renesas/edosk7705/Makefile
arch/sh/boards/renesas/edosk7705/setup.c
arch/sh/boards/renesas/hs7751rvoip/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/hs7751rvoip/Makefile
arch/sh/boards/renesas/hs7751rvoip/io.c
arch/sh/boards/renesas/hs7751rvoip/irq.c
arch/sh/boards/renesas/hs7751rvoip/led.c [deleted file]
arch/sh/boards/renesas/hs7751rvoip/mach.c [deleted file]
arch/sh/boards/renesas/hs7751rvoip/setup.c
arch/sh/boards/renesas/r7780rp/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/io.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/irq.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/led.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/rts7751r2d/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/rts7751r2d/Makefile
arch/sh/boards/renesas/rts7751r2d/io.c
arch/sh/boards/renesas/rts7751r2d/irq.c
arch/sh/boards/renesas/rts7751r2d/led.c
arch/sh/boards/renesas/rts7751r2d/mach.c [deleted file]
arch/sh/boards/renesas/rts7751r2d/setup.c
arch/sh/boards/renesas/sh7710voipgw/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/sh7710voipgw/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/systemh/io.c
arch/sh/boards/renesas/systemh/irq.c
arch/sh/boards/renesas/systemh/setup.c
arch/sh/boards/saturn/setup.c
arch/sh/boards/se/7300/io.c
arch/sh/boards/se/7300/irq.c
arch/sh/boards/se/7300/led.c
arch/sh/boards/se/7300/setup.c
arch/sh/boards/se/73180/io.c
arch/sh/boards/se/73180/irq.c
arch/sh/boards/se/73180/led.c
arch/sh/boards/se/73180/setup.c
arch/sh/boards/se/7343/Makefile [new file with mode: 0644]
arch/sh/boards/se/7343/io.c [new file with mode: 0644]
arch/sh/boards/se/7343/irq.c [new file with mode: 0644]
arch/sh/boards/se/7343/led.c [new file with mode: 0644]
arch/sh/boards/se/7343/setup.c [new file with mode: 0644]
arch/sh/boards/se/770x/Makefile
arch/sh/boards/se/770x/io.c
arch/sh/boards/se/770x/irq.c
arch/sh/boards/se/770x/led.c
arch/sh/boards/se/770x/mach.c [deleted file]
arch/sh/boards/se/770x/setup.c
arch/sh/boards/se/7751/Makefile
arch/sh/boards/se/7751/io.c
arch/sh/boards/se/7751/irq.c
arch/sh/boards/se/7751/led.c
arch/sh/boards/se/7751/mach.c [deleted file]
arch/sh/boards/se/7751/setup.c
arch/sh/boards/sh03/rtc.c
arch/sh/boards/sh03/setup.c
arch/sh/boards/sh2000/Makefile [deleted file]
arch/sh/boards/sh2000/setup.c [deleted file]
arch/sh/boards/shmin/Makefile [new file with mode: 0644]
arch/sh/boards/shmin/setup.c [new file with mode: 0644]
arch/sh/boards/snapgear/io.c
arch/sh/boards/snapgear/rtc.c
arch/sh/boards/snapgear/setup.c
arch/sh/boards/superh/microdev/irq.c
arch/sh/boards/superh/microdev/setup.c
arch/sh/boards/titan/Makefile [new file with mode: 0644]
arch/sh/boards/titan/io.c [new file with mode: 0644]
arch/sh/boards/titan/setup.c [new file with mode: 0644]
arch/sh/boards/unknown/setup.c
arch/sh/boot/compressed/Makefile
arch/sh/cchips/Kconfig
arch/sh/cchips/hd6446x/hd64461/io.c
arch/sh/cchips/hd6446x/hd64461/setup.c
arch/sh/cchips/hd6446x/hd64465/setup.c
arch/sh/cchips/voyagergx/irq.c
arch/sh/cchips/voyagergx/setup.c
arch/sh/configs/landisk_defconfig [new file with mode: 0644]
arch/sh/configs/r7780rp_defconfig [new file with mode: 0644]
arch/sh/configs/se73180_defconfig
arch/sh/configs/se7343_defconfig [new file with mode: 0644]
arch/sh/configs/sh7710voipgw_defconfig [new file with mode: 0644]
arch/sh/configs/shmin_defconfig [new file with mode: 0644]
arch/sh/configs/titan_defconfig [new file with mode: 0644]
arch/sh/drivers/dma/Kconfig
arch/sh/drivers/dma/dma-g2.c
arch/sh/drivers/dma/dma-pvr2.c
arch/sh/drivers/dma/dma-sh.c
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/fixups-dreamcast.c
arch/sh/drivers/pci/fixups-r7780rp.c [new file with mode: 0644]
arch/sh/drivers/pci/fixups-rts7751r2d.c
arch/sh/drivers/pci/fixups-sh03.c
arch/sh/drivers/pci/ops-bigsur.c
arch/sh/drivers/pci/ops-landisk.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-r7780rp.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-rts7751r2d.c
arch/sh/drivers/pci/ops-sh4.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-snapgear.c
arch/sh/drivers/pci/ops-titan.c [new file with mode: 0644]
arch/sh/drivers/pci/pci-auto.c
arch/sh/drivers/pci/pci-sh4.h [new file with mode: 0644]
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7751.h
arch/sh/drivers/pci/pci-sh7780.c [new file with mode: 0644]
arch/sh/drivers/pci/pci-sh7780.h [new file with mode: 0644]
arch/sh/drivers/pci/pci-st40.c
arch/sh/drivers/pci/pci.c
arch/sh/kernel/Makefile
arch/sh/kernel/apm.c [new file with mode: 0644]
arch/sh/kernel/cf-enabler.c
arch/sh/kernel/cpu/Makefile
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/Makefile
arch/sh/kernel/cpu/irq/intc2.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/irq/maskreg.c [new file with mode: 0644]
arch/sh/kernel/cpu/irq/pint.c
arch/sh/kernel/cpu/rtc.c [deleted file]
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/clock-sh7706.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh3/probe.c
arch/sh/kernel/cpu/sh3/setup-sh7300.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7705.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7708.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7709.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7710.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/Makefile
arch/sh/kernel/cpu/sh4/ex.S
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4/setup-sh4-202.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh73180.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7343.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7750.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7760.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7770.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7780.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/sq.c
arch/sh/kernel/early_printk.c
arch/sh/kernel/entry.S
arch/sh/kernel/head.S
arch/sh/kernel/io.c
arch/sh/kernel/irq.c
arch/sh/kernel/kgdb_stub.c
arch/sh/kernel/machine_kexec.c
arch/sh/kernel/pm.c [new file with mode: 0644]
arch/sh/kernel/process.c
arch/sh/kernel/ptrace.c
arch/sh/kernel/semaphore.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/signal.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/syscalls.S [new file with mode: 0644]
arch/sh/kernel/time.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps.c
arch/sh/kernel/vmlinux.lds.S
arch/sh/kernel/vsyscall/Makefile [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-note.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-sigreturn.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-syscall.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-trapa.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall.c [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall.lds.S [new file with mode: 0644]
arch/sh/lib/checksum.S
arch/sh/lib/memcpy-sh4.S
arch/sh/lib/memset.S
arch/sh/math-emu/Makefile [new file with mode: 0644]
arch/sh/math-emu/math.c [new file with mode: 0644]
arch/sh/math-emu/sfp-util.h [new file with mode: 0644]
arch/sh/mm/Kconfig
arch/sh/mm/Makefile
arch/sh/mm/cache-debugfs.c [new file with mode: 0644]
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/clear_page.S
arch/sh/mm/consistent.c
arch/sh/mm/fault.c
arch/sh/mm/hugetlbpage.c
arch/sh/mm/init.c
arch/sh/mm/ioremap.c
arch/sh/mm/pg-nommu.c
arch/sh/mm/pg-sh4.c
arch/sh/mm/pmb.c [new file with mode: 0644]
arch/sh/mm/tlb-flush.c [new file with mode: 0644]
arch/sh/mm/tlb-sh4.c
arch/sh/oprofile/Makefile
arch/sh/tools/mach-types
arch/sh64/kernel/time.c
arch/sh64/mm/fault.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/time.c
arch/sparc/lib/copy_user.S
arch/sparc64/defconfig
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/time.c
arch/sparc64/mm/init.c
arch/sparc64/solaris/misc.c
arch/um/Makefile-x86_64
arch/um/drivers/chan_kern.c
arch/um/drivers/daemon.h
arch/um/drivers/daemon_kern.c
arch/um/drivers/daemon_user.c
arch/um/drivers/fd.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/line.c
arch/um/drivers/mcast.h
arch/um/drivers/mcast_kern.c
arch/um/drivers/mcast_user.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_user.c
arch/um/drivers/mmapper_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/net_user.c
arch/um/drivers/null.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/pcap_user.c
arch/um/drivers/port_user.c
arch/um/drivers/pty.c
arch/um/drivers/random.c
arch/um/drivers/slip.h
arch/um/drivers/slip_kern.c
arch/um/drivers/slip_user.c
arch/um/drivers/slirp.h
arch/um/drivers/slirp_kern.c
arch/um/drivers/slirp_user.c
arch/um/drivers/ssl.c
arch/um/drivers/stderr_console.c
arch/um/drivers/stdio_console.c
arch/um/drivers/tty.c
arch/um/drivers/ubd_kern.c
arch/um/drivers/xterm.c
arch/um/include/chan_kern.h
arch/um/include/chan_user.h
arch/um/include/kern_util.h
arch/um/include/line.h
arch/um/include/net_kern.h
arch/um/include/net_user.h
arch/um/include/os.h
arch/um/include/skas/skas.h
arch/um/include/sysdep-i386/archsetjmp.h
arch/um/include/sysdep-x86_64/archsetjmp.h
arch/um/include/sysdep-x86_64/ptrace.h
arch/um/include/sysdep-x86_64/sc.h
arch/um/kernel/Makefile
arch/um/kernel/exitcode.c
arch/um/kernel/gmon_syms.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/process.c [new file with mode: 0644]
arch/um/kernel/process_kern.c [deleted file]
arch/um/kernel/skas/Makefile
arch/um/kernel/skas/exec.c [new file with mode: 0644]
arch/um/kernel/skas/exec_kern.c [deleted file]
arch/um/kernel/skas/mmu.c
arch/um/kernel/skas/process.c [new file with mode: 0644]
arch/um/kernel/skas/process_kern.c [deleted file]
arch/um/kernel/time.c
arch/um/kernel/trap.c
arch/um/kernel/um_arch.c
arch/um/os-Linux/Makefile
arch/um/os-Linux/drivers/etap.h
arch/um/os-Linux/drivers/ethertap_kern.c
arch/um/os-Linux/drivers/ethertap_user.c
arch/um/os-Linux/drivers/tuntap.h
arch/um/os-Linux/drivers/tuntap_kern.c
arch/um/os-Linux/drivers/tuntap_user.c
arch/um/os-Linux/mem.c
arch/um/os-Linux/skas/process.c
arch/v850/kernel/memcons.c
arch/v850/kernel/rte_cb_leds.c
arch/v850/kernel/rte_mb_a_pci.c
arch/v850/kernel/time.c
arch/x86_64/Kconfig
arch/x86_64/defconfig
arch/x86_64/ia32/sys_ia32.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-dma.c
arch/x86_64/kernel/pci-swiotlb.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/kernel/vsyscall.c
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/ioremap.c
arch/x86_64/mm/k8topology.c
arch/x86_64/mm/numa.c
arch/x86_64/mm/srat.c
arch/xtensa/kernel/time.c
arch/xtensa/mm/fault.c
arch/xtensa/platform-iss/network.c
block/Kconfig
block/Kconfig.iosched
block/Makefile
block/as-iosched.c
block/blktrace.c
block/cfq-iosched.c
block/deadline-iosched.c
block/elevator.c
block/genhd.c
block/ll_rw_blk.c
block/noop-iosched.c
block/scsi_ioctl.c
drivers/acorn/char/i2c.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/i2c_ec.c
drivers/acpi/osl.c
drivers/acpi/processor_idle.c
drivers/ata/Kconfig
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sff.c
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_artop.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_cypress.c
drivers/ata/pata_efar.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_isapnp.c
drivers/ata/pata_it821x.c
drivers/ata/pata_jmicron.c
drivers/ata/pata_legacy.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_netcell.c
drivers/ata/pata_ns87410.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_opti.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_qdi.c
drivers/ata/pata_radisys.c
drivers/ata/pata_rz1000.c
drivers/ata/pata_sc1200.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_mv.c
drivers/base/Makefile
drivers/base/class.c
drivers/base/firmware_class.c
drivers/block/DAC960.c
drivers/block/DAC960.h
drivers/block/Kconfig
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cciss_cmd.h
drivers/block/cciss_scsi.c
drivers/block/cpqarray.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/paride/pd.c
drivers/block/pktcdvd.c
drivers/block/swim3.c
drivers/block/swim_iop.c
drivers/block/ub.c
drivers/block/xd.c
drivers/bluetooth/bfusb.c
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_usb.c
drivers/bluetooth/hci_vhci.c
drivers/cdrom/Kconfig
drivers/cdrom/cdrom.c
drivers/cdrom/cdu31a.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/drm/Kconfig
drivers/char/drm/Makefile
drivers/char/drm/drmP.h
drivers/char/drm/drm_auth.c
drivers/char/drm/drm_bufs.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_fops.c
drivers/char/drm/drm_hashtab.c [new file with mode: 0644]
drivers/char/drm/drm_hashtab.h [new file with mode: 0644]
drivers/char/drm/drm_ioc32.c
drivers/char/drm/drm_ioctl.c
drivers/char/drm/drm_irq.c
drivers/char/drm/drm_mm.c [new file with mode: 0644]
drivers/char/drm/drm_pciids.h
drivers/char/drm/drm_proc.c
drivers/char/drm/drm_sman.c [new file with mode: 0644]
drivers/char/drm/drm_sman.h [new file with mode: 0644]
drivers/char/drm/drm_stub.c
drivers/char/drm/drm_vm.c
drivers/char/drm/i810_dma.c
drivers/char/drm/i830_dma.c
drivers/char/drm/i915_dma.c
drivers/char/drm/i915_drm.h
drivers/char/drm/i915_drv.h
drivers/char/drm/i915_irq.c
drivers/char/drm/radeon_cp.c
drivers/char/drm/radeon_drv.c
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_state.c
drivers/char/drm/sis_drv.c
drivers/char/drm/sis_drv.h
drivers/char/drm/sis_ds.c [deleted file]
drivers/char/drm/sis_ds.h [deleted file]
drivers/char/drm/sis_mm.c
drivers/char/drm/via_dmablit.c
drivers/char/drm/via_drm.h
drivers/char/drm/via_drv.c
drivers/char/drm/via_drv.h
drivers/char/drm/via_ds.c [deleted file]
drivers/char/drm/via_ds.h [deleted file]
drivers/char/drm/via_map.c
drivers/char/drm/via_mm.c
drivers/char/ds1286.c
drivers/char/generic_serial.c
drivers/char/hw_random/intel-rng.c
drivers/char/ip2/ip2main.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/lp.c
drivers/char/mbcs.c
drivers/char/mem.c
drivers/char/moxa.c
drivers/char/mspec.c [new file with mode: 0644]
drivers/char/mwave/mwavedd.c
drivers/char/mxser.c
drivers/char/pc8736x_gpio.c
drivers/char/random.c
drivers/char/raw.c
drivers/char/riscom8.c
drivers/char/rtc.c
drivers/char/s3c2410-rtc.c [deleted file]
drivers/char/scx200_gpio.c
drivers/char/selection.c
drivers/char/specialix.c
drivers/char/synclink_gt.c
drivers/char/sysrq.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/vc_screen.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Makefile
drivers/char/watchdog/omap_wdt.c [new file with mode: 0644]
drivers/char/watchdog/omap_wdt.h [new file with mode: 0644]
drivers/char/watchdog/shwdt.c
drivers/cpufreq/cpufreq.c
drivers/eisa/eisa-bus.c
drivers/fc4/fc.c
drivers/firmware/dmi_scan.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/abituguru.c
drivers/hwmon/adm1021.c
drivers/hwmon/adm1025.c
drivers/hwmon/adm1026.c
drivers/hwmon/adm1031.c
drivers/hwmon/adm9240.c
drivers/hwmon/asb100.c
drivers/hwmon/atxp1.c
drivers/hwmon/ds1621.c
drivers/hwmon/f71805f.c
drivers/hwmon/fscher.c
drivers/hwmon/fscpos.c
drivers/hwmon/gl518sm.c
drivers/hwmon/gl520sm.c
drivers/hwmon/hdaps.c
drivers/hwmon/it87.c
drivers/hwmon/k8temp.c [new file with mode: 0644]
drivers/hwmon/lm63.c
drivers/hwmon/lm75.c
drivers/hwmon/lm77.c
drivers/hwmon/lm78.c
drivers/hwmon/lm80.c
drivers/hwmon/lm83.c
drivers/hwmon/lm85.c
drivers/hwmon/lm87.c
drivers/hwmon/lm90.c
drivers/hwmon/lm92.c
drivers/hwmon/max1619.c
drivers/hwmon/pc87360.c
drivers/hwmon/sis5595.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/smsc47m192.c
drivers/hwmon/via686a.c
drivers/hwmon/vt1211.c [new file with mode: 0644]
drivers/hwmon/vt8231.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/hwmon/w83791d.c
drivers/hwmon/w83792d.c
drivers/hwmon/w83l785ts.c
drivers/i2c/Kconfig
drivers/i2c/algos/Kconfig
drivers/i2c/algos/Makefile
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-sgi.c
drivers/i2c/algos/i2c-algo-sibyte.c [deleted file]
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i810.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isa.c
drivers/i2c/busses/i2c-ite.c
drivers/i2c/busses/i2c-ixp2000.c
drivers/i2c/busses/i2c-ixp4xx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-omap.c [new file with mode: 0644]
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-prosavage.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-savage4.c
drivers/i2c/busses/i2c-sibyte.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-voodoo3.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/busses/scx200_i2c.c
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/isp1301_omap.c
drivers/i2c/chips/max6875.c
drivers/i2c/chips/pca9539.c
drivers/i2c/chips/pcf8574.c
drivers/i2c/chips/pcf8591.c
drivers/i2c/chips/tps65010.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/Kconfig
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-io.c
drivers/ide/ide-lib.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/legacy/hd.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/piix.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/sis5513.c
drivers/ieee1394/Kconfig
drivers/ieee1394/csr.c
drivers/ieee1394/csr.h
drivers/ieee1394/dma.c
drivers/ieee1394/dma.h
drivers/ieee1394/dv1394-private.h
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/highlevel.h
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394-ioctl.h
drivers/ieee1394/ieee1394.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/ieee1394_hotplug.h
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_transactions.h
drivers/ieee1394/ieee1394_types.h
drivers/ieee1394/iso.c
drivers/ieee1394/iso.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/nodemgr.h
drivers/ieee1394/ohci1394.c
drivers/ieee1394/pcilynx.c
drivers/ieee1394/raw1394-private.h
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/mad.c
drivers/infiniband/hw/amso1100/c2_ae.c
drivers/infiniband/hw/amso1100/c2_alloc.c
drivers/infiniband/hw/amso1100/c2_cm.c
drivers/infiniband/hw/amso1100/c2_provider.c
drivers/infiniband/hw/amso1100/c2_rnic.c
drivers/infiniband/hw/ipath/ipath_common.h
drivers/infiniband/hw/ipath/ipath_cq.c
drivers/infiniband/hw/ipath/ipath_driver.c
drivers/infiniband/hw/ipath/ipath_eeprom.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/ipath/ipath_iba6110.c
drivers/infiniband/hw/ipath/ipath_iba6120.c
drivers/infiniband/hw/ipath/ipath_init_chip.c
drivers/infiniband/hw/ipath/ipath_intr.c
drivers/infiniband/hw/ipath/ipath_kernel.h
drivers/infiniband/hw/ipath/ipath_keys.c
drivers/infiniband/hw/ipath/ipath_mad.c
drivers/infiniband/hw/ipath/ipath_mr.c
drivers/infiniband/hw/ipath/ipath_qp.c
drivers/infiniband/hw/ipath/ipath_rc.c
drivers/infiniband/hw/ipath/ipath_registers.h
drivers/infiniband/hw/ipath/ipath_ruc.c
drivers/infiniband/hw/ipath/ipath_srq.c
drivers/infiniband/hw/ipath/ipath_sysfs.c
drivers/infiniband/hw/ipath/ipath_uc.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/hw/ipath/ipath_user_pages.c
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/ipath/ipath_verbs.h
drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
drivers/infiniband/ulp/ipoib/ipoib_fs.c
drivers/infiniband/ulp/iser/Kconfig
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/omap-keypad.c [new file with mode: 0644]
drivers/input/serio/i8042-io.h
drivers/input/touchscreen/hp680_ts_input.c
drivers/isdn/capi/capifs.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/hardware/eicon/dsp_defs.h
drivers/isdn/hisax/hfc_usb.h
drivers/isdn/i4l/isdn_net.c
drivers/leds/led-triggers.c
drivers/leds/leds-net48xx.c
drivers/macintosh/smu.c
drivers/macintosh/via-pmu-backlight.c
drivers/macintosh/via-pmu.c
drivers/macintosh/via-pmu68k.c
drivers/macintosh/windfarm_smu_controls.c
drivers/macintosh/windfarm_smu_sat.c
drivers/macintosh/windfarm_smu_sensors.c
drivers/md/Kconfig
drivers/md/dm-emc.c
drivers/media/common/Kconfig
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_fops.c
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/dvb-core/Kconfig
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dibusb-common.c
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/dibusb.h
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/dvb-usb/dvb-usb-urb.c
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/bcm3510.h
drivers/media/dvb/frontends/cx22700.h
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/dvb/frontends/dib3000-common.c [deleted file]
drivers/media/dvb/frontends/dib3000-common.h [deleted file]
drivers/media/dvb/frontends/dib3000.h
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/frontends/dib3000mb_priv.h
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/dib3000mc.h [new file with mode: 0644]
drivers/media/dvb/frontends/dib3000mc_priv.h [deleted file]
drivers/media/dvb/frontends/dibx000_common.c [new file with mode: 0644]
drivers/media/dvb/frontends/dibx000_common.h [new file with mode: 0644]
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/isl6421.c
drivers/media/dvb/frontends/isl6421.h
drivers/media/dvb/frontends/l64781.h
drivers/media/dvb/frontends/lgdt330x.h
drivers/media/dvb/frontends/lnbp21.c
drivers/media/dvb/frontends/lnbp21.h
drivers/media/dvb/frontends/mt2060.c [new file with mode: 0644]
drivers/media/dvb/frontends/mt2060.h [new file with mode: 0644]
drivers/media/dvb/frontends/mt2060_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/mt352.h
drivers/media/dvb/frontends/nxt200x.h
drivers/media/dvb/frontends/nxt6000.h
drivers/media/dvb/frontends/or51132.h
drivers/media/dvb/frontends/or51211.h
drivers/media/dvb/frontends/s5h1420.h
drivers/media/dvb/frontends/sp8870.h
drivers/media/dvb/frontends/sp887x.h
drivers/media/dvb/frontends/stv0297.h
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10021.h
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda10086.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda10086.h [new file with mode: 0644]
drivers/media/dvb/frontends/tda8083.h
drivers/media/dvb/frontends/tda826x.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda826x.h [new file with mode: 0644]
drivers/media/dvb/frontends/tua6100.c [new file with mode: 0644]
drivers/media/dvb/frontends/tua6100.h [new file with mode: 0644]
drivers/media/dvb/frontends/ves1820.h
drivers/media/dvb/frontends/ves1x93.h
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/frontends/zl10353.h
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110.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/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-budget/Kconfig
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/radio/Kconfig
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt866.c
drivers/media/video/bt8xx/Kconfig
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/compat_ioctl32.c
drivers/media/video/cpia2/cpia2.h
drivers/media/video/cx2341x.c
drivers/media/video/cx25840/Kconfig
drivers/media/video/cx25840/cx25840-vbi.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/Makefile
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88-vp3054-i2c.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/ks0127.c
drivers/media/video/ov511.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/Makefile
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7115.c
drivers/media/video/saa711x_regs.h [new file with mode: 0644]
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/Makefile
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/tda9887.c
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-types.c
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/konicawc.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/video-buf-dvb.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vpx3220.c
drivers/media/video/w9968cf.c
drivers/media/video/zoran_card.c
drivers/media/video/zoran_driver.c
drivers/media/video/zr36120.c
drivers/message/i2o/Kconfig
drivers/message/i2o/i2o_block.c
drivers/message/i2o/pci.c
drivers/mfd/ucb1x00-ts.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/at91_mci.c
drivers/mmc/imxmmc.c
drivers/mmc/mmc.c
drivers/mmc/mmc_block.c
drivers/mmc/mmc_queue.c
drivers/mmc/mmci.c
drivers/mmc/omap.c
drivers/mmc/sdhci.c
drivers/mmc/sdhci.h
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h
drivers/mtd/Kconfig
drivers/mtd/devices/Kconfig
drivers/mtd/mtd_blkdevs.c
drivers/net/3c509.c
drivers/net/3c59x.c
drivers/net/8390.c
drivers/net/Kconfig
drivers/net/acenic.c
drivers/net/appletalk/ipddp.c
drivers/net/arm/at91_ether.c
drivers/net/bnx2.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/dgrs.c
drivers/net/e1000/e1000_hw.h
drivers/net/fec_8xx/fec_main.c
drivers/net/forcedeth.c
drivers/net/fs_enet/fs_enet.h
drivers/net/gt64240eth.h [deleted file]
drivers/net/irda/Kconfig
drivers/net/irda/irda-usb.c
drivers/net/irda/nsc-ircc.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/stir4200.c
drivers/net/irda/via-ircc.c
drivers/net/irda/vlsi_ir.h
drivers/net/loopback.c
drivers/net/ne3210.c
drivers/net/phy/phy_device.c
drivers/net/pppoe.c
drivers/net/s2io.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/smc91x.h
drivers/net/stnic.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/lanstreamer.h
drivers/net/tulip/de4x5.c
drivers/net/tun.c
drivers/net/typhoon.c
drivers/net/wan/Kconfig
drivers/net/wan/Makefile
drivers/net/wan/hdlc.c [new file with mode: 0644]
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_generic.c [deleted file]
drivers/net/wan/hdlc_ppp.c
drivers/net/wan/hdlc_raw.c
drivers/net/wan/hdlc_raw_eth.c
drivers/net/wan/hdlc_x25.c
drivers/net/wan/pc300.h
drivers/net/wan/pc300_drv.c
drivers/net/wan/syncppp.c
drivers/net/wireless/airo.c
drivers/net/wireless/atmel.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_phy.c
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/orinoco.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/strip.c
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/zd1201.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_mac.h
drivers/net/wireless/zd1211rw/zd_netdev.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/oprofile/oprofilefs.c
drivers/parport/parport_pc.c
drivers/parport/parport_serial.c
drivers/pci/bus.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/cpqphp_sysfs.c
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/pci_hotplug.h
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pcihp_skeleton.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_sysfs.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/Makefile
drivers/pci/pcie/aer/Kconfig [new file with mode: 0644]
drivers/pci/pcie/aer/Makefile [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv.h [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv_acpi.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv_core.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv_errprint.c [new file with mode: 0644]
drivers/pci/pcie/portdrv.h
drivers/pci/pcie/portdrv_bus.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/pcmcia/cardbus.c
drivers/pcmcia/omap_cf.c
drivers/pnp/pnpbios/core.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/rtc-at91.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-ep93xx.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-lib.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-max6902.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-proc.c
drivers/rtc/rtc-rs5c348.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-sh.c [new file with mode: 0644]
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-test.c
drivers/rtc/rtc-v3020.c
drivers/rtc/rtc-vr41xx.c
drivers/rtc/rtc-x1205.c
drivers/s390/block/Kconfig
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/xpram.c
drivers/s390/char/fs3270.c
drivers/s390/char/sclp.c
drivers/s390/char/tty3270.c
drivers/s390/char/vmwatchdog.c
drivers/s390/cio/device_id.c
drivers/s390/cio/ioasm.h
drivers/s390/cio/qdio.h
drivers/s390/net/iucv.c
drivers/s390/net/qeth_main.c
drivers/s390/s390mach.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/53c700.c
drivers/scsi/BusLogic.h
drivers/scsi/Kconfig
drivers/scsi/aha1740.c
drivers/scsi/aic7xxx/aic7770_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx_old.c
drivers/scsi/gdth.c
drivers/scsi/ide-scsi.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/pluto.c
drivers/scsi/qla1280.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sim710.c
drivers/scsi/sun3_NCR5380.c
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi_vme.c
drivers/serial/8250_acorn.c
drivers/serial/8250_gsc.c
drivers/serial/Kconfig
drivers/serial/at91_serial.c
drivers/serial/ioc4_serial.c
drivers/serial/ip22zilog.c
drivers/serial/mpc52xx_uart.c
drivers/serial/mpsc.c
drivers/serial/mux.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/serial/sunsu.c
drivers/serial/sunzilog.c
drivers/usb/Kconfig
drivers/usb/Makefile
drivers/usb/atm/ueagle-atm.c
drivers/usb/class/usblp.c
drivers/usb/core/Makefile
drivers/usb/core/buffer.c
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/endpoint.c
drivers/usb/core/file.c
drivers/usb/core/generic.c [new file with mode: 0644]
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/inode.c
drivers/usb/core/message.c
drivers/usb/core/notify.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/gmidi.c [new file with mode: 0644]
drivers/usb/gadget/inode.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/pxa2xx_udc.h
drivers/usb/gadget/serial.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp116x.h
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-mem.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pnx4008.c [new file with mode: 0644]
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci.h
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c [new file with mode: 0644]
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/image/mdc800.c
drivers/usb/image/microtek.c
drivers/usb/image/microtek.h
drivers/usb/input/Kconfig
drivers/usb/input/Makefile
drivers/usb/input/acecad.c
drivers/usb/input/appletouch.c
drivers/usb/input/ati_remote.c
drivers/usb/input/hid-core.c
drivers/usb/input/hiddev.c
drivers/usb/input/itmtouch.c
drivers/usb/input/keyspan_remote.c
drivers/usb/input/mtouchusb.c
drivers/usb/input/powermate.c
drivers/usb/input/touchkitusb.c
drivers/usb/input/trancevibrator.c [new file with mode: 0644]
drivers/usb/input/usbmouse.c
drivers/usb/input/usbtouchscreen.c
drivers/usb/input/wacom.c [deleted file]
drivers/usb/input/wacom.h [new file with mode: 0644]
drivers/usb/input/wacom_sys.c [new file with mode: 0644]
drivers/usb/input/wacom_wac.c [new file with mode: 0644]
drivers/usb/input/wacom_wac.h [new file with mode: 0644]
drivers/usb/input/yealink.c
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/adutux.c [new file with mode: 0644]
drivers/usb/misc/auerswald.c
drivers/usb/misc/cypress_cy7c63.c
drivers/usb/misc/cytherm.c
drivers/usb/misc/ftdi-elan.c [new file with mode: 0644]
drivers/usb/misc/idmouse.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/phidget.c [new file with mode: 0644]
drivers/usb/misc/phidget.h [new file with mode: 0644]
drivers/usb/misc/phidgetkit.c
drivers/usb/misc/phidgetmotorcontrol.c [new file with mode: 0644]
drivers/usb/misc/phidgetservo.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/usb_u132.h [new file with mode: 0644]
drivers/usb/misc/usblcd.c
drivers/usb/misc/usbled.c
drivers/usb/mon/mon_main.c
drivers/usb/mon/mon_stat.c
drivers/usb/mon/mon_text.c
drivers/usb/mon/usb_mon.h
drivers/usb/net/asix.c
drivers/usb/net/kaweth.c
drivers/usb/net/net1080.c
drivers/usb/net/pegasus.c
drivers/usb/net/rtl8150.c
drivers/usb/net/usbnet.c
drivers/usb/net/usbnet.h
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/aircable.c [new file with mode: 0644]
drivers/usb/serial/airprime.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/mos7840.c [new file with mode: 0644]
drivers/usb/serial/omninet.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/safe_serial.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/Kconfig
drivers/usb/storage/Makefile
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/karma.c [new file with mode: 0644]
drivers/usb/storage/karma.h [new file with mode: 0644]
drivers/usb/storage/libusual.c
drivers/usb/storage/onetouch.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/usb-skeleton.c
drivers/video/Kconfig
drivers/video/backlight/hp680_bl.c
drivers/video/backlight/locomolcd.c
drivers/video/console/Kconfig
drivers/video/hitfb.c
drivers/video/i810/i810-i2c.c
drivers/video/intelfb/Makefile
drivers/video/intelfb/intelfb.h
drivers/video/intelfb/intelfb_i2c.c [new file with mode: 0644]
drivers/video/intelfb/intelfbdrv.c
drivers/video/intelfb/intelfbhw.c
drivers/video/intelfb/intelfbhw.h
drivers/video/matrox/i2c-matroxfb.c
drivers/video/pvr2fb.c
drivers/video/savage/savagefb-i2c.c
fs/9p/v9fs.c
fs/9p/vfs_inode.c
fs/Kconfig
fs/Makefile
fs/adfs/file.c
fs/adfs/inode.c
fs/adfs/super.c
fs/affs/file.c
fs/affs/super.c
fs/afs/file.c
fs/afs/inode.c
fs/afs/proc.c
fs/afs/vlocation.c
fs/afs/volume.c
fs/aio.c
fs/autofs/inode.c
fs/autofs/root.c
fs/autofs/symlink.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/bad_inode.c
fs/befs/linuxvfs.c
fs/bfs/dir.c
fs/bfs/file.c
fs/bfs/inode.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_misc.c
fs/bio.c
fs/block_dev.c
fs/buffer.c
fs/char_dev.c
fs/cifs/cifsfs.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/ioctl.c
fs/cifs/readdir.c
fs/coda/coda_linux.c
fs/coda/dir.c
fs/coda/inode.c
fs/compat.c
fs/compat_ioctl.c
fs/configfs/dir.c
fs/configfs/file.c
fs/configfs/inode.c
fs/configfs/mount.c
fs/cramfs/inode.c
fs/cramfs/uncompress.c
fs/dcache.c
fs/debugfs/file.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/dquot.c
fs/efs/super.c
fs/eventpoll.c
fs/exec.c
fs/ext2/acl.c
fs/ext2/dir.c
fs/ext2/ext2.h
fs/ext2/file.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/ioctl.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext2/xattr.c
fs/ext3/acl.c
fs/ext3/balloc.c
fs/ext3/bitmap.c
fs/ext3/dir.c
fs/ext3/file.c
fs/ext3/fsync.c
fs/ext3/hash.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext3/ioctl.c
fs/ext3/namei.c
fs/ext3/resize.c
fs/ext3/super.c
fs/ext3/xattr.c
fs/fat/cache.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/inode.c
fs/file.c
fs/file_table.c
fs/filesystems.c
fs/freevxfs/vxfs.h
fs/freevxfs/vxfs_inode.c
fs/freevxfs/vxfs_super.c
fs/fs-writeback.c
fs/fuse/control.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/inode.c
fs/generic_acl.c [new file with mode: 0644]
fs/hfs/bnode.c
fs/hfs/btree.c
fs/hfs/dir.c
fs/hfs/inode.c
fs/hfs/super.c
fs/hfsplus/bnode.c
fs/hfsplus/btree.c
fs/hfsplus/dir.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/ioctl.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/buffer.c
fs/hpfs/file.c
fs/hpfs/inode.c
fs/hpfs/namei.c
fs/hpfs/super.c
fs/hppfs/hppfs_kern.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/internal.h [new file with mode: 0644]
fs/ioprio.c
fs/isofs/inode.c
fs/jbd/checkpoint.c
fs/jbd/journal.c
fs/jbd/recovery.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jffs/inode-v23.c
fs/jffs/intrep.c
fs/jffs/jffs_fm.c
fs/jffs2/dir.c
fs/jffs2/file.c
fs/jffs2/fs.c
fs/jffs2/super.c
fs/jfs/file.c
fs/jfs/inode.c
fs/jfs/ioctl.c
fs/jfs/jfs_dmap.c
fs/jfs/jfs_extent.c
fs/jfs/jfs_extent.h
fs/jfs/jfs_imap.c
fs/jfs/jfs_imap.h
fs/jfs/jfs_inode.c
fs/jfs/jfs_metapage.c
fs/jfs/jfs_metapage.h
fs/jfs/jfs_txnmgr.c
fs/jfs/jfs_types.h
fs/jfs/jfs_xtree.c
fs/jfs/namei.c
fs/jfs/xattr.c
fs/libfs.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/host.c
fs/lockd/svcsubs.c
fs/locks.c
fs/mbcache.c
fs/minix/bitmap.c
fs/minix/file.c
fs/minix/inode.c
fs/minix/namei.c
fs/mpage.c
fs/msdos/namei.c
fs/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/ncpfs/file.c
fs/ncpfs/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/symlink.c
fs/nfs/delegation.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/namespace.c
fs/nfs/nfs3proc.c
fs/nfs/pagelist.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4state.c
fs/no-block.c [new file with mode: 0644]
fs/ntfs/aops.c
fs/ntfs/aops.h
fs/ntfs/attrib.c
fs/ntfs/attrib.h
fs/ntfs/bitmap.c
fs/ntfs/bitmap.h
fs/ntfs/collate.h
fs/ntfs/compress.c
fs/ntfs/dir.c
fs/ntfs/file.c
fs/ntfs/index.c
fs/ntfs/index.h
fs/ntfs/inode.c
fs/ntfs/layout.h
fs/ntfs/lcnalloc.c
fs/ntfs/lcnalloc.h
fs/ntfs/logfile.c
fs/ntfs/logfile.h
fs/ntfs/mft.c
fs/ntfs/mft.h
fs/ntfs/ntfs.h
fs/ntfs/quota.c
fs/ntfs/quota.h
fs/ntfs/runlist.c
fs/ntfs/super.c
fs/ntfs/types.h
fs/ntfs/unistr.c
fs/ntfs/usnjrnl.c
fs/ntfs/usnjrnl.h
fs/ocfs2/dlm/dlmfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/namei.c
fs/open.c
fs/partitions/Makefile
fs/partitions/efi.c
fs/partitions/ldm.c
fs/partitions/msdos.c
fs/pipe.c
fs/posix_acl.c
fs/proc/array.c
fs/proc/base.c
fs/proc/internal.h
fs/proc/kcore.c
fs/proc/nommu.c
fs/proc/proc_misc.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/qnx4/file.c
fs/qnx4/inode.c
fs/qnx4/namei.c
fs/quota.c
fs/ramfs/file-mmu.c
fs/ramfs/file-nommu.c
fs/ramfs/inode.c
fs/read_write.c
fs/read_write.h [new file with mode: 0644]
fs/reiserfs/Makefile
fs/reiserfs/bitmap.c
fs/reiserfs/dir.c
fs/reiserfs/file.c
fs/reiserfs/inode.c
fs/reiserfs/ioctl.c
fs/reiserfs/journal.c
fs/reiserfs/namei.c
fs/reiserfs/resize.c
fs/reiserfs/super.c
fs/romfs/inode.c
fs/select.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/smbfs/request.c
fs/splice.c
fs/stat.c
fs/super.c
fs/sync.c
fs/sysfs/dir.c
fs/sysfs/inode.c
fs/sysfs/mount.c
fs/sysv/file.c
fs/sysv/ialloc.c
fs/sysv/inode.c
fs/sysv/namei.c
fs/sysv/super.c
fs/udf/file.c
fs/udf/ialloc.c
fs/udf/inode.c
fs/udf/namei.c
fs/udf/super.c
fs/ufs/file.c
fs/ufs/ialloc.c
fs/ufs/inode.c
fs/ufs/namei.c
fs/ufs/super.c
fs/utimes.c [new file with mode: 0644]
fs/vfat/namei.c
fs/xfs/Kconfig
fs/xfs/Makefile-linux-2.6
fs/xfs/linux-2.6/kmem.c
fs/xfs/linux-2.6/kmem.h
fs/xfs/linux-2.6/sema.h
fs/xfs/linux-2.6/sv.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_file.c
fs/xfs/linux-2.6/xfs_globals.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_vfs.h
fs/xfs/linux-2.6/xfs_vnode.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/quota/xfs_dquot_item.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm.h
fs/xfs/quota/xfs_quota_priv.h
fs/xfs/support/ktrace.c
fs/xfs/xfs_ag.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc_btree.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr.h
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_leaf.h
fs/xfs/xfs_behavior.c
fs/xfs/xfs_behavior.h
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap_btree.c
fs/xfs/xfs_bmap_btree.h
fs/xfs/xfs_btree.c
fs/xfs/xfs_btree.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_error.h
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_extfree_item.h
fs/xfs/xfs_fs.h
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_ialloc_btree.c
fs/xfs/xfs_ialloc_btree.h
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_inode_item.h
fs/xfs/xfs_iomap.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_itable.h
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_mount.h
fs/xfs/xfs_quota.h
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_sb.h
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_ail.c
fs/xfs/xfs_trans_priv.h
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vnodeops.c
include/asm-alpha/spinlock.h
include/asm-arm/arch-at91rm9200/at91rm9200.h
include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
include/asm-arm/arch-at91rm9200/at91rm9200_twi.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/gpio.h
include/asm-arm/arch-at91rm9200/hardware.h
include/asm-arm/arch-at91rm9200/irqs.h
include/asm-arm/arch-clps711x/time.h
include/asm-arm/arch-iop32x/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-iop32x/dma.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-iop32x/glantank.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/hardware.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/io.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/iop32x.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/iq31244.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/iq80321.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/irqs.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/memory.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/n2100.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/system.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/timex.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-iop32x/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-iop33x/dma.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-iop33x/hardware.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/io.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/iop33x.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/iq80331.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/iq80332.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/irqs.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/memory.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/system.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/timex.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-iop33x/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-iop3xx/debug-macro.S [deleted file]
include/asm-arm/arch-iop3xx/dma.h [deleted file]
include/asm-arm/arch-iop3xx/entry-macro.S [deleted file]
include/asm-arm/arch-iop3xx/hardware.h [deleted file]
include/asm-arm/arch-iop3xx/io.h [deleted file]
include/asm-arm/arch-iop3xx/iop321-irqs.h [deleted file]
include/asm-arm/arch-iop3xx/iop321.h [deleted file]
include/asm-arm/arch-iop3xx/iop331-irqs.h [deleted file]
include/asm-arm/arch-iop3xx/iop331.h [deleted file]
include/asm-arm/arch-iop3xx/iq31244.h [deleted file]
include/asm-arm/arch-iop3xx/iq80321.h [deleted file]
include/asm-arm/arch-iop3xx/iq80331.h [deleted file]
include/asm-arm/arch-iop3xx/iq80332.h [deleted file]
include/asm-arm/arch-iop3xx/irqs.h [deleted file]
include/asm-arm/arch-iop3xx/memory.h [deleted file]
include/asm-arm/arch-iop3xx/system.h [deleted file]
include/asm-arm/arch-iop3xx/timex.h [deleted file]
include/asm-arm/arch-iop3xx/uncompress.h [deleted file]
include/asm-arm/arch-iop3xx/vmalloc.h [deleted file]
include/asm-arm/arch-ixp4xx/platform.h
include/asm-arm/arch-l7200/io.h
include/asm-arm/arch-l7200/time.h
include/asm-arm/arch-omap/board-ams-delta.h
include/asm-arm/arch-omap/clock.h
include/asm-arm/arch-omap/dma.h
include/asm-arm/arch-omap/dmtimer.h
include/asm-arm/arch-omap/gpmc.h
include/asm-arm/arch-omap/irqs.h
include/asm-arm/arch-omap/keypad.h
include/asm-arm/arch-omap/mux.h
include/asm-arm/arch-pxa/udc.h
include/asm-arm/arch-s3c2410/dma.h
include/asm-arm/arch-s3c2410/map.h
include/asm-arm/arch-s3c2410/osiris-map.h
include/asm-arm/arch-s3c2410/regs-ac97.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-lcd.h
include/asm-arm/atomic.h
include/asm-arm/bitops.h
include/asm-arm/cacheflush.h
include/asm-arm/flat.h [new file with mode: 0644]
include/asm-arm/hardware/iop3xx.h [new file with mode: 0644]
include/asm-arm/hardware/locomo.h
include/asm-arm/hardware/sharpsl_pm.h
include/asm-arm/io.h
include/asm-arm/irqflags.h [new file with mode: 0644]
include/asm-arm/mach/pci.h
include/asm-arm/mach/time.h
include/asm-arm/page.h
include/asm-arm/pgtable.h
include/asm-arm/proc-fns.h
include/asm-arm/setup.h
include/asm-arm/spinlock.h
include/asm-arm/system.h
include/asm-arm/timeofday.h [new file with mode: 0644]
include/asm-arm/tlbflush.h
include/asm-arm/unaligned.h
include/asm-arm/unistd.h
include/asm-arm26/unistd.h
include/asm-cris/arch-v32/spinlock.h
include/asm-frv/pgtable.h
include/asm-frv/timex.h
include/asm-frv/unistd.h
include/asm-generic/bug.h
include/asm-generic/pgtable.h
include/asm-generic/vmlinux.lds.h
include/asm-h8300/keyboard.h
include/asm-h8300/unistd.h
include/asm-i386/dma-mapping.h
include/asm-i386/mach-default/do_timer.h
include/asm-i386/mach-summit/mach_apic.h
include/asm-i386/mach-visws/do_timer.h
include/asm-i386/mach-voyager/do_timer.h
include/asm-i386/nmi.h
include/asm-i386/pgtable-2level.h
include/asm-i386/pgtable-3level.h
include/asm-i386/pgtable.h
include/asm-i386/semaphore.h
include/asm-i386/smp.h
include/asm-i386/spinlock.h
include/asm-i386/unistd.h
include/asm-ia64/esi.h [new file with mode: 0644]
include/asm-ia64/futex.h
include/asm-ia64/kprobes.h
include/asm-ia64/mca_asm.h
include/asm-ia64/meminit.h
include/asm-ia64/numa.h
include/asm-ia64/pal.h
include/asm-ia64/processor.h
include/asm-ia64/smp.h
include/asm-ia64/spinlock.h
include/asm-ia64/unistd.h
include/asm-m32r/pgtable-2level.h
include/asm-m32r/spinlock.h
include/asm-m32r/system.h
include/asm-m32r/timex.h
include/asm-m32r/unistd.h
include/asm-m68k/unistd.h
include/asm-m68knommu/unistd.h
include/asm-mips/Kbuild
include/asm-mips/bootinfo.h
include/asm-mips/cacheflush.h
include/asm-mips/fcntl.h
include/asm-mips/galileo-boards/gt96100.h [deleted file]
include/asm-mips/hazards.h
include/asm-mips/irq.h
include/asm-mips/mach-atlas/mc146818rtc.h
include/asm-mips/mach-ev96100/mach-gt64120.h [deleted file]
include/asm-mips/mach-excite/excite.h
include/asm-mips/mach-excite/excite_fpga.h [new file with mode: 0644]
include/asm-mips/mach-qemu/cpu-feature-overrides.h
include/asm-mips/mips-boards/atlasint.h
include/asm-mips/mmu_context.h
include/asm-mips/page.h
include/asm-mips/pgtable-64.h
include/asm-mips/ptrace.h
include/asm-mips/serial.h
include/asm-mips/sibyte/sb1250_defs.h
include/asm-mips/sibyte/sb1250_scd.h
include/asm-mips/signal.h
include/asm-mips/spinlock.h
include/asm-mips/timex.h
include/asm-mips/unistd.h
include/asm-mips/user.h
include/asm-parisc/spinlock.h
include/asm-powerpc/bug.h
include/asm-powerpc/io.h
include/asm-powerpc/spinlock.h
include/asm-ppc/spinlock.h
include/asm-s390/appldata.h
include/asm-s390/atomic.h
include/asm-s390/bitops.h
include/asm-s390/byteorder.h
include/asm-s390/checksum.h
include/asm-s390/div64.h
include/asm-s390/ebcdic.h
include/asm-s390/io.h
include/asm-s390/irq.h
include/asm-s390/irqflags.h
include/asm-s390/lowcore.h
include/asm-s390/page.h
include/asm-s390/pgtable.h
include/asm-s390/processor.h
include/asm-s390/ptrace.h
include/asm-s390/rwsem.h
include/asm-s390/semaphore.h
include/asm-s390/setup.h
include/asm-s390/sfp-machine.h
include/asm-s390/sigp.h
include/asm-s390/smp.h
include/asm-s390/spinlock.h
include/asm-s390/spinlock_types.h
include/asm-s390/string.h
include/asm-s390/system.h
include/asm-s390/timex.h
include/asm-s390/tlbflush.h
include/asm-s390/uaccess.h
include/asm-s390/unistd.h
include/asm-sh/addrspace.h
include/asm-sh/adx/io.h [deleted file]
include/asm-sh/apm.h [new file with mode: 0644]
include/asm-sh/atomic.h
include/asm-sh/auxvec.h
include/asm-sh/bitops.h
include/asm-sh/bugs.h
include/asm-sh/cache.h
include/asm-sh/cacheflush.h
include/asm-sh/cat68701/io.h [deleted file]
include/asm-sh/checksum.h
include/asm-sh/cpu-features.h [new file with mode: 0644]
include/asm-sh/cpu-sh2/shmparam.h [deleted file]
include/asm-sh/cpu-sh3/cache.h
include/asm-sh/cpu-sh3/cacheflush.h
include/asm-sh/cpu-sh3/freq.h
include/asm-sh/cpu-sh3/mmu_context.h
include/asm-sh/cpu-sh3/shmparam.h [deleted file]
include/asm-sh/cpu-sh3/timer.h
include/asm-sh/cpu-sh3/ubc.h
include/asm-sh/cpu-sh4/addrspace.h
include/asm-sh/cpu-sh4/cache.h
include/asm-sh/cpu-sh4/cacheflush.h
include/asm-sh/cpu-sh4/dma-sh7780.h [new file with mode: 0644]
include/asm-sh/cpu-sh4/dma.h
include/asm-sh/cpu-sh4/shmparam.h [deleted file]
include/asm-sh/cpu-sh4/sq.h
include/asm-sh/cqreek/cqreek.h [deleted file]
include/asm-sh/dma-mapping.h
include/asm-sh/dma.h
include/asm-sh/dmida/io.h [deleted file]
include/asm-sh/ec3104/keyboard.h
include/asm-sh/elf.h
include/asm-sh/fixmap.h
include/asm-sh/flat.h
include/asm-sh/harp/harp.h [deleted file]
include/asm-sh/harp/io.h [deleted file]
include/asm-sh/hd64461.h [new file with mode: 0644]
include/asm-sh/hd64461/hd64461.h [deleted file]
include/asm-sh/hd64461/io.h [deleted file]
include/asm-sh/hp6xx/hp6xx.h
include/asm-sh/hp6xx/io.h
include/asm-sh/hs7751rvoip/hs7751rvoip.h
include/asm-sh/io.h
include/asm-sh/irq-sh73180.h
include/asm-sh/irq-sh7343.h [new file with mode: 0644]
include/asm-sh/irq-sh7780.h
include/asm-sh/irq.h
include/asm-sh/kexec.h
include/asm-sh/kgdb.h
include/asm-sh/landisk/gio.h [new file with mode: 0644]
include/asm-sh/landisk/ide.h [new file with mode: 0644]
include/asm-sh/landisk/iodata_landisk.h [new file with mode: 0644]
include/asm-sh/machvec.h
include/asm-sh/mc146818rtc.h
include/asm-sh/mmu.h
include/asm-sh/mmu_context.h
include/asm-sh/mpc1211/keyboard.h
include/asm-sh/overdrive/fpga.h [deleted file]
include/asm-sh/overdrive/gt64111.h [deleted file]
include/asm-sh/overdrive/io.h [deleted file]
include/asm-sh/overdrive/overdrive.h [deleted file]
include/asm-sh/page.h
include/asm-sh/pci.h
include/asm-sh/pgalloc.h
include/asm-sh/pgtable.h
include/asm-sh/pm.h [new file with mode: 0644]
include/asm-sh/processor.h
include/asm-sh/r7780rp/ide.h [new file with mode: 0644]
include/asm-sh/r7780rp/r7780rp.h [new file with mode: 0644]
include/asm-sh/rtc.h
include/asm-sh/rts7751r2d/rts7751r2d.h
include/asm-sh/rts7751r2d/voyagergx_reg.h [deleted file]
include/asm-sh/scatterlist.h
include/asm-sh/sci.h [new file with mode: 0644]
include/asm-sh/se.h [new file with mode: 0644]
include/asm-sh/se/io.h [deleted file]
include/asm-sh/se/se.h [deleted file]
include/asm-sh/se/smc37c93x.h [deleted file]
include/asm-sh/se7300.h [new file with mode: 0644]
include/asm-sh/se7300/io.h [deleted file]
include/asm-sh/se7300/se7300.h [deleted file]
include/asm-sh/se73180.h [new file with mode: 0644]
include/asm-sh/se73180/io.h [deleted file]
include/asm-sh/se73180/se73180.h [deleted file]
include/asm-sh/se7343.h [new file with mode: 0644]
include/asm-sh/se7751.h [new file with mode: 0644]
include/asm-sh/se7751/io.h [deleted file]
include/asm-sh/se7751/se7751.h [deleted file]
include/asm-sh/setup.h
include/asm-sh/sfp-machine.h [new file with mode: 0644]
include/asm-sh/sh03/io.h
include/asm-sh/sh2000/sh2000.h [deleted file]
include/asm-sh/shmin/shmin.h [new file with mode: 0644]
include/asm-sh/shmparam.h
include/asm-sh/smc37c93x.h [new file with mode: 0644]
include/asm-sh/smp.h
include/asm-sh/snapgear.h [new file with mode: 0644]
include/asm-sh/snapgear/io.h [deleted file]
include/asm-sh/spinlock.h
include/asm-sh/system.h
include/asm-sh/systemh/7751systemh.h [deleted file]
include/asm-sh/systemh/io.h [deleted file]
include/asm-sh/systemh7751.h [new file with mode: 0644]
include/asm-sh/thread_info.h
include/asm-sh/timer.h
include/asm-sh/titan.h [new file with mode: 0644]
include/asm-sh/uaccess.h
include/asm-sh/unistd.h
include/asm-sh/voyagergx.h [new file with mode: 0644]
include/asm-sh/watchdog.h
include/asm-sh64/keyboard.h
include/asm-sh64/timex.h
include/asm-sh64/unistd.h
include/asm-sparc/spinlock.h
include/asm-sparc64/spinlock.h
include/asm-um/pgtable.h
include/asm-um/processor-generic.h
include/asm-um/ptrace-x86_64.h
include/asm-v850/unistd.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/e820.h
include/asm-x86_64/nmi.h
include/asm-x86_64/proto.h
include/asm-x86_64/semaphore.h
include/asm-x86_64/spinlock.h
include/asm-x86_64/uaccess.h
include/asm-x86_64/unistd.h
include/asm-x86_64/vsyscall.h
include/asm-xtensa/timex.h
include/linux/Kbuild
include/linux/acct.h
include/linux/aer.h [new file with mode: 0644]
include/linux/aio.h
include/linux/aio_abi.h
include/linux/atalk.h
include/linux/atmlec.h
include/linux/audit.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/buffer_head.h
include/linux/cdev.h
include/linux/compat_ioctl.h
include/linux/compiler.h
include/linux/cpuset.h
include/linux/cramfs_fs.h
include/linux/dma-mapping.h
include/linux/dmi.h
include/linux/eisa.h
include/linux/elevator.h
include/linux/err.h
include/linux/errqueue.h
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/ext3_fs_i.h
include/linux/ext3_jbd.h
include/linux/file.h
include/linux/fs.h
include/linux/generic_acl.h [new file with mode: 0644]
include/linux/genhd.h
include/linux/getcpu.h
include/linux/gfp.h
include/linux/hdlc.h
include/linux/hdlc/ioctl.h
include/linux/hrtimer.h
include/linux/i2c-algo-bit.h
include/linux/i2c-algo-pcf.h
include/linux/i2c-algo-sibyte.h [deleted file]
include/linux/i2c-id.h
include/linux/i2c.h
include/linux/icmp.h
include/linux/if.h
include/linux/if_arp.h
include/linux/if_link.h [new file with mode: 0644]
include/linux/igmp.h
include/linux/in.h
include/linux/in6.h
include/linux/inet_diag.h
include/linux/inetdevice.h
include/linux/init.h
include/linux/interrupt.h
include/linux/io.h
include/linux/ip.h
include/linux/ipmi.h
include/linux/ipv6.h
include/linux/jbd.h
include/linux/kernel.h
include/linux/kmod.h
include/linux/latency.h [new file with mode: 0644]
include/linux/leds.h
include/linux/list.h
include/linux/lockdep.h
include/linux/loop.h
include/linux/memory.h
include/linux/memory_hotplug.h
include/linux/mm.h
include/linux/mm_types.h [new file with mode: 0644]
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/module.h
include/linux/mpage.h
include/linux/mroute.h
include/linux/msdos_fs.h
include/linux/namei.h
include/linux/ncp_fs.h
include/linux/netdevice.h
include/linux/netfilter_arp/arp_tables.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack_h323.h
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
include/linux/netfilter_ipv4/ip_nat.h
include/linux/netfilter_ipv4/ip_queue.h
include/linux/netfilter_ipv4/ipt_iprange.h
include/linux/nfs_fs.h
include/linux/nfsd/nfsfh.h
include/linux/nmi.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pci_regs.h
include/linux/pcieport_if.h
include/linux/percpu.h
include/linux/pid.h
include/linux/posix-timers.h
include/linux/proc_fs.h
include/linux/ptrace.h
include/linux/raid/md.h
include/linux/raid/md_k.h
include/linux/ramfs.h
include/linux/rbtree.h
include/linux/reiserfs_acl.h
include/linux/reiserfs_fs.h
include/linux/reiserfs_fs_i.h
include/linux/reiserfs_fs_sb.h
include/linux/reiserfs_xattr.h
include/linux/rtc.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/scx200_gpio.h
include/linux/security.h
include/linux/shmem_fs.h
include/linux/slab.h
include/linux/smb.h
include/linux/spinlock.h
include/linux/spinlock_api_smp.h
include/linux/stddef.h
include/linux/string.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/msg_prot.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svcauth.h
include/linux/sunrpc/xdr.h
include/linux/sunrpc/xprt.h
include/linux/synclink.h
include/linux/syscalls.h
include/linux/sysrq.h
include/linux/taskstats.h
include/linux/tcp.h
include/linux/timex.h
include/linux/trdevice.h
include/linux/tsacct_kern.h [new file with mode: 0644]
include/linux/tty.h
include/linux/types.h
include/linux/uaccess.h
include/linux/udp.h
include/linux/unwind.h
include/linux/usb.h
include/linux/usb/audio.h [new file with mode: 0644]
include/linux/usb/midi.h [new file with mode: 0644]
include/linux/usb/otg.h [new file with mode: 0644]
include/linux/usb_otg.h [deleted file]
include/linux/usb_usual.h
include/linux/utime.h
include/linux/videodev2.h
include/linux/vmalloc.h
include/linux/vmstat.h
include/linux/vt_kern.h
include/linux/wireless.h
include/linux/writeback.h
include/linux/xfrm.h
include/media/ir-common.h
include/media/tuner-types.h
include/media/tuner.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/net/arp.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/cipso_ipv4.h
include/net/dst.h
include/net/flow.h
include/net/genetlink.h
include/net/icmp.h
include/net/inet_connection_sock.h
include/net/inet_hashtables.h
include/net/inet_sock.h
include/net/inet_timewait_sock.h
include/net/inetpeer.h
include/net/ip.h
include/net/ip_fib.h
include/net/ip_mp_alg.h
include/net/ip_vs.h
include/net/ipv6.h
include/net/irda/irlan_common.h
include/net/irda/irlap_frame.h
include/net/irda/irlmp.h
include/net/netlabel.h
include/net/netlink.h
include/net/route.h
include/net/sock.h
include/net/xfrm.h
include/scsi/scsi_device.h
include/scsi/scsi_tcq.h
include/sound/pcm.h
init/Kconfig
init/do_mounts.c
init/main.c
ipc/mqueue.c
kernel/Makefile
kernel/acct.c
kernel/auditsc.c
kernel/capability.c
kernel/compat.c
kernel/cpuset.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/chip.c
kernel/kexec.c
kernel/kfifo.c
kernel/kmod.c
kernel/latency.c [new file with mode: 0644]
kernel/lockdep.c
kernel/module.c
kernel/panic.c
kernel/params.c
kernel/pid.c
kernel/posix-cpu-timers.c
kernel/posix-timers.c
kernel/ptrace.c
kernel/rcutorture.c
kernel/relay.c
kernel/resource.c
kernel/rtmutex.c
kernel/sched.c
kernel/signal.c
kernel/softirq.c
kernel/softlockup.c
kernel/spinlock.c
kernel/stop_machine.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl.c
kernel/taskstats.c
kernel/time.c
kernel/time/Makefile
kernel/time/ntp.c [new file with mode: 0644]
kernel/timer.c
kernel/tsacct.c [new file with mode: 0644]
kernel/unwind.c
lib/Kconfig.debug
lib/Makefile
lib/ioremap.c [new file with mode: 0644]
lib/list_debug.c [new file with mode: 0644]
lib/rbtree.c
lib/rwsem.c
lib/spinlock_debug.c
lib/ts_fsm.c
mm/Kconfig
mm/Makefile
mm/bounce.c [new file with mode: 0644]
mm/filemap.c
mm/fremap.c
mm/highmem.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/migrate.c
mm/mprotect.c
mm/mremap.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/shmem.c
mm/shmem_acl.c [new file with mode: 0644]
mm/slab.c
mm/slob.c
mm/swapfile.c
mm/truncate.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/802/tr.c
net/Kconfig
net/appletalk/ddp.c
net/atm/lec.c
net/atm/lec.h
net/atm/lec_arpc.h
net/atm/mpc.c
net/atm/mpoa_caches.c
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/core.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sysfs.c
net/bluetooth/hidp/core.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/tty.c
net/bridge/netfilter/ebt_arpreply.c
net/core/dev.c
net/core/ethtool.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/utils.c
net/core/wireless.c
net/dccp/ipv4.c
net/ethernet/eth.c
net/ieee80211/softmac/ieee80211softmac_wx.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/cipso_ipv4.c
net/ipv4/datagram.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_hash.c
net/ipv4/fib_lookup.h
net/ipv4/fib_rules.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/inet_hashtables.c
net/ipv4/inetpeer.c
net/ipv4/ip_fragment.c
net/ipv4/ip_options.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipcomp.c
net/ipv4/ipmr.c
net/ipv4/ipvs/ip_vs_conn.c
net/ipv4/ipvs/ip_vs_core.c
net/ipv4/ipvs/ip_vs_ctl.c
net/ipv4/ipvs/ip_vs_dh.c
net/ipv4/ipvs/ip_vs_ftp.c
net/ipv4/ipvs/ip_vs_lblc.c
net/ipv4/ipvs/ip_vs_lblcr.c
net/ipv4/ipvs/ip_vs_proto.c
net/ipv4/ipvs/ip_vs_proto_tcp.c
net/ipv4/ipvs/ip_vs_proto_udp.c
net/ipv4/ipvs/ip_vs_sh.c
net/ipv4/ipvs/ip_vs_sync.c
net/ipv4/ipvs/ip_vs_xmit.c
net/ipv4/multipath_wrandom.c
net/ipv4/netfilter.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_conntrack_amanda.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_ftp.c
net/ipv4/netfilter/ip_conntrack_helper_h323.c
net/ipv4/netfilter/ip_conntrack_helper_pptp.c
net/ipv4/netfilter/ip_conntrack_irc.c
net/ipv4/netfilter/ip_conntrack_netbios_ns.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_sctp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_sip.c
net/ipv4/netfilter/ip_conntrack_tftp.c
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_ftp.c
net/ipv4/netfilter/ip_nat_helper.c
net/ipv4/netfilter/ip_nat_helper_h323.c
net/ipv4/netfilter/ip_nat_helper_pptp.c
net/ipv4/netfilter/ip_nat_proto_icmp.c
net/ipv4/netfilter/ip_nat_proto_tcp.c
net/ipv4/netfilter/ip_nat_proto_udp.c
net/ipv4/netfilter/ip_nat_rule.c
net/ipv4/netfilter/ip_nat_sip.c
net/ipv4/netfilter/ip_nat_snmp_basic.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_ECN.c
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/netfilter/ipt_NETMAP.c
net/ipv4/netfilter/ipt_REDIRECT.c
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/ipt_SAME.c
net/ipv4/netfilter/ipt_TCPMSS.c
net/ipv4/netfilter/ipt_TOS.c
net/ipv4/netfilter/ipt_TTL.c
net/ipv4/netfilter/ipt_addrtype.c
net/ipv4/netfilter/ipt_hashlimit.c
net/ipv4/netfilter/ipt_recent.c
net/ipv4/netfilter/iptable_mangle.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_lp.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_policy.c
net/ipv4/xfrm4_state.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/inet6_hashtables.c
net/ipv6/ipcomp6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/tcp_ipv6.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_state.c
net/ipv6/xfrm6_tunnel.c
net/irda/af_irda.c
net/irda/ircomm/ircomm_lmp.c
net/irda/iriap.c
net/irda/iriap_event.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_provider.c
net/irda/irlap_frame.c
net/irda/irlmp.c
net/irda/irttp.c
net/key/af_key.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_domainhash.h
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_user.c
net/netlabel/netlabel_user.h
net/rxrpc/transport.c
net/sched/cls_api.c
net/sched/cls_basic.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sctp/input.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_null.c
net/sunrpc/auth_unix.c
net/sunrpc/clnt.c
net/sunrpc/pmap_clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/svcauth.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
net/xfrm/xfrm_hash.h
net/xfrm/xfrm_input.c
net/xfrm/xfrm_state.c
scripts/Makefile
scripts/basic/docproc.c
scripts/mod/file2alias.c
security/Kconfig
security/Makefile
security/commoncap.c
security/inode.c
security/seclvl.c [deleted file]
security/selinux/hooks.c
security/selinux/selinuxfs.c
sound/Makefile
sound/core/pcm.c
sound/core/pcm_native.c
sound/mips/au1x00.c
sound/oss/COPYING [deleted file]
sound/oss/cs46xx.c
sound/oss/cs46xxpm-24.h [deleted file]
sound/oss/sh_dac_audio.c
sound/oss/swarm_cs4297a.c
sound/oss/trident.c
sound/oss/via82cxxx_audio.c
sound/pci/echoaudio/layla24_dsp.c
sound/sound_core.c
sound/sound_firmware.c
sound/sparc/dbri.c
sound/usb/usbaudio.c
sound/usb/usbmidi.c

diff --git a/CREDITS b/CREDITS
index cc3453a55fb948f5173ff82715c304d18dc1212d..66e82466dde8af73c814354d8e4df82398e78e5c 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1620,7 +1620,8 @@ D: fbdev hacking
 
 N: Jesper Juhl
 E: jesper.juhl@gmail.com
-D: Various fixes, cleanups and minor features.
+D: Various fixes, cleanups and minor features all over the tree.
+D: Wrote initial version of the hdaps driver (since passed on to others).
 S: Lemnosvej 1, 3.tv
 S: 2300 Copenhagen S.
 S: Denmark
@@ -2477,7 +2478,8 @@ S: Derbyshire DE4 3RL
 S: United Kingdom
 
 N: Ian S. Nelson
-E: ian.nelson@echostar.com
+E: nelsonis@earthlink.net
+P: 1024D/00D3D983 3EFD 7B86 B888 D7E2 29B6  9E97 576F 1B97 00D3 D983
 D: Minor mmap and ide hacks
 S: 1370 Atlantis Ave.
 S: Lafayette CO, 80026
index 6d2412ec91edb21ebab0c13e581951bbe352b610..29c18966b0502c3489e1058bd361db50a6c07686 100644 (file)
@@ -532,6 +532,40 @@ appears outweighs the potential value of the hint that tells gcc to do
 something it would have done anyway.
 
 
+               Chapter 16: Function return values and names
+
+Functions can return values of many different kinds, and one of the
+most common is a value indicating whether the function succeeded or
+failed.  Such a value can be represented as an error-code integer
+(-Exxx = failure, 0 = success) or a "succeeded" boolean (0 = failure,
+non-zero = success).
+
+Mixing up these two sorts of representations is a fertile source of
+difficult-to-find bugs.  If the C language included a strong distinction
+between integers and booleans then the compiler would find these mistakes
+for us... but it doesn't.  To help prevent such bugs, always follow this
+convention:
+
+       If the name of a function is an action or an imperative command,
+       the function should return an error-code integer.  If the name
+       is a predicate, the function should return a "succeeded" boolean.
+
+For example, "add work" is a command, and the add_work() function returns 0
+for success or -EBUSY for failure.  In the same way, "PCI device present" is
+a predicate, and the pci_dev_present() function returns 1 if it succeeds in
+finding a matching device or 0 if it doesn't.
+
+All EXPORTed functions must respect this convention, and so should all
+public functions.  Private (static) functions need not, but it is
+recommended that they do.
+
+Functions whose return value is the actual result of a computation, rather
+than an indication of whether the computation succeeded, are not subject to
+this rule.  Generally they indicate failure by returning some out-of-range
+result.  Typical examples would be functions that return pointers; they use
+NULL or the ERR_PTR mechanism to report failure.
+
+
 
                Appendix I: References
 
index f8fe882e33dccfc50f6e5add6ca89a53389d649f..6d4b1ef5b6f11a24a1705e1c0e73b17220feb35c 100644 (file)
@@ -181,27 +181,6 @@ X!Ilib/string.c
      </sect1>
   </chapter>
 
-  <chapter id="proc">
-     <title>The proc filesystem</title>
-     <sect1><title>sysctl interface</title>
-!Ekernel/sysctl.c
-     </sect1>
-
-     <sect1><title>proc filesystem interface</title>
-!Ifs/proc/base.c
-     </sect1>
-  </chapter>
-
-  <chapter id="debugfs">
-     <title>The debugfs filesystem</title>
-     <sect1><title>debugfs interface</title>
-!Efs/debugfs/inode.c
-!Efs/debugfs/file.c
-     </sect1>
-  </chapter>
-
   <chapter id="vfs">
      <title>The Linux VFS</title>
      <sect1><title>The Filesystem types</title>
@@ -234,6 +213,50 @@ X!Ilib/string.c
      </sect1>
   </chapter>
 
+  <chapter id="proc">
+     <title>The proc filesystem</title>
+     <sect1><title>sysctl interface</title>
+!Ekernel/sysctl.c
+     </sect1>
+
+     <sect1><title>proc filesystem interface</title>
+!Ifs/proc/base.c
+     </sect1>
+  </chapter>
+
+  <chapter id="sysfs">
+     <title>The Filesystem for Exporting Kernel Objects</title>
+!Efs/sysfs/file.c
+!Efs/sysfs/symlink.c
+!Efs/sysfs/bin.c
+  </chapter>
+
+  <chapter id="debugfs">
+     <title>The debugfs filesystem</title>
+     <sect1><title>debugfs interface</title>
+!Efs/debugfs/inode.c
+!Efs/debugfs/file.c
+     </sect1>
+  </chapter>
+
+  <chapter id="relayfs">
+     <title>relay interface support</title>
+
+     <para>
+       Relay interface support
+       is designed to provide an efficient mechanism for tools and
+       facilities to relay large amounts of data from kernel space to
+       user space.
+     </para>
+
+     <sect1><title>relay interface</title>
+!Ekernel/relay.c
+!Ikernel/relay.c
+     </sect1>
+  </chapter>
+
   <chapter id="netcore">
      <title>Linux Networking</title>
      <sect1><title>Networking Base Types</title>
@@ -349,13 +372,6 @@ X!Earch/i386/kernel/mca.c
      </sect1>
   </chapter>
 
-  <chapter id="sysfs">
-     <title>The Filesystem for Exporting Kernel Objects</title>
-!Efs/sysfs/file.c
-!Efs/sysfs/symlink.c
-!Efs/sysfs/bin.c
-  </chapter>
-
   <chapter id="security">
      <title>Security Framework</title>
 !Esecurity/security.c
@@ -386,6 +402,7 @@ X!Iinclude/linux/device.h
 -->
 !Edrivers/base/driver.c
 !Edrivers/base/core.c
+!Edrivers/base/class.c
 !Edrivers/base/firmware_class.c
 !Edrivers/base/transport_class.c
 !Edrivers/base/dmapool.c
@@ -437,6 +454,11 @@ X!Edrivers/pnp/system.c
 !Eblock/ll_rw_blk.c
   </chapter>
 
+  <chapter id="chrdev">
+       <title>Char devices</title>
+!Efs/char_dev.c
+  </chapter>
+
   <chapter id="miscdev">
      <title>Miscellaneous Devices</title>
 !Edrivers/char/misc.c
index 320af25de3a276fd5b77aa830b08549c2c523793..3608472d7b7450ef291d07e8fb1dd4de69a9dbdf 100644 (file)
 
     <para>A Universal Serial Bus (USB) is used to connect a host,
     such as a PC or workstation, to a number of peripheral
-    devices.  USB uses a tree structure, with the host at the
+    devices.  USB uses a tree structure, with the host as the
     root (the system's master), hubs as interior nodes, and
-    peripheral devices as leaves (and slaves).
+    peripherals as leaves (and slaves).
     Modern PCs support several such trees of USB devices, usually
     one USB 2.0 tree (480 Mbit/sec each) with
     a few USB 1.1 trees (12 Mbit/sec each) that are used when you
     connect a USB 1.1 device directly to the machine's "root hub".
     </para>
 
-    <para>That master/slave asymmetry was designed in part for
-    ease of use.  It is not physically possible to assemble
-    (legal) USB cables incorrectly:  all upstream "to-the-host"
-    connectors are the rectangular typematching the sockets on
-    root hubs, and the downstream type are the squarish type
-    (or they are built in to the peripheral).
-    Software doesn't need to deal with distributed autoconfiguration
-    since the pre-designated master node manages all that.
-    At the electrical level, bus protocol overhead is reduced by
-    eliminating arbitration and moving scheduling into host software.
+    <para>That master/slave asymmetry was designed-in for a number of
+    reasons, one being ease of use.  It is not physically possible to
+    assemble (legal) USB cables incorrectly:  all upstream "to the host"
+    connectors are the rectangular type (matching the sockets on
+    root hubs), and all downstream connectors are the squarish type
+    (or they are built into the peripheral).
+    Also, the host software doesn't need to deal with distributed
+    auto-configuration since the pre-designated master node manages all that.
+    And finally, at the electrical level, bus protocol overhead is reduced by
+    eliminating arbitration and moving scheduling into the host software.
     </para>
 
-    <para>USB 1.0 was announced in January 1996, and was revised
+    <para>USB 1.0 was announced in January 1996 and was revised
     as USB 1.1 (with improvements in hub specification and
     support for interrupt-out transfers) in September 1998.
-    USB 2.0 was released in April 2000, including high speed
-    transfers and transaction translating hubs (used for USB 1.1
+    USB 2.0 was released in April 2000, adding high-speed
+    transfers and transaction-translating hubs (used for USB 1.1
     and 1.0 backward compatibility).
     </para>
 
-    <para>USB support was added to Linux early in the 2.2 kernel series
-    shortly before the 2.3 development forked off.  Updates
-    from 2.3 were regularly folded back into 2.2 releases, bringing
-    new features such as <filename>/sbin/hotplug</filename> support,
-    more drivers, and more robustness.
-    The 2.5 kernel series continued such improvements, and also
-    worked on USB 2.0 support,
-    higher performance,
-    better consistency between host controller drivers,
-    API simplification (to make bugs less likely),
-    and providing internal "kerneldoc" documentation.
+    <para>Kernel developers added USB support to Linux early in the 2.2 kernel
+    series, shortly before 2.3 development forked.  Updates from 2.3 were
+    regularly folded back into 2.2 releases, which improved reliability and
+    brought <filename>/sbin/hotplug</filename> support as well more drivers.
+    Such improvements were continued in the 2.5 kernel series, where they added
+    USB 2.0 support, improved performance, and made the host controller drivers
+    (HCDs) more consistent.  They also simplified the API (to make bugs less
+    likely) and added internal "kerneldoc" documentation.
     </para>
 
     <para>Linux can run inside USB devices as well as on
     the hosts that control the devices.
-    Because the Linux 2.x USB support evolved to support mass market
-    platforms such as Apple Macintosh or PC-compatible systems,
-    it didn't address design concerns for those types of USB systems.
-    So it can't be used inside mass-market PDAs, or other peripherals.
-    USB device drivers running inside those Linux peripherals
+    But USB device drivers running inside those peripherals
     don't do the same things as the ones running inside hosts,
-    and so they've been given a different name:
-    they're called <emphasis>gadget drivers</emphasis>.
-    This document does not present gadget drivers.
+    so they've been given a different name:
+    <emphasis>gadget drivers</emphasis>.
+    This document does not cover gadget drivers.
     </para>
 
     </chapter>
 <chapter id="host">
     <title>USB Host-Side API Model</title>
 
-    <para>Within the kernel,
-    host-side drivers for USB devices talk to the "usbcore" APIs.
-    There are two types of public "usbcore" APIs, targetted at two different
-    layers of USB driver.  Those are
-    <emphasis>general purpose</emphasis> drivers, exposed through
-    driver frameworks such as block, character, or network devices;
-    and drivers that are <emphasis>part of the core</emphasis>,
-    which are involved in managing a USB bus.
-    Such core drivers include the <emphasis>hub</emphasis> driver,
-    which manages trees of USB devices, and several different kinds
-    of <emphasis>host controller driver (HCD)</emphasis>,
+    <para>Host-side drivers for USB devices talk to the "usbcore" APIs.
+    There are two.  One is intended for
+    <emphasis>general-purpose</emphasis> drivers (exposed through
+    driver frameworks), and the other is for drivers that are
+    <emphasis>part of the core</emphasis>.
+    Such core drivers include the <emphasis>hub</emphasis> driver
+    (which manages trees of USB devices) and several different kinds
+    of <emphasis>host controller drivers</emphasis>,
     which control individual busses.
     </para>
 
      
     <itemizedlist>
 
-       <listitem><para>USB supports four kinds of data transfer
-       (control, bulk, interrupt, and isochronous).  Two transfer
-       types use bandwidth as it's available (control and bulk),
-       while the other two types of transfer (interrupt and isochronous)
+       <listitem><para>USB supports four kinds of data transfers
+       (control, bulk, interrupt, and isochronous).  Two of them (control
+       and bulk) use bandwidth as it's available,
+       while the other two (interrupt and isochronous)
        are scheduled to provide guaranteed bandwidth.
        </para></listitem>
 
        <listitem><para>The device description model includes one or more
        "configurations" per device, only one of which is active at a time.
-       Devices that are capable of high speed operation must also support
-       full speed configurations, along with a way to ask about the
-       "other speed" configurations that might be used.
+       Devices that are capable of high-speed operation must also support
+       full-speed configurations, along with a way to ask about the
+       "other speed" configurations which might be used.
        </para></listitem>
 
-       <listitem><para>Configurations have one or more "interface", each
+       <listitem><para>Configurations have one or more "interfaces", each
        of which may have "alternate settings".  Interfaces may be
        standardized by USB "Class" specifications, or may be specific to
        a vendor or device.</para>
        </para></listitem>
 
        <listitem><para>The Linux USB API supports synchronous calls for
-       control and bulk messaging.
+       control and bulk messages.
        It also supports asynchnous calls for all kinds of data transfer,
        using request structures called "URBs" (USB Request Blocks).
        </para></listitem>
            file in your Linux kernel sources.
            </para>
 
-           <para>Otherwise the main use for this file from programs
-           is to poll() it to get notifications of usb devices
-           as they're plugged or unplugged.
-           To see what changed, you'd need to read the file and
-           compare "before" and "after" contents, scan the filesystem,
-           or see its hotplug event.
+           <para>This file, in combination with the poll() system call, can
+           also be used to detect when devices are added or removed:
+<programlisting>int fd;
+struct pollfd pfd;
+
+fd = open("/proc/bus/usb/devices", O_RDONLY);
+pfd = { fd, POLLIN, 0 };
+for (;;) {
+       /* The first time through, this call will return immediately. */
+       poll(&amp;pfd, 1, -1);
+
+       /* To see what's changed, compare the file's previous and current
+          contents or scan the filesystem.  (Scanning is more precise.) */
+}</programlisting>
+           Note that this behavior is intended to be used for informational
+           and debug purposes.  It would be more appropriate to use programs
+           such as udev or HAL to initialize a device or start a user-mode
+           helper program, for instance.
            </para>
-
        </sect1>
 
        <sect1>
index 1d6560413cc593e001080759ce867c070956aeb7..d6f3dd1a3464f0cd6950e1c6dcecc4f7bcb6c84f 100644 (file)
@@ -375,6 +375,26 @@ of information is needed by the kernel developers to help track down the
 problem.
 
 
+Managing bug reports
+--------------------
+
+One of the best ways to put into practice your hacking skills is by fixing
+bugs reported by other people. Not only you will help to make the kernel
+more stable, you'll learn to fix real world problems and you will improve
+your skills, and other developers will be aware of your presence. Fixing
+bugs is one of the best ways to earn merit amongst the developers, because
+not many people like wasting time fixing other people's bugs.
+
+To work in the already reported bug reports, go to http://bugzilla.kernel.org.
+If you want to be advised of the future bug reports, you can subscribe to the
+bugme-new mailing list (only new bug reports are mailed here) or to the
+bugme-janitor mailing list (every change in the bugzilla is mailed here)
+
+       http://lists.osdl.org/mailman/listinfo/bugme-new
+       http://lists.osdl.org/mailman/listinfo/bugme-janitors
+
+
+
 Mailing lists
 -------------
 
index 0256805b548f8c43906c07b4e05ab1f76ae1f972..7756e09ea7595a999c69311b5bb399054154826e 100644 (file)
@@ -326,9 +326,12 @@ for events, they will all receive all events that come in.
 
 For receiving commands, you have to individually register commands you
 want to receive.  Call ipmi_register_for_cmd() and supply the netfn
-and command name for each command you want to receive.  Only one user
-may be registered for each netfn/cmd, but different users may register
-for different commands.
+and command name for each command you want to receive.  You also
+specify a bitmask of the channels you want to receive the command from
+(or use IPMI_CHAN_ALL for all channels if you don't care).  Only one
+user may be registered for each netfn/cmd/channel, but different users
+may register for different commands, or the same command if the
+channel bitmasks do not overlap.
 
 From userland, equivalent IOCTLs are provided to do these functions.
 
index a10bfb6ecd9fa4e55c9beecd2e588c9a0359ec71..7ac61f60037af81905aad58a39d70152f333eb82 100644 (file)
@@ -61,3 +61,8 @@ kernel patches.
     Documentation/kernel-parameters.txt.
 
 18: All new module parameters are documented with MODULE_PARM_DESC()
+
+19: All new userspace interfaces are documented in Documentation/ABI/.
+    See Documentation/ABI/README for more information.
+
+20: Check that it all passes `make headers_check'.
index 6bd30fdd0786b9a7c64aa4c34f5a732b4c7096e0..58bead05eabb057fb777bdd5fe7a56b44f35b0e0 100644 (file)
@@ -59,11 +59,11 @@ Copyright:  The copyright owner must agree to use of GPL.
                are the same person/entity. If not, the name of
                the person/entity authorizing use of GPL should be
                listed in case it's necessary to verify the will of
-               the copright owner.
+               the copyright owner.
 
 Interfaces:    If your driver uses existing interfaces and behaves like
                other drivers in the same class it will be much more likely
-               to be accepted than if it invents gratuitous new ones. 
+               to be accepted than if it invents gratuitous new ones.
                If you need to implement a common API over Linux and NT
                drivers do it in userspace.
 
@@ -88,7 +88,7 @@ Clarity:      It helps if anyone can see how to fix the driver. It helps
                it will go in the bitbucket.
 
 Control:       In general if there is active maintainance of a driver by
-               the author then patches will be redirected to them unless 
+               the author then patches will be redirected to them unless
                they are totally obvious and without need of checking.
                If you want to be the contact and update point for the
                driver it is a good idea to state this in the comments,
@@ -100,7 +100,7 @@ What Criteria Do Not Determine Acceptance
 Vendor:                Being the hardware vendor and maintaining the driver is
                often a good thing. If there is a stable working driver from
                other people already in the tree don't expect 'we are the
-               vendor' to get your driver chosen. Ideally work with the 
+               vendor' to get your driver chosen. Ideally work with the
                existing driver author to build a single perfect driver.
 
 Author:                It doesn't matter if a large Linux company wrote the driver,
@@ -116,17 +116,13 @@ Linux kernel master tree:
        ftp.??.kernel.org:/pub/linux/kernel/...
        ?? == your country code, such as "us", "uk", "fr", etc.
 
-Linux kernel mailing list:             
+Linux kernel mailing list:
        linux-kernel@vger.kernel.org
        [mail majordomo@vger.kernel.org to subscribe]
 
 Linux Device Drivers, Third Edition (covers 2.6.10):
        http://lwn.net/Kernel/LDD3/  (free version)
 
-Kernel traffic:
-       Weekly summary of kernel list activity (much easier to read)
-       http://www.kerneltraffic.org/kernel-traffic/
-
 LWN.net:
        Weekly summary of kernel development activity - http://lwn.net/
        2.6 API changes:
@@ -145,11 +141,8 @@ KernelNewbies:
 Linux USB project:
        http://www.linux-usb.org/
 
-How to NOT write kernel driver by arjanv@redhat.com
-       http://people.redhat.com/arjanv/olspaper.pdf
+How to NOT write kernel driver by Arjan van de Ven:
+       http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
 
 Kernel Janitor:
        http://janitor.kernelnewbies.org/
-
---
-Last updated on 17 Nov 2005.
index d42ab4c9e893b787d0918cc9f5a540a785a11aee..302d148c2e18f0e0fe565bc9c9c1a2f4b232d346 100644 (file)
@@ -173,15 +173,15 @@ For small patches you may want to CC the Trivial Patch Monkey
 trivial@kernel.org managed by Adrian Bunk; which collects "trivial"
 patches. Trivial patches must qualify for one of the following rules:
  Spelling fixes in documentation
- Spelling fixes which could break grep(1).
+ Spelling fixes which could break grep(1)
  Warning fixes (cluttering with useless warnings is bad)
  Compilation fixes (only if they are actually correct)
  Runtime fixes (only if they actually fix things)
- Removing use of deprecated functions/macros (eg. check_region).
+ Removing use of deprecated functions/macros (eg. check_region)
  Contact detail and documentation fixes
  Non-portable code replaced by portable code (even in arch-specific,
  since people copy, as long as it's trivial)
- Any fix by the author/maintainer of the file. (ie. patch monkey
+ Any fix by the author/maintainer of the file (ie. patch monkey
  in re-transmission mode)
 URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
 
@@ -209,6 +209,19 @@ Exception:  If your mailer is mangling patches then someone may ask
 you to re-send them using MIME.
 
 
+WARNING: Some mailers like Mozilla send your messages with
+---- message header ----
+Content-Type: text/plain; charset=us-ascii; format=flowed
+---- message header ----
+The problem is that "format=flowed" makes some of the mailers
+on receiving side to replace TABs with spaces and do similar
+changes. Thus the patches from you can look corrupted.
+
+To fix this just make your mozilla defaults/pref/mailnews.js file to look like:
+pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
+pref("mailnews.display.disable_format_flowed_support", true);
+
+
 
 7) E-mail size.
 
@@ -245,13 +258,13 @@ updated change.
 It is quite common for Linus to "drop" your patch without comment.
 That's the nature of the system.  If he drops your patch, it could be
 due to
-* Your patch did not apply cleanly to the latest kernel version
+* Your patch did not apply cleanly to the latest kernel version.
 * Your patch was not sufficiently discussed on linux-kernel.
-* A style issue (see section 2),
-* An e-mail formatting issue (re-read this section)
-* A technical problem with your change
-* He gets tons of e-mail, and yours got lost in the shuffle
-* You are being annoying (See Figure 1)
+* A style issue (see section 2).
+* An e-mail formatting issue (re-read this section).
+* A technical problem with your change.
+* He gets tons of e-mail, and yours got lost in the shuffle.
+* You are being annoying.
 
 When in doubt, solicit comments on linux-kernel mailing list.
 
@@ -476,10 +489,10 @@ SECTION 3 - REFERENCES
 Andrew Morton, "The perfect patch" (tpp).
   <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
 
-Jeff Garzik, "Linux kernel patch submission format."
+Jeff Garzik, "Linux kernel patch submission format".
   <http://linux.yyz.us/patch-format.html>
 
-Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
   <http://www.kroah.com/log/2005/03/31/>
   <http://www.kroah.com/log/2005/07/08/>
   <http://www.kroah.com/log/2005/10/19/>
@@ -488,9 +501,9 @@ Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
 NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
   <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
 
-Kernel Documentation/CodingStyle
+Kernel Documentation/CodingStyle:
   <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
 
-Linus Torvald's mail on the canonical patch format:
+Linus Torvalds's mail on the canonical patch format:
   <http://lkml.org/lkml/2005/4/7/183>
 --
index 795ca3911cc58f7fd043a6e51b95df8e9bff449f..b11792abd6b616d56754edcc9b940a519f7a36fb 100644 (file)
@@ -285,7 +285,7 @@ int main(int argc, char *argv[])
        if (maskset) {
                rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
                              TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
-                             &cpumask, sizeof(cpumask));
+                             &cpumask, strlen(cpumask) + 1);
                PRINTF("Sent register cpumask, retval %d\n", rc);
                if (rc < 0) {
                        printf("error sending register cpumask\n");
@@ -315,7 +315,8 @@ int main(int argc, char *argv[])
                }
                if (msg.n.nlmsg_type == NLMSG_ERROR ||
                    !NLMSG_OK((&msg.n), rep_len)) {
-                       printf("fatal reply error,  errno %d\n", errno);
+                       struct nlmsgerr *err = NLMSG_DATA(&msg);
+                       printf("fatal reply error,  errno %d\n", err->error);
                        goto done;
                }
 
@@ -383,7 +384,7 @@ done:
        if (maskset) {
                rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
                              TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
-                             &cpumask, sizeof(cpumask));
+                             &cpumask, strlen(cpumask) + 1);
                printf("Sent deregister mask, retval %d\n", rc);
                if (rc < 0)
                        err(rc, "error sending deregister cpumask\n");
diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt
new file mode 100644 (file)
index 0000000..661c797
--- /dev/null
@@ -0,0 +1,161 @@
+The struct taskstats
+--------------------
+
+This document contains an explanation of the struct taskstats fields.
+
+There are three different groups of fields in the struct taskstats:
+
+1) Common and basic accounting fields
+    If CONFIG_TASKSTATS is set, the taskstats inteface is enabled and
+    the common fields and basic accounting fields are collected for
+    delivery at do_exit() of a task.
+2) Delay accounting fields
+    These fields are placed between
+    /* Delay accounting fields start */
+    and
+    /* Delay accounting fields end */
+    Their values are collected if CONFIG_TASK_DELAY_ACCT is set.
+3) Extended accounting fields
+    These fields are placed between
+    /* Extended accounting fields start */
+    and
+    /* Extended accounting fields end */
+    Their values are collected if CONFIG_TASK_XACCT is set.
+
+Future extension should add fields to the end of the taskstats struct, and
+should not change the relative position of each field within the struct.
+
+
+struct taskstats {
+
+1) Common and basic accounting fields:
+       /* The version number of this struct. This field is always set to
+        * TAKSTATS_VERSION, which is defined in <linux/taskstats.h>.
+        * Each time the struct is changed, the value should be incremented.
+        */
+       __u16   version;
+
+       /* The exit code of a task. */
+       __u32   ac_exitcode;            /* Exit status */
+
+       /* The accounting flags of a task as defined in <linux/acct.h>
+        * Defined values are AFORK, ASU, ACOMPAT, ACORE, and AXSIG.
+        */
+       __u8    ac_flag;                /* Record flags */
+
+       /* The value of task_nice() of a task. */
+       __u8    ac_nice;                /* task_nice */
+
+       /* The name of the command that started this task. */
+       char    ac_comm[TS_COMM_LEN];   /* Command name */
+
+       /* The scheduling discipline as set in task->policy field. */
+       __u8    ac_sched;               /* Scheduling discipline */
+
+       __u8    ac_pad[3];
+       __u32   ac_uid;                 /* User ID */
+       __u32   ac_gid;                 /* Group ID */
+       __u32   ac_pid;                 /* Process ID */
+       __u32   ac_ppid;                /* Parent process ID */
+
+       /* The time when a task begins, in [secs] since 1970. */
+       __u32   ac_btime;               /* Begin time [sec since 1970] */
+
+       /* The elapsed time of a task, in [usec]. */
+       __u64   ac_etime;               /* Elapsed time [usec] */
+
+       /* The user CPU time of a task, in [usec]. */
+       __u64   ac_utime;               /* User CPU time [usec] */
+
+       /* The system CPU time of a task, in [usec]. */
+       __u64   ac_stime;               /* System CPU time [usec] */
+
+       /* The minor page fault count of a task, as set in task->min_flt. */
+       __u64   ac_minflt;              /* Minor Page Fault Count */
+
+       /* The major page fault count of a task, as set in task->maj_flt. */
+       __u64   ac_majflt;              /* Major Page Fault Count */
+
+
+2) Delay accounting fields:
+       /* Delay accounting fields start
+        *
+        * All values, until the comment "Delay accounting fields end" are
+        * available only if delay accounting is enabled, even though the last
+        * few fields are not delays
+        *
+        * xxx_count is the number of delay values recorded
+        * xxx_delay_total is the corresponding cumulative delay in nanoseconds
+        *
+        * xxx_delay_total wraps around to zero on overflow
+        * xxx_count incremented regardless of overflow
+        */
+
+       /* Delay waiting for cpu, while runnable
+        * count, delay_total NOT updated atomically
+        */
+       __u64   cpu_count;
+       __u64   cpu_delay_total;
+
+       /* Following four fields atomically updated using task->delays->lock */
+
+       /* Delay waiting for synchronous block I/O to complete
+        * does not account for delays in I/O submission
+        */
+       __u64   blkio_count;
+       __u64   blkio_delay_total;
+
+       /* Delay waiting for page fault I/O (swap in only) */
+       __u64   swapin_count;
+       __u64   swapin_delay_total;
+
+       /* cpu "wall-clock" running time
+        * On some architectures, value will adjust for cpu time stolen
+        * from the kernel in involuntary waits due to virtualization.
+        * Value is cumulative, in nanoseconds, without a corresponding count
+        * and wraps around to zero silently on overflow
+        */
+       __u64   cpu_run_real_total;
+
+       /* cpu "virtual" running time
+        * Uses time intervals seen by the kernel i.e. no adjustment
+        * for kernel's involuntary waits due to virtualization.
+        * Value is cumulative, in nanoseconds, without a corresponding count
+        * and wraps around to zero silently on overflow
+        */
+       __u64   cpu_run_virtual_total;
+       /* Delay accounting fields end */
+       /* version 1 ends here */
+
+
+3) Extended accounting fields
+       /* Extended accounting fields start */
+
+       /* Accumulated RSS usage in duration of a task, in MBytes-usecs.
+        * The current rss usage is added to this counter every time
+        * a tick is charged to a task's system time. So, at the end we
+        * will have memory usage multiplied by system time. Thus an
+        * average usage per system time unit can be calculated.
+        */
+       __u64   coremem;                /* accumulated RSS usage in MB-usec */
+
+       /* Accumulated virtual memory usage in duration of a task.
+        * Same as acct_rss_mem1 above except that we keep track of VM usage.
+        */
+       __u64   virtmem;                /* accumulated VM usage in MB-usec */
+
+       /* High watermark of RSS usage in duration of a task, in KBytes. */
+       __u64   hiwater_rss;            /* High-watermark of RSS usage */
+
+       /* High watermark of VM  usage in duration of a task, in KBytes. */
+       __u64   hiwater_vm;             /* High-water virtual memory usage */
+
+       /* The following four fields are I/O statistics of a task. */
+       __u64   read_char;              /* bytes read */
+       __u64   write_char;             /* bytes written */
+       __u64   read_syscalls;          /* read syscalls */
+       __u64   write_syscalls;         /* write syscalls */
+
+       /* Extended accounting fields end */
+
+}
index 76b44290c1546c50a4e15527c18a19e626249f35..842f0d1ab2165781420fdd53b3875a16ba91adb6 100644 (file)
@@ -217,11 +217,11 @@ exclusive cpuset.  Also, the use of a Linux virtual file system (vfs)
 to represent the cpuset hierarchy provides for a familiar permission
 and name space for cpusets, with a minimum of additional kernel code.
 
-The cpus file in the root (top_cpuset) cpuset is read-only.
-It automatically tracks the value of cpu_online_map, using a CPU
-hotplug notifier.  If and when memory nodes can be hotplugged,
-we expect to make the mems file in the root cpuset read-only
-as well, and have it track the value of node_online_map.
+The cpus and mems files in the root (top_cpuset) cpuset are
+read-only.  The cpus file automatically tracks the value of
+cpu_online_map using a CPU hotplug notifier, and the mems file
+automatically tracks the value of node_online_map using the
+cpuset_track_online_nodes() hook.
 
 
 1.4 What are exclusive cpusets ?
index 66c725f530f38b2c836f52ced2fa898c640f8db1..addc67b1d770e26fd0dee02613866a40735f01b1 100644 (file)
@@ -2543,6 +2543,9 @@ Your cooperation is appreciated.
                 64 = /dev/usb/rio500   Diamond Rio 500
                 65 = /dev/usb/usblcd   USBLCD Interface (info@usblcd.de)
                 66 = /dev/usb/cpad0    Synaptics cPad (mouse/LCD)
+                67 = /dev/usb/adutux0  1st Ontrak ADU device
+                   ...
+                76 = /dev/usb/adutux10 10th Ontrak ADU device
                 96 = /dev/usb/hiddev0  1st USB HID device
                    ...
                111 = /dev/usb/hiddev15 16th USB HID device
index c12d39a23c3d1b43827f2fe37a1b1776036db2d1..aa0d322db171d1175bee86f2e85448a94ceff8d7 100644 (file)
@@ -1,16 +1,19 @@
-Intel 830M/845G/852GM/855GM/865G/915G Framebuffer driver
+Intel 830M/845G/852GM/855GM/865G/915G/945G Framebuffer driver
 ================================================================
 
 A. Introduction
-       This is a framebuffer driver for various Intel 810/815 compatible
+       This is a framebuffer driver for various Intel 8xx/9xx compatible
 graphics devices.  These would include:
 
        Intel 830M
-       Intel 810E845G
+       Intel 845G
        Intel 852GM
        Intel 855GM
        Intel 865G
        Intel 915G
+       Intel 915GM
+       Intel 945G
+       Intel 945GM
 
 B.  List of available options
 
@@ -78,7 +81,7 @@ C. Kernel booting
 Separate each option/option-pair by commas (,) and the option from its value
 with an equals sign (=) as in the following:
 
-video=i810fb:option1,option2=value2
+video=intelfb:option1,option2=value2
 
 Sample Usage
 ------------
index 611acc32fdf545be7b3efd88cd6aa26bc852887c..9364f47c711690e4a262ed0c93c1072ff1be181e 100644 (file)
@@ -46,17 +46,8 @@ Who: Jody McIntyre <scjody@modernduck.com>
 
 ---------------------------
 
-What:  sbp2: module parameter "force_inquiry_hack"
-When:  July 2006
-Why:   Superceded by parameter "workarounds". Both parameters are meant to be
-       used ad-hoc and for single devices only, i.e. not in modprobe.conf,
-       therefore the impact of this feature replacement should be low.
-Who:   Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
 What:  Video4Linux API 1 ioctls and video_decoder.h from Video devices.
-When:  July 2006
+When:  December 2006
 Why:   V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
        series. The old API have lots of drawbacks and don't provide enough
        means to work with all video and audio standards. The newer API is
@@ -70,6 +61,18 @@ Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
 
 ---------------------------
 
+What:  sys_sysctl
+When:  January 2007
+Why:   The same information is available through /proc/sys and that is the
+       interface user space prefers to use. And there do not appear to be
+       any existing user in user space of sys_sysctl.  The additional
+       maintenance overhead of keeping a set of binary names gets
+       in the way of doing a good job of maintaining this interface.
+
+Who:   Eric Biederman <ebiederm@xmission.com>
+
+---------------------------
+
 What:  PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
 When:  November 2005
 Files: drivers/pcmcia/: pcmcia_ioctl.c
@@ -217,14 +220,6 @@ Who:       Nick Piggin <npiggin@suse.de>
 
 ---------------------------
 
-What:  Support for the MIPS EV96100 evaluation board
-When:  September 2006
-Why:   Does no longer build since at least November 15, 2003, apparently
-       no userbase left.
-Who:   Ralf Baechle <ralf@linux-mips.org>
-
----------------------------
-
 What:  Support for the Momentum / PMC-Sierra Jaguar ATX evaluation board
 When:  September 2006
 Why:   Does no longer build since quite some time, and was never popular,
@@ -321,3 +316,12 @@ Why:       The stacking of class devices makes these values misleading and
 Who:   Kay Sievers <kay.sievers@suse.de>
 
 ---------------------------
+
+What:  i2c-isa
+When:  December 2006
+Why:   i2c-isa is a non-sense and doesn't fit in the device driver
+       model. Drivers relying on it are better implemented as platform
+       drivers.
+Who:   Jean Delvare <khali@linux-fr.org>
+
+---------------------------
index 247d7f619aa2c8cc86e7777004c198428798ff9c..eb1a6cad21e6a8cadc993111b1f4c7099d794ad2 100644 (file)
@@ -356,10 +356,9 @@ The last two are called only from check_disk_change().
 prototypes:
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
-       ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
-       ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t,
-                       loff_t);
+       ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+       ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int,
index 7db71d6fba824bc92f08785578d7dc8fefb4c5aa..7240ee7515decf7b8d5205a18e43b891ddba2f9a 100644 (file)
@@ -39,6 +39,8 @@ Table of Contents
   2.9  Appletalk
   2.10 IPX
   2.11 /proc/sys/fs/mqueue - POSIX message queues filesystem
+  2.12 /proc/<pid>/oom_adj - Adjust the oom-killer score
+  2.13 /proc/<pid>/oom_score - Display current oom-killer score
 
 ------------------------------------------------------------------------------
 Preface
@@ -1962,6 +1964,22 @@ a queue must be less or equal then msg_max.
 maximum  message size value (it is every  message queue's attribute set during
 its creation).
 
+2.12 /proc/<pid>/oom_adj - Adjust the oom-killer score
+------------------------------------------------------
+
+This file can be used to adjust the score used to select which processes
+should be killed in an  out-of-memory  situation.  Giving it a high score will
+increase the likelihood of this process being killed by the oom-killer.  Valid
+values are in the range -16 to +15, plus the special value -17, which disables
+oom-killing altogether for this process.
+
+2.13 /proc/<pid>/oom_score - Display current oom-killer score
+-------------------------------------------------------------
+
+------------------------------------------------------------------------------
+This file can be used to check the current score used by the oom-killer is for
+any given <pid>. Use it together with /proc/<pid>/oom_adj to tune which
+process should be killed in an out-of-memory situation.
 
 ------------------------------------------------------------------------------
 Summary
index 1cb7e8be927ad55acdd739bd31439096d9c55d5d..cd07c21b84005cb4e2cd3980f1c103ec94824662 100644 (file)
@@ -699,9 +699,9 @@ This describes how the VFS can manipulate an open file. As of kernel
 struct file_operations {
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
-       ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
-       ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+       ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+       ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
index 9555be1ed99947b88a776fa2b9e6b49e143fde2e..e783fd62e3085a5abb7a965d83fa3b462d990e8d 100644 (file)
@@ -13,12 +13,25 @@ Supported chips:
                        from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
                http://www.ite.com.tw/
+  * IT8716F
+    Prefix: 'it8716'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP
+  * IT8718F
+    Prefix: 'it8718'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip
+               http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip
   * SiS950   [clone of IT8705F]
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: No longer be available
 
-Author: Christophe Gauthron <chrisg@0-in.com>
+Authors:
+    Christophe Gauthron <chrisg@0-in.com>
+    Jean Delvare <khali@linux-fr.org>
 
 
 Module Parameters
@@ -43,26 +56,46 @@ Module Parameters
 Description
 -----------
 
-This driver implements support for the IT8705F, IT8712F and SiS950 chips.
-
-This driver also supports IT8712F, which adds SMBus access, and a VID
-input, used to report the Vcore voltage of the Pentium processor.
-The IT8712F additionally features VID inputs.
+This driver implements support for the IT8705F, IT8712F, IT8716F,
+IT8718F and SiS950 chips.
 
 These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
 joysticks and other miscellaneous stuff. For hardware monitoring, they
 include an 'environment controller' with 3 temperature sensors, 3 fan
 rotation speed sensors, 8 voltage sensors, and associated alarms.
 
+The IT8712F and IT8716F additionally feature VID inputs, used to report
+the Vcore voltage of the processor. The early IT8712F have 5 VID pins,
+the IT8716F and late IT8712F have 6. They are shared with other functions
+though, so the functionality may not be available on a given system.
+The driver dumbly assume it is there.
+
+The IT8718F also features VID inputs (up to 8 pins) but the value is
+stored in the Super-I/O configuration space. Due to technical limitations,
+this value can currently only be read once at initialization time, so
+the driver won't notice and report changes in the VID value. The two
+upper VID bits share their pins with voltage inputs (in5 and in6) so you
+can't have both on a given board.
+
+The IT8716F, IT8718F and later IT8712F revisions have support for
+2 additional fans. They are not yet supported by the driver.
+
+The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
+16-bit tachometer counters for fans 1 to 3. This is better (no more fan
+clock divider mess) but not compatible with the older chips and
+revisions. For now, the driver only uses the 16-bit mode on the
+IT8716F and IT8718F.
+
 Temperatures are measured in degrees Celsius. An alarm is triggered once
 when the Overtemperature Shutdown limit is crossed.
 
 Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
-triggered if the rotation speed has dropped below a programmable limit. Fan
-readings can be divided by a programmable divider (1, 2, 4 or 8) to give the
-readings more range or accuracy. Not all RPM values can accurately be
-represented, so some rounding is done. With a divider of 2, the lowest
-representable value is around 2600 RPM.
+triggered if the rotation speed has dropped below a programmable limit. When
+16-bit tachometer counters aren't used, fan readings can be divided by
+a programmable divider (1, 2, 4 or 8) to give the readings more range or
+accuracy. With a divider of 2, the lowest representable value is around
+2600 RPM. Not all RPM values can accurately be represented, so some rounding
+is done.
 
 Voltage sensors (also known as IN sensors) report their values in volts. An
 alarm is triggered if the voltage has crossed a programmable minimum or
@@ -71,9 +104,9 @@ zero'; this is important for negative voltage measurements. All voltage
 inputs can measure voltages between 0 and 4.08 volts, with a resolution of
 0.016 volt. The battery voltage in8 does not have limit registers.
 
-The VID lines (IT8712F only) encode the core voltage value: the voltage
-level your processor should work with. This is hardcoded by the mainboard
-and/or processor itself. It is a value in volts.
+The VID lines (IT8712F/IT8716F/IT8718F) encode the core voltage value:
+the voltage level your processor should work with. This is hardcoded by
+the mainboard and/or processor itself. It is a value in volts.
 
 If an alarm triggers, it will remain triggered until the hardware register
 is read at least once. This means that the cause for the alarm may already
diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp
new file mode 100644 (file)
index 0000000..bab445a
--- /dev/null
@@ -0,0 +1,52 @@
+Kernel driver k8temp
+====================
+
+Supported chips:
+  * AMD K8 CPU
+    Prefix: 'k8temp'
+    Addresses scanned: PCI space
+    Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
+
+Author: Rudolf Marek
+Contact: Rudolf Marek <r.marek@sh.cvut.cz>
+
+Description
+-----------
+
+This driver permits reading temperature sensor(s) embedded inside AMD K8 CPUs.
+Official documentation says that it works from revision F of K8 core, but
+in fact it seems to be implemented for all revisions of K8 except the first
+two revisions (SH-B0 and SH-B3).
+
+There can be up to four temperature sensors inside single CPU. The driver
+will auto-detect the sensors and will display only temperatures from
+implemented sensors.
+
+Mapping of /sys files is as follows:
+
+temp1_input - temperature of Core 0 and "place" 0
+temp2_input - temperature of Core 0 and "place" 1
+temp3_input - temperature of Core 1 and "place" 0
+temp4_input - temperature of Core 1 and "place" 1
+
+Temperatures are measured in degrees Celsius and measurement resolution is
+1 degree C. It is expected that future CPU will have better resolution. The
+temperature is updated once a second. Valid temperatures are from -49 to
+206 degrees C.
+
+Temperature known as TCaseMax was specified for processors up to revision E.
+This temperature is defined as temperature between heat-spreader and CPU
+case, so the internal CPU temperature supplied by this driver can be higher.
+There is no easy way how to measure the temperature which will correlate
+with TCaseMax temperature.
+
+For newer revisions of CPU (rev F, socket AM2) there is a mathematically
+computed temperature called TControl, which must be lower than TControlMax.
+
+The relationship is following:
+
+temp1_input - TjOffset*2 < TControlMax,
+
+TjOffset is not yet exported by the driver, TControlMax is usually
+70 degrees C. The rule of the thumb -> CPU temperature should not cross
+60 degrees C too much.
diff --git a/Documentation/hwmon/vt1211 b/Documentation/hwmon/vt1211
new file mode 100644 (file)
index 0000000..77fa633
--- /dev/null
@@ -0,0 +1,206 @@
+Kernel driver vt1211
+====================
+
+Supported chips:
+  * VIA VT1211
+    Prefix: 'vt1211'
+    Addresses scanned: none, address read from Super-I/O config space
+    Datasheet: Provided by VIA upon request and under NDA
+
+Authors: Juerg Haefliger <juergh@gmail.com>
+
+This driver is based on the driver for kernel 2.4 by Mark D. Studebaker and
+its port to kernel 2.6 by Lars Ekman.
+
+Thanks to Joseph Chan and Fiona Gatt from VIA for providing documentation and
+technical support.
+
+
+Module Parameters
+-----------------
+
+* uch_config: int      Override the BIOS default universal channel (UCH)
+                       configuration for channels 1-5.
+                       Legal values are in the range of 0-31. Bit 0 maps to
+                       UCH1, bit 1 maps to UCH2 and so on. Setting a bit to 1
+                       enables the thermal input of that particular UCH and
+                       setting a bit to 0 enables the voltage input.
+
+* int_mode: int                Override the BIOS default temperature interrupt mode.
+                       The only possible value is 0 which forces interrupt
+                       mode 0. In this mode, any pending interrupt is cleared
+                       when the status register is read but is regenerated as
+                       long as the temperature stays above the hysteresis
+                       limit.
+
+Be aware that overriding BIOS defaults might cause some unwanted side effects!
+
+
+Description
+-----------
+
+The VIA VT1211 Super-I/O chip includes complete hardware monitoring
+capabilities. It monitors 2 dedicated temperature sensor inputs (temp1 and
+temp2), 1 dedicated voltage (in5) and 2 fans. Additionally, the chip
+implements 5 universal input channels (UCH1-5) that can be individually
+programmed to either monitor a voltage or a temperature.
+
+This chip also provides manual and automatic control of fan speeds (according
+to the datasheet). The driver only supports automatic control since the manual
+mode doesn't seem to work as advertised in the datasheet. In fact I couldn't
+get manual mode to work at all! Be aware that automatic mode hasn't been
+tested very well (due to the fact that my EPIA M10000 doesn't have the fans
+connected to the PWM outputs of the VT1211 :-().
+
+The following table shows the relationship between the vt1211 inputs and the
+sysfs nodes.
+
+Sensor          Voltage Mode   Temp Mode   Default Use (from the datasheet)
+------          ------------   ---------   --------------------------------
+Reading 1                      temp1       Intel thermal diode
+Reading 3                      temp2       Internal thermal diode
+UCH1/Reading2   in0            temp3       NTC type thermistor
+UCH2            in1            temp4       +2.5V
+UCH3            in2            temp5       VccP (processor core)
+UCH4            in3            temp6       +5V
+UCH5            in4            temp7       +12V
++3.3V           in5                        Internal VCC (+3.3V)
+
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled by an 8-bit ADC with a LSB of ~10mV. The supported input
+range is thus from 0 to 2.60V. Voltage values outside of this range need
+external scaling resistors. This external scaling needs to be compensated for
+via compute lines in sensors.conf, like:
+
+compute inx @*(1+R1/R2), @/(1+R1/R2)
+
+The board level scaling resistors according to VIA's recommendation are as
+follows. And this is of course totally dependent on the actual board
+implementation :-) You will have to find documentation for your own
+motherboard and edit sensors.conf accordingly.
+
+                                      Expected
+Voltage       R1     R2     Divider   Raw Value
+-----------------------------------------------
++2.5V         2K     10K    1.2       2083 mV
+VccP          ---    ---    1.0       1400 mV (1)
++5V           14K    10K    2.4       2083 mV
++12V          47K    10K    5.7       2105 mV
++3.3V (int)   2K     3.4K   1.588     3300 mV (2)
++3.3V (ext)   6.8K   10K    1.68      1964 mV
+
+(1) Depending on the CPU (1.4V is for a VIA C3 Nehemiah).
+(2) R1 and R2 for 3.3V (int) are internal to the VT1211 chip and the driver
+    performs the scaling and returns the properly scaled voltage value.
+
+Each measured voltage has an associated low and high limit which triggers an
+alarm when crossed.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in millidegree Celsius. Each measured temperature
+has a high limit which triggers an alarm if crossed. There is an associated
+hysteresis value with each temperature below which the temperature has to drop
+before the alarm is cleared (this is only true for interrupt mode 0). The
+interrupt mode can be forced to 0 in case the BIOS doesn't do it
+automatically. See the 'Module Parameters' section for details.
+
+All temperature channels except temp2 are external. Temp2 is the VT1211
+internal thermal diode and the driver does all the scaling for temp2 and
+returns the temperature in millidegree Celsius. For the external channels
+temp1 and temp3-temp7, scaling depends on the board implementation and needs
+to be performed in userspace via sensors.conf.
+
+Temp1 is an Intel-type thermal diode which requires the following formula to
+convert between sysfs readings and real temperatures:
+
+compute temp1 (@-Offset)/Gain, (@*Gain)+Offset
+
+According to the VIA VT1211 BIOS porting guide, the following gain and offset
+values should be used:
+
+Diode Type      Offset   Gain
+----------      ------   ----
+Intel CPU       88.638   0.9528
+                65.000   0.9686   *)
+VIA C3 Ezra     83.869   0.9528
+VIA C3 Ezra-T   73.869   0.9528
+
+*) This is the formula from the lm_sensors 2.10.0 sensors.conf file. I don't
+know where it comes from or how it was derived, it's just listed here for
+completeness.
+
+Temp3-temp7 support NTC thermistors. For these channels, the driver returns
+the voltages as seen at the individual pins of UCH1-UCH5. The voltage at the
+pin (Vpin) is formed by a voltage divider made of the thermistor (Rth) and a
+scaling resistor (Rs):
+
+Vpin = 2200 * Rth / (Rs + Rth)   (2200 is the ADC max limit of 2200 mV)
+
+The equation for the thermistor is as follows (google it if you want to know
+more about it):
+
+Rth = Ro * exp(B * (1 / T - 1 / To))   (To is 298.15K (25C) and Ro is the
+                                        nominal resistance at 25C)
+
+Mingling the above two equations and assuming Rs = Ro and B = 3435 yields the
+following formula for sensors.conf:
+
+compute tempx 1 / (1 / 298.15 - (` (2200 / @ - 1)) / 3435) - 273.15,
+              2200 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @))))
+
+
+Fan Speed Control
+-----------------
+
+The VT1211 provides 2 programmable PWM outputs to control the speeds of 2
+fans. Writing a 2 to any of the two pwm[1-2]_enable sysfs nodes will put the
+PWM controller in automatic mode. There is only a single controller that
+controls both PWM outputs but each PWM output can be individually enabled and
+disabled.
+
+Each PWM has 4 associated distinct output duty-cycles: full, high, low and
+off. Full and off are internally hard-wired to 255 (100%) and 0 (0%),
+respectively. High and low can be programmed via
+pwm[1-2]_auto_point[2-3]_pwm. Each PWM output can be associated with a
+different thermal input but - and here's the weird part - only one set of
+thermal thresholds exist that controls both PWMs output duty-cycles. The
+thermal thresholds are accessible via pwm[1-2]_auto_point[1-4]_temp. Note
+that even though there are 2 sets of 4 auto points each, they map to the same
+registers in the VT1211 and programming one set is sufficient (actually only
+the first set pwm1_auto_point[1-4]_temp is writable, the second set is
+read-only).
+
+PWM Auto Point             PWM Output Duty-Cycle
+------------------------------------------------
+pwm[1-2]_auto_point4_pwm   full speed duty-cycle (hard-wired to 255)
+pwm[1-2]_auto_point3_pwm   high speed duty-cycle
+pwm[1-2]_auto_point2_pwm   low speed duty-cycle
+pwm[1-2]_auto_point1_pwm   off duty-cycle (hard-wired to 0)
+
+Temp Auto Point             Thermal Threshold
+---------------------------------------------
+pwm[1-2]_auto_point4_temp   full speed temp
+pwm[1-2]_auto_point3_temp   high speed temp
+pwm[1-2]_auto_point2_temp   low speed temp
+pwm[1-2]_auto_point1_temp   off temp
+
+Long story short, the controller implements the following algorithm to set the
+PWM output duty-cycle based on the input temperature:
+
+Thermal Threshold             Output Duty-Cycle
+                    (Rising Temp)           (Falling Temp)
+----------------------------------------------------------
+                    full speed duty-cycle   full speed duty-cycle
+full speed temp
+                    high speed duty-cycle   full speed duty-cycle
+high speed temp
+                    low speed duty-cycle    high speed duty-cycle
+low speed temp
+                    off duty-cycle          low speed duty-cycle
+off temp
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
new file mode 100644 (file)
index 0000000..fae3b78
--- /dev/null
@@ -0,0 +1,85 @@
+Kernel driver w83627ehf
+=======================
+
+Supported chips:
+  * Winbond W83627EHF/EHG (ISA access ONLY)
+    Prefix: 'w83627ehf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf
+
+Authors:
+        Jean Delvare <khali@linux-fr.org>
+        Yuan Mu (Winbond)
+        Rudolf Marek <r.marek@sh.cvut.cz>
+
+Description
+-----------
+
+This driver implements support for the Winbond W83627EHF and W83627EHG
+super I/O chips. We will refer to them collectively as Winbond chips.
+
+The chips implement three temperature sensors, five fan rotation
+speed sensors, ten analog voltage sensors, alarms with beep warnings (control
+unimplemented), and some automatic fan regulation strategies (plus manual
+fan control mode).
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
+the temperature gets higher than high limit; it stays on until the temperature
+falls below the Hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
+128) to give the readings more range or accuracy. The driver sets the most
+suitable fan divisor itself. Some fans might not be present because they
+share pins with other functions.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+The driver supports automatic fan control mode known as Thermal Cruise.
+In this mode, the chip attempts to keep the measured temperature in a
+predefined temperature range. If the temperature goes out of range, fan
+is driven slower/faster to reach the predefined range again.
+
+The mode works for fan1-fan4. Mapping of temperatures to pwm outputs is as
+follows:
+
+temp1 -> pwm1
+temp2 -> pwm2
+temp3 -> pwm3
+prog  -> pwm4 (the programmable setting is not supported by the driver)
+
+/sys files
+----------
+
+pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
+          0 (stop) to 255 (full)
+
+pwm[1-4]_enable - this file controls mode of fan/temperature control:
+       * 1 Manual Mode, write to pwm file any value 0-255 (full speed)
+       * 2 Thermal Cruise
+
+Thermal Cruise mode
+-------------------
+
+If the temperature is in the range defined by:
+
+pwm[1-4]_target    - set target temperature, unit millidegree Celcius
+                    (range 0 - 127000)
+pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (range 0 - 15000)
+
+there are no changes to fan speed. Once the temperature leaves the interval,
+fan speed increases (temp is higher) or decreases if lower than desired.
+There are defined steps and times, but not exported by the driver yet.
+
+pwm[1-4]_min_output - minimum fan speed (range 1 - 255), when the temperature
+                      is below defined range.
+pwm[1-4]_stop_time  - how many milliseconds [ms] must elapse to switch
+                      corresponding fan off. (when the temperature was below
+                      defined range).
+
+Note: last two functions are influenced by other control bits, not yet exported
+      by the driver, so a change might not have any effect.
index 83a3836289c2e0db91f9148258d70effd860eb4c..19b2ed739fa1325e09ab91cb629ce69b3331a2af 100644 (file)
@@ -5,7 +5,7 @@ Supported chips:
   * Winbond W83791D
     Prefix: 'w83791d'
     Addresses scanned: I2C 0x2c - 0x2f
-    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791D_W83791Gb.pdf
 
 Author: Charles Spirakis <bezaur@gmail.com>
 
@@ -20,6 +20,9 @@ Credits:
     Chunhao Huang <DZShen@Winbond.com.tw>,
     Rudolf Marek <r.marek@sh.cvut.cz>
 
+Additional contributors:
+    Sven Anders <anders@anduras.de>
+
 Module Parameters
 -----------------
 
@@ -46,7 +49,8 @@ Module Parameters
 Description
 -----------
 
-This driver implements support for the Winbond W83791D chip.
+This driver implements support for the Winbond W83791D chip. The W83791G
+chip appears to be the same as the W83791D but is lead free.
 
 Detection of the chip can sometimes be foiled because it can be in an
 internal state that allows no clean access (Bank with ID register is not
@@ -71,34 +75,36 @@ Voltage sensors (also known as IN sensors) report their values in millivolts.
 An alarm is triggered if the voltage has crossed a programmable minimum
 or maximum limit.
 
-Alarms are provided as output from a "realtime status register". The
-following bits are defined:
-
-bit - alarm on:
-0  - Vcore
-1  - VINR0
-2  - +3.3VIN
-3  - 5VDD
-4  - temp1
-5  - temp2
-6  - fan1
-7  - fan2
-8  - +12VIN
-9  - -12VIN
-10 - -5VIN
-11 - fan3
-12 - chassis
-13 - temp3
-14 - VINR1
-15 - reserved
-16 - tart1
-17 - tart2
-18 - tart3
-19 - VSB
-20 - VBAT
-21 - fan4
-22 - fan5
-23 - reserved
+The bit ordering for the alarm "realtime status register" and the
+"beep enable registers" are different.
+
+in0 (VCORE)  :  alarms: 0x000001 beep_enable: 0x000001
+in1 (VINR0)  :  alarms: 0x000002 beep_enable: 0x002000 <== mismatch
+in2 (+3.3VIN):  alarms: 0x000004 beep_enable: 0x000004
+in3 (5VDD)   :  alarms: 0x000008 beep_enable: 0x000008
+in4 (+12VIN) :  alarms: 0x000100 beep_enable: 0x000100
+in5 (-12VIN) :  alarms: 0x000200 beep_enable: 0x000200
+in6 (-5VIN)  :  alarms: 0x000400 beep_enable: 0x000400
+in7 (VSB)    :  alarms: 0x080000 beep_enable: 0x010000 <== mismatch
+in8 (VBAT)   :  alarms: 0x100000 beep_enable: 0x020000 <== mismatch
+in9 (VINR1)  :  alarms: 0x004000 beep_enable: 0x004000
+temp1        :  alarms: 0x000010 beep_enable: 0x000010
+temp2        :  alarms: 0x000020 beep_enable: 0x000020
+temp3        :  alarms: 0x002000 beep_enable: 0x000002 <== mismatch
+fan1         :  alarms: 0x000040 beep_enable: 0x000040
+fan2         :  alarms: 0x000080 beep_enable: 0x000080
+fan3         :  alarms: 0x000800 beep_enable: 0x000800
+fan4         :  alarms: 0x200000 beep_enable: 0x200000
+fan5         :  alarms: 0x400000 beep_enable: 0x400000
+tart1        :  alarms: 0x010000 beep_enable: 0x040000 <== mismatch
+tart2        :  alarms: 0x020000 beep_enable: 0x080000 <== mismatch
+tart3        :  alarms: 0x040000 beep_enable: 0x100000 <== mismatch
+case_open    :  alarms: 0x001000 beep_enable: 0x001000
+user_enable  :  alarms: -------- beep_enable: 0x800000
+
+*** NOTE: It is the responsibility of user-space code to handle the fact
+that the beep enable and alarm bits are in different positions when using that
+feature of the chip.
 
 When an alarm goes off, you can be warned by a beeping signal through your
 computer speaker. It is possible to enable all beeping globally, or only
@@ -109,5 +115,6 @@ often will do no harm, but will return 'old' values.
 
 W83791D TODO:
 ---------------
-Provide a patch for per-file alarms as discussed on the mailing list
+Provide a patch for per-file alarms and beep enables as defined in the hwmon
+       documentation (Documentation/hwmon/sysfs-interface)
 Provide a patch for smart-fan control (still need appropriate motherboard/fans)
index 16775663b9f5a5f9831fa2e251299352cced3ec7..25680346e0acd2059bf23608f5982b8bb2163eaf 100644 (file)
@@ -7,9 +7,12 @@ Supported adapters:
   * VIA Technologies, Inc. VT82C686A/B
     Datasheet: Sometimes available at the VIA website
 
-  * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237R
+  * VIA Technologies, Inc. VT8231, VT8233, VT8233A
     Datasheet: available on request from VIA
 
+  * VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251
+    Datasheet: available on request and under NDA from VIA
+
 Authors:
        Kyösti Mälkki <kmalkki@cc.hut.fi>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -39,6 +42,8 @@ Your lspci -n listing must show one of these :
  device 1106:8235   (VT8231 function 4)
  device 1106:3177   (VT8235)
  device 1106:3227   (VT8237R)
+ device 1106:3337   (VT8237A)
+ device 1106:3287   (VT8251)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.
index d6dcb138abf510534d2539665f74176c013a37b4..9cc081e697648ecb3feaadddcc4b8da187294db9 100644 (file)
@@ -6,9 +6,12 @@ This module is a very simple fake I2C/SMBus driver.  It implements four
 types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, and
 (r/w) word data.
 
+You need to provide a chip address as a module parameter when loading
+this driver, which will then only react to SMBus commands to this address.
+
 No hardware is needed nor associated with this module.  It will accept write
-quick commands to all addresses; it will respond to the other commands (also
-to all addresses) by reading from or writing to an array in memory.  It will
+quick commands to one address; it will respond to the other commands (also
+to one address) by reading from or writing to an array in memory.  It will
 also spam the kernel logs for every command it handles.
 
 A pointer register with auto-increment is implemented for all byte
@@ -21,6 +24,11 @@ The typical use-case is like this:
        3. load the target sensors chip driver module
        4. observe its behavior in the kernel log
 
+PARAMETERS:
+
+int chip_addr:
+       The SMBus address to emulate a chip at.
+
 CAVEATS:
 
 There are independent arrays for byte/data and word/data commands.  Depending
@@ -33,6 +41,9 @@ If the hardware for your driver has banked registers (e.g. Winbond sensors
 chips) this module will not work well - although it could be extended to
 support that pretty easily.
 
+Only one chip address is supported - although this module could be
+extended to support more.
+
 If you spam it hard enough, printk can be lossy.  This module really wants
 something like relayfs.
 
index c918cc3f65fbbc3bff4470a0131d4c63bc40a5f7..137e993f4329aa9c6cc83a7835dcc9380312dbd6 100644 (file)
@@ -110,6 +110,13 @@ be entered as an environment variable, whereas its absence indicates that
 it will appear as a kernel argument readable via /proc/cmdline by programs
 running once the system is up.
 
+The number of kernel parameters is not limited, but the length of the
+complete command line (parameters including spaces etc.) is limited to
+a fixed number of characters. This limit depends on the architecture
+and is between 256 and 4096 characters. It is defined in the file
+./include/asm/setup.h as COMMAND_LINE_SIZE.
+
+
        53c7xx=         [HW,SCSI] Amiga SCSI controllers
                        See header of drivers/scsi/53c7xx.c.
                        See also Documentation/scsi/ncr53c7xx.txt.
@@ -573,8 +580,6 @@ running once the system is up.
        gscd=           [HW,CD]
                        Format: <io>
 
-       gt96100eth=     [NET] MIPS GT96100 Advanced Communication Controller
-
        gus=            [HW,OSS]
                        Format: <io>,<irq>,<dma>,<dma16>
 
@@ -1326,7 +1331,7 @@ running once the system is up.
        pt.             [PARIDE]
                        See Documentation/paride.txt.
 
-       quiet=          [KNL] Disable log messages
+       quiet           [KNL] Disable most log messages
 
        r128=           [HW,DRM]
 
@@ -1372,6 +1377,9 @@ running once the system is up.
                        Reserves a hole at the top of the kernel virtual
                        address space.
 
+       reset_devices   [KNL] Force drivers to reset the underlying device
+                       during initialization.
+
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
index 00d93605bfd3093f377ea2325719e9b0140577da..55a7e4fa8cc2b5d37635188475d15e6e9268073e 100644 (file)
@@ -36,6 +36,28 @@ The validator tracks lock-class usage history into 5 separate state bits:
 
 - 'ever used'                                       [ == !unused        ]
 
+When locking rules are violated, these 4 state bits are presented in the
+locking error messages, inside curlies.  A contrived example:
+
+   modprobe/2287 is trying to acquire lock:
+    (&sio_locks[i].lock){--..}, at: [<c02867fd>] mutex_lock+0x21/0x24
+
+   but task is already holding lock:
+    (&sio_locks[i].lock){--..}, at: [<c02867fd>] mutex_lock+0x21/0x24
+
+
+The bit position indicates hardirq, softirq, hardirq-read,
+softirq-read respectively, and the character displayed in each
+indicates:
+
+   '.'  acquired while irqs enabled
+   '+'  acquired in irq context
+   '-'  acquired in process context with irqs disabled
+   '?'  read-acquired both with irqs enabled and in irq context
+
+Unused mutexes cannot be part of the cause of an error.
+
+
 Single-lock state rules:
 ------------------------
 
index afac780445cd19a9042a629fa32245d11806e610..dc942eaf490fb8474a136f10a132d375d7759635 100644 (file)
@@ -192,6 +192,17 @@ or, for backwards compatibility, the option value.  E.g.,
 arp_interval
 
        Specifies the ARP link monitoring frequency in milliseconds.
+
+       The ARP monitor works by periodically checking the slave
+       devices to determine whether they have sent or received
+       traffic recently (the precise criteria depends upon the
+       bonding mode, and the state of the slave).  Regular traffic is
+       generated via ARP probes issued for the addresses specified by
+       the arp_ip_target option.
+
+       This behavior can be modified by the arp_validate option,
+       below.
+
        If ARP monitoring is used in an etherchannel compatible mode
        (modes 0 and 2), the switch should be configured in a mode
        that evenly distributes packets across all links. If the
@@ -213,6 +224,54 @@ arp_ip_target
        maximum number of targets that can be specified is 16.  The
        default value is no IP addresses.
 
+arp_validate
+
+       Specifies whether or not ARP probes and replies should be
+       validated in the active-backup mode.  This causes the ARP
+       monitor to examine the incoming ARP requests and replies, and
+       only consider a slave to be up if it is receiving the
+       appropriate ARP traffic.
+
+       Possible values are:
+
+       none or 0
+
+               No validation is performed.  This is the default.
+
+       active or 1
+
+               Validation is performed only for the active slave.
+
+       backup or 2
+
+               Validation is performed only for backup slaves.
+
+       all or 3
+
+               Validation is performed for all slaves.
+
+       For the active slave, the validation checks ARP replies to
+       confirm that they were generated by an arp_ip_target.  Since
+       backup slaves do not typically receive these replies, the
+       validation performed for backup slaves is on the ARP request
+       sent out via the active slave.  It is possible that some
+       switch or network configurations may result in situations
+       wherein the backup slaves do not receive the ARP requests; in
+       such a situation, validation of backup slaves must be
+       disabled.
+
+       This option is useful in network configurations in which
+       multiple bonding hosts are concurrently issuing ARPs to one or
+       more targets beyond a common switch.  Should the link between
+       the switch and target fail (but not the switch itself), the
+       probe traffic generated by the multiple bonding instances will
+       fool the standard ARP monitor into considering the links as
+       still up.  Use of the arp_validate option can resolve this, as
+       the ARP monitor will only consider ARP requests and replies
+       associated with its own instance of bonding.
+
+       This option was added in bonding version 3.1.0.
+
 downdelay
 
        Specifies the time, in milliseconds, to wait before disabling
index 44f2f769e8659dd2565c82a9ece8771150091a5f..18d385c068fc85b8a87deaef82caadd27e4204e6 100644 (file)
@@ -100,6 +100,7 @@ Examples:
                          are: IPSRC_RND #IP Source is random (between min/max),
                               IPDST_RND, UDPSRC_RND,
                               UDPDST_RND, MACSRC_RND, MACDST_RND 
+                              MPLS_RND, VID_RND, SVID_RND
 
  pgset "udp_src_min 9"   set UDP source port min, If < udp_src_max, then
                          cycle through the port range.
@@ -125,6 +126,21 @@ Examples:
 
  pgset "mpls 0"                  turn off mpls (or any invalid argument works too!)
 
+ pgset "vlan_id 77"       set VLAN ID 0-4095
+ pgset "vlan_p 3"         set priority bit 0-7 (default 0)
+ pgset "vlan_cfi 0"       set canonical format identifier 0-1 (default 0)
+
+ pgset "svlan_id 22"      set SVLAN ID 0-4095
+ pgset "svlan_p 3"        set priority bit 0-7 (default 0)
+ pgset "svlan_cfi 0"      set canonical format identifier 0-1 (default 0)
+
+ pgset "vlan_id 9999"     > 4095 remove vlan and svlan tags
+ pgset "svlan 9999"       > 4095 remove svlan tag
+
+
+ pgset "tos XX"           set former IPv4 TOS field (e.g. "tos 28" for AF11 no ECN, default 00)
+ pgset "traffic_class XX" set former IPv6 TRAFFIC CLASS (e.g. "traffic_class B8" for EF no ECN, default 00)
+
  pgset stop                      aborts injection. Also, ^C aborts generator.
 
 
index b88ebe4d808c36a9bc6526354562a121bd245ea2..7714f57caad5b4312e7289761c0561c68b822049 100644 (file)
@@ -116,6 +116,9 @@ FURTHER NOTES ON NO-MMU MMAP
  (*) A list of all the mappings on the system is visible through /proc/maps in
      no-MMU mode.
 
+ (*) A list of all the mappings in use by a process is visible through
+     /proc/<pid>/maps in no-MMU mode.
+
  (*) Supplying MAP_FIXED or a requesting a particular mapping address will
      result in an error.
 
@@ -125,6 +128,49 @@ FURTHER NOTES ON NO-MMU MMAP
      error will result if they don't. This is most likely to be encountered
      with character device files, pipes, fifos and sockets.
 
+
+==========================
+INTERPROCESS SHARED MEMORY
+==========================
+
+Both SYSV IPC SHM shared memory and POSIX shared memory is supported in NOMMU
+mode.  The former through the usual mechanism, the latter through files created
+on ramfs or tmpfs mounts.
+
+
+=======
+FUTEXES
+=======
+
+Futexes are supported in NOMMU mode if the arch supports them.  An error will
+be given if an address passed to the futex system call lies outside the
+mappings made by a process or if the mapping in which the address lies does not
+support futexes (such as an I/O chardev mapping).
+
+
+=============
+NO-MMU MREMAP
+=============
+
+The mremap() function is partially supported.  It may change the size of a
+mapping, and may move it[*] if MREMAP_MAYMOVE is specified and if the new size
+of the mapping exceeds the size of the slab object currently occupied by the
+memory to which the mapping refers, or if a smaller slab object could be used.
+
+MREMAP_FIXED is not supported, though it is ignored if there's no change of
+address and the object does not need to be moved.
+
+Shared mappings may not be moved.  Shareable mappings may not be moved either,
+even if they are not currently shared.
+
+The mremap() function must be given an exact match for base address and size of
+a previously mapped object.  It may not be used to create holes in existing
+mappings, move parts of existing mappings or resize parts of mappings.  It must
+act on a complete mapping.
+
+[*] Not currently supported.
+
+
 ============================================
 PROVIDING SHAREABLE CHARACTER DEVICE SUPPORT
 ============================================
diff --git a/Documentation/pcieaer-howto.txt b/Documentation/pcieaer-howto.txt
new file mode 100644 (file)
index 0000000..16c2512
--- /dev/null
@@ -0,0 +1,253 @@
+   The PCI Express Advanced Error Reporting Driver Guide HOWTO
+               T. Long Nguyen  <tom.l.nguyen@intel.com>
+               Yanmin Zhang    <yanmin.zhang@intel.com>
+                               07/29/2006
+
+
+1. Overview
+
+1.1 About this guide
+
+This guide describes the basics of the PCI Express Advanced Error
+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.3 What is the PCI Express AER Driver?
+
+PCI Express error signaling can occur on the PCI Express link itself
+or on behalf of transactions initiated on the link. PCI Express
+defines two error reporting paradigms: the baseline capability and
+the Advanced Error Reporting capability. The baseline capability is
+required of all PCI Express components providing a minimum defined
+set of error reporting requirements. Advanced Error Reporting
+capability is implemented with a PCI Express advanced error reporting
+extended capability structure providing more robust error reporting.
+
+The PCI Express AER driver provides the infrastructure to support PCI
+Express Advanced Error Reporting capability. The PCI Express AER
+driver provides three basic functions:
+
+-      Gathers the comprehensive error information if errors occurred.
+-      Reports error to the users.
+-      Performs error recovery actions.
+
+AER driver only attaches root ports which support PCI-Express AER
+capability.
+
+
+2. User Guide
+
+2.1 Include the PCI Express AER Root Driver into the Linux Kernel
+
+The PCI Express AER Root driver is a Root Port service driver attached
+to the PCI Express Port Bus driver. If a user wants to use it, the driver
+has to be compiled. Option CONFIG_PCIEAER supports this capability. It
+depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
+CONFIG_PCIEAER = y.
+
+2.2 Load PCI Express AER Root Driver
+There is a case where a system has AER support in BIOS. Enabling the AER
+Root driver and having AER support in BIOS may result unpredictable
+behavior. To avoid this conflict, a successful load of the AER Root driver
+requires ACPI _OSC support in the BIOS to allow the AER Root driver to
+request for native control of AER. See the PCI FW 3.0 Specification for
+details regarding OSC usage. Currently, lots of firmwares don't provide
+_OSC support while they use PCI Express. To support such firmwares,
+forceload, a parameter of type bool, could enable AER to continue to
+be initiated although firmwares have no _OSC support. To enable the
+walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
+when booting kernel. Note that forceload=n by default.
+
+2.3 AER error output
+When a PCI-E AER error is captured, an error message will be outputed to
+console. If it's a correctable error, it is outputed as a warning.
+Otherwise, it is printed as an error. So users could choose different
+log level to filter out correctable error messages.
+
+Below shows an example.
++------ PCI-Express Device Error -----+
+Error Severity          : Uncorrected (Fatal)
+PCIE Bus Error type     : Transaction Layer
+Unsupported Request     : First
+Requester ID            : 0500
+VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
+TLB Header:
+04000001 00200a03 05010000 00050100
+
+In the example, 'Requester ID' means the ID of the device who sends
+the error message to root port. Pls. refer to pci express specs for
+other fields.
+
+
+3. Developer Guide
+
+To enable AER aware support requires a software driver to configure
+the AER capability structure within its device and to provide callbacks.
+
+To support AER better, developers need understand how AER does work
+firstly.
+
+PCI Express errors are classified into two types: correctable errors
+and uncorrectable errors. This classification is based on the impacts
+of those errors, which may result in degraded performance or function
+failure.
+
+Correctable errors pose no impacts on the functionality of the
+interface. The PCI Express protocol can recover without any software
+intervention or any loss of data. These errors are detected and
+corrected by hardware. Unlike correctable errors, uncorrectable
+errors impact functionality of the interface. Uncorrectable errors
+can cause a particular transaction or a particular PCI Express link
+to be unreliable. Depending on those error conditions, uncorrectable
+errors are further classified into non-fatal errors and fatal errors.
+Non-fatal errors cause the particular transaction to be unreliable,
+but the PCI Express link itself is fully functional. Fatal errors, on
+the other hand, cause the link to be unreliable.
+
+When AER is enabled, a PCI Express device will automatically send an
+error message to the PCIE root port above it when the device captures
+an error. The Root Port, upon receiving an error reporting message,
+internally processes and logs the error message in its PCI Express
+capability structure. Error information being logged includes storing
+the error reporting agent's requestor ID into the Error Source
+Identification Registers and setting the error bits of the Root Error
+Status Register accordingly. If AER error reporting is enabled in Root
+Error Command Register, the Root Port generates an interrupt if an
+error is detected.
+
+Note that the errors as described above are related to the PCI Express
+hierarchy and links. These errors do not include any device specific
+errors because device specific errors will still get sent directly to
+the device driver.
+
+3.1 Configure the AER capability structure
+
+AER aware drivers of PCI Express component need change the device
+control registers to enable AER. They also could change AER registers,
+including mask and severity registers. Helper function
+pci_enable_pcie_error_reporting could be used to enable AER. See
+section 3.3.
+
+3.2. Provide callbacks
+
+3.2.1 callback reset_link to reset pci express link
+
+This callback is used to reset the pci express physical link when a
+fatal error happens. The root port aer service driver provides a
+default reset_link function, but different upstream ports might
+have different specifications to reset pci express link, so all
+upstream ports should provide their own reset_link functions.
+
+In struct pcie_port_service_driver, a new pointer, reset_link, is
+added.
+
+pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+
+Section 3.2.2.2 provides more detailed info on when to call
+reset_link.
+
+3.2.2 PCI error-recovery callbacks
+
+The PCI Express AER Root driver uses error callbacks to coordinate
+with downstream device drivers associated with a hierarchy in question
+when performing error recovery actions.
+
+Data struct pci_driver has a pointer, err_handler, to point to
+pci_error_handlers who consists of a couple of callback function
+pointers. AER driver follows the rules defined in
+pci-error-recovery.txt except pci express specific parts (e.g.
+reset_link). Pls. refer to pci-error-recovery.txt for detailed
+definitions of the callbacks.
+
+Below sections specify when to call the error callback functions.
+
+3.2.2.1 Correctable errors
+
+Correctable errors pose no impacts on the functionality of
+the interface. The PCI Express protocol can recover without any
+software intervention or any loss of data. These errors do not
+require any recovery actions. The AER driver clears the device's
+correctable error status register accordingly and logs these errors.
+
+3.2.2.2 Non-correctable (non-fatal and fatal) errors
+
+If an error message indicates a non-fatal error, performing link reset
+at upstream is not required. The AER driver calls error_detected(dev,
+pci_channel_io_normal) to all drivers associated within a hierarchy in
+question. for example,
+EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
+If Upstream port A captures an AER error, the hierarchy consists of
+Downstream port B and EndPoint.
+
+A driver may return PCI_ERS_RESULT_CAN_RECOVER,
+PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
+whether it can recover or the AER driver calls mmio_enabled as next.
+
+If an error message indicates a fatal error, kernel will broadcast
+error_detected(dev, pci_channel_io_frozen) to all drivers within
+a hierarchy in question. Then, performing link reset at upstream is
+necessary. As different kinds of devices might use different approaches
+to reset link, AER port service driver is required to provide the
+function to reset link. Firstly, kernel looks for if the upstream
+component has an aer driver. If it has, kernel uses the reset_link
+callback of the aer driver. If the upstream component has no aer driver
+and the port is downstream port, we will use the aer driver of the
+root port who reports the AER error. As for upstream ports,
+they should provide their own aer service drivers with reset_link
+function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
+reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
+to mmio_enabled.
+
+3.3 helper functions
+
+3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
+pci_find_aer_capability locates the PCI Express AER capability
+in the device configuration space. If the device doesn't support
+PCI-Express AER, the function returns 0.
+
+3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+pci_enable_pcie_error_reporting enables the device to send error
+messages to root port when an error is detected. Note that devices
+don't enable the error reporting by default, so device drivers need
+call this function to enable it.
+
+3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+pci_disable_pcie_error_reporting disables the device to send error
+messages to root port when an error is detected.
+
+3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
+error status register.
+
+3.4 Frequent Asked Questions
+
+Q: What happens if a PCI Express device driver does not provide an
+error recovery handler (pci_driver->err_handler is equal to NULL)?
+
+A: The devices attached with the driver won't be recovered. If the
+error is fatal, kernel will print out warning messages. Please refer
+to section 3 for more information.
+
+Q: What happens if an upstream port service driver does not provide
+callback reset_link?
+
+A: Fatal error recovery will fail if the errors are reported by the
+upstream ports who are attached by the service driver.
+
+Q: How does this infrastructure deal with driver that is not PCI
+Express aware?
+
+A: This infrastructure calls the error callback functions of the
+driver when an error happens. But if the driver is not aware of
+PCI Express, the device might not report its own errors to root
+port.
+
+Q: What modifications will that driver need to make it compatible
+with the PCI Express AER Root driver?
+
+A: It could call the helper functions to enable AER in devices and
+cleanup uncorrectable status register. Pls. refer to section 3.3.
+
index c472ffacc2f6f6cfa517e70df96211919b2767e8..4b736d24da7a95ef0b292c542bedccf9122448f1 100644 (file)
@@ -333,11 +333,11 @@ cmpxchg is basically the following function performed atomically:
 
 unsigned long _cmpxchg(unsigned long *A, unsigned long *B, unsigned long *C)
 {
-        unsigned long T = *A;
-        if (*A == *B) {
-                *A = *C;
-        }
-        return T;
+       unsigned long T = *A;
+       if (*A == *B) {
+               *A = *C;
+       }
+       return T;
 }
 #define cmpxchg(a,b,c) _cmpxchg(&a,&b,&c)
 
@@ -582,7 +582,7 @@ contention).
 try_to_take_rt_mutex is used every time the task tries to grab a mutex in the
 slow path.  The first thing that is done here is an atomic setting of
 the "Has Waiters" flag of the mutex's owner field.  Yes, this could really
-be false, because if the the mutex has no owner, there are no waiters and
+be false, because if the mutex has no owner, there are no waiters and
 the current task also won't have any waiters.  But we don't have the lock
 yet, so we assume we are going to be a waiter.  The reason for this is to
 play nice for those architectures that do have CMPXCHG.  By setting this flag
@@ -735,7 +735,7 @@ do have CMPXCHG, that check is done in the fast path, but it is still needed
 in the slow path too.  If a waiter of a mutex woke up because of a signal
 or timeout between the time the owner failed the fast path CMPXCHG check and
 the grabbing of the wait_lock, the mutex may not have any waiters, thus the
-owner still needs to make this check. If there are no waiters than the mutex
+owner still needs to make this check. If there are no waiters then the mutex
 owner field is set to NULL, the wait_lock is released and nothing more is
 needed.
 
diff --git a/Documentation/seclvl.txt b/Documentation/seclvl.txt
deleted file mode 100644 (file)
index 97274d1..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-BSD Secure Levels Linux Security Module
-Michael A. Halcrow <mike@halcrow.us>
-
-
-Introduction
-
-Under the BSD Secure Levels security model, sets of policies are
-associated with levels. Levels range from -1 to 2, with -1 being the
-weakest and 2 being the strongest. These security policies are
-enforced at the kernel level, so not even the superuser is able to
-disable or circumvent them. This hardens the machine against attackers
-who gain root access to the system.
-
-
-Levels and Policies
-
-Level -1 (Permanently Insecure):
- - Cannot increase the secure level
-
-Level 0 (Insecure):
- - Cannot ptrace the init process
-
-Level 1 (Default):
- - /dev/mem and /dev/kmem are read-only
- - IMMUTABLE and APPEND extended attributes, if set, may not be unset
- - Cannot load or unload kernel modules
- - Cannot write directly to a mounted block device
- - Cannot perform raw I/O operations
- - Cannot perform network administrative tasks
- - Cannot setuid any file
-
-Level 2 (Secure):
- - Cannot decrement the system time
- - Cannot write to any block device, whether mounted or not
- - Cannot unmount any mounted filesystems
-
-
-Compilation
-
-To compile the BSD Secure Levels LSM, seclvl.ko, enable the
-SECURITY_SECLVL configuration option.  This is found under Security
-options -> BSD Secure Levels in the kernel configuration menu.
-
-
-Basic Usage
-
-Once the machine is in a running state, with all the necessary modules
-loaded and all the filesystems mounted, you can load the seclvl.ko
-module:
-
-# insmod seclvl.ko
-
-The module defaults to secure level 1, except when compiled directly
-into the kernel, in which case it defaults to secure level 0. To raise
-the secure level to 2, the administrator writes ``2'' to the
-seclvl/seclvl file under the sysfs mount point (assumed to be /sys in
-these examples):
-
-# echo -n "2" > /sys/seclvl/seclvl
-
-Alternatively, you can initialize the module at secure level 2 with
-the initlvl module parameter:
-
-# insmod seclvl.ko initlvl=2
-
-At this point, it is impossible to remove the module or reduce the
-secure level.  If the administrator wishes to have the option of doing
-so, he must provide a module parameter, sha1_passwd, that specifies
-the SHA1 hash of the password that can be used to reduce the secure
-level to 0.
-
-To generate this SHA1 hash, the administrator can use OpenSSL:
-
-# echo -n "boogabooga" | openssl sha1
-abeda4e0f33defa51741217592bf595efb8d289c
-
-In order to use password-instigated secure level reduction, the SHA1
-crypto module must be loaded or compiled into the kernel:
-
-# insmod sha1.ko
-
-The administrator can then insmod the seclvl module, including the
-SHA1 hash of the password:
-
-# insmod seclvl.ko
-         sha1_passwd=abeda4e0f33defa51741217592bf595efb8d289c
-
-To reduce the secure level, write the password to seclvl/passwd under
-your sysfs mount point:
-
-# echo -n "boogabooga" > /sys/seclvl/passwd
-
-The September 2004 edition of Sys Admin Magazine has an article about
-the BSD Secure Levels LSM.  I encourage you to refer to that article
-for a more in-depth treatment of this security module:
-
-http://www.samag.com/documents/s=9304/sam0409a/0409a.htm
index eb2dd2e6993bebeffa684ba51ebd2e4957fa6b8a..73988e0d112b490ad187144e88a7904b2ab49000 100644 (file)
@@ -41,11 +41,6 @@ Board-specific code:
         |
        .. more boards here ...
 
-It should also be noted that each board is required to have some certain
-headers. At the time of this writing, io.h is the only thing that needs
-to be provided for each board, and can generally just reference generic
-functions (with the exception of isa_port2addr).
-
 Next, for companion chips:
 .
 `-- arch
@@ -104,12 +99,13 @@ and then populate that with sub-directories for each member of the family.
 Both the Solution Engine and the hp6xx boards are an example of this.
 
 After you have setup your new arch/sh/boards/ directory, remember that you
-also must add a directory in include/asm-sh for headers localized to this
-board. In order to interoperate seamlessly with the build system, it's best
-to have this directory the same as the arch/sh/boards/ directory name,
-though if your board is again part of a family, the build system has ways
-of dealing with this, and you can feel free to name the directory after
-the family member itself.
+should also add a directory in include/asm-sh for headers localized to this
+board (if there are going to be more than one). In order to interoperate
+seamlessly with the build system, it's best to have this directory the same
+as the arch/sh/boards/ directory name, though if your board is again part of
+a family, the build system has ways of dealing with this (via incdir-y
+overloading), and you can feel free to name the directory after the family
+member itself.
 
 There are a few things that each board is required to have, both in the
 arch/sh/boards and the include/asm-sh/ heirarchy. In order to better
@@ -122,6 +118,7 @@ might look something like:
  * arch/sh/boards/vapor/setup.c - Setup code for imaginary board
  */
 #include <linux/init.h>
+#include <asm/rtc.h> /* for board_time_init() */
 
 const char *get_system_type(void)
 {
@@ -152,79 +149,57 @@ int __init platform_setup(void)
 }
 
 Our new imaginary board will also have to tie into the machvec in order for it
-to be of any use. Currently the machvec is slowly on its way out, but is still
-required for the time being. As such, let us take a look at what needs to be
-done for the machvec assignment.
+to be of any use.
 
 machvec functions fall into a number of categories:
 
  - I/O functions to IO memory (inb etc) and PCI/main memory (readb etc).
- - I/O remapping functions (ioremap etc)
- - some initialisation functions
- - a 'heartbeat' function
- - some miscellaneous flags
-
-The tree can be built in two ways:
- - as a fully generic build. All drivers are linked in, and all functions
-   go through the machvec
- - as a machine specific build. In this case only the required drivers
-   will be linked in, and some macros may be redefined to not go through
-   the machvec where performance is important (in particular IO functions).
-
-There are three ways in which IO can be performed:
- - none at all. This is really only useful for the 'unknown' machine type,
-   which us designed to run on a machine about which we know nothing, and
-   so all all IO instructions do nothing.
- - fully custom. In this case all IO functions go to a machine specific
-   set of functions which can do what they like
- - a generic set of functions. These will cope with most situations,
-   and rely on a single function, mv_port2addr, which is called through the
-   machine vector, and converts an IO address into a memory address, which
-   can be read from/written to directly.
-
-Thus adding a new machine involves the following steps (I will assume I am
-adding a machine called vapor):
-
- - add a new file include/asm-sh/vapor/io.h which contains prototypes for
+ - I/O mapping functions (ioport_map, ioport_unmap, etc).
+ - a 'heartbeat' function.
+ - PCI and IRQ initialization routines.
+ - Consistent allocators (for boards that need special allocators,
+   particularly for allocating out of some board-specific SRAM for DMA
+   handles).
+
+There are machvec functions added and removed over time, so always be sure to
+consult include/asm-sh/machvec.h for the current state of the machvec.
+
+The kernel will automatically wrap in generic routines for undefined function
+pointers in the machvec at boot time, as machvec functions are referenced
+unconditionally throughout most of the tree. Some boards have incredibly
+sparse machvecs (such as the dreamcast and sh03), whereas others must define
+virtually everything (rts7751r2d).
+
+Adding a new machine is relatively trivial (using vapor as an example):
+
+If the board-specific definitions are quite minimalistic, as is the case for
+the vast majority of boards, simply having a single board-specific header is
+sufficient.
+
+ - add a new file include/asm-sh/vapor.h which contains prototypes for
    any machine specific IO functions prefixed with the machine name, for
    example vapor_inb. These will be needed when filling out the machine
    vector.
 
-   This is the minimum that is required, however there are ample
-   opportunities to optimise this. In particular, by making the prototypes
-   inline function definitions, it is possible to inline the function when
-   building machine specific versions. Note that the machine vector
-   functions will still be needed, so that a module built for a generic
-   setup can be loaded.
-
- - add a new file arch/sh/boards/vapor/mach.c. This contains the definition
-   of the machine vector. When building the machine specific version, this
-   will be the real machine vector (via an alias), while in the generic
-   version is used to initialise the machine vector, and then freed, by
-   making it initdata. This should be defined as:
-
-     struct sh_machine_vector mv_vapor __initmv = {
-       .mv_name = "vapor",
-     }
-     ALIAS_MV(vapor)
-
- - finally add a file arch/sh/boards/vapor/io.c, which contains
-   definitions of the machine specific io functions.
-
-A note about initialisation functions. Three initialisation functions are
-provided in the machine vector:
- - mv_arch_init - called very early on from setup_arch
- - mv_init_irq - called from init_IRQ, after the generic SH interrupt
-   initialisation
- - mv_init_pci - currently not used
-
-Any other remaining functions which need to be called at start up can be
-added to the list using the __initcalls macro (or module_init if the code
-can be built as a module). Many generic drivers probe to see if the device
-they are targeting is present, however this may not always be appropriate,
-so a flag can be added to the machine vector which will be set on those
-machines which have the hardware in question, reducing the probe to a
-single conditional.
+   Note that these prototypes are generated automatically by setting
+   __IO_PREFIX to something sensible. A typical example would be:
+
+       #define __IO_PREFIX vapor
+       #include <asm/io_generic.h>
+
+   somewhere in the board-specific header. Any boards being ported that still
+   have a legacy io.h should remove it entirely and switch to the new model.
+
+ - Add machine vector definitions to the board's setup.c. At a bare minimum,
+   this must be defined as something like:
+
+       struct sh_machine_vector mv_vapor __initmv = {
+               .mv_name = "vapor",
+       };
+       ALIAS_MV(vapor)
+
+ - finally add a file arch/sh/boards/vapor/io.c, which contains definitions of
+   the machine specific io functions (if there are enough to warrant it).
 
 3. Hooking into the Build System
 ================================
@@ -303,4 +278,3 @@ which will in turn copy the defconfig for this board, run it through
 oldconfig (prompting you for any new options since the time of creation),
 and start you on your way to having a functional kernel for your new
 board.
-
diff --git a/Documentation/sh/register-banks.txt b/Documentation/sh/register-banks.txt
new file mode 100644 (file)
index 0000000..a6719f2
--- /dev/null
@@ -0,0 +1,33 @@
+       Notes on register bank usage in the kernel
+       ==========================================
+
+Introduction
+------------
+
+The SH-3 and SH-4 CPU families traditionally include a single partial register
+bank (selected by SR.RB, only r0 ... r7 are banked), whereas other families
+may have more full-featured banking or simply no such capabilities at all.
+
+SR.RB banking
+-------------
+
+In the case of this type of banking, banked registers are mapped directly to
+r0 ... r7 if SR.RB is set to the bank we are interested in, otherwise ldc/stc
+can still be used to reference the banked registers (as r0_bank ... r7_bank)
+when in the context of another bank. The developer must keep the SR.RB value
+in mind when writing code that utilizes these banked registers, for obvious
+reasons. Userspace is also not able to poke at the bank1 values, so these can
+be used rather effectively as scratch registers by the kernel.
+
+Presently the kernel uses several of these registers.
+
+       - r0_bank, r1_bank (referenced as k0 and k1, used for scratch
+         registers when doing exception handling).
+       - r2_bank (used to track the EXPEVT/INTEVT code)
+               - Used by do_IRQ() and friends for doing irq mapping based off
+                 of the interrupt exception vector jump table offset
+       - r6_bank (global interrupt mask)
+               - The SR.IMASK interrupt handler makes use of this to set the
+                 interrupt priority level (used by local_irq_enable())
+       - r7_bank (current)
+
index 867f4c38f3564ae8fcfa8aa92df2b8eb41cfa31a..39c68f8c4e6c7cd8969fa1f0ae03a1afd1bcc424 100644 (file)
@@ -98,13 +98,13 @@ one or more packets could finish before an error stops further endpoint I/O.
                        error, a failure to respond (often caused by
                        device disconnect), or some other fault.
 
--ETIMEDOUT (**)                No response packet received within the prescribed
+-ETIME (**)            No response packet received within the prescribed
                        bus turn-around time.  This error may instead be
                        reported as -EPROTO or -EILSEQ.
 
-                       Note that the synchronous USB message functions
-                       also use this code to indicate timeout expired
-                       before the transfer completed.
+-ETIMEDOUT             Synchronous USB message functions use this code
+                       to indicate timeout expired before the transfer
+                       completed, and no other error was reported by HC.
 
 -EPIPE (**)            Endpoint stalled.  For non-control endpoints,
                        reset this status with usb_clear_halt().
@@ -163,6 +163,3 @@ usb_get_*/usb_set_*():
 usb_control_msg():
 usb_bulk_msg():
 -ETIMEDOUT             Timeout expired before the transfer completed.
-                       In the future this code may change to -ETIME,
-                       whose definition is a closer match to this sort
-                       of error.
index 02b0f7beb6d1623e542d7610e91971eeca2ce614..a2dee6e6190d73e9c1c266cf3544a5e252e8b5eb 100644 (file)
@@ -433,6 +433,11 @@ Options supported:
   See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
   information on this driver.
 
+AIRcable USB Dongle Bluetooth driver
+  If there is the cdc_acm driver loaded in the system, you will find that the
+  cdc_acm claims the device before AIRcable can. This is simply corrected
+  by unloading both modules and then loading the aircable module before
+  cdc_acm module
 
 Generic Serial driver
 
index 00d9a1f2a54c05dc01d1ab0b16b3b90f7aad6bf1..669a09aa5bb463934d96c25a76dc0346b8611fe8 100644 (file)
@@ -7,10 +7,10 @@
   6 -> AverTV Studio 303 (M126)                            [1461:000b]
   7 -> MSI TV-@nywhere Master                              [1462:8606]
   8 -> Leadtek Winfast DV2000                              [107d:6620]
-  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663C]
+  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663c,107d:6632]
  10 -> IODATA GV-VCP3/PCI                                  [10fc:d003]
  11 -> Prolink PlayTV PVR
- 12 -> ASUS PVR-416                                        [1043:4823]
+ 12 -> ASUS PVR-416                                        [1043:4823,1461:c111]
  13 -> MSI TV-@nywhere
  14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
@@ -51,3 +51,7 @@
  50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
  51 -> WinFast DTV2000 H                                   [107d:665e]
  52 -> Geniatech DVB-S                                     [14f1:0084]
+ 53 -> Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T  [0070:1404]
+ 54 -> Norwood Micro TV Tuner
+ 55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM  [c180:c980]
+ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
index 9068b669f5ee5d34af6dac4ff91a834df623b2f1..94cf695b1378ce8f79dd763448d3303909b76d19 100644 (file)
@@ -58,7 +58,7 @@
  57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
  58 -> ADS Tech Instant TV (saa7135)            [1421:0350,1421:0351,1421:0370,1421:1370]
  59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
- 60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus    [5168:0502,4e42:0502]
+ 60 -> LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus [5168:0502,4e42:0502,1489:0502]
  61 -> Philips TOUGH DVB-T reference design     [1131:2004]
  62 -> Compro VideoMate TV Gold+II
  63 -> Kworld Xpert TV PVR7134
@@ -83,7 +83,7 @@
  82 -> MSI TV@Anywhere plus                     [1462:6231]
  83 -> Terratec Cinergy 250 PCI TV              [153b:1160]
  84 -> LifeView FlyDVB Trio                     [5168:0319]
- 85 -> AverTV DVB-T 777                         [1461:2c05]
+ 85 -> AverTV DVB-T 777                         [1461:2c05,1461:2c05]
  86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
  87 -> ADS Instant TV Duo Cardbus PTV331        [0331:1421]
  88 -> Tevion/KWorld DVB-T 220RF                [17de:7201]
@@ -94,3 +94,6 @@
  93 -> Medion 7134 Bridge #2                    [16be:0005]
  94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
  95 -> LifeView FlyVIDEO3000 (NTSC)             [5169:0138]
+ 96 -> Medion Md8800 Quadro                     [16be:0007,16be:0008]
+ 97 -> LifeView FlyDVB-S /Acorp TV134DS         [5168:0300,4e42:0300]
+ 98 -> Proteus Pro 2309                         [0919:2003]
index fc94ff235ffac51f1f0079bbe673f47c3a460632..bb7c2cac7917e97bd206442747eb6b0e77356c42 100644 (file)
@@ -54,6 +54,12 @@ bttv.o
                                dropouts.
                chroma_agc=0/1  AGC of chroma signal, off by default.
                adc_crush=0/1   Luminance ADC crush, on by default.
+               i2c_udelay=     Allow reduce I2C speed. Default is 5 usecs
+                               (meaning 66,67 Kbps). The default is the
+                               maximum supported speed by kernel bitbang
+                               algoritm. You may use lower numbers, if I2C
+                               messages are lost (16 is known to work on
+                               all supported cards).
 
                bttv_gpio=0/1
                gpiomask=
diff --git a/Documentation/video4linux/cx2341x/README.hm12 b/Documentation/video4linux/cx2341x/README.hm12
new file mode 100644 (file)
index 0000000..0e213ed
--- /dev/null
@@ -0,0 +1,116 @@
+The cx23416 can produce (and the cx23415 can also read) raw YUV output. The
+format of a YUV frame is specific to this chip and is called HM12. 'HM' stands
+for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would
+be more accurate.
+
+The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per
+four pixels.
+
+The data is encoded as two macroblock planes, the first containing the Y
+values, the second containing UV macroblocks.
+
+The Y plane is divided into blocks of 16x16 pixels from left to right
+and from top to bottom. Each block is transmitted in turn, line-by-line.
+
+So the first 16 bytes are the first line of the top-left block, the
+second 16 bytes are the second line of the top-left block, etc. After
+transmitting this block the first line of the block on the right to the
+first block is transmitted, etc.
+
+The UV plane is divided into blocks of 16x8 UV values going from left
+to right, top to bottom. Each block is transmitted in turn, line-by-line.
+
+So the first 16 bytes are the first line of the top-left block and
+contain 8 UV value pairs (16 bytes in total). The second 16 bytes are the
+second line of 8 UV pairs of the top-left block, etc. After transmitting
+this block the first line of the block on the right to the first block is
+transmitted, etc.
+
+The code below is given as an example on how to convert HM12 to separate
+Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
+
+The width of a frame is always 720 pixels, regardless of the actual specified
+width.
+
+--------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static unsigned char frame[576*720*3/2];
+static unsigned char framey[576*720];
+static unsigned char frameu[576*720 / 4];
+static unsigned char framev[576*720 / 4];
+
+static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h)
+{
+    unsigned int y, x, i;
+
+    // descramble Y plane
+    // dstride = 720 = w
+    // The Y plane is divided into blocks of 16x16 pixels
+    // Each block in transmitted in turn, line-by-line.
+    for (y = 0; y < h; y += 16) {
+       for (x = 0; x < w; x += 16) {
+           for (i = 0; i < 16; i++) {
+               memcpy(dst + x + (y + i) * dstride, src, 16);
+               src += 16;
+           }
+       }
+    }
+}
+
+static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h)
+{
+    unsigned int y, x, i;
+
+    // descramble U/V plane
+    // dstride = 720 / 2 = w
+    // The U/V values are interlaced (UVUV...).
+    // Again, the UV plane is divided into blocks of 16x16 UV values.
+    // Each block in transmitted in turn, line-by-line.
+    for (y = 0; y < h; y += 16) {
+       for (x = 0; x < w; x += 8) {
+           for (i = 0; i < 16; i++) {
+               int idx = x + (y + i) * dstride;
+
+               dstu[idx+0] = src[0];  dstv[idx+0] = src[1];
+               dstu[idx+1] = src[2];  dstv[idx+1] = src[3];
+               dstu[idx+2] = src[4];  dstv[idx+2] = src[5];
+               dstu[idx+3] = src[6];  dstv[idx+3] = src[7];
+               dstu[idx+4] = src[8];  dstv[idx+4] = src[9];
+               dstu[idx+5] = src[10]; dstv[idx+5] = src[11];
+               dstu[idx+6] = src[12]; dstv[idx+6] = src[13];
+               dstu[idx+7] = src[14]; dstv[idx+7] = src[15];
+               src += 16;
+           }
+       }
+    }
+}
+
+/*************************************************************************/
+int main(int argc, char **argv)
+{
+    FILE *fin;
+    int i;
+
+    if (argc == 1) fin = stdin;
+    else fin = fopen(argv[1], "r");
+
+    if (fin == NULL) {
+       fprintf(stderr, "cannot open input\n");
+       exit(-1);
+    }
+    while (fread(frame, sizeof(frame), 1, fin) == 1) {
+       de_macro_y(framey, frame, 720, 720, 576);
+       de_macro_uv(frameu, framev, frame + 720 * 576, 720 / 2, 720 / 2, 576 / 2);
+       fwrite(framey, sizeof(framey), 1, stdout);
+       fwrite(framev, sizeof(framev), 1, stdout);
+       fwrite(frameu, sizeof(frameu), 1, stdout);
+    }
+    fclose(fin);
+    return 0;
+}
+
+--------------------------------------------------------------------------
diff --git a/Documentation/video4linux/cx2341x/README.vbi b/Documentation/video4linux/cx2341x/README.vbi
new file mode 100644 (file)
index 0000000..5807cf1
--- /dev/null
@@ -0,0 +1,45 @@
+
+Format of embedded V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data
+=========================================================
+
+This document describes the V4L2_MPEG_STREAM_VBI_FMT_IVTV format of the VBI data
+embedded in an MPEG-2 program stream. This format is in part dictated by some
+hardware limitations of the ivtv driver (the driver for the Conexant cx23415/6
+chips), in particular a maximum size for the VBI data. Anything longer is cut
+off when the MPEG stream is played back through the cx23415.
+
+The advantage of this format is it is very compact and that all VBI data for
+all lines can be stored while still fitting within the maximum allowed size.
+
+The stream ID of the VBI data is 0xBD. The maximum size of the embedded data is
+4 + 43 * 36, which is 4 bytes for a header and 2 * 18 VBI lines with a 1 byte
+header and a 42 bytes payload each. Anything beyond this limit is cut off by
+the cx23415/6 firmware. Besides the data for the VBI lines we also need 36 bits
+for a bitmask determining which lines are captured and 4 bytes for a magic cookie,
+signifying that this data package contains V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data.
+If all lines are used, then there is no longer room for the bitmask. To solve this
+two different magic numbers were introduced:
+
+'itv0': After this magic number two unsigned longs follow. Bits 0-17 of the first
+unsigned long denote which lines of the first field are captured. Bits 18-31 of
+the first unsigned long and bits 0-3 of the second unsigned long are used for the
+second field.
+
+'ITV0': This magic number assumes all VBI lines are captured, i.e. it implicitly
+implies that the bitmasks are 0xffffffff and 0xf.
+
+After these magic cookies (and the 8 byte bitmask in case of cookie 'itv0') the
+captured VBI lines start:
+
+For each line the least significant 4 bits of the first byte contain the data type.
+Possible values are shown in the table below. The payload is in the following 42
+bytes.
+
+Here is the list of possible data types:
+
+#define IVTV_SLICED_TYPE_TELETEXT       0x1     // Teletext (uses lines 6-22 for PAL)
+#define IVTV_SLICED_TYPE_CC             0x4     // Closed Captions (line 21 NTSC)
+#define IVTV_SLICED_TYPE_WSS            0x5     // Wide Screen Signal (line 23 PAL)
+#define IVTV_SLICED_TYPE_VPS            0x7     // Video Programming System (PAL) (line 16)
+
+Hans Verkuil <hverkuil@xs4all.nl>
index 4303e0c12476d1afb4af9c7998e46cb2ed4b7494..74b77f9e91bc5cc5692eee19fc0b4b6be3a49302 100644 (file)
@@ -199,6 +199,11 @@ IOMMU
    allowed  overwrite iommu off workarounds for specific chipsets.
    soft         Use software bounce buffering (default for Intel machines)
    noaperture Don't touch the aperture for AGP.
+   allowdac Allow DMA >4GB
+           When off all DMA over >4GB is forced through an IOMMU or bounce
+           buffering.
+   nodac    Forbid DMA >4GB
+   panic    Always panic when IOMMU overflows
 
   swiotlb=pages[,force]
 
index 767a43434ae80fa6940c36b6cf6799dddb85270c..f0cd5a3f6de69188f57e1aafb10406b58a2fe288 100644 (file)
@@ -501,7 +501,7 @@ S:  Maintained
 
 BLOCK LAYER
 P:     Jens Axboe
-M:     axboe@suse.de
+M:     axboe@kernel.dk
 L:     linux-kernel@vger.kernel.org
 T:     git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
 S:     Maintained
@@ -851,7 +851,7 @@ P:  Doug Warzecha
 M:     Douglas_Warzecha@dell.com
 S:     Maintained
 
-DEVICE-MAPPER
+DEVICE-MAPPER  (LVM)
 P:     Alasdair Kergon
 L:     dm-devel@redhat.com
 W:     http://sources.redhat.com/dm
@@ -1380,7 +1380,7 @@ S:        Maintained
 
 IDE/ATAPI CDROM DRIVER
 P:     Jens Axboe
-M:     axboe@suse.de
+M:     axboe@kernel.dk
 L:     linux-kernel@vger.kernel.org
 W:     http://www.kernel.dk
 S:     Maintained
@@ -1398,36 +1398,29 @@ M:      Gadi Oxman <gadio@netvision.net.il>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
-IEEE 1394 ETHERNET (eth1394)
-L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
-S:     Orphan
-
 IEEE 1394 SUBSYSTEM
 P:     Ben Collins
 M:     bcollins@debian.org
-P:     Jody McIntyre
-M:     scjody@modernduck.com
+P:     Stefan Richter
+M:     stefanr@s5r6.in-berlin.de
 L:     linux1394-devel@lists.sourceforge.net
 W:     http://www.linux1394.org/
-T:     git kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
+T:     git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
 S:     Maintained
 
-IEEE 1394 OHCI DRIVER
-P:     Ben Collins
-M:     bcollins@debian.org
-P:     Jody McIntyre
-M:     scjody@modernduck.com
+IEEE 1394 IPV4 DRIVER (eth1394)
+P:     Stefan Richter
+M:     stefanr@s5r6.in-berlin.de
 L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
-S:     Maintained
+S:     Odd Fixes
 
 IEEE 1394 PCILYNX DRIVER
 P:     Jody McIntyre
 M:     scjody@modernduck.com
+P:     Stefan Richter
+M:     stefanr@s5r6.in-berlin.de
 L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
-S:     Maintained
+S:     Odd Fixes
 
 IEEE 1394 RAW I/O DRIVER
 P:     Ben Collins
@@ -1435,16 +1428,6 @@ M:       bcollins@debian.org
 P:     Dan Dennedy
 M:     dan@dennedy.org
 L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
-S:     Maintained
-
-IEEE 1394 SBP2
-P:     Ben Collins
-M:     bcollins@debian.org
-P:     Stefan Richter
-M:     stefanr@s5r6.in-berlin.de
-L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
 S:     Maintained
 
 IMS TWINTURBO FRAMEBUFFER DRIVER
@@ -2062,7 +2045,7 @@ L:        linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
 
-NETWORK BLOCK DEVICE
+NETWORK BLOCK DEVICE (NBD)
 P:     Paul Clements
 M:     Paul.Clements@steeleye.com
 S:     Maintained
@@ -2548,7 +2531,7 @@ S:        Maintained
 
 SCSI CDROM DRIVER
 P:     Jens Axboe
-M:     axboe@suse.de
+M:     axboe@kernel.dk
 L:     linux-scsi@vger.kernel.org
 W:     http://www.kernel.dk
 S:     Maintained
@@ -2679,7 +2662,6 @@ M:        josejx@gentoo.org
 P:     Daniel Drake
 M:     dsd@gentoo.org
 W:     http://softmac.sipsolutions.net/
-L:     softmac-dev@sipsolutions.net
 L:     netdev@vger.kernel.org
 S:     Maintained
 
@@ -2811,6 +2793,12 @@ M:       R.E.Wolff@BitWizard.nl
 L:     linux-kernel@vger.kernel.org ?
 S:     Supported
 
+SPIDERNET NETWORK DRIVER for CELL
+P:     Jim Lewis
+M:     jim@jklewis.com
+L:     netdev@vger.kernel.org
+S:     Supported
+
 SRM (Alpha) environment access
 P:     Jan-Benedict Glaw
 M:     jbglaw@lug-owl.de
@@ -2835,12 +2823,9 @@ S:       Maintained
 SUPERH (sh)
 P:     Paul Mundt
 M:     lethal@linux-sh.org
-P:     Kazumoto Kojima
-M:     kkojima@rr.iij4u.or.jp
-L:     linuxsh-dev@lists.sourceforge.net
+L:     linuxsh-dev@lists.sourceforge.net (subscribers-only)
 W:     http://www.linux-sh.org
 W:     http://www.m17n.org/linux-sh/
-W:     http://www.rr.iij4u.or.jp/~kkojima/linux-sh4.html
 S:     Maintained
 
 SUPERH64 (sh64)
@@ -2991,7 +2976,7 @@ S:        Maintained
 
 UNIFORM CDROM DRIVER
 P:     Jens Axboe
-M:     axboe@suse.de
+M:     axboe@kernel.dk
 L:     linux-kernel@vger.kernel.org
 W:     http://www.kernel.dk
 S:     Maintained
@@ -3310,6 +3295,12 @@ W:       http://linuxtv.org
 T:     git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
 S:     Maintained
 
+VT1211 HARDWARE MONITOR DRIVER
+P:     Juerg Haefliger
+M:     juergh@gmail.com
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+
 VT8231 HARDWARE MONITOR DRIVER
 P:     Roger Lucas
 M:     roger@planbit.co.uk
index 80dac0245d6647459857617dcbb02b693ee832d1..4c6c5e32ef96e3d12da975e682ee8a3f6ebc37e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1385,9 +1385,13 @@ endif #ifeq ($(config-targets),1)
 endif #ifeq ($(mixed-targets),1)
 
 PHONY += checkstack kernelrelease kernelversion
+
+# Use $(SUBARCH) here instead of $(ARCH) so that this works for UML.
+# In the UML case, $(SUBARCH) is the name of the underlying
+# architecture, while for all other arches, it is the same as $(ARCH).
 checkstack:
        $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
-       $(PERL) $(src)/scripts/checkstack.pl $(ARCH)
+       $(PERL) $(src)/scripts/checkstack.pl $(SUBARCH)
 
 kernelrelease:
        $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
index 2a6e3da8144f01440733135289cb8760c872804c..21f71287b6f5f11b511a939d54222d4f4b5e7087 100644 (file)
@@ -1,5 +1,7 @@
 #include <linux/interrupt.h>
+#include <linux/io.h>
 
+#include <asm/pgtable.h>
 
 /* Prototypes of functions used across modules here in this directory.  */
 
@@ -181,9 +183,16 @@ extern void titan_dispatch_irqs(u64, struct pt_regs *);
 extern void switch_to_system_map(void);
 extern void srm_paging_stop(void);
 
-/* ../mm/remap.c */
-extern int __alpha_remap_area_pages(unsigned long, unsigned long, 
-                                   unsigned long, unsigned long);
+static inline int
+__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
+                        unsigned long size, unsigned long flags)
+{
+       pgprot_t prot;
+
+       prot = __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE
+                       | _PAGE_KWE | flags);
+       return ioremap_page_range(address, address + size, phys_addr, prot);
+}
 
 /* irq.c */
 
index b191cc75973751d5bdfe6137596a051a1c821b13..581ddcc22fc58e13eca80f75446e04c4c866ef09 100644 (file)
@@ -54,8 +54,6 @@
 #include "proto.h"
 #include "irq_impl.h"
 
-extern unsigned long wall_jiffies;     /* kernel/timer.c */
-
 static int set_rtc_mmss(unsigned long);
 
 DEFINE_SPINLOCK(rtc_lock);
@@ -132,7 +130,7 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
        nticks = delta >> FIX_SHIFT;
 
        while (nticks > 0) {
-               do_timer(regs);
+               do_timer(1);
 #ifndef CONFIG_SMP
                update_process_times(user_mode(regs));
 #endif
@@ -413,7 +411,7 @@ void
 do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
-       unsigned long sec, usec, lost, seq;
+       unsigned long sec, usec, seq;
        unsigned long delta_cycles, delta_usec, partial_tick;
 
        do {
@@ -423,14 +421,13 @@ do_gettimeofday(struct timeval *tv)
                sec = xtime.tv_sec;
                usec = (xtime.tv_nsec / 1000);
                partial_tick = state.partial_tick;
-               lost = jiffies - wall_jiffies;
 
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
 #ifdef CONFIG_SMP
        /* Until and unless we figure out how to get cpu cycle counters
           in sync and keep them there, we can't use the rpcc tricks.  */
-       delta_usec = lost * (1000000 / HZ);
+       delta_usec = 0;
 #else
        /*
         * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks)
@@ -446,8 +443,7 @@ do_gettimeofday(struct timeval *tv)
         */
 
        delta_usec = (delta_cycles * state.scaled_ticks_per_cycle 
-                     + partial_tick
-                     + (lost << FIX_SHIFT)) * 15625;
+                     + partial_tick) * 15625;
        delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
 #endif
 
@@ -480,12 +476,11 @@ do_settimeofday(struct timespec *tv)
           time.  Without this, a full-tick error is possible.  */
 
 #ifdef CONFIG_SMP
-       delta_nsec = (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
+       delta_nsec = 0;
 #else
        delta_nsec = rpcc() - state.last_time;
        delta_nsec = (delta_nsec * state.scaled_ticks_per_cycle 
-                     + state.partial_tick
-                     + ((jiffies - wall_jiffies) << FIX_SHIFT)) * 15625;
+                     + state.partial_tick) * 15625;
        delta_nsec = ((delta_nsec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
        delta_nsec *= 1000;
 #endif
index 6edd9a09ea4fdcd3c267c16a9cf9a2deffb11b6d..09399c5386cbaf058fce1e0906d4028cfeaad28c 100644 (file)
@@ -4,6 +4,6 @@
 
 EXTRA_CFLAGS := -Werror
 
-obj-y  := init.o fault.o extable.o remap.o
+obj-y  := init.o fault.o extable.o
 
 obj-$(CONFIG_DISCONTIGMEM) += numa.o
index 622dabd846800b14fb13c623eff5c61da0ac9cf7..8871529a34e2026e4f2bd4eda531df7ec59808a4 100644 (file)
@@ -193,7 +193,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
        /* We ran out of memory, or some other thing happened to us that
           made us unable to handle the page fault gracefully.  */
  out_of_memory:
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
diff --git a/arch/alpha/mm/remap.c b/arch/alpha/mm/remap.c
deleted file mode 100644 (file)
index a78356c..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#include <linux/vmalloc.h>
-#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-
-static inline void 
-remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, 
-              unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-       unsigned long pfn;
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-               set_pte(pte, pfn_pte(pfn, 
-                                    __pgprot(_PAGE_VALID | _PAGE_ASM | 
-                                             _PAGE_KRE | _PAGE_KWE | flags)));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int 
-remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, 
-              unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, 
-                                    address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-int
-__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
-                        unsigned long size, unsigned long flags)
-{
-       pgd_t * dir;
-       int error = 0;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset(&init_mm, address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pmd_t *pmd;
-               pmd = pmd_alloc(&init_mm, dir, address);
-               error = -ENOMEM;
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                  phys_addr + address, flags))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       return error;
-}
-
index f81a62380addefde7db4f0cde3902cb872c1c061..f9362ee9955f2411e932dbdca13a9dab5bf2c364 100644 (file)
@@ -17,6 +17,10 @@ config ARM
          Europe.  There is an ARM Linux project with a web page at
          <http://www.arm.linux.org.uk/>.
 
+config GENERIC_TIME
+       bool
+       default n
+
 config MMU
        bool
        default y
@@ -51,6 +55,10 @@ config GENERIC_HARDIRQS
        bool
        default y
 
+config TRACE_IRQFLAGS_SUPPORT
+       bool
+       default y
+
 config HARDIRQS_SW_RESEND
        bool
        default y
@@ -91,7 +99,7 @@ config ARCH_MTD_XIP
 
 config VECTORS_BASE
        hex
-       default 0xffff0000 if MMU
+       default 0xffff0000 if MMU || CPU_HIGH_VECTOR
        default DRAM_BASE if REMAP_VECTORS_TO_RAM
        default 0x00000000
        help
@@ -198,16 +206,27 @@ config ARCH_IMX
        help
          Support for Motorola's i.MX family of processors (MX1, MXL).
 
-config ARCH_IOP3XX
-       bool "IOP3xx-based"
+config ARCH_IOP32X
+       bool "IOP32x-based"
+       depends on MMU
+       select PLAT_IOP
+       select PCI
+       help
+         Support for Intel's 80219 and IOP32X (XScale) family of
+         processors.
+
+config ARCH_IOP33X
+       bool "IOP33x-based"
        depends on MMU
+       select PLAT_IOP
        select PCI
        help
-         Support for Intel's IOP3XX (XScale) family of processors.
+         Support for Intel's IOP33X (XScale) family of processors.
 
 config ARCH_IXP4XX
        bool "IXP4xx-based"
        depends on MMU
+       select GENERIC_TIME
        help
          Support for Intel's IXP4XX (XScale) family of processors.
 
@@ -308,7 +327,9 @@ source "arch/arm/mach-footbridge/Kconfig"
 
 source "arch/arm/mach-integrator/Kconfig"
 
-source "arch/arm/mach-iop3xx/Kconfig"
+source "arch/arm/mach-iop32x/Kconfig"
+
+source "arch/arm/mach-iop33x/Kconfig"
 
 source "arch/arm/mach-ixp4xx/Kconfig"
 
@@ -348,6 +369,9 @@ source "arch/arm/mach-netx/Kconfig"
 config ARCH_ACORN
        bool
 
+config PLAT_IOP
+       bool
+
 source arch/arm/mm/Kconfig
 
 #  bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
@@ -602,6 +626,7 @@ config LEDS_CPU
 
 config ALIGNMENT_TRAP
        bool
+       depends on CPU_CP15_MMU
        default y if !ARCH_EBSA110
        help
          ARM processors can not fetch/store information which is not
@@ -633,11 +658,12 @@ config ZBOOT_ROM_BSS
        hex "Compressed ROM boot loader BSS address"
        default "0"
        help
-         The base address of 64KiB of read/write memory in the target
-         for the ROM-able zImage, which must be available while the
-         decompressor is running.  Platforms which normally make use of
-         ROM-able zImage formats normally set this to a suitable
-         value in their defconfig file.
+         The base address of an area of read/write memory in the target
+         for the ROM-able zImage which must be available while the
+         decompressor is running. It must be large enough to hold the
+         entire decompressed kernel plus an additional 128 KiB.
+         Platforms which normally make use of ROM-able zImage formats
+         normally set this to a suitable value in their defconfig file.
 
          If ZBOOT_ROM is not enabled, this has no effect.
 
@@ -832,7 +858,7 @@ source "drivers/base/Kconfig"
 
 source "drivers/connector/Kconfig"
 
-if ALIGNMENT_TRAP
+if ALIGNMENT_TRAP || !CPU_CP15_MMU
 source "drivers/mtd/Kconfig"
 endif
 
@@ -844,7 +870,7 @@ source "drivers/block/Kconfig"
 
 source "drivers/acorn/block/Kconfig"
 
-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
+if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
        || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
        || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
        || ARCH_IXP23XX
index e1574be2ded614e05633c715381df9086d69f776..f087376748d12253bb9f0414c6c742dfd6eb0b89 100644 (file)
@@ -25,6 +25,14 @@ config FLASH_SIZE
        hex 'FLASH Size' if SET_MEM_PARAM
        default 0x00400000
 
+config PROCESSOR_ID
+       hex
+       default 0x00007700
+       depends on !CPU_CP15
+       help
+         If processor has no CP15 register, this processor ID is
+         used instead of the auto-probing which utilizes the register.
+
 config REMAP_VECTORS_TO_RAM
        bool 'Install vectors to the begining of RAM' if DRAM_BASE
        depends on DRAM_BASE
index 92873cdee31f50d259bda86d3c8a3241f9aa149c..2a0b2c8a1fe00df55a7dd87092d4ce3661399cfe 100644 (file)
@@ -55,7 +55,12 @@ arch-$(CONFIG_CPU_32v3)              :=-D__LINUX_ARM_ARCH__=3 -march=armv3
 # This selects how we optimise for the processor.
 tune-$(CONFIG_CPU_ARM610)      :=-mtune=arm610
 tune-$(CONFIG_CPU_ARM710)      :=-mtune=arm710
+tune-$(CONFIG_CPU_ARM7TDMI)    :=-mtune=arm7tdmi
 tune-$(CONFIG_CPU_ARM720T)     :=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM740T)     :=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM9TDMI)    :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM940T)     :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM946T)     :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
 tune-$(CONFIG_CPU_ARM920T)     :=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM922T)     :=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM925T)     :=-mtune=arm9tdmi
@@ -101,7 +106,8 @@ endif
  machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
  textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
- machine-$(CONFIG_ARCH_IOP3XX)    := iop3xx
+ machine-$(CONFIG_ARCH_IOP32X)    := iop32x
+ machine-$(CONFIG_ARCH_IOP33X)    := iop33x
  machine-$(CONFIG_ARCH_IXP4XX)    := ixp4xx
  machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
  machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
@@ -157,6 +163,7 @@ core-$(CONFIG_FPE_FASTFPE)  += $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)             += arch/arm/vfp/
 
 # If we have a common platform directory, then include it in the build.
+core-$(CONFIG_PLAT_IOP)                += arch/arm/plat-iop/
 core-$(CONFIG_ARCH_OMAP)       += arch/arm/plat-omap/
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
index 2adc1527e0ebc9d7a3d4936b0eb4e767381e2e84..adddc71316852f5001314faf10678f5fc4e3ef8d 100644 (file)
@@ -51,7 +51,11 @@ OBJS         += head-at91rm9200.o
 endif
 
 ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+ifeq ($(CONFIG_CPU_CP15),y)
 OBJS           += big-endian.o
+else
+# The endian should be set by h/w design.
+endif
 endif
 
 #
index 14a9ff9c68df4bfcdbca3fe97dcea28f702588a0..e5ab51b9cceb1bdfd155c9824ba6364d21cc1977 100644 (file)
 #ifdef DEBUG
 
 #if defined(CONFIG_DEBUG_ICEDCC)
+
+#ifdef CONFIG_CPU_V6
+               .macro  loadsp, rb
+               .endm
+               .macro  writeb, ch, rb
+               mcr     p14, 0, \ch, c0, c5, 0
+               .endm
+#else
                .macro  loadsp, rb
                .endm
                .macro  writeb, ch, rb
                mcr     p14, 0, \ch, c0, c1, 0
                .endm
+#endif
+
 #else
 
 #include <asm/arch/debug-macro.S>
                add     \rb, \rb, #0x00010000   @ Ser1
 #endif
                .endm
-#elif defined(CONFIG_ARCH_IOP331)
-               .macro loadsp, rb
-                mov    \rb, #0xff000000
-                orr     \rb, \rb, #0x00ff0000
-                orr     \rb, \rb, #0x0000f700   @ location of the UART
-               .endm
 #elif defined(CONFIG_ARCH_S3C2410)
                .macro loadsp, rb
                mov     \rb, #0x50000000
                kphex   r6, 8           /* processor id */
                kputc   #':'
                kphex   r7, 8           /* architecture id */
+#ifdef CONFIG_CPU_CP15
                kputc   #':'
                mrc     p15, 0, r0, c1, c0
                kphex   r0, 8           /* control reg */
+#endif
                kputc   #'\n'
                kphex   r5, 8           /* decompressed kernel start */
                kputc   #'-'
@@ -503,7 +509,11 @@ call_kernel:       bl      cache_clean_flush
  */
 
 call_cache_fn: adr     r12, proc_types
+#ifdef CONFIG_CPU_CP15
                mrc     p15, 0, r6, c0, c0      @ get processor ID
+#else
+               ldr     r6, =CONFIG_PROCESSOR_ID
+#endif
 1:             ldr     r1, [r12, #0]           @ get value
                ldr     r2, [r12, #4]           @ get mask
                eor     r1, r1, r6              @ (real ^ match)
index ace3fb5835d9278833a0c539b8fff0b74e8af885..283891c736c4a9a92ab9f336f93b23ba83dfe956 100644 (file)
@@ -30,6 +30,25 @@ static void putstr(const char *ptr);
 #include <asm/arch/uncompress.h>
 
 #ifdef CONFIG_DEBUG_ICEDCC
+
+#ifdef CONFIG_CPU_V6
+
+static void icedcc_putc(int ch)
+{
+       int status, i = 0x4000000;
+
+       do {
+               if (--i < 0)
+                       return;
+
+               asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
+       } while (status & (1 << 29));
+
+       asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
+}
+
+#else
+
 static void icedcc_putc(int ch)
 {
        int status, i = 0x4000000;
@@ -44,6 +63,8 @@ static void icedcc_putc(int ch)
        asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
 }
 
+#endif
+
 #define putc(ch)       icedcc_putc(ch)
 #define flush()        do { } while (0)
 #endif
index bafe8b19be82a422ada8f2617a60b8022e584f08..6d094c1575400d0487b754ecb6a723ee474435dd 100644 (file)
@@ -57,7 +57,7 @@ icst307_khz_to_vco(const struct icst307_params *p, unsigned long freq)
                        break;
        } while (i < ARRAY_SIZE(idx2s));
 
-       if (i > ARRAY_SIZE(idx2s))
+       if (i >= ARRAY_SIZE(idx2s))
                return vco;
 
        vco.s = idx2s[i];
@@ -119,7 +119,7 @@ icst307_ps_to_vco(const struct icst307_params *p, unsigned long period)
                        break;
        } while (i < ARRAY_SIZE(idx2s));
 
-       if (i > ARRAY_SIZE(idx2s))
+       if (i >= ARRAY_SIZE(idx2s))
                return vco;
 
        vco.s = idx2s[i];
index 943ef88c0379b79ee25505392cb21f3ade0a523f..3d377c5bdef6299332c068974753a0c41e8c939d 100644 (file)
@@ -55,7 +55,7 @@ icst525_khz_to_vco(const struct icst525_params *p, unsigned long freq)
                        break;
        } while (i < ARRAY_SIZE(idx2s));
 
-       if (i > ARRAY_SIZE(idx2s))
+       if (i >= ARRAY_SIZE(idx2s))
                return vco;
 
        vco.s = idx2s[i];
@@ -118,7 +118,7 @@ icst525_ps_to_vco(const struct icst525_params *p, unsigned long period)
                        break;
        } while (i < ARRAY_SIZE(idx2s));
 
-       if (i > ARRAY_SIZE(idx2s))
+       if (i >= ARRAY_SIZE(idx2s))
                return vco;
 
        vco.s = idx2s[i];
index 4e0dcaef6eb204a4a5c344d2011baadcfd64502a..181ef1ead5b8362e1bef5fabe94f2659befceced 100644 (file)
@@ -121,6 +121,13 @@ static struct locomo_dev_info locomo_devices[] = {
                .offset         = 0,
                .length         = 0,
        },
+       {
+               .devid          = LOCOMO_DEVID_SPI,
+               .irq            = {},
+               .name           = "locomo-spi",
+               .offset         = LOCOMO_SPI,
+               .length         = 0x30,
+       },
 };
 
 
@@ -374,7 +381,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc,
        struct irqdesc *d;
        void __iomem *mapbase = get_irq_chipdata(irq);
 
-       req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F;
+       req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
        if (req) {
                irq = LOCOMO_IRQ_SPI_START;
                d = irq_desc + irq;
@@ -391,35 +398,35 @@ static void locomo_spi_ack_irq(unsigned int irq)
 {
        void __iomem *mapbase = get_irq_chipdata(irq);
        unsigned int r;
-       r = locomo_readl(mapbase + LOCOMO_SPIWE);
+       r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
        r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-       locomo_writel(r, mapbase + LOCOMO_SPIWE);
+       locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
 
-       r = locomo_readl(mapbase + LOCOMO_SPIIS);
+       r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
        r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-       locomo_writel(r, mapbase + LOCOMO_SPIIS);
+       locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
 
-       r = locomo_readl(mapbase + LOCOMO_SPIWE);
+       r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
        r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-       locomo_writel(r, mapbase + LOCOMO_SPIWE);
+       locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
 }
 
 static void locomo_spi_mask_irq(unsigned int irq)
 {
        void __iomem *mapbase = get_irq_chipdata(irq);
        unsigned int r;
-       r = locomo_readl(mapbase + LOCOMO_SPIIE);
+       r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
        r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-       locomo_writel(r, mapbase + LOCOMO_SPIIE);
+       locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
 }
 
 static void locomo_spi_unmask_irq(unsigned int irq)
 {
        void __iomem *mapbase = get_irq_chipdata(irq);
        unsigned int r;
-       r = locomo_readl(mapbase + LOCOMO_SPIIE);
+       r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
        r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-       locomo_writel(r, mapbase + LOCOMO_SPIIE);
+       locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
 }
 
 static struct irq_chip locomo_spi_chip = {
@@ -814,12 +821,15 @@ static inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev)
        return (struct locomo *)dev_get_drvdata(ldev->dev.parent);
 }
 
-void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir)
+void locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir)
 {
-       struct locomo *lchip = locomo_chip_driver(ldev);
+       struct locomo *lchip = dev_get_drvdata(dev);
        unsigned long flags;
        unsigned int r;
 
+       if (!lchip)
+               return;
+
        spin_lock_irqsave(&lchip->lock, flags);
 
        r = locomo_readl(lchip->base + LOCOMO_GPD);
@@ -836,12 +846,15 @@ void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned in
        spin_unlock_irqrestore(&lchip->lock, flags);
 }
 
-unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits)
+int locomo_gpio_read_level(struct device *dev, unsigned int bits)
 {
-       struct locomo *lchip = locomo_chip_driver(ldev);
+       struct locomo *lchip = dev_get_drvdata(dev);
        unsigned long flags;
        unsigned int ret;
 
+       if (!lchip)
+               return -ENODEV;
+
        spin_lock_irqsave(&lchip->lock, flags);
        ret = locomo_readl(lchip->base + LOCOMO_GPL);
        spin_unlock_irqrestore(&lchip->lock, flags);
@@ -850,12 +863,15 @@ unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits)
        return ret;
 }
 
-unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits)
+int locomo_gpio_read_output(struct device *dev, unsigned int bits)
 {
-       struct locomo *lchip = locomo_chip_driver(ldev);
+       struct locomo *lchip = dev_get_drvdata(dev);
        unsigned long flags;
        unsigned int ret;
 
+       if (!lchip)
+               return -ENODEV;
+
        spin_lock_irqsave(&lchip->lock, flags);
        ret = locomo_readl(lchip->base + LOCOMO_GPO);
        spin_unlock_irqrestore(&lchip->lock, flags);
@@ -864,12 +880,15 @@ unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits)
        return ret;
 }
 
-void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set)
+void locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set)
 {
-       struct locomo *lchip = locomo_chip_driver(ldev);
+       struct locomo *lchip = dev_get_drvdata(dev);
        unsigned long flags;
        unsigned int r;
 
+       if (!lchip)
+               return;
+
        spin_lock_irqsave(&lchip->lock, flags);
 
        r = locomo_readl(lchip->base + LOCOMO_GPO);
@@ -1058,9 +1077,9 @@ void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
        struct locomo *lchip = locomo_chip_driver(dev);
 
        if (vr)
-               locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 1);
+               locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 1);
        else
-               locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 0);
+               locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
 
        spin_lock_irqsave(&lchip->lock, flags);
        locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
index 59b5ddec480f6992db54c2e8d0fdae5c9639b2ac..f412dedda68412b2c6ac239826e1adc14f03931a 100644 (file)
@@ -40,6 +40,7 @@
 #define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
 #define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
 #define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
+
 #define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
 #define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
@@ -575,6 +576,9 @@ static int corgi_pxa_pm_enter(suspend_state_t state)
        while (corgi_enter_suspend(alarm_time,alarm_status,state))
                {}
 
+       if (sharpsl_pm.machinfo->earlyresume)
+               sharpsl_pm.machinfo->earlyresume();
+
        dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
 
        return 0;
diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig
deleted file mode 100644 (file)
index 3c73b70..0000000
+++ /dev/null
@@ -1,952 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:34:12 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-# CONFIG_ARCH_IQ80321 is not set
-CONFIG_ARCH_IQ31244=y
-# CONFIG_ARCH_IQ80331 is not set
-# CONFIG_MACH_IQ80332 is not set
-CONFIG_ARCH_EP80219=y
-CONFIG_ARCH_IOP321=y
-# CONFIG_ARCH_IOP331 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xf0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# 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=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-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=y
-
-#
-# 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
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA 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_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-# CONFIG_MD_LINEAR is not set
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH 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
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-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 is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET 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_NET_VENDOR_3COM is not set
-# CONFIG_SMC91X is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 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_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO 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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=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_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_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_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS 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=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=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
-
-#
-# 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
index 2948b4589a8b4bc8bfea4ebb09d9c191c6a01e73..3b4802a849e444590175933b77fb73d5061cd724 100644 (file)
@@ -126,6 +126,7 @@ CONFIG_CRUNCH=y
 # EP93xx Platforms
 #
 CONFIG_MACH_EDB9302=y
+CONFIG_MACH_EDB9312=y
 CONFIG_MACH_EDB9315=y
 CONFIG_MACH_EDB9315A=y
 CONFIG_MACH_GESBC9312=y
diff --git a/arch/arm/configs/iop32x_defconfig b/arch/arm/configs/iop32x_defconfig
new file mode 100644 (file)
index 0000000..0d67f66
--- /dev/null
@@ -0,0 +1,1236 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc7
+# Tue Sep 19 00:30:18 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+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_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# 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_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=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_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+CONFIG_ARCH_IOP32X=y
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# IOP32x Implementation Options
+#
+
+#
+# IOP32x Platform Types
+#
+CONFIG_MACH_GLANTANK=y
+CONFIG_ARCH_IQ80321=y
+CONFIG_ARCH_IQ31244=y
+CONFIG_MACH_N2100=y
+CONFIG_PLAT_IOP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+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_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 is not set
+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 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=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT 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_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# 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=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH 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_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=y
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 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_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
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH 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
+
+#
+# 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 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 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 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_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO 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
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+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=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_IOP3XX=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT 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=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID 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
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# 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_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=y
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT 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_SYSFS=y
+CONFIG_TMPFS=y
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS 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=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS 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_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/iop33x_defconfig b/arch/arm/configs/iop33x_defconfig
new file mode 100644 (file)
index 0000000..2a8fc15
--- /dev/null
@@ -0,0 +1,1081 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc7
+# Tue Sep 19 00:30:42 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+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_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# 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_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=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_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+CONFIG_ARCH_IOP33X=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# IOP33x Implementation Options
+#
+
+#
+# IOP33x Platform Types
+#
+CONFIG_ARCH_IQ80331=y
+CONFIG_MACH_IQ80332=y
+CONFIG_PLAT_IOP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+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_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 is not set
+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 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=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT 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_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# 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=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH 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_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=y
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 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_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
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH 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
+
+#
+# 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
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT 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
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO 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
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+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=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_IOP3XX=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT 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
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# 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_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=y
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT 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_SYSFS=y
+CONFIG_TMPFS=y
+# 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_JFFS_FS is not set
+# CONFIG_JFFS2_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=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS 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_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
deleted file mode 100644 (file)
index 3246716..0000000
+++ /dev/null
@@ -1,922 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 02:10:38 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-# CONFIG_ARCH_IQ80321 is not set
-CONFIG_ARCH_IQ31244=y
-# CONFIG_ARCH_IQ80331 is not set
-# CONFIG_MACH_IQ80332 is not set
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP321=y
-# CONFIG_ARCH_IOP331 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xf0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# 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=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-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=y
-
-#
-# 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
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA 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_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-# CONFIG_MD_LINEAR is not set
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH 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
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-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 is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO 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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=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_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_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_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS 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=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=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
-
-#
-# 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
deleted file mode 100644 (file)
index b000da7..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 13:24:10 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-CONFIG_ARCH_IQ80321=y
-# CONFIG_ARCH_IQ31244 is not set
-# CONFIG_ARCH_IQ80331 is not set
-# CONFIG_MACH_IQ80332 is not set
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP321=y
-# CONFIG_ARCH_IOP331 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xf0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# 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=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-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 is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO 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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=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_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_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_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS 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=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=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
-
-#
-# 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig
deleted file mode 100644 (file)
index 46c79e1..0000000
+++ /dev/null
@@ -1,916 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 15:13:37 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-# CONFIG_ARCH_IQ80321 is not set
-# CONFIG_ARCH_IQ31244 is not set
-CONFIG_ARCH_IQ80331=y
-# CONFIG_MACH_IQ80332 is not set
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP331=y
-
-#
-# IOP3xx Chipset Features
-#
-CONFIG_IOP331_STEPD=y
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_GEOMETRY is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xc0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# 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=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-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=y
-
-#
-# 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
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA 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_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH 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
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-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 is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO 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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=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_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_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_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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_JFFS_FS is not set
-# CONFIG_JFFS2_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=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=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
-
-#
-# 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig
deleted file mode 100644 (file)
index 11959b7..0000000
+++ /dev/null
@@ -1,916 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 17:33:39 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# IOP3xx Implementation Options
-#
-
-#
-# IOP3xx Platform Types
-#
-# CONFIG_ARCH_IQ80321 is not set
-# CONFIG_ARCH_IQ31244 is not set
-# CONFIG_ARCH_IQ80331 is not set
-CONFIG_MACH_IQ80332=y
-# CONFIG_ARCH_EP80219 is not set
-CONFIG_ARCH_IOP331=y
-
-#
-# IOP3xx Chipset Features
-#
-# CONFIG_IOP331_STEPD is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
-
-#
-# Bus support
-#
-CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_GEOMETRY is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xc0000000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# 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=8192
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-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=y
-
-#
-# 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
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA 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_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH 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
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-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 is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-CONFIG_E1000_NAPI=y
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO 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
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=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_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_IOP3XX=y
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR 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_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_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_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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_JFFS_FS is not set
-# CONFIG_JFFS2_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=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=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
-
-#
-# 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_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
index f20814e6f4976b11441bd2a05b935c22a17259f7..a83222641045754afc8e0ec63a181d57cbd7cc72 100644 (file)
@@ -1,14 +1,19 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-git9
-# Sun Jun 25 23:56:32 2006
+# Linux kernel version: 2.6.18
+# Wed Sep 20 20:27:31 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -26,14 +31,15 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -46,6 +52,8 @@ 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
@@ -84,7 +92,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
@@ -94,7 +102,8 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
 # CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
@@ -122,13 +131,18 @@ CONFIG_ARCH_SMDK2410=y
 CONFIG_ARCH_S3C2440=y
 CONFIG_SMDK2440_CPU2440=y
 CONFIG_SMDK2440_CPU2442=y
+CONFIG_MACH_S3C2413=y
 CONFIG_MACH_SMDK2413=y
 CONFIG_MACH_VR1000=y
 CONFIG_MACH_RX3715=y
 CONFIG_MACH_OTOM=y
 CONFIG_MACH_NEXCODER_2440=y
+CONFIG_MACH_VSTMS=y
 CONFIG_S3C2410_CLOCK=y
+CONFIG_S3C2410_PM=y
+CONFIG_CPU_S3C2410_DMA=y
 CONFIG_CPU_S3C2410=y
+CONFIG_S3C2412_PM=y
 CONFIG_CPU_S3C2412=y
 CONFIG_CPU_S3C244X=y
 CONFIG_CPU_S3C2440=y
@@ -156,7 +170,7 @@ CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
 CONFIG_CPU_32=y
 CONFIG_CPU_ARM920T=y
 CONFIG_CPU_ARM926T=y
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32v4T=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV4T=y
 CONFIG_CPU_ABRT_EV5TJ=y
@@ -200,6 +214,7 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -304,7 +319,6 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -460,6 +474,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 CONFIG_ATA_OVER_ETH=m
@@ -640,6 +655,7 @@ CONFIG_SERIO_LIBPS2=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_COMPUTONE is not set
 # CONFIG_ROCKETPORT is not set
@@ -716,6 +732,7 @@ CONFIG_S3C2410_WATCHDOG=y
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
 # CONFIG_NVRAM is not set
 CONFIG_S3C2410_RTC=y
 # CONFIG_DTLK is not set
@@ -857,12 +874,12 @@ CONFIG_VIDEO_V4L2=y
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
-CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
@@ -995,7 +1012,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
@@ -1095,6 +1112,7 @@ CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -1202,14 +1220,19 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS 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=y
@@ -1251,3 +1274,4 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
index 33c55689f999ea3f7bcd6f4955d339b4d08fd343..ecf4f9472d94e950781e7bfdea05fd446bd40ade 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/completion.h>
+#include <linux/kthread.h>
 
 #include <asm/apm.h> /* apm_power_info */
 #include <asm/system.h>
@@ -80,7 +81,7 @@ struct apm_user {
  */
 static int suspends_pending;
 static int apm_disabled;
-static int arm_apm_active;
+static struct task_struct *kapmd_tsk;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
@@ -97,7 +98,6 @@ static LIST_HEAD(apm_user_list);
  * to be suspending the system.
  */
 static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
-static DECLARE_COMPLETION(kapmd_exit);
 static DEFINE_SPINLOCK(kapmd_queue_lock);
 static struct apm_queue kapmd_queue;
 
@@ -468,16 +468,13 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
 
 static int kapmd(void *arg)
 {
-       daemonize("kapmd");
-       current->flags |= PF_NOFREEZE;
-
        do {
                apm_event_t event;
 
                wait_event_interruptible(kapmd_wait,
-                               !queue_empty(&kapmd_queue) || !arm_apm_active);
+                               !queue_empty(&kapmd_queue) || kthread_should_stop());
 
-               if (!arm_apm_active)
+               if (kthread_should_stop())
                        break;
 
                spin_lock_irq(&kapmd_queue_lock);
@@ -508,7 +505,7 @@ static int kapmd(void *arg)
                }
        } while (1);
 
-       complete_and_exit(&kapmd_exit, 0);
+       return 0;
 }
 
 static int __init apm_init(void)
@@ -520,13 +517,14 @@ static int __init apm_init(void)
                return -ENODEV;
        }
 
-       arm_apm_active = 1;
-
-       ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
-       if (ret < 0) {
-               arm_apm_active = 0;
+       kapmd_tsk = kthread_create(kapmd, NULL, "kapmd");
+       if (IS_ERR(kapmd_tsk)) {
+               ret = PTR_ERR(kapmd_tsk);
+               kapmd_tsk = NULL;
                return ret;
        }
+       kapmd_tsk->flags |= PF_NOFREEZE;
+       wake_up_process(kapmd_tsk);
 
 #ifdef CONFIG_PROC_FS
        create_proc_info_entry("apm", 0, NULL, apm_get_info);
@@ -535,10 +533,7 @@ static int __init apm_init(void)
        ret = misc_register(&apm_device);
        if (ret != 0) {
                remove_proc_entry("apm", NULL);
-
-               arm_apm_active = 0;
-               wake_up(&kapmd_wait);
-               wait_for_completion(&kapmd_exit);
+               kthread_stop(kapmd_tsk);
        }
 
        return ret;
@@ -549,9 +544,7 @@ static void __exit apm_exit(void)
        misc_deregister(&apm_device);
        remove_proc_entry("apm", NULL);
 
-       arm_apm_active = 0;
-       wake_up(&kapmd_wait);
-       wait_for_completion(&kapmd_exit);
+       kthread_stop(kapmd_tsk);
 }
 
 module_init(apm_init);
index a5747e58a9dc66d37e0b7182b7f06be2795257a0..5617566477b493d5cc6034a8518b8f6e696195f3 100644 (file)
 
 #if defined(CONFIG_DEBUG_ICEDCC)
                @@ debug using ARM EmbeddedICE DCC channel
+
+#if defined(CONFIG_CPU_V6)
+
+               .macro  addruart, rx
+               .endm
+
+               .macro  senduart, rd, rx
+               mcr     p14, 0, \rd, c0, c5, 0
+               .endm
+
+               .macro  busyuart, rd, rx
+1001:
+               mrc     p14, 0, \rx, c0, c1, 0
+               tst     \rx, #0x20000000
+               beq     1001b
+               .endm
+
+               .macro  waituart, rd, rx
+               mov     \rd, #0x2000000
+1001:
+               subs    \rd, \rd, #1
+               bmi     1002f
+               mrc     p14, 0, \rx, c0, c1, 0
+               tst     \rx, #0x20000000
+               bne     1001b
+1002:
+               .endm
+
+#else
+
                .macro  addruart, rx
                .endm
 
                bne     1001b
 1002:
                .endm
+
+#endif /* CONFIG_CPU_V6 */
+
 #else
 #include <asm/arch/debug-macro.S>
-#endif
+#endif /* CONFIG_DEBUG_ICEDCC */
 
 /*
  * Useful debugging routines
index eca248d9eba44823986f1e6c30a1ffa7b8d1f77f..3e14b1348c0b715d77c77390bdd12e95668c5e0a 100644 (file)
@@ -295,7 +295,7 @@ ecard_task(void * unused)
  */
 static void ecard_call(struct ecard_request *req)
 {
-       DECLARE_COMPLETION(completion);
+       DECLARE_COMPLETION_ONSTACK(completion);
 
        req->complete = &completion;
 
index de4e331379013229082a76f86a3c314492ba206d..bd623b73445f79a9b37018e0da7d320d003c2a7c 100644 (file)
@@ -191,6 +191,9 @@ __dabt_svc:
 __irq_svc:
        svc_entry
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
 #ifdef CONFIG_PREEMPT
        get_thread_info tsk
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
@@ -211,6 +214,10 @@ preempt_return:
 #endif
        ldr     r0, [sp, #S_PSR]                @ irqs are already disabled
        msr     spsr_cxsf, r0
+#ifdef CONFIG_TRACE_IRQFLAGS
+       tst     r0, #PSR_I_BIT
+       bleq    trace_hardirqs_on
+#endif
        ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
 
        .ltorg
@@ -398,6 +405,9 @@ __dabt_usr:
 __irq_usr:
        usr_entry
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
        get_thread_info tsk
 #ifdef CONFIG_PREEMPT
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
@@ -412,6 +422,9 @@ __irq_usr:
        teq     r0, r7
        strne   r0, [r0, -r0]
 #endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_on
+#endif
 
        mov     why, #0
        b       ret_to_user
index ac9eb3d30518ade76e1b01965fb969d90f856950..f359a189dcf2cda84f112dc0003e616cdd6434d4 100644 (file)
@@ -9,7 +9,6 @@
  * published by the Free Software Foundation.
  *
  *  Common kernel startup code (non-paged MM)
- *    for 32-bit CPUs which has a process ID register(CP15).
  *
  */
 #include <linux/linkage.h>
 ENTRY(stext)
        msr     cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
                                                @ and irqs disabled
+#ifndef CONFIG_CPU_CP15
+       ldr     r9, =CONFIG_PROCESSOR_ID
+#else
        mrc     p15, 0, r9, c0, c0              @ get processor id
+#endif
        bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
        movs    r10, r5                         @ invalid processor (r5=0)?
        beq     __error_p                               @ yes, error 'p'
@@ -58,6 +61,7 @@ ENTRY(stext)
  */
        .type   __after_proc_init, %function
 __after_proc_init:
+#ifdef CONFIG_CPU_CP15
        mrc     p15, 0, r0, c1, c0, 0           @ read control reg
 #ifdef CONFIG_ALIGNMENT_TRAP
        orr     r0, r0, #CR_A
@@ -72,8 +76,14 @@ __after_proc_init:
 #endif
 #ifdef CONFIG_CPU_ICACHE_DISABLE
        bic     r0, r0, #CR_I
+#endif
+#ifdef CONFIG_CPU_HIGH_VECTOR
+       orr     r0, r0, #CR_V
+#else
+       bic     r0, r0, #CR_V
 #endif
        mcr     p15, 0, r0, c1, c0, 0           @ write control reg
+#endif /* CONFIG_CPU_CP15 */
 
        mov     pc, r13                         @ clear the BSS and jump
                                                @ to start_kernel
index 298363d97047755c3ac969baef5a95217a69bea8..1b061583408ed7f44158a7dfcf7b996e56f7a53f 100644 (file)
@@ -2,6 +2,7 @@
  *  linux/arch/arm/kernel/module.c
  *
  *  Copyright (C) 2002 Russell King.
+ *  Modified for nommu by Hyok S. Choi
  *
  * 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
@@ -32,6 +33,7 @@ extern void _etext;
 #define MODULE_START   (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK)
 #endif
 
+#ifdef CONFIG_MMU
 void *module_alloc(unsigned long size)
 {
        struct vm_struct *area;
@@ -46,6 +48,12 @@ void *module_alloc(unsigned long size)
 
        return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
 }
+#else /* CONFIG_MMU */
+void *module_alloc(unsigned long size)
+{
+       return size == 0 ? NULL : vmalloc(size);
+}
+#endif /* !CONFIG_MMU */
 
 void module_free(struct module *module, void *region)
 {
index 3079535afccd4be9daf1219c101ac8bc0959e7c7..bf35c178a8772d232fc5e5e1eb0e5ba91449a2fd 100644 (file)
@@ -221,16 +221,26 @@ void __show_regs(struct pt_regs *regs)
                processor_modes[processor_mode(regs)],
                thumb_mode(regs) ? " (T)" : "",
                get_fs() == get_ds() ? "kernel" : "user");
+#if CONFIG_CPU_CP15
        {
-               unsigned int ctrl, transbase, dac;
+               unsigned int ctrl;
                  __asm__ (
                "       mrc p15, 0, %0, c1, c0\n"
-               "       mrc p15, 0, %1, c2, c0\n"
-               "       mrc p15, 0, %2, c3, c0\n"
-               : "=r" (ctrl), "=r" (transbase), "=r" (dac));
-               printk("Control: %04X  Table: %08X  DAC: %08X\n",
-                       ctrl, transbase, dac);
+               : "=r" (ctrl));
+               printk("Control: %04X\n", ctrl);
        }
+#ifdef CONFIG_CPU_CP15_MMU
+       {
+               unsigned int transbase, dac;
+                 __asm__ (
+               "       mrc p15, 0, %0, c2, c0\n"
+               "       mrc p15, 0, %1, c3, c0\n"
+               : "=r" (transbase), "=r" (dac));
+               printk("Table: %08X  DAC: %08X\n",
+                       transbase, dac);
+       }
+#endif
+#endif
 }
 
 void show_regs(struct pt_regs * regs)
index 09a67d77185775937a6f70c9541172bbee416d67..b030320b17c7eef06e1a66ddd084b67867aa235f 100644 (file)
@@ -37,8 +37,6 @@
  */
 struct sys_timer *system_timer;
 
-extern unsigned long wall_jiffies;
-
 /* this needs a better home */
 DEFINE_SPINLOCK(rtc_lock);
 
@@ -69,10 +67,12 @@ EXPORT_SYMBOL(profile_pc);
  */
 int (*set_rtc)(void);
 
+#ifndef CONFIG_GENERIC_TIME
 static unsigned long dummy_gettimeoffset(void)
 {
        return 0;
 }
+#endif
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -230,20 +230,16 @@ static inline void do_leds(void)
 #define        do_leds()
 #endif
 
+#ifndef CONFIG_GENERIC_TIME
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
        unsigned long seq;
-       unsigned long usec, sec, lost;
+       unsigned long usec, sec;
 
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = system_timer->offset();
-
-               lost = jiffies - wall_jiffies;
-               if (lost)
-                       usec += lost * USECS_PER_JIFFY;
-
                sec = xtime.tv_sec;
                usec += xtime.tv_nsec / 1000;
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -276,7 +272,6 @@ int do_settimeofday(struct timespec *tv)
         * done, and then undo it!
         */
        nsec -= system_timer->offset() * NSEC_PER_USEC;
-       nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -291,6 +286,7 @@ int do_settimeofday(struct timespec *tv)
 }
 
 EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
 
 /**
  * save_time_delta - Save the offset between system time and RTC time
@@ -333,7 +329,7 @@ void timer_tick(struct pt_regs *regs)
        profile_tick(CPU_PROFILING, regs);
        do_leds();
        do_set_rtc();
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -500,8 +496,10 @@ device_initcall(timer_init_sysfs);
 
 void __init time_init(void)
 {
+#ifndef CONFIG_GENERIC_TIME
        if (system_timer->offset == NULL)
                system_timer->offset = dummy_gettimeoffset;
+#endif
        system_timer->init();
 
 #ifdef CONFIG_NO_IDLE_HZ
index aeeed806f9915574576e5ea628562a86d8f3a7b1..bede380c07a9ef2e285303756502792c2a7f0c45 100644 (file)
@@ -191,7 +191,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
        if (tsk != current)
                fp = thread_saved_fp(tsk);
        else
-               asm("mov%? %0, fp" : "=r" (fp));
+               asm("mov %0, fp" : "=r" (fp) : : "cc");
 
        c_backtrace(fp, 0x10);
        barrier();
index 0985b1c42c7c83f2523a91d87ba46756469e3358..dcf6136fedf9deb51f916a190634e0c333d416c1 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <asm/hardware.h>
 #include "generic.h"
+#include "clock.h"
 
 static struct map_desc at91rm9200_io_desc[] __initdata = {
        {
@@ -26,87 +27,224 @@ static struct map_desc at91rm9200_io_desc[] __initdata = {
                .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_VA_BASE_SPI,
-               .pfn            = __phys_to_pfn(AT91_BASE_SPI),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_SSC2,
-               .pfn            = __phys_to_pfn(AT91_BASE_SSC2),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_SSC1,
-               .pfn            = __phys_to_pfn(AT91_BASE_SSC1),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_SSC0,
-               .pfn            = __phys_to_pfn(AT91_BASE_SSC0),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_US3,
-               .pfn            = __phys_to_pfn(AT91_BASE_US3),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_US2,
-               .pfn            = __phys_to_pfn(AT91_BASE_US2),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_US1,
-               .pfn            = __phys_to_pfn(AT91_BASE_US1),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_US0,
-               .pfn            = __phys_to_pfn(AT91_BASE_US0),
+               .pfn            = __phys_to_pfn(AT91RM9200_BASE_SPI),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_VA_BASE_EMAC,
-               .pfn            = __phys_to_pfn(AT91_BASE_EMAC),
+               .pfn            = __phys_to_pfn(AT91RM9200_BASE_EMAC),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_VA_BASE_TWI,
-               .pfn            = __phys_to_pfn(AT91_BASE_TWI),
+               .pfn            = __phys_to_pfn(AT91RM9200_BASE_TWI),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_VA_BASE_MCI,
-               .pfn            = __phys_to_pfn(AT91_BASE_MCI),
+               .pfn            = __phys_to_pfn(AT91RM9200_BASE_MCI),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_VA_BASE_UDP,
-               .pfn            = __phys_to_pfn(AT91_BASE_UDP),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_TCB1,
-               .pfn            = __phys_to_pfn(AT91_BASE_TCB1),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = AT91_VA_BASE_TCB0,
-               .pfn            = __phys_to_pfn(AT91_BASE_TCB0),
+               .pfn            = __phys_to_pfn(AT91RM9200_BASE_UDP),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = AT91_SRAM_VIRT_BASE,
-               .pfn            = __phys_to_pfn(AT91_SRAM_BASE),
-               .length         = AT91_SRAM_SIZE,
+               .pfn            = __phys_to_pfn(AT91RM9200_SRAM_BASE),
+               .length         = AT91RM9200_SRAM_SIZE,
                .type           = MT_DEVICE,
        },
 };
 
-void __init at91rm9200_map_io(void)
+/* --------------------------------------------------------------------
+ *  Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk udc_clk = {
+       .name           = "udc_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_UDP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+       .name           = "ohci_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_UHP,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ether_clk = {
+       .name           = "ether_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_EMAC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc_clk = {
+       .name           = "mci_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_MCI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+       .name           = "twi_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_TWI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+       .name           = "usart0_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_US0,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+       .name           = "usart1_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_US1,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+       .name           = "usart2_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_US2,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart3_clk = {
+       .name           = "usart3_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_US3,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi_clk = {
+       .name           = "spi_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_SPI,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioA_clk = {
+       .name           = "pioA_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_PIOA,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+       .name           = "pioB_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_PIOB,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioC_clk = {
+       .name           = "pioC_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_PIOC,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioD_clk = {
+       .name           = "pioD_clk",
+       .pmc_mask       = 1 << AT91RM9200_ID_PIOD,
+       .type           = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+       &pioA_clk,
+       &pioB_clk,
+       &pioC_clk,
+       &pioD_clk,
+       &usart0_clk,
+       &usart1_clk,
+       &usart2_clk,
+       &usart3_clk,
+       &mmc_clk,
+       &udc_clk,
+       &twi_clk,
+       &spi_clk,
+       // ssc 0 .. ssc2
+       // tc0 .. tc5
+       &ohci_clk,
+       &ether_clk,
+       // irq0 .. irq6
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+       .name           = "pck0",
+       .pmc_mask       = AT91_PMC_PCK0,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 0,
+};
+static struct clk pck1 = {
+       .name           = "pck1",
+       .pmc_mask       = AT91_PMC_PCK1,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 1,
+};
+static struct clk pck2 = {
+       .name           = "pck2",
+       .pmc_mask       = AT91_PMC_PCK2,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 2,
+};
+static struct clk pck3 = {
+       .name           = "pck3",
+       .pmc_mask       = AT91_PMC_PCK3,
+       .type           = CLK_TYPE_PROGRAMMABLE,
+       .id             = 3,
+};
+
+static void __init at91rm9200_register_clocks(void)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+               clk_register(periph_clocks[i]);
+
+       clk_register(&pck0);
+       clk_register(&pck1);
+       clk_register(&pck2);
+       clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ *  GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91rm9200_gpio[] = {
+       {
+               .id             = AT91RM9200_ID_PIOA,
+               .offset         = AT91_PIOA,
+               .clock          = &pioA_clk,
+       }, {
+               .id             = AT91RM9200_ID_PIOB,
+               .offset         = AT91_PIOB,
+               .clock          = &pioB_clk,
+       }, {
+               .id             = AT91RM9200_ID_PIOC,
+               .offset         = AT91_PIOC,
+               .clock          = &pioC_clk,
+       }, {
+               .id             = AT91RM9200_ID_PIOD,
+               .offset         = AT91_PIOD,
+               .clock          = &pioD_clk,
+       }
+};
+
+/* --------------------------------------------------------------------
+ *  AT91RM9200 processor initialization
+ * -------------------------------------------------------------------- */
+void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks)
+{
+       /* Map peripherals */
        iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+
+       /* Init clock subsystem */
+       at91_clock_init(main_clock);
+
+       /* Register the processor-specific clocks */
+       at91rm9200_register_clocks();
+
+       /* Initialize GPIO subsystem */
+       at91_gpio_init(at91rm9200_gpio, banks);
 }
 
+
+/* --------------------------------------------------------------------
+ *  Interrupt initialization
+ * -------------------------------------------------------------------- */
+
 /*
  * The default interrupt priority levels (0 = lowest, 7 = highest).
  */
@@ -145,10 +283,14 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
        0       /* Advanced Interrupt Controller (IRQ6) */
 };
 
-void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
+void __init at91rm9200_init_interrupts(unsigned int priority[NR_AIC_IRQS])
 {
        if (!priority)
                priority = at91rm9200_default_irq_priority;
 
+       /* Initialize the AIC interrupt controller */
        at91_aic_init(priority);
+
+       /* Enable GPIO interrupts */
+       at91_gpio_irq_setup();
 }
index dc79e0992af71955056aa78ad2165f62d93678fc..36eecd7161f5646d64d706513433b17becc3d232 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init onearm_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(PQFP_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -62,15 +53,18 @@ static struct at91_uart_config __initdata onearm_uart_config = {
 
 static void __init onearm_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 18.432 MHz crystal */
-       at91_clock_init(18432000);
+       /* Initialize processor: 18.432 MHz crystal */
+       at91rm9200_initialize(18432000, AT91RM9200_PQFP);
 
        /* Setup the serial ports and console */
        at91_init_serial(&onearm_uart_config);
 }
 
+static void __init onearm_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata onearm_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
index 2c138b542ebe65b345fd0dae41f50c549280a9f2..50e513681ae6b1c3d897f3919cf7fed71888872c 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init carmeva_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -63,15 +54,19 @@ static struct at91_uart_config __initdata carmeva_uart_config = {
 
 static void __init carmeva_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 20.000 MHz crystal */
-       at91_clock_init(20000000);
+       /* Initialize processor: 20.000 MHz crystal */
+       at91rm9200_initialize(20000000, AT91RM9200_BGA);
 
        /* Setup the serial ports and console */
        at91_init_serial(&carmeva_uart_config);
 }
 
+static void __init carmeva_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
+
 static struct at91_eth_data __initdata carmeva_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
index 794d3fbb449ba0b3d6efe1f4985cb9a6a6fb0275..8eeae491ce712c83d714b99c8ffa72b5c58fee48 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init csb337_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -62,10 +53,8 @@ static struct at91_uart_config __initdata csb337_uart_config = {
 
 static void __init csb337_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 3.6864 MHz crystal */
-       at91_clock_init(3686400);
+       /* Initialize processor: 3.6864 MHz crystal */
+       at91rm9200_initialize(3686400, AT91RM9200_BGA);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
@@ -74,6 +63,11 @@ static void __init csb337_map_io(void)
        at91_init_serial(&csb337_uart_config);
 }
 
+static void __init csb337_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata csb337_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 0,
index c8b6f334246a9b41470e52ff3658854d760e16c2..a29fa0e822ce61af2ebec8f62b8450f89b9b0b0b 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init csb637_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -61,10 +52,8 @@ static struct at91_uart_config __initdata csb637_uart_config = {
 
 static void __init csb637_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 3.6864 MHz crystal */
-       at91_clock_init(3686400);
+       /* Initialize processor: 3.6864 MHz crystal */
+       at91rm9200_initialize(3686400, AT91RM9200_BGA);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
@@ -73,6 +62,11 @@ static void __init csb637_map_io(void)
        at91_init_serial(&csb637_uart_config);
 }
 
+static void __init csb637_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata csb637_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC0,
        .is_rmii        = 0,
index 65873037e02ad94572290e4848fb330b16b01491..c699f3984d4b086b25820257b2c6a11c9172cffd 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init dk_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -65,10 +56,8 @@ static struct at91_uart_config __initdata dk_uart_config = {
 
 static void __init dk_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 18.432 MHz crystal */
-       at91_clock_init(18432000);
+       /* Initialize processor: 18.432 MHz crystal */
+       at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
@@ -77,6 +66,11 @@ static void __init dk_map_io(void)
        at91_init_serial(&dk_uart_config);
 }
 
+static void __init dk_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata dk_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
@@ -128,6 +122,29 @@ static struct spi_board_info dk_spi_devices[] = {
 #endif
 };
 
+static struct mtd_partition __initdata dk_nand_partition[] = {
+       {
+               .name   = "NAND Partition 1",
+               .offset = 0,
+               .size   = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+       *num_partitions = ARRAY_SIZE(dk_nand_partition);
+       return dk_nand_partition;
+}
+
+static struct at91_nand_data __initdata dk_nand_data = {
+       .ale            = 22,
+       .cle            = 21,
+       .det_pin        = AT91_PIN_PB1,
+       .rdy_pin        = AT91_PIN_PC2,
+       // .enable_pin  = ... not there
+       .partition_info = nand_partitions,
+};
+
 static void __init dk_board_init(void)
 {
        /* Serial */
@@ -153,6 +170,8 @@ static void __init dk_board_init(void)
        at91_set_gpio_output(AT91_PIN_PB7, 1);  /* this MMC card slot can optionally use SPI signaling (CS3). */
        at91_add_device_mmc(&dk_mmc_data);
 #endif
+       /* NAND */
+       at91_add_device_nand(&dk_nand_data);
        /* VGA */
 //     dk_add_device_video();
 }
index a3e2df968a66b1801f62b230f86fc106d4b1a332..c6e0d51fbea0c31c0a230531b7b89c227cbb68b1 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init eb9200_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -63,15 +54,18 @@ static struct at91_uart_config __initdata eb9200_uart_config = {
 
 static void __init eb9200_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 18.432 MHz crystal */
-       at91_clock_init(18432000);
+       /* Initialize processor: 18.432 MHz crystal */
+       at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
        /* Setup the serial ports and console */
        at91_init_serial(&eb9200_uart_config);
 }
 
+static void __init eb9200_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata eb9200_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
index 868192351ddaf8dcde4af7d35100e6e1e42a9543..830eb7932178dee09e72c554cc8fddfa72e70d9f 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init ek_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(BGA_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -65,10 +56,8 @@ static struct at91_uart_config __initdata ek_uart_config = {
 
 static void __init ek_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 18.432 MHz crystal */
-       at91_clock_init(18432000);
+       /* Initialize processor: 18.432 MHz crystal */
+       at91rm9200_initialize(18432000, AT91RM9200_BGA);
 
        /* Setup the LEDs */
        at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
@@ -77,6 +66,11 @@ static void __init ek_map_io(void)
        at91_init_serial(&ek_uart_config);
 }
 
+static void __init ek_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata ek_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 1,
index bf760c5e0c469692e8ae4547b0081205eec952b6..91e301924f2cc178f8f936478ac7a4d00229e189 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init kafa_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(PQFP_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -62,10 +53,8 @@ static struct at91_uart_config __initdata kafa_uart_config = {
 
 static void __init kafa_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 18.432 MHz crystal */
-       at91_clock_init(18432000);
+       /* Initialize processor: 18.432 MHz crystal */
+       at91rm9200_initialize(18432000, AT91RM9200_PQFP);
 
        /* Set up the LEDs */
        at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
@@ -74,6 +63,11 @@ static void __init kafa_map_io(void)
        at91_init_serial(&kafa_uart_config);
 }
 
+static void __init kafa_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata kafa_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC4,
        .is_rmii        = 0,
index f06d2b54cc9a880d5d872425d6b3ca5a730a90ab..272fe43bceca0c070f90bbeed8137ae0875e8bfc 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/hardware.h>
 #include <asm/arch/board.h>
 #include <asm/arch/gpio.h>
 
 #include "generic.h"
 
-static void __init kb9202_init_irq(void)
-{
-       /* Initialize AIC controller */
-       at91rm9200_init_irq(NULL);
-
-       /* Set up the GPIO interrupts */
-       at91_gpio_irq_setup(PQFP_GPIO_BANKS);
-}
 
 /*
  * Serial port configuration.
@@ -63,10 +54,8 @@ static struct at91_uart_config __initdata kb9202_uart_config = {
 
 static void __init kb9202_map_io(void)
 {
-       at91rm9200_map_io();
-
-       /* Initialize clocks: 10 MHz crystal */
-       at91_clock_init(10000000);
+       /* Initialize processor: 10 MHz crystal */
+       at91rm9200_initialize(10000000, AT91RM9200_PQFP);
 
        /* Set up the LEDs */
        at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
@@ -75,6 +64,11 @@ static void __init kb9202_map_io(void)
        at91_init_serial(&kb9202_uart_config);
 }
 
+static void __init kb9202_init_irq(void)
+{
+       at91rm9200_init_interrupts(NULL);
+}
+
 static struct at91_eth_data __initdata kb9202_eth_data = {
        .phy_irq_pin    = AT91_PIN_PB29,
        .is_rmii        = 0,
@@ -95,6 +89,29 @@ static struct at91_mmc_data __initdata kb9202_mmc_data = {
        .wire4          = 1,
 };
 
+static struct mtd_partition __initdata kb9202_nand_partition[] = {
+       {
+               .name   = "nand_fs",
+               .offset = 0,
+               .size   = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+       *num_partitions = ARRAY_SIZE(kb9202_nand_partition);
+       return kb9202_nand_partition;
+}
+
+static struct at91_nand_data __initdata kb9202_nand_data = {
+       .ale            = 22,
+       .cle            = 21,
+       // .det_pin     = ... not there
+       .rdy_pin        = AT91_PIN_PC29,
+       .enable_pin     = AT91_PIN_PC28,
+       .partition_info = nand_partitions,
+};
+
 static void __init kb9202_board_init(void)
 {
        /* Serial */
@@ -111,6 +128,8 @@ static void __init kb9202_board_init(void)
        at91_add_device_i2c();
        /* SPI */
        at91_add_device_spi(NULL, 0);
+       /* NAND */
+       at91_add_device_nand(&kb9202_nand_data);
 }
 
 MACHINE_START(KB9200, "KB920x")
index edc2cc837ae630b34381397f69fbbf7c157cf1e3..a43b061a7c852789d404f931658217a8a4fdd6e1 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <asm/hardware.h>
 
-#include "generic.h"
+#include "clock.h"
 
 
 /*
  * PLLB be used at other rates (on boards that don't need USB), etc.
  */
 
-struct clk {
-       const char      *name;          /* unique clock name */
-       const char      *function;      /* function of the clock */
-       struct device   *dev;           /* device associated with function */
-       unsigned long   rate_hz;
-       struct clk      *parent;
-       u32             pmc_mask;
-       void            (*mode)(struct clk *, int);
-       unsigned        id:2;           /* PCK0..3, or 32k/main/a/b */
-       unsigned        primary:1;
-       unsigned        pll:1;
-       unsigned        programmable:1;
-       u16             users;
-};
+#define clk_is_primary(x)      ((x)->type & CLK_TYPE_PRIMARY)
+#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
+#define clk_is_peripheral(x)   ((x)->type & CLK_TYPE_PERIPHERAL)
+
+
+static LIST_HEAD(clocks);
+static DEFINE_SPINLOCK(clk_lock);
 
-static spinlock_t      clk_lock;
-static u32             at91_pllb_usb_init;
+static u32 at91_pllb_usb_init;
 
 /*
  * Four primary clock sources:  two crystal oscillators (32K, main), and
@@ -67,21 +59,20 @@ static struct clk clk32k = {
        .rate_hz        = AT91_SLOW_CLOCK,
        .users          = 1,            /* always on */
        .id             = 0,
-       .primary        = 1,
+       .type           = CLK_TYPE_PRIMARY,
 };
 static struct clk main_clk = {
        .name           = "main",
        .pmc_mask       = AT91_PMC_MOSCS,       /* in PMC_SR */
        .id             = 1,
-       .primary        = 1,
+       .type           = CLK_TYPE_PRIMARY,
 };
 static struct clk plla = {
        .name           = "plla",
        .parent         = &main_clk,
        .pmc_mask       = AT91_PMC_LOCKA,       /* in PMC_SR */
        .id             = 2,
-       .primary        = 1,
-       .pll            = 1,
+       .type           = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
 };
 
 static void pllb_mode(struct clk *clk, int is_on)
@@ -94,6 +85,7 @@ static void pllb_mode(struct clk *clk, int is_on)
        } else
                value = 0;
 
+       // REVISIT: Add work-around for AT91RM9200 Errata #26 ?
        at91_sys_write(AT91_CKGR_PLLBR, value);
 
        do {
@@ -107,8 +99,7 @@ static struct clk pllb = {
        .pmc_mask       = AT91_PMC_LOCKB,       /* in PMC_SR */
        .mode           = pllb_mode,
        .id             = 3,
-       .primary        = 1,
-       .pll            = 1,
+       .type           = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
 };
 
 static void pmc_sys_mode(struct clk *clk, int is_on)
@@ -133,41 +124,6 @@ static struct clk uhpck = {
        .mode           = pmc_sys_mode,
 };
 
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-/*
- * The four programmable clocks can be parented by any primary clock.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .mode           = pmc_sys_mode,
-       .programmable   = 1,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .mode           = pmc_sys_mode,
-       .programmable   = 1,
-       .id             = 1,
-};
-static struct clk pck2 = {
-       .name           = "pck2",
-       .pmc_mask       = AT91_PMC_PCK2,
-       .mode           = pmc_sys_mode,
-       .programmable   = 1,
-       .id             = 2,
-};
-static struct clk pck3 = {
-       .name           = "pck3",
-       .pmc_mask       = AT91_PMC_PCK3,
-       .mode           = pmc_sys_mode,
-       .programmable   = 1,
-       .id             = 3,
-};
-#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
-
 
 /*
  * The master clock is divided from the CPU clock (by 1-4).  It's used for
@@ -187,131 +143,21 @@ static void pmc_periph_mode(struct clk *clk, int is_on)
                at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
 }
 
-static struct clk udc_clk = {
-       .name           = "udc_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_UDP,
-       .mode           = pmc_periph_mode,
-};
-static struct clk ohci_clk = {
-       .name           = "ohci_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_UHP,
-       .mode           = pmc_periph_mode,
-};
-static struct clk ether_clk = {
-       .name           = "ether_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_EMAC,
-       .mode           = pmc_periph_mode,
-};
-static struct clk mmc_clk = {
-       .name           = "mci_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_MCI,
-       .mode           = pmc_periph_mode,
-};
-static struct clk twi_clk = {
-       .name           = "twi_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_TWI,
-       .mode           = pmc_periph_mode,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_US0,
-       .mode           = pmc_periph_mode,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_US1,
-       .mode           = pmc_periph_mode,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_US2,
-       .mode           = pmc_periph_mode,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_US3,
-       .mode           = pmc_periph_mode,
-};
-static struct clk spi_clk = {
-       .name           = "spi0_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_SPI,
-       .mode           = pmc_periph_mode,
-};
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_PIOA,
-       .mode           = pmc_periph_mode,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_PIOB,
-       .mode           = pmc_periph_mode,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_PIOC,
-       .mode           = pmc_periph_mode,
-};
-static struct clk pioD_clk = {
-       .name           = "pioD_clk",
-       .parent         = &mck,
-       .pmc_mask       = 1 << AT91_ID_PIOD,
-       .mode           = pmc_periph_mode,
-};
-
-static struct clk *const clock_list[] = {
-       /* four primary clocks -- MUST BE FIRST! */
-       &clk32k,
-       &main_clk,
-       &plla,
-       &pllb,
-
-       /* PLLB children (USB) */
-       &udpck,
-       &uhpck,
-
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-       /* programmable clocks */
-       &pck0,
-       &pck1,
-       &pck2,
-       &pck3,
-#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
-
-       /* MCK and peripherals */
-       &mck,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &usart3_clk,
-       &mmc_clk,
-       &udc_clk,
-       &twi_clk,
-       &spi_clk,
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &pioD_clk,
-       // ssc0..ssc2
-       // tc0..tc5
-       // irq0..irq6
-       &ohci_clk,
-       &ether_clk,
-};
+static struct clk __init *at91_css_to_clk(unsigned long css)
+{
+       switch (css) {
+               case AT91_PMC_CSS_SLOW:
+                       return &clk32k;
+               case AT91_PMC_CSS_MAIN:
+                       return &main_clk;
+               case AT91_PMC_CSS_PLLA:
+                       return &plla;
+               case AT91_PMC_CSS_PLLB:
+                       return &pllb;
+       }
 
+       return NULL;
+}
 
 /*
  * Associate a particular clock with a function (eg, "uart") and device.
@@ -329,14 +175,12 @@ void __init at91_clock_associate(const char *id, struct device *dev, const char
        clk->dev = dev;
 }
 
-/* clocks are all static for now; no refcounting necessary */
+/* clocks cannot be de-registered no refcounting necessary */
 struct clk *clk_get(struct device *dev, const char *id)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-               struct clk *clk = clock_list[i];
+       struct clk *clk;
 
+       list_for_each_entry(clk, &clocks, node) {
                if (strcmp(id, clk->name) == 0)
                        return clk;
                if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
@@ -424,7 +268,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
        unsigned        prescale;
        unsigned long   actual;
 
-       if (!clk->programmable)
+       if (!clk_is_programmable(clk))
                return -EINVAL;
        spin_lock_irqsave(&clk_lock, flags);
 
@@ -446,7 +290,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
        unsigned        prescale;
        unsigned long   actual;
 
-       if (!clk->programmable)
+       if (!clk_is_programmable(clk))
                return -EINVAL;
        if (clk->users)
                return -EBUSY;
@@ -484,7 +328,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 
        if (clk->users)
                return -EBUSY;
-       if (!parent->primary || !clk->programmable)
+       if (!clk_is_primary(parent) || !clk_is_programmable(clk))
                return -EINVAL;
        spin_lock_irqsave(&clk_lock, flags);
 
@@ -497,6 +341,18 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 }
 EXPORT_SYMBOL(clk_set_parent);
 
+/* establish PCK0..PCK3 parentage and rate */
+static void init_programmable_clock(struct clk *clk)
+{
+       struct clk      *parent;
+       u32             pckr;
+
+       pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+       parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
+       clk->parent = parent;
+       clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+}
+
 #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
 
 /*------------------------------------------------------------------------*/
@@ -506,6 +362,7 @@ EXPORT_SYMBOL(clk_set_parent);
 static int at91_clk_show(struct seq_file *s, void *unused)
 {
        u32             scsr, pcsr, sr;
+       struct clk      *clk;
        unsigned        i;
 
        seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
@@ -523,9 +380,8 @@ static int at91_clk_show(struct seq_file *s, void *unused)
 
        seq_printf(s, "\n");
 
-       for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-               char            *state;
-               struct clk      *clk = clock_list[i];
+       list_for_each_entry(clk, &clocks, node) {
+               char    *state;
 
                if (clk->mode == pmc_sys_mode)
                        state = (scsr & clk->pmc_mask) ? "on" : "off";
@@ -568,6 +424,28 @@ postcore_initcall(at91_clk_debugfs_init);
 
 #endif
 
+/*------------------------------------------------------------------------*/
+
+/* Register a new clock */
+int __init clk_register(struct clk *clk)
+{
+       if (clk_is_peripheral(clk)) {
+               clk->parent = &mck;
+               clk->mode = pmc_periph_mode;
+               list_add_tail(&clk->node, &clocks);
+       }
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+       else if (clk_is_programmable(clk)) {
+               clk->mode = pmc_sys_mode;
+               init_programmable_clock(clk);
+               list_add_tail(&clk->node, &clocks);
+       }
+#endif
+
+       return 0;
+}
+
+
 /*------------------------------------------------------------------------*/
 
 static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
@@ -640,20 +518,17 @@ fail:
        return 0;
 }
 
-
 /*
  * Several unused clocks may be active.  Turn them off.
  */
-static void at91_periphclk_reset(void)
+static void __init at91_periphclk_reset(void)
 {
        unsigned long reg;
-       int i;
+       struct clk *clk;
 
        reg = at91_sys_read(AT91_PMC_PCSR);
 
-       for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-               struct clk      *clk = clock_list[i];
-
+       list_for_each_entry(clk, &clocks, node) {
                if (clk->mode != pmc_periph_mode)
                        continue;
 
@@ -664,11 +539,25 @@ static void at91_periphclk_reset(void)
        at91_sys_write(AT91_PMC_PCDR, reg);
 }
 
+static struct clk *const standard_pmc_clocks[] __initdata = {
+       /* four primary clocks */
+       &clk32k,
+       &main_clk,
+       &plla,
+       &pllb,
+
+       /* PLLB children (USB) */
+       &udpck,
+       &uhpck,
+
+       /* MCK */
+       &mck
+};
+
 int __init at91_clock_init(unsigned long main_clock)
 {
        unsigned tmp, freq, mckr;
-
-       spin_lock_init(&clk_lock);
+       int i;
 
        /*
         * When the bootloader initialized the main oscillator correctly,
@@ -709,11 +598,15 @@ int __init at91_clock_init(unsigned long main_clock)
         * For now, assume this parentage won't change.
         */
        mckr = at91_sys_read(AT91_PMC_MCKR);
-       mck.parent = clock_list[mckr & AT91_PMC_CSS];
+       mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
        freq = mck.parent->rate_hz;
        freq /= (1 << ((mckr >> 2) & 3));               /* prescale */
        mck.rate_hz = freq / (1 + ((mckr >> 8) & 3));   /* mdiv */
 
+       /* Register the PMC's standard clocks */
+       for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
+               list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
+
        /* MCK and CPU clock are "always on" */
        clk_enable(&mck);
 
@@ -722,35 +615,8 @@ int __init at91_clock_init(unsigned long main_clock)
                (unsigned) main_clock / 1000000,
                ((unsigned) main_clock % 1000000) / 1000);
 
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-       /* establish PCK0..PCK3 parentage */
-       for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
-               struct clk      *clk = clock_list[tmp], *parent;
-               u32             pckr;
-
-               if (!clk->programmable)
-                       continue;
-
-               pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-               parent = clock_list[pckr & AT91_PMC_CSS];
-               clk->parent = parent;
-               clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
-
-               if (clk->users == 0) {
-                       /* not being used, so switch it off */
-                       at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
-               }
-       }
-#else
        /* disable all programmable clocks */
        at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
-#endif
-
-       /* enable the PIO clocks */
-       clk_enable(&pioA_clk);
-       clk_enable(&pioB_clk);
-       clk_enable(&pioC_clk);
-       clk_enable(&pioD_clk);
 
        /* disable all other unused peripheral clocks */
        at91_periphclk_reset();
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91rm9200/clock.h
new file mode 100644 (file)
index 0000000..0592e66
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/clock.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
+ * published by the Free Software Foundation.
+ */
+
+#define CLK_TYPE_PRIMARY       0x1
+#define CLK_TYPE_PLL           0x2
+#define CLK_TYPE_PROGRAMMABLE  0x4
+#define CLK_TYPE_PERIPHERAL    0x8
+
+
+struct clk {
+       struct list_head node;
+       const char      *name;          /* unique clock name */
+       const char      *function;      /* function of the clock */
+       struct device   *dev;           /* device associated with function */
+       unsigned long   rate_hz;
+       struct clk      *parent;
+       u32             pmc_mask;
+       void            (*mode)(struct clk *, int);
+       unsigned        id:2;           /* PCK0..3, or 32k/main/a/b */
+       unsigned        type;           /* clock type */
+       u16             users;
+};
+
+
+extern int __init clk_register(struct clk *clk);
index 4352acb88178a6930c1a0a39c6f76cda1f0c355d..01525530c287df93f1686a0985c351da25c495ab 100644 (file)
@@ -35,13 +35,13 @@ static struct at91_usbh_data usbh_data;
 
 static struct resource at91_usbh_resources[] = {
        [0] = {
-               .start  = AT91_UHP_BASE,
-               .end    = AT91_UHP_BASE + SZ_1M - 1,
+               .start  = AT91RM9200_UHP_BASE,
+               .end    = AT91RM9200_UHP_BASE + SZ_1M - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_UHP,
-               .end    = AT91_ID_UHP,
+               .start  = AT91RM9200_ID_UHP,
+               .end    = AT91RM9200_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -80,13 +80,13 @@ static struct at91_udc_data udc_data;
 
 static struct resource at91_udc_resources[] = {
        [0] = {
-               .start  = AT91_BASE_UDP,
-               .end    = AT91_BASE_UDP + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_UDP,
+               .end    = AT91RM9200_BASE_UDP + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_UDP,
-               .end    = AT91_ID_UDP,
+               .start  = AT91RM9200_ID_UDP,
+               .end    = AT91RM9200_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -131,13 +131,13 @@ static struct at91_eth_data eth_data;
 
 static struct resource at91_eth_resources[] = {
        [0] = {
-               .start  = AT91_BASE_EMAC,
-               .end    = AT91_BASE_EMAC + SZ_16K - 1,
+               .start  = AT91_VA_BASE_EMAC,
+               .end    = AT91_VA_BASE_EMAC + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_EMAC,
-               .end    = AT91_ID_EMAC,
+               .start  = AT91RM9200_ID_EMAC,
+               .end    = AT91RM9200_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -263,13 +263,13 @@ static struct at91_mmc_data mmc_data;
 
 static struct resource at91_mmc_resources[] = {
        [0] = {
-               .start  = AT91_BASE_MCI,
-               .end    = AT91_BASE_MCI + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_MCI,
+               .end    = AT91RM9200_BASE_MCI + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_MCI,
-               .end    = AT91_ID_MCI,
+               .start  = AT91RM9200_ID_MCI,
+               .end    = AT91RM9200_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -423,13 +423,13 @@ static u64 spi_dmamask = 0xffffffffUL;
 
 static struct resource at91_spi_resources[] = {
        [0] = {
-               .start  = AT91_BASE_SPI,
-               .end    = AT91_BASE_SPI + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_SPI,
+               .end    = AT91RM9200_BASE_SPI + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SPI,
-               .end    = AT91_ID_SPI,
+               .start  = AT91RM9200_ID_SPI,
+               .end    = AT91RM9200_ID_SPI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -582,13 +582,13 @@ static inline void configure_dbgu_pins(void)
 
 static struct resource uart0_resources[] = {
        [0] = {
-               .start  = AT91_BASE_US0,
-               .end    = AT91_BASE_US0 + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_US0,
+               .end    = AT91RM9200_BASE_US0 + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_US0,
-               .end    = AT91_ID_US0,
+               .start  = AT91RM9200_ID_US0,
+               .end    = AT91RM9200_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -624,13 +624,13 @@ static inline void configure_usart0_pins(void)
 
 static struct resource uart1_resources[] = {
        [0] = {
-               .start  = AT91_BASE_US1,
-               .end    = AT91_BASE_US1 + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_US1,
+               .end    = AT91RM9200_BASE_US1 + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_US1,
-               .end    = AT91_ID_US1,
+               .start  = AT91RM9200_ID_US1,
+               .end    = AT91RM9200_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -665,13 +665,13 @@ static inline void configure_usart1_pins(void)
 
 static struct resource uart2_resources[] = {
        [0] = {
-               .start  = AT91_BASE_US2,
-               .end    = AT91_BASE_US2 + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_US2,
+               .end    = AT91RM9200_BASE_US2 + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_US2,
-               .end    = AT91_ID_US2,
+               .start  = AT91RM9200_ID_US2,
+               .end    = AT91RM9200_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -700,13 +700,13 @@ static inline void configure_usart2_pins(void)
 
 static struct resource uart3_resources[] = {
        [0] = {
-               .start  = AT91_BASE_US3,
-               .end    = AT91_BASE_US3 + SZ_16K - 1,
+               .start  = AT91RM9200_BASE_US3,
+               .end    = AT91RM9200_BASE_US3 + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_US3,
-               .end    = AT91_ID_US3,
+               .start  = AT91RM9200_ID_US3,
+               .end    = AT91RM9200_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 7979d8ab7e07bebe75828d3eaf8c6567682f67c4..694e411e285f6933254ccbf077c2aa69c50a2237 100644 (file)
@@ -8,18 +8,17 @@
  * published by the Free Software Foundation.
  */
 
+ /* Processors */
+extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
+
  /* Interrupts */
-extern void __init at91rm9200_init_irq(unsigned int priority[]);
+extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
-extern void __init at91_gpio_irq_setup(unsigned banks);
 
  /* Timer */
 struct sys_timer;
 extern struct sys_timer at91rm9200_timer;
 
- /* Memory Map */
-extern void __init at91rm9200_map_io(void);
-
  /* Clocks */
 extern int __init at91_clock_init(unsigned long main_clock);
 struct device;
@@ -29,3 +28,14 @@ extern void __init at91_clock_associate(const char *id, struct device *dev, cons
 extern void at91_irq_suspend(void);
 extern void at91_irq_resume(void);
 
+ /* GPIO */
+#define AT91RM9200_PQFP                3       /* AT91RM9200 PQFP package has 3 banks */
+#define AT91RM9200_BGA         4       /* AT91RM9200 BGA package has 4 banks */
+
+struct at91_gpio_bank {
+       unsigned short id;              /* peripheral ID */
+       unsigned long offset;           /* offset from system peripheral base */
+       struct clk *clock;              /* associated clock */
+};
+extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
+extern void __init at91_gpio_irq_setup(void);
index cec199fd67217bd171303762431843a6722354c8..58c9bf5e95205f1e4ecbed09d85b175f284a5a22 100644 (file)
@@ -9,6 +9,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/hardware.h>
 #include <asm/arch/gpio.h>
 
-static const u32 pio_controller_offset[4] = {
-       AT91_PIOA,
-       AT91_PIOB,
-       AT91_PIOC,
-       AT91_PIOD,
-};
+#include "generic.h"
+
+
+static struct at91_gpio_bank *gpio;
+static int gpio_banks;
+
 
 static inline void __iomem *pin_to_controller(unsigned pin)
 {
@@ -33,8 +34,8 @@ static inline void __iomem *pin_to_controller(unsigned pin)
 
        pin -= PIN_BASE;
        pin /= 32;
-       if (likely(pin < BGA_GPIO_BANKS))
-               return sys_base + pio_controller_offset[pin];
+       if (likely(pin < gpio_banks))
+               return sys_base + gpio[pin].offset;
 
        return NULL;
 }
@@ -179,7 +180,6 @@ EXPORT_SYMBOL(at91_set_multi_drive);
 
 /*--------------------------------------------------------------------------*/
 
-
 /*
  * assuming the pin is muxed as a gpio output, set its value.
  */
@@ -216,8 +216,8 @@ EXPORT_SYMBOL(at91_get_gpio_value);
 
 #ifdef CONFIG_PM
 
-static u32 wakeups[BGA_GPIO_BANKS];
-static u32 backups[BGA_GPIO_BANKS];
+static u32 wakeups[MAX_GPIO_BANKS];
+static u32 backups[MAX_GPIO_BANKS];
 
 static int gpio_irq_set_wake(unsigned pin, unsigned state)
 {
@@ -226,7 +226,7 @@ static int gpio_irq_set_wake(unsigned pin, unsigned state)
        pin -= PIN_BASE;
        pin /= 32;
 
-       if (unlikely(pin >= BGA_GPIO_BANKS))
+       if (unlikely(pin >= MAX_GPIO_BANKS))
                return -EINVAL;
 
        if (state)
@@ -241,8 +241,8 @@ void at91_gpio_suspend(void)
 {
        int i;
 
-       for (i = 0; i < BGA_GPIO_BANKS; i++) {
-               u32 pio = pio_controller_offset[i];
+       for (i = 0; i < gpio_banks; i++) {
+               u32 pio = gpio[i].offset;
 
                /*
                 * Note: drivers should have disabled GPIO interrupts that
@@ -257,14 +257,14 @@ void at91_gpio_suspend(void)
                 * first place!
                 */
                backups[i] = at91_sys_read(pio + PIO_IMR);
-               at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]);
-               at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]);
+               at91_sys_write(pio + PIO_IDR, backups[i]);
+               at91_sys_write(pio + PIO_IER, wakeups[i]);
 
                if (!wakeups[i]) {
-                       disable_irq_wake(AT91_ID_PIOA + i);
-                       at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i));
+                       disable_irq_wake(gpio[i].id);
+                       at91_sys_write(AT91_PMC_PCDR, 1 << gpio[i].id);
                } else {
-                       enable_irq_wake(AT91_ID_PIOA + i);
+                       enable_irq_wake(gpio[i].id);
 #ifdef CONFIG_PM_DEBUG
                        printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]);
 #endif
@@ -276,16 +276,13 @@ void at91_gpio_resume(void)
 {
        int i;
 
-       for (i = 0; i < BGA_GPIO_BANKS; i++) {
-               at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]);
-               at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]);
-       }
+       for (i = 0; i < gpio_banks; i++) {
+               u32 pio = gpio[i].offset;
 
-       at91_sys_write(AT91_PMC_PCER,
-                         (1 << AT91_ID_PIOA)
-                       | (1 << AT91_ID_PIOB)
-                       | (1 << AT91_ID_PIOC)
-                       | (1 << AT91_ID_PIOD));
+               at91_sys_write(pio + PIO_IDR, wakeups[i]);
+               at91_sys_write(pio + PIO_IER, backups[i]);
+               at91_sys_write(AT91_PMC_PCER, 1 << gpio[i].id);
+       }
 }
 
 #else
@@ -377,20 +374,25 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs
        /* now it may re-trigger */
 }
 
-/* call this from board-specific init_irq */
-void __init at91_gpio_irq_setup(unsigned banks)
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Called from the processor-specific init to enable GPIO interrupt support.
+ */
+void __init at91_gpio_irq_setup(void)
 {
-       unsigned        pioc, pin, id;
+       unsigned        pioc, pin;
 
-       if (banks > 4)
-               banks = 4;
-       for (pioc = 0, pin = PIN_BASE, id = AT91_ID_PIOA;
-                       pioc < banks;
-                       pioc++, id++) {
+       for (pioc = 0, pin = PIN_BASE;
+                       pioc < gpio_banks;
+                       pioc++) {
                void __iomem    *controller;
+               unsigned        id = gpio[pioc].id;
                unsigned        i;
 
-               controller = (void __iomem *) AT91_VA_BASE_SYS + pio_controller_offset[pioc];
+               clk_enable(gpio[pioc].clock);   /* enable PIO controller's clock */
+
+               controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
                __raw_writel(~0, controller + PIO_IDR);
 
                set_irq_data(id, (void *) pin);
@@ -408,5 +410,16 @@ void __init at91_gpio_irq_setup(unsigned banks)
 
                set_irq_chained_handler(id, gpio_irq_handler);
        }
-       pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks);
+       pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
+}
+
+/*
+ * Called from the processor-specific init to enable GPIO pin support.
+ */
+void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
+{
+       BUG_ON(nr_banks > MAX_GPIO_BANKS);
+
+       gpio = data;
+       gpio_banks = nr_banks;
 }
index c3a5e777f9f8c3753656b59a3e3c42dfc9ebc86a..3e488117ca91bb2154d992c9bd815d0d619750f2 100644 (file)
@@ -34,8 +34,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include "generic.h"
-
 
 static void at91_aic_mask_irq(unsigned int irq)
 {
@@ -61,12 +59,12 @@ static int at91_aic_set_type(unsigned irq, unsigned type)
                srctype = AT91_AIC_SRCTYPE_RISING;
                break;
        case IRQT_LOW:
-               if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))        /* only supported on external interrupts */
+               if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0))  /* only supported on external interrupts */
                        return -EINVAL;
                srctype = AT91_AIC_SRCTYPE_LOW;
                break;
        case IRQT_FALLING:
-               if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))        /* only supported on external interrupts */
+               if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0))  /* only supported on external interrupts */
                        return -EINVAL;
                srctype = AT91_AIC_SRCTYPE_FALLING;
                break;
index 47e5480feb7eef279a6c5a8b5a748b7f4c1dee19..32c95d8eaacf3dabe0866f9603104534b43839eb 100644 (file)
@@ -123,13 +123,13 @@ static int at91_pm_enter(suspend_state_t state)
                        (at91_sys_read(AT91_PMC_PCSR)
                                        | (1 << AT91_ID_FIQ)
                                        | (1 << AT91_ID_SYS)
-                                       | (1 << AT91_ID_IRQ0)
-                                       | (1 << AT91_ID_IRQ1)
-                                       | (1 << AT91_ID_IRQ2)
-                                       | (1 << AT91_ID_IRQ3)
-                                       | (1 << AT91_ID_IRQ4)
-                                       | (1 << AT91_ID_IRQ5)
-                                       | (1 << AT91_ID_IRQ6))
+                                       | (1 << AT91RM9200_ID_IRQ0)
+                                       | (1 << AT91RM9200_ID_IRQ1)
+                                       | (1 << AT91RM9200_ID_IRQ2)
+                                       | (1 << AT91RM9200_ID_IRQ3)
+                                       | (1 << AT91RM9200_ID_IRQ4)
+                                       | (1 << AT91RM9200_ID_IRQ5)
+                                       | (1 << AT91RM9200_ID_IRQ6))
                                & at91_sys_read(AT91_AIC_IMR),
                        state);
 
index f1b740083aee5dfc30967a09540614ddfeb714f9..e346b03cd92114ed29ef44770de626c404e4df34 100644 (file)
@@ -15,6 +15,12 @@ config MACH_EDB9302
          Say 'Y' here if you want your kernel to support the Cirrus
          Logic EDB9302 Evaluation Board.
 
+config MACH_EDB9312
+       bool "Support Cirrus Logic EDB9312"
+       help
+         Say 'Y' here if you want your kernel to support the Cirrus
+         Logic EDB9312 Evaluation Board.
+
 config MACH_EDB9315
        bool "Support Cirrus Logic EDB9315"
        help
index 1f5a6b0487ee542e43dd5e4498f0422fcd68712e..c2eb18b530c2d0367be36a4e86fb01105a83e552 100644 (file)
@@ -7,6 +7,7 @@ obj-n                   :=
 obj-                   :=
 
 obj-$(CONFIG_MACH_EDB9302)     += edb9302.o
+obj-$(CONFIG_MACH_EDB9312)     += edb9312.o
 obj-$(CONFIG_MACH_EDB9315)     += edb9315.o
 obj-$(CONFIG_MACH_EDB9315A)    += edb9315a.o
 obj-$(CONFIG_MACH_GESBC9312)   += gesbc9312.o
diff --git a/arch/arm/mach-ep93xx/edb9312.c b/arch/arm/mach-ep93xx/edb9312.c
new file mode 100644 (file)
index 0000000..9e39921
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/arm/mach-ep93xx/edb9312.c
+ * Cirrus Logic EDB9312 support.
+ *
+ * Copyright (C) 2006 Infosys Technologies Limited
+ *     Toufeeq Hussain <toufeeq_hussain@infosys.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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9312_flash_data = {
+       .width          = 4,
+};
+
+static struct resource edb9312_flash_resource = {
+       .start          = 0x60000000,
+       .end            = 0x61ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device edb9312_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &edb9312_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &edb9312_flash_resource,
+};
+
+static void __init edb9312_init_machine(void)
+{
+       ep93xx_init_devices();
+       platform_device_register(&edb9312_flash);
+}
+
+MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
+       /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = edb9312_init_machine,
+MACHINE_END
index 823e25d4547e8b0b7a0ad26b51844c93df290492..a1ae49df5c3be95c6ba23070a7369ee56b173a4c 100644 (file)
@@ -69,16 +69,16 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
        if (addr)
                switch (size) {
                case 1:
-                       asm("ldr%?b     %0, [%1, %2]"
-                               : "=r" (v) : "r" (addr), "r" (where));
+                       asm("ldrb       %0, [%1, %2]"
+                               : "=r" (v) : "r" (addr), "r" (where) : "cc");
                        break;
                case 2:
-                       asm("ldr%?h     %0, [%1, %2]"
-                               : "=r" (v) : "r" (addr), "r" (where));
+                       asm("ldrh       %0, [%1, %2]"
+                               : "=r" (v) : "r" (addr), "r" (where) : "cc");
                        break;
                case 4:
-                       asm("ldr%?      %0, [%1, %2]"
-                               : "=r" (v) : "r" (addr), "r" (where));
+                       asm("ldr        %0, [%1, %2]"
+                               : "=r" (v) : "r" (addr), "r" (where) : "cc");
                        break;
                }
 
@@ -103,16 +103,19 @@ dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
        if (addr)
                switch (size) {
                case 1:
-                       asm("str%?b     %0, [%1, %2]"
-                               : : "r" (value), "r" (addr), "r" (where));
+                       asm("strb       %0, [%1, %2]"
+                               : : "r" (value), "r" (addr), "r" (where)
+                               : "cc");
                        break;
                case 2:
-                       asm("str%?h     %0, [%1, %2]"
-                               : : "r" (value), "r" (addr), "r" (where));
+                       asm("strh       %0, [%1, %2]"
+                               : : "r" (value), "r" (addr), "r" (where)
+                               : "cc");
                        break;
                case 4:
-                       asm("str%?      %0, [%1, %2]"
-                               : : "r" (value), "r" (addr), "r" (where));
+                       asm("str        %0, [%1, %2]"
+                               : : "r" (value), "r" (addr), "r" (where)
+                               : "cc");
                        break;
                }
 
diff --git a/arch/arm/mach-iop32x/Kconfig b/arch/arm/mach-iop32x/Kconfig
new file mode 100644 (file)
index 0000000..c072d94
--- /dev/null
@@ -0,0 +1,35 @@
+if ARCH_IOP32X
+
+menu "IOP32x Implementation Options"
+
+comment "IOP32x Platform Types"
+
+config MACH_GLANTANK
+       bool "Enable support for the IO-Data GLAN Tank"
+       help
+         Say Y here if you want to run your kernel on the GLAN Tank
+         NAS appliance or machines from IO-Data's HDL-Gxxx, HDL-GWxxx
+         and HDL-GZxxx series.
+
+config ARCH_IQ80321
+       bool "Enable support for IQ80321"
+       help
+         Say Y here if you want to run your kernel on the Intel IQ80321
+         evaluation kit for the IOP321 processor.
+
+config ARCH_IQ31244
+       bool "Enable support for EP80219/IQ31244"
+       help
+         Say Y here if you want to run your kernel on the Intel EP80219
+         evaluation kit for the Intel 80219 processor (a IOP321 variant)
+         or the IQ31244 evaluation kit for the IOP321 processor.
+
+config MACH_N2100
+       bool "Enable support for the Thecus n2100"
+       help
+         Say Y here if you want to run your kernel on the Thecus n2100
+         NAS appliance.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-iop32x/Makefile b/arch/arm/mach-iop32x/Makefile
new file mode 100644 (file)
index 0000000..7b05b37
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                  := irq.o
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
+
+obj-$(CONFIG_MACH_GLANTANK) += glantank.o
+obj-$(CONFIG_ARCH_IQ80321) += iq80321.o
+obj-$(CONFIG_ARCH_IQ31244) += iq31244.o
+obj-$(CONFIG_MACH_N2100) += n2100.o
diff --git a/arch/arm/mach-iop32x/Makefile.boot b/arch/arm/mach-iop32x/Makefile.boot
new file mode 100644 (file)
index 0000000..47000dc
--- /dev/null
@@ -0,0 +1,3 @@
+   zreladdr-y  := 0xa0008000
+params_phys-y  := 0xa0000100
+initrd_phys-y  := 0xa0800000
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
new file mode 100644 (file)
index 0000000..b9b7650
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * arch/arm/mach-iop32x/glantank.c
+ *
+ * Board support code for the GLAN Tank.
+ *
+ * Copyright (C) 2006 Martin Michlmayr <tbm@cyrius.com>
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+
+/*
+ * GLAN Tank timer tick configuration.
+ */
+static void __init glantank_timer_init(void)
+{
+       /* 33.333 MHz crystal.  */
+       iop3xx_init_time(200000000);
+}
+
+static struct sys_timer glantank_timer = {
+       .init           = glantank_timer_init,
+       .offset         = iop3xx_gettimeoffset,
+};
+
+
+/*
+ * GLAN Tank I/O.
+ */
+static struct map_desc glantank_io_desc[] __initdata = {
+       {       /* on-board devices */
+               .virtual        = GLANTANK_UART,
+               .pfn            = __phys_to_pfn(GLANTANK_UART),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       },
+};
+
+void __init glantank_map_io(void)
+{
+       iop3xx_map_io();
+       iotable_init(glantank_io_desc, ARRAY_SIZE(glantank_io_desc));
+}
+
+
+/*
+ * GLAN Tank PCI.
+ */
+#define INTA   IRQ_IOP32X_XINT0
+#define INTB   IRQ_IOP32X_XINT1
+#define INTC   IRQ_IOP32X_XINT2
+#define INTD   IRQ_IOP32X_XINT3
+
+static inline int __init
+glantank_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       static int pci_irq_table[][4] = {
+               /*
+                * PCI IDSEL/INTPIN->INTLINE
+                * A       B       C       D
+                */
+               {INTD, INTD, INTD, INTD}, /* UART (8250) */
+               {INTA, INTA, INTA, INTA}, /* Ethernet (E1000) */
+               {INTB, INTB, INTB, INTB}, /* IDE (AEC6280R) */
+               {INTC, INTC, INTC, INTC}, /* USB (NEC) */
+       };
+
+       BUG_ON(pin < 1 || pin > 4);
+
+       return pci_irq_table[slot % 4][pin - 1];
+}
+
+static struct hw_pci glantank_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = glantank_pci_map_irq,
+};
+
+static int __init glantank_pci_init(void)
+{
+       if (machine_is_glantank())
+               pci_common_init(&glantank_pci);
+
+       return 0;
+}
+
+subsys_initcall(glantank_pci_init);
+
+
+/*
+ * GLAN Tank machine initialization.
+ */
+static struct physmap_flash_data glantank_flash_data = {
+       .width          = 1,
+};
+
+static struct resource glantank_flash_resource = {
+       .start          = 0xf0000000,
+       .end            = 0xf007ffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device glantank_flash_device = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &glantank_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &glantank_flash_resource,
+};
+
+static struct plat_serial8250_port glantank_serial_port[] = {
+       {
+               .mapbase        = GLANTANK_UART,
+               .membase        = (char *)GLANTANK_UART,
+               .irq            = IRQ_IOP32X_XINT3,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 0,
+               .uartclk        = 1843200,
+       },
+       { },
+};
+
+static struct resource glantank_uart_resource = {
+       .start          = GLANTANK_UART,
+       .end            = GLANTANK_UART + 7,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device glantank_serial_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev            = {
+               .platform_data          = glantank_serial_port,
+       },
+       .num_resources  = 1,
+       .resource       = &glantank_uart_resource,
+};
+
+static void glantank_power_off(void)
+{
+       __raw_writeb(0x01, 0xfe8d0004);
+
+       while (1)
+               ;
+}
+
+static void __init glantank_init_machine(void)
+{
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&glantank_flash_device);
+       platform_device_register(&glantank_serial_device);
+
+       pm_power_off = glantank_power_off;
+}
+
+MACHINE_START(GLANTANK, "GLAN Tank")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = GLANTANK_UART,
+       .io_pg_offst    = ((GLANTANK_UART) >> 18) & 0xfffc,
+       .boot_params    = 0xa0000100,
+       .map_io         = glantank_map_io,
+       .init_irq       = iop32x_init_irq,
+       .timer          = &glantank_timer,
+       .init_machine   = glantank_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
new file mode 100644 (file)
index 0000000..be4aedf
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * arch/arm/mach-iop32x/iq31244.c
+ *
+ * Board support code for the Intel EP80219 and IQ31244 platforms.
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright 2003 (c) MontaVista, Software, Inc.
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+
+/*
+ * The EP80219 and IQ31244 use the same machine ID.  To find out
+ * which of the two we're running on, we look at the processor ID.
+ */
+static int is_80219(void)
+{
+       extern int processor_id;
+       return !!((processor_id & 0xffffffe0) == 0x69052e20);
+}
+
+
+/*
+ * EP80219/IQ31244 timer tick configuration.
+ */
+static void __init iq31244_timer_init(void)
+{
+       if (is_80219()) {
+               /* 33.333 MHz crystal.  */
+               iop3xx_init_time(200000000);
+       } else {
+               /* 33.000 MHz crystal.  */
+               iop3xx_init_time(198000000);
+       }
+}
+
+static struct sys_timer iq31244_timer = {
+       .init           = iq31244_timer_init,
+       .offset         = iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ31244 I/O.
+ */
+static struct map_desc iq31244_io_desc[] __initdata = {
+       {       /* on-board devices */
+               .virtual        = IQ31244_UART,
+               .pfn            = __phys_to_pfn(IQ31244_UART),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init iq31244_map_io(void)
+{
+       iop3xx_map_io();
+       iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
+}
+
+
+/*
+ * EP80219/IQ31244 PCI.
+ */
+static inline int __init
+ep80219_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if (slot == 0) {
+               /* CFlash */
+               irq = IRQ_IOP32X_XINT1;
+       } else if (slot == 1) {
+               /* 82551 Pro 100 */
+               irq = IRQ_IOP32X_XINT0;
+       } else if (slot == 2) {
+               /* PCI-X Slot */
+               irq = IRQ_IOP32X_XINT3;
+       } else if (slot == 3) {
+               /* SATA */
+               irq = IRQ_IOP32X_XINT2;
+       } else {
+               printk(KERN_ERR "ep80219_pci_map_irq() called for unknown "
+                       "device PCI:%d:%d:%d\n", dev->bus->number,
+                       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+               irq = -1;
+       }
+
+       return irq;
+}
+
+static struct hw_pci ep80219_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = ep80219_pci_map_irq,
+};
+
+static inline int __init
+iq31244_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if (slot == 0) {
+               /* CFlash */
+               irq = IRQ_IOP32X_XINT1;
+       } else if (slot == 1) {
+               /* SATA */
+               irq = IRQ_IOP32X_XINT2;
+       } else if (slot == 2) {
+               /* PCI-X Slot */
+               irq = IRQ_IOP32X_XINT3;
+       } else if (slot == 3) {
+               /* 82546 GigE */
+               irq = IRQ_IOP32X_XINT0;
+       } else {
+               printk(KERN_ERR "iq31244_pci_map_irq called for unknown "
+                       "device PCI:%d:%d:%d\n", dev->bus->number,
+                       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+               irq = -1;
+       }
+
+       return irq;
+}
+
+static struct hw_pci iq31244_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = iq31244_pci_map_irq,
+};
+
+static int __init iq31244_pci_init(void)
+{
+       if (machine_is_iq31244()) {
+               if (is_80219()) {
+                       pci_common_init(&ep80219_pci);
+               } else {
+                       pci_common_init(&iq31244_pci);
+               }
+       }
+
+       return 0;
+}
+
+subsys_initcall(iq31244_pci_init);
+
+
+/*
+ * IQ31244 machine initialisation.
+ */
+static struct physmap_flash_data iq31244_flash_data = {
+       .width          = 2,
+};
+
+static struct resource iq31244_flash_resource = {
+       .start          = 0xf0000000,
+       .end            = 0xf07fffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device iq31244_flash_device = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &iq31244_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &iq31244_flash_resource,
+};
+
+static struct plat_serial8250_port iq31244_serial_port[] = {
+       {
+               .mapbase        = IQ31244_UART,
+               .membase        = (char *)IQ31244_UART,
+               .irq            = IRQ_IOP32X_XINT1,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 0,
+               .uartclk        = 1843200,
+       },
+       { },
+};
+
+static struct resource iq31244_uart_resource = {
+       .start          = IQ31244_UART,
+       .end            = IQ31244_UART + 7,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device iq31244_serial_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev            = {
+               .platform_data          = iq31244_serial_port,
+       },
+       .num_resources  = 1,
+       .resource       = &iq31244_uart_resource,
+};
+
+/*
+ * This function will send a SHUTDOWN_COMPLETE message to the PIC
+ * controller over I2C.  We are not using the i2c subsystem since
+ * we are going to power off and it may be removed
+ */
+void ep80219_power_off(void)
+{
+       /*
+        * Send the Address byte w/ the start condition
+        */
+       *IOP3XX_IDBR1 = 0x60;
+       *IOP3XX_ICR1 = 0xE9;
+       mdelay(1);
+
+       /*
+        * Send the START_MSG byte w/ no start or stop condition
+        */
+       *IOP3XX_IDBR1 = 0x0F;
+       *IOP3XX_ICR1 = 0xE8;
+       mdelay(1);
+
+       /*
+        * Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or
+        * stop condition
+        */
+       *IOP3XX_IDBR1 = 0x03;
+       *IOP3XX_ICR1 = 0xE8;
+       mdelay(1);
+
+       /*
+        * Send an ignored byte w/ stop condition
+        */
+       *IOP3XX_IDBR1 = 0x00;
+       *IOP3XX_ICR1 = 0xEA;
+
+       while (1)
+               ;
+}
+
+static void __init iq31244_init_machine(void)
+{
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&iq31244_flash_device);
+       platform_device_register(&iq31244_serial_device);
+
+       if (is_80219())
+               pm_power_off = ep80219_power_off;
+}
+
+MACHINE_START(IQ31244, "Intel IQ31244")
+       /* Maintainer: Intel Corp. */
+       .phys_io        = IQ31244_UART,
+       .io_pg_offst    = ((IQ31244_UART) >> 18) & 0xfffc,
+       .boot_params    = 0xa0000100,
+       .map_io         = iq31244_map_io,
+       .init_irq       = iop32x_init_irq,
+       .timer          = &iq31244_timer,
+       .init_machine   = iq31244_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
new file mode 100644 (file)
index 0000000..1f37b55
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * arch/arm/mach-iop32x/iq80321.c
+ *
+ * Board support code for the Intel IQ80321 platform.
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * IQ80321 timer tick configuration.
+ */
+static void __init iq80321_timer_init(void)
+{
+       /* 33.333 MHz crystal.  */
+       iop3xx_init_time(200000000);
+}
+
+static struct sys_timer iq80321_timer = {
+       .init           = iq80321_timer_init,
+       .offset         = iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ80321 I/O.
+ */
+static struct map_desc iq80321_io_desc[] __initdata = {
+       {       /* on-board devices */
+               .virtual        = IQ80321_UART,
+               .pfn            = __phys_to_pfn(IQ80321_UART),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init iq80321_map_io(void)
+{
+       iop3xx_map_io();
+       iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
+}
+
+
+/*
+ * IQ80321 PCI.
+ */
+static inline int __init
+iq80321_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if ((slot == 2 || slot == 6) && pin == 1) {
+               /* PCI-X Slot INTA */
+               irq = IRQ_IOP32X_XINT2;
+       } else if ((slot == 2 || slot == 6) && pin == 2) {
+               /* PCI-X Slot INTA */
+               irq = IRQ_IOP32X_XINT3;
+       } else if ((slot == 2 || slot == 6) && pin == 3) {
+               /* PCI-X Slot INTA */
+               irq = IRQ_IOP32X_XINT0;
+       } else if ((slot == 2 || slot == 6) && pin == 4) {
+               /* PCI-X Slot INTA */
+               irq = IRQ_IOP32X_XINT1;
+       } else if (slot == 4 || slot == 8) {
+               /* Gig-E */
+               irq = IRQ_IOP32X_XINT0;
+       } else {
+               printk(KERN_ERR "iq80321_pci_map_irq() called for unknown "
+                       "device PCI:%d:%d:%d\n", dev->bus->number,
+                       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+               irq = -1;
+       }
+
+       return irq;
+}
+
+static struct hw_pci iq80321_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = iq80321_pci_map_irq,
+};
+
+static int __init iq80321_pci_init(void)
+{
+       if (machine_is_iq80321())
+               pci_common_init(&iq80321_pci);
+
+       return 0;
+}
+
+subsys_initcall(iq80321_pci_init);
+
+
+/*
+ * IQ80321 machine initialisation.
+ */
+static struct physmap_flash_data iq80321_flash_data = {
+       .width          = 1,
+};
+
+static struct resource iq80321_flash_resource = {
+       .start          = 0xf0000000,
+       .end            = 0xf07fffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device iq80321_flash_device = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &iq80321_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &iq80321_flash_resource,
+};
+
+static struct plat_serial8250_port iq80321_serial_port[] = {
+       {
+               .mapbase        = IQ80321_UART,
+               .membase        = (char *)IQ80321_UART,
+               .irq            = IRQ_IOP32X_XINT1,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 0,
+               .uartclk        = 1843200,
+       },
+       { },
+};
+
+static struct resource iq80321_uart_resource = {
+       .start          = IQ80321_UART,
+       .end            = IQ80321_UART + 7,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device iq80321_serial_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev            = {
+               .platform_data          = iq80321_serial_port,
+       },
+       .num_resources  = 1,
+       .resource       = &iq80321_uart_resource,
+};
+
+static void __init iq80321_init_machine(void)
+{
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&iq80321_flash_device);
+       platform_device_register(&iq80321_serial_device);
+}
+
+MACHINE_START(IQ80321, "Intel IQ80321")
+       /* Maintainer: Intel Corp. */
+       .phys_io        = IQ80321_UART,
+       .io_pg_offst    = ((IQ80321_UART) >> 18) & 0xfffc,
+       .boot_params    = 0xa0000100,
+       .map_io         = iq80321_map_io,
+       .init_irq       = iop32x_init_irq,
+       .timer          = &iq80321_timer,
+       .init_machine   = iq80321_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
new file mode 100644 (file)
index 0000000..69d6302
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * arch/arm/mach-iop32x/irq.c
+ *
+ * Generic IOP32X IRQ handling functionality
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * 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/interrupt.h>
+#include <linux/list.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static u32 iop32x_mask;
+
+static inline void intctl_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static inline void intstr_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static void
+iop32x_irq_mask(unsigned int irq)
+{
+       iop32x_mask &= ~(1 << irq);
+       intctl_write(iop32x_mask);
+}
+
+static void
+iop32x_irq_unmask(unsigned int irq)
+{
+       iop32x_mask |= 1 << irq;
+       intctl_write(iop32x_mask);
+}
+
+struct irq_chip ext_chip = {
+       .name   = "IOP32x",
+       .ack    = iop32x_irq_mask,
+       .mask   = iop32x_irq_mask,
+       .unmask = iop32x_irq_unmask,
+};
+
+void __init iop32x_init_irq(void)
+{
+       int i;
+
+       intctl_write(0);
+       intstr_write(0);
+       if (machine_is_glantank() ||
+           machine_is_iq80321() ||
+           machine_is_iq31244() ||
+           machine_is_n2100())
+               *IOP3XX_PCIIRSR = 0x0f;
+
+       for (i = 0; i < NR_IRQS; i++) {
+               set_irq_chip(i, &ext_chip);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+}
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
new file mode 100644 (file)
index 0000000..a2c94a4
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * arch/arm/mach-iop32x/n2100.c
+ *
+ * Board support code for the Thecus N2100 platform.
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright 2003 (c) MontaVista, Software, Inc.
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * N2100 timer tick configuration.
+ */
+static void __init n2100_timer_init(void)
+{
+       /* 33.000 MHz crystal.  */
+       iop3xx_init_time(198000000);
+}
+
+static struct sys_timer n2100_timer = {
+       .init           = n2100_timer_init,
+       .offset         = iop3xx_gettimeoffset,
+};
+
+
+/*
+ * N2100 I/O.
+ */
+static struct map_desc n2100_io_desc[] __initdata = {
+       {       /* on-board devices */
+               .virtual        = N2100_UART,
+               .pfn            = __phys_to_pfn(N2100_UART),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       },
+};
+
+void __init n2100_map_io(void)
+{
+       iop3xx_map_io();
+       iotable_init(n2100_io_desc, ARRAY_SIZE(n2100_io_desc));
+}
+
+
+/*
+ * N2100 PCI.
+ */
+static inline int __init
+n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if (PCI_SLOT(dev->devfn) == 1) {
+               /* RTL8110SB #1 */
+               irq = IRQ_IOP32X_XINT0;
+       } else if (PCI_SLOT(dev->devfn) == 2) {
+               /* RTL8110SB #2 */
+               irq = IRQ_IOP32X_XINT1;
+       } else if (PCI_SLOT(dev->devfn) == 3) {
+               /* Sil3512 */
+               irq = IRQ_IOP32X_XINT2;
+       } else if (PCI_SLOT(dev->devfn) == 4 && pin == 1) {
+               /* VT6212 INTA */
+               irq = IRQ_IOP32X_XINT1;
+       } else if (PCI_SLOT(dev->devfn) == 4 && pin == 2) {
+               /* VT6212 INTB */
+               irq = IRQ_IOP32X_XINT0;
+       } else if (PCI_SLOT(dev->devfn) == 4 && pin == 3) {
+               /* VT6212 INTC */
+               irq = IRQ_IOP32X_XINT2;
+       } else if (PCI_SLOT(dev->devfn) == 5) {
+               /* Mini-PCI slot */
+               irq = IRQ_IOP32X_XINT3;
+       } else {
+               printk(KERN_ERR "n2100_pci_map_irq() called for unknown "
+                       "device PCI:%d:%d:%d\n", dev->bus->number,
+                       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+               irq = -1;
+       }
+
+       return irq;
+}
+
+static struct hw_pci n2100_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = n2100_pci_map_irq,
+};
+
+static int __init n2100_pci_init(void)
+{
+       if (machine_is_n2100())
+               pci_common_init(&n2100_pci);
+
+       return 0;
+}
+
+subsys_initcall(n2100_pci_init);
+
+
+/*
+ * N2100 machine initialisation.
+ */
+static struct physmap_flash_data n2100_flash_data = {
+       .width          = 2,
+};
+
+static struct resource n2100_flash_resource = {
+       .start          = 0xf0000000,
+       .end            = 0xf0ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device n2100_flash_device = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &n2100_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &n2100_flash_resource,
+};
+
+
+static struct plat_serial8250_port n2100_serial_port[] = {
+       {
+               .mapbase        = N2100_UART,
+               .membase        = (char *)N2100_UART,
+               .irq            = 0,
+               .flags          = UPF_SKIP_TEST,
+               .iotype         = UPIO_MEM,
+               .regshift       = 0,
+               .uartclk        = 1843200,
+       },
+       { },
+};
+
+static struct resource n2100_uart_resource = {
+       .start          = N2100_UART,
+       .end            = N2100_UART + 7,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device n2100_serial_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev            = {
+               .platform_data          = n2100_serial_port,
+       },
+       .num_resources  = 1,
+       .resource       = &n2100_uart_resource,
+};
+
+
+/*
+ * Pull PCA9532 GPIO #8 low to power off the machine.
+ */
+static void n2100_power_off(void)
+{
+       local_irq_disable();
+
+       /* Start condition, I2C address of PCA9532, write transaction.  */
+       *IOP3XX_IDBR0 = 0xc0;
+       *IOP3XX_ICR0 = 0xe9;
+       mdelay(1);
+
+       /* Write address 0x08.  */
+       *IOP3XX_IDBR0 = 0x08;
+       *IOP3XX_ICR0 = 0xe8;
+       mdelay(1);
+
+       /* Write data 0x01, stop condition.  */
+       *IOP3XX_IDBR0 = 0x01;
+       *IOP3XX_ICR0 = 0xea;
+
+       while (1)
+               ;
+}
+
+
+static struct timer_list power_button_poll_timer;
+
+static void power_button_poll(unsigned long dummy)
+{
+       if (gpio_line_get(N2100_POWER_BUTTON) == 0) {
+               ctrl_alt_del();
+               return;
+       }
+
+       power_button_poll_timer.expires = jiffies + (HZ / 10);
+       add_timer(&power_button_poll_timer);
+}
+
+
+static void __init n2100_init_machine(void)
+{
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&n2100_flash_device);
+       platform_device_register(&n2100_serial_device);
+
+       pm_power_off = n2100_power_off;
+
+       init_timer(&power_button_poll_timer);
+       power_button_poll_timer.function = power_button_poll;
+       power_button_poll_timer.expires = jiffies + (HZ / 10);
+       add_timer(&power_button_poll_timer);
+}
+
+MACHINE_START(N2100, "Thecus N2100")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = N2100_UART,
+       .io_pg_offst    = ((N2100_UART) >> 18) & 0xfffc,
+       .boot_params    = 0xa0000100,
+       .map_io         = n2100_map_io,
+       .init_irq       = iop32x_init_irq,
+       .timer          = &n2100_timer,
+       .init_machine   = n2100_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop33x/Kconfig b/arch/arm/mach-iop33x/Kconfig
new file mode 100644 (file)
index 0000000..9aa016b
--- /dev/null
@@ -0,0 +1,21 @@
+if ARCH_IOP33X
+
+menu "IOP33x Implementation Options"
+
+comment "IOP33x Platform Types"
+
+config ARCH_IQ80331
+       bool "Enable support for IQ80331"
+       help
+         Say Y here if you want to run your kernel on the Intel IQ80331
+         evaluation kit for the IOP331 chipset.
+
+config MACH_IQ80332
+       bool "Enable support for IQ80332"
+       help
+         Say Y here if you want to run your kernel on the Intel IQ80332
+         evaluation kit for the IOP332 chipset.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-iop33x/Makefile b/arch/arm/mach-iop33x/Makefile
new file mode 100644 (file)
index 0000000..90081d8
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                  := irq.o uart.o
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
+
+obj-$(CONFIG_ARCH_IQ80331) += iq80331.o
+obj-$(CONFIG_MACH_IQ80332) += iq80332.o
diff --git a/arch/arm/mach-iop33x/Makefile.boot b/arch/arm/mach-iop33x/Makefile.boot
new file mode 100644 (file)
index 0000000..67039c3
--- /dev/null
@@ -0,0 +1,3 @@
+   zreladdr-y  := 0x00008000
+params_phys-y  := 0x00000100
+initrd_phys-y  := 0x00800000
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
new file mode 100644 (file)
index 0000000..97a7b74
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/mach-iop33x/iq80331.c
+ *
+ * Board support code for the Intel IQ80331 platform.
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * IQ80331 timer tick configuration.
+ */
+static void __init iq80331_timer_init(void)
+{
+       /* D-Step parts run at a higher internal bus frequency */
+       if (*IOP3XX_ATURID >= 0xa)
+               iop3xx_init_time(333000000);
+       else
+               iop3xx_init_time(266000000);
+}
+
+static struct sys_timer iq80331_timer = {
+       .init           = iq80331_timer_init,
+       .offset         = iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ80331 PCI.
+ */
+static inline int __init
+iq80331_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if (slot == 1 && pin == 1) {
+               /* PCI-X Slot INTA */
+               irq = IRQ_IOP33X_XINT1;
+       } else if (slot == 1 && pin == 2) {
+               /* PCI-X Slot INTB */
+               irq = IRQ_IOP33X_XINT2;
+       } else if (slot == 1 && pin == 3) {
+               /* PCI-X Slot INTC */
+               irq = IRQ_IOP33X_XINT3;
+       } else if (slot == 1 && pin == 4) {
+               /* PCI-X Slot INTD */
+               irq = IRQ_IOP33X_XINT0;
+       } else if (slot == 2) {
+               /* GigE */
+               irq = IRQ_IOP33X_XINT2;
+       } else {
+               printk(KERN_ERR "iq80331_pci_map_irq() called for unknown "
+                       "device PCI:%d:%d:%d\n", dev->bus->number,
+                       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+               irq = -1;
+       }
+
+       return irq;
+}
+
+static struct hw_pci iq80331_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = iq80331_pci_map_irq,
+};
+
+static int __init iq80331_pci_init(void)
+{
+       if (machine_is_iq80331())
+               pci_common_init(&iq80331_pci);
+
+       return 0;
+}
+
+subsys_initcall(iq80331_pci_init);
+
+
+/*
+ * IQ80331 machine initialisation.
+ */
+static struct physmap_flash_data iq80331_flash_data = {
+       .width          = 1,
+};
+
+static struct resource iq80331_flash_resource = {
+       .start          = 0xc0000000,
+       .end            = 0xc07fffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device iq80331_flash_device = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &iq80331_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &iq80331_flash_resource,
+};
+
+static void __init iq80331_init_machine(void)
+{
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&iop33x_uart0_device);
+       platform_device_register(&iop33x_uart1_device);
+       platform_device_register(&iq80331_flash_device);
+}
+
+MACHINE_START(IQ80331, "Intel IQ80331")
+       /* Maintainer: Intel Corp. */
+       .phys_io        = 0xfefff000,
+       .io_pg_offst    = ((0xfffff000) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = iop3xx_map_io,
+       .init_irq       = iop33x_init_irq,
+       .timer          = &iq80331_timer,
+       .init_machine   = iq80331_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
new file mode 100644 (file)
index 0000000..9887bfc
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * arch/arm/mach-iop33x/iq80332.c
+ *
+ * Board support code for the Intel IQ80332 platform.
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * IQ80332 timer tick configuration.
+ */
+static void __init iq80332_timer_init(void)
+{
+       /* D-Step parts and the iop333 run at a higher internal bus frequency */
+       if (*IOP3XX_ATURID >= 0xa || *IOP3XX_ATUDID == 0x374)
+               iop3xx_init_time(333000000);
+       else
+               iop3xx_init_time(266000000);
+}
+
+static struct sys_timer iq80332_timer = {
+       .init           = iq80332_timer_init,
+       .offset         = iop3xx_gettimeoffset,
+};
+
+
+/*
+ * IQ80332 PCI.
+ */
+static inline int __init
+iq80332_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+
+       if (slot == 4 && pin == 1) {
+               /* PCI-X Slot INTA */
+               irq = IRQ_IOP33X_XINT0;
+       } else if (slot == 4 && pin == 2) {
+               /* PCI-X Slot INTB */
+               irq = IRQ_IOP33X_XINT1;
+       } else if (slot == 4 && pin == 3) {
+               /* PCI-X Slot INTC */
+               irq = IRQ_IOP33X_XINT2;
+       } else if (slot == 4 && pin == 4) {
+               /* PCI-X Slot INTD */
+               irq = IRQ_IOP33X_XINT3;
+       } else if (slot == 6) {
+               /* GigE */
+               irq = IRQ_IOP33X_XINT2;
+       } else {
+               printk(KERN_ERR "iq80332_pci_map_irq() called for unknown "
+                       "device PCI:%d:%d:%d\n", dev->bus->number,
+                       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+               irq = -1;
+       }
+
+       return irq;
+}
+
+static struct hw_pci iq80332_pci __initdata = {
+       .swizzle        = pci_std_swizzle,
+       .nr_controllers = 1,
+       .setup          = iop3xx_pci_setup,
+       .preinit        = iop3xx_pci_preinit,
+       .scan           = iop3xx_pci_scan_bus,
+       .map_irq        = iq80332_pci_map_irq,
+};
+
+static int __init iq80332_pci_init(void)
+{
+       if (machine_is_iq80332())
+               pci_common_init(&iq80332_pci);
+
+       return 0;
+}
+
+subsys_initcall(iq80332_pci_init);
+
+
+/*
+ * IQ80332 machine initialisation.
+ */
+static struct physmap_flash_data iq80332_flash_data = {
+       .width          = 1,
+};
+
+static struct resource iq80332_flash_resource = {
+       .start          = 0xc0000000,
+       .end            = 0xc07fffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device iq80332_flash_device = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &iq80332_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &iq80332_flash_resource,
+};
+
+static void __init iq80332_init_machine(void)
+{
+       platform_device_register(&iop3xx_i2c0_device);
+       platform_device_register(&iop3xx_i2c1_device);
+       platform_device_register(&iop33x_uart0_device);
+       platform_device_register(&iop33x_uart1_device);
+       platform_device_register(&iq80332_flash_device);
+}
+
+MACHINE_START(IQ80332, "Intel IQ80332")
+       /* Maintainer: Intel Corp. */
+       .phys_io        = 0xfefff000,
+       .io_pg_offst    = ((0xfffff000) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = iop3xx_map_io,
+       .init_irq       = iop33x_init_irq,
+       .timer          = &iq80332_timer,
+       .init_machine   = iq80332_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c
new file mode 100644 (file)
index 0000000..63304b3
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-iop33x/irq.c
+ *
+ * Generic IOP331 IRQ handling functionality
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/interrupt.h>
+#include <linux/list.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static u32 iop33x_mask0;
+static u32 iop33x_mask1;
+
+static inline void intctl0_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static inline void intctl1_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c1, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static inline void intstr0_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c2, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static inline void intstr1_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c3, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static inline void intbase_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c12, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static inline void intsize_write(u32 val)
+{
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c13, c0, 0" : : "r" (val));
+       iop3xx_cp6_disable();
+}
+
+static void
+iop33x_irq_mask1 (unsigned int irq)
+{
+       iop33x_mask0 &= ~(1 << irq);
+       intctl0_write(iop33x_mask0);
+}
+
+static void
+iop33x_irq_mask2 (unsigned int irq)
+{
+       iop33x_mask1 &= ~(1 << (irq - 32));
+       intctl1_write(iop33x_mask1);
+}
+
+static void
+iop33x_irq_unmask1(unsigned int irq)
+{
+       iop33x_mask0 |= 1 << irq;
+       intctl0_write(iop33x_mask0);
+}
+
+static void
+iop33x_irq_unmask2(unsigned int irq)
+{
+       iop33x_mask1 |= (1 << (irq - 32));
+       intctl1_write(iop33x_mask1);
+}
+
+struct irq_chip iop33x_irqchip1 = {
+       .name   = "IOP33x-1",
+       .ack    = iop33x_irq_mask1,
+       .mask   = iop33x_irq_mask1,
+       .unmask = iop33x_irq_unmask1,
+};
+
+struct irq_chip iop33x_irqchip2 = {
+       .name   = "IOP33x-2",
+       .ack    = iop33x_irq_mask2,
+       .mask   = iop33x_irq_mask2,
+       .unmask = iop33x_irq_unmask2,
+};
+
+void __init iop33x_init_irq(void)
+{
+       int i;
+
+       intctl0_write(0);
+       intctl1_write(0);
+       intstr0_write(0);
+       intstr1_write(0);
+       intbase_write(0);
+       intsize_write(1);
+       if (machine_is_iq80331())
+               *IOP3XX_PCIIRSR = 0x0f;
+
+       for (i = 0; i < NR_IRQS; i++) {
+               set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+       }
+}
diff --git a/arch/arm/mach-iop33x/uart.c b/arch/arm/mach-iop33x/uart.c
new file mode 100644 (file)
index 0000000..ac297cd
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * arch/arm/mach-iop33x/uart.c
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2004 Intel 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop3xx.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#define IOP33X_UART_XTAL 33334000
+
+static struct plat_serial8250_port iop33x_uart0_data[] = {
+       {
+               .membase        = (char *)IOP33X_UART0_VIRT,
+               .mapbase        = IOP33X_UART0_PHYS,
+               .irq            = IRQ_IOP33X_UART0,
+               .uartclk        = IOP33X_UART_XTAL,
+               .regshift       = 2,
+               .iotype         = UPIO_MEM,
+               .flags          = UPF_SKIP_TEST,
+       },
+       { },
+};
+
+static struct resource iop33x_uart0_resources[] = {
+       [0] = {
+               .start  = IOP33X_UART0_PHYS,
+               .end    = IOP33X_UART0_PHYS + 0x3f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_IOP33X_UART0,
+               .end    = IRQ_IOP33X_UART0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device iop33x_uart0_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM,
+       .dev            = {
+               .platform_data          = iop33x_uart0_data,
+       },
+       .num_resources  = 2,
+       .resource       = iop33x_uart0_resources,
+};
+
+
+static struct resource iop33x_uart1_resources[] = {
+       [0] = {
+               .start  = IOP33X_UART1_PHYS,
+               .end    = IOP33X_UART1_PHYS + 0x3f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_IOP33X_UART1,
+               .end    = IRQ_IOP33X_UART1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct plat_serial8250_port iop33x_uart1_data[] = {
+       {
+               .membase        = (char *)IOP33X_UART1_VIRT,
+               .mapbase        = IOP33X_UART1_PHYS,
+               .irq            = IRQ_IOP33X_UART1,
+               .uartclk        = IOP33X_UART_XTAL,
+               .regshift       = 2,
+               .iotype         = UPIO_MEM,
+               .flags          = UPF_SKIP_TEST,
+       },
+       { },
+};
+
+struct platform_device iop33x_uart1_device = {
+       .name           = "serial8250",
+       .id             = PLAT8250_DEV_PLATFORM1,
+       .dev            = {
+               .platform_data          = iop33x_uart1_data,
+       },
+       .num_resources  = 2,
+       .resource       = iop33x_uart1_resources,
+};
diff --git a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig
deleted file mode 100644 (file)
index 4422f23..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-if ARCH_IOP3XX
-
-menu "IOP3xx Implementation Options"
-
-comment "IOP3xx Platform Types"
-
-config ARCH_IQ80321
-       bool "Enable support for IQ80321"
-       select ARCH_IOP321
-       help
-         Say Y here if you want to run your kernel on the Intel IQ80321
-         evaluation kit for the IOP321 chipset.
-
-config ARCH_IQ31244
-       bool "Enable support for IQ31244"
-       select ARCH_IOP321
-       help
-         Say Y here if you want to run your kernel on the Intel IQ31244
-         evaluation kit for the IOP321 chipset.
-
-config ARCH_IQ80331
-       bool "Enable support for IQ80331"
-       select ARCH_IOP331
-       help
-         Say Y here if you want to run your kernel on the Intel IQ80331
-         evaluation kit for the IOP331 chipset.
-
-config MACH_IQ80332
-       bool "Enable support for IQ80332"
-       select ARCH_IOP331
-       help
-         Say Y here if you want to run your kernel on the Intel IQ80332
-         evaluation kit for the IOP332 chipset.
-
-config ARCH_EP80219
-       bool "Enable support for EP80219"
-       select ARCH_IOP321
-       select ARCH_IQ31244
-       help
-         Say Y here if you want to run your kernel on the Intel EP80219
-         evaluation kit for the Intel 80219 chipset (a IOP321 variant).
-
-# Which IOP variant are we running?
-config ARCH_IOP321
-       bool
-       help
-         The IQ80321 uses the IOP321 variant.
-         The IQ31244 and EP80219 uses the IOP321 variant.
-
-config ARCH_IOP331
-       bool
-       default ARCH_IQ80331
-       help
-         The IQ80331, IQ80332, and IQ80333 uses the IOP331 variant.
-
-comment "IOP3xx Chipset Features"
-
-config IOP331_STEPD
-       bool "Chip stepping D of the IOP80331 processor or IOP80333"
-       depends on (ARCH_IOP331)
-       help
-         Say Y here if you have StepD of the IOP80331 or IOP8033
-         based platforms.
-
-endmenu
-endif
diff --git a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile
deleted file mode 100644 (file)
index b17eb1f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y                  := common.o
-
-obj-m                  :=
-obj-n                  :=
-obj-                   :=
-
-obj-$(CONFIG_ARCH_IOP321)  += iop321-setup.o iop321-irq.o iop321-pci.o iop321-time.o
-
-obj-$(CONFIG_ARCH_IOP331)  += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
-
-obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
-
-obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
-
-obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o
-
-obj-$(CONFIG_MACH_IQ80332) += iq80332-mm.o iq80332-pci.o
diff --git a/arch/arm/mach-iop3xx/Makefile.boot b/arch/arm/mach-iop3xx/Makefile.boot
deleted file mode 100644 (file)
index 6387aa2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-   zreladdr-y  := 0xa0008000
-params_phys-y  := 0xa0000100
-initrd_phys-y  := 0xa0800000
-ifeq ($(CONFIG_ARCH_IOP331),y)
-   zreladdr-y  := 0x00008000
-params_phys-y  := 0x00000100
-initrd_phys-y  := 0x00800000
-endif
-
diff --git a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c
deleted file mode 100644 (file)
index d7f50e5..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/common.c
- *
- * Common routines shared across all IOP3xx implementations
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright 2003 (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/delay.h>
-#include <asm/hardware.h>
-
-/*
- * Shared variables
- */
-unsigned long iop3xx_pcibios_min_io = 0;
-unsigned long iop3xx_pcibios_min_mem = 0;
-
-#ifdef CONFIG_ARCH_EP80219
-#include <linux/kernel.h>
-/*
- * Default power-off for EP80219
- */
-
-static inline void ep80219_send_to_pic(__u8 c) {
-}
-
-void ep80219_power_off(void)
-{
-       /*
-     * This function will send a SHUTDOWN_COMPLETE message to the PIC controller
-     * over I2C.  We are not using the i2c subsystem since we are going to power
-     * off and it may be removed
-     */
-
-       /* Send the Address byte w/ the start condition */
-       *IOP321_IDBR1 = 0x60;
-       *IOP321_ICR1 = 0xE9;
-    mdelay(1);
-
-       /* Send the START_MSG byte w/ no start or stop condition */
-       *IOP321_IDBR1 = 0x0F;
-       *IOP321_ICR1 = 0xE8;
-    mdelay(1);
-
-       /* Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or stop condition */
-       *IOP321_IDBR1 = 0x03;
-       *IOP321_ICR1 = 0xE8;
-    mdelay(1);
-
-       /* Send an ignored byte w/ stop condition */
-       *IOP321_IDBR1 = 0x00;
-       *IOP321_ICR1 = 0xEA;
-
-       while (1) ;
-}
-
-#include <linux/init.h>
-#include <linux/pm.h>
-
-static int __init ep80219_init(void)
-{
-       pm_power_off = ep80219_power_off;
-       return 0;
-}
-arch_initcall(ep80219_init);
-#endif
diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
deleted file mode 100644 (file)
index 88ac333..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop321-irq.c
- *
- * Generic IOP321 IRQ handling functionality
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * 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.
- *
- * Added IOP3XX chipset and IQ80321 board masking code.
- *
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-#include <asm/mach-types.h>
-
-static u32 iop321_mask /* = 0 */;
-
-static inline void intctl_write(u32 val)
-{
-       asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
-}
-
-static inline void intstr_write(u32 val)
-{
-       asm volatile("mcr p6,0,%0,c4,c0,0"::"r" (val));
-}
-
-static void
-iop321_irq_mask (unsigned int irq)
-{
-
-       iop321_mask &= ~(1 << (irq - IOP321_IRQ_OFS));
-
-       intctl_write(iop321_mask);
-}
-
-static void
-iop321_irq_unmask (unsigned int irq)
-{
-       iop321_mask |= (1 << (irq - IOP321_IRQ_OFS));
-
-       intctl_write(iop321_mask);
-}
-
-struct irq_chip ext_chip = {
-       .name   = "IOP",
-       .ack    = iop321_irq_mask,
-       .mask   = iop321_irq_mask,
-       .unmask = iop321_irq_unmask,
-};
-
-void __init iop321_init_irq(void)
-{
-       unsigned int i, tmp;
-
-       /* Enable access to coprocessor 6 for dealing with IRQs.
-        * From RMK:
-        * Basically, the Intel documentation here is poor.  It appears that
-        * you need to set the bit to be able to access the coprocessor from
-        * SVC mode.  Whether that allows access from user space or not is
-        * unclear.
-        */
-       asm volatile (
-               "mrc p15, 0, %0, c15, c1, 0\n\t"
-               "orr %0, %0, %1\n\t"
-               "mcr p15, 0, %0, c15, c1, 0\n\t"
-               /* The action is delayed, so we have to do this: */
-               "mrc p15, 0, %0, c15, c1, 0\n\t"
-               "mov %0, %0\n\t"
-               "sub pc, pc, #4"
-               : "=r" (tmp) : "i" (1 << 6) );
-
-       intctl_write(0);                // disable all interrupts
-       intstr_write(0);                // treat all as IRQ
-       if(machine_is_iq80321() ||
-          machine_is_iq31244())        // all interrupts are inputs to chip
-               *IOP321_PCIIRSR = 0x0f;
-
-       for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++)
-       {
-               set_irq_chip(i, &ext_chip);
-               set_irq_handler(i, do_level_IRQ);
-               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-
-       }
-}
-
diff --git a/arch/arm/mach-iop3xx/iop321-pci.c b/arch/arm/mach-iop3xx/iop321-pci.c
deleted file mode 100644 (file)
index 8ba6a0e..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop321-pci.c
- *
- * PCI support for the Intel IOP321 chipset
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/mach/pci.h>
-
-#include <asm/arch/iop321.h>
-
-// #define DEBUG
-
-#ifdef DEBUG
-#define  DBG(x...) printk(x)
-#else
-#define  DBG(x...) do { } while (0)
-#endif
-
-/*
- * This routine builds either a type0 or type1 configuration command.  If the
- * bus is on the 80321 then a type0 made, else a type1 is created.
- */
-static u32 iop321_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
-       struct pci_sys_data *sys = bus->sysdata;
-       u32 addr;
-
-       if (sys->busnr == bus->number)
-               addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
-       else
-               addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
-
-       addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
-
-       return addr;
-}
-
-/*
- * This routine checks the status of the last configuration cycle.  If an error
- * was detected it returns a 1, else it returns a 0.  The errors being checked
- * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
- * the discovery stage.
- */
-static int iop321_pci_status(void)
-{
-       unsigned int status;
-       int ret = 0;
-
-       /*
-        * Check the status registers.
-        */
-       status = *IOP321_ATUSR;
-       if (status & 0xf900)
-       {
-               DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
-               *IOP321_ATUSR = status & 0xf900;
-               ret = 1;
-       }
-       status = *IOP321_ATUISR;
-       if (status & 0x679f)
-       {
-               DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
-               *IOP321_ATUISR = status & 0x679f;
-               ret = 1;
-       }
-       return ret;
-}
-
-/*
- * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
- * a delayed abort (in theory.)
- */
-static inline u32 iop321_read(unsigned long addr)
-{
-       u32 val;
-
-       __asm__ __volatile__(
-               "str    %1, [%2]\n\t"
-               "ldr    %0, [%3]\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               : "=r" (val)
-               : "r" (addr), "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
-
-       return val;
-}
-
-/*
- * The read routines must check the error status of the last configuration
- * cycle.  If there was an error, the routine returns all hex f's.
- */
-static int
-iop321_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-               int size, u32 *value)
-{
-       unsigned long addr = iop321_cfg_address(bus, devfn, where);
-       u32 val = iop321_read(addr) >> ((where & 3) * 8);
-
-       if( iop321_pci_status() )
-               val = 0xffffffff;
-
-       *value = val;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-               int size, u32 value)
-{
-       unsigned long addr = iop321_cfg_address(bus, devfn, where);
-       u32 val;
-
-       if (size != 4) {
-               val = iop321_read(addr);
-               if (!iop321_pci_status() == 0)
-                       return PCIBIOS_SUCCESSFUL;
-
-               where = (where & 3) * 8;
-
-               if (size == 1)
-                       val &= ~(0xff << where);
-               else
-                       val &= ~(0xffff << where);
-
-               *IOP321_OCCDR = val | value << where;
-       } else {
-               asm volatile(
-                       "str    %1, [%2]\n\t"
-                       "str    %0, [%3]\n\t"
-                       "nop\n\t"
-                       "nop\n\t"
-                       "nop\n\t"
-                       "nop\n\t"
-                       :
-                       : "r" (value), "r" (addr),
-                         "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
-       }
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop321_ops = {
-       .read   = iop321_read_config,
-       .write  = iop321_write_config,
-};
-
-/*
- * When a PCI device does not exist during config cycles, the 80200 gets a
- * bus error instead of returning 0xffffffff. This handler simply returns.
- */
-int
-iop321_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
-       DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
-               addr, fsr, regs->ARM_pc, regs->ARM_lr);
-
-       /*
-        * If it was an imprecise abort, then we need to correct the
-        * return address to be _after_ the instruction.
-        */
-       if (fsr & (1 << 10))
-               regs->ARM_pc += 4;
-
-       return 0;
-}
-
-/*
- * Scan an IOP321 PCI bus.  sys->bus defines which bus we scan.
- */
-struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *sys)
-{
-       return pci_scan_bus(sys->busnr, &iop321_ops, sys);
-}
-
-void iop321_init(void)
-{
-       DBG("PCI:  Intel 80321 PCI init code.\n");
-       DBG("ATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD);
-       DBG("ATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n",
-                       *IOP321_OMWTVR0,
-                       *IOP321_OIOWTVR);
-       DBG("ATU: IOP321_ATUCR=0x%08x\n", *IOP321_ATUCR);
-       DBG("ATU: IOP321_IABAR0=0x%08x IOP321_IALR0=0x%08x IOP321_IATVR0=%08x\n",
-                       *IOP321_IABAR0, *IOP321_IALR0, *IOP321_IATVR0);
-       DBG("ATU: IOP321_OMWTVR0=0x%08x\n", *IOP321_OMWTVR0);
-       DBG("ATU: IOP321_IABAR1=0x%08x IOP321_IALR1=0x%08x\n",
-                       *IOP321_IABAR1, *IOP321_IALR1);
-       DBG("ATU: IOP321_ERBAR=0x%08x IOP321_ERLR=0x%08x IOP321_ERTVR=%08x\n",
-                       *IOP321_ERBAR, *IOP321_ERLR, *IOP321_ERTVR);
-       DBG("ATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n",
-                       *IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2);
-       DBG("ATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n",
-                       *IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3);
-
-       hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort");
-}
-
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
deleted file mode 100644 (file)
index b6d0969..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop321-setup.c
- *
- * Author: Nicolas Pitre <nico@cam.org>
- * Copyright (C) 2001 MontaVista Software, Inc.
- * Copyright (C) 2004 Intel 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.
- *
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#define IOP321_UART_XTAL 1843200
-
-/*
- * Standard IO mapping for all IOP321 based systems
- */
-static struct map_desc iop321_std_desc[] __initdata = {
-        {      /* mem mapped registers */
-               .virtual        = IOP321_VIRT_MEM_BASE,
-               .pfn            = __phys_to_pfn(IOP321_PHYS_MEM_BASE),
-               .length         = 0x00002000,
-               .type           = MT_DEVICE
-        }, {   /* PCI IO space */
-               .virtual        = IOP321_PCI_LOWER_IO_VA,
-               .pfn            = __phys_to_pfn(IOP321_PCI_LOWER_IO_PA),
-               .length         = IOP321_PCI_IO_WINDOW_SIZE,
-               .type           = MT_DEVICE
-        }
-};
-
-#ifdef CONFIG_ARCH_IQ80321
-#define UARTBASE IQ80321_UART
-#define IRQ_UART IRQ_IQ80321_UART
-#endif
-
-#ifdef CONFIG_ARCH_IQ31244
-#define UARTBASE IQ31244_UART
-#define IRQ_UART IRQ_IQ31244_UART
-#endif
-
-static struct uart_port iop321_serial_ports[] = {
-       {
-               .membase        = (char*)(UARTBASE),
-               .mapbase        = (UARTBASE),
-               .irq            = IRQ_UART,
-               .flags          = UPF_SKIP_TEST,
-               .iotype         = UPIO_MEM,
-               .regshift       = 0,
-               .uartclk        = IOP321_UART_XTAL,
-               .line           = 0,
-               .type           = PORT_16550A,
-               .fifosize       = 16
-       }
-};
-
-static struct resource iop32x_i2c_0_resources[] = {
-       [0] = {
-               .start = 0xfffff680,
-               .end = 0xfffff698,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IOP321_I2C_0,
-               .end = IRQ_IOP321_I2C_0,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-static struct resource iop32x_i2c_1_resources[] = {
-       [0] = {
-               .start = 0xfffff6a0,
-               .end = 0xfffff6b8,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IOP321_I2C_1,
-               .end = IRQ_IOP321_I2C_1,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-static struct platform_device iop32x_i2c_0_controller = {
-       .name = "IOP3xx-I2C",
-       .id = 0,
-       .num_resources = 2,
-       .resource = iop32x_i2c_0_resources
-};
-
-static struct platform_device iop32x_i2c_1_controller = {
-       .name = "IOP3xx-I2C",
-       .id = 1,
-       .num_resources = 2,
-       .resource = iop32x_i2c_1_resources
-};
-
-static struct platform_device *iop32x_devices[] __initdata = {
-       &iop32x_i2c_0_controller,
-       &iop32x_i2c_1_controller
-};
-
-void __init iop32x_init(void)
-{
-       if(iop_is_321())
-       {
-               platform_add_devices(iop32x_devices,
-                               ARRAY_SIZE(iop32x_devices));
-       }
-}
-
-void __init iop321_map_io(void)
-{
-       iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
-       early_serial_setup(&iop321_serial_ports[0]);
-}
-
-#ifdef CONFIG_ARCH_IQ80321
-extern void iq80321_map_io(void);
-extern struct sys_timer iop321_timer;
-extern void iop321_init_time(void);
-#endif
-
-#ifdef CONFIG_ARCH_IQ31244
-extern void iq31244_map_io(void);
-extern struct sys_timer iop321_timer;
-extern void iop321_init_time(void);
-#endif
-
-#if defined(CONFIG_ARCH_IQ80321)
-MACHINE_START(IQ80321, "Intel IQ80321")
-       /* Maintainer: Intel Corporation */
-       .phys_io        = IQ80321_UART,
-       .io_pg_offst    = ((IQ80321_UART) >> 18) & 0xfffc,
-       .map_io         = iq80321_map_io,
-       .init_irq       = iop321_init_irq,
-       .timer          = &iop321_timer,
-       .boot_params    = 0xa0000100,
-       .init_machine   = iop32x_init,
-MACHINE_END
-#elif defined(CONFIG_ARCH_IQ31244)
-MACHINE_START(IQ31244, "Intel IQ31244")
-       /* Maintainer: Intel Corp. */
-       .phys_io        = IQ31244_UART,
-       .io_pg_offst    = ((IQ31244_UART) >> 18) & 0xfffc,
-       .map_io         = iq31244_map_io,
-       .init_irq       = iop321_init_irq,
-       .timer          = &iop321_timer,
-       .boot_params    = 0xa0000100,
-       .init_machine   = iop32x_init,
-MACHINE_END
-#else
-#error No machine descriptor defined for this IOP3XX implementation
-#endif
diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
deleted file mode 100644 (file)
index 04b1a6f..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop321-time.c
- *
- * Timer code for IOP321 based systems
- *
- * Author: Deepak Saxena <dsaxena@mvista.com>
- *
- * Copyright 2002-2003 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#define IOP321_TIME_SYNC 0
-
-static inline unsigned long get_elapsed(void)
-{
-       return LATCH - *IOP321_TU_TCR0;
-}
-
-static unsigned long iop321_gettimeoffset(void)
-{
-       unsigned long elapsed, usec;
-       u32 tisr1, tisr2;
-
-       /*
-        * If an interrupt was pending before we read the timer,
-        * we've already wrapped.  Factor this into the time.
-        * If an interrupt was pending after we read the timer,
-        * it may have wrapped between checking the interrupt
-        * status and reading the timer.  Re-read the timer to
-        * be sure its value is after the wrap.
-        */
-
-       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
-       elapsed = get_elapsed();
-       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
-
-       if(tisr1 & 1)
-               elapsed += LATCH;
-       else if (tisr2 & 1)
-               elapsed = LATCH + get_elapsed();
-
-       /*
-        * Now convert them to usec.
-        */
-       usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
-
-       return usec;
-}
-
-static irqreturn_t
-iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       u32 tisr;
-
-       write_seqlock(&xtime_lock);
-
-       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
-       tisr |= 1;
-       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
-
-       timer_tick(regs);
-
-       write_sequnlock(&xtime_lock);
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction iop321_timer_irq = {
-       .name           = "IOP321 Timer Tick",
-       .handler        = iop321_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
-};
-
-static void __init iop321_timer_init(void)
-{
-       u32 timer_ctl;
-
-       setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
-
-       timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
-                       IOP321_TMR_RATIO_1_1;
-
-       asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
-
-       asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
-}
-
-struct sys_timer iop321_timer = {
-       .init           = &iop321_timer_init,
-       .offset         = iop321_gettimeoffset,
-};
diff --git a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
deleted file mode 100644 (file)
index cab1172..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop331-irq.c
- *
- * Generic IOP331 IRQ handling functionality
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003 Intel Corp.
- *
- * 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/interrupt.h>
-#include <linux/list.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-#include <asm/mach-types.h>
-
-static u32 iop331_mask0 = 0;
-static u32 iop331_mask1 = 0;
-
-static inline void intctl_write0(u32 val)
-{
-    // INTCTL0
-       asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
-}
-
-static inline void intctl_write1(u32 val)
-{
-    // INTCTL1
-    asm volatile("mcr p6,0,%0,c1,c0,0"::"r" (val));
-}
-
-static inline void intstr_write0(u32 val)
-{
-    // INTSTR0
-       asm volatile("mcr p6,0,%0,c2,c0,0"::"r" (val));
-}
-
-static inline void intstr_write1(u32 val)
-{
-    // INTSTR1
-       asm volatile("mcr p6,0,%0,c3,c0,0"::"r" (val));
-}
-
-static void
-iop331_irq_mask1 (unsigned int irq)
-{
-        iop331_mask0 &= ~(1 << (irq - IOP331_IRQ_OFS));
-        intctl_write0(iop331_mask0);
-}
-
-static void
-iop331_irq_mask2 (unsigned int irq)
-{
-        iop331_mask1 &= ~(1 << (irq - IOP331_IRQ_OFS - 32));
-        intctl_write1(iop331_mask1);
-}
-
-static void
-iop331_irq_unmask1(unsigned int irq)
-{
-        iop331_mask0 |= (1 << (irq - IOP331_IRQ_OFS));
-        intctl_write0(iop331_mask0);
-}
-
-static void
-iop331_irq_unmask2(unsigned int irq)
-{
-        iop331_mask1 |= (1 << (irq - IOP331_IRQ_OFS - 32));
-        intctl_write1(iop331_mask1);
-}
-
-struct irq_chip iop331_irqchip1 = {
-       .name   = "IOP-1",
-       .ack    = iop331_irq_mask1,
-       .mask   = iop331_irq_mask1,
-       .unmask = iop331_irq_unmask1,
-};
-
-struct irq_chip iop331_irqchip2 = {
-       .name   = "IOP-2",
-       .ack    = iop331_irq_mask2,
-       .mask   = iop331_irq_mask2,
-       .unmask = iop331_irq_unmask2,
-};
-
-void __init iop331_init_irq(void)
-{
-       unsigned int i, tmp;
-
-       /* Enable access to coprocessor 6 for dealing with IRQs.
-        * From RMK:
-        * Basically, the Intel documentation here is poor.  It appears that
-        * you need to set the bit to be able to access the coprocessor from
-        * SVC mode.  Whether that allows access from user space or not is
-        * unclear.
-        */
-       asm volatile (
-               "mrc p15, 0, %0, c15, c1, 0\n\t"
-               "orr %0, %0, %1\n\t"
-               "mcr p15, 0, %0, c15, c1, 0\n\t"
-               /* The action is delayed, so we have to do this: */
-               "mrc p15, 0, %0, c15, c1, 0\n\t"
-               "mov %0, %0\n\t"
-               "sub pc, pc, #4"
-               : "=r" (tmp) : "i" (1 << 6) );
-
-       intctl_write0(0);               // disable all interrupts
-       intctl_write1(0);
-       intstr_write0(0);               // treat all as IRQ
-       intstr_write1(0);
-       if(machine_is_iq80331())        // all interrupts are inputs to chip
-               *IOP331_PCIIRSR = 0x0f;
-
-       for(i = IOP331_IRQ_OFS; i < NR_IOP331_IRQS; i++)
-       {
-               set_irq_chip(i, (i < 32) ? &iop331_irqchip1 : &iop331_irqchip2);
-               set_irq_handler(i, do_level_IRQ);
-               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-       }
-}
-
diff --git a/arch/arm/mach-iop3xx/iop331-pci.c b/arch/arm/mach-iop3xx/iop331-pci.c
deleted file mode 100644 (file)
index 44dd213..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop331-pci.c
- *
- * PCI support for the Intel IOP331 chipset
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2003, 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/mach/pci.h>
-
-#include <asm/arch/iop331.h>
-
-#undef DEBUG
-#undef DEBUG1
-
-#ifdef DEBUG
-#define  DBG(x...) printk(x)
-#else
-#define  DBG(x...) do { } while (0)
-#endif
-
-#ifdef DEBUG1
-#define  DBG1(x...) printk(x)
-#else
-#define  DBG1(x...) do { } while (0)
-#endif
-
-/*
- * This routine builds either a type0 or type1 configuration command.  If the
- * bus is on the 80331 then a type0 made, else a type1 is created.
- */
-static u32 iop331_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
-       struct pci_sys_data *sys = bus->sysdata;
-       u32 addr;
-
-       if (sys->busnr == bus->number)
-               addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
-       else
-               addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
-
-       addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
-
-       return addr;
-}
-
-/*
- * This routine checks the status of the last configuration cycle.  If an error
- * was detected it returns a 1, else it returns a 0.  The errors being checked
- * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
- * the discovery stage.
- */
-static int iop331_pci_status(void)
-{
-       unsigned int status;
-       int ret = 0;
-
-       /*
-        * Check the status registers.
-        */
-       status = *IOP331_ATUSR;
-       if (status & 0xf900)
-       {
-               DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
-               *IOP331_ATUSR = status & 0xf900;
-               ret = 1;
-       }
-       status = *IOP331_ATUISR;
-       if (status & 0x679f)
-       {
-               DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
-               *IOP331_ATUISR = status & 0x679f;
-               ret = 1;
-       }
-       return ret;
-}
-
-/*
- * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
- * a delayed abort (in theory.)
- */
-static inline u32 iop331_read(unsigned long addr)
-{
-       u32 val;
-
-       __asm__ __volatile__(
-               "str    %1, [%2]\n\t"
-               "ldr    %0, [%3]\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               : "=r" (val)
-               : "r" (addr), "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
-
-       return val;
-}
-
-/*
- * The read routines must check the error status of the last configuration
- * cycle.  If there was an error, the routine returns all hex f's.
- */
-static int
-iop331_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-               int size, u32 *value)
-{
-       unsigned long addr = iop331_cfg_address(bus, devfn, where);
-       u32 val = iop331_read(addr) >> ((where & 3) * 8);
-
-       if( iop331_pci_status() )
-               val = 0xffffffff;
-
-       *value = val;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop331_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-               int size, u32 value)
-{
-       unsigned long addr = iop331_cfg_address(bus, devfn, where);
-       u32 val;
-
-       if (size != 4) {
-               val = iop331_read(addr);
-               if (!iop331_pci_status() == 0)
-                       return PCIBIOS_SUCCESSFUL;
-
-               where = (where & 3) * 8;
-
-               if (size == 1)
-                       val &= ~(0xff << where);
-               else
-                       val &= ~(0xffff << where);
-
-               *IOP331_OCCDR = val | value << where;
-       } else {
-               asm volatile(
-                       "str    %1, [%2]\n\t"
-                       "str    %0, [%3]\n\t"
-                       "nop\n\t"
-                       "nop\n\t"
-                       "nop\n\t"
-                       "nop\n\t"
-                       :
-                       : "r" (value), "r" (addr),
-                         "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
-       }
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop331_ops = {
-       .read   = iop331_read_config,
-       .write  = iop331_write_config,
-};
-
-/*
- * When a PCI device does not exist during config cycles, the XScale gets a
- * bus error instead of returning 0xffffffff. This handler simply returns.
- */
-int
-iop331_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
-       DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
-               addr, fsr, regs->ARM_pc, regs->ARM_lr);
-
-       /*
-        * If it was an imprecise abort, then we need to correct the
-        * return address to be _after_ the instruction.
-        */
-       if (fsr & (1 << 10))
-               regs->ARM_pc += 4;
-
-       return 0;
-}
-
-/*
- * Scan an IOP331 PCI bus.  sys->bus defines which bus we scan.
- */
-struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *sys)
-{
-       return pci_scan_bus(sys->busnr, &iop331_ops, sys);
-}
-
-void iop331_init(void)
-{
-       DBG1("PCI:  Intel 80331 PCI init code.\n");
-       DBG1("\tATU: IOP331_ATUCMD=0x%04x\n", *IOP331_ATUCMD);
-       DBG1("\tATU: IOP331_OMWTVR0=0x%04x, IOP331_OIOWTVR=0x%04x\n",
-                       *IOP331_OMWTVR0,
-                       *IOP331_OIOWTVR);
-       DBG1("\tATU: IOP331_OMWTVR1=0x%04x\n", *IOP331_OMWTVR1);
-       DBG1("\tATU: IOP331_ATUCR=0x%08x\n", *IOP331_ATUCR);
-       DBG1("\tATU: IOP331_IABAR0=0x%08x IOP331_IALR0=0x%08x IOP331_IATVR0=%08x\n", *IOP331_IABAR0, *IOP331_IALR0, *IOP331_IATVR0);
-       DBG1("\tATU: IOP31_IABAR1=0x%08x IOP331_IALR1=0x%08x\n", *IOP331_IABAR1, *IOP331_IALR1);
-       DBG1("\tATU: IOP331_ERBAR=0x%08x IOP331_ERLR=0x%08x IOP331_ERTVR=%08x\n", *IOP331_ERBAR, *IOP331_ERLR, *IOP331_ERTVR);
-       DBG1("\tATU: IOP331_IABAR2=0x%08x IOP331_IALR2=0x%08x IOP331_IATVR2=%08x\n", *IOP331_IABAR2, *IOP331_IALR2, *IOP331_IATVR2);
-       DBG1("\tATU: IOP331_IABAR3=0x%08x IOP331_IALR3=0x%08x IOP331_IATVR3=%08x\n", *IOP331_IABAR3, *IOP331_IALR3, *IOP331_IATVR3);
-
-       hook_fault_code(16+6, iop331_pci_abort, SIGBUS, "imprecise external abort");
-}
-
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
deleted file mode 100644 (file)
index 3cc98d8..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop331-setup.c
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2004 Intel 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.
- *
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#define IOP331_UART_XTAL 33334000
-
-/*
- * Standard IO mapping for all IOP331 based systems
- */
-static struct map_desc iop331_std_desc[] __initdata = {
-       {       /* mem mapped registers */
-               .virtual        = IOP331_VIRT_MEM_BASE,
-               .pfn            = __phys_to_pfn(IOP331_PHYS_MEM_BASE),
-               .length         = 0x00002000,
-               .type           = MT_DEVICE
-       }, {    /* PCI IO space */
-               .virtual        = IOP331_PCI_LOWER_IO_VA,
-               .pfn            = __phys_to_pfn(IOP331_PCI_LOWER_IO_PA),
-               .length         = IOP331_PCI_IO_WINDOW_SIZE,
-               .type           = MT_DEVICE
-       }
-};
-
-static struct resource iop33x_uart0_resources[] = {
-       [0] = {
-               .start = IOP331_UART0_PHYS,
-               .end = IOP331_UART0_PHYS + 0x3f,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IOP331_UART0,
-               .end = IRQ_IOP331_UART0,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-static struct resource iop33x_uart1_resources[] = {
-       [0] = {
-               .start = IOP331_UART1_PHYS,
-               .end = IOP331_UART1_PHYS + 0x3f,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IOP331_UART1,
-               .end = IRQ_IOP331_UART1,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-static struct plat_serial8250_port iop33x_uart0_data[] = {
-       {
-       .membase     = (char*)(IOP331_UART0_VIRT),
-       .mapbase     = (IOP331_UART0_PHYS),
-       .irq         = IRQ_IOP331_UART0,
-       .uartclk     = IOP331_UART_XTAL,
-       .regshift    = 2,
-       .iotype      = UPIO_MEM,
-       .flags       = UPF_SKIP_TEST,
-       },
-       {  },
-};
-
-static struct plat_serial8250_port iop33x_uart1_data[] = {
-       {
-       .membase     = (char*)(IOP331_UART1_VIRT),
-       .mapbase     = (IOP331_UART1_PHYS),
-       .irq         = IRQ_IOP331_UART1,
-       .uartclk     = IOP331_UART_XTAL,
-       .regshift    = 2,
-       .iotype      = UPIO_MEM,
-       .flags       = UPF_SKIP_TEST,
-       },
-       {  },
-};
-
-static struct platform_device iop33x_uart0 = {
-       .name = "serial8250",
-       .id = PLAT8250_DEV_PLATFORM,
-       .dev.platform_data = iop33x_uart0_data,
-       .num_resources = 2,
-       .resource = iop33x_uart0_resources,
-};
-
-static struct platform_device iop33x_uart1 = {
-       .name = "serial8250",
-       .id = PLAT8250_DEV_PLATFORM1,
-       .dev.platform_data = iop33x_uart1_data,
-       .num_resources = 2,
-       .resource = iop33x_uart1_resources,
-};
-
-static struct resource iop33x_i2c_0_resources[] = {
-       [0] = {
-               .start = 0xfffff680,
-               .end = 0xfffff698,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IOP331_I2C_0,
-               .end = IRQ_IOP331_I2C_0,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-static struct resource iop33x_i2c_1_resources[] = {
-       [0] = {
-               .start = 0xfffff6a0,
-               .end = 0xfffff6b8,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IOP331_I2C_1,
-               .end = IRQ_IOP331_I2C_1,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-static struct platform_device iop33x_i2c_0_controller = {
-       .name = "IOP3xx-I2C",
-       .id = 0,
-       .num_resources = 2,
-       .resource = iop33x_i2c_0_resources
-};
-
-static struct platform_device iop33x_i2c_1_controller = {
-       .name = "IOP3xx-I2C",
-       .id = 1,
-       .num_resources = 2,
-       .resource = iop33x_i2c_1_resources
-};
-
-static struct platform_device *iop33x_devices[] __initdata = {
-       &iop33x_uart0,
-       &iop33x_uart1,
-       &iop33x_i2c_0_controller,
-       &iop33x_i2c_1_controller
-};
-
-void __init iop33x_init(void)
-{
-       if(iop_is_331())
-       {
-               platform_add_devices(iop33x_devices,
-                               ARRAY_SIZE(iop33x_devices));
-       }
-}
-
-void __init iop331_map_io(void)
-{
-       iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
-}
-
-#ifdef CONFIG_ARCH_IOP331
-extern void iop331_init_irq(void);
-extern struct sys_timer iop331_timer;
-#endif
-
-#ifdef CONFIG_ARCH_IQ80331
-extern void iq80331_map_io(void);
-#endif
-
-#ifdef CONFIG_MACH_IQ80332
-extern void iq80332_map_io(void);
-#endif
-
-#if defined(CONFIG_ARCH_IQ80331)
-MACHINE_START(IQ80331, "Intel IQ80331")
-       /* Maintainer: Intel Corp. */
-       .phys_io        = 0xfefff000,
-       .io_pg_offst    = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
-       .map_io         = iq80331_map_io,
-       .init_irq       = iop331_init_irq,
-       .timer          = &iop331_timer,
-       .boot_params    = 0x0100,
-       .init_machine   = iop33x_init,
-MACHINE_END
-
-#elif defined(CONFIG_MACH_IQ80332)
-MACHINE_START(IQ80332, "Intel IQ80332")
-       /* Maintainer: Intel Corp. */
-       .phys_io        = 0xfefff000,
-       .io_pg_offst    = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
-       .map_io         = iq80332_map_io,
-       .init_irq       = iop331_init_irq,
-       .timer          = &iop331_timer,
-       .boot_params    = 0x0100,
-       .init_machine   = iop33x_init,
-MACHINE_END
-
-#else
-#error No machine descriptor defined for this IOP3XX implementation
-#endif
-
-
diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
deleted file mode 100644 (file)
index 0c09e74..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop331-time.c
- *
- * Timer code for IOP331 based systems
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- *
- * Copyright 2003 Intel Corp.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-static inline unsigned long get_elapsed(void)
-{
-       return LATCH - *IOP331_TU_TCR0;
-}
-
-static unsigned long iop331_gettimeoffset(void)
-{
-       unsigned long elapsed, usec;
-       u32 tisr1, tisr2;
-
-       /*
-        * If an interrupt was pending before we read the timer,
-        * we've already wrapped.  Factor this into the time.
-        * If an interrupt was pending after we read the timer,
-        * it may have wrapped between checking the interrupt
-        * status and reading the timer.  Re-read the timer to
-        * be sure its value is after the wrap.
-        */
-
-       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
-       elapsed = get_elapsed();
-       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
-
-       if(tisr1 & 1)
-               elapsed += LATCH;
-       else if (tisr2 & 1)
-               elapsed = LATCH + get_elapsed();
-
-       /*
-        * Now convert them to usec.
-        */
-       usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
-
-       return usec;
-}
-
-static irqreturn_t
-iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       u32 tisr;
-
-       write_seqlock(&xtime_lock);
-
-       asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
-       tisr |= 1;
-       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
-
-       timer_tick(regs);
-
-       write_sequnlock(&xtime_lock);
-       return IRQ_HANDLED;
-}
-
-static struct irqaction iop331_timer_irq = {
-       .name           = "IOP331 Timer Tick",
-       .handler        = iop331_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
-};
-
-static void __init iop331_timer_init(void)
-{
-       u32 timer_ctl;
-
-       setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq);
-
-       timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD |
-                       IOP331_TMR_RATIO_1_1;
-
-       asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
-
-       asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
-
-}
-
-struct sys_timer iop331_timer = {
-       .init           = iop331_timer_init,
-       .offset         = iop331_gettimeoffset,
-};
diff --git a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c
deleted file mode 100644 (file)
index e874b54..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80321 platform
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * 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/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80321 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-static struct map_desc iq31244_io_desc[] __initdata = {
-       {       /* on-board devices */
-               .virtual        = IQ31244_UART,
-               .pfn            = __phys_to_pfn(IQ31244_UART),
-               .length         = 0x00100000,
-               .type           = MT_DEVICE
-       }
-};
-
-void __init iq31244_map_io(void)
-{
-       iop321_map_io();
-
-       iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
-}
diff --git a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c
deleted file mode 100644 (file)
index f3c6413..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80321-pci.c
- *
- * PCI support for the Intel IQ80321 reference board
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)      \
-({ int _ctl_ = -1;                             \
-   unsigned int _idsel = idsel - minid;                \
-   if (_idsel <= maxid)                                \
-      _ctl_ = pci_irq_table[_idsel][pin-1];    \
-   _ctl_; })
-
-#define INTA   IRQ_IQ31244_INTA
-#define INTB   IRQ_IQ31244_INTB
-#define INTC   IRQ_IQ31244_INTC
-#define INTD   IRQ_IQ31244_INTD
-
-#define INTE   IRQ_IQ31244_I82546
-
-static inline int __init
-iq31244_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-       static int pci_irq_table[][4] = {
-               /*
-                * PCI IDSEL/INTPIN->INTLINE
-                * A       B       C       D
-                */
-#ifdef CONFIG_ARCH_EP80219
-               {INTB, INTB, INTB, INTB}, /* CFlash */
-               {INTE, INTE, INTE, INTE}, /* 82551 Pro 100 */
-               {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
-               {INTC, INTC, INTC, INTC}, /* SATA   */
-#else
-               {INTB, INTB, INTB, INTB}, /* CFlash */
-               {INTC, INTC, INTC, INTC}, /* SATA   */
-               {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
-               {INTE, INTE, INTE, INTE}, /* 82546 GigE */
-#endif // CONFIG_ARCH_EP80219
-       };
-
-       BUG_ON(pin < 1 || pin > 4);
-
-       return PCI_IRQ_TABLE_LOOKUP(0, 7);
-}
-
-static int iq31244_setup(int nr, struct pci_sys_data *sys)
-{
-       struct resource *res;
-
-       if(nr != 0)
-               return 0;
-
-       res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-       if (!res)
-               panic("PCI: unable to alloc resources");
-
-       res[0].start = IOP321_PCI_LOWER_IO_VA;
-       res[0].end   = IOP321_PCI_UPPER_IO_VA;
-       res[0].name  = "IQ31244 PCI I/O Space";
-       res[0].flags = IORESOURCE_IO;
-
-       res[1].start = IOP321_PCI_LOWER_MEM_PA;
-       res[1].end   = IOP321_PCI_UPPER_MEM_PA;
-       res[1].name  = "IQ31244 PCI Memory Space";
-       res[1].flags = IORESOURCE_MEM;
-
-       request_resource(&ioport_resource, &res[0]);
-       request_resource(&iomem_resource, &res[1]);
-
-       sys->mem_offset = IOP321_PCI_MEM_OFFSET;
-       sys->io_offset  = IOP321_PCI_IO_OFFSET;
-
-       sys->resource[0] = &res[0];
-       sys->resource[1] = &res[1];
-       sys->resource[2] = NULL;
-
-       return 1;
-}
-
-static void iq31244_preinit(void)
-{
-       iop321_init();
-}
-
-static struct hw_pci iq31244_pci __initdata = {
-       .swizzle        = pci_std_swizzle,
-       .nr_controllers = 1,
-       .setup          = iq31244_setup,
-       .scan           = iop321_scan_bus,
-       .preinit        = iq31244_preinit,
-       .map_irq        = iq31244_map_irq
-};
-
-static int __init iq31244_pci_init(void)
-{
-       if (machine_is_iq31244())
-               pci_common_init(&iq31244_pci);
-       return 0;
-}
-
-subsys_initcall(iq31244_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c
deleted file mode 100644 (file)
index d9cac5e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80321 platform
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- *
- * 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/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80321 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-static struct map_desc iq80321_io_desc[] __initdata = {
-       {       /* on-board devices */
-               .virtual        = IQ80321_UART,
-               .pfn            = __phys_to_pfn(IQ80321_UART),
-               .length         = 0x00100000,
-               .type           = MT_DEVICE
-       }
-};
-
-void __init iq80321_map_io(void)
-{
-       iop321_map_io();
-
-       iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
-}
diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c
deleted file mode 100644 (file)
index d9758d3..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80321-pci.c
- *
- * PCI support for the Intel IQ80321 reference board
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)      \
-({ int _ctl_ = -1;                             \
-   unsigned int _idsel = idsel - minid;                \
-   if (_idsel <= maxid)                                \
-      _ctl_ = pci_irq_table[_idsel][pin-1];    \
-   _ctl_; })
-
-#define INTA   IRQ_IQ80321_INTA
-#define INTB   IRQ_IQ80321_INTB
-#define INTC   IRQ_IQ80321_INTC
-#define INTD   IRQ_IQ80321_INTD
-
-#define INTE   IRQ_IQ80321_I82544
-
-static inline int __init
-iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-       static int pci_irq_table[][4] = {
-               /*
-                * PCI IDSEL/INTPIN->INTLINE
-                * A       B       C       D
-                */
-               {INTE, INTE, INTE, INTE}, /* Gig-E */
-               {-1, -1, -1, -1},         /* Unused */
-               {INTC, INTD, INTA, INTB}, /* PCI-X Slot */
-               {-1, -1, -1, -1},
-       };
-
-       BUG_ON(pin < 1 || pin > 4);
-
-//     return PCI_IRQ_TABLE_LOOKUP(4, 7);
-       return pci_irq_table[idsel%4][pin-1];
-}
-
-static int iq80321_setup(int nr, struct pci_sys_data *sys)
-{
-       struct resource *res;
-
-       if(nr != 0)
-               return 0;
-
-       res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-       if (!res)
-               panic("PCI: unable to alloc resources");
-
-       res[0].start = IOP321_PCI_LOWER_IO_VA;
-       res[0].end   = IOP321_PCI_UPPER_IO_VA;
-       res[0].name  = "IQ80321 PCI I/O Space";
-       res[0].flags = IORESOURCE_IO;
-
-       res[1].start = IOP321_PCI_LOWER_MEM_PA;
-       res[1].end   = IOP321_PCI_UPPER_MEM_PA;
-       res[1].name  = "IQ80321 PCI Memory Space";
-       res[1].flags = IORESOURCE_MEM;
-
-       request_resource(&ioport_resource, &res[0]);
-       request_resource(&iomem_resource, &res[1]);
-
-       sys->mem_offset = IOP321_PCI_MEM_OFFSET;
-       sys->io_offset  = IOP321_PCI_IO_OFFSET;
-
-       sys->resource[0] = &res[0];
-       sys->resource[1] = &res[1];
-       sys->resource[2] = NULL;
-
-       return 1;
-}
-
-static void iq80321_preinit(void)
-{
-       iop321_init();
-}
-
-static struct hw_pci iq80321_pci __initdata = {
-       .swizzle        = pci_std_swizzle,
-       .nr_controllers = 1,
-       .setup          = iq80321_setup,
-       .scan           = iop321_scan_bus,
-       .preinit        = iq80321_preinit,
-       .map_irq        = iq80321_map_irq
-};
-
-static int __init iq80321_pci_init(void)
-{
-       if (machine_is_iq80321())
-               pci_common_init(&iq80321_pci);
-       return 0;
-}
-
-subsys_initcall(iq80321_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-iop3xx/iq80331-mm.c b/arch/arm/mach-iop3xx/iq80331-mm.c
deleted file mode 100644 (file)
index 129eb49..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80331 platform
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003 Intel Corp.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80331 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-
-void __init iq80331_map_io(void)
-{
-       iop331_map_io();
-}
diff --git a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c
deleted file mode 100644 (file)
index 40d8610..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80331-pci.c
- *
- * PCI support for the Intel IQ80331 reference board
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2003, 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)      \
-({ int _ctl_ = -1;                             \
-   unsigned int _idsel = idsel - minid;                \
-   if (_idsel <= maxid)                                \
-      _ctl_ = pci_irq_table[_idsel][pin-1];    \
-   _ctl_; })
-
-#define INTA   IRQ_IQ80331_INTA
-#define INTB   IRQ_IQ80331_INTB
-#define INTC   IRQ_IQ80331_INTC
-#define INTD   IRQ_IQ80331_INTD
-
-//#define INTE IRQ_IQ80331_I82544
-
-static inline int __init
-iq80331_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-       static int pci_irq_table[][4] = {
-               /*
-                * PCI IDSEL/INTPIN->INTLINE
-                * A       B       C       D
-                */
-               {INTB, INTC, INTD, INTA}, /* PCI-X Slot */
-               {INTC, INTC, INTC, INTC}, /* GigE  */
-       };
-
-       BUG_ON(pin < 1 || pin > 4);
-
-       return PCI_IRQ_TABLE_LOOKUP(1, 7);
-}
-
-static int iq80331_setup(int nr, struct pci_sys_data *sys)
-{
-       struct resource *res;
-
-       if(nr != 0)
-               return 0;
-
-       res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-       if (!res)
-               panic("PCI: unable to alloc resources");
-
-       res[0].start = IOP331_PCI_LOWER_IO_VA;
-       res[0].end   = IOP331_PCI_UPPER_IO_VA;
-       res[0].name  = "IQ80331 PCI I/O Space";
-       res[0].flags = IORESOURCE_IO;
-
-       res[1].start = IOP331_PCI_LOWER_MEM_PA;
-       res[1].end   = IOP331_PCI_UPPER_MEM_PA;
-       res[1].name  = "IQ80331 PCI Memory Space";
-       res[1].flags = IORESOURCE_MEM;
-
-       request_resource(&ioport_resource, &res[0]);
-       request_resource(&iomem_resource, &res[1]);
-
-       sys->mem_offset = IOP331_PCI_MEM_OFFSET;
-       sys->io_offset  = IOP331_PCI_IO_OFFSET;
-
-       sys->resource[0] = &res[0];
-       sys->resource[1] = &res[1];
-       sys->resource[2] = NULL;
-
-       return 1;
-}
-
-static void iq80331_preinit(void)
-{
-       iop331_init();
-}
-
-static struct hw_pci iq80331_pci __initdata = {
-       .swizzle        = pci_std_swizzle,
-       .nr_controllers = 1,
-       .setup          = iq80331_setup,
-       .scan           = iop331_scan_bus,
-       .preinit        = iq80331_preinit,
-       .map_irq        = iq80331_map_irq
-};
-
-static int __init iq80331_pci_init(void)
-{
-       if (machine_is_iq80331())
-               pci_common_init(&iq80331_pci);
-       return 0;
-}
-
-subsys_initcall(iq80331_pci_init);
-
-
-
-
diff --git a/arch/arm/mach-iop3xx/iq80332-mm.c b/arch/arm/mach-iop3xx/iq80332-mm.c
deleted file mode 100644 (file)
index 2feaf75..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for iq80332 platform
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-
-/*
- * IQ80332 specific IO mappings
- *
- * We use RedBoot's setup for the onboard devices.
- */
-
-void __init iq80332_map_io(void)
-{
-       iop331_map_io();
-}
diff --git a/arch/arm/mach-iop3xx/iq80332-pci.c b/arch/arm/mach-iop3xx/iq80332-pci.c
deleted file mode 100644 (file)
index afc0676..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80332-pci.c
- *
- * PCI support for the Intel IQ80332 reference board
- *
- * Author: Dave Jiang <dave.jiang@intel.com>
- * Copyright (C) 2004 Intel Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)      \
-({ int _ctl_ = -1;                             \
-   unsigned int _idsel = idsel - minid;                \
-   if (_idsel <= maxid)                                \
-      _ctl_ = pci_irq_table[_idsel][pin-1];    \
-   _ctl_; })
-
-#define INTA   IRQ_IQ80332_INTA
-#define INTB   IRQ_IQ80332_INTB
-#define INTC   IRQ_IQ80332_INTC
-#define INTD   IRQ_IQ80332_INTD
-
-//#define INTE IRQ_IQ80332_I82544
-
-static inline int __init
-iq80332_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-       static int pci_irq_table[][8] = {
-               /*
-                * PCI IDSEL/INTPIN->INTLINE
-                * A       B       C       D
-                */
-               {-1,   -1,   -1,   -1},
-               {-1,   -1,   -1,   -1},
-               {-1,   -1,   -1,   -1},
-               {INTA, INTB, INTC, INTD}, /* PCI-X Slot */
-               {-1,   -1,   -1,   -1},
-               {INTC, INTC, INTC, INTC}, /* GigE  */
-               {-1,   -1,   -1,   -1},
-               {-1,   -1,   -1,   -1},
-       };
-
-       BUG_ON(pin < 1 || pin > 4);
-
-       return PCI_IRQ_TABLE_LOOKUP(1, 7);
-}
-
-static int iq80332_setup(int nr, struct pci_sys_data *sys)
-{
-       struct resource *res;
-
-       if(nr != 0)
-               return 0;
-
-       res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-       if (!res)
-               panic("PCI: unable to alloc resources");
-
-       res[0].start = IOP331_PCI_LOWER_IO_VA;
-       res[0].end   = IOP331_PCI_UPPER_IO_VA;
-       res[0].name  = "IQ80332 PCI I/O Space";
-       res[0].flags = IORESOURCE_IO;
-
-       res[1].start = IOP331_PCI_LOWER_MEM_PA;
-       res[1].end   = IOP331_PCI_UPPER_MEM_PA;
-       res[1].name  = "IQ80332 PCI Memory Space";
-       res[1].flags = IORESOURCE_MEM;
-
-       request_resource(&ioport_resource, &res[0]);
-       request_resource(&iomem_resource, &res[1]);
-
-       sys->mem_offset = IOP331_PCI_MEM_OFFSET;
-       sys->io_offset  = IOP331_PCI_IO_OFFSET;
-
-       sys->resource[0] = &res[0];
-       sys->resource[1] = &res[1];
-       sys->resource[2] = NULL;
-
-       return 1;
-}
-
-static void iq80332_preinit(void)
-{
-       iop331_init();
-}
-
-static struct hw_pci iq80332_pci __initdata = {
-       .swizzle        = pci_std_swizzle,
-       .nr_controllers = 1,
-       .setup          = iq80332_setup,
-       .scan           = iop331_scan_bus,
-       .preinit        = iq80332_preinit,
-       .map_irq        = iq80332_map_irq
-};
-
-static int __init iq80332_pci_init(void)
-{
-       if (machine_is_iq80332())
-               pci_common_init(&iq80332_pci);
-       return 0;
-}
-
-subsys_initcall(iq80332_pci_init);
-
-
-
-
index 7c25dbd5a181cb78723a5f969b55aebc94ba0029..35dd8b3824b0301a5d8fc9ecc4b849408c21324f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/bitops.h>
 #include <linux/time.h>
 #include <linux/timex.h>
+#include <linux/clocksource.h>
 
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
@@ -255,16 +256,6 @@ static unsigned volatile last_jiffy_time;
 
 #define CLOCK_TICKS_PER_USEC   ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
 
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long ixp4xx_gettimeoffset(void)
-{
-       u32 elapsed;
-
-       elapsed = *IXP4XX_OSTS - last_jiffy_time;
-
-       return elapsed / CLOCK_TICKS_PER_USEC;
-}
-
 static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        write_seqlock(&xtime_lock);
@@ -309,7 +300,6 @@ static void __init ixp4xx_timer_init(void)
 
 struct sys_timer ixp4xx_timer = {
        .init           = ixp4xx_timer_init,
-       .offset         = ixp4xx_gettimeoffset,
 };
 
 static struct resource ixp46x_i2c_resources[] = {
@@ -365,3 +355,29 @@ void __init ixp4xx_sys_init(void)
                        ixp4xx_exp_bus_size >> 20);
 }
 
+cycle_t ixp4xx_get_cycles(void)
+{
+       return *IXP4XX_OSTS;
+}
+
+static struct clocksource clocksource_ixp4xx = {
+       .name           = "OSTS",
+       .rating         = 200,
+       .read           = ixp4xx_get_cycles,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 20,
+       .is_continuous  = 1,
+};
+
+unsigned long ixp4xx_timer_freq = FREQ;
+static int __init ixp4xx_clocksource_init(void)
+{
+       clocksource_ixp4xx.mult =
+               clocksource_hz2mult(ixp4xx_timer_freq,
+                                   clocksource_ixp4xx.shift);
+       clocksource_register(&clocksource_ixp4xx);
+
+       return 0;
+}
+
+device_initcall(ixp4xx_clocksource_init);
index 749a337494d3a710769dad39239e3140dcd43448..162c266e5f8fb8ff3883f4df29ddc69c7f80e3ab 100644 (file)
@@ -159,6 +159,8 @@ static void nslu2_power_off(void)
 
 static void __init nslu2_init(void)
 {
+       ixp4xx_timer_freq = NSLU2_FREQ;
+
        ixp4xx_sys_init();
 
        nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
index c753a3c5aadd4f09d9e0e7e0cbde7de606410a0d..62e42c7a628e55ac1f86616064667ea2e0188534 100644 (file)
@@ -172,9 +172,11 @@ static struct resource kp_resources[] = {
 };
 
 static struct omap_kp_platform_data kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = fsample_keymap,
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = fsample_keymap,
+       .keymapsize     = ARRAY_SIZE(fsample_keymap),
+       .delay          = 4,
 };
 
 static struct platform_device kp_device = {
index cd3a06dfc0a83d2e5f0d280c4ace0f49cef988c3..6e113078f7ab4fa3415f42d68901e3e0ecc0aaaf 100644 (file)
@@ -167,10 +167,13 @@ static struct resource h2_kp_resources[] = {
 };
 
 static struct omap_kp_platform_data h2_kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = h2_keymap,
-       .rep    = 1,
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = h2_keymap,
+       .keymapsize     = ARRAY_SIZE(h2_keymap),
+       .rep            = 1,
+       .delay          = 9,
+       .dbounce        = 1,
 };
 
 static struct platform_device h2_kp_device = {
index 7b206116cd0391882f6d093325150bf9577acd80..f225a083dee1bb13073127a6cc05c6a21e199cfa 100644 (file)
@@ -247,10 +247,13 @@ static struct resource h3_kp_resources[] = {
 };
 
 static struct omap_kp_platform_data h3_kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = h3_keymap,
-       .rep    = 1,
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = h3_keymap,
+       .keymapsize     = ARRAY_SIZE(h3_keymap),
+       .rep            = 1,
+       .delay          = 9,
+       .dbounce        = 1,
 };
 
 static struct platform_device h3_kp_device = {
index 4cbc62db5b5dd5cd6a72da1c4efbdf2ec56b8aa2..cb00530ad279392725581ae81b57c07a215eb1e6 100644 (file)
@@ -159,9 +159,11 @@ static struct resource innovator_kp_resources[] = {
 };
 
 static struct omap_kp_platform_data innovator_kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = innovator_keymap,
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = innovator_keymap,
+       .keymapsize     = ARRAY_SIZE(innovator_keymap),
+       .delay          = 4,
 };
 
 static struct platform_device innovator_kp_device = {
index 02b980d77b12d2079e84d23a27eea010005707be..dbc555d209ff914eeff8b0b51d77d814212e430b 100644 (file)
@@ -71,9 +71,11 @@ static struct resource nokia770_kp_resources[] = {
 };
 
 static struct omap_kp_platform_data nokia770_kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = nokia770_keymap
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = nokia770_keymap,
+       .keymapsize     = ARRAY_SIZE(nokia770_keymap)
+       .delay          = 4,
 };
 
 static struct platform_device nokia770_kp_device = {
index b742261c97ade63be4e744070d374ab66407bd4e..6b05647a6c01743504650c1021013b19dc367f51 100644 (file)
@@ -266,9 +266,11 @@ static const int osk_keymap[] = {
 };
 
 static struct omap_kp_platform_data osk_kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = (int *) osk_keymap,
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = (int *) osk_keymap,
+       .keymapsize     = ARRAY_SIZE(osk_keymap),
+       .delay          = 9,
 };
 
 static struct resource osk5912_kp_resources[] = {
index 64b45d8ae357e9e7e3addb767707201672aa6031..fa4be962df67b454c09afc2ea956f11251904825 100644 (file)
@@ -171,9 +171,12 @@ static struct resource kp_resources[] = {
 };
 
 static struct omap_kp_platform_data kp_data = {
-       .rows   = 8,
-       .cols   = 8,
-       .keymap = p2_keymap,
+       .rows           = 8,
+       .cols           = 8,
+       .keymap         = p2_keymap,
+       .keymapsize     = ARRAY_SIZE(p2_keymap),
+       .delay          = 4,
+       .dbounce        = 1,
 };
 
 static struct platform_device kp_device = {
index f1958e882e8694e3bd480dd46b62af3f351c6d28..638490e62d5f5ebb7e07a21f586c521b9b2f2fe2 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 
 #include <asm/io.h>
+#include <asm/mach-types.h>
 
 #include <asm/arch/cpu.h>
 #include <asm/arch/usb.h>
@@ -586,77 +587,53 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
  *-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
-/*
- * Resets some clocks that may be left on from bootloader,
- * but leaves serial clocks on. See also omap_late_clk_reset().
- */
-static inline void omap1_early_clk_reset(void)
-{
-       //omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
-}
 
-static int __init omap1_late_clk_reset(void)
+static void __init omap1_clk_disable_unused(struct clk *clk)
 {
-       /* Turn off all unused clocks */
-       struct clk *p;
        __u32 regval32;
 
-       /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
-       regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
-       omap_writew(regval32, SOFT_REQ_REG);
-       omap_writew(0, SOFT_REQ_REG2);
-
-       list_for_each_entry(p, &clocks, node) {
-               if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) ||
-                       p->enable_reg == 0)
-                       continue;
-
-               /* Clocks in the DSP domain need api_ck. Just assume bootloader
-                * has not enabled any DSP clocks */
-               if ((u32)p->enable_reg == DSP_IDLECT2) {
-                       printk(KERN_INFO "Skipping reset check for DSP domain "
-                              "clock \"%s\"\n", p->name);
-                       continue;
-               }
+       /* Clocks in the DSP domain need api_ck. Just assume bootloader
+        * has not enabled any DSP clocks */
+       if ((u32)clk->enable_reg == DSP_IDLECT2) {
+               printk(KERN_INFO "Skipping reset check for DSP domain "
+                      "clock \"%s\"\n", clk->name);
+               return;
+       }
 
-               /* Is the clock already disabled? */
-               if (p->flags & ENABLE_REG_32BIT) {
-                       if (p->flags & VIRTUAL_IO_ADDRESS)
-                               regval32 = __raw_readl(p->enable_reg);
-                       else
-                               regval32 = omap_readl(p->enable_reg);
-               } else {
-                       if (p->flags & VIRTUAL_IO_ADDRESS)
-                               regval32 = __raw_readw(p->enable_reg);
+       /* Is the clock already disabled? */
+       if (clk->flags & ENABLE_REG_32BIT) {
+               if (clk->flags & VIRTUAL_IO_ADDRESS)
+                       regval32 = __raw_readl(clk->enable_reg);
                        else
-                               regval32 = omap_readw(p->enable_reg);
-               }
-
-               if ((regval32 & (1 << p->enable_bit)) == 0)
-                       continue;
+                               regval32 = omap_readl(clk->enable_reg);
+       } else {
+               if (clk->flags & VIRTUAL_IO_ADDRESS)
+                       regval32 = __raw_readw(clk->enable_reg);
+               else
+                       regval32 = omap_readw(clk->enable_reg);
+       }
 
-               /* FIXME: This clock seems to be necessary but no-one
-                * has asked for its activation. */
-               if (p == &tc2_ck         // FIX: pm.c (SRAM), CCP, Camera
-                   || p == &ck_dpll1out.clk // FIX: SoSSI, SSR
-                   || p == &arm_gpio_ck // FIX: GPIO code for 1510
-                   ) {
-                       printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
-                              p->name);
-                       continue;
-               }
+       if ((regval32 & (1 << clk->enable_bit)) == 0)
+               return;
 
-               printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name);
-               p->disable(p);
-               printk(" done\n");
+       /* FIXME: This clock seems to be necessary but no-one
+        * has asked for its activation. */
+       if (clk == &tc2_ck              // FIX: pm.c (SRAM), CCP, Camera
+           || clk == &ck_dpll1out.clk  // FIX: SoSSI, SSR
+           || clk == &arm_gpio_ck      // FIX: GPIO code for 1510
+               ) {
+               printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
+                      clk->name);
+               return;
        }
 
-       return 0;
+       printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
+       clk->disable(clk);
+       printk(" done\n");
 }
-late_initcall(omap1_late_clk_reset);
 
 #else
-#define omap1_early_clk_reset()        {}
+#define omap1_clk_disable_unused       NULL
 #endif
 
 static struct clk_functions omap1_clk_functions = {
@@ -664,6 +641,7 @@ static struct clk_functions omap1_clk_functions = {
        .clk_disable            = omap1_clk_disable,
        .clk_round_rate         = omap1_clk_round_rate,
        .clk_set_rate           = omap1_clk_set_rate,
+       .clk_disable_unused     = omap1_clk_disable_unused,
 };
 
 int __init omap1_clk_init(void)
@@ -671,8 +649,13 @@ int __init omap1_clk_init(void)
        struct clk ** clkp;
        const struct omap_clock_config *info;
        int crystal_type = 0; /* Default 12 MHz */
+       u32 reg;
+
+       /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
+       reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
+       omap_writew(reg, SOFT_REQ_REG);
+       omap_writew(0, SOFT_REQ_REG2);
 
-       omap1_early_clk_reset();
        clk_init(&omap1_clk_functions);
 
        /* By default all idlect1 clocks are allowed to idle */
@@ -772,6 +755,12 @@ int __init omap1_clk_init(void)
        omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
 #endif
 
+       /* Amstrad Delta wants BCLK high when inactive */
+       if (machine_is_ams_delta())
+               omap_writel(omap_readl(ULPD_CLOCK_CTRL) |
+                               (1 << SDW_MCLK_INV_BIT),
+                               ULPD_CLOCK_CTRL);
+
        /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
        /* (on 730, bit 13 must not be cleared) */
        if (cpu_is_omap730())
index b7c68819c4e7e2391cf474491bd441f0d8b38bc6..f7df00205c4a6541827cb6e8331901b4c229e34b 100644 (file)
@@ -89,6 +89,7 @@ struct arm_idlect1_clk {
 #define EN_DSPTIMCK    5
 
 /* Various register defines for clock controls scattered around OMAP chip */
+#define SDW_MCLK_INV_BIT       2       /* In ULPD_CLKC_CTRL */
 #define USB_MCLK_EN_BIT                4       /* In ULPD_CLKC_CTRL */
 #define USB_HOST_HHC_UHOST_EN  9       /* In MOD_CONF_CTRL_0 */
 #define SWD_ULPD_PLL_CLK_REQ   1       /* In SWD_CLK_DIV_CTRL_SEL */
@@ -741,6 +742,18 @@ static struct clk i2c_fck = {
        .disable        = &omap1_clk_disable_generic,
 };
 
+static struct clk i2c_ick = {
+       .name           = "i2c_ick",
+       .id             = 1,
+       .flags          = CLOCK_IN_OMAP16XX |
+                         VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+                         ALWAYS_ENABLED,
+       .parent         = &armper_ck.clk,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable_generic,
+       .disable        = &omap1_clk_disable_generic,
+};
+
 static struct clk * onchip_clks[] = {
        /* non-ULPD clocks */
        &ck_ref,
@@ -790,6 +803,7 @@ static struct clk * onchip_clks[] = {
        /* Virtual clocks */
        &virtual_ck_mpu,
        &i2c_fck,
+       &i2c_ick,
 };
 
 #endif
index fa74ef7af15f730d8af3da0a150982c0b50ae675..5432335bc493de0d65e44155909bd5ff413d7195 100644 (file)
@@ -199,6 +199,17 @@ MUX_CFG("N14_1610_UWIRE_CS0",       8,    9,    1,   1,  21,   0,    1,     1,  1)
 MUX_CFG("P15_1610_UWIRE_CS3",   8,   12,    1,   1,  22,   0,    1,     1,  1)
 MUX_CFG("N15_1610_UWIRE_CS1",   7,   18,    2,   1,  14,   0,   NA,     0,  1)
 
+/* OMAP-1610 SPI */
+MUX_CFG("U19_1610_SPIF_SCK",    7,    21,   6,   1,  15,   0,    1,     1,  1)
+MUX_CFG("U18_1610_SPIF_DIN",    8,    0,    6,   1,  18,   1,    1,     0,  1)
+MUX_CFG("P20_1610_SPIF_DIN",    6,    27,   4,   1,   7,   1,    1,     0,  1)
+MUX_CFG("W21_1610_SPIF_DOUT",   8,    3,    6,   1,  19,   0,    1,     0,  1)
+MUX_CFG("R18_1610_SPIF_DOUT",   7,    9,    3,   1,  11,   0,    1,     0,  1)
+MUX_CFG("N14_1610_SPIF_CS0",    8,    9,    6,   1,  21,   0,    1,     1,  1)
+MUX_CFG("N15_1610_SPIF_CS1",    7,    18,   6,   1,  14,   0,    1,     1,  1)
+MUX_CFG("T19_1610_SPIF_CS2",    7,    15,   4,   1,  13,   0,    1,     1,  1)
+MUX_CFG("P15_1610_SPIF_CS3",    8,    12,   3,   1,  22,   0,    1,     1,  1)
+
 /* OMAP-1610 Flash */
 MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,         NA,   0,   0,   NA,     0,  1)
 MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,         NA,   0,   0,   NA,     0,  1)
index 7993b7bae2bdaaae807305b54527bec43a40abae..2db6b732b084837fe29e7f4d5f7213b213c88ee9 100644 (file)
@@ -166,8 +166,8 @@ static struct omap_uart_config apollon_uart_config __initdata = {
 
 static struct omap_mmc_config apollon_mmc_config __initdata = {
        .mmc [0] = {
-               .enabled        = 0,
-               .wire4          = 0,
+               .enabled        = 1,
+               .wire4          = 1,
                .wp_pin         = -1,
                .power_pin      = -1,
                .switch_pin     = -1,
@@ -257,6 +257,9 @@ static void __init omap_apollon_init(void)
        /* REVISIT: where's the correct place */
        omap_cfg_reg(W19_24XX_SYS_NIRQ);
 
+       /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */
+       CONTROL_DEVCONF |= (1 << 24);
+
        /*
         * Make sure the serial ports are muxed on at this point.
         * You have to mux them off in device drivers later on
index 4933fce766c8269569b3e4f8bec8843e5c987916..996aeda1285d058e6abe2b39df36bfb5bbcf75b1 100644 (file)
@@ -245,6 +245,7 @@ static struct omap_kp_platform_data h4_kp_data = {
        .rows           = 6,
        .cols           = 7,
        .keymap         = h4_keymap,
+       .keymapsize     = ARRAY_SIZE(h4_keymap),
        .rep            = 1,
        .row_gpios      = row_gpios,
        .col_gpios      = col_gpios,
index d1b648a4efbfde4ad325e1f136fab6d226fb2789..0de201c3d50b4a09d488109338d90a1df12597a9 100644 (file)
 #include "memory.h"
 #include "clock.h"
 
+#undef DEBUG
+
 //#define DOWN_VARIABLE_DPLL 1                 /* Experimental */
 
 static struct prcm_config *curr_prcm_set;
 static u32 curr_perf_level = PRCM_FULL_SPEED;
+static struct clk *vclk;
+static struct clk *sclk;
 
 /*-------------------------------------------------------------------------
  * Omap2 specific clock functions
@@ -79,6 +83,14 @@ static void omap2_propagate_rate(struct clk * clk)
        propagate_rate(clk);
 }
 
+static void omap2_set_osc_ck(int enable)
+{
+       if (enable)
+               PRCM_CLKSRC_CTRL &= ~(0x3 << 3);
+       else
+               PRCM_CLKSRC_CTRL |= 0x3 << 3;
+}
+
 /* Enable an APLL if off */
 static void omap2_clk_fixed_enable(struct clk *clk)
 {
@@ -101,12 +113,54 @@ static void omap2_clk_fixed_enable(struct clk *clk)
        else if (clk == &apll54_ck)
                cval = (1 << 6);
 
-       while (!CM_IDLEST_CKGEN & cval) {               /* Wait for lock */
+       while (!(CM_IDLEST_CKGEN & cval)) {             /* Wait for lock */
                ++i;
                udelay(1);
-               if (i == 100000)
+               if (i == 100000) {
+                       printk(KERN_ERR "Clock %s didn't lock\n", clk->name);
+                       break;
+               }
+       }
+}
+
+static void omap2_clk_wait_ready(struct clk *clk)
+{
+       unsigned long reg, other_reg, st_reg;
+       u32 bit;
+       int i;
+
+       reg = (unsigned long) clk->enable_reg;
+       if (reg == (unsigned long) &CM_FCLKEN1_CORE ||
+           reg == (unsigned long) &CM_FCLKEN2_CORE)
+               other_reg = (reg & ~0xf0) | 0x10;
+       else if (reg == (unsigned long) &CM_ICLKEN1_CORE ||
+                reg == (unsigned long) &CM_ICLKEN2_CORE)
+               other_reg = (reg & ~0xf0) | 0x00;
+       else
+               return;
+
+       /* No check for DSS or cam clocks */
+       if ((reg & 0x0f) == 0) {
+               if (clk->enable_bit <= 1 || clk->enable_bit == 31)
+                       return;
+       }
+
+       /* Check if both functional and interface clocks
+        * are running. */
+       bit = 1 << clk->enable_bit;
+       if (!(__raw_readl(other_reg) & bit))
+               return;
+       st_reg = (other_reg & ~0xf0) | 0x20;
+       i = 0;
+       while (!(__raw_readl(st_reg) & bit)) {
+               i++;
+               if (i == 100000) {
+                       printk(KERN_ERR "Timeout enabling clock %s\n", clk->name);
                        break;
+               }
        }
+       if (i)
+               pr_debug("Clock %s stable after %d loops\n", clk->name, i);
 }
 
 /* Enables clock without considering parent dependencies or use count
@@ -119,6 +173,11 @@ static int _omap2_clk_enable(struct clk * clk)
        if (clk->flags & ALWAYS_ENABLED)
                return 0;
 
+       if (unlikely(clk == &osc_ck)) {
+               omap2_set_osc_ck(1);
+               return 0;
+       }
+
        if (unlikely(clk->enable_reg == 0)) {
                printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
                       clk->name);
@@ -133,6 +192,9 @@ static int _omap2_clk_enable(struct clk * clk)
        regval32 = __raw_readl(clk->enable_reg);
        regval32 |= (1 << clk->enable_bit);
        __raw_writel(regval32, clk->enable_reg);
+       wmb();
+
+       omap2_clk_wait_ready(clk);
 
        return 0;
 }
@@ -155,6 +217,11 @@ static void _omap2_clk_disable(struct clk *clk)
 {
        u32 regval32;
 
+       if (unlikely(clk == &osc_ck)) {
+               omap2_set_osc_ck(0);
+               return;
+       }
+
        if (clk->enable_reg == 0)
                return;
 
@@ -166,6 +233,7 @@ static void _omap2_clk_disable(struct clk *clk)
        regval32 = __raw_readl(clk->enable_reg);
        regval32 &= ~(1 << clk->enable_bit);
        __raw_writel(regval32, clk->enable_reg);
+       wmb();
 }
 
 static int omap2_clk_enable(struct clk *clk)
@@ -695,12 +763,14 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
                reg_val = __raw_readl(reg);
                reg_val &= ~(field_mask << div_off);
                reg_val |= (field_val << div_off);
-
                __raw_writel(reg_val, reg);
+               wmb();
                clk->rate = clk->parent->rate / field_val;
 
-               if (clk->flags & DELAYED_APP)
+               if (clk->flags & DELAYED_APP) {
                        __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+                       wmb();
+               }
                ret = 0;
        } else if (clk->set_rate != 0)
                ret = clk->set_rate(clk, rate);
@@ -836,10 +906,12 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
                reg_val = __raw_readl(reg) & ~(field_mask << src_off);
                reg_val |= (field_val << src_off);
                __raw_writel(reg_val, reg);
+               wmb();
 
-               if (clk->flags & DELAYED_APP)
+               if (clk->flags & DELAYED_APP) {
                        __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
-
+                       wmb();
+               }
                if (clk->usecount > 0)
                        _omap2_clk_enable(clk);
 
@@ -953,12 +1025,29 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
  * Omap2 clock reset and init functions
  *-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+static void __init omap2_clk_disable_unused(struct clk *clk)
+{
+       u32 regval32;
+
+       regval32 = __raw_readl(clk->enable_reg);
+       if ((regval32 & (1 << clk->enable_bit)) == 0)
+               return;
+
+       printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
+       _omap2_clk_disable(clk);
+}
+#else
+#define omap2_clk_disable_unused       NULL
+#endif
+
 static struct clk_functions omap2_clk_functions = {
        .clk_enable             = omap2_clk_enable,
        .clk_disable            = omap2_clk_disable,
        .clk_round_rate         = omap2_clk_round_rate,
        .clk_set_rate           = omap2_clk_set_rate,
        .clk_set_parent         = omap2_clk_set_parent,
+       .clk_disable_unused     = omap2_clk_disable_unused,
 };
 
 static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
@@ -984,27 +1073,19 @@ static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
        sys->rate = sclk;
 }
 
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-static void __init omap2_disable_unused_clocks(void)
+/*
+ * Set clocks for bypass mode for reboot to work.
+ */
+void omap2_clk_prepare_for_reboot(void)
 {
-       struct clk *ck;
-       u32 regval32;
+       u32 rate;
 
-       list_for_each_entry(ck, &clocks, node) {
-               if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
-                       ck->enable_reg == 0)
-                       continue;
-
-               regval32 = __raw_readl(ck->enable_reg);
-               if ((regval32 & (1 << ck->enable_bit)) == 0)
-                       continue;
+       if (vclk == NULL || sclk == NULL)
+               return;
 
-               printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
-               _omap2_clk_disable(ck);
-       }
+       rate = clk_get_rate(sclk);
+       clk_set_rate(vclk, rate);
 }
-late_initcall(omap2_disable_unused_clocks);
-#endif
 
 /*
  * Switch the MPU rate if specified on cmdline.
@@ -1077,8 +1158,27 @@ int __init omap2_clk_init(void)
         */
        clk_enable(&sync_32k_ick);
        clk_enable(&omapctrl_ick);
+
+       /* Force the APLLs active during bootup to avoid disabling and
+        * enabling them unnecessarily. */
+       clk_enable(&apll96_ck);
+       clk_enable(&apll54_ck);
+
        if (cpu_is_omap2430())
                clk_enable(&sdrc_ick);
 
+       /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
+       vclk = clk_get(NULL, "virt_prcm_set");
+       sclk = clk_get(NULL, "sys_ck");
+
+       return 0;
+}
+
+static int __init omap2_disable_aplls(void)
+{
+       clk_disable(&apll96_ck);
+       clk_disable(&apll54_ck);
+
        return 0;
 }
+late_initcall(omap2_disable_aplls);
index 2781dfbc51644815f778e84b047fc3d02eac0525..8816f5a33a289b12aa59669d291c1a5d20dc7fde 100644 (file)
@@ -560,7 +560,7 @@ static struct clk osc_ck = {                /* (*12, *13, 19.2, *26, 38.4)MHz */
        .name           = "osc_ck",
        .rate           = 26000000,             /* fixed up in clock init */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-                               RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+                               RATE_FIXED | RATE_PROPAGATES,
 };
 
 /* With out modem likely 12MHz, with modem likely 13MHz */
@@ -1368,7 +1368,8 @@ static struct clk mcbsp5_fck = {
 };
 
 static struct clk mcspi1_ick = {
-       .name           = "mcspi1_ick",
+       .name           = "mcspi_ick",
+       .id             = 1,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
        .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1377,7 +1378,8 @@ static struct clk mcspi1_ick = {
 };
 
 static struct clk mcspi1_fck = {
-       .name           = "mcspi1_fck",
+       .name           = "mcspi_fck",
+       .id             = 1,
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
        .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1386,7 +1388,8 @@ static struct clk mcspi1_fck = {
 };
 
 static struct clk mcspi2_ick = {
-       .name           = "mcspi2_ick",
+       .name           = "mcspi_ick",
+       .id             = 2,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
        .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1395,7 +1398,8 @@ static struct clk mcspi2_ick = {
 };
 
 static struct clk mcspi2_fck = {
-       .name           = "mcspi2_fck",
+       .name           = "mcspi_fck",
+       .id             = 2,
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
        .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1404,7 +1408,8 @@ static struct clk mcspi2_fck = {
 };
 
 static struct clk mcspi3_ick = {
-       .name           = "mcspi3_ick",
+       .name           = "mcspi_ick",
+       .id             = 3,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
        .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
@@ -1413,7 +1418,8 @@ static struct clk mcspi3_ick = {
 };
 
 static struct clk mcspi3_fck = {
-       .name           = "mcspi3_fck",
+       .name           = "mcspi_fck",
+       .id             = 3,
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP243X,
        .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
index c7a48f921fef01b58464fbdb85fd760578817ba7..f4f04d87df32902ae37b377af9cbb352d906e021 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
 
 #include <asm/io.h>
 #include <asm/arch/gpmc.h>
 #define GPMC_CS0               0x60
 #define GPMC_CS_SIZE           0x30
 
+#define GPMC_CS_NUM            8
+#define GPMC_MEM_START         0x00000000
+#define GPMC_MEM_END           0x3FFFFFFF
+#define BOOT_ROM_SPACE         0x100000        /* 1MB */
+
+#define GPMC_CHUNK_SHIFT       24              /* 16 MB */
+#define GPMC_SECTION_SHIFT     28              /* 128 MB */
+
+static struct resource gpmc_mem_root;
+static struct resource gpmc_cs_mem[GPMC_CS_NUM];
+static spinlock_t      gpmc_mem_lock = SPIN_LOCK_UNLOCKED;
+static unsigned                gpmc_cs_map;
+
 static void __iomem *gpmc_base =
        (void __iomem *) IO_ADDRESS(GPMC_BASE);
 static void __iomem *gpmc_cs_base =
@@ -187,9 +202,168 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
        return 0;
 }
 
-unsigned long gpmc_cs_get_base_addr(int cs)
+static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+{
+       u32 l;
+       u32 mask;
+
+       mask = (1 << GPMC_SECTION_SHIFT) - size;
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       l &= ~0x3f;
+       l = (base >> GPMC_CHUNK_SHIFT) & 0x3f;
+       l &= ~(0x0f << 8);
+       l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
+       l |= 1 << 6;            /* CSVALID */
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_disable_mem(int cs)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       l &= ~(1 << 6);         /* CSVALID */
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+{
+       u32 l;
+       u32 mask;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       *base = (l & 0x3f) << GPMC_CHUNK_SHIFT;
+       mask = (l >> 8) & 0x0f;
+       *size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT);
+}
+
+static int gpmc_cs_mem_enabled(int cs)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       return l & (1 << 6);
+}
+
+static void gpmc_cs_set_reserved(int cs, int reserved)
 {
-       return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24;
+       gpmc_cs_map &= ~(1 << cs);
+       gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+}
+
+static int gpmc_cs_reserved(int cs)
+{
+       return gpmc_cs_map & (1 << cs);
+}
+
+static unsigned long gpmc_mem_align(unsigned long size)
+{
+       int order;
+
+       size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
+       order = GPMC_CHUNK_SHIFT - 1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+       size = 1 << order;
+       return size;
+}
+
+static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+{
+       struct resource *res = &gpmc_cs_mem[cs];
+       int r;
+
+       size = gpmc_mem_align(size);
+       spin_lock(&gpmc_mem_lock);
+       res->start = base;
+       res->end = base + size - 1;
+       r = request_resource(&gpmc_mem_root, res);
+       spin_unlock(&gpmc_mem_lock);
+
+       return r;
+}
+
+int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
+{
+       struct resource *res = &gpmc_cs_mem[cs];
+       int r = -1;
+
+       if (cs > GPMC_CS_NUM)
+               return -ENODEV;
+
+       size = gpmc_mem_align(size);
+       if (size > (1 << GPMC_SECTION_SHIFT))
+               return -ENOMEM;
+
+       spin_lock(&gpmc_mem_lock);
+       if (gpmc_cs_reserved(cs)) {
+               r = -EBUSY;
+               goto out;
+       }
+       if (gpmc_cs_mem_enabled(cs))
+               r = adjust_resource(res, res->start & ~(size - 1), size);
+       if (r < 0)
+               r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+                                     size, NULL, NULL);
+       if (r < 0)
+               goto out;
+
+       gpmc_cs_enable_mem(cs, res->start, res->end - res->start + 1);
+       *base = res->start;
+       gpmc_cs_set_reserved(cs, 1);
+out:
+       spin_unlock(&gpmc_mem_lock);
+       return r;
+}
+
+void gpmc_cs_free(int cs)
+{
+       spin_lock(&gpmc_mem_lock);
+       if (cs >= GPMC_CS_NUM || !gpmc_cs_reserved(cs)) {
+               printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
+               BUG();
+               spin_unlock(&gpmc_mem_lock);
+               return;
+       }
+       gpmc_cs_disable_mem(cs);
+       release_resource(&gpmc_cs_mem[cs]);
+       gpmc_cs_set_reserved(cs, 0);
+       spin_unlock(&gpmc_mem_lock);
+}
+
+void __init gpmc_mem_init(void)
+{
+       int cs;
+       unsigned long boot_rom_space = 0;
+
+       if (cpu_is_omap242x()) {
+               u32 l;
+               l = omap_readl(OMAP242X_CONTROL_STATUS);
+               /* In case of internal boot the 1st MB is redirected to the
+                * boot ROM memory space.
+                */
+               if (l & (1 << 3))
+                       boot_rom_space = BOOT_ROM_SPACE;
+       } else
+               /* We assume internal boot if the mode can't be
+                * determined.
+                */
+               boot_rom_space = BOOT_ROM_SPACE;
+       gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+       gpmc_mem_root.end = GPMC_MEM_END;
+
+       /* Reserve all regions that has been set up by bootloader */
+       for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+               u32 base, size;
+
+               if (!gpmc_cs_mem_enabled(cs))
+                       continue;
+               gpmc_cs_get_memconf(cs, &base, &size);
+               if (gpmc_cs_insert_mem(cs, base, size) < 0)
+                       BUG();
+       }
 }
 
 void __init gpmc_init(void)
@@ -206,4 +380,6 @@ void __init gpmc_init(void)
        l &= 0x03 << 3;
        l |= (0x02 << 3) | (1 << 0);
        gpmc_write_reg(GPMC_SYSCONFIG, l);
+
+       gpmc_mem_init();
 }
index dfc3b35cc1ffaeb00f57ba31d55ab1f66797e251..1ed2fff4691a348b38faa68e4cff766bf0203e46 100644 (file)
@@ -41,18 +41,6 @@ static struct omap_irq_bank {
                .nr_irqs        = 96,
        }, {
                /* XXX: DSP INTC */
-
-#if 0
-       /*
-        * Commented out for now until we fix the IVA clocking
-        */
-#ifdef CONFIG_ARCH_OMAP2420
-       }, {
-               /* IVA INTC (2420 only) */
-               .base_reg       = OMAP24XX_IVA_INTC_BASE,
-               .nr_irqs        = 16,   /* Actually 32, but only 16 are used */
-#endif
-#endif
        }
 };
 
index 60ef084faffd04e8102ac9c3dbbc94d58b0cef2c..f538d0fdb13c35a47ec2bca1c3996f1b8e44c9c0 100644 (file)
@@ -104,6 +104,20 @@ MUX_CFG_24XX("P20_24XX_TSC_IRQ",   0x108,  0,      0,      0,      1)
 MUX_CFG_24XX("K15_24XX_UART3_TX",      0x118,  0,      0,      0,      1)
 MUX_CFG_24XX("K14_24XX_UART3_RX",      0x119,  0,      0,      0,      1)
 
+/* MMC/SDIO */
+MUX_CFG_24XX("G19_24XX_MMC_CLKO",      0x0f3,  0,      0,      0,      1)
+MUX_CFG_24XX("H18_24XX_MMC_CMD",       0x0f4,  0,      0,      0,      1)
+MUX_CFG_24XX("F20_24XX_MMC_DAT0",      0x0f5,  0,      0,      0,      1)
+MUX_CFG_24XX("H14_24XX_MMC_DAT1",      0x0f6,  0,      0,      0,      1)
+MUX_CFG_24XX("E19_24XX_MMC_DAT2",      0x0f7,  0,      0,      0,      1)
+MUX_CFG_24XX("D19_24XX_MMC_DAT3",      0x0f8,  0,      0,      0,      1)
+MUX_CFG_24XX("F19_24XX_MMC_DAT_DIR0",  0x0f9,  0,      0,      0,      1)
+MUX_CFG_24XX("E20_24XX_MMC_DAT_DIR1",  0x0fa,  0,      0,      0,      1)
+MUX_CFG_24XX("F18_24XX_MMC_DAT_DIR2",  0x0fb,  0,      0,      0,      1)
+MUX_CFG_24XX("E18_24XX_MMC_DAT_DIR3",  0x0fc,  0,      0,      0,      1)
+MUX_CFG_24XX("G18_24XX_MMC_CMD_DIR",   0x0fd,  0,      0,      0,      1)
+MUX_CFG_24XX("H15_24XX_MMC_CLKI",      0x0fe,  0,      0,      0,      1)
+
 /* Keypad GPIO*/
 MUX_CFG_24XX("T19_24XX_KBR0",          0x106,  3,      1,      1,      1)
 MUX_CFG_24XX("R19_24XX_KBR1",          0x107,  3,      1,      1,      1)
index c2bf57ef68255309ab46096f6de08202af433a1b..90f530540c6529138c6a9e6a77d4ec21c7095d72 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "prcm-regs.h"
 
+extern void omap2_clk_prepare_for_reboot(void);
+
 u32 omap_prcm_get_reset_sources(void)
 {
        return RM_RSTST_WKUP & 0x7f;
@@ -28,12 +30,6 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources);
 /* Resets clock rates and reboots the system. Only called from system.h */
 void omap_prcm_arch_reset(char mode)
 {
-       u32 rate;
-       struct clk *vclk, *sclk;
-
-       vclk = clk_get(NULL, "virt_prcm_set");
-       sclk = clk_get(NULL, "sys_ck");
-       rate = clk_get_rate(sclk);
-       clk_set_rate(vclk, rate);       /* go to bypass for OMAP limitation */
+       omap2_clk_prepare_for_reboot();
        RM_RSTCTRL_WKUP |= 2;
 }
index cce26576999ea8333a89a132f622edbe01185928..337c01c4ac37194860c45f845a503686ecc0e6c4 100644 (file)
@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = {
 /*
  * USB Device Controller
  */
-static void corgi_udc_command(int cmd)
-{
-       switch(cmd)     {
-       case PXA2XX_UDC_CMD_CONNECT:
-               GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
-               break;
-       case PXA2XX_UDC_CMD_DISCONNECT:
-               GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
-               break;
-       }
-}
-
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
        /* no connect GPIO; corgi can't tell connection status */
-       .udc_command            = corgi_udc_command,
+       .gpio_pullup            = CORGI_GPIO_USB_PULLUP,
 };
 
 
@@ -350,7 +338,6 @@ static void __init corgi_init(void)
        corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
 
        pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
-       pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
        pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
 
        pxa_set_udc_info(&udc_info);
index bbd138be6a70779663bd4aa1798f629e4b81e007..df37594c30f83baef8a80d54b218ed56c83e4929 100644 (file)
@@ -2,6 +2,13 @@ if ARCH_S3C2410
 
 menu "S3C24XX Implementations"
 
+config MACH_AML_M5900
+       bool "AML M5900 Series"
+       select CPU_S3C2410
+       help
+          Say Y here if you are using the American Microsystems M5900 Series
+           <http://www.amltd.com>
+
 config MACH_ANUBIS
        bool "Simtec Electronics ANUBIS"
        select CPU_S3C2440
@@ -126,6 +133,12 @@ config MACH_NEXCODER_2440
        help
          Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
 
+config MACH_VSTMS
+       bool "VMSTMS"
+       select CPU_S3C2412
+       help
+         Say Y here if you are using an VSTMS board
+
 endmenu
 
 config S3C2410_CLOCK
@@ -133,10 +146,24 @@ config S3C2410_CLOCK
        help
          Clock code for the S3C2410, and similar processors
 
+config S3C2410_PM
+       bool
+       depends on CONFIG_PM
+       help
+         Power Management code common to S3C2410 and better
+
+config CPU_S3C2410_DMA
+       bool
+       depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+       default y if CPU_S3C2410 || CPU_S3C2442
+       help
+         DMA device selection for S3C2410 and compatible CPUs
+
 config CPU_S3C2410
        bool
        depends on ARCH_S3C2410
        select S3C2410_CLOCK
+       select S3C2410_PM
        help
          Support for S3C2410 and S3C2410A family from the S3C24XX line
          of Samsung Mobile CPUs.
@@ -149,6 +176,13 @@ config CPU_S3C2412_ONLY
                   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
        default y if CPU_S3C2412
 
+config S3C2412_PM
+       bool
+       default y if PM
+       depends on CPU_S3C2412
+       help
+         Internal config node to apply S3C2412 power management
+
 config CPU_S3C2412
        bool
        depends on ARCH_S3C2410
@@ -165,6 +199,7 @@ config CPU_S3C2440
        bool
        depends on ARCH_S3C2410
        select S3C2410_CLOCK
+       select S3C2410_PM
        select CPU_S3C244X
        help
          Support for S3C2440 Samsung Mobile CPU based systems.
@@ -173,6 +208,7 @@ config CPU_S3C2442
        bool
        depends on ARCH_S3C2420
        select S3C2410_CLOCK
+       select S3C2410_PM
        select CPU_S3C244X
        help
          Support for S3C2442 Samsung Mobile CPU based systems.
@@ -256,7 +292,7 @@ config S3C2410_PM_CHECK_CHUNKSIZE
 
 config PM_SIMTEC
        bool
-       depends on PM && (ARCH_BAST || MACH_VR1000)
+       depends on PM && (ARCH_BAST || MACH_VR1000 || MACH_AML_M5900)
        default y
 
 config S3C2410_LOWLEVEL_UART_PORT
index 0eadec916214ecde32fa0ed66532d4ee33732276..d66013365b6bc2e7fa9d2888272a5df8520cd17d 100644 (file)
@@ -9,6 +9,8 @@ obj-y                   := cpu.o irq.o time.o gpio.o clock.o devs.o
 obj-m                  :=
 obj-n                  :=
 obj-                   :=
+obj-dma-y              :=
+obj-dma-n              :=
 
 # DMA
 obj-$(CONFIG_S3C2410_DMA)      += dma.o
@@ -20,6 +22,10 @@ obj-$(CONFIG_CPU_S3C2400)    += s3c2400-gpio.o
 
 obj-$(CONFIG_CPU_S3C2410)      += s3c2410.o
 obj-$(CONFIG_CPU_S3C2410)      += s3c2410-gpio.o
+obj-$(CONFIG_CPU_S3C2410)      += s3c2410-irq.o
+
+obj-$(CONFIG_S3C2410_PM)       += s3c2410-pm.o s3c2410-sleep.o
+obj-$(CONFIG_CPU_S3C2410_DMA)  += s3c2410-dma.o
 
 # Power Management support
 
@@ -30,6 +36,9 @@ obj-$(CONFIG_PM_SIMTEC)               += pm-simtec.o
 obj-$(CONFIG_CPU_S3C2412)      += s3c2412.o
 obj-$(CONFIG_CPU_S3C2412)      += s3c2412-irq.o
 obj-$(CONFIG_CPU_S3C2412)      += s3c2412-clock.o
+obj-dma-$(CONFIG_CPU_S3C2412)  += s3c2412-dma.o
+
+obj-$(CONFIG_S3C2412_PM)       += s3c2412-pm.o
 
 #
 # S3C244X support
@@ -47,6 +56,7 @@ obj-$(CONFIG_CPU_S3C2440)     += s3c2440.o s3c2440-dsc.o
 obj-$(CONFIG_CPU_S3C2440)      += s3c2440-irq.o
 obj-$(CONFIG_CPU_S3C2440)      += s3c2440-clock.o
 obj-$(CONFIG_CPU_S3C2440)      += s3c2410-gpio.o
+obj-dma-$(CONFIG_CPU_S3C2440)  += s3c2440-dma.o
 
 # S3C2442 support
 
@@ -57,8 +67,13 @@ obj-$(CONFIG_CPU_S3C2442)    += s3c2442-clock.o
 
 obj-$(CONFIG_BAST_PC104_IRQ)   += bast-irq.o
 
+# merge in dma objects
+
+obj-y                          += $(obj-dma-y)
+
 # machine specific support
 
+obj-$(CONFIG_MACH_AML_M5900)   += mach-amlm5900.o
 obj-$(CONFIG_MACH_ANUBIS)      += mach-anubis.o
 obj-$(CONFIG_MACH_OSIRIS)      += mach-osiris.o
 obj-$(CONFIG_ARCH_BAST)                += mach-bast.o usb-simtec.o
@@ -71,5 +86,6 @@ obj-$(CONFIG_MACH_VR1000)     += mach-vr1000.o usb-simtec.o
 obj-$(CONFIG_MACH_RX3715)      += mach-rx3715.o
 obj-$(CONFIG_MACH_OTOM)                += mach-otom.o
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+obj-$(CONFIG_MACH_VSTMS)       += mach-vstms.o
 
 obj-$(CONFIG_MACH_SMDK)                += common-smdk.o
\ No newline at end of file
index def4441d24420e260278672a6fac06160ec46c53..440e9aa0211abafad0585c93cc26e86463d72210 100644 (file)
  * 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
- *
- * Modifications:
- *     08-Jan-2003 BJD  Moved from central IRQ code
- *     21-Aug-2005 BJD  Fixed missing code and compile errors
 */
 
 
index 1c3c6adae6c4c11b69339eebc46650c58f57ccce..9d4899eddf1f26ccccc8906504c25578c11a4378 100644 (file)
@@ -124,6 +124,15 @@ static struct cpu_table cpu_ids[] __initdata = {
                .init           = s3c2412_init,
                .name           = name_s3c2412,
        },
+       {                       /* a newer version of the s3c2412 */
+               .idcode         = 0x32412003,
+               .idmask         = 0xffffffff,
+               .map_io         = s3c2412_map_io,
+               .init_clocks    = s3c2412_init_clocks,
+               .init_uarts     = s3c2412_init_uarts,
+               .init           = s3c2412_init,
+               .name           = name_s3c2412,
+       },
        {
                .idcode         = 0x0,   /* S3C2400 doesn't have an idcode */
                .idmask         = 0xffffffff,
index 726e2eaf8797c58cd4c6016c34f2ba84d316256e..14fb0bade7165c68057eeb1cda6b03a353d2a176 100644 (file)
@@ -8,11 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *      18-Aug-2004 BJD  Created initial version
- *     27-Aug-2004 BJD  Added timers 0 through 3
- *     10-Feb-2005 BJD  Added camera from guillaume.gourat@nexvision.tv
 */
 #include <linux/platform_device.h>
 
index cc92a7b2db889e7cbc5ec151e61a888718325046..d264bbbd8bef893fa660255fafbb88876f290b52 100644 (file)
@@ -1,35 +1,16 @@
-/* linux/arch/arm/mach-bast/dma.c
+/* linux/arch/arm/mach-s3c2410/dma.c
  *
- * (c) 2003-2005 Simtec Electronics
+ * (c) 2003-2005,2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
  * S3C2410 DMA core
  *
- * http://www.simtec.co.uk/products/EB2410ITX/
+ * http://armlinux.simtec.co.uk/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  27-Feb-2005 BJD  Added kmem cache for dma descriptors
- *  18-Nov-2004 BJD  Removed error for loading onto stopped channel
- *  10-Nov-2004 BJD  Ensure all external symbols exported for modules
- *  10-Nov-2004 BJD  Use sys_device and sysdev_class for power management
- *  08-Aug-2004 BJD  Apply rmk's suggestions
- *  21-Jul-2004 BJD  Ported to linux 2.6
- *  12-Jul-2004 BJD  Finished re-write and change of API
- *  06-Jul-2004 BJD  Rewrote dma code to try and cope with various problems
- *  23-May-2003 BJD  Created file
- *  19-Aug-2003 BJD  Cleanup, header fix, added URL
- *
- * This file is based on the Sangwook Lee/Samsung patches, re-written due
- * to various ommisions from the code (such as flexible dma configuration)
- * for use with the BAST system board.
- *
- * The re-write is pretty much complete, and should be good enough for any
- * possible DMA function
- */
+*/
 
 
 #ifdef CONFIG_S3C2410_DMA_DEBUG
 #include <asm/mach/dma.h>
 #include <asm/arch/map.h>
 
+#include "dma.h"
+
 /* io map for dma */
 static void __iomem *dma_base;
 static kmem_cache_t *dma_kmem;
 
+struct s3c24xx_dma_selection dma_sel;
+
 /* dma channel state information */
 struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
 
@@ -79,7 +64,6 @@ dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
        pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
        writel(val, dma_regaddr(chan, reg));
 }
-
 #endif
 
 #define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
@@ -151,12 +135,20 @@ dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
 #define dbg_showchan(chan) do { } while(0)
 #endif /* CONFIG_S3C2410_DMA_DEBUG */
 
-#define check_channel(chan) \
-  do { if ((chan) >= S3C2410_DMA_CHANNELS) { \
-    printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
-    return -EINVAL; \
-  } } while(0)
+static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
 
+/* lookup_dma_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
+{
+       if (channel & DMACH_LOW_LEVEL)
+               return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+       else
+               return dma_chan_map[channel];
+}
 
 /* s3c2410_dma_stats_timeout
  *
@@ -321,8 +313,10 @@ static inline void
 s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
                     enum s3c2410_dma_buffresult result)
 {
+#if 0
        pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
                 chan->callback_fn, buf, buf->id, buf->size, result);
+#endif
 
        if (chan->callback_fn != NULL) {
                (chan->callback_fn)(chan, buf->id, buf->size, result);
@@ -439,7 +433,6 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
        return 0;
 }
 
-
 /* s3c2410_dma_enqueue
  *
  * queue an given buffer for dma transfer.
@@ -460,11 +453,12 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
 int s3c2410_dma_enqueue(unsigned int channel, void *id,
                        dma_addr_t data, int size)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
        struct s3c2410_dma_buf *buf;
        unsigned long flags;
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        pr_debug("%s: id=%p, data=%08x, size=%d\n",
                 __FUNCTION__, id, (unsigned int)data, size);
@@ -562,8 +556,10 @@ s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
 static inline void
 s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
 {
+#if 0
        pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
                 chan->number, chan->load_state);
+#endif
 
        switch (chan->load_state) {
        case S3C2410_DMALOAD_NONE:
@@ -718,7 +714,8 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
                if (chan->load_state == S3C2410_DMALOAD_NONE) {
                        pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
                                 chan->number, jiffies);
-                       s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+                       s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+                                        S3C2410_DMAOP_STOP);
                }
        }
 
@@ -726,37 +723,34 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
+
 /* s3c2410_request_dma
  *
  * get control of an dma channel
 */
 
-int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client,
+int s3c2410_dma_request(unsigned int channel,
+                       struct s3c2410_dma_client *client,
                        void *dev)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan;
        unsigned long flags;
        int err;
 
        pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
                 channel, client->name, dev);
 
-       check_channel(channel);
-
        local_irq_save(flags);
 
-       dbg_showchan(chan);
-
-       if (chan->in_use) {
-               if (client != chan->client) {
-                       printk(KERN_ERR "dma%d: already in use\n", channel);
-                       local_irq_restore(flags);
-                       return -EBUSY;
-               } else {
-                       printk(KERN_ERR "dma%d: client already has channel\n", channel);
-               }
+       chan = s3c2410_dma_map_channel(channel);
+       if (chan == NULL) {
+               local_irq_restore(flags);
+               return -EBUSY;
        }
 
+       dbg_showchan(chan);
+
        chan->client = client;
        chan->in_use = 1;
 
@@ -809,14 +803,14 @@ EXPORT_SYMBOL(s3c2410_dma_request);
 
 int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
        unsigned long flags;
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        local_irq_save(flags);
 
-
        if (chan->client != client) {
                printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
                       channel, chan->client, client);
@@ -837,8 +831,12 @@ int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
 
        if (chan->irq_claimed)
                free_irq(chan->irq, (void *)chan);
+
        chan->irq_claimed = 0;
 
+       if (!(channel & DMACH_LOW_LEVEL))
+               dma_chan_map[channel] = NULL;
+
        local_irq_restore(flags);
 
        return 0;
@@ -848,8 +846,8 @@ EXPORT_SYMBOL(s3c2410_dma_free);
 
 static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
 {
-       unsigned long tmp;
        unsigned long flags;
+       unsigned long tmp;
 
        pr_debug("%s:\n", __FUNCTION__);
 
@@ -997,9 +995,10 @@ s3c2410_dma_started(struct s3c2410_dma_chan *chan)
 int
 s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        switch (op) {
        case S3C2410_DMAOP_START:
@@ -1046,12 +1045,19 @@ int s3c2410_dma_config(dmach_t channel,
                       int xferunit,
                       int dcon)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
        pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
                 __FUNCTION__, channel, xferunit, dcon);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
+
+       printk("Initial dcon is %08x\n", dcon);
+
+       dcon |= chan->dcon & dma_sel.dcon_mask;
+
+       printk("New dcon is %08x\n", dcon);
 
        switch (xferunit) {
        case 1:
@@ -1086,9 +1092,10 @@ EXPORT_SYMBOL(s3c2410_dma_config);
 
 int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
 
@@ -1106,9 +1113,10 @@ EXPORT_SYMBOL(s3c2410_dma_setflags);
 
 int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
 
@@ -1121,9 +1129,10 @@ EXPORT_SYMBOL(s3c2410_dma_set_opfn);
 
 int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
 
@@ -1153,9 +1162,10 @@ int s3c2410_dma_devconfig(int channel,
                          int hwcfg,
                          unsigned long devaddr)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
                 __FUNCTION__, (int)source, hwcfg, devaddr);
@@ -1200,9 +1210,10 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig);
 
 int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
 {
-       struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+       struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
-       check_channel(channel);
+       if (chan == NULL)
+               return -EINVAL;
 
        if (src != NULL)
                *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
@@ -1252,7 +1263,7 @@ static int s3c2410_dma_resume(struct sys_device *dev)
 #define s3c2410_dma_resume  NULL
 #endif /* CONFIG_PM */
 
-static struct sysdev_class dma_sysclass = {
+struct sysdev_class dma_sysclass = {
        set_kset_name("s3c24xx-dma"),
        .suspend        = s3c2410_dma_suspend,
        .resume         = s3c2410_dma_resume,
@@ -1265,7 +1276,6 @@ static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
        memset(p, 0, sizeof(struct s3c2410_dma_buf));
 }
 
-
 /* initialisation code */
 
 static int __init s3c2410_init_dma(void)
@@ -1274,7 +1284,7 @@ static int __init s3c2410_init_dma(void)
        int channel;
        int ret;
 
-       printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
+       printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
 
        dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
        if (dma_base == NULL) {
@@ -1282,6 +1292,8 @@ static int __init s3c2410_init_dma(void)
                return -ENOMEM;
        }
 
+       printk("Registering sysclass\n");
+
        ret = sysdev_class_register(&dma_sysclass);
        if (ret != 0) {
                printk(KERN_ERR "dma sysclass registration failed\n");
@@ -1335,4 +1347,95 @@ static int __init s3c2410_init_dma(void)
        return ret;
 }
 
-__initcall(s3c2410_init_dma);
+core_initcall(s3c2410_init_dma);
+
+static inline int is_channel_valid(unsigned int channel)
+{
+       return (channel & DMA_CH_VALID);
+}
+
+/* s3c2410_dma_map_channel()
+ *
+ * turn the virtual channel number into a real, and un-used hardware
+ * channel.
+ *
+ * currently this code uses first-free channel from the specified harware
+ * map, not taking into account anything that the board setup code may
+ * have to say about the likely peripheral set to be in use.
+*/
+
+struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+{
+       struct s3c24xx_dma_map *ch_map;
+       struct s3c2410_dma_chan *dmach;
+       int ch;
+
+       if (dma_sel.map == NULL || channel > dma_sel.map_size)
+               return NULL;
+
+       ch_map = dma_sel.map + channel;
+
+       for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
+               if (!is_channel_valid(ch_map->channels[ch]))
+                       continue;
+
+               if (s3c2410_chans[ch].in_use == 0) {
+                       printk("mapped channel %d to %d\n", channel, ch);
+                       break;
+               }
+       }
+
+       if (ch >= S3C2410_DMA_CHANNELS)
+               return NULL;
+
+       /* update our channel mapping */
+
+       dmach = &s3c2410_chans[ch];
+       dma_chan_map[channel] = dmach;
+
+       /* select the channel */
+
+       (dma_sel.select)(dmach, ch_map);
+
+       return dmach;
+}
+
+static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
+{
+       /* show the channel configuration */
+
+       printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
+              (is_channel_valid(map->channels[0]) ? '0' : '-'),
+              (is_channel_valid(map->channels[1]) ? '1' : '-'),
+              (is_channel_valid(map->channels[2]) ? '2' : '-'),
+              (is_channel_valid(map->channels[3]) ? '3' : '-'));
+}
+
+static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
+{
+       if (1)
+               s3c24xx_dma_show_ch(map, ch);
+
+       return 0;
+}
+
+int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
+{
+       struct s3c24xx_dma_map *nmap;
+       size_t map_sz = sizeof(*nmap) * sel->map_size;
+       int ptr;
+
+       nmap = kmalloc(map_sz, GFP_KERNEL);
+       if (nmap == NULL)
+               return -ENOMEM;
+
+       memcpy(nmap, sel->map, map_sz);
+       memcpy(&dma_sel, sel, sizeof(*sel));
+
+       dma_sel.map = nmap;
+
+       for (ptr = 0; ptr < sel->map_size; ptr++)
+               s3c24xx_dma_check_entry(nmap+ptr, ptr);
+
+       return 0;
+}
diff --git a/arch/arm/mach-s3c2410/dma.h b/arch/arm/mach-s3c2410/dma.h
new file mode 100644 (file)
index 0000000..0ebfe0a
--- /dev/null
@@ -0,0 +1,45 @@
+/* arch/arm/mach-s3c2410/dma.h
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * 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.
+*/
+
+extern struct sysdev_class dma_sysclass;
+extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+#define DMA_CH_VALID           (1<<31)
+
+struct s3c24xx_dma_addr {
+       unsigned long           from;
+       unsigned long           to;
+};
+
+/* struct s3c24xx_dma_map
+ *
+ * this holds the mapping information for the channel selected
+ * to be connected to the specified device
+*/
+
+struct s3c24xx_dma_map {
+       const char              *name;
+       struct s3c24xx_dma_addr  hw_addr;
+
+       unsigned long            channels[S3C2410_DMA_CHANNELS];
+};
+
+struct s3c24xx_dma_selection {
+       struct s3c24xx_dma_map  *map;
+       unsigned long            map_size;
+       unsigned long            dcon_mask;
+
+       void    (*select)(struct s3c2410_dma_chan *chan,
+                         struct s3c24xx_dma_map *map);
+};
+
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
index cd39e86845848ec6a515383fef3c6d4bda3ac114..db6393c9986091328cd1f31b00beeb1219d42315 100644 (file)
  * 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
- *
- * Changelog
- *     13-Sep-2004  BJD  Implemented change of MISCCR
- *     14-Sep-2004  BJD  Added getpin call
- *     14-Sep-2004  BJD  Fixed bug in setpin() call
- *     30-Sep-2004  BJD  Fixed cfgpin() mask bug
- *     01-Oct-2004  BJD  Added getcfg() to get pin configuration
- *     01-Oct-2004  BJD  Fixed mask bug in pullup() call
- *     01-Oct-2004  BJD  Added getirq() to turn pin into irqno
- *     04-Oct-2004  BJD  Added irq filter controls for GPIO
- *     05-Nov-2004  BJD  EXPORT_SYMBOL() added for all code
- *     13-Mar-2005  BJD  Updates for __iomem
- *     26-Oct-2005  BJD  Added generic configuration types
- *     15-Jan-2006  LCVR Added support for the S3C2400
- */
+*/
 
 
 #include <linux/kernel.h>
index cd6139b359996ed3dd37528201023b7ed65a3157..3e9f3462c61b13f012eb5479228196e1f7405ad3 100644 (file)
@@ -181,17 +181,19 @@ s3c_irq_unmask(unsigned int irqno)
 }
 
 struct irqchip s3c_irq_level_chip = {
-       .ack       = s3c_irq_maskack,
-       .mask      = s3c_irq_mask,
-       .unmask    = s3c_irq_unmask,
-       .set_wake          = s3c_irq_wake
+       .name           = "s3c-level",
+       .ack            = s3c_irq_maskack,
+       .mask           = s3c_irq_mask,
+       .unmask         = s3c_irq_unmask,
+       .set_wake       = s3c_irq_wake
 };
 
 static struct irqchip s3c_irq_chip = {
-       .ack       = s3c_irq_ack,
-       .mask      = s3c_irq_mask,
-       .unmask    = s3c_irq_unmask,
-       .set_wake  = s3c_irq_wake
+       .name           = "s3c",
+       .ack            = s3c_irq_ack,
+       .mask           = s3c_irq_mask,
+       .unmask         = s3c_irq_unmask,
+       .set_wake       = s3c_irq_wake
 };
 
 static void
@@ -343,19 +345,21 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
 }
 
 static struct irqchip s3c_irqext_chip = {
-       .mask       = s3c_irqext_mask,
-       .unmask     = s3c_irqext_unmask,
-       .ack        = s3c_irqext_ack,
-       .set_type    = s3c_irqext_type,
-       .set_wake    = s3c_irqext_wake
+       .name           = "s3c-ext",
+       .mask           = s3c_irqext_mask,
+       .unmask         = s3c_irqext_unmask,
+       .ack            = s3c_irqext_ack,
+       .set_type       = s3c_irqext_type,
+       .set_wake       = s3c_irqext_wake
 };
 
 static struct irqchip s3c_irq_eint0t4 = {
-       .ack       = s3c_irq_ack,
-       .mask      = s3c_irq_mask,
-       .unmask    = s3c_irq_unmask,
-       .set_wake  = s3c_irq_wake,
-       .set_type  = s3c_irqext_type,
+       .name           = "s3c-ext0",
+       .ack            = s3c_irq_ack,
+       .mask           = s3c_irq_mask,
+       .unmask         = s3c_irq_unmask,
+       .set_wake       = s3c_irq_wake,
+       .set_type       = s3c_irqext_type,
 };
 
 /* mask values for the parent registers for each of the interrupt types */
@@ -387,9 +391,10 @@ s3c_irq_uart0_ack(unsigned int irqno)
 }
 
 static struct irqchip s3c_irq_uart0 = {
-       .mask       = s3c_irq_uart0_mask,
-       .unmask     = s3c_irq_uart0_unmask,
-       .ack        = s3c_irq_uart0_ack,
+       .name           = "s3c-uart0",
+       .mask           = s3c_irq_uart0_mask,
+       .unmask         = s3c_irq_uart0_unmask,
+       .ack            = s3c_irq_uart0_ack,
 };
 
 /* UART1 */
@@ -413,9 +418,10 @@ s3c_irq_uart1_ack(unsigned int irqno)
 }
 
 static struct irqchip s3c_irq_uart1 = {
-       .mask       = s3c_irq_uart1_mask,
-       .unmask     = s3c_irq_uart1_unmask,
-       .ack        = s3c_irq_uart1_ack,
+       .name           = "s3c-uart1",
+       .mask           = s3c_irq_uart1_mask,
+       .unmask         = s3c_irq_uart1_unmask,
+       .ack            = s3c_irq_uart1_ack,
 };
 
 /* UART2 */
@@ -439,9 +445,10 @@ s3c_irq_uart2_ack(unsigned int irqno)
 }
 
 static struct irqchip s3c_irq_uart2 = {
-       .mask       = s3c_irq_uart2_mask,
-       .unmask     = s3c_irq_uart2_unmask,
-       .ack        = s3c_irq_uart2_ack,
+       .name           = "s3c-uart2",
+       .mask           = s3c_irq_uart2_mask,
+       .unmask         = s3c_irq_uart2_unmask,
+       .ack            = s3c_irq_uart2_ack,
 };
 
 /* ADC and Touchscreen */
@@ -465,9 +472,10 @@ s3c_irq_adc_ack(unsigned int irqno)
 }
 
 static struct irqchip s3c_irq_adc = {
-       .mask       = s3c_irq_adc_mask,
-       .unmask     = s3c_irq_adc_unmask,
-       .ack        = s3c_irq_adc_ack,
+       .name           = "s3c-adc",
+       .mask           = s3c_irq_adc_mask,
+       .unmask         = s3c_irq_adc_unmask,
+       .ack            = s3c_irq_adc_ack,
 };
 
 /* irq demux for adc */
@@ -569,23 +577,104 @@ s3c_irq_demux_uart2(unsigned int irq,
 }
 
 static void
-s3c_irq_demux_extint(unsigned int irq,
-                    struct irqdesc *desc,
-                    struct pt_regs *regs)
+s3c_irq_demux_extint8(unsigned int irq,
+                     struct irqdesc *desc,
+                     struct pt_regs *regs)
 {
        unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
        unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
 
        eintpnd &= ~eintmsk;
+       eintpnd &= ~0xff;       /* ignore lower irqs */
 
-       if (eintpnd) {
-               irq = fls(eintpnd);
-               irq += (IRQ_EINT4 - (4 + 1));
+       /* we may as well handle all the pending IRQs here */
 
+       while (eintpnd) {
+               irq = __ffs(eintpnd);
+               eintpnd &= ~(1<<irq);
+
+               irq += (IRQ_EINT4 - 4);
                desc_handle_irq(irq, irq_desc + irq, regs);
        }
+
+}
+
+static void
+s3c_irq_demux_extint4t7(unsigned int irq,
+                       struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+       unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+       eintpnd &= ~eintmsk;
+       eintpnd &= 0xff;        /* only lower irqs */
+
+       /* we may as well handle all the pending IRQs here */
+
+       while (eintpnd) {
+               irq = __ffs(eintpnd);
+               eintpnd &= ~(1<<irq);
+
+               irq += (IRQ_EINT4 - 4);
+
+               desc_handle_irq(irq, irq_desc + irq, regs);
+       }
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+       SAVE_ITEM(S3C2410_INTMSK),
+       SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+               save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+               save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+       s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+       save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+       return 0;
 }
 
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+               __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+       for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+               __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+       s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+       __raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+       return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
 /* s3c24xx_init_irq
  *
  * Initialise S3C2410 IRQ system
@@ -674,8 +763,8 @@ void __init s3c24xx_init_irq(void)
 
        /* setup the cascade irq handlers */
 
-       set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
-       set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
+       set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+       set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
 
        set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
        set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
new file mode 100644 (file)
index 0000000..ba5109a
--- /dev/null
@@ -0,0 +1,266 @@
+/***********************************************************************
+ *
+ * linux/arch/arm/mach-s3c2410/mach-amlm5900.c
+ *
+ * Copyright (c) 2006 American Microsystems Limited
+ *     David Anders <danders@amltd.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
+ *
+ * @History:
+ * derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ ***********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/arch/fb.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "devs.h"
+#include "cpu.h"
+
+#ifdef CONFIG_MTD_PARTITIONS
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/physmap.h>
+
+static struct resource amlm5900_nor_resource = {
+               .start = 0x00000000,
+               .end   = 0x01000000 - 1,
+               .flags = IORESOURCE_MEM,
+};
+
+
+
+static struct mtd_partition amlm5900_mtd_partitions[] = {
+       {
+               .name           = "System",
+               .size           = 0x240000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "Kernel",
+               .size           = 0x100000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "Ramdisk",
+               .size           = 0x300000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "JFFS2",
+               .size           = 0x9A0000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "Settings",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+
+static struct physmap_flash_data amlm5900_flash_data = {
+       .width          = 2,
+       .parts          = amlm5900_mtd_partitions,
+       .nr_parts       = ARRAY_SIZE(amlm5900_mtd_partitions),
+};
+
+static struct platform_device amlm5900_device_nor = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev = {
+                       .platform_data = &amlm5900_flash_data,
+               },
+       .num_resources  = 1,
+       .resource       = &amlm5900_nor_resource,
+};
+#endif
+
+static struct map_desc amlm5900_iodesc[] __initdata = {
+       {
+               .virtual        = (u32)S3C24XX_VA_SPI,
+               .pfn            = __phys_to_pfn(S3C2410_PA_SPI),
+               .length         = SZ_1M,
+               .type           = MT_DEVICE
+       }
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg amlm5900_uartcfgs[] = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       },
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = UCON,
+               .ulcon       = ULCON,
+               .ufcon       = UFCON,
+       }
+};
+
+
+static struct platform_device *amlm5900_devices[] __initdata = {
+#ifdef CONFIG_FB_S3C2410
+       &s3c_device_lcd,
+#endif
+       &s3c_device_adc,
+       &s3c_device_wdt,
+       &s3c_device_i2c,
+       &s3c_device_usb,
+       &s3c_device_rtc,
+       &s3c_device_usbgadget,
+        &s3c_device_sdi,
+#ifdef CONFIG_MTD_PARTITIONS
+       &amlm5900_device_nor,
+#endif
+};
+
+static struct s3c24xx_board amlm5900_board __initdata = {
+       .devices       = amlm5900_devices,
+       .devices_count = ARRAY_SIZE(amlm5900_devices)
+};
+
+void __init amlm5900_map_io(void)
+{
+       s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
+       s3c24xx_init_clocks(0);
+       s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
+       s3c24xx_set_board(&amlm5900_board);
+}
+
+#ifdef CONFIG_FB_S3C2410
+static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = {
+       .width          = 160,
+       .height         = 160,
+
+/* commented out until stn patch is submitted
+*      .type           = S3C2410_LCDCON1_STN4,
+*/
+       .gpccon =       0xaaaaaaaa,
+       .gpccon_mask =  0xffffffff,
+       .gpcup =        0x0000ffff,
+       .gpcup_mask =   0xffffffff,
+
+       .gpdcon =       0xaaaaaaaa,
+       .gpdcon_mask =  0xffffffff,
+       .gpdup =        0x0000ffff,
+       .gpdup_mask =   0xffffffff,
+
+       .xres           = {
+               .min            = 160,
+               .max            = 160,
+               .defval         = 160,
+       },
+
+       .yres           = {
+               .min            = 160,
+               .max            = 160,
+               .defval         = 160,
+       },
+
+       .bpp            = {
+               .min            = 4,
+               .max            = 4,
+               .defval         = 4,
+       },
+
+       .regs           = {
+               .lcdcon1        = 0x00008225,
+               .lcdcon2        = 0x0027c000,
+               .lcdcon3        = 0x00182708,
+               .lcdcon4        = 0x00000002,
+               .lcdcon5        = 0x00000001,
+       }
+};
+#endif
+
+static irqreturn_t
+amlm5900_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+       return IRQ_HANDLED;
+}
+
+static void amlm5900_init_pm(void)
+{
+       int ret = 0;
+
+       ret = request_irq(IRQ_EINT9, &amlm5900_wake_interrupt,
+                               IRQF_TRIGGER_RISING | IRQF_SHARED,
+                               "amlm5900_wakeup", &amlm5900_wake_interrupt);
+       if (ret != 0) {
+               printk(KERN_ERR "AML-M5900: no wakeup irq, %d?\n", ret);
+       } else {
+               enable_irq_wake(IRQ_EINT9);
+               /* configure the suspend/resume status pin */
+               s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP);
+               s3c2410_gpio_pullup(S3C2410_GPF2, 0);
+       }
+}
+static void __init amlm5900_init(void)
+{
+       amlm5900_init_pm();
+#ifdef CONFIG_FB_S3C2410
+       s3c24xx_fb_set_platdata(&amlm5900_lcd_info);
+#endif
+}
+
+MACHINE_START(AML_M5900, "AML_M5900")
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+       .map_io         = amlm5900_map_io,
+       .init_irq       = s3c24xx_init_irq,
+       .init_machine   = amlm5900_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
index 60641d452db33275c57d4b33adcc1caebf23cad3..e94cdcd965916437970151942ef26c31af8f1c6d 100644 (file)
@@ -4,15 +4,9 @@
  *     http://armlinux.simtec.co.uk/
  *     Ben Dooks <ben@simtec.co.uk>
  *
- *
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     02-May-2005 BJD  Copied from mach-bast.c
- *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
index d661c6b7ff5650811efa40a3afc66868aaa7ac21..e2205ff1b0ee97b76d9038815e6b864e77b3d93b 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *     01-Nov-2004 BJD   Initial version
- *     12-Nov-2004 BJD   Updated for release
- *     04-Jan-2005 BJD   Fixes for pre-release
- *     22-Feb-2005 BJD   Updated for 2.6.11-rc5 relesa
- *     10-Mar-2005 LCVR  Replaced S3C2410_VA by S3C24XX_VA
- *     14-Mar-2005 BJD   void __iomem fixes
- *     20-Sep-2005 BJD   Added static to non-exported items
- *     26-Oct-2005 BJD   Added framebuffer data
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2410/mach-vstms.c
new file mode 100644 (file)
index 0000000..ea554e7
--- /dev/null
@@ -0,0 +1,168 @@
+/* linux/arch/arm/mach-s3c2410/mach-vstms.c
+ *
+ * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Derived from mach-smdk2413.c - (C) 2006 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/arch/nand.h>
+
+#include "s3c2410.h"
+#include "s3c2412.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+
+static struct map_desc vstms_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg vstms_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       }
+};
+
+static struct mtd_partition vstms_nand_part[] = {
+       [0] = {
+               .name   = "Boot Agent",
+               .size   = 0x7C000,
+               .offset = 0,
+       },
+       [1] = {
+               .name   = "UBoot Config",
+               .offset = 0x7C000,
+               .size   = 0x4000,
+       },
+       [2] = {
+               .name   = "Kernel",
+               .offset = 0x80000,
+               .size   = 0x200000,
+       },
+       [3] = {
+               .name   = "RFS",
+               .offset = 0x280000,
+               .size   = 0x3d80000,
+       },
+};
+
+static struct s3c2410_nand_set vstms_nand_sets[] = {
+       [0] = {
+               .name           = "NAND",
+               .nr_chips       = 1,
+               .nr_partitions  = ARRAY_SIZE(vstms_nand_part),
+               .partitions     = vstms_nand_part,
+       },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand vstms_nand_info = {
+       .tacls          = 20,
+       .twrph0         = 60,
+       .twrph1         = 20,
+       .nr_sets        = ARRAY_SIZE(vstms_nand_sets),
+       .sets           = vstms_nand_sets,
+};
+
+static struct platform_device *vstms_devices[] __initdata = {
+       &s3c_device_usb,
+       &s3c_device_wdt,
+       &s3c_device_i2c,
+       &s3c_device_iis,
+       &s3c_device_rtc,
+       &s3c_device_nand,
+};
+
+static struct s3c24xx_board vstms_board __initdata = {
+       .devices       = vstms_devices,
+       .devices_count = ARRAY_SIZE(vstms_devices)
+};
+
+static void __init vstms_fixup(struct machine_desc *desc,
+                                 struct tag *tags, char **cmdline,
+                                 struct meminfo *mi)
+{
+       if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+               mi->nr_banks=1;
+               mi->bank[0].start = 0x30000000;
+               mi->bank[0].size = SZ_64M;
+               mi->bank[0].node = 0;
+       }
+}
+
+static void __init vstms_map_io(void)
+{
+       s3c_device_nand.dev.platform_data = &vstms_nand_info;
+
+       s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
+       s3c24xx_set_board(&vstms_board);
+}
+
+MACHINE_START(VSTMS, "VSTMS")
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+
+       .fixup          = vstms_fixup,
+       .init_irq       = s3c24xx_init_irq,
+       .map_io         = vstms_map_io,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
index 7b244566a436891d6f2b9f32cf848f1f222a0627..42cd05e298f8dc5765e495712558f271ef4aa91d 100644 (file)
@@ -49,7 +49,8 @@ static __init int pm_simtec_init(void)
        /* check which machine we are running on */
 
        if (!machine_is_bast() && !machine_is_vr1000() &&
-           !machine_is_anubis() && !machine_is_osiris())
+           !machine_is_anubis() && !machine_is_osiris() &&
+           !machine_is_aml_m5900())
                return 0;
 
        printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
index a589fe76d9158d1eedac0ff04ae657ed38f22e53..b49a0b3b72b319562dcaf4763627ee52c85ad6de 100644 (file)
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/pm.c
  *
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004,2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 Power Manager (Suspend-To-RAM) support
+ * S3C24XX Power Manager (Suspend-To-RAM) support
  *
  * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
  *
@@ -24,9 +24,6 @@
  * Parts based on arch/arm/mach-pxa/pm.c
  *
  * Thanks to Dimitry Andric for debugging
- *
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA_UART to S3C24XX_VA_UART
 */
 
 #include <linux/init.h>
@@ -38,6 +35,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 
+#include <asm/cacheflush.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 
 
 unsigned long s3c_pm_flags;
 
-/* cache functions from arch/arm/mm/proc-arm920.S */
-
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-extern void arm920_flush_kern_cache_all(void);
-#else
-static void arm920_flush_kern_cache_all(void) { }
-#endif
-
 #define PFX "s3c24xx-pm: "
 
 static struct sleep_save core_save[] = {
@@ -92,19 +82,6 @@ static struct sleep_save core_save[] = {
        SAVE_ITEM(S3C2410_REFRESH),
 };
 
-/* this lot should be really saved by the IRQ code */
-static struct sleep_save irq_save[] = {
-       SAVE_ITEM(S3C2410_EXTINT0),
-       SAVE_ITEM(S3C2410_EXTINT1),
-       SAVE_ITEM(S3C2410_EXTINT2),
-       SAVE_ITEM(S3C2410_EINFLT0),
-       SAVE_ITEM(S3C2410_EINFLT1),
-       SAVE_ITEM(S3C2410_EINFLT2),
-       SAVE_ITEM(S3C2410_EINFLT3),
-       SAVE_ITEM(S3C2410_EINTMASK),
-       SAVE_ITEM(S3C2410_INTMSK)
-};
-
 static struct sleep_save gpio_save[] = {
        SAVE_ITEM(S3C2410_GPACON),
        SAVE_ITEM(S3C2410_GPADAT),
@@ -165,7 +142,7 @@ static struct sleep_save uart_save[] = {
 
 extern void printascii(const char *);
 
-static void pm_dbg(const char *fmt, ...)
+void pm_dbg(const char *fmt, ...)
 {
        va_list va;
        char buff[256];
@@ -509,6 +486,9 @@ static void s3c2410_pm_configure_extint(void)
        }
 }
 
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
 #define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
 
 /* s3c2410_pm_enter
@@ -519,7 +499,6 @@ static void s3c2410_pm_configure_extint(void)
 static int s3c2410_pm_enter(suspend_state_t state)
 {
        unsigned long regs_save[16];
-       unsigned long tmp;
 
        /* ensure the debug is initialised (if enabled) */
 
@@ -527,6 +506,11 @@ static int s3c2410_pm_enter(suspend_state_t state)
 
        DBG("s3c2410_pm_enter(%d)\n", state);
 
+       if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+               printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
+               return -EINVAL;
+       }
+
        if (state != PM_SUSPEND_MEM) {
                printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
                return -EINVAL;
@@ -554,17 +538,9 @@ static int s3c2410_pm_enter(suspend_state_t state)
 
        DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
 
-       /* ensure at least GESTATUS3 has the resume address */
-
-       __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
-
-       DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
-       DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
-
        /* save all necessary core registers not covered by the drivers */
 
        s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
-       s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
        s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
        s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
 
@@ -581,10 +557,16 @@ static int s3c2410_pm_enter(suspend_state_t state)
        /* ack any outstanding external interrupts before we go to sleep */
 
        __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+       __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+       __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+       /* call cpu specific preperation */
+
+       pm_cpu_prep();
 
        /* flush cache back to ram */
 
-       arm920_flush_kern_cache_all();
+       flush_cache_all();
 
        s3c2410_pm_check_store();
 
@@ -592,23 +574,23 @@ static int s3c2410_pm_enter(suspend_state_t state)
 
        __raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
 
-       s3c2410_cpu_suspend(regs_save);
+       /* s3c2410_cpu_save will also act as our return point from when
+        * we resume as it saves its own register state, so use the return
+        * code to differentiate return from save and return from sleep */
+
+       if (s3c2410_cpu_save(regs_save) == 0) {
+               flush_cache_all();
+               pm_cpu_sleep();
+       }
 
        /* restore the cpu state */
 
        cpu_init();
 
-       /* unset the return-from-sleep flag, to ensure reset */
-
-       tmp = __raw_readl(S3C2410_GSTATUS2);
-       tmp &= S3C2410_GSTATUS2_OFFRESET;
-       __raw_writel(tmp, S3C2410_GSTATUS2);
-
        /* restore the system state */
 
        s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
        s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
-       s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
        s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
 
        s3c2410_pm_debug_init();
index 7a5e714c73866ca46daa6676cefa85c1cf5f2c85..ffe197a119fb096b2e3c1d9c6788094946011fcc 100644 (file)
@@ -34,13 +34,19 @@ extern unsigned long s3c_irqwake_eintmask;
 extern unsigned long s3c_irqwake_intallow;
 extern unsigned long s3c_irqwake_eintallow;
 
+/* per-cpu sleep functions */
+
+extern void (*pm_cpu_prep)(void);
+extern void (*pm_cpu_sleep)(void);
+
 /* Flags for PM Control */
 
 extern unsigned long s3c_pm_flags;
 
 /* from sleep.S */
 
-extern void s3c2410_cpu_suspend(unsigned long *saveblk);
+extern int  s3c2410_cpu_save(unsigned long *saveblk);
+extern void s3c2410_cpu_suspend(void);
 extern void s3c2410_cpu_resume(void);
 
 extern unsigned long s3c2410_sleep_save_phys;
@@ -57,3 +63,11 @@ struct sleep_save {
 
 extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
 extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
+
+#ifdef CONFIG_PM
+extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s3c24xx_irq_resume(struct sys_device *dev);
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
new file mode 100644 (file)
index 0000000..51e5098
--- /dev/null
@@ -0,0 +1,158 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
+ *
+ * (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include "dma.h"
+
+#include "cpu.h"
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
+       [DMACH_XD0] = {
+               .name           = "xdreq0",
+               .channels[0]    = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+       },
+       [DMACH_XD1] = {
+               .name           = "xdreq1",
+               .channels[1]    = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+       },
+       [DMACH_SDI] = {
+               .name           = "sdi",
+               .channels[0]    = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+               .channels[3]    = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_SPI0] = {
+               .name           = "spi0",
+               .channels[1]    = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_SPI + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + S3C2410_SPRDAT,
+       },
+       [DMACH_SPI1] = {
+               .name           = "spi1",
+               .channels[3]    = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+       },
+       [DMACH_UART0] = {
+               .name           = "uart0",
+               .channels[0]    = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1] = {
+               .name           = "uart1",
+               .channels[1]    = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2] = {
+               .name           = "uart2",
+               .channels[3]    = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_TIMER] = {
+               .name           = "timer",
+               .channels[0]    = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+               .channels[3]    = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+       },
+       [DMACH_I2S_IN] = {
+               .name           = "i2s-sdi",
+               .channels[1]    = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_I2S_OUT] = {
+               .name           = "i2s-sdo",
+               .channels[2]    = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_USB_EP1] = {
+               .name           = "usb-ep1",
+               .channels[0]    = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP2] = {
+               .name           = "usb-ep2",
+               .channels[1]    = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP3] = {
+               .name           = "usb-ep3",
+               .channels[2]    = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP4] = {
+               .name           = "usb-ep4",
+               .channels[3]    =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+       },
+};
+
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+                              struct s3c24xx_dma_map *map)
+{
+       chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
+       .select         = s3c2410_dma_select,
+       .dcon_mask      = 7 << 24,
+       .map            = s3c2410_dma_mappings,
+       .map_size       = ARRAY_SIZE(s3c2410_dma_mappings),
+};
+
+static int s3c2410_dma_add(struct sys_device *sysdev)
+{
+       return s3c24xx_dma_init_map(&s3c2410_dma_sel);
+}
+
+static struct sysdev_driver s3c2410_dma_driver = {
+       .add    = s3c2410_dma_add,
+};
+
+static int __init s3c2410_dma_init(void)
+{
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
+}
+
+arch_initcall(s3c2410_dma_init);
+
+/* S3C2442 DMA contains the same selection table as the S3C2410 */
+
+static struct sysdev_driver s3c2442_dma_driver = {
+       .add    = s3c2410_dma_add,
+};
+
+static int __init s3c2442_dma_init(void)
+{
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
+}
+
+arch_initcall(s3c2442_dma_init);
+
+
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
new file mode 100644 (file)
index 0000000..c796c9c
--- /dev/null
@@ -0,0 +1,48 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include "cpu.h"
+#include "pm.h"
+
+static int s3c2410_irq_add(struct sys_device *sysdev)
+{
+       return 0;
+}
+
+static struct sysdev_driver s3c2410_irq_driver = {
+       .add            = s3c2410_irq_add,
+       .suspend        = s3c24xx_irq_suspend,
+       .resume         = s3c24xx_irq_resume,
+};
+
+static int s3c2410_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
+}
+
+arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
new file mode 100644 (file)
index 0000000..e51d766
--- /dev/null
@@ -0,0 +1,120 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
+ *
+ * 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/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "pm.h"
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+extern void pm_dbg(const char *fmt, ...);
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+#endif
+
+static void s3c2410_pm_prepare(void)
+{
+       /* ensure at least GSTATUS3 has the resume address */
+
+       __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
+
+       DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+       DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
+
+       if ( machine_is_aml_m5900() )
+               s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+
+}
+
+int s3c2410_pm_resume(struct sys_device *dev)
+{
+       unsigned long tmp;
+
+       /* unset the return-from-sleep flag, to ensure reset */
+
+       tmp = __raw_readl(S3C2410_GSTATUS2);
+       tmp &= S3C2410_GSTATUS2_OFFRESET;
+       __raw_writel(tmp, S3C2410_GSTATUS2);
+
+       if ( machine_is_aml_m5900() )
+               s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+
+       return 0;
+}
+
+static int s3c2410_pm_add(struct sys_device *dev)
+{
+       pm_cpu_prep = s3c2410_pm_prepare;
+       pm_cpu_sleep = s3c2410_cpu_suspend;
+
+       return 0;
+}
+
+static struct sysdev_driver s3c2410_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
+
+/* register ourselves */
+
+static int __init s3c2410_pm_drvinit(void)
+{
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
+}
+
+arch_initcall(s3c2410_pm_drvinit);
+
+static struct sysdev_driver s3c2440_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
+
+static int __init s3c2440_pm_drvinit(void)
+{
+       return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
+}
+
+arch_initcall(s3c2440_pm_drvinit);
+
+static struct sysdev_driver s3c2442_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
+
+static int __init s3c2442_pm_drvinit(void)
+{
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
+}
+
+arch_initcall(s3c2442_pm_drvinit);
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
new file mode 100644 (file)
index 0000000..9179a10
--- /dev/null
@@ -0,0 +1,68 @@
+/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *     Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *     Cliff Brake, (c) 2001
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+       /* s3c2410_cpu_suspend
+        *
+        * put the cpu into sleep mode
+       */
+
+ENTRY(s3c2410_cpu_suspend)
+       @@ prepare cpu to sleep
+
+       ldr     r4, =S3C2410_REFRESH
+       ldr     r5, =S3C24XX_MISCCR
+       ldr     r6, =S3C2410_CLKCON
+       ldr     r7, [ r4 ]              @ get REFRESH (and ensure in TLB)
+       ldr     r8, [ r5 ]              @ get MISCCR (and ensure in TLB)
+       ldr     r9, [ r6 ]              @ get CLKCON (and ensure in TLB)
+
+       orr     r7, r7, #S3C2410_REFRESH_SELF   @ SDRAM sleep command
+       orr     r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+       orr     r9, r9, #S3C2410_CLKCON_POWER   @ power down command
+
+       teq     pc, #0                  @ first as a trial-run to load cache
+       bl      s3c2410_do_sleep
+       teq     r0, r0                  @ now do it for real
+       b       s3c2410_do_sleep        @
+
+       @@ align next bit of code to cache line
+       .align  8
+s3c2410_do_sleep:
+       streq   r7, [ r4 ]                      @ SDRAM sleep command
+       streq   r8, [ r5 ]                      @ SDRAM power-down config
+       streq   r9, [ r6 ]                      @ CPU sleep
+1:     beq     1b
+       mov     pc, r14
index a110cff9cf6bf06f4546972afe007138d537e21d..183e4033ce617b07b9c5bff936d454e21292b47d 100644 (file)
@@ -8,17 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to kernel v2.6
- *     18-Jan-2004 BJD  Added serial port configuration
- *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
- *     28-Sep-2004 BJD  Updates for new serial port bits
- *     04-Nov-2004 BJD  Updated UART configuration process
- *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
- *     13-Aug-2005 DA   Removed UART from initial I/O mappings
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2410/s3c2412-dma.c
new file mode 100644 (file)
index 0000000..171f370
--- /dev/null
@@ -0,0 +1,160 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
+ *
+ * (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+
+#include "dma.h"
+#include "cpu.h"
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
+
+static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
+       [DMACH_XD0] = {
+               .name           = "xdreq0",
+               .channels       = MAP(S3C2412_DMAREQSEL_XDREQ0),
+       },
+       [DMACH_XD1] = {
+               .name           = "xdreq1",
+               .channels       = MAP(S3C2412_DMAREQSEL_XDREQ1),
+       },
+       [DMACH_SDI] = {
+               .name           = "sdi",
+               .channels       = MAP(S3C2412_DMAREQSEL_SDI),
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_SPI0] = {
+               .name           = "spi0",
+               .channels       = MAP(S3C2412_DMAREQSEL_SPI0TX),
+               .hw_addr.to     = S3C2410_PA_SPI + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + S3C2410_SPRDAT,
+       },
+       [DMACH_SPI1] = {
+               .name           = "spi1",
+               .channels       = MAP(S3C2412_DMAREQSEL_SPI1TX),
+               .hw_addr.to     = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+       },
+       [DMACH_UART0] = {
+               .name           = "uart0",
+               .channels       = MAP(S3C2412_DMAREQSEL_UART0_0),
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1] = {
+               .name           = "uart1",
+               .channels       = MAP(S3C2412_DMAREQSEL_UART1_0),
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2] = {
+               .name           = "uart2",
+               .channels       = MAP(S3C2412_DMAREQSEL_UART2_0),
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_UART0_SRC2] = {
+               .name           = "uart0",
+               .channels       = MAP(S3C2412_DMAREQSEL_UART0_1),
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1_SRC2] = {
+               .name           = "uart1",
+               .channels       = MAP(S3C2412_DMAREQSEL_UART1_1),
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2_SRC2] = {
+               .name           = "uart2",
+               .channels       = MAP(S3C2412_DMAREQSEL_UART2_1),
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_TIMER] = {
+               .name           = "timer",
+               .channels       = MAP(S3C2412_DMAREQSEL_TIMER),
+       },
+       [DMACH_I2S_IN] = {
+               .name           = "i2s-sdi",
+               .channels       = MAP(S3C2412_DMAREQSEL_I2SRX),
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_I2S_OUT] = {
+               .name           = "i2s-sdo",
+               .channels       = MAP(S3C2412_DMAREQSEL_I2STX),
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_USB_EP1] = {
+               .name           = "usb-ep1",
+               .channels       = MAP(S3C2412_DMAREQSEL_USBEP1),
+       },
+       [DMACH_USB_EP2] = {
+               .name           = "usb-ep2",
+               .channels       = MAP(S3C2412_DMAREQSEL_USBEP2),
+       },
+       [DMACH_USB_EP3] = {
+               .name           = "usb-ep3",
+               .channels       = MAP(S3C2412_DMAREQSEL_USBEP3),
+       },
+       [DMACH_USB_EP4] = {
+               .name           = "usb-ep4",
+               .channels       = MAP(S3C2412_DMAREQSEL_USBEP4),
+       },
+};
+
+static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
+                              struct s3c24xx_dma_map *map)
+{
+       writel(chan->regs + S3C2412_DMA_DMAREQSEL,
+              map->channels[0] | S3C2412_DMAREQSEL_HW);
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
+       .select         = s3c2412_dma_select,
+       .dcon_mask      = 0,
+       .map            = s3c2412_dma_mappings,
+       .map_size       = ARRAY_SIZE(s3c2412_dma_mappings),
+};
+
+static int s3c2412_dma_add(struct sys_device *sysdev)
+{
+       return s3c24xx_dma_init_map(&s3c2412_dma_sel);
+}
+
+static struct sysdev_driver s3c2412_dma_driver = {
+       .add    = s3c2412_dma_add,
+};
+
+static int __init s3c2412_dma_init(void)
+{
+       return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_dma_driver);
+}
+
+arch_initcall(s3c2412_dma_init);
index c80ec93dfea968104d1c3ce254c8ae589fd09700..7f741547658fbd34173815982ecc92d9411b6b2d 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "cpu.h"
 #include "irq.h"
+#include "pm.h"
 
 /* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
  * having them turn up in both the INT* and the EINT* registers. Whilst
@@ -120,6 +121,8 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
 
 static struct sysdev_driver s3c2412_irq_driver = {
        .add            = s3c2412_irq_add,
+       .suspend        = s3c24xx_irq_suspend,
+       .resume         = s3c24xx_irq_resume,
 };
 
 static int s3c2412_irq_init(void)
diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2410/s3c2412-pm.c
new file mode 100644 (file)
index 0000000..19b6332
--- /dev/null
@@ -0,0 +1,128 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "cpu.h"
+#include "pm.h"
+
+#include "s3c2412.h"
+
+static void s3c2412_cpu_suspend(void)
+{
+       unsigned long tmp;
+
+       /* set our standby method to sleep */
+
+       tmp = __raw_readl(S3C2412_PWRCFG);
+       tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP;
+       __raw_writel(tmp, S3C2412_PWRCFG);
+
+       /* issue the standby signal into the pm unit. Note, we
+        * issue a write-buffer drain just in case */
+
+       tmp = 0;
+
+       asm("b 1f\n\t"
+           ".align 5\n\t"
+           "1:\n\t"
+           "mcr p15, 0, %0, c7, c10, 4\n\t"
+           "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+       /* we should never get past here */
+
+       panic("sleep resumed to originator?");
+}
+
+static void s3c2412_pm_prepare(void)
+{
+}
+
+static int s3c2412_pm_add(struct sys_device *sysdev)
+{
+       pm_cpu_prep = s3c2412_pm_prepare;
+       pm_cpu_sleep = s3c2412_cpu_suspend;
+
+       return 0;
+}
+
+static struct sleep_save s3c2412_sleep[] = {
+       SAVE_ITEM(S3C2412_DSC0),
+       SAVE_ITEM(S3C2412_DSC1),
+       SAVE_ITEM(S3C2413_GPJDAT),
+       SAVE_ITEM(S3C2413_GPJCON),
+       SAVE_ITEM(S3C2413_GPJUP),
+
+       /* save the PWRCFG to get back to original sleep method */
+
+       SAVE_ITEM(S3C2412_PWRCFG),
+
+       /* save the sleep configuration anyway, just in case these
+        * get damaged during wakeup */
+
+       SAVE_ITEM(S3C2412_GPBSLPCON),
+       SAVE_ITEM(S3C2412_GPCSLPCON),
+       SAVE_ITEM(S3C2412_GPDSLPCON),
+       SAVE_ITEM(S3C2412_GPESLPCON),
+       SAVE_ITEM(S3C2412_GPFSLPCON),
+       SAVE_ITEM(S3C2412_GPGSLPCON),
+       SAVE_ITEM(S3C2412_GPHSLPCON),
+       SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+       s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+       return 0;
+}
+
+static int s3c2412_pm_resume(struct sys_device *dev)
+{
+       unsigned long tmp;
+
+       tmp = __raw_readl(S3C2412_PWRCFG);
+       tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
+       tmp |=  S3C2412_PWRCFG_STANDBYWFI_IDLE;
+       __raw_writel(tmp, S3C2412_PWRCFG);
+
+       s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+       return 0;
+}
+
+static struct sysdev_driver s3c2412_pm_driver = {
+       .add            = s3c2412_pm_add,
+       .suspend        = s3c2412_pm_suspend,
+       .resume         = s3c2412_pm_resume,
+};
+
+static __init int s3c2412_pm_init(void)
+{
+       return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver);
+}
+
+arch_initcall(s3c2412_pm_init);
index 2d163f7600be51606c9a1fc7dba7b21e3c87048f..e76431c41461f1f195fd77625da0134f77576155 100644 (file)
@@ -8,17 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to kernel v2.6
- *     18-Jan-2004 BJD  Added serial port configuration
- *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
- *     28-Sep-2004 BJD  Updates for new serial port bits
- *     04-Nov-2004 BJD  Updated UART configuration process
- *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
- *     13-Aug-2005 DA   Removed UART from initial I/O mappings
 */
 
 #include <linux/kernel.h>
 
 #ifndef CONFIG_CPU_S3C2412_ONLY
 void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+
+static inline void s3c2412_init_gpio2(void)
+{
+       s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+}
+#else
+#define s3c2412_init_gpio2() do { } while(0)
 #endif
 
 /* Initial IO mappings */
@@ -76,6 +72,7 @@ void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
        /* rename devices that are s3c2412/s3c2413 specific */
        s3c_device_sdi.name  = "s3c2412-sdi";
+       s3c_device_lcd.name  = "s3c2412-lcd";
        s3c_device_nand.name = "s3c2412-nand";
 }
 
@@ -110,7 +107,7 @@ void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
 {
        /* move base of IO */
 
-       s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+       s3c2412_init_gpio2();
 
        /* set our idle function */
 
@@ -161,48 +158,8 @@ void __init s3c2412_init_clocks(int xtal)
  * as a driver which may support both 2410 and 2440 may try and use it.
 */
 
-#ifdef CONFIG_PM
-static struct sleep_save s3c2412_sleep[] = {
-       SAVE_ITEM(S3C2412_DSC0),
-       SAVE_ITEM(S3C2412_DSC1),
-       SAVE_ITEM(S3C2413_GPJDAT),
-       SAVE_ITEM(S3C2413_GPJCON),
-       SAVE_ITEM(S3C2413_GPJUP),
-
-       /* save the sleep configuration anyway, just in case these
-        * get damaged during wakeup */
-
-       SAVE_ITEM(S3C2412_GPBSLPCON),
-       SAVE_ITEM(S3C2412_GPCSLPCON),
-       SAVE_ITEM(S3C2412_GPDSLPCON),
-       SAVE_ITEM(S3C2412_GPESLPCON),
-       SAVE_ITEM(S3C2412_GPFSLPCON),
-       SAVE_ITEM(S3C2412_GPGSLPCON),
-       SAVE_ITEM(S3C2412_GPHSLPCON),
-       SAVE_ITEM(S3C2413_GPJSLPCON),
-};
-
-static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
-{
-       s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-       return 0;
-}
-
-static int s3c2412_resume(struct sys_device *dev)
-{
-       s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
-       return 0;
-}
-
-#else
-#define s3c2412_suspend NULL
-#define s3c2412_resume  NULL
-#endif
-
 struct sysdev_class s3c2412_sysclass = {
        set_kset_name("s3c2412-core"),
-       .suspend        = s3c2412_suspend,
-       .resume         = s3c2412_resume
 };
 
 static int __init s3c2412_core_init(void)
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2410/s3c2440-dma.c
new file mode 100644 (file)
index 0000000..11e109c
--- /dev/null
@@ -0,0 +1,164 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
+ *
+ * (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2440 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include "dma.h"
+
+#include "cpu.h"
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
+       [DMACH_XD0] = {
+               .name           = "xdreq0",
+               .channels[0]    = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+       },
+       [DMACH_XD1] = {
+               .name           = "xdreq1",
+               .channels[1]    = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+       },
+       [DMACH_SDI] = {
+               .name           = "sdi",
+               .channels[0]    = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+               .channels[1]    = S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+               .channels[3]    = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_SPI0] = {
+               .name           = "spi0",
+               .channels[1]    = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_SPI + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + S3C2410_SPRDAT,
+       },
+       [DMACH_SPI1] = {
+               .name           = "spi1",
+               .channels[3]    = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+               .hw_addr.from   = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+       },
+       [DMACH_UART0] = {
+               .name           = "uart0",
+               .channels[0]    = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART0 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART0 + S3C2410_URXH,
+       },
+       [DMACH_UART1] = {
+               .name           = "uart1",
+               .channels[1]    = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART1 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART1 + S3C2410_URXH,
+       },
+       [DMACH_UART2] = {
+               .name           = "uart2",
+               .channels[3]    = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_UART2 + S3C2410_UTXH,
+               .hw_addr.from   = S3C2410_PA_UART2 + S3C2410_URXH,
+       },
+       [DMACH_TIMER] = {
+               .name           = "timer",
+               .channels[0]    = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+               .channels[3]    = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+       },
+       [DMACH_I2S_IN] = {
+               .name           = "i2s-sdi",
+               .channels[1]    = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+               .hw_addr.from   = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_I2S_OUT] = {
+               .name           = "i2s-sdo",
+               .channels[0]    = S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
+               .channels[2]    = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+               .hw_addr.to     = S3C2410_PA_IIS + S3C2410_IISFIFO,
+       },
+       [DMACH_PCM_IN] = {
+               .name           = "pcm-in",
+               .channels[0]    = S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
+               .channels[2]    = S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
+               .hw_addr.from   = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+       },
+       [DMACH_PCM_OUT] = {
+               .name           = "pcm-out",
+               .channels[1]    = S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
+               .channels[3]    = S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
+               .hw_addr.to     = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+       },
+       [DMACH_MIC_IN] = {
+               .name           = "mic-in",
+               .channels[2]    = S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
+               .channels[3]    = S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
+               .hw_addr.from   = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
+       },
+       [DMACH_USB_EP1] = {
+               .name           = "usb-ep1",
+               .channels[0]    = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP2] = {
+               .name           = "usb-ep2",
+               .channels[1]    = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP3] = {
+               .name           = "usb-ep3",
+               .channels[2]    = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+       },
+       [DMACH_USB_EP4] = {
+               .name           = "usb-ep4",
+               .channels[3]    = S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+       },
+};
+
+static void s3c2440_dma_select(struct s3c2410_dma_chan *chan,
+                              struct s3c24xx_dma_map *map)
+{
+       chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
+       .select         = s3c2440_dma_select,
+       .dcon_mask      = 7 << 24,
+       .map            = s3c2440_dma_mappings,
+       .map_size       = ARRAY_SIZE(s3c2440_dma_mappings),
+};
+
+static int s3c2440_dma_add(struct sys_device *sysdev)
+{
+       return s3c24xx_dma_init_map(&s3c2440_dma_sel);
+}
+
+static struct sysdev_driver s3c2440_dma_driver = {
+       .add    = s3c2440_dma_add,
+};
+
+static int __init s3c2440_dma_init(void)
+{
+       return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver);
+}
+
+arch_initcall(s3c2440_dma_init);
+
index 16fa2a3b38fa02de47a5d24e96bed959352d9143..c92ea66ba45e5599b99d59efae967268630a5046 100644 (file)
@@ -8,11 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     29-Aug-2004 BJD  Start of drive-strength control
- *     09-Nov-2004 BJD  Added symbol export
- *     11-Jan-2005 BJD  Include fix
 */
 
 #include <linux/kernel.h>
index 1667ba1fa43dc9b29d568ca8dd4a8ca86da83b01..fc08febe2e543891cd2b0599a0dcb403e8f32cdf 100644 (file)
@@ -119,7 +119,7 @@ static int s3c2440_irq_add(struct sys_device *sysdev)
 }
 
 static struct sysdev_driver s3c2440_irq_driver = {
-       .add    = s3c2440_irq_add,
+       .add            = s3c2440_irq_add,
 };
 
 static int s3c2440_irq_init(void)
index 44c5affa9b89ac96e1b8729568afacb2daa80a29..0d13546c350005152d330b193fdf135f72605ade 100644 (file)
@@ -120,7 +120,9 @@ static int s3c244x_irq_add(struct sys_device *sysdev)
 }
 
 static struct sysdev_driver s3c2440_irq_driver = {
-       .add    = s3c244x_irq_add,
+       .add            = s3c244x_irq_add,
+       .suspend        = s3c24xx_irq_suspend,
+       .resume         = s3c24xx_irq_resume,
 };
 
 static int s3c2440_irq_init(void)
@@ -131,9 +133,12 @@ static int s3c2440_irq_init(void)
 arch_initcall(s3c2440_irq_init);
 
 static struct sysdev_driver s3c2442_irq_driver = {
-       .add    = s3c244x_irq_add,
+       .add            = s3c244x_irq_add,
+       .suspend        = s3c24xx_irq_suspend,
+       .resume         = s3c24xx_irq_resume,
 };
 
+
 static int s3c2442_irq_init(void)
 {
        return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver);
index a7561a79fc825dac89b97188554d5ff326411791..2018c2e1dcc5aecc97a9c9ec1825fc3c6b2fc29c 100644 (file)
 
        .text
 
-       /* s3c2410_cpu_suspend
+       /* s3c2410_cpu_save
         *
-        * put the cpu into sleep mode
+        * save enough of the CPU state to allow us to re-start
+        * pm.c code. as we store items like the sp/lr, we will
+        * end up returning from this function when the cpu resumes
+        * so the return value is set to mark this.
+        *
+        * This arangement means we avoid having to flush the cache
+        * from this code.
         *
         * entry:
-        *      r0 = sleep save block
+        *      r0 = pointer to save block
+        *
+        * exit:
+        *      r0 = 0 => we stored everything
+        *           1 => resumed from sleep
        */
 
-ENTRY(s3c2410_cpu_suspend)
+ENTRY(s3c2410_cpu_save)
        stmfd   sp!, { r4 - r12, lr }
 
        @@ store co-processor registers
@@ -62,44 +72,14 @@ ENTRY(s3c2410_cpu_suspend)
 
        stmia   r0, { r4 - r13 }
 
-       @@ flush the caches to ensure everything is back out to
-       @@ SDRAM before the core powers down
-
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-       bl      arm920_flush_kern_cache_all
-#endif
-
-       @@ prepare cpu to sleep
-
-       ldr     r4, =S3C2410_REFRESH
-       ldr     r5, =S3C24XX_MISCCR
-       ldr     r6, =S3C2410_CLKCON
-       ldr     r7, [ r4 ]              @ get REFRESH (and ensure in TLB)
-       ldr     r8, [ r5 ]              @ get MISCCR (and ensure in TLB)
-       ldr     r9, [ r6 ]              @ get CLKCON (and ensure in TLB)
-
-       orr     r7, r7, #S3C2410_REFRESH_SELF   @ SDRAM sleep command
-       orr     r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
-       orr     r9, r9, #S3C2410_CLKCON_POWER   @ power down command
-
-       teq     pc, #0                  @ first as a trial-run to load cache
-       bl      s3c2410_do_sleep
-       teq     r0, r0                  @ now do it for real
-       b       s3c2410_do_sleep        @
-
-       @@ align next bit of code to cache line
-       .align  8
-s3c2410_do_sleep:
-       streq   r7, [ r4 ]                      @ SDRAM sleep command
-       streq   r8, [ r5 ]                      @ SDRAM power-down config
-       streq   r9, [ r6 ]                      @ CPU sleep
-1:     beq     1b
-       mov     pc, r14
+       mov     r0, #0
+       ldmfd   sp, { r4 - r12, pc }
 
        @@ return to the caller, after having the MMU
        @@ turned on, this restores the last bits from the
        @@ stack
 resume_with_mmu:
+       mov     r0, #1
        ldmfd   sp!, { r4 - r12, pc }
 
        .ltorg
index 6b22d8f0a00df5de142bed58ee9adbce2f0a2612..c635efa7cd3189cf97f1ec4550d4b987d6a2b870 100644 (file)
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     14-Sep-2004 BJD  Created
- *     18-Oct-2004 BJD  Cleanups, and added code to report OC cleared
- *     09-Aug-2005 BJD  Renamed s3c2410_report_oc to s3c2410_usb_report_oc
- *     09-Aug-2005 BJD  Ports powered only if both are enabled
 */
 
 #define DEBUG
index a0dfa390e34bd0c686e3fdf05776684cd4ee08f8..6496eb645ceeb9eed2f3a8b85def1fd7400d6e03 100644 (file)
@@ -91,30 +91,29 @@ static struct mcp_plat_data collie_mcp_data = {
 /*
  * low-level UART features.
  */
-static struct locomo_dev *uart_dev = NULL;
+struct platform_device collie_locomo_device;
 
 static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
 {
-       if (!uart_dev) return;
-
        if (mctrl & TIOCM_RTS)
-               locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+               locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_RTS, 0);
        else
-               locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+               locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_RTS, 1);
 
        if (mctrl & TIOCM_DTR)
-               locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+               locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_DTR, 0);
        else
-               locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+               locomo_gpio_write(&collie_locomo_device.dev, LOCOMO_GPIO_DTR, 1);
 }
 
 static u_int collie_uart_get_mctrl(struct uart_port *port)
 {
        int ret = TIOCM_CD;
        unsigned int r;
-       if (!uart_dev) return ret;
 
-       r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+       r = locomo_gpio_read_output(&collie_locomo_device.dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+       if (r == -ENODEV)
+               return ret;
        if (r & LOCOMO_GPIO_CTS)
                ret |= TIOCM_CTS;
        if (r & LOCOMO_GPIO_DSR)
@@ -130,13 +129,11 @@ static struct sa1100_port_fns collie_port_fns __initdata = {
 
 static int collie_uart_probe(struct locomo_dev *dev)
 {
-       uart_dev = dev;
        return 0;
 }
 
 static int collie_uart_remove(struct locomo_dev *dev)
 {
-       uart_dev = NULL;
        return 0;
 }
 
@@ -170,7 +167,7 @@ static struct resource locomo_resources[] = {
        },
 };
 
-static struct platform_device locomo_device = {
+struct platform_device collie_locomo_device = {
        .name           = "locomo",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(locomo_resources),
@@ -178,7 +175,7 @@ static struct platform_device locomo_device = {
 };
 
 static struct platform_device *devices[] __initdata = {
-       &locomo_device,
+       &collie_locomo_device,
        &colliescoop_device,
 };
 
index 41b370090b60e2903ea8a3d1919fd19991332197..13bbd08ff841d2c006bd99646488193a7a7c619b 100644 (file)
@@ -117,7 +117,6 @@ static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int wh
        } else {
                switch (size) {
                case 1:
-                       addr &= ~3;
                        v = __raw_readb(addr);
                        break;
 
index b4f220dd5eb8bf60e6290e0419a6447c6827479b..c0bfb8212b7742abda15da17ffd47b09c3fe24e2 100644 (file)
@@ -15,6 +15,7 @@ config CPU_ARM610
        select CPU_32v3
        select CPU_CACHE_V3
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V3 if MMU
        select CPU_TLB_V3 if MMU
        help
@@ -24,6 +25,20 @@ config CPU_ARM610
          Say Y if you want support for the ARM610 processor.
          Otherwise, say N.
 
+# ARM7TDMI
+config CPU_ARM7TDMI
+       bool "Support ARM7TDMI processor"
+       depends on !MMU
+       select CPU_32v4T
+       select CPU_ABRT_LV4T
+       select CPU_CACHE_V4
+       help
+         A 32-bit RISC microprocessor based on the ARM7 processor core
+         which has no memory control unit and cache.
+
+         Say Y if you want support for the ARM7TDMI processor.
+         Otherwise, say N.
+
 # ARM710
 config CPU_ARM710
        bool "Support ARM710 processor" if !ARCH_CLPS7500 && ARCH_RPC
@@ -31,6 +46,7 @@ config CPU_ARM710
        select CPU_32v3
        select CPU_CACHE_V3
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V3 if MMU
        select CPU_TLB_V3 if MMU
        help
@@ -50,6 +66,7 @@ config CPU_ARM720T
        select CPU_ABRT_LV4T
        select CPU_CACHE_V4
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WT if MMU
        select CPU_TLB_V4WT if MMU
        help
@@ -59,6 +76,36 @@ config CPU_ARM720T
          Say Y if you want support for the ARM720T processor.
          Otherwise, say N.
 
+# ARM740T
+config CPU_ARM740T
+       bool "Support ARM740T processor" if ARCH_INTEGRATOR
+       depends on !MMU
+       select CPU_32v4T
+       select CPU_ABRT_LV4T
+       select CPU_CACHE_V3     # although the core is v4t
+       select CPU_CP15_MPU
+       help
+         A 32-bit RISC processor with 8KB cache or 4KB variants,
+         write buffer and MPU(Protection Unit) built around
+         an ARM7TDMI core.
+
+         Say Y if you want support for the ARM740T processor.
+         Otherwise, say N.
+
+# ARM9TDMI
+config CPU_ARM9TDMI
+       bool "Support ARM9TDMI processor"
+       depends on !MMU
+       select CPU_32v4T
+       select CPU_ABRT_NOMMU
+       select CPU_CACHE_V4
+       help
+         A 32-bit RISC microprocessor based on the ARM9 processor core
+         which has no memory control unit and cache.
+
+         Say Y if you want support for the ARM9TDMI processor.
+         Otherwise, say N.
+
 # ARM920T
 config CPU_ARM920T
        bool "Support ARM920T processor"
@@ -68,6 +115,7 @@ config CPU_ARM920T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WBI if MMU
        help
@@ -89,6 +137,7 @@ config CPU_ARM922T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WBI if MMU
        help
@@ -108,6 +157,7 @@ config CPU_ARM925T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WBI if MMU
        help
@@ -126,6 +176,7 @@ config CPU_ARM926T
        select CPU_32v5
        select CPU_ABRT_EV5TJ
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WBI if MMU
        help
@@ -136,6 +187,39 @@ config CPU_ARM926T
          Say Y if you want support for the ARM926T processor.
          Otherwise, say N.
 
+# ARM940T
+config CPU_ARM940T
+       bool "Support ARM940T processor" if ARCH_INTEGRATOR
+       depends on !MMU
+       select CPU_32v4T
+       select CPU_ABRT_NOMMU
+       select CPU_CACHE_VIVT
+       select CPU_CP15_MPU
+       help
+         ARM940T is a member of the ARM9TDMI family of general-
+         purpose microprocessors with MPU and seperate 4KB
+         instruction and 4KB data cases, each with a 4-word line
+         length.
+
+         Say Y if you want support for the ARM940T processor.
+         Otherwise, say N.
+
+# ARM946E-S
+config CPU_ARM946E
+       bool "Support ARM946E-S processor" if ARCH_INTEGRATOR
+       depends on !MMU
+       select CPU_32v5
+       select CPU_ABRT_NOMMU
+       select CPU_CACHE_VIVT
+       select CPU_CP15_MPU
+       help
+         ARM946E-S is a member of the ARM9E-S family of high-
+         performance, 32-bit system-on-chip processor solutions.
+         The TCM and ARMv5TE 32-bit instruction set is supported.
+
+         Say Y if you want support for the ARM946E-S processor.
+         Otherwise, say N.
+
 # ARM1020 - needs validating
 config CPU_ARM1020
        bool "Support ARM1020T (rev 0) processor"
@@ -144,6 +228,7 @@ config CPU_ARM1020
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WBI if MMU
        help
@@ -161,6 +246,7 @@ config CPU_ARM1020E
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WBI if MMU
        depends on n
@@ -172,6 +258,7 @@ config CPU_ARM1022
        select CPU_32v5
        select CPU_ABRT_EV4T
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU # can probably do better
        select CPU_TLB_V4WBI if MMU
        help
@@ -189,6 +276,7 @@ config CPU_ARM1026
        select CPU_32v5
        select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU # can probably do better
        select CPU_TLB_V4WBI if MMU
        help
@@ -207,6 +295,7 @@ config CPU_SA110
        select CPU_ABRT_EV4
        select CPU_CACHE_V4WB
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_COPY_V4WB if MMU
        select CPU_TLB_V4WB if MMU
        help
@@ -227,16 +316,18 @@ config CPU_SA1100
        select CPU_ABRT_EV4
        select CPU_CACHE_V4WB
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_TLB_V4WB if MMU
 
 # XScale
 config CPU_XSCALE
        bool
-       depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
+       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
        default y
        select CPU_32v5
        select CPU_ABRT_EV5T
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_TLB_V4WBI if MMU
 
 # XScale Core Version 3
@@ -247,6 +338,7 @@ config CPU_XSC3
        select CPU_32v5
        select CPU_ABRT_EV5T
        select CPU_CACHE_VIVT
+       select CPU_CP15_MMU
        select CPU_TLB_V4WBI if MMU
        select IO_36
 
@@ -258,6 +350,7 @@ config CPU_V6
        select CPU_ABRT_EV6
        select CPU_CACHE_V6
        select CPU_CACHE_VIPT
+       select CPU_CP15_MMU
        select CPU_COPY_V6 if MMU
        select CPU_TLB_V6 if MMU
 
@@ -299,6 +392,9 @@ config CPU_32v6
        bool
 
 # The abort model
+config CPU_ABRT_NOMMU
+       bool
+
 config CPU_ABRT_EV4
        bool
 
@@ -380,6 +476,23 @@ config CPU_TLB_V6
 
 endif
 
+config CPU_CP15
+       bool
+       help
+         Processor has the CP15 register.
+
+config CPU_CP15_MMU
+       bool
+       select CPU_CP15
+       help
+         Processor has the CP15 register, which has MMU related registers.
+
+config CPU_CP15_MPU
+       bool
+       select CPU_CP15
+       help
+         Processor has the CP15 register, which has MPU related registers.
+
 #
 # CPU supports 36-bit I/O
 #
@@ -390,7 +503,7 @@ comment "Processor Features"
 
 config ARM_THUMB
        bool "Support Thumb user binaries"
-       depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || 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
        default y
        help
          Say Y if you want to include kernel support for running user space
@@ -411,23 +524,48 @@ config CPU_BIG_ENDIAN
          port must properly enable any big-endian related features
          of your chipset/board/processor.
 
+config CPU_HIGH_VECTOR
+       depends !MMU && CPU_CP15 && !CPU_ARM740T
+       bool "Select the High exception vector"
+       default n
+       help
+         Say Y here to select high exception vector(0xFFFF0000~).
+         The exception vector can be vary depending on the platform
+         design in nommu mode. If your platform needs to select
+         high exception vector, say Y.
+         Otherwise or if you are unsure, say N, and the low exception
+         vector (0x00000000~) will be used.
+
 config CPU_ICACHE_DISABLE
-       bool "Disable I-Cache"
-       depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6
+       bool "Disable I-Cache (I-bit)"
+       depends on CPU_CP15 && !(CPU_ARM610 || CPU_ARM710 || CPU_ARM720T || CPU_ARM740T || CPU_XSCALE || CPU_XSC3)
        help
          Say Y here to disable the processor instruction cache. Unless
          you have a reason not to or are unsure, say N.
 
 config CPU_DCACHE_DISABLE
-       bool "Disable D-Cache"
-       depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6
+       bool "Disable D-Cache (C-bit)"
+       depends on CPU_CP15
        help
          Say Y here to disable the processor data cache. Unless
          you have a reason not to or are unsure, say N.
 
+config CPU_DCACHE_SIZE
+       hex
+       depends on CPU_ARM740T || CPU_ARM946E
+       default 0x00001000 if CPU_ARM740T
+       default 0x00002000 # default size for ARM946E-S
+       help
+         Some cores are synthesizable to have various sized cache. For
+         ARM946E-S case, it can vary from 0KB to 1MB.
+         To support such cache operations, it is efficient to know the size
+         before compile time.
+         If your SoC is configured to have a different size, define the value
+         here with proper conditions.
+
 config CPU_DCACHE_WRITETHROUGH
        bool "Force write through D-cache"
-       depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE
+       depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE
        default y if CPU_ARM925T
        help
          Say Y here to use the data cache in writethrough mode. Unless you
@@ -435,7 +573,7 @@ config CPU_DCACHE_WRITETHROUGH
 
 config CPU_CACHE_ROUND_ROBIN
        bool "Round robin I and D cache replacement algorithm"
-       depends on (CPU_ARM926T || CPU_ARM1020) && (!CPU_ICACHE_DISABLE || !CPU_DCACHE_DISABLE)
+       depends on (CPU_ARM926T || CPU_ARM946E || CPU_ARM1020) && (!CPU_ICACHE_DISABLE || !CPU_DCACHE_DISABLE)
        help
          Say Y here to use the predictable round-robin cache replacement
          policy.  Unless you specifically require this or are unsure, say N.
index 21a2770226ee418e9756d2a6663a255850352333..d2f5672ecf62e2a06967884f9edf1c7b53975ab6 100644 (file)
@@ -6,7 +6,7 @@ obj-y                           := consistent.o extable.o fault.o init.o \
                                   iomap.o
 
 obj-$(CONFIG_MMU)              += fault-armv.o flush.o ioremap.o mmap.o \
-                                  mm-armv.o
+                                  pgd.o mmu.o
 
 ifneq ($(CONFIG_MMU),y)
 obj-y                          += nommu.o
@@ -17,6 +17,7 @@ obj-$(CONFIG_MODULES)         += proc-syms.o
 obj-$(CONFIG_ALIGNMENT_TRAP)   += alignment.o
 obj-$(CONFIG_DISCONTIGMEM)     += discontig.o
 
+obj-$(CONFIG_CPU_ABRT_NOMMU)   += abort-nommu.o
 obj-$(CONFIG_CPU_ABRT_EV4)     += abort-ev4.o
 obj-$(CONFIG_CPU_ABRT_EV4T)    += abort-ev4t.o
 obj-$(CONFIG_CPU_ABRT_LV4T)    += abort-lv4t.o
@@ -33,7 +34,7 @@ obj-$(CONFIG_CPU_CACHE_V6)    += cache-v6.o
 obj-$(CONFIG_CPU_COPY_V3)      += copypage-v3.o
 obj-$(CONFIG_CPU_COPY_V4WT)    += copypage-v4wt.o
 obj-$(CONFIG_CPU_COPY_V4WB)    += copypage-v4wb.o
-obj-$(CONFIG_CPU_COPY_V6)      += copypage-v6.o mmu.o
+obj-$(CONFIG_CPU_COPY_V6)      += copypage-v6.o context.o
 obj-$(CONFIG_CPU_SA1100)       += copypage-v4mc.o
 obj-$(CONFIG_CPU_XSCALE)       += copypage-xscale.o
 obj-$(CONFIG_CPU_XSC3)         += copypage-xsc3.o
@@ -46,11 +47,16 @@ obj-$(CONFIG_CPU_TLB_V6)    += tlb-v6.o
 
 obj-$(CONFIG_CPU_ARM610)       += proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM710)       += proc-arm6_7.o
+obj-$(CONFIG_CPU_ARM7TDMI)     += proc-arm7tdmi.o
 obj-$(CONFIG_CPU_ARM720T)      += proc-arm720.o
+obj-$(CONFIG_CPU_ARM740T)      += proc-arm740.o
+obj-$(CONFIG_CPU_ARM9TDMI)     += proc-arm9tdmi.o
 obj-$(CONFIG_CPU_ARM920T)      += proc-arm920.o
 obj-$(CONFIG_CPU_ARM922T)      += proc-arm922.o
 obj-$(CONFIG_CPU_ARM925T)      += proc-arm925.o
 obj-$(CONFIG_CPU_ARM926T)      += proc-arm926.o
+obj-$(CONFIG_CPU_ARM940T)      += proc-arm940.o
+obj-$(CONFIG_CPU_ARM946E)      += proc-arm946.o
 obj-$(CONFIG_CPU_ARM1020)      += proc-arm1020.o
 obj-$(CONFIG_CPU_ARM1020E)     += proc-arm1020e.o
 obj-$(CONFIG_CPU_ARM1022)      += proc-arm1022.o
index db743e510214513740a31b28ee1aca1dc1c2bb43..9fb7b0e25ea1094cec42e47b76c69e45ddf13f44 100644 (file)
  */
 ENTRY(v4t_late_abort)
        tst     r3, #PSR_T_BIT                  @ check for thumb mode
+#ifdef CONFIG_CPU_CP15_MMU
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
+       bic     r1, r1, #1 << 11 | 1 << 10      @ clear bits 11 and 10 of FSR
+#else
+       mov     r0, #0                          @ clear r0, r1 (no FSR/FAR)
+       mov     r1, #0
+#endif
        bne     .data_thumb_abort
        ldr     r8, [r2]                        @ read arm instruction
-       bic     r1, r1, #1 << 11 | 1 << 10      @ clear bits 11 and 10 of FSR
        tst     r8, #1 << 20                    @ L = 1 -> write?
        orreq   r1, r1, #1 << 11                @ yes.
        and     r7, r8, #15 << 24
diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S
new file mode 100644 (file)
index 0000000..a7cc7f9
--- /dev/null
@@ -0,0 +1,19 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: nommu_early_abort
+ *
+ * Params  : r2 = address of aborted instruction
+ *         : r3 = saved SPSR
+ *
+ * Returns : r0 = 0 (abort address)
+ *        : r1 = 0 (FSR)
+ *
+ * Note: There is no FSR/FAR on !CPU_CP15_MMU cores.
+ *       Just fill zero into the registers.
+ */
+       .align  5
+ENTRY(nommu_early_abort)
+       mov     r0, #0                          @ clear r0, r1 (no FSR/FAR)
+       mov     r1, #0
+       mov     pc, lr
index e0d21bbbe7d788e55854dfd3b2c5eb62cc96050a..aa109f074dd9d84d64e0873133c899ef22ebb449 100644 (file)
@@ -735,7 +735,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        /*
         * We got a fault - fix it up, or die.
         */
-       do_bad_area(current, current->mm, addr, fsr, regs);
+       do_bad_area(addr, fsr, regs);
        return 0;
 
  swp:
index b8ad5d58ebe2ff11f687704c8f31a86d83014dd3..b2908063ed6aa5be10ebdfd7ee00b37ef5e8021f 100644 (file)
@@ -29,9 +29,13 @@ ENTRY(v4_flush_user_cache_all)
  *     Clean and invalidate the entire cache.
  */
 ENTRY(v4_flush_kern_cache_all)
+#ifdef CPU_CP15
        mov     r0, #0
        mcr     p15, 0, r0, c7, c7, 0           @ flush ID cache
        mov     pc, lr
+#else
+       /* FALLTHROUGH */
+#endif
 
 /*
  *     flush_user_cache_range(start, end, flags)
@@ -44,9 +48,13 @@ ENTRY(v4_flush_kern_cache_all)
  *     - flags - vma_area_struct flags describing address space
  */
 ENTRY(v4_flush_user_cache_range)
+#ifdef CPU_CP15
        mov     ip, #0
        mcreq   p15, 0, ip, c7, c7, 0           @ flush ID cache
        mov     pc, lr
+#else
+       /* FALLTHROUGH */
+#endif
 
 /*
  *     coherent_kern_range(start, end)
@@ -108,8 +116,10 @@ ENTRY(v4_dma_inv_range)
  *     - end    - virtual end address
  */
 ENTRY(v4_dma_flush_range)
+#ifdef CPU_CP15
        mov     r0, #0
        mcr     p15, 0, r0, c7, c7, 0           @ flush ID cache
+#endif
        /* FALLTHROUGH */
 
 /*
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
new file mode 100644 (file)
index 0000000..79e8002
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  linux/arch/arm/mm/context.c
+ *
+ *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+unsigned int cpu_last_asid = { 1 << ASID_BITS };
+
+/*
+ * We fork()ed a process, and we need a new context for the child
+ * to run in.  We reserve version 0 for initial tasks so we will
+ * always allocate an ASID.
+ */
+void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+       mm->context.id = 0;
+}
+
+void __new_context(struct mm_struct *mm)
+{
+       unsigned int asid;
+
+       asid = ++cpu_last_asid;
+       if (asid == 0)
+               asid = cpu_last_asid = 1 << ASID_BITS;
+
+       /*
+        * If we've used up all our ASIDs, we need
+        * to start a new version and flush the TLB.
+        */
+       if ((asid & ~ASID_MASK) == 0)
+               flush_tlb_all();
+
+       mm->context.id = asid;
+}
index fc69dccdace19cdf7ee6d0f3212318698bc88666..df1645e14b4c11401cc11d454934b8de1b1717ee 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+#include "mm.h"
+
 /*
  * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
  * specific hacks for copying pages efficiently.
@@ -27,8 +29,6 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  L_PTE_CACHEABLE)
 
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
-
 static DEFINE_SPINLOCK(minicache_lock);
 
 /*
index 269ce6913ee95958948b6ce142c8a1773206434f..3d0d3a963d20b6f135bd78c1ad2641aa3d313690 100644 (file)
@@ -17,6 +17,8 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
+#include "mm.h"
+
 #if SHMLBA > 16384
 #error FIX ME
 #endif
@@ -24,8 +26,6 @@
 #define from_address   (0xffff8000)
 #define to_address     (0xffffc000)
 
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
-
 static DEFINE_SPINLOCK(v6_lock);
 
 /*
index 42a6ee255ce0a29a2ae4a53a13c655d3ac4bb802..84ebe0aa379e3b4ae3f017fd28d75ce8474a2665 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+#include "mm.h"
+
 /*
  * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
  * specific hacks for copying pages efficiently.
@@ -29,8 +31,6 @@
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  L_PTE_CACHEABLE)
 
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
-
 static DEFINE_SPINLOCK(minicache_lock);
 
 /*
index c5e0622c77650480f4dc148254d77f3545606d5d..5e658a8744984688ee171e16b67a44aee65c1331 100644 (file)
@@ -131,10 +131,11 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
        force_sig_info(sig, &si, tsk);
 }
 
-void
-do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
-           unsigned int fsr, struct pt_regs *regs)
+void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
+       struct task_struct *tsk = current;
+       struct mm_struct *mm = tsk->active_mm;
+
        /*
         * If we are in kernel mode at this point, we
         * have no context to handle this fault with.
@@ -170,7 +171,7 @@ good_area:
        if (fsr & (1 << 11)) /* write? */
                mask = VM_WRITE;
        else
-               mask = VM_READ|VM_EXEC;
+               mask = VM_READ|VM_EXEC|VM_WRITE;
 
        fault = VM_FAULT_BADACCESS;
        if (!(vma->vm_flags & mask))
@@ -197,7 +198,7 @@ survive:
                return fault;
        }
 
-       if (tsk->pid != 1)
+       if (!is_init(tsk))
                goto out;
 
        /*
@@ -319,7 +320,6 @@ static int
 do_translation_fault(unsigned long addr, unsigned int fsr,
                     struct pt_regs *regs)
 {
-       struct task_struct *tsk;
        unsigned int index;
        pgd_t *pgd, *pgd_k;
        pmd_t *pmd, *pmd_k;
@@ -351,9 +351,7 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
        return 0;
 
 bad_area:
-       tsk = current;
-
-       do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
+       do_bad_area(addr, fsr, regs);
        return 0;
 }
 
@@ -364,8 +362,7 @@ bad_area:
 static int
 do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
-       struct task_struct *tsk = current;
-       do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
+       do_bad_area(addr, fsr, regs);
        return 0;
 }
 
index 73b59e83227f87d4183c5a97db0b9aee41aaaed2..49e9e3804de41ead9959b676a57279cfdd800baf 100644 (file)
@@ -1,6 +1,3 @@
-void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
-                unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-
-void show_pte(struct mm_struct *mm, unsigned long addr);
+void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
 
 unsigned long search_exception_table(unsigned long addr);
index d438ce41cdd5c5ef76d8b1b6d9507a35bbfb6205..454205b789d5a06f52965978a156681cfe34de69 100644 (file)
 #include <asm/system.h>
 #include <asm/tlbflush.h>
 
+#include "mm.h"
+
 #ifdef CONFIG_CPU_CACHE_VIPT
 
 #define ALIAS_FLUSH_START      0xffff4000
 
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
-
 static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 {
        unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
@@ -107,7 +107,7 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
 
        /* VIPT non-aliasing cache */
        if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask) &&
-           vma->vm_flags | VM_EXEC) {
+           vma->vm_flags & VM_EXEC) {
                unsigned long addr = (unsigned long)kaddr;
                /* only flushing the kernel mapping on non-aliasing VIPT */
                __cpuc_coherent_kern_range(addr, addr + len);
index fe3f7f6250085c5c279306ba979cde87407d19d8..22217fe2650b61276b82a280ea9eecc18b48b613 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+#include "mm.h"
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-extern void _stext, _text, _etext, __data_start, _end, __init_begin, __init_end;
+extern void _text, _etext, __data_start, _end, __init_begin, __init_end;
 extern unsigned long phys_initrd_start;
 extern unsigned long phys_initrd_size;
 
@@ -38,12 +37,6 @@ extern unsigned long phys_initrd_size;
  */
 static struct meminfo meminfo __initdata = { 0, };
 
-/*
- * empty_zero_page is a special page that is used for
- * zero-initialized data and COW.
- */
-struct page *empty_zero_page;
-
 void show_mem(void)
 {
        int free = 0, total = 0, reserved = 0;
@@ -83,16 +76,6 @@ void show_mem(void)
        printk("%d pages swap cached\n", cached);
 }
 
-static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
-{
-       return pmd_offset(pgd, virt);
-}
-
-static inline pmd_t *pmd_off_k(unsigned long virt)
-{
-       return pmd_off(pgd_offset_k(virt), virt);
-}
-
 #define for_each_nodebank(iter,mi,no)                  \
        for (iter = 0; iter < mi->nr_banks; iter++)     \
                if (mi->bank[iter].node == no)
@@ -176,62 +159,20 @@ static int __init check_initrd(struct meminfo *mi)
        return initrd_node;
 }
 
-/*
- * Reserve the various regions of node 0
- */
-static __init void reserve_node_zero(pg_data_t *pgdat)
+static inline void map_memory_bank(struct membank *bank)
 {
-       unsigned long res_size = 0;
-
-       /*
-        * Register the kernel text and data with bootmem.
-        * Note that this can only be in node 0.
-        */
-#ifdef CONFIG_XIP_KERNEL
-       reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
-#else
-       reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
-#endif
-
-       /*
-        * Reserve the page tables.  These are already in use,
-        * and can only be in node 0.
-        */
-       reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
-                            PTRS_PER_PGD * sizeof(pgd_t));
-
-       /*
-        * Hmm... This should go elsewhere, but we really really need to
-        * stop things allocating the low memory; ideally we need a better
-        * implementation of GFP_DMA which does not assume that DMA-able
-        * memory starts at zero.
-        */
-       if (machine_is_integrator() || machine_is_cintegrator())
-               res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+#ifdef CONFIG_MMU
+       struct map_desc map;
 
-       /*
-        * These should likewise go elsewhere.  They pre-reserve the
-        * screen memory region at the start of main system memory.
-        */
-       if (machine_is_edb7211())
-               res_size = 0x00020000;
-       if (machine_is_p720t())
-               res_size = 0x00014000;
+       map.pfn = __phys_to_pfn(bank->start);
+       map.virtual = __phys_to_virt(bank->start);
+       map.length = bank->size;
+       map.type = MT_MEMORY;
 
-#ifdef CONFIG_SA1111
-       /*
-        * Because of the SA1111 DMA bug, we want to preserve our
-        * precious DMA-able memory...
-        */
-       res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+       create_mapping(&map);
 #endif
-       if (res_size)
-               reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size);
 }
 
-void __init build_mem_type_table(void);
-void __init create_mapping(struct map_desc *md);
-
 static unsigned long __init
 bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
 {
@@ -248,23 +189,18 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
         * Calculate the pfn range, and map the memory banks for this node.
         */
        for_each_nodebank(i, mi, node) {
+               struct membank *bank = &mi->bank[i];
                unsigned long start, end;
-               struct map_desc map;
 
-               start = mi->bank[i].start >> PAGE_SHIFT;
-               end = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
+               start = bank->start >> PAGE_SHIFT;
+               end = (bank->start + bank->size) >> PAGE_SHIFT;
 
                if (start_pfn > start)
                        start_pfn = start;
                if (end_pfn < end)
                        end_pfn = end;
 
-               map.pfn = __phys_to_pfn(mi->bank[i].start);
-               map.virtual = __phys_to_virt(mi->bank[i].start);
-               map.length = mi->bank[i].size;
-               map.type = MT_MEMORY;
-
-               create_mapping(&map);
+               map_memory_bank(bank);
        }
 
        /*
@@ -346,9 +282,9 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
        return end_pfn;
 }
 
-static void __init bootmem_init(struct meminfo *mi)
+void __init bootmem_init(struct meminfo *mi)
 {
-       unsigned long addr, memend_pfn = 0;
+       unsigned long memend_pfn = 0;
        int node, initrd_node, i;
 
        /*
@@ -360,26 +296,6 @@ static void __init bootmem_init(struct meminfo *mi)
 
        memcpy(&meminfo, mi, sizeof(meminfo));
 
-       /*
-        * Clear out all the mappings below the kernel image.
-        */
-       for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE)
-               pmd_clear(pmd_off_k(addr));
-#ifdef CONFIG_XIP_KERNEL
-       /* The XIP kernel is mapped in the module area -- skip over it */
-       addr = ((unsigned long)&_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
-#endif
-       for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
-               pmd_clear(pmd_off_k(addr));
-
-       /*
-        * Clear out all the kernel space mappings, except for the first
-        * memory bank, up to the end of the vmalloc region.
-        */
-       for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size);
-            addr < VMALLOC_END; addr += PGDIR_SIZE)
-               pmd_clear(pmd_off_k(addr));
-
        /*
         * Locate which node contains the ramdisk image, if any.
         */
@@ -413,114 +329,6 @@ static void __init bootmem_init(struct meminfo *mi)
        max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET;
 }
 
-/*
- * Set up device the mappings.  Since we clear out the page tables for all
- * mappings above VMALLOC_END, we will remove any debug device mappings.
- * This means you have to be careful how you debug this function, or any
- * called function.  This means you can't use any function or debugging
- * method which may touch any device, otherwise the kernel _will_ crash.
- */
-static void __init devicemaps_init(struct machine_desc *mdesc)
-{
-       struct map_desc map;
-       unsigned long addr;
-       void *vectors;
-
-       /*
-        * Allocate the vector page early.
-        */
-       vectors = alloc_bootmem_low_pages(PAGE_SIZE);
-       BUG_ON(!vectors);
-
-       for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
-               pmd_clear(pmd_off_k(addr));
-
-       /*
-        * Map the kernel if it is XIP.
-        * It is always first in the modulearea.
-        */
-#ifdef CONFIG_XIP_KERNEL
-       map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & PGDIR_MASK);
-       map.virtual = MODULE_START;
-       map.length = ((unsigned long)&_etext - map.virtual + ~PGDIR_MASK) & PGDIR_MASK;
-       map.type = MT_ROM;
-       create_mapping(&map);
-#endif
-
-       /*
-        * Map the cache flushing regions.
-        */
-#ifdef FLUSH_BASE
-       map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
-       map.virtual = FLUSH_BASE;
-       map.length = SZ_1M;
-       map.type = MT_CACHECLEAN;
-       create_mapping(&map);
-#endif
-#ifdef FLUSH_BASE_MINICACHE
-       map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
-       map.virtual = FLUSH_BASE_MINICACHE;
-       map.length = SZ_1M;
-       map.type = MT_MINICLEAN;
-       create_mapping(&map);
-#endif
-
-       /*
-        * Create a mapping for the machine vectors at the high-vectors
-        * location (0xffff0000).  If we aren't using high-vectors, also
-        * create a mapping at the low-vectors virtual address.
-        */
-       map.pfn = __phys_to_pfn(virt_to_phys(vectors));
-       map.virtual = 0xffff0000;
-       map.length = PAGE_SIZE;
-       map.type = MT_HIGH_VECTORS;
-       create_mapping(&map);
-
-       if (!vectors_high()) {
-               map.virtual = 0;
-               map.type = MT_LOW_VECTORS;
-               create_mapping(&map);
-       }
-
-       /*
-        * Ask the machine support to map in the statically mapped devices.
-        */
-       if (mdesc->map_io)
-               mdesc->map_io();
-
-       /*
-        * Finally flush the caches and tlb to ensure that we're in a
-        * consistent state wrt the writebuffer.  This also ensures that
-        * any write-allocated cache lines in the vector page are written
-        * back.  After this point, we can start to touch devices again.
-        */
-       local_flush_tlb_all();
-       flush_cache_all();
-}
-
-/*
- * paging_init() sets up the page tables, initialises the zone memory
- * maps, and sets up the zero page, bad page and bad page tables.
- */
-void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
-{
-       void *zero_page;
-
-       build_mem_type_table();
-       bootmem_init(mi);
-       devicemaps_init(mdesc);
-
-       top_pmd = pmd_off_k(0xffff0000);
-
-       /*
-        * allocate the zero page.  Note that we count on this going ok.
-        */
-       zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
-       memzero(zero_page, PAGE_SIZE);
-       empty_zero_page = virt_to_page(zero_page);
-       flush_dcache_page(empty_zero_page);
-}
-
 static inline void free_area(unsigned long addr, unsigned long end, char *s)
 {
        unsigned int size = (end - addr) >> 10;
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
deleted file mode 100644 (file)
index 38769f5..0000000
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- *  linux/arch/arm/mm/mm-armv.c
- *
- *  Copyright (C) 1998-2005 Russell King
- *
- * 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.
- *
- *  Page table sludge for ARM v3 and v4 processor architectures.
- */
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/nodemask.h>
-
-#include <asm/pgalloc.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/tlbflush.h>
-
-#include <asm/mach/map.h>
-
-#define CPOLICY_UNCACHED       0
-#define CPOLICY_BUFFERED       1
-#define CPOLICY_WRITETHROUGH   2
-#define CPOLICY_WRITEBACK      3
-#define CPOLICY_WRITEALLOC     4
-
-static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
-static unsigned int ecc_mask __initdata = 0;
-pgprot_t pgprot_kernel;
-
-EXPORT_SYMBOL(pgprot_kernel);
-
-pmd_t *top_pmd;
-
-struct cachepolicy {
-       const char      policy[16];
-       unsigned int    cr_mask;
-       unsigned int    pmd;
-       unsigned int    pte;
-};
-
-static struct cachepolicy cache_policies[] __initdata = {
-       {
-               .policy         = "uncached",
-               .cr_mask        = CR_W|CR_C,
-               .pmd            = PMD_SECT_UNCACHED,
-               .pte            = 0,
-       }, {
-               .policy         = "buffered",
-               .cr_mask        = CR_C,
-               .pmd            = PMD_SECT_BUFFERED,
-               .pte            = PTE_BUFFERABLE,
-       }, {
-               .policy         = "writethrough",
-               .cr_mask        = 0,
-               .pmd            = PMD_SECT_WT,
-               .pte            = PTE_CACHEABLE,
-       }, {
-               .policy         = "writeback",
-               .cr_mask        = 0,
-               .pmd            = PMD_SECT_WB,
-               .pte            = PTE_BUFFERABLE|PTE_CACHEABLE,
-       }, {
-               .policy         = "writealloc",
-               .cr_mask        = 0,
-               .pmd            = PMD_SECT_WBWA,
-               .pte            = PTE_BUFFERABLE|PTE_CACHEABLE,
-       }
-};
-
-/*
- * These are useful for identifing cache coherency
- * problems by allowing the cache or the cache and
- * writebuffer to be turned off.  (Note: the write
- * buffer should not be on and the cache off).
- */
-static void __init early_cachepolicy(char **p)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
-               int len = strlen(cache_policies[i].policy);
-
-               if (memcmp(*p, cache_policies[i].policy, len) == 0) {
-                       cachepolicy = i;
-                       cr_alignment &= ~cache_policies[i].cr_mask;
-                       cr_no_alignment &= ~cache_policies[i].cr_mask;
-                       *p += len;
-                       break;
-               }
-       }
-       if (i == ARRAY_SIZE(cache_policies))
-               printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
-       flush_cache_all();
-       set_cr(cr_alignment);
-}
-
-static void __init early_nocache(char **__unused)
-{
-       char *p = "buffered";
-       printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
-       early_cachepolicy(&p);
-}
-
-static void __init early_nowrite(char **__unused)
-{
-       char *p = "uncached";
-       printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
-       early_cachepolicy(&p);
-}
-
-static void __init early_ecc(char **p)
-{
-       if (memcmp(*p, "on", 2) == 0) {
-               ecc_mask = PMD_PROTECTION;
-               *p += 2;
-       } else if (memcmp(*p, "off", 3) == 0) {
-               ecc_mask = 0;
-               *p += 3;
-       }
-}
-
-__early_param("nocache", early_nocache);
-__early_param("nowb", early_nowrite);
-__early_param("cachepolicy=", early_cachepolicy);
-__early_param("ecc=", early_ecc);
-
-static int __init noalign_setup(char *__unused)
-{
-       cr_alignment &= ~CR_A;
-       cr_no_alignment &= ~CR_A;
-       set_cr(cr_alignment);
-       return 1;
-}
-
-__setup("noalign", noalign_setup);
-
-#define FIRST_KERNEL_PGD_NR    (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-
-static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
-{
-       return pmd_offset(pgd, virt);
-}
-
-static inline pmd_t *pmd_off_k(unsigned long virt)
-{
-       return pmd_off(pgd_offset_k(virt), virt);
-}
-
-/*
- * need to get a 16k page for level 1
- */
-pgd_t *get_pgd_slow(struct mm_struct *mm)
-{
-       pgd_t *new_pgd, *init_pgd;
-       pmd_t *new_pmd, *init_pmd;
-       pte_t *new_pte, *init_pte;
-
-       new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
-       if (!new_pgd)
-               goto no_pgd;
-
-       memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
-
-       /*
-        * Copy over the kernel and IO PGD entries
-        */
-       init_pgd = pgd_offset_k(0);
-       memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
-                      (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
-
-       clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
-
-       if (!vectors_high()) {
-               /*
-                * On ARM, first page must always be allocated since it
-                * contains the machine vectors.
-                */
-               new_pmd = pmd_alloc(mm, new_pgd, 0);
-               if (!new_pmd)
-                       goto no_pmd;
-
-               new_pte = pte_alloc_map(mm, new_pmd, 0);
-               if (!new_pte)
-                       goto no_pte;
-
-               init_pmd = pmd_offset(init_pgd, 0);
-               init_pte = pte_offset_map_nested(init_pmd, 0);
-               set_pte(new_pte, *init_pte);
-               pte_unmap_nested(init_pte);
-               pte_unmap(new_pte);
-       }
-
-       return new_pgd;
-
-no_pte:
-       pmd_free(new_pmd);
-no_pmd:
-       free_pages((unsigned long)new_pgd, 2);
-no_pgd:
-       return NULL;
-}
-
-void free_pgd_slow(pgd_t *pgd)
-{
-       pmd_t *pmd;
-       struct page *pte;
-
-       if (!pgd)
-               return;
-
-       /* pgd is always present and good */
-       pmd = pmd_off(pgd, 0);
-       if (pmd_none(*pmd))
-               goto free;
-       if (pmd_bad(*pmd)) {
-               pmd_ERROR(*pmd);
-               pmd_clear(pmd);
-               goto free;
-       }
-
-       pte = pmd_page(*pmd);
-       pmd_clear(pmd);
-       dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
-       pte_lock_deinit(pte);
-       pte_free(pte);
-       pmd_free(pmd);
-free:
-       free_pages((unsigned long) pgd, 2);
-}
-
-/*
- * Create a SECTION PGD between VIRT and PHYS in domain
- * DOMAIN with protection PROT.  This operates on half-
- * pgdir entry increments.
- */
-static inline void
-alloc_init_section(unsigned long virt, unsigned long phys, int prot)
-{
-       pmd_t *pmdp = pmd_off_k(virt);
-
-       if (virt & (1 << 20))
-               pmdp++;
-
-       *pmdp = __pmd(phys | prot);
-       flush_pmd_entry(pmdp);
-}
-
-/*
- * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
- */
-static inline void
-alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
-{
-       int i;
-
-       for (i = 0; i < 16; i += 1) {
-               alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
-
-               virt += (PGDIR_SIZE / 2);
-       }
-}
-
-/*
- * Add a PAGE mapping between VIRT and PHYS in domain
- * DOMAIN with protection PROT.  Note that due to the
- * way we map the PTEs, we must allocate two PTE_SIZE'd
- * blocks - one for the Linux pte table, and one for
- * the hardware pte table.
- */
-static inline void
-alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
-{
-       pmd_t *pmdp = pmd_off_k(virt);
-       pte_t *ptep;
-
-       if (pmd_none(*pmdp)) {
-               ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
-                                              sizeof(pte_t));
-
-               __pmd_populate(pmdp, __pa(ptep) | prot_l1);
-       }
-       ptep = pte_offset_kernel(pmdp, virt);
-
-       set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
-}
-
-struct mem_types {
-       unsigned int    prot_pte;
-       unsigned int    prot_l1;
-       unsigned int    prot_sect;
-       unsigned int    domain;
-};
-
-static struct mem_types mem_types[] __initdata = {
-       [MT_DEVICE] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE,
-               .prot_l1   = PMD_TYPE_TABLE,
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
-                               PMD_SECT_AP_WRITE,
-               .domain    = DOMAIN_IO,
-       },
-       [MT_CACHECLEAN] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4,
-               .domain    = DOMAIN_KERNEL,
-       },
-       [MT_MINICLEAN] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE,
-               .domain    = DOMAIN_KERNEL,
-       },
-       [MT_LOW_VECTORS] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_EXEC,
-               .prot_l1   = PMD_TYPE_TABLE,
-               .domain    = DOMAIN_USER,
-       },
-       [MT_HIGH_VECTORS] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_USER | L_PTE_EXEC,
-               .prot_l1   = PMD_TYPE_TABLE,
-               .domain    = DOMAIN_USER,
-       },
-       [MT_MEMORY] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE,
-               .domain    = DOMAIN_KERNEL,
-       },
-       [MT_ROM] = {
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4,
-               .domain    = DOMAIN_KERNEL,
-       },
-       [MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE,
-               .prot_l1   = PMD_TYPE_TABLE,
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
-                               PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
-                               PMD_SECT_TEX(1),
-               .domain    = DOMAIN_IO,
-       },
-       [MT_NONSHARED_DEVICE] = {
-               .prot_l1   = PMD_TYPE_TABLE,
-               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_NONSHARED_DEV |
-                               PMD_SECT_AP_WRITE,
-               .domain    = DOMAIN_IO,
-       }
-};
-
-/*
- * Adjust the PMD section entries according to the CPU in use.
- */
-void __init build_mem_type_table(void)
-{
-       struct cachepolicy *cp;
-       unsigned int cr = get_cr();
-       unsigned int user_pgprot, kern_pgprot;
-       int cpu_arch = cpu_architecture();
-       int i;
-
-#if defined(CONFIG_CPU_DCACHE_DISABLE)
-       if (cachepolicy > CPOLICY_BUFFERED)
-               cachepolicy = CPOLICY_BUFFERED;
-#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
-       if (cachepolicy > CPOLICY_WRITETHROUGH)
-               cachepolicy = CPOLICY_WRITETHROUGH;
-#endif
-       if (cpu_arch < CPU_ARCH_ARMv5) {
-               if (cachepolicy >= CPOLICY_WRITEALLOC)
-                       cachepolicy = CPOLICY_WRITEBACK;
-               ecc_mask = 0;
-       }
-
-       /*
-        * Xscale must not have PMD bit 4 set for section mappings.
-        */
-       if (cpu_is_xscale())
-               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
-                       mem_types[i].prot_sect &= ~PMD_BIT4;
-
-       /*
-        * ARMv5 and lower, excluding Xscale, bit 4 must be set for
-        * page tables.
-        */
-       if (cpu_arch < CPU_ARCH_ARMv6 && !cpu_is_xscale())
-               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
-                       if (mem_types[i].prot_l1)
-                               mem_types[i].prot_l1 |= PMD_BIT4;
-
-       cp = &cache_policies[cachepolicy];
-       kern_pgprot = user_pgprot = cp->pte;
-
-       /*
-        * Enable CPU-specific coherency if supported.
-        * (Only available on XSC3 at the moment.)
-        */
-       if (arch_is_coherent()) {
-               if (cpu_is_xsc3()) {
-                       mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-                       mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
-               }
-       }
-
-       /*
-        * ARMv6 and above have extended page tables.
-        */
-       if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
-               /*
-                * bit 4 becomes XN which we must clear for the
-                * kernel memory mapping.
-                */
-               mem_types[MT_MEMORY].prot_sect &= ~PMD_SECT_XN;
-               mem_types[MT_ROM].prot_sect &= ~PMD_SECT_XN;
-
-               /*
-                * Mark cache clean areas and XIP ROM read only
-                * from SVC mode and no access from userspace.
-                */
-               mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-               mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-               mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-
-               /*
-                * Mark the device area as "shared device"
-                */
-               mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
-               mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
-
-               /*
-                * User pages need to be mapped with the ASID
-                * (iow, non-global)
-                */
-               user_pgprot |= L_PTE_ASID;
-
-#ifdef CONFIG_SMP
-               /*
-                * Mark memory with the "shared" attribute for SMP systems
-                */
-               user_pgprot |= L_PTE_SHARED;
-               kern_pgprot |= L_PTE_SHARED;
-               mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-#endif
-       }
-
-       for (i = 0; i < 16; i++) {
-               unsigned long v = pgprot_val(protection_map[i]);
-               v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
-               protection_map[i] = __pgprot(v);
-       }
-
-       mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
-       mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
-
-       if (cpu_arch >= CPU_ARCH_ARMv5) {
-#ifndef CONFIG_SMP
-               /*
-                * Only use write-through for non-SMP systems
-                */
-               mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
-               mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
-#endif
-       } else {
-               mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
-       }
-
-       pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
-                                L_PTE_DIRTY | L_PTE_WRITE |
-                                L_PTE_EXEC | kern_pgprot);
-
-       mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
-       mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
-       mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
-       mem_types[MT_ROM].prot_sect |= cp->pmd;
-
-       switch (cp->pmd) {
-       case PMD_SECT_WT:
-               mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
-               break;
-       case PMD_SECT_WB:
-       case PMD_SECT_WBWA:
-               mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
-               break;
-       }
-       printk("Memory policy: ECC %sabled, Data cache %s\n",
-               ecc_mask ? "en" : "dis", cp->policy);
-}
-
-#define vectors_base() (vectors_high() ? 0xffff0000 : 0)
-
-/*
- * Create the page directory entries and any necessary
- * page tables for the mapping specified by `md'.  We
- * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections and
- * supersections.
- */
-void __init create_mapping(struct map_desc *md)
-{
-       unsigned long virt, length;
-       int prot_sect, prot_l1, domain;
-       pgprot_t prot_pte;
-       unsigned long off = (u32)__pfn_to_phys(md->pfn);
-
-       if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
-               printk(KERN_WARNING "BUG: not creating mapping for "
-                      "0x%08llx at 0x%08lx in user region\n",
-                      __pfn_to_phys((u64)md->pfn), md->virtual);
-               return;
-       }
-
-       if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
-           md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
-               printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
-                      "overlaps vmalloc space\n",
-                      __pfn_to_phys((u64)md->pfn), md->virtual);
-       }
-
-       domain    = mem_types[md->type].domain;
-       prot_pte  = __pgprot(mem_types[md->type].prot_pte);
-       prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
-       prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
-
-       /*
-        * Catch 36-bit addresses
-        */
-       if(md->pfn >= 0x100000) {
-               if(domain) {
-                       printk(KERN_ERR "MM: invalid domain in supersection "
-                               "mapping for 0x%08llx at 0x%08lx\n",
-                               __pfn_to_phys((u64)md->pfn), md->virtual);
-                       return;
-               }
-               if((md->virtual | md->length | __pfn_to_phys(md->pfn))
-                       & ~SUPERSECTION_MASK) {
-                       printk(KERN_ERR "MM: cannot create mapping for "
-                               "0x%08llx at 0x%08lx invalid alignment\n",
-                               __pfn_to_phys((u64)md->pfn), md->virtual);
-                       return;
-               }
-
-               /*
-                * Shift bits [35:32] of address into bits [23:20] of PMD
-                * (See ARMv6 spec).
-                */
-               off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
-       }
-
-       virt   = md->virtual;
-       off   -= virt;
-       length = md->length;
-
-       if (mem_types[md->type].prot_l1 == 0 &&
-           (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
-               printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
-                      "be mapped using pages, ignoring.\n",
-                      __pfn_to_phys(md->pfn), md->virtual);
-               return;
-       }
-
-       while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
-               alloc_init_page(virt, virt + off, prot_l1, prot_pte);
-
-               virt   += PAGE_SIZE;
-               length -= PAGE_SIZE;
-       }
-
-       /* N.B. ARMv6 supersections are only defined to work with domain 0.
-        *      Since domain assignments can in fact be arbitrary, the
-        *      'domain == 0' check below is required to insure that ARMv6
-        *      supersections are only allocated for domain 0 regardless
-        *      of the actual domain assignments in use.
-        */
-       if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
-               && domain == 0) {
-               /*
-                * Align to supersection boundary if !high pages.
-                * High pages have already been checked for proper
-                * alignment above and they will fail the SUPSERSECTION_MASK
-                * check because of the way the address is encoded into
-                * offset.
-                */
-               if (md->pfn <= 0x100000) {
-                       while ((virt & ~SUPERSECTION_MASK ||
-                               (virt + off) & ~SUPERSECTION_MASK) &&
-                               length >= (PGDIR_SIZE / 2)) {
-                               alloc_init_section(virt, virt + off, prot_sect);
-
-                               virt   += (PGDIR_SIZE / 2);
-                               length -= (PGDIR_SIZE / 2);
-                       }
-               }
-
-               while (length >= SUPERSECTION_SIZE) {
-                       alloc_init_supersection(virt, virt + off, prot_sect);
-
-                       virt   += SUPERSECTION_SIZE;
-                       length -= SUPERSECTION_SIZE;
-               }
-       }
-
-       /*
-        * A section mapping covers half a "pgdir" entry.
-        */
-       while (length >= (PGDIR_SIZE / 2)) {
-               alloc_init_section(virt, virt + off, prot_sect);
-
-               virt   += (PGDIR_SIZE / 2);
-               length -= (PGDIR_SIZE / 2);
-       }
-
-       while (length >= PAGE_SIZE) {
-               alloc_init_page(virt, virt + off, prot_l1, prot_pte);
-
-               virt   += PAGE_SIZE;
-               length -= PAGE_SIZE;
-       }
-}
-
-/*
- * In order to soft-boot, we need to insert a 1:1 mapping in place of
- * the user-mode pages.  This will then ensure that we have predictable
- * results when turning the mmu off
- */
-void setup_mm_for_reboot(char mode)
-{
-       unsigned long base_pmdval;
-       pgd_t *pgd;
-       int i;
-
-       if (current->mm && current->mm->pgd)
-               pgd = current->mm->pgd;
-       else
-               pgd = init_mm.pgd;
-
-       base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
-       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
-               base_pmdval |= PMD_BIT4;
-
-       for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
-               unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
-               pmd_t *pmd;
-
-               pmd = pmd_off(pgd, i << PGDIR_SHIFT);
-               pmd[0] = __pmd(pmdval);
-               pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
-               flush_pmd_entry(pmd);
-       }
-}
-
-/*
- * Create the architecture specific mappings
- */
-void __init iotable_init(struct map_desc *io_desc, int nr)
-{
-       int i;
-
-       for (i = 0; i < nr; i++)
-               create_mapping(io_desc + i);
-}
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
new file mode 100644 (file)
index 0000000..bb2bc9a
--- /dev/null
@@ -0,0 +1,22 @@
+/* the upper-most page table pointer */
+extern pmd_t *top_pmd;
+
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+       return pmd_offset(pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+       return pmd_off(pgd_offset_k(virt), virt);
+}
+
+struct map_desc;
+struct meminfo;
+struct pglist_data;
+
+void __init create_mapping(struct map_desc *md);
+void __init bootmem_init(struct meminfo *mi);
+void reserve_node_zero(struct pglist_data *pgdat);
index 29e54807c5bc6a1a0e010495aad34b9fd60346f2..b0b5f46940705431a468efb6681a7636e40e988e 100644 (file)
@@ -114,3 +114,25 @@ full_search:
        }
 }
 
+
+/*
+ * You really shouldn't be using read() or write() on /dev/mem.  This
+ * might go away in the future.
+ */
+int valid_phys_addr_range(unsigned long addr, size_t size)
+{
+       if (addr + size > __pa(high_memory))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * We don't use supersection mappings for mmap() on /dev/mem, which
+ * means that we can't map the memory area above the 4G barrier into
+ * userspace.
+ */
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+{
+       return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
+}
index 0d90227a0a32e0d7365591d2f402c26ff1de894e..e566cbe4b222cd93186d6d06dd7b279fbbae4563 100644 (file)
 /*
  *  linux/arch/arm/mm/mmu.c
  *
- *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ *  Copyright (C) 1995-2005 Russell King
  *
  * 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/kernel.h>
+#include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
 
-#include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
 
-unsigned int cpu_last_asid = { 1 << ASID_BITS };
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "mm.h"
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+extern void _stext, __data_start, _end;
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/*
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
+ */
+struct page *empty_zero_page;
 
 /*
- * We fork()ed a process, and we need a new context for the child
- * to run in.  We reserve version 0 for initial tasks so we will
- * always allocate an ASID.
+ * The pmd table for the upper-most set of pages.
  */
-void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+pmd_t *top_pmd;
+
+#define CPOLICY_UNCACHED       0
+#define CPOLICY_BUFFERED       1
+#define CPOLICY_WRITETHROUGH   2
+#define CPOLICY_WRITEBACK      3
+#define CPOLICY_WRITEALLOC     4
+
+static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
+static unsigned int ecc_mask __initdata = 0;
+pgprot_t pgprot_kernel;
+
+EXPORT_SYMBOL(pgprot_kernel);
+
+struct cachepolicy {
+       const char      policy[16];
+       unsigned int    cr_mask;
+       unsigned int    pmd;
+       unsigned int    pte;
+};
+
+static struct cachepolicy cache_policies[] __initdata = {
+       {
+               .policy         = "uncached",
+               .cr_mask        = CR_W|CR_C,
+               .pmd            = PMD_SECT_UNCACHED,
+               .pte            = 0,
+       }, {
+               .policy         = "buffered",
+               .cr_mask        = CR_C,
+               .pmd            = PMD_SECT_BUFFERED,
+               .pte            = PTE_BUFFERABLE,
+       }, {
+               .policy         = "writethrough",
+               .cr_mask        = 0,
+               .pmd            = PMD_SECT_WT,
+               .pte            = PTE_CACHEABLE,
+       }, {
+               .policy         = "writeback",
+               .cr_mask        = 0,
+               .pmd            = PMD_SECT_WB,
+               .pte            = PTE_BUFFERABLE|PTE_CACHEABLE,
+       }, {
+               .policy         = "writealloc",
+               .cr_mask        = 0,
+               .pmd            = PMD_SECT_WBWA,
+               .pte            = PTE_BUFFERABLE|PTE_CACHEABLE,
+       }
+};
+
+/*
+ * These are useful for identifing cache coherency
+ * problems by allowing the cache or the cache and
+ * writebuffer to be turned off.  (Note: the write
+ * buffer should not be on and the cache off).
+ */
+static void __init early_cachepolicy(char **p)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
+               int len = strlen(cache_policies[i].policy);
+
+               if (memcmp(*p, cache_policies[i].policy, len) == 0) {
+                       cachepolicy = i;
+                       cr_alignment &= ~cache_policies[i].cr_mask;
+                       cr_no_alignment &= ~cache_policies[i].cr_mask;
+                       *p += len;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(cache_policies))
+               printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
+       flush_cache_all();
+       set_cr(cr_alignment);
+}
+__early_param("cachepolicy=", early_cachepolicy);
+
+static void __init early_nocache(char **__unused)
+{
+       char *p = "buffered";
+       printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
+       early_cachepolicy(&p);
+}
+__early_param("nocache", early_nocache);
+
+static void __init early_nowrite(char **__unused)
+{
+       char *p = "uncached";
+       printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
+       early_cachepolicy(&p);
+}
+__early_param("nowb", early_nowrite);
+
+static void __init early_ecc(char **p)
+{
+       if (memcmp(*p, "on", 2) == 0) {
+               ecc_mask = PMD_PROTECTION;
+               *p += 2;
+       } else if (memcmp(*p, "off", 3) == 0) {
+               ecc_mask = 0;
+               *p += 3;
+       }
+}
+__early_param("ecc=", early_ecc);
+
+static int __init noalign_setup(char *__unused)
 {
-       mm->context.id = 0;
+       cr_alignment &= ~CR_A;
+       cr_no_alignment &= ~CR_A;
+       set_cr(cr_alignment);
+       return 1;
 }
+__setup("noalign", noalign_setup);
+
+struct mem_types {
+       unsigned int    prot_pte;
+       unsigned int    prot_l1;
+       unsigned int    prot_sect;
+       unsigned int    domain;
+};
 
-void __new_context(struct mm_struct *mm)
+static struct mem_types mem_types[] __initdata = {
+       [MT_DEVICE] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_WRITE,
+               .prot_l1   = PMD_TYPE_TABLE,
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
+                               PMD_SECT_AP_WRITE,
+               .domain    = DOMAIN_IO,
+       },
+       [MT_CACHECLEAN] = {
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4,
+               .domain    = DOMAIN_KERNEL,
+       },
+       [MT_MINICLEAN] = {
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE,
+               .domain    = DOMAIN_KERNEL,
+       },
+       [MT_LOW_VECTORS] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_EXEC,
+               .prot_l1   = PMD_TYPE_TABLE,
+               .domain    = DOMAIN_USER,
+       },
+       [MT_HIGH_VECTORS] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_USER | L_PTE_EXEC,
+               .prot_l1   = PMD_TYPE_TABLE,
+               .domain    = DOMAIN_USER,
+       },
+       [MT_MEMORY] = {
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE,
+               .domain    = DOMAIN_KERNEL,
+       },
+       [MT_ROM] = {
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4,
+               .domain    = DOMAIN_KERNEL,
+       },
+       [MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_WRITE,
+               .prot_l1   = PMD_TYPE_TABLE,
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED |
+                               PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
+                               PMD_SECT_TEX(1),
+               .domain    = DOMAIN_IO,
+       },
+       [MT_NONSHARED_DEVICE] = {
+               .prot_l1   = PMD_TYPE_TABLE,
+               .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_NONSHARED_DEV |
+                               PMD_SECT_AP_WRITE,
+               .domain    = DOMAIN_IO,
+       }
+};
+
+/*
+ * Adjust the PMD section entries according to the CPU in use.
+ */
+static void __init build_mem_type_table(void)
 {
-       unsigned int asid;
+       struct cachepolicy *cp;
+       unsigned int cr = get_cr();
+       unsigned int user_pgprot, kern_pgprot;
+       int cpu_arch = cpu_architecture();
+       int i;
 
-       asid = ++cpu_last_asid;
-       if (asid == 0)
-               asid = cpu_last_asid = 1 << ASID_BITS;
+#if defined(CONFIG_CPU_DCACHE_DISABLE)
+       if (cachepolicy > CPOLICY_BUFFERED)
+               cachepolicy = CPOLICY_BUFFERED;
+#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
+       if (cachepolicy > CPOLICY_WRITETHROUGH)
+               cachepolicy = CPOLICY_WRITETHROUGH;
+#endif
+       if (cpu_arch < CPU_ARCH_ARMv5) {
+               if (cachepolicy >= CPOLICY_WRITEALLOC)
+                       cachepolicy = CPOLICY_WRITEBACK;
+               ecc_mask = 0;
+       }
+
+       /*
+        * Xscale must not have PMD bit 4 set for section mappings.
+        */
+       if (cpu_is_xscale())
+               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+                       mem_types[i].prot_sect &= ~PMD_BIT4;
 
        /*
-        * If we've used up all our ASIDs, we need
-        * to start a new version and flush the TLB.
+        * ARMv5 and lower, excluding Xscale, bit 4 must be set for
+        * page tables.
         */
-       if ((asid & ~ASID_MASK) == 0)
-               flush_tlb_all();
+       if (cpu_arch < CPU_ARCH_ARMv6 && !cpu_is_xscale())
+               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+                       if (mem_types[i].prot_l1)
+                               mem_types[i].prot_l1 |= PMD_BIT4;
+
+       cp = &cache_policies[cachepolicy];
+       kern_pgprot = user_pgprot = cp->pte;
+
+       /*
+        * Enable CPU-specific coherency if supported.
+        * (Only available on XSC3 at the moment.)
+        */
+       if (arch_is_coherent()) {
+               if (cpu_is_xsc3()) {
+                       mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+               }
+       }
+
+       /*
+        * ARMv6 and above have extended page tables.
+        */
+       if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
+               /*
+                * bit 4 becomes XN which we must clear for the
+                * kernel memory mapping.
+                */
+               mem_types[MT_MEMORY].prot_sect &= ~PMD_SECT_XN;
+               mem_types[MT_ROM].prot_sect &= ~PMD_SECT_XN;
+
+               /*
+                * Mark cache clean areas and XIP ROM read only
+                * from SVC mode and no access from userspace.
+                */
+               mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+               mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+               mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+
+               /*
+                * Mark the device area as "shared device"
+                */
+               mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
+               mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
+
+               /*
+                * User pages need to be mapped with the ASID
+                * (iow, non-global)
+                */
+               user_pgprot |= L_PTE_ASID;
+
+#ifdef CONFIG_SMP
+               /*
+                * Mark memory with the "shared" attribute for SMP systems
+                */
+               user_pgprot |= L_PTE_SHARED;
+               kern_pgprot |= L_PTE_SHARED;
+               mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+#endif
+       }
+
+       for (i = 0; i < 16; i++) {
+               unsigned long v = pgprot_val(protection_map[i]);
+               v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
+               protection_map[i] = __pgprot(v);
+       }
+
+       mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
+       mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
+
+       if (cpu_arch >= CPU_ARCH_ARMv5) {
+#ifndef CONFIG_SMP
+               /*
+                * Only use write-through for non-SMP systems
+                */
+               mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
+               mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
+#endif
+       } else {
+               mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
+       }
+
+       pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
+                                L_PTE_DIRTY | L_PTE_WRITE |
+                                L_PTE_EXEC | kern_pgprot);
+
+       mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
+       mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
+       mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
+       mem_types[MT_ROM].prot_sect |= cp->pmd;
+
+       switch (cp->pmd) {
+       case PMD_SECT_WT:
+               mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
+               break;
+       case PMD_SECT_WB:
+       case PMD_SECT_WBWA:
+               mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
+               break;
+       }
+       printk("Memory policy: ECC %sabled, Data cache %s\n",
+               ecc_mask ? "en" : "dis", cp->policy);
+}
+
+#define vectors_base() (vectors_high() ? 0xffff0000 : 0)
+
+/*
+ * Create a SECTION PGD between VIRT and PHYS in domain
+ * DOMAIN with protection PROT.  This operates on half-
+ * pgdir entry increments.
+ */
+static inline void
+alloc_init_section(unsigned long virt, unsigned long phys, int prot)
+{
+       pmd_t *pmdp = pmd_off_k(virt);
+
+       if (virt & (1 << 20))
+               pmdp++;
+
+       *pmdp = __pmd(phys | prot);
+       flush_pmd_entry(pmdp);
+}
+
+/*
+ * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
+ */
+static inline void
+alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
+{
+       int i;
+
+       for (i = 0; i < 16; i += 1) {
+               alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
+
+               virt += (PGDIR_SIZE / 2);
+       }
+}
+
+/*
+ * Add a PAGE mapping between VIRT and PHYS in domain
+ * DOMAIN with protection PROT.  Note that due to the
+ * way we map the PTEs, we must allocate two PTE_SIZE'd
+ * blocks - one for the Linux pte table, and one for
+ * the hardware pte table.
+ */
+static inline void
+alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
+{
+       pmd_t *pmdp = pmd_off_k(virt);
+       pte_t *ptep;
+
+       if (pmd_none(*pmdp)) {
+               ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
+                                              sizeof(pte_t));
+
+               __pmd_populate(pmdp, __pa(ptep) | prot_l1);
+       }
+       ptep = pte_offset_kernel(pmdp, virt);
+
+       set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
+}
+
+/*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections and
+ * supersections.
+ */
+void __init create_mapping(struct map_desc *md)
+{
+       unsigned long virt, length;
+       int prot_sect, prot_l1, domain;
+       pgprot_t prot_pte;
+       unsigned long off = (u32)__pfn_to_phys(md->pfn);
+
+       if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+               printk(KERN_WARNING "BUG: not creating mapping for "
+                      "0x%08llx at 0x%08lx in user region\n",
+                      __pfn_to_phys((u64)md->pfn), md->virtual);
+               return;
+       }
+
+       if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+           md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
+               printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
+                      "overlaps vmalloc space\n",
+                      __pfn_to_phys((u64)md->pfn), md->virtual);
+       }
+
+       domain    = mem_types[md->type].domain;
+       prot_pte  = __pgprot(mem_types[md->type].prot_pte);
+       prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
+       prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
+
+       /*
+        * Catch 36-bit addresses
+        */
+       if(md->pfn >= 0x100000) {
+               if(domain) {
+                       printk(KERN_ERR "MM: invalid domain in supersection "
+                               "mapping for 0x%08llx at 0x%08lx\n",
+                               __pfn_to_phys((u64)md->pfn), md->virtual);
+                       return;
+               }
+               if((md->virtual | md->length | __pfn_to_phys(md->pfn))
+                       & ~SUPERSECTION_MASK) {
+                       printk(KERN_ERR "MM: cannot create mapping for "
+                               "0x%08llx at 0x%08lx invalid alignment\n",
+                               __pfn_to_phys((u64)md->pfn), md->virtual);
+                       return;
+               }
+
+               /*
+                * Shift bits [35:32] of address into bits [23:20] of PMD
+                * (See ARMv6 spec).
+                */
+               off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
+       }
+
+       virt   = md->virtual;
+       off   -= virt;
+       length = md->length;
+
+       if (mem_types[md->type].prot_l1 == 0 &&
+           (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
+               printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
+                      "be mapped using pages, ignoring.\n",
+                      __pfn_to_phys(md->pfn), md->virtual);
+               return;
+       }
+
+       while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
+               alloc_init_page(virt, virt + off, prot_l1, prot_pte);
+
+               virt   += PAGE_SIZE;
+               length -= PAGE_SIZE;
+       }
+
+       /* N.B. ARMv6 supersections are only defined to work with domain 0.
+        *      Since domain assignments can in fact be arbitrary, the
+        *      'domain == 0' check below is required to insure that ARMv6
+        *      supersections are only allocated for domain 0 regardless
+        *      of the actual domain assignments in use.
+        */
+       if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
+               && domain == 0) {
+               /*
+                * Align to supersection boundary if !high pages.
+                * High pages have already been checked for proper
+                * alignment above and they will fail the SUPSERSECTION_MASK
+                * check because of the way the address is encoded into
+                * offset.
+                */
+               if (md->pfn <= 0x100000) {
+                       while ((virt & ~SUPERSECTION_MASK ||
+                               (virt + off) & ~SUPERSECTION_MASK) &&
+                               length >= (PGDIR_SIZE / 2)) {
+                               alloc_init_section(virt, virt + off, prot_sect);
+
+                               virt   += (PGDIR_SIZE / 2);
+                               length -= (PGDIR_SIZE / 2);
+                       }
+               }
+
+               while (length >= SUPERSECTION_SIZE) {
+                       alloc_init_supersection(virt, virt + off, prot_sect);
+
+                       virt   += SUPERSECTION_SIZE;
+                       length -= SUPERSECTION_SIZE;
+               }
+       }
+
+       /*
+        * A section mapping covers half a "pgdir" entry.
+        */
+       while (length >= (PGDIR_SIZE / 2)) {
+               alloc_init_section(virt, virt + off, prot_sect);
+
+               virt   += (PGDIR_SIZE / 2);
+               length -= (PGDIR_SIZE / 2);
+       }
+
+       while (length >= PAGE_SIZE) {
+               alloc_init_page(virt, virt + off, prot_l1, prot_pte);
+
+               virt   += PAGE_SIZE;
+               length -= PAGE_SIZE;
+       }
+}
+
+/*
+ * Create the architecture specific mappings
+ */
+void __init iotable_init(struct map_desc *io_desc, int nr)
+{
+       int i;
+
+       for (i = 0; i < nr; i++)
+               create_mapping(io_desc + i);
+}
+
+static inline void prepare_page_table(struct meminfo *mi)
+{
+       unsigned long addr;
+
+       /*
+        * Clear out all the mappings below the kernel image.
+        */
+       for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE)
+               pmd_clear(pmd_off_k(addr));
+
+#ifdef CONFIG_XIP_KERNEL
+       /* The XIP kernel is mapped in the module area -- skip over it */
+       addr = ((unsigned long)&_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
+#endif
+       for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+               pmd_clear(pmd_off_k(addr));
+
+       /*
+        * Clear out all the kernel space mappings, except for the first
+        * memory bank, up to the end of the vmalloc region.
+        */
+       for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size);
+            addr < VMALLOC_END; addr += PGDIR_SIZE)
+               pmd_clear(pmd_off_k(addr));
+}
+
+/*
+ * Reserve the various regions of node 0
+ */
+void __init reserve_node_zero(pg_data_t *pgdat)
+{
+       unsigned long res_size = 0;
+
+       /*
+        * Register the kernel text and data with bootmem.
+        * Note that this can only be in node 0.
+        */
+#ifdef CONFIG_XIP_KERNEL
+       reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
+#else
+       reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+#endif
+
+       /*
+        * Reserve the page tables.  These are already in use,
+        * and can only be in node 0.
+        */
+       reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
+                            PTRS_PER_PGD * sizeof(pgd_t));
+
+       /*
+        * Hmm... This should go elsewhere, but we really really need to
+        * stop things allocating the low memory; ideally we need a better
+        * implementation of GFP_DMA which does not assume that DMA-able
+        * memory starts at zero.
+        */
+       if (machine_is_integrator() || machine_is_cintegrator())
+               res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+
+       /*
+        * These should likewise go elsewhere.  They pre-reserve the
+        * screen memory region at the start of main system memory.
+        */
+       if (machine_is_edb7211())
+               res_size = 0x00020000;
+       if (machine_is_p720t())
+               res_size = 0x00014000;
+
+#ifdef CONFIG_SA1111
+       /*
+        * Because of the SA1111 DMA bug, we want to preserve our
+        * precious DMA-able memory...
+        */
+       res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+#endif
+       if (res_size)
+               reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size);
+}
+
+/*
+ * Set up device the mappings.  Since we clear out the page tables for all
+ * mappings above VMALLOC_END, we will remove any debug device mappings.
+ * This means you have to be careful how you debug this function, or any
+ * called function.  This means you can't use any function or debugging
+ * method which may touch any device, otherwise the kernel _will_ crash.
+ */
+static void __init devicemaps_init(struct machine_desc *mdesc)
+{
+       struct map_desc map;
+       unsigned long addr;
+       void *vectors;
+
+       /*
+        * Allocate the vector page early.
+        */
+       vectors = alloc_bootmem_low_pages(PAGE_SIZE);
+       BUG_ON(!vectors);
+
+       for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+               pmd_clear(pmd_off_k(addr));
+
+       /*
+        * Map the kernel if it is XIP.
+        * It is always first in the modulearea.
+        */
+#ifdef CONFIG_XIP_KERNEL
+       map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
+       map.virtual = MODULE_START;
+       map.length = ((unsigned long)&_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK;
+       map.type = MT_ROM;
+       create_mapping(&map);
+#endif
+
+       /*
+        * Map the cache flushing regions.
+        */
+#ifdef FLUSH_BASE
+       map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
+       map.virtual = FLUSH_BASE;
+       map.length = SZ_1M;
+       map.type = MT_CACHECLEAN;
+       create_mapping(&map);
+#endif
+#ifdef FLUSH_BASE_MINICACHE
+       map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
+       map.virtual = FLUSH_BASE_MINICACHE;
+       map.length = SZ_1M;
+       map.type = MT_MINICLEAN;
+       create_mapping(&map);
+#endif
+
+       /*
+        * Create a mapping for the machine vectors at the high-vectors
+        * location (0xffff0000).  If we aren't using high-vectors, also
+        * create a mapping at the low-vectors virtual address.
+        */
+       map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+       map.virtual = 0xffff0000;
+       map.length = PAGE_SIZE;
+       map.type = MT_HIGH_VECTORS;
+       create_mapping(&map);
+
+       if (!vectors_high()) {
+               map.virtual = 0;
+               map.type = MT_LOW_VECTORS;
+               create_mapping(&map);
+       }
+
+       /*
+        * Ask the machine support to map in the statically mapped devices.
+        */
+       if (mdesc->map_io)
+               mdesc->map_io();
+
+       /*
+        * Finally flush the caches and tlb to ensure that we're in a
+        * consistent state wrt the writebuffer.  This also ensures that
+        * any write-allocated cache lines in the vector page are written
+        * back.  After this point, we can start to touch devices again.
+        */
+       local_flush_tlb_all();
+       flush_cache_all();
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
+{
+       void *zero_page;
+
+       build_mem_type_table();
+       prepare_page_table(mi);
+       bootmem_init(mi);
+       devicemaps_init(mdesc);
+
+       top_pmd = pmd_off_k(0xffff0000);
+
+       /*
+        * allocate the zero page.  Note that we count on this going ok.
+        */
+       zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
+       memzero(zero_page, PAGE_SIZE);
+       empty_zero_page = virt_to_page(zero_page);
+       flush_dcache_page(empty_zero_page);
+}
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+       unsigned long base_pmdval;
+       pgd_t *pgd;
+       int i;
+
+       if (current->mm && current->mm->pgd)
+               pgd = current->mm->pgd;
+       else
+               pgd = init_mm.pgd;
+
+       base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
+       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+               base_pmdval |= PMD_BIT4;
+
+       for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
+               unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
+               pmd_t *pmd;
 
-       mm->context.id = asid;
+               pmd = pmd_off(pgd, i << PGDIR_SHIFT);
+               pmd[0] = __pmd(pmdval);
+               pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+               flush_pmd_entry(pmd);
+       }
 }
index 1464ed817b5dc87b1d456a898bf66c8bc9b4007f..d0e66424a59720886d81908643ba1431afdd609e 100644 (file)
 #include <asm/io.h>
 #include <asm/page.h>
 
+#include "mm.h"
+
+extern void _stext, __data_start, _end;
+
+/*
+ * Reserve the various regions of node 0
+ */
+void __init reserve_node_zero(pg_data_t *pgdat)
+{
+       /*
+        * Register the kernel text and data with bootmem.
+        * Note that this can only be in node 0.
+        */
+#ifdef CONFIG_XIP_KERNEL
+       reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
+#else
+       reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+#endif
+
+       /*
+        * Register the exception vector page.
+        * some architectures which the DRAM is the exception vector to trap,
+        * alloc_page breaks with error, although it is not NULL, but "0."
+        */
+       reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE);
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
+{
+       bootmem_init(mi);
+}
+
+/*
+ * We don't need to do anything here for nommu machines.
+ */
+void setup_mm_for_reboot(char mode)
+{
+}
+
 void flush_dcache_page(struct page *page)
 {
        __cpuc_flush_dcache_page(page_address(page));
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
new file mode 100644 (file)
index 0000000..20c1b0d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  linux/arch/arm/mm/pgd.c
+ *
+ *  Copyright (C) 1998-2005 Russell King
+ *
+ * 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/mm.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+
+#include "mm.h"
+
+#define FIRST_KERNEL_PGD_NR    (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
+
+/*
+ * need to get a 16k page for level 1
+ */
+pgd_t *get_pgd_slow(struct mm_struct *mm)
+{
+       pgd_t *new_pgd, *init_pgd;
+       pmd_t *new_pmd, *init_pmd;
+       pte_t *new_pte, *init_pte;
+
+       new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
+       if (!new_pgd)
+               goto no_pgd;
+
+       memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+
+       /*
+        * Copy over the kernel and IO PGD entries
+        */
+       init_pgd = pgd_offset_k(0);
+       memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+                      (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+
+       clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+
+       if (!vectors_high()) {
+               /*
+                * On ARM, first page must always be allocated since it
+                * contains the machine vectors.
+                */
+               new_pmd = pmd_alloc(mm, new_pgd, 0);
+               if (!new_pmd)
+                       goto no_pmd;
+
+               new_pte = pte_alloc_map(mm, new_pmd, 0);
+               if (!new_pte)
+                       goto no_pte;
+
+               init_pmd = pmd_offset(init_pgd, 0);
+               init_pte = pte_offset_map_nested(init_pmd, 0);
+               set_pte(new_pte, *init_pte);
+               pte_unmap_nested(init_pte);
+               pte_unmap(new_pte);
+       }
+
+       return new_pgd;
+
+no_pte:
+       pmd_free(new_pmd);
+no_pmd:
+       free_pages((unsigned long)new_pgd, 2);
+no_pgd:
+       return NULL;
+}
+
+void free_pgd_slow(pgd_t *pgd)
+{
+       pmd_t *pmd;
+       struct page *pte;
+
+       if (!pgd)
+               return;
+
+       /* pgd is always present and good */
+       pmd = pmd_off(pgd, 0);
+       if (pmd_none(*pmd))
+               goto free;
+       if (pmd_bad(*pmd)) {
+               pmd_ERROR(*pmd);
+               pmd_clear(pmd);
+               goto free;
+       }
+
+       pte = pmd_page(*pmd);
+       pmd_clear(pmd);
+       dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
+       pte_lock_deinit(pte);
+       pte_free(pte);
+       pmd_free(pmd);
+free:
+       free_pages((unsigned long) pgd, 2);
+}
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
new file mode 100644 (file)
index 0000000..4071381
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *  linux/arch/arm/mm/arm740.S: utility functions for ARM740
+ *
+ *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@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.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+       .text
+/*
+ * cpu_arm740_proc_init()
+ * cpu_arm740_do_idle()
+ * cpu_arm740_dcache_clean_area()
+ * cpu_arm740_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm740_proc_init)
+ENTRY(cpu_arm740_do_idle)
+ENTRY(cpu_arm740_dcache_clean_area)
+ENTRY(cpu_arm740_switch_mm)
+       mov     pc, lr
+
+/*
+ * cpu_arm740_proc_fin()
+ */
+ENTRY(cpu_arm740_proc_fin)
+       stmfd   sp!, {lr}
+       mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+       msr     cpsr_c, ip
+       mrc     p15, 0, r0, c1, c0, 0
+       bic     r0, r0, #0x3f000000             @ bank/f/lock/s
+       bic     r0, r0, #0x0000000c             @ w-buffer/cache
+       mcr     p15, 0, r0, c1, c0, 0           @ disable caches
+       mcr     p15, 0, r0, c7, c0, 0           @ invalidate cache
+       ldmfd   sp!, {pc}
+
+/*
+ * cpu_arm740_reset(loc)
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm740_reset)
+       mov     ip, #0
+       mcr     p15, 0, ip, c7, c0, 0           @ invalidate cache
+       mrc     p15, 0, ip, c1, c0, 0           @ get ctrl register
+       bic     ip, ip, #0x0000000c             @ ............wc..
+       mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
+       mov     pc, r0
+
+       __INIT
+
+       .type   __arm740_setup, #function
+__arm740_setup:
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c0, 0           @ invalidate caches
+
+       mcr     p15, 0, r0, c6, c3              @ disable area 3~7
+       mcr     p15, 0, r0, c6, c4
+       mcr     p15, 0, r0, c6, c5
+       mcr     p15, 0, r0, c6, c6
+       mcr     p15, 0, r0, c6, c7
+
+       mov     r0, #0x0000003F                 @ base = 0, size = 4GB
+       mcr     p15, 0, r0, c6, c0              @ set area 0, default
+
+       ldr     r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
+       ldr     r1, =(CONFIG_DRAM_SIZE >> 12)   @ size of RAM (must be >= 4KB)
+       mov     r2, #10                         @ 11 is the minimum (4KB)
+1:     add     r2, r2, #1                      @ area size *= 2
+       mov     r1, r1, lsr #1
+       bne     1b                              @ count not zero r-shift
+       orr     r0, r0, r2, lsl #1              @ the area register value
+       orr     r0, r0, #1                      @ set enable bit
+       mcr     p15, 0, r0, c6, c1              @ set area 1, RAM
+
+       ldr     r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
+       ldr     r1, =(CONFIG_FLASH_SIZE >> 12)  @ size of FLASH (must be >= 4KB)
+       mov     r2, #10                         @ 11 is the minimum (4KB)
+1:     add     r2, r2, #1                      @ area size *= 2
+       mov     r1, r1, lsr #1
+       bne     1b                              @ count not zero r-shift
+       orr     r0, r0, r2, lsl #1              @ the area register value
+       orr     r0, r0, #1                      @ set enable bit
+       mcr     p15, 0, r0, c6, c2              @ set area 2, ROM/FLASH
+
+       mov     r0, #0x06
+       mcr     p15, 0, r0, c2, c0              @ Region 1&2 cacheable
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mov     r0, #0x00                       @ disable whole write buffer
+#else
+       mov     r0, #0x02                       @ Region 1 write bufferred
+#endif
+       mcr     p15, 0, r0, c3, c0
+
+       mov     r0, #0x10000
+       sub     r0, r0, #1                      @ r0 = 0xffff
+       mcr     p15, 0, r0, c5, c0              @ all read/write access
+
+       mrc     p15, 0, r0, c1, c0              @ get control register
+       bic     r0, r0, #0x3F000000             @ set to standard caching mode
+                                               @ need some benchmark
+       orr     r0, r0, #0x0000000d             @ MPU/Cache/WB
+
+       mov     pc, lr
+
+       .size   __arm740_setup, . - __arm740_setup
+
+       __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *          come through these
+ */
+       .type   arm740_processor_functions, #object
+ENTRY(arm740_processor_functions)
+       .word   v4t_late_abort
+       .word   cpu_arm740_proc_init
+       .word   cpu_arm740_proc_fin
+       .word   cpu_arm740_reset
+       .word   cpu_arm740_do_idle
+       .word   cpu_arm740_dcache_clean_area
+       .word   cpu_arm740_switch_mm
+       .word   0                       @ cpu_*_set_pte
+       .size   arm740_processor_functions, . - arm740_processor_functions
+
+       .section ".rodata"
+
+       .type   cpu_arch_name, #object
+cpu_arch_name:
+       .asciz  "armv4"
+       .size   cpu_arch_name, . - cpu_arch_name
+
+       .type   cpu_elf_name, #object
+cpu_elf_name:
+       .asciz  "v4"
+       .size   cpu_elf_name, . - cpu_elf_name
+
+       .type   cpu_arm740_name, #object
+cpu_arm740_name:
+       .ascii  "ARM740T"
+       .size   cpu_arm740_name, . - cpu_arm740_name
+
+       .align
+
+       .section ".proc.info.init", #alloc, #execinstr
+       .type   __arm740_proc_info,#object
+__arm740_proc_info:
+       .long   0x41807400
+       .long   0xfffffff0
+       .long   0
+       b       __arm740_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+       .long   cpu_arm740_name
+       .long   arm740_processor_functions
+       .long   0
+       .long   0
+       .long   v3_cache_fns                    @ cache model
+       .size   __arm740_proc_info, . - __arm740_proc_info
+
+
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
new file mode 100644 (file)
index 0000000..22d7e31
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ *  linux/arch/arm/mm/proc-arm7tdmi.S: utility functions for ARM7TDMI
+ *
+ *  Copyright (C) 2003-2006 Hyok S. Choi <hyok.choi@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.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+       .text
+/*
+ * cpu_arm7tdmi_proc_init()
+ * cpu_arm7tdmi_do_idle()
+ * cpu_arm7tdmi_dcache_clean_area()
+ * cpu_arm7tdmi_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm7tdmi_proc_init)
+ENTRY(cpu_arm7tdmi_do_idle)
+ENTRY(cpu_arm7tdmi_dcache_clean_area)
+ENTRY(cpu_arm7tdmi_switch_mm)
+               mov     pc, lr
+
+/*
+ * cpu_arm7tdmi_proc_fin()
+ */
+ENTRY(cpu_arm7tdmi_proc_fin)
+               mov     r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+               msr     cpsr_c, r0
+               mov     pc, lr
+
+/*
+ * Function: cpu_arm7tdmi_reset(loc)
+ * Params  : loc(r0)   address to jump to
+ * Purpose : Sets up everything for a reset and jump to the location for soft reset.
+ */
+ENTRY(cpu_arm7tdmi_reset)
+               mov     pc, r0
+
+               __INIT
+
+               .type   __arm7tdmi_setup, #function
+__arm7tdmi_setup:
+               mov     pc, lr
+               .size   __arm7tdmi_setup, . - __arm7tdmi_setup
+
+               __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *          come through these
+ */
+               .type   arm7tdmi_processor_functions, #object
+ENTRY(arm7tdmi_processor_functions)
+               .word   v4t_late_abort
+               .word   cpu_arm7tdmi_proc_init
+               .word   cpu_arm7tdmi_proc_fin
+               .word   cpu_arm7tdmi_reset
+               .word   cpu_arm7tdmi_do_idle
+               .word   cpu_arm7tdmi_dcache_clean_area
+               .word   cpu_arm7tdmi_switch_mm
+               .word   0               @ cpu_*_set_pte
+               .size   arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
+
+               .section ".rodata"
+
+               .type   cpu_arch_name, #object
+cpu_arch_name:
+               .asciz  "armv4t"
+               .size   cpu_arch_name, . - cpu_arch_name
+
+               .type   cpu_elf_name, #object
+cpu_elf_name:
+               .asciz  "v4"
+               .size   cpu_elf_name, . - cpu_elf_name
+
+               .type   cpu_arm7tdmi_name, #object
+cpu_arm7tdmi_name:
+               .asciz  "ARM7TDMI"
+               .size   cpu_arm7tdmi_name, . - cpu_arm7tdmi_name
+
+               .type   cpu_triscenda7_name, #object
+cpu_triscenda7_name:
+               .asciz  "Triscend-A7x"
+               .size   cpu_triscenda7_name, . - cpu_triscenda7_name
+
+               .type   cpu_at91_name, #object
+cpu_at91_name:
+               .asciz  "Atmel-AT91M40xxx"
+               .size   cpu_at91_name, . - cpu_at91_name
+
+               .type   cpu_s3c3410_name, #object
+cpu_s3c3410_name:
+               .asciz  "Samsung-S3C3410"
+               .size   cpu_s3c3410_name, . - cpu_s3c3410_name
+
+               .type   cpu_s3c44b0x_name, #object
+cpu_s3c44b0x_name:
+               .asciz  "Samsung-S3C44B0x"
+               .size   cpu_s3c44b0x_name, . - cpu_s3c44b0x_name
+
+               .type   cpu_s3c4510b, #object
+cpu_s3c4510b_name:
+               .asciz  "Samsung-S3C4510B"
+               .size   cpu_s3c4510b_name, . - cpu_s3c4510b_name
+
+               .type   cpu_s3c4530_name, #object
+cpu_s3c4530_name:
+               .asciz  "Samsung-S3C4530"
+               .size   cpu_s3c4530_name, . - cpu_s3c4530_name
+
+               .type   cpu_netarm_name, #object
+cpu_netarm_name:
+               .asciz  "NETARM"
+               .size   cpu_netarm_name, . - cpu_netarm_name
+
+               .align
+
+               .section ".proc.info.init", #alloc, #execinstr
+
+               .type   __arm7tdmi_proc_info, #object
+__arm7tdmi_proc_info:
+               .long   0x41007700
+               .long   0xfff8ff00
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_26BIT
+               .long   cpu_arm7tdmi_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __arm7tdmi_proc_info, . - __arm7dmi_proc_info
+
+               .type   __triscenda7_proc_info, #object
+__triscenda7_proc_info:
+               .long   0x0001d2ff
+               .long   0x0001ffff
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_triscenda7_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __triscenda7_proc_info, . - __triscenda7_proc_info
+
+               .type   __at91_proc_info, #object
+__at91_proc_info:
+               .long   0x14000040
+               .long   0xfff000e0
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_at91_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __at91_proc_info, . - __at91_proc_info
+
+               .type   __s3c4510b_proc_info, #object
+__s3c4510b_proc_info:
+               .long   0x36365000
+               .long   0xfffff000
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_s3c4510b_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __s3c4510b_proc_info, . - __s3c4510b_proc_info
+
+               .type   __s3c4530_proc_info, #object
+__s3c4530_proc_info:
+               .long   0x4c000000
+               .long   0xfff000e0
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_s3c4530_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __s3c4530_proc_info, . - __s3c4530_proc_info
+
+               .type   __s3c3410_proc_info, #object
+__s3c3410_proc_info:
+               .long   0x34100000
+               .long   0xffff0000
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_s3c3410_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __s3c3410_proc_info, . - __s3c3410_proc_info
+
+               .type   __s3c44b0x_proc_info, #object
+__s3c44b0x_proc_info:
+               .long   0x44b00000
+               .long   0xffff0000
+               .long   0
+               .long   0
+               b       __arm7tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_s3c44b0x_name
+               .long   arm7tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __s3c44b0x_proc_info, . - __s3c44b0x_proc_info
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
new file mode 100644 (file)
index 0000000..2397f4b
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ *  linux/arch/arm/mm/arm940.S: utility functions for ARM940T
+ *
+ *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@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.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+/* ARM940T has a 4KB DCache comprising 256 lines of 4 words */
+#define CACHE_DLINESIZE        16
+#define CACHE_DSEGMENTS        4
+#define CACHE_DENTRIES 64
+
+       .text
+/*
+ * cpu_arm940_proc_init()
+ * cpu_arm940_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm940_proc_init)
+ENTRY(cpu_arm940_switch_mm)
+       mov     pc, lr
+
+/*
+ * cpu_arm940_proc_fin()
+ */
+ENTRY(cpu_arm940_proc_fin)
+       stmfd   sp!, {lr}
+       mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+       msr     cpsr_c, ip
+       bl      arm940_flush_kern_cache_all
+       mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
+       bic     r0, r0, #0x00001000             @ i-cache
+       bic     r0, r0, #0x00000004             @ d-cache
+       mcr     p15, 0, r0, c1, c0, 0           @ disable caches
+       ldmfd   sp!, {pc}
+
+/*
+ * cpu_arm940_reset(loc)
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm940_reset)
+       mov     ip, #0
+       mcr     p15, 0, ip, c7, c5, 0           @ flush I cache
+       mcr     p15, 0, ip, c7, c6, 0           @ flush D cache
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
+       bic     ip, ip, #0x00000005             @ .............c.p
+       bic     ip, ip, #0x00001000             @ i-cache
+       mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
+       mov     pc, r0
+
+/*
+ * cpu_arm940_do_idle()
+ */
+       .align  5
+ENTRY(cpu_arm940_do_idle)
+       mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
+       mov     pc, lr
+
+/*
+ *     flush_user_cache_all()
+ */
+ENTRY(arm940_flush_user_cache_all)
+       /* FALLTHROUGH */
+
+/*
+ *     flush_kern_cache_all()
+ *
+ *     Clean and invalidate the entire cache.
+ */
+ENTRY(arm940_flush_kern_cache_all)
+       mov     r2, #VM_EXEC
+       /* FALLTHROUGH */
+
+/*
+ *     flush_user_cache_range(start, end, flags)
+ *
+ *     There is no efficient way to flush a range of cache entries
+ *     in the specified address range. Thus, flushes all.
+ *
+ *     - start - start address (inclusive)
+ *     - end   - end address (exclusive)
+ *     - flags - vm_flags describing address space
+ */
+ENTRY(arm940_flush_user_cache_range)
+       mov     ip, #0
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, ip, c7, c6, 0           @ flush D cache
+#else
+       mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
+1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:     mcr     p15, 0, r3, c7, c14, 2          @ clean/flush D index
+       subs    r3, r3, #1 << 26
+       bcs     2b                              @ entries 63 to 0
+       subs    r1, r1, #1 << 4
+       bcs     1b                              @ segments 3 to 0
+#endif
+       tst     r2, #VM_EXEC
+       mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
+       mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     coherent_kern_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm940_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm940_coherent_user_range)
+       /* FALLTHROUGH */
+
+/*
+ *     flush_kern_dcache_page(void *page)
+ *
+ *     Ensure no D cache aliasing occurs, either with itself or
+ *     the I cache
+ *
+ *     - addr  - page aligned address
+ */
+ENTRY(arm940_flush_kern_dcache_page)
+       mov     ip, #0
+       mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
+1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:     mcr     p15, 0, r3, c7, c14, 2          @ clean/flush D index
+       subs    r3, r3, #1 << 26
+       bcs     2b                              @ entries 63 to 0
+       subs    r1, r1, #1 << 4
+       bcs     1b                              @ segments 7 to 0
+       mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     dma_inv_range(start, end)
+ *
+ *     There is no efficient way to invalidate a specifid virtual
+ *     address range. Thus, invalidates all.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm940_dma_inv_range)
+       mov     ip, #0
+       mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
+1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:     mcr     p15, 0, r3, c7, c6, 2           @ flush D entry
+       subs    r3, r3, #1 << 26
+       bcs     2b                              @ entries 63 to 0
+       subs    r1, r1, #1 << 4
+       bcs     1b                              @ segments 7 to 0
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     dma_clean_range(start, end)
+ *
+ *     There is no efficient way to clean a specifid virtual
+ *     address range. Thus, cleans all.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm940_dma_clean_range)
+ENTRY(cpu_arm940_dcache_clean_area)
+       mov     ip, #0
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
+1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:     mcr     p15, 0, r3, c7, c10, 2          @ clean D entry
+       subs    r3, r3, #1 << 26
+       bcs     2b                              @ entries 63 to 0
+       subs    r1, r1, #1 << 4
+       bcs     1b                              @ segments 7 to 0
+#endif
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     dma_flush_range(start, end)
+ *
+ *     There is no efficient way to clean and invalidate a specifid
+ *     virtual address range.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm940_dma_flush_range)
+       mov     ip, #0
+       mov     r1, #(CACHE_DSEGMENTS - 1) << 4 @ 4 segments
+1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, r3, c7, c14, 2          @ clean/flush D entry
+#else
+       mcr     p15, 0, r3, c7, c10, 2          @ clean D entry
+#endif
+       subs    r3, r3, #1 << 26
+       bcs     2b                              @ entries 63 to 0
+       subs    r1, r1, #1 << 4
+       bcs     1b                              @ segments 7 to 0
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+ENTRY(arm940_cache_fns)
+       .long   arm940_flush_kern_cache_all
+       .long   arm940_flush_user_cache_all
+       .long   arm940_flush_user_cache_range
+       .long   arm940_coherent_kern_range
+       .long   arm940_coherent_user_range
+       .long   arm940_flush_kern_dcache_page
+       .long   arm940_dma_inv_range
+       .long   arm940_dma_clean_range
+       .long   arm940_dma_flush_range
+
+       __INIT
+
+       .type   __arm940_setup, #function
+__arm940_setup:
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c6, 0           @ invalidate D cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+
+       mcr     p15, 0, r0, c6, c3, 0           @ disable data area 3~7
+       mcr     p15, 0, r0, c6, c4, 0
+       mcr     p15, 0, r0, c6, c5, 0
+       mcr     p15, 0, r0, c6, c6, 0
+       mcr     p15, 0, r0, c6, c7, 0
+
+       mcr     p15, 0, r0, c6, c3, 1           @ disable instruction area 3~7
+       mcr     p15, 0, r0, c6, c4, 1
+       mcr     p15, 0, r0, c6, c5, 1
+       mcr     p15, 0, r0, c6, c6, 1
+       mcr     p15, 0, r0, c6, c7, 1
+
+       mov     r0, #0x0000003F                 @ base = 0, size = 4GB
+       mcr     p15, 0, r0, c6, c0, 0           @ set area 0, default
+       mcr     p15, 0, r0, c6, c0, 1
+
+       ldr     r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
+       ldr     r1, =(CONFIG_DRAM_SIZE >> 12)   @ size of RAM (must be >= 4KB)
+       mov     r2, #10                         @ 11 is the minimum (4KB)
+1:     add     r2, r2, #1                      @ area size *= 2
+       mov     r1, r1, lsr #1
+       bne     1b                              @ count not zero r-shift
+       orr     r0, r0, r2, lsl #1              @ the area register value
+       orr     r0, r0, #1                      @ set enable bit
+       mcr     p15, 0, r0, c6, c1, 0           @ set area 1, RAM
+       mcr     p15, 0, r0, c6, c1, 1
+
+       ldr     r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
+       ldr     r1, =(CONFIG_FLASH_SIZE >> 12)  @ size of FLASH (must be >= 4KB)
+       mov     r2, #10                         @ 11 is the minimum (4KB)
+1:     add     r2, r2, #1                      @ area size *= 2
+       mov     r1, r1, lsr #1
+       bne     1b                              @ count not zero r-shift
+       orr     r0, r0, r2, lsl #1              @ the area register value
+       orr     r0, r0, #1                      @ set enable bit
+       mcr     p15, 0, r0, c6, c2, 0           @ set area 2, ROM/FLASH
+       mcr     p15, 0, r0, c6, c2, 1
+
+       mov     r0, #0x06
+       mcr     p15, 0, r0, c2, c0, 0           @ Region 1&2 cacheable
+       mcr     p15, 0, r0, c2, c0, 1
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mov     r0, #0x00                       @ disable whole write buffer
+#else
+       mov     r0, #0x02                       @ Region 1 write bufferred
+#endif
+       mcr     p15, 0, r0, c3, c0, 0
+
+       mov     r0, #0x10000
+       sub     r0, r0, #1                      @ r0 = 0xffff
+       mcr     p15, 0, r0, c5, c0, 0           @ all read/write access
+       mcr     p15, 0, r0, c5, c0, 1
+
+       mrc     p15, 0, r0, c1, c0              @ get control register
+       orr     r0, r0, #0x00001000             @ I-cache
+       orr     r0, r0, #0x00000005             @ MPU/D-cache
+
+       mov     pc, lr
+
+       .size   __arm940_setup, . - __arm940_setup
+
+       __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *          come through these
+ */
+       .type   arm940_processor_functions, #object
+ENTRY(arm940_processor_functions)
+       .word   nommu_early_abort
+       .word   cpu_arm940_proc_init
+       .word   cpu_arm940_proc_fin
+       .word   cpu_arm940_reset
+       .word   cpu_arm940_do_idle
+       .word   cpu_arm940_dcache_clean_area
+       .word   cpu_arm940_switch_mm
+       .word   0               @ cpu_*_set_pte
+       .size   arm940_processor_functions, . - arm940_processor_functions
+
+       .section ".rodata"
+
+.type  cpu_arch_name, #object
+cpu_arch_name:
+       .asciz  "armv4t"
+       .size   cpu_arch_name, . - cpu_arch_name
+
+       .type   cpu_elf_name, #object
+cpu_elf_name:
+       .asciz  "v4"
+       .size   cpu_elf_name, . - cpu_elf_name
+
+       .type   cpu_arm940_name, #object
+cpu_arm940_name:
+       .ascii  "ARM940T"
+       .size   cpu_arm940_name, . - cpu_arm940_name
+
+       .align
+
+       .section ".proc.info.init", #alloc, #execinstr
+
+       .type   __arm940_proc_info,#object
+__arm940_proc_info:
+       .long   0x41009400
+       .long   0xff00fff0
+       .long   0
+       b       __arm940_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+       .long   cpu_arm940_name
+       .long   arm940_processor_functions
+       .long   0
+       .long   0
+       .long   arm940_cache_fns
+       .size   __arm940_proc_info, . - __arm940_proc_info
+
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
new file mode 100644 (file)
index 0000000..e186175
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ *  linux/arch/arm/mm/arm946.S: utility functions for ARM946E-S
+ *
+ *  Copyright (C) 2004-2006 Hyok S. Choi (hyok.choi@samsung.com)
+ *
+ *  (Many of cache codes are from proc-arm926.S)
+ *
+ * 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/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+/*
+ * ARM946E-S is synthesizable to have 0KB to 1MB sized D-Cache,
+ * comprising 256 lines of 32 bytes (8 words).
+ */
+#define CACHE_DSIZE    (CONFIG_CPU_DCACHE_SIZE) /* typically 8KB. */
+#define CACHE_DLINESIZE        32                      /* fixed */
+#define CACHE_DSEGMENTS        4                       /* fixed */
+#define CACHE_DENTRIES (CACHE_DSIZE / CACHE_DSEGMENTS / CACHE_DLINESIZE)
+#define CACHE_DLIMIT   (CACHE_DSIZE * 4)       /* benchmark needed */
+
+       .text
+/*
+ * cpu_arm946_proc_init()
+ * cpu_arm946_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm946_proc_init)
+ENTRY(cpu_arm946_switch_mm)
+       mov     pc, lr
+
+/*
+ * cpu_arm946_proc_fin()
+ */
+ENTRY(cpu_arm946_proc_fin)
+       stmfd   sp!, {lr}
+       mov     ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+       msr     cpsr_c, ip
+       bl      arm946_flush_kern_cache_all
+       mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
+       bic     r0, r0, #0x00001000             @ i-cache
+       bic     r0, r0, #0x00000004             @ d-cache
+       mcr     p15, 0, r0, c1, c0, 0           @ disable caches
+       ldmfd   sp!, {pc}
+
+/*
+ * cpu_arm946_reset(loc)
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm946_reset)
+       mov     ip, #0
+       mcr     p15, 0, ip, c7, c5, 0           @ flush I cache
+       mcr     p15, 0, ip, c7, c6, 0           @ flush D cache
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       mrc     p15, 0, ip, c1, c0, 0           @ ctrl register
+       bic     ip, ip, #0x00000005             @ .............c.p
+       bic     ip, ip, #0x00001000             @ i-cache
+       mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
+       mov     pc, r0
+
+/*
+ * cpu_arm946_do_idle()
+ */
+       .align  5
+ENTRY(cpu_arm946_do_idle)
+       mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
+       mov     pc, lr
+
+/*
+ *     flush_user_cache_all()
+ */
+ENTRY(arm946_flush_user_cache_all)
+       /* FALLTHROUGH */
+
+/*
+ *     flush_kern_cache_all()
+ *
+ *     Clean and invalidate the entire cache.
+ */
+ENTRY(arm946_flush_kern_cache_all)
+       mov     r2, #VM_EXEC
+       mov     ip, #0
+__flush_whole_cache:
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, ip, c7, c6, 0           @ flush D cache
+#else
+       mov     r1, #(CACHE_DSEGMENTS - 1) << 29 @ 4 segments
+1:     orr     r3, r1, #(CACHE_DENTRIES - 1) << 4 @ n entries
+2:     mcr     p15, 0, r3, c7, c14, 2          @ clean/flush D index
+       subs    r3, r3, #1 << 4
+       bcs     2b                              @ entries n to 0
+       subs    r1, r1, #1 << 29
+       bcs     1b                              @ segments 3 to 0
+#endif
+       tst     r2, #VM_EXEC
+       mcrne   p15, 0, ip, c7, c5, 0           @ flush I cache
+       mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     flush_user_cache_range(start, end, flags)
+ *
+ *     Clean and invalidate a range of cache entries in the
+ *     specified address range.
+ *
+ *     - start - start address (inclusive)
+ *     - end   - end address (exclusive)
+ *     - flags - vm_flags describing address space
+ * (same as arm926)
+ */
+ENTRY(arm946_flush_user_cache_range)
+       mov     ip, #0
+       sub     r3, r1, r0                      @ calculate total size
+       cmp     r3, #CACHE_DLIMIT
+       bhs     __flush_whole_cache
+
+1:     tst     r2, #VM_EXEC
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
+       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
+       add     r0, r0, #CACHE_DLINESIZE
+       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
+       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
+       add     r0, r0, #CACHE_DLINESIZE
+#else
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
+       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
+       add     r0, r0, #CACHE_DLINESIZE
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
+       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
+       add     r0, r0, #CACHE_DLINESIZE
+#endif
+       cmp     r0, r1
+       blo     1b
+       tst     r2, #VM_EXEC
+       mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     coherent_kern_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ */
+ENTRY(arm946_coherent_kern_range)
+       /* FALLTHROUGH */
+
+/*
+ *     coherent_user_range(start, end)
+ *
+ *     Ensure coherency between the Icache and the Dcache in the
+ *     region described by start, end.  If you have non-snooping
+ *     Harvard caches, you need to implement this function.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ * (same as arm926)
+ */
+ENTRY(arm946_coherent_user_range)
+       bic     r0, r0, #CACHE_DLINESIZE - 1
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+       mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
+       add     r0, r0, #CACHE_DLINESIZE
+       cmp     r0, r1
+       blo     1b
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     flush_kern_dcache_page(void *page)
+ *
+ *     Ensure no D cache aliasing occurs, either with itself or
+ *     the I cache
+ *
+ *     - addr  - page aligned address
+ * (same as arm926)
+ */
+ENTRY(arm946_flush_kern_dcache_page)
+       add     r1, r0, #PAGE_SZ
+1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
+       add     r0, r0, #CACHE_DLINESIZE
+       cmp     r0, r1
+       blo     1b
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     dma_inv_range(start, end)
+ *
+ *     Invalidate (discard) the specified virtual address range.
+ *     May not write back any entries.  If 'start' or 'end'
+ *     are not cache line aligned, those lines must be written
+ *     back.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ * (same as arm926)
+ */
+ENTRY(arm946_dma_inv_range)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+       tst     r0, #CACHE_DLINESIZE - 1
+       mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
+       tst     r1, #CACHE_DLINESIZE - 1
+       mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
+#endif
+       bic     r0, r0, #CACHE_DLINESIZE - 1
+1:     mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
+       add     r0, r0, #CACHE_DLINESIZE
+       cmp     r0, r1
+       blo     1b
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     dma_clean_range(start, end)
+ *
+ *     Clean the specified virtual address range.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ *
+ * (same as arm926)
+ */
+ENTRY(arm946_dma_clean_range)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+       bic     r0, r0, #CACHE_DLINESIZE - 1
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+       add     r0, r0, #CACHE_DLINESIZE
+       cmp     r0, r1
+       blo     1b
+#endif
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+/*
+ *     dma_flush_range(start, end)
+ *
+ *     Clean and invalidate the specified virtual address range.
+ *
+ *     - start - virtual start address
+ *     - end   - virtual end address
+ *
+ * (same as arm926)
+ */
+ENTRY(arm946_dma_flush_range)
+       bic     r0, r0, #CACHE_DLINESIZE - 1
+1:
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
+#else
+       mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+#endif
+       add     r0, r0, #CACHE_DLINESIZE
+       cmp     r0, r1
+       blo     1b
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+ENTRY(arm946_cache_fns)
+       .long   arm946_flush_kern_cache_all
+       .long   arm946_flush_user_cache_all
+       .long   arm946_flush_user_cache_range
+       .long   arm946_coherent_kern_range
+       .long   arm946_coherent_user_range
+       .long   arm946_flush_kern_dcache_page
+       .long   arm946_dma_inv_range
+       .long   arm946_dma_clean_range
+       .long   arm946_dma_flush_range
+
+
+ENTRY(cpu_arm946_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+       add     r0, r0, #CACHE_DLINESIZE
+       subs    r1, r1, #CACHE_DLINESIZE
+       bhi     1b
+#endif
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+       mov     pc, lr
+
+       __INIT
+
+       .type   __arm946_setup, #function
+__arm946_setup:
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mcr     p15, 0, r0, c7, c6, 0           @ invalidate D cache
+       mcr     p15, 0, r0, c7, c10, 4          @ drain WB
+
+       mcr     p15, 0, r0, c6, c3, 0           @ disable memory region 3~7
+       mcr     p15, 0, r0, c6, c4, 0
+       mcr     p15, 0, r0, c6, c5, 0
+       mcr     p15, 0, r0, c6, c6, 0
+       mcr     p15, 0, r0, c6, c7, 0
+
+       mov     r0, #0x0000003F                 @ base = 0, size = 4GB
+       mcr     p15, 0, r0, c6, c0, 0           @ set region 0, default
+
+       ldr     r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
+       ldr     r1, =(CONFIG_DRAM_SIZE >> 12)   @ size of RAM (must be >= 4KB)
+       mov     r2, #10                         @ 11 is the minimum (4KB)
+1:     add     r2, r2, #1                      @ area size *= 2
+       mov     r1, r1, lsr #1
+       bne     1b                              @ count not zero r-shift
+       orr     r0, r0, r2, lsl #1              @ the region register value
+       orr     r0, r0, #1                      @ set enable bit
+       mcr     p15, 0, r0, c6, c1, 0           @ set region 1, RAM
+
+       ldr     r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
+       ldr     r1, =(CONFIG_FLASH_SIZE >> 12)  @ size of FLASH (must be >= 4KB)
+       mov     r2, #10                         @ 11 is the minimum (4KB)
+1:     add     r2, r2, #1                      @ area size *= 2
+       mov     r1, r1, lsr #1
+       bne     1b                              @ count not zero r-shift
+       orr     r0, r0, r2, lsl #1              @ the region register value
+       orr     r0, r0, #1                      @ set enable bit
+       mcr     p15, 0, r0, c6, c2, 0           @ set region 2, ROM/FLASH
+
+       mov     r0, #0x06
+       mcr     p15, 0, r0, c2, c0, 0           @ region 1,2 d-cacheable
+       mcr     p15, 0, r0, c2, c0, 1           @ region 1,2 i-cacheable
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mov     r0, #0x00                       @ disable whole write buffer
+#else
+       mov     r0, #0x02                       @ region 1 write bufferred
+#endif
+       mcr     p15, 0, r0, c3, c0, 0
+
+/*
+ *  Access Permission Settings for future permission control by PU.
+ *
+ *                             priv.   user
+ *     region 0 (whole)        rw      --      : b0001
+ *     region 1 (RAM)          rw      rw      : b0011
+ *     region 2 (FLASH)        rw      r-      : b0010
+ *     region 3~7 (none)       --      --      : b0000
+ */
+       mov     r0, #0x00000031
+       orr     r0, r0, #0x00000200
+       mcr     p15, 0, r0, c5, c0, 2           @ set data access permission
+       mcr     p15, 0, r0, c5, c0, 3           @ set inst. access permission
+
+       mrc     p15, 0, r0, c1, c0              @ get control register
+       orr     r0, r0, #0x00001000             @ I-cache
+       orr     r0, r0, #0x00000005             @ MPU/D-cache
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
+       orr     r0, r0, #0x00004000             @ .1.. .... .... ....
+#endif
+       mov     pc, lr
+
+       .size   __arm946_setup, . - __arm946_setup
+
+       __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *          come through these
+ */
+       .type   arm946_processor_functions, #object
+ENTRY(arm946_processor_functions)
+       .word   nommu_early_abort
+       .word   cpu_arm946_proc_init
+       .word   cpu_arm946_proc_fin
+       .word   cpu_arm946_reset
+       .word   cpu_arm946_do_idle
+
+       .word   cpu_arm946_dcache_clean_area
+       .word   cpu_arm946_switch_mm
+       .word   0               @ cpu_*_set_pte
+       .size   arm946_processor_functions, . - arm946_processor_functions
+
+       .section ".rodata"
+
+       .type   cpu_arch_name, #object
+cpu_arch_name:
+       .asciz  "armv5te"
+       .size   cpu_arch_name, . - cpu_arch_name
+
+       .type   cpu_elf_name, #object
+cpu_elf_name:
+       .asciz  "v5t"
+       .size   cpu_elf_name, . - cpu_elf_name
+
+       .type   cpu_arm946_name, #object
+cpu_arm946_name:
+       .ascii  "ARM946E-S"
+       .size   cpu_arm946_name, . - cpu_arm946_name
+
+       .align
+
+       .section ".proc.info.init", #alloc, #execinstr
+       .type   __arm946_proc_info,#object
+__arm946_proc_info:
+       .long   0x41009460
+       .long   0xff00fff0
+       .long   0
+       b       __arm946_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+       .long   cpu_arm946_name
+       .long   arm946_processor_functions
+       .long   0
+       .long   0
+       .long   arm940_cache_fns
+       .size   __arm946_proc_info, . - __arm946_proc_info
+
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
new file mode 100644 (file)
index 0000000..918ebf6
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  linux/arch/arm/mm/proc-arm9tdmi.S: utility functions for ARM9TDMI
+ *
+ *  Copyright (C) 2003-2006 Hyok S. Choi <hyok.choi@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.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+
+       .text
+/*
+ * cpu_arm9tdmi_proc_init()
+ * cpu_arm9tdmi_do_idle()
+ * cpu_arm9tdmi_dcache_clean_area()
+ * cpu_arm9tdmi_switch_mm()
+ *
+ * These are not required.
+ */
+ENTRY(cpu_arm9tdmi_proc_init)
+ENTRY(cpu_arm9tdmi_do_idle)
+ENTRY(cpu_arm9tdmi_dcache_clean_area)
+ENTRY(cpu_arm9tdmi_switch_mm)
+               mov     pc, lr
+
+/*
+ * cpu_arm9tdmi_proc_fin()
+ */
+ENTRY(cpu_arm9tdmi_proc_fin)
+               mov     r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+               msr     cpsr_c, r0
+               mov     pc, lr
+
+/*
+ * Function: cpu_arm9tdmi_reset(loc)
+ * Params  : loc(r0)   address to jump to
+ * Purpose : Sets up everything for a reset and jump to the location for soft reset.
+ */
+ENTRY(cpu_arm9tdmi_reset)
+               mov     pc, r0
+
+               __INIT
+
+               .type   __arm9tdmi_setup, #function
+__arm9tdmi_setup:
+               mov     pc, lr
+               .size   __arm9tdmi_setup, . - __arm9tdmi_setup
+
+               __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *          come through these
+ */
+               .type   arm9tdmi_processor_functions, #object
+ENTRY(arm9tdmi_processor_functions)
+               .word   nommu_early_abort
+               .word   cpu_arm9tdmi_proc_init
+               .word   cpu_arm9tdmi_proc_fin
+               .word   cpu_arm9tdmi_reset
+               .word   cpu_arm9tdmi_do_idle
+               .word   cpu_arm9tdmi_dcache_clean_area
+               .word   cpu_arm9tdmi_switch_mm
+               .word   0               @ cpu_*_set_pte
+               .size   arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
+
+               .section ".rodata"
+
+               .type   cpu_arch_name, #object
+cpu_arch_name:
+               .asciz  "armv4t"
+               .size   cpu_arch_name, . - cpu_arch_name
+
+               .type   cpu_elf_name, #object
+cpu_elf_name:
+               .asciz  "v4"
+               .size   cpu_elf_name, . - cpu_elf_name
+
+               .type   cpu_arm9tdmi_name, #object
+cpu_arm9tdmi_name:
+               .asciz  "ARM9TDMI"
+               .size   cpu_arm9tdmi_name, . - cpu_arm9tdmi_name
+
+               .type   cpu_p2001_name, #object
+cpu_p2001_name:
+               .asciz  "P2001"
+               .size   cpu_p2001_name, . - cpu_p2001_name
+
+               .align
+
+               .section ".proc.info.init", #alloc, #execinstr
+
+               .type   __arm9tdmi_proc_info, #object
+__arm9tdmi_proc_info:
+               .long   0x41009900
+               .long   0xfff8ff00
+               .long   0
+               .long   0
+               b       __arm9tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_arm9tdmi_name
+               .long   arm9tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __arm9tdmi_proc_info, . - __arm9dmi_proc_info
+
+               .type   __p2001_proc_info, #object
+__p2001_proc_info:
+               .long   0x41029000
+               .long   0xffffffff
+               .long   0
+               .long   0
+               b       __arm9tdmi_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
+               .long   cpu_p2001_name
+               .long   arm9tdmi_processor_functions
+               .long   0
+               .long   0
+               .long   v4_cache_fns
+               .size   __p2001_proc_info, . - __p2001_proc_info
index 3ca0c92e98a2ddba5a3b2f3d21a09cb775700abd..e8b377d637f664753917371a626563461c2ca94a 100644 (file)
@@ -311,12 +311,6 @@ ENTRY(xscale_flush_kern_dcache_page)
  *     - end    - virtual end address
  */
 ENTRY(xscale_dma_inv_range)
-       mrc     p15, 0, r2, c0, c0, 0           @ read ID
-       eor     r2, r2, #0x69000000
-       eor     r2, r2, #0x00052000
-       bics    r2, r2, #1
-       beq     xscale_dma_flush_range
-
        tst     r0, #CACHELINESIZE - 1
        bic     r0, r0, #CACHELINESIZE - 1
        mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
@@ -375,6 +369,30 @@ ENTRY(xscale_cache_fns)
        .long   xscale_dma_clean_range
        .long   xscale_dma_flush_range
 
+/*
+ * On stepping A0/A1 of the 80200, invalidating D-cache by line doesn't
+ * clear the dirty bits, which means that if we invalidate a dirty line,
+ * the dirty data can still be written back to external memory later on.
+ *
+ * The recommended workaround is to always do a clean D-cache line before
+ * doing an invalidate D-cache line, so on the affected processors,
+ * dma_inv_range() is implemented as dma_flush_range().
+ *
+ * See erratum #25 of "Intel 80200 Processor Specification Update",
+ * revision January 22, 2003, available at:
+ *     http://www.intel.com/design/iio/specupdt/273415.htm
+ */
+ENTRY(xscale_80200_A0_A1_cache_fns)
+       .long   xscale_flush_kern_cache_all
+       .long   xscale_flush_user_cache_all
+       .long   xscale_flush_user_cache_range
+       .long   xscale_coherent_kern_range
+       .long   xscale_coherent_user_range
+       .long   xscale_flush_kern_dcache_page
+       .long   xscale_dma_flush_range
+       .long   xscale_dma_clean_range
+       .long   xscale_dma_flush_range
+
 ENTRY(cpu_xscale_dcache_clean_area)
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, #CACHELINESIZE
@@ -531,6 +549,11 @@ cpu_elf_name:
        .asciz  "v5"
        .size   cpu_elf_name, . - cpu_elf_name
 
+       .type   cpu_80200_A0_A1_name, #object
+cpu_80200_A0_A1_name:
+       .asciz  "XScale-80200 A0/A1"
+       .size   cpu_80200_A0_A1_name, . - cpu_80200_A0_A1_name
+
        .type   cpu_80200_name, #object
 cpu_80200_name:
        .asciz  "XScale-80200"
@@ -595,6 +618,29 @@ cpu_pxa270_name:
 
        .section ".proc.info.init", #alloc, #execinstr
 
+       .type   __80200_A0_A1_proc_info,#object
+__80200_A0_A1_proc_info:
+       .long   0x69052000
+       .long   0xfffffffe
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_BUFFERABLE | \
+               PMD_SECT_CACHEABLE | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       .long   PMD_TYPE_SECT | \
+               PMD_SECT_AP_WRITE | \
+               PMD_SECT_AP_READ
+       b       __xscale_setup
+       .long   cpu_arch_name
+       .long   cpu_elf_name
+       .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+       .long   cpu_80200_name
+       .long   xscale_processor_functions
+       .long   v4wbi_tlb_fns
+       .long   xscale_mc_user_fns
+       .long   xscale_80200_A0_A1_cache_fns
+       .size   __80200_A0_A1_proc_info, . - __80200_A0_A1_proc_info
+
        .type   __80200_proc_info,#object
 __80200_proc_info:
        .long   0x69052000
index 34fdc733743b9ec3a5c626c18541f24a4a46be87..6576143f25598253bba9e5d8701bdb44d8bd4234 100644 (file)
 #ifdef CONFIG_ARCH_IOP310
 #define XSCALE_PMU_IRQ  IRQ_XS80200_PMU
 #endif
-#ifdef CONFIG_ARCH_IOP321
-#define XSCALE_PMU_IRQ  IRQ_IOP321_CORE_PMU
+#ifdef CONFIG_ARCH_IOP32X
+#define XSCALE_PMU_IRQ  IRQ_IOP32X_CORE_PMU
 #endif
-#ifdef CONFIG_ARCH_IOP331
-#define XSCALE_PMU_IRQ  IRQ_IOP331_CORE_PMU
+#ifdef CONFIG_ARCH_IOP33X
+#define XSCALE_PMU_IRQ  IRQ_IOP33X_CORE_PMU
 #endif
 #ifdef CONFIG_ARCH_PXA
 #define XSCALE_PMU_IRQ  IRQ_PMU
@@ -88,7 +88,7 @@ static struct pmu_counter results[MAX_COUNTERS];
 /*
  * There are two versions of the PMU in current XScale processors
  * with differing register layouts and number of performance counters.
- * e.g. IOP321 is xsc1 whilst IOP331 is xsc2.
+ * e.g. IOP32x is xsc1 whilst IOP33x is xsc2.
  * We detect which register layout to use in xscale_detect_pmu()
  */
 enum { PMU_XSC1, PMU_XSC2 };
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
new file mode 100644 (file)
index 0000000..23da00b
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                  := gpio.o i2c.o pci.o setup.o time.o
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
diff --git a/arch/arm/plat-iop/gpio.c b/arch/arm/plat-iop/gpio.c
new file mode 100644 (file)
index 0000000..eda4360
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * arch/arm/plat-iop/gpio.c
+ * GPIO handling for Intel IOP3xx processors.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/device.h>
+#include <asm/hardware/iop3xx.h>
+
+void gpio_line_config(int line, int direction)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (direction == GPIO_IN) {
+               *IOP3XX_GPOE |= 1 << line;
+       } else if (direction == GPIO_OUT) {
+               *IOP3XX_GPOE &= ~(1 << line);
+       }
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_line_config);
+
+int gpio_line_get(int line)
+{
+       return !!(*IOP3XX_GPID & (1 << line));
+}
+EXPORT_SYMBOL(gpio_line_get);
+
+void gpio_line_set(int line, int value)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (value == GPIO_LOW) {
+               *IOP3XX_GPOD &= ~(1 << line);
+       } else if (value == GPIO_HIGH) {
+               *IOP3XX_GPOD |= 1 << line;
+       }
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_line_set);
diff --git a/arch/arm/plat-iop/i2c.c b/arch/arm/plat-iop/i2c.c
new file mode 100644 (file)
index 0000000..e99909b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * arch/arm/plat-iop/i2c.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ * Copyright (C) 2004 Intel 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop3xx.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_IOP3XX_I2C_0       IRQ_IOP32X_I2C_0
+#define IRQ_IOP3XX_I2C_1       IRQ_IOP32X_I2C_1
+#endif
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_IOP3XX_I2C_0       IRQ_IOP33X_I2C_0
+#define IRQ_IOP3XX_I2C_1       IRQ_IOP33X_I2C_1
+#endif
+
+static struct resource iop3xx_i2c0_resources[] = {
+       [0] = {
+               .start  = 0xfffff680,
+               .end    = 0xfffff697,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_IOP3XX_I2C_0,
+               .end    = IRQ_IOP3XX_I2C_0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device iop3xx_i2c0_device = {
+       .name           = "IOP3xx-I2C",
+       .id             = 0,
+       .num_resources  = 2,
+       .resource       = iop3xx_i2c0_resources,
+};
+
+
+static struct resource iop3xx_i2c1_resources[] = {
+       [0] = {
+               .start  = 0xfffff6a0,
+               .end    = 0xfffff6b7,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_IOP3XX_I2C_1,
+               .end    = IRQ_IOP3XX_I2C_1,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+struct platform_device iop3xx_i2c1_device = {
+       .name           = "IOP3xx-I2C",
+       .id             = 1,
+       .num_resources  = 2,
+       .resource       = iop3xx_i2c1_resources,
+};
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
new file mode 100644 (file)
index 0000000..e647812
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * arch/arm/plat-iop/pci.c
+ *
+ * PCI support for the Intel IOP32X and IOP33X processors
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach/pci.h>
+#include <asm/hardware/iop3xx.h>
+
+// #define DEBUG
+
+#ifdef DEBUG
+#define  DBG(x...) printk(x)
+#else
+#define  DBG(x...) do { } while (0)
+#endif
+
+/*
+ * This routine builds either a type0 or type1 configuration command.  If the
+ * bus is on the 803xx then a type0 made, else a type1 is created.
+ */
+static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where)
+{
+       struct pci_sys_data *sys = bus->sysdata;
+       u32 addr;
+
+       if (sys->busnr == bus->number)
+               addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
+       else
+               addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
+
+       addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
+
+       return addr;
+}
+
+/*
+ * This routine checks the status of the last configuration cycle.  If an error
+ * was detected it returns a 1, else it returns a 0.  The errors being checked
+ * are parity, master abort, target abort (master and target).  These types of
+ * errors occure during a config cycle where there is no device, like during
+ * the discovery stage.
+ */
+static int iop3xx_pci_status(void)
+{
+       unsigned int status;
+       int ret = 0;
+
+       /*
+        * Check the status registers.
+        */
+       status = *IOP3XX_ATUSR;
+       if (status & 0xf900) {
+               DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
+               *IOP3XX_ATUSR = status & 0xf900;
+               ret = 1;
+       }
+
+       status = *IOP3XX_ATUISR;
+       if (status & 0x679f) {
+               DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
+               *IOP3XX_ATUISR = status & 0x679f;
+               ret = 1;
+       }
+
+       return ret;
+}
+
+/*
+ * Simply write the address register and read the configuration
+ * data.  Note that the 4 nop's ensure that we are able to handle
+ * a delayed abort (in theory.)
+ */
+static inline u32 iop3xx_read(unsigned long addr)
+{
+       u32 val;
+
+       __asm__ __volatile__(
+               "str    %1, [%2]\n\t"
+               "ldr    %0, [%3]\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               "nop\n\t"
+               : "=r" (val)
+               : "r" (addr), "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR));
+
+       return val;
+}
+
+/*
+ * The read routines must check the error status of the last configuration
+ * cycle.  If there was an error, the routine returns all hex f's.
+ */
+static int
+iop3xx_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 *value)
+{
+       unsigned long addr = iop3xx_cfg_address(bus, devfn, where);
+       u32 val = iop3xx_read(addr) >> ((where & 3) * 8);
+
+       if (iop3xx_pci_status())
+               val = 0xffffffff;
+
+       *value = val;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+               int size, u32 value)
+{
+       unsigned long addr = iop3xx_cfg_address(bus, devfn, where);
+       u32 val;
+
+       if (size != 4) {
+               val = iop3xx_read(addr);
+               if (iop3xx_pci_status())
+                       return PCIBIOS_SUCCESSFUL;
+
+               where = (where & 3) * 8;
+
+               if (size == 1)
+                       val &= ~(0xff << where);
+               else
+                       val &= ~(0xffff << where);
+
+               *IOP3XX_OCCDR = val | value << where;
+       } else {
+               asm volatile(
+                       "str    %1, [%2]\n\t"
+                       "str    %0, [%3]\n\t"
+                       "nop\n\t"
+                       "nop\n\t"
+                       "nop\n\t"
+                       "nop\n\t"
+                       :
+                       : "r" (value), "r" (addr),
+                         "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR));
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop3xx_ops = {
+       .read   = iop3xx_read_config,
+       .write  = iop3xx_write_config,
+};
+
+/*
+ * When a PCI device does not exist during config cycles, the 80200 gets a
+ * bus error instead of returning 0xffffffff. This handler simply returns.
+ */
+static int
+iop3xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+       DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
+               addr, fsr, regs->ARM_pc, regs->ARM_lr);
+
+       /*
+        * If it was an imprecise abort, then we need to correct the
+        * return address to be _after_ the instruction.
+        */
+       if (fsr & (1 << 10))
+               regs->ARM_pc += 4;
+
+       return 0;
+}
+
+int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
+{
+       struct resource *res;
+
+       if (nr != 0)
+               return 0;
+
+       res = kzalloc(2 * sizeof(struct resource), GFP_KERNEL);
+       if (!res)
+               panic("PCI: unable to alloc resources");
+
+       res[0].start = IOP3XX_PCI_LOWER_IO_VA;
+       res[0].end   = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
+       res[0].name  = "IOP3XX PCI I/O Space";
+       res[0].flags = IORESOURCE_IO;
+       request_resource(&ioport_resource, &res[0]);
+
+       res[1].start = IOP3XX_PCI_LOWER_MEM_PA;
+       res[1].end   = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1;
+       res[1].name  = "IOP3XX PCI Memory Space";
+       res[1].flags = IORESOURCE_MEM;
+       request_resource(&iomem_resource, &res[1]);
+
+       sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
+       sys->io_offset  = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA;
+
+       sys->resource[0] = &res[0];
+       sys->resource[1] = &res[1];
+       sys->resource[2] = NULL;
+
+       return 1;
+}
+
+struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys)
+{
+       return pci_scan_bus(sys->busnr, &iop3xx_ops, sys);
+}
+
+void iop3xx_pci_preinit(void)
+{
+       DBG("PCI:  Intel 803xx PCI init code.\n");
+       DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
+       DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
+                       *IOP3XX_OMWTVR0,
+                       *IOP3XX_OIOWTVR);
+       DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR);
+       DBG("ATU: IOP3XX_IABAR0=0x%08x IOP3XX_IALR0=0x%08x IOP3XX_IATVR0=%08x\n",
+                       *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
+       DBG("ATU: IOP3XX_OMWTVR0=0x%08x\n", *IOP3XX_OMWTVR0);
+       DBG("ATU: IOP3XX_IABAR1=0x%08x IOP3XX_IALR1=0x%08x\n",
+                       *IOP3XX_IABAR1, *IOP3XX_IALR1);
+       DBG("ATU: IOP3XX_ERBAR=0x%08x IOP3XX_ERLR=0x%08x IOP3XX_ERTVR=%08x\n",
+                       *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
+       DBG("ATU: IOP3XX_IABAR2=0x%08x IOP3XX_IALR2=0x%08x IOP3XX_IATVR2=%08x\n",
+                       *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
+       DBG("ATU: IOP3XX_IABAR3=0x%08x IOP3XX_IALR3=0x%08x IOP3XX_IATVR3=%08x\n",
+                       *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
+
+       hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
+}
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c
new file mode 100644 (file)
index 0000000..4689db6
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/plat-iop/setup.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001 MontaVista Software, Inc.
+ * Copyright (C) 2004 Intel 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/iop3xx.h>
+
+/*
+ * Standard IO mapping for all IOP3xx based systems
+ */
+static struct map_desc iop3xx_std_desc[] __initdata = {
+        {      /* mem mapped registers */
+               .virtual        = IOP3XX_PERIPHERAL_VIRT_BASE,
+               .pfn            = __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE),
+               .length         = IOP3XX_PERIPHERAL_SIZE,
+               .type           = MT_DEVICE,
+        }, {   /* PCI IO space */
+               .virtual        = IOP3XX_PCI_LOWER_IO_VA,
+               .pfn            = __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA),
+               .length         = IOP3XX_PCI_IO_WINDOW_SIZE,
+               .type           = MT_DEVICE,
+        },
+};
+
+void __init iop3xx_map_io(void)
+{
+       iotable_init(iop3xx_std_desc, ARRAY_SIZE(iop3xx_std_desc));
+}
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
new file mode 100644 (file)
index 0000000..06282df
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * arch/arm/plat-iop/time.c
+ *
+ * Timer code for IOP32x and IOP33x based systems
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright 2002-2003 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/timex.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_IOP3XX_TIMER0      IRQ_IOP32X_TIMER0
+#else
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_IOP3XX_TIMER0      IRQ_IOP33X_TIMER0
+#endif
+#endif
+
+static unsigned long ticks_per_jiffy;
+static unsigned long ticks_per_usec;
+static unsigned long next_jiffy_time;
+
+unsigned long iop3xx_gettimeoffset(void)
+{
+       unsigned long offset;
+
+       offset = next_jiffy_time - *IOP3XX_TU_TCR1;
+
+       return offset / ticks_per_usec;
+}
+
+static irqreturn_t
+iop3xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       write_seqlock(&xtime_lock);
+
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (1));
+       iop3xx_cp6_disable();
+
+       while ((signed long)(next_jiffy_time - *IOP3XX_TU_TCR1)
+                                                       >= ticks_per_jiffy) {
+               timer_tick(regs);
+               next_jiffy_time -= ticks_per_jiffy;
+       }
+
+       write_sequnlock(&xtime_lock);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction iop3xx_timer_irq = {
+       .name           = "IOP3XX Timer Tick",
+       .handler        = iop3xx_timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+};
+
+void __init iop3xx_init_time(unsigned long tick_rate)
+{
+       u32 timer_ctl;
+
+       ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
+       ticks_per_usec = tick_rate / 1000000;
+       next_jiffy_time = 0xffffffff;
+
+       timer_ctl = IOP3XX_TMR_EN | IOP3XX_TMR_PRIVILEGED |
+                       IOP3XX_TMR_RELOAD | IOP3XX_TMR_RATIO_1_1;
+
+       /*
+        * We use timer 0 for our timer interrupt, and timer 1 as
+        * monotonic counter for tracking missed jiffies.
+        */
+       iop3xx_cp6_enable();
+       asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (ticks_per_jiffy - 1));
+       asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
+       asm volatile("mcr p6, 0, %0, c5, c1, 0" : : "r" (0xffffffff));
+       asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
+       iop3xx_cp6_disable();
+
+       setup_irq(IRQ_IOP3XX_TIMER0, &iop3xx_timer_irq);
+}
index 7f45c7c3e673d1898902fbac743de5e7cb655fd8..f1179ad4be1bb0f63e3d95059c8e3188b5bcc1e4 100644 (file)
@@ -100,6 +100,7 @@ void clk_disable(struct clk *clk)
                return;
 
        spin_lock_irqsave(&clockfw_lock, flags);
+       BUG_ON(clk->usecount == 0);
        if (arch_clock->clk_disable)
                arch_clock->clk_disable(clk);
        spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -322,6 +323,31 @@ EXPORT_SYMBOL(clk_allow_idle);
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+/*
+ * Disable any unused clocks left on by the bootloader
+ */
+static int __init clk_disable_unused(void)
+{
+       struct clk *ck;
+       unsigned long flags;
+
+       list_for_each_entry(ck, &clocks, node) {
+               if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
+                       ck->enable_reg == 0)
+                       continue;
+
+               spin_lock_irqsave(&clockfw_lock, flags);
+               if (arch_clock->clk_disable_unused)
+                       arch_clock->clk_disable_unused(ck);
+               spin_unlock_irqrestore(&clockfw_lock, flags);
+       }
+
+       return 0;
+}
+late_initcall(clk_disable_unused);
+#endif
+
 int __init clk_init(struct clk_functions * custom_clocks)
 {
        if (!custom_clocks) {
index 1812f237d12f9f0327531d73db6b302356847339..dbc3f44e07a603f8b891c2901e1223a846dc34f1 100644 (file)
@@ -148,7 +148,7 @@ static inline void omap_init_kp(void) {}
 
 #ifdef CONFIG_ARCH_OMAP24XX
 #define        OMAP_MMC1_BASE          0x4809c000
-#define OMAP_MMC1_INT          83
+#define OMAP_MMC1_INT          INT_24XX_MMC_IRQ
 #else
 #define        OMAP_MMC1_BASE          0xfffb7800
 #define OMAP_MMC1_INT          INT_MMC
@@ -225,7 +225,14 @@ static void __init omap_init_mmc(void)
        /* block 1 is always available and has just one pinout option */
        mmc = &mmc_conf->mmc[0];
        if (mmc->enabled) {
-               if (!cpu_is_omap24xx()) {
+               if (cpu_is_omap24xx()) {
+                       omap_cfg_reg(H18_24XX_MMC_CMD);
+                       omap_cfg_reg(H15_24XX_MMC_CLKI);
+                       omap_cfg_reg(G19_24XX_MMC_CLKO);
+                       omap_cfg_reg(F20_24XX_MMC_DAT0);
+                       omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
+                       omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
+               } else {
                        omap_cfg_reg(MMC_CMD);
                        omap_cfg_reg(MMC_CLK);
                        omap_cfg_reg(MMC_DAT0);
@@ -236,7 +243,14 @@ static void __init omap_init_mmc(void)
                        }
                }
                if (mmc->wire4) {
-                       if (!cpu_is_omap24xx()) {
+                       if (cpu_is_omap24xx()) {
+                               omap_cfg_reg(H14_24XX_MMC_DAT1);
+                               omap_cfg_reg(E19_24XX_MMC_DAT2);
+                               omap_cfg_reg(D19_24XX_MMC_DAT3);
+                               omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
+                               omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
+                               omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
+                       } else {
                                omap_cfg_reg(MMC_DAT1);
                                /* NOTE:  DAT2 can be on W10 (here) or M15 */
                                if (!mmc->nomux)
index 9eddc9507147121a892291563dd4902eda322810..1bbb431843ce056ced668044bd5d71a43036a14e 100644 (file)
@@ -119,32 +119,41 @@ static void clear_lch_regs(int lch)
                omap_writew(0, lch_base + i);
 }
 
-void omap_set_dma_priority(int dst_port, int priority)
+void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
        unsigned long reg;
        u32 l;
 
-       switch (dst_port) {
-       case OMAP_DMA_PORT_OCP_T1:      /* FFFECC00 */
-               reg = OMAP_TC_OCPT1_PRIOR;
-               break;
-       case OMAP_DMA_PORT_OCP_T2:      /* FFFECCD0 */
-               reg = OMAP_TC_OCPT2_PRIOR;
-               break;
-       case OMAP_DMA_PORT_EMIFF:       /* FFFECC08 */
-               reg = OMAP_TC_EMIFF_PRIOR;
-               break;
-       case OMAP_DMA_PORT_EMIFS:       /* FFFECC04 */
-               reg = OMAP_TC_EMIFS_PRIOR;
-               break;
-       default:
-               BUG();
-               return;
+       if (cpu_class_is_omap1()) {
+               switch (dst_port) {
+               case OMAP_DMA_PORT_OCP_T1:      /* FFFECC00 */
+                       reg = OMAP_TC_OCPT1_PRIOR;
+                       break;
+               case OMAP_DMA_PORT_OCP_T2:      /* FFFECCD0 */
+                       reg = OMAP_TC_OCPT2_PRIOR;
+                       break;
+               case OMAP_DMA_PORT_EMIFF:       /* FFFECC08 */
+                       reg = OMAP_TC_EMIFF_PRIOR;
+                       break;
+               case OMAP_DMA_PORT_EMIFS:       /* FFFECC04 */
+                       reg = OMAP_TC_EMIFS_PRIOR;
+                       break;
+               default:
+                       BUG();
+                       return;
+               }
+               l = omap_readl(reg);
+               l &= ~(0xf << 8);
+               l |= (priority & 0xf) << 8;
+               omap_writel(l, reg);
+       }
+
+       if (cpu_is_omap24xx()) {
+               if (priority)
+                       OMAP_DMA_CCR_REG(lch) |= (1 << 6);
+               else
+                       OMAP_DMA_CCR_REG(lch) &= ~(1 << 6);
        }
-       l = omap_readl(reg);
-       l &= ~(0xf << 8);
-       l |= (priority & 0xf) << 8;
-       omap_writel(l, reg);
 }
 
 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
@@ -234,6 +243,14 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
        OMAP1_DMA_LCH_CTRL_REG(lch) = w;
 }
 
+void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
+{
+       if (cpu_is_omap24xx()) {
+               OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16);
+               OMAP_DMA_CSDP_REG(lch) |= (mode << 16);
+       }
+}
+
 /* Note that src_port is only for omap1 */
 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
                             unsigned long src_start,
@@ -697,6 +714,32 @@ void omap_stop_dma(int lch)
        dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
+/*
+ * Allows changing the DMA callback function or data. This may be needed if
+ * the driver shares a single DMA channel for multiple dma triggers.
+ */
+int omap_set_dma_callback(int lch,
+                         void (* callback)(int lch, u16 ch_status, void *data),
+                         void *data)
+{
+       unsigned long flags;
+
+       if (lch < 0)
+               return -ENODEV;
+
+       spin_lock_irqsave(&dma_chan_lock, flags);
+       if (dma_chan[lch].dev_id == -1) {
+               printk(KERN_ERR "DMA callback for not set for free channel\n");
+               spin_unlock_irqrestore(&dma_chan_lock, flags);
+               return -EINVAL;
+       }
+       dma_chan[lch].callback = callback;
+       dma_chan[lch].data = data;
+       spin_unlock_irqrestore(&dma_chan_lock, flags);
+
+       return 0;
+}
+
 /*
  * Returns current physical source address for the given DMA channel.
  * If the channel is running the caller must disable interrupts prior calling
@@ -1339,6 +1382,14 @@ static int __init omap_init_dma(void)
                        dma_chan_count = 16;
                } else
                        dma_chan_count = 9;
+               if (cpu_is_omap16xx()) {
+                       u16 w;
+
+                       /* this would prevent OMAP sleep */
+                       w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+                       w &= ~(1 << 8);
+                       omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+               }
        } else if (cpu_is_omap24xx()) {
                u8 revision = omap_readb(OMAP_DMA4_REVISION);
                printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
@@ -1414,11 +1465,13 @@ EXPORT_SYMBOL(omap_request_dma);
 EXPORT_SYMBOL(omap_free_dma);
 EXPORT_SYMBOL(omap_start_dma);
 EXPORT_SYMBOL(omap_stop_dma);
+EXPORT_SYMBOL(omap_set_dma_callback);
 EXPORT_SYMBOL(omap_enable_dma_irq);
 EXPORT_SYMBOL(omap_disable_dma_irq);
 
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 EXPORT_SYMBOL(omap_set_dma_color_mode);
+EXPORT_SYMBOL(omap_set_dma_write_mode);
 
 EXPORT_SYMBOL(omap_set_dma_src_params);
 EXPORT_SYMBOL(omap_set_dma_src_index);
index 50524436de63e8896764048ca813d510f5e9bebc..bcbb8d7392be6d5b5ca729b29a32439a1ba5331a 100644 (file)
@@ -75,10 +75,14 @@ struct omap_dm_timer {
 #endif
        void __iomem *io_base;
        unsigned reserved:1;
+       unsigned enabled:1;
 };
 
 #ifdef CONFIG_ARCH_OMAP1
 
+#define omap_dm_clk_enable(x)
+#define omap_dm_clk_disable(x)
+
 static struct omap_dm_timer dm_timers[] = {
        { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
        { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
@@ -92,6 +96,9 @@ static struct omap_dm_timer dm_timers[] = {
 
 #elif defined(CONFIG_ARCH_OMAP2)
 
+#define omap_dm_clk_enable(x) clk_enable(x)
+#define omap_dm_clk_disable(x) clk_disable(x)
+
 static struct omap_dm_timer dm_timers[] = {
        { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
        { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
@@ -154,24 +161,28 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
        u32 l;
 
-       if (timer != &dm_timers[0]) {
+       if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
                omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
                omap_dm_timer_wait_for_reset(timer);
        }
-       omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
+       omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
        /* Set to smart-idle mode */
        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
        l |= 0x02 << 3;
+
+       if (cpu_class_is_omap2() && timer == &dm_timers[0]) {
+               /* Enable wake-up only for GPT1 on OMAP2 CPUs*/
+               l |= 1 << 2;
+               /* Non-posted mode */
+               omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0);
+       }
        omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
 }
 
 static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-#ifdef CONFIG_ARCH_OMAP2
-       clk_enable(timer->iclk);
-       clk_enable(timer->fclk);
-#endif
+       omap_dm_timer_enable(timer);
        omap_dm_timer_reset(timer);
 }
 
@@ -223,15 +234,36 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 
 void omap_dm_timer_free(struct omap_dm_timer *timer)
 {
+       omap_dm_timer_enable(timer);
        omap_dm_timer_reset(timer);
-#ifdef CONFIG_ARCH_OMAP2
-       clk_disable(timer->iclk);
-       clk_disable(timer->fclk);
-#endif
+       omap_dm_timer_disable(timer);
+
        WARN_ON(!timer->reserved);
        timer->reserved = 0;
 }
 
+void omap_dm_timer_enable(struct omap_dm_timer *timer)
+{
+       if (timer->enabled)
+               return;
+
+       omap_dm_clk_enable(timer->fclk);
+       omap_dm_clk_enable(timer->iclk);
+
+       timer->enabled = 1;
+}
+
+void omap_dm_timer_disable(struct omap_dm_timer *timer)
+{
+       if (!timer->enabled)
+               return;
+
+       omap_dm_clk_disable(timer->iclk);
+       omap_dm_clk_disable(timer->fclk);
+
+       timer->enabled = 0;
+}
+
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
        return timer->irq;
@@ -276,7 +308,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-        return timer->fclk;
+       return timer->fclk;
 }
 
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
@@ -406,11 +438,16 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
                                  unsigned int value)
 {
        omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
 }
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
-       return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+       unsigned int l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+
+       return l;
 }
 
 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
@@ -420,12 +457,16 @@ void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-       return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+       unsigned int l;
+
+       l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+
+       return l;
 }
 
 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
-       return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
 }
 
 int omap_dm_timers_active(void)
@@ -436,9 +477,14 @@ int omap_dm_timers_active(void)
                struct omap_dm_timer *timer;
 
                timer = &dm_timers[i];
+
+               if (!timer->enabled)
+                       continue;
+
                if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
-                   OMAP_TIMER_CTRL_ST)
+                   OMAP_TIMER_CTRL_ST) {
                        return 1;
+               }
        }
        return 0;
 }
index cd7f973fb286618e23c1370dd56b532e9b5cbc15..f55f99ae58aea6ab07402c2562ab00b84ff8c38e 100644 (file)
@@ -94,6 +94,8 @@
 #define OMAP24XX_GPIO_SYSCONFIG                0x0010
 #define OMAP24XX_GPIO_SYSSTATUS                0x0014
 #define OMAP24XX_GPIO_IRQSTATUS1       0x0018
+#define OMAP24XX_GPIO_IRQSTATUS2       0x0028
+#define OMAP24XX_GPIO_IRQENABLE2       0x002c
 #define OMAP24XX_GPIO_IRQENABLE1       0x001c
 #define OMAP24XX_GPIO_CTRL             0x0030
 #define OMAP24XX_GPIO_OE               0x0034
 #define OMAP24XX_GPIO_CLEARDATAOUT     0x0090
 #define OMAP24XX_GPIO_SETDATAOUT       0x0094
 
-#define OMAP_MPUIO_MASK                (~OMAP_MAX_GPIO_LINES & 0xff)
-
 struct gpio_bank {
        void __iomem *base;
        u16 irq;
@@ -216,11 +216,13 @@ static inline int gpio_valid(int gpio)
 {
        if (gpio < 0)
                return -1;
+#ifndef CONFIG_ARCH_OMAP24XX
        if (OMAP_GPIO_IS_MPUIO(gpio)) {
-               if ((gpio & OMAP_MPUIO_MASK) > 16)
+               if (gpio >= OMAP_MAX_GPIO_LINES + 16)
                        return -1;
                return 0;
        }
+#endif
 #ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap15xx() && gpio < 16)
                return 0;
@@ -529,6 +531,10 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
                return;
        }
        __raw_writel(gpio_mask, reg);
+
+       /* Workaround for clearing DSP GPIO interrupts to allow retention */
+       if (cpu_is_omap2420())
+               __raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2);
 }
 
 static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
@@ -662,6 +668,14 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
        }
 }
 
+static void _reset_gpio(struct gpio_bank *bank, int gpio)
+{
+       _set_gpio_direction(bank, get_gpio_index(gpio), 1);
+       _set_gpio_irqenable(bank, gpio, 0);
+       _clear_gpio_irqstatus(bank, gpio);
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
+}
+
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int gpio_wake_enable(unsigned int irq, unsigned int enable)
 {
@@ -672,9 +686,7 @@ static int gpio_wake_enable(unsigned int irq, unsigned int enable)
        if (check_gpio(gpio) < 0)
                return -ENODEV;
        bank = get_gpio_bank(gpio);
-       spin_lock(&bank->lock);
        retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
-       spin_unlock(&bank->lock);
 
        return retval;
 }
@@ -696,7 +708,9 @@ int omap_request_gpio(int gpio)
        }
        bank->reserved_map |= (1 << get_gpio_index(gpio));
 
-       /* Set trigger to none. You need to enable the trigger after request_irq */
+       /* Set trigger to none. You need to enable the desired trigger with
+        * request_irq() or set_irq_type().
+        */
        _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -756,9 +770,7 @@ void omap_free_gpio(int gpio)
        }
 #endif
        bank->reserved_map &= ~(1 << get_gpio_index(gpio));
-       _set_gpio_direction(bank, get_gpio_index(gpio), 1);
-       _set_gpio_irqenable(bank, gpio, 0);
-       _clear_gpio_irqstatus(bank, gpio);
+       _reset_gpio(bank, gpio);
        spin_unlock(&bank->lock);
 }
 
@@ -898,6 +910,14 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
 
 }
 
+static void gpio_irq_shutdown(unsigned int irq)
+{
+       unsigned int gpio = irq - IH_GPIO_BASE;
+       struct gpio_bank *bank = get_gpio_bank(gpio);
+
+       _reset_gpio(bank, gpio);
+}
+
 static void gpio_ack_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
@@ -946,6 +966,7 @@ static void mpuio_unmask_irq(unsigned int irq)
 
 static struct irq_chip gpio_irq_chip = {
        .name           = "GPIO",
+       .shutdown       = gpio_irq_shutdown,
        .ack            = gpio_ack_irq,
        .mask           = gpio_mask_irq,
        .unmask         = gpio_unmask_irq,
@@ -985,7 +1006,7 @@ static int __init _omap_gpio_init(void)
                else
                        clk_enable(gpio_ick);
                gpio_fck = clk_get(NULL, "gpios_fck");
-               if (IS_ERR(gpio_ick))
+               if (IS_ERR(gpio_fck))
                        printk("Could not get gpios_fck\n");
                else
                        clk_enable(gpio_fck);
@@ -1144,8 +1165,8 @@ static int omap_gpio_resume(struct sys_device *dev)
                        wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
                        break;
                case METHOD_GPIO_24XX:
-                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+                       wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+                       wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
                        break;
                default:
                        continue;
index 196aac3ac329aad9df2eeb5bd4867eec89dd0c03..ade9a0fa6ef678033ff2f17f6dd8446389e7ae21 100644 (file)
@@ -75,8 +75,6 @@ static struct clk *mcbsp1_ick = 0;
 static struct clk *mcbsp1_fck = 0;
 static struct clk *mcbsp2_ick = 0;
 static struct clk *mcbsp2_fck = 0;
-static struct clk *sys_ck = 0;
-static struct clk *sys_clkout = 0;
 #endif
 
 static void omap_mcbsp_dump_reg(u8 id)
@@ -232,7 +230,6 @@ static void omap2_mcbsp2_mux_setup(void)
        omap_cfg_reg(W15_24XX_MCBSP2_DR);
        omap_cfg_reg(V15_24XX_MCBSP2_DX);
        omap_cfg_reg(V14_24XX_GPIO117);
-       omap_cfg_reg(W14_24XX_SYS_CLKOUT);
 }
 #endif
 
@@ -984,13 +981,7 @@ static int __init omap_mcbsp_init(void)
        if (cpu_is_omap24xx()) {
                mcbsp_info = mcbsp_24xx;
                mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
-
-               /* REVISIT: where's the right place? */
                omap2_mcbsp2_mux_setup();
-               sys_ck = clk_get(0, "sys_ck");
-               sys_clkout = clk_get(0, "sys_clkout");
-               clk_set_parent(sys_clkout, sys_ck);
-               clk_enable(sys_clkout);
        }
 #endif
        for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
deleted file mode 100644 (file)
index 04b4102..0000000
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/pm.c
- *
- * OMAP Power Management Routines
- *
- * Original code for the SA11x0:
- * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
- *
- * Modified for the PXA250 by Nicolas Pitre:
- * Copyright (c) 2002 Monta Vista Software, Inc.
- *
- * Modified for the OMAP1510 by David Singleton:
- * Copyright (c) 2002 Monta Vista Software, Inc.
- *
- * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/pm.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/pm.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-
-#include <asm/mach-types.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/tc.h>
-#include <asm/arch/pm.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/tps65010.h>
-#include <asm/arch/dsp_common.h>
-
-#include <asm/arch/clock.h>
-#include <asm/arch/sram.h>
-
-static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
-static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
-static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
-static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
-static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
-
-static void (*omap_sram_idle)(void) = NULL;
-static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
-
-/*
- * Let's power down on idle, but only if we are really
- * idle, because once we start down the path of
- * going idle we continue to do idle even if we get
- * a clock tick interrupt . .
- */
-void omap_pm_idle(void)
-{
-       unsigned int mask32 = 0;
-
-       /*
-        * If the DSP is being used let's just idle the CPU, the overhead
-        * to wake up from Big Sleep is big, milliseconds versus micro
-        * seconds for wait for interrupt.
-        */
-
-       local_irq_disable();
-       local_fiq_disable();
-       if (need_resched()) {
-               local_fiq_enable();
-               local_irq_enable();
-               return;
-       }
-       mask32 = omap_readl(ARM_SYSST);
-
-       /*
-        * Prevent the ULPD from entering low power state by setting
-        * POWER_CTRL_REG:4 = 0
-        */
-       omap_writew(omap_readw(ULPD_POWER_CTRL) &
-                   ~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL);
-
-       /*
-        * Since an interrupt may set up a timer, we don't want to
-        * reprogram the hardware timer with interrupts enabled.
-        * Re-enable interrupts only after returning from idle.
-        */
-       timer_dyn_reprogram();
-
-       if ((mask32 & DSP_IDLE) == 0) {
-               __asm__ volatile ("mcr  p15, 0, r0, c7, c0, 4");
-       } else
-               omap_sram_idle();
-
-       local_fiq_enable();
-       local_irq_enable();
-}
-
-/*
- * Configuration of the wakeup event is board specific. For the
- * moment we put it into this helper function. Later it may move
- * to board specific files.
- */
-static void omap_pm_wakeup_setup(void)
-{
-       u32 level1_wake = 0;
-       u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
-
-       /*
-        * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
-        * and the L2 wakeup interrupts: keypad and UART2. Note that the
-        * drivers must still separately call omap_set_gpio_wakeup() to
-        * wake up to a GPIO interrupt.
-        */
-       if (cpu_is_omap730())
-               level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
-                       OMAP_IRQ_BIT(INT_730_IH2_IRQ);
-       else if (cpu_is_omap1510())
-               level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
-                       OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
-       else if (cpu_is_omap16xx())
-               level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
-                       OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
-
-       omap_writel(~level1_wake, OMAP_IH1_MIR);
-
-       if (cpu_is_omap730()) {
-               omap_writel(~level2_wake, OMAP_IH2_0_MIR);
-               omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), OMAP_IH2_1_MIR);
-       } else if (cpu_is_omap1510()) {
-               level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
-               omap_writel(~level2_wake,  OMAP_IH2_MIR);
-       } else if (cpu_is_omap16xx()) {
-               level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
-               omap_writel(~level2_wake, OMAP_IH2_0_MIR);
-
-               /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
-               omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
-               omap_writel(~0x0, OMAP_IH2_2_MIR);
-               omap_writel(~0x0, OMAP_IH2_3_MIR);
-       }
-
-       /*  New IRQ agreement, recalculate in cascade order */
-       omap_writel(1, OMAP_IH2_CONTROL);
-       omap_writel(1, OMAP_IH1_CONTROL);
-}
-
-void omap_pm_suspend(void)
-{
-       unsigned long arg0 = 0, arg1 = 0;
-
-       printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
-
-       omap_serial_wake_trigger(1);
-
-       if (machine_is_omap_osk()) {
-               /* Stop LED1 (D9) blink */
-               tps65010_set_led(LED1, OFF);
-       }
-
-       omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
-
-       /*
-        * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
-        */
-
-       local_irq_disable();
-       local_fiq_disable();
-
-       /*
-        * Step 2: save registers
-        *
-        * The omap is a strange/beautiful device. The caches, memory
-        * and register state are preserved across power saves.
-        * We have to save and restore very little register state to
-        * idle the omap.
-         *
-        * Save interrupt, MPUI, ARM and UPLD control registers.
-        */
-
-       if (cpu_is_omap730()) {
-               MPUI730_SAVE(OMAP_IH1_MIR);
-               MPUI730_SAVE(OMAP_IH2_0_MIR);
-               MPUI730_SAVE(OMAP_IH2_1_MIR);
-               MPUI730_SAVE(MPUI_CTRL);
-               MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
-               MPUI730_SAVE(MPUI_DSP_API_CONFIG);
-               MPUI730_SAVE(EMIFS_CONFIG);
-               MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
-
-       } else if (cpu_is_omap1510()) {
-               MPUI1510_SAVE(OMAP_IH1_MIR);
-               MPUI1510_SAVE(OMAP_IH2_MIR);
-               MPUI1510_SAVE(MPUI_CTRL);
-               MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
-               MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
-               MPUI1510_SAVE(EMIFS_CONFIG);
-               MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
-       } else if (cpu_is_omap16xx()) {
-               MPUI1610_SAVE(OMAP_IH1_MIR);
-               MPUI1610_SAVE(OMAP_IH2_0_MIR);
-               MPUI1610_SAVE(OMAP_IH2_1_MIR);
-               MPUI1610_SAVE(OMAP_IH2_2_MIR);
-               MPUI1610_SAVE(OMAP_IH2_3_MIR);
-               MPUI1610_SAVE(MPUI_CTRL);
-               MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
-               MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
-               MPUI1610_SAVE(EMIFS_CONFIG);
-               MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
-       }
-
-       ARM_SAVE(ARM_CKCTL);
-       ARM_SAVE(ARM_IDLECT1);
-       ARM_SAVE(ARM_IDLECT2);
-       if (!(cpu_is_omap1510()))
-               ARM_SAVE(ARM_IDLECT3);
-       ARM_SAVE(ARM_EWUPCT);
-       ARM_SAVE(ARM_RSTCT1);
-       ARM_SAVE(ARM_RSTCT2);
-       ARM_SAVE(ARM_SYSST);
-       ULPD_SAVE(ULPD_CLOCK_CTRL);
-       ULPD_SAVE(ULPD_STATUS_REQ);
-
-       /* (Step 3 removed - we now allow deep sleep by default) */
-
-       /*
-        * Step 4: OMAP DSP Shutdown
-        */
-
-
-       /*
-        * Step 5: Wakeup Event Setup
-        */
-
-       omap_pm_wakeup_setup();
-
-       /*
-        * Step 6: ARM and Traffic controller shutdown
-        */
-
-       /* disable ARM watchdog */
-       omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
-       omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
-
-       /*
-        * Step 6b: ARM and Traffic controller shutdown
-        *
-        * Step 6 continues here. Prepare jump to power management
-        * assembly code in internal SRAM.
-        *
-        * Since the omap_cpu_suspend routine has been copied to
-        * SRAM, we'll do an indirect procedure call to it and pass the
-        * contents of arm_idlect1 and arm_idlect2 so it can restore
-        * them when it wakes up and it will return.
-        */
-
-       arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
-       arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
-
-       /*
-        * Step 6c: ARM and Traffic controller shutdown
-        *
-        * Jump to assembly code. The processor will stay there
-        * until wake up.
-        */
-        omap_sram_suspend(arg0, arg1);
-
-       /*
-        * If we are here, processor is woken up!
-        */
-
-       /*
-        * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
-        */
-
-       if (!(cpu_is_omap1510()))
-               ARM_RESTORE(ARM_IDLECT3);
-       ARM_RESTORE(ARM_CKCTL);
-       ARM_RESTORE(ARM_EWUPCT);
-       ARM_RESTORE(ARM_RSTCT1);
-       ARM_RESTORE(ARM_RSTCT2);
-       ARM_RESTORE(ARM_SYSST);
-       ULPD_RESTORE(ULPD_CLOCK_CTRL);
-       ULPD_RESTORE(ULPD_STATUS_REQ);
-
-       if (cpu_is_omap730()) {
-               MPUI730_RESTORE(EMIFS_CONFIG);
-               MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
-               MPUI730_RESTORE(OMAP_IH1_MIR);
-               MPUI730_RESTORE(OMAP_IH2_0_MIR);
-               MPUI730_RESTORE(OMAP_IH2_1_MIR);
-       } else if (cpu_is_omap1510()) {
-               MPUI1510_RESTORE(MPUI_CTRL);
-               MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
-               MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
-               MPUI1510_RESTORE(EMIFS_CONFIG);
-               MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
-               MPUI1510_RESTORE(OMAP_IH1_MIR);
-               MPUI1510_RESTORE(OMAP_IH2_MIR);
-       } else if (cpu_is_omap16xx()) {
-               MPUI1610_RESTORE(MPUI_CTRL);
-               MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
-               MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
-               MPUI1610_RESTORE(EMIFS_CONFIG);
-               MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
-
-               MPUI1610_RESTORE(OMAP_IH1_MIR);
-               MPUI1610_RESTORE(OMAP_IH2_0_MIR);
-               MPUI1610_RESTORE(OMAP_IH2_1_MIR);
-               MPUI1610_RESTORE(OMAP_IH2_2_MIR);
-               MPUI1610_RESTORE(OMAP_IH2_3_MIR);
-       }
-
-       omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
-
-       /*
-        * Reenable interrupts
-        */
-
-       local_irq_enable();
-       local_fiq_enable();
-
-       omap_serial_wake_trigger(0);
-
-       printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
-
-       if (machine_is_omap_osk()) {
-               /* Let LED1 (D9) blink again */
-               tps65010_set_led(LED1, BLINK);
-       }
-}
-
-#if defined(DEBUG) && defined(CONFIG_PROC_FS)
-static int g_read_completed;
-
-/*
- * Read system PM registers for debugging
- */
-static int omap_pm_read_proc(
-       char *page_buffer,
-       char **my_first_byte,
-       off_t virtual_start,
-       int length,
-       int *eof,
-       void *data)
-{
-       int my_buffer_offset = 0;
-       char * const my_base = page_buffer;
-
-       ARM_SAVE(ARM_CKCTL);
-       ARM_SAVE(ARM_IDLECT1);
-       ARM_SAVE(ARM_IDLECT2);
-       if (!(cpu_is_omap1510()))
-               ARM_SAVE(ARM_IDLECT3);
-       ARM_SAVE(ARM_EWUPCT);
-       ARM_SAVE(ARM_RSTCT1);
-       ARM_SAVE(ARM_RSTCT2);
-       ARM_SAVE(ARM_SYSST);
-
-       ULPD_SAVE(ULPD_IT_STATUS);
-       ULPD_SAVE(ULPD_CLOCK_CTRL);
-       ULPD_SAVE(ULPD_SOFT_REQ);
-       ULPD_SAVE(ULPD_STATUS_REQ);
-       ULPD_SAVE(ULPD_DPLL_CTRL);
-       ULPD_SAVE(ULPD_POWER_CTRL);
-
-       if (cpu_is_omap730()) {
-               MPUI730_SAVE(MPUI_CTRL);
-               MPUI730_SAVE(MPUI_DSP_STATUS);
-               MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
-               MPUI730_SAVE(MPUI_DSP_API_CONFIG);
-               MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
-               MPUI730_SAVE(EMIFS_CONFIG);
-       } else if (cpu_is_omap1510()) {
-               MPUI1510_SAVE(MPUI_CTRL);
-               MPUI1510_SAVE(MPUI_DSP_STATUS);
-               MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
-               MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
-               MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
-               MPUI1510_SAVE(EMIFS_CONFIG);
-       } else if (cpu_is_omap16xx()) {
-               MPUI1610_SAVE(MPUI_CTRL);
-               MPUI1610_SAVE(MPUI_DSP_STATUS);
-               MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
-               MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
-               MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
-               MPUI1610_SAVE(EMIFS_CONFIG);
-       }
-
-       if (virtual_start == 0) {
-               g_read_completed = 0;
-
-               my_buffer_offset += sprintf(my_base + my_buffer_offset,
-                  "ARM_CKCTL_REG:            0x%-8x     \n"
-                  "ARM_IDLECT1_REG:          0x%-8x     \n"
-                  "ARM_IDLECT2_REG:          0x%-8x     \n"
-                  "ARM_IDLECT3_REG:          0x%-8x     \n"
-                  "ARM_EWUPCT_REG:           0x%-8x     \n"
-                  "ARM_RSTCT1_REG:           0x%-8x     \n"
-                  "ARM_RSTCT2_REG:           0x%-8x     \n"
-                  "ARM_SYSST_REG:            0x%-8x     \n"
-                  "ULPD_IT_STATUS_REG:       0x%-4x     \n"
-                  "ULPD_CLOCK_CTRL_REG:      0x%-4x     \n"
-                  "ULPD_SOFT_REQ_REG:        0x%-4x     \n"
-                  "ULPD_DPLL_CTRL_REG:       0x%-4x     \n"
-                  "ULPD_STATUS_REQ_REG:      0x%-4x     \n"
-                  "ULPD_POWER_CTRL_REG:      0x%-4x     \n",
-                  ARM_SHOW(ARM_CKCTL),
-                  ARM_SHOW(ARM_IDLECT1),
-                  ARM_SHOW(ARM_IDLECT2),
-                  ARM_SHOW(ARM_IDLECT3),
-                  ARM_SHOW(ARM_EWUPCT),
-                  ARM_SHOW(ARM_RSTCT1),
-                  ARM_SHOW(ARM_RSTCT2),
-                  ARM_SHOW(ARM_SYSST),
-                  ULPD_SHOW(ULPD_IT_STATUS),
-                  ULPD_SHOW(ULPD_CLOCK_CTRL),
-                  ULPD_SHOW(ULPD_SOFT_REQ),
-                  ULPD_SHOW(ULPD_DPLL_CTRL),
-                  ULPD_SHOW(ULPD_STATUS_REQ),
-                  ULPD_SHOW(ULPD_POWER_CTRL));
-
-               if (cpu_is_omap730()) {
-                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
-                          "MPUI730_CTRL_REG         0x%-8x \n"
-                          "MPUI730_DSP_STATUS_REG:      0x%-8x \n"
-                          "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
-        "MPUI730_DSP_API_CONFIG_REG:  0x%-8x \n"
-        "MPUI730_SDRAM_CONFIG_REG:    0x%-8x \n"
-        "MPUI730_EMIFS_CONFIG_REG:    0x%-8x \n",
-        MPUI730_SHOW(MPUI_CTRL),
-        MPUI730_SHOW(MPUI_DSP_STATUS),
-        MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
-        MPUI730_SHOW(MPUI_DSP_API_CONFIG),
-        MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
-        MPUI730_SHOW(EMIFS_CONFIG));
-               } else if (cpu_is_omap1510()) {
-                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
-                          "MPUI1510_CTRL_REG             0x%-8x \n"
-                          "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
-                          "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
-                          "MPUI1510_DSP_API_CONFIG_REG:  0x%-8x \n"
-                          "MPUI1510_SDRAM_CONFIG_REG:    0x%-8x \n"
-                          "MPUI1510_EMIFS_CONFIG_REG:    0x%-8x \n",
-                          MPUI1510_SHOW(MPUI_CTRL),
-                          MPUI1510_SHOW(MPUI_DSP_STATUS),
-                          MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
-                          MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
-                          MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
-                          MPUI1510_SHOW(EMIFS_CONFIG));
-               } else if (cpu_is_omap16xx()) {
-                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
-                          "MPUI1610_CTRL_REG             0x%-8x \n"
-                          "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
-                          "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
-                          "MPUI1610_DSP_API_CONFIG_REG:  0x%-8x \n"
-                          "MPUI1610_SDRAM_CONFIG_REG:    0x%-8x \n"
-                          "MPUI1610_EMIFS_CONFIG_REG:    0x%-8x \n",
-                          MPUI1610_SHOW(MPUI_CTRL),
-                          MPUI1610_SHOW(MPUI_DSP_STATUS),
-                          MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
-                          MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
-                          MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
-                          MPUI1610_SHOW(EMIFS_CONFIG));
-               }
-
-               g_read_completed++;
-       } else if (g_read_completed >= 1) {
-                *eof = 1;
-                return 0;
-       }
-       g_read_completed++;
-
-       *my_first_byte = page_buffer;
-       return  my_buffer_offset;
-}
-
-static void omap_pm_init_proc(void)
-{
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_read_entry("driver/omap_pm",
-                                      S_IWUSR | S_IRUGO, NULL,
-          omap_pm_read_proc, NULL);
-}
-
-#endif /* DEBUG && CONFIG_PROC_FS */
-
-/*
- *     omap_pm_prepare - Do preliminary suspend work.
- *     @state:         suspend state we're entering.
- *
- */
-//#include <asm/hardware.h>
-
-static int omap_pm_prepare(suspend_state_t state)
-{
-       int error = 0;
-
-       switch (state)
-       {
-       case PM_SUSPEND_STANDBY:
-       case PM_SUSPEND_MEM:
-               break;
-
-       case PM_SUSPEND_DISK:
-               return -ENOTSUPP;
-
-       default:
-               return -EINVAL;
-       }
-
-       return error;
-}
-
-
-/*
- *     omap_pm_enter - Actually enter a sleep state.
- *     @state:         State we're entering.
- *
- */
-
-static int omap_pm_enter(suspend_state_t state)
-{
-       switch (state)
-       {
-       case PM_SUSPEND_STANDBY:
-       case PM_SUSPEND_MEM:
-               omap_pm_suspend();
-               break;
-
-       case PM_SUSPEND_DISK:
-               return -ENOTSUPP;
-
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-
-/**
- *     omap_pm_finish - Finish up suspend sequence.
- *     @state:         State we're coming out of.
- *
- *     This is called after we wake back up (or if entering the sleep state
- *     failed).
- */
-
-static int omap_pm_finish(suspend_state_t state)
-{
-       return 0;
-}
-
-
-static irqreturn_t  omap_wakeup_interrupt(int  irq, void *  dev,
-                                    struct pt_regs *  regs)
-{
-       return IRQ_HANDLED;
-}
-
-static struct irqaction omap_wakeup_irq = {
-       .name           = "peripheral wakeup",
-       .flags          = IRQF_DISABLED,
-       .handler        = omap_wakeup_interrupt
-};
-
-
-
-static struct pm_ops omap_pm_ops ={
-       .pm_disk_mode = 0,
-        .prepare        = omap_pm_prepare,
-        .enter          = omap_pm_enter,
-        .finish         = omap_pm_finish,
-};
-
-static int __init omap_pm_init(void)
-{
-       printk("Power Management for TI OMAP.\n");
-       /*
-        * We copy the assembler sleep/wakeup routines to SRAM.
-        * These routines need to be in SRAM as that's the only
-        * memory the MPU can see when it wakes up.
-        */
-       if (cpu_is_omap730()) {
-               omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
-                                               omap730_idle_loop_suspend_sz);
-               omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
-        omap730_cpu_suspend_sz);
-       } else if (cpu_is_omap1510()) {
-               omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
-                                               omap1510_idle_loop_suspend_sz);
-               omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
-                                                  omap1510_cpu_suspend_sz);
-       } else if (cpu_is_omap16xx()) {
-               omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
-                                               omap1610_idle_loop_suspend_sz);
-               omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
-                                                  omap1610_cpu_suspend_sz);
-       }
-
-       if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
-               printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
-               return -ENODEV;
-       }
-
-       pm_idle = omap_pm_idle;
-
-       if (cpu_is_omap730())
-               setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
-       else if (cpu_is_omap16xx())
-               setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
-
-#if 0
-       /* --- BEGIN BOARD-DEPENDENT CODE --- */
-       /* Sleepx mask direction */
-       omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
-       /* Unmask sleepx signal */
-       omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
-       /* --- END BOARD-DEPENDENT CODE --- */
-#endif
-
-       /* Program new power ramp-up time
-        * (0 for most boards since we don't lower voltage when in deep sleep)
-        */
-       omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
-
-       /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
-       omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
-
-       /* Configure IDLECT3 */
-       if (cpu_is_omap730())
-               omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
-       else if (cpu_is_omap16xx())
-               omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
-
-       pm_set_ops(&omap_pm_ops);
-
-#if defined(DEBUG) && defined(CONFIG_PROC_FS)
-       omap_pm_init_proc();
-#endif
-
-       if (cpu_is_omap16xx()) {
-               /* configure LOW_PWR pin */
-               omap_cfg_reg(T20_1610_LOW_PWR);
-       }
-
-       return 0;
-}
-__initcall(omap_pm_init);
-
index e75718301b0f460bc59ea9912905a5c0a34c6dc8..19014b2ff4c6315a6e190c3c2c03e17c33eb184b 100644 (file)
@@ -174,10 +174,7 @@ void __init omap_map_sram(void)
        if (cpu_is_omap24xx()) {
                omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
 
-               if (is_sram_locked())
-                       base = OMAP2_SRAM_PUB_PA;
-               else
-                       base = OMAP2_SRAM_PA;
+               base = OMAP2_SRAM_PA;
                base = ROUND_DOWN(base, PAGE_SIZE);
                omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
        }
index 281ecc7fcdfcc995e90fe94f3e9c1b2b345ed2e1..cf6df3378d3786d3bcaa2876f770b70db46cc6ca 100644 (file)
@@ -105,6 +105,8 @@ static inline unsigned long omap_32k_timer_read(int reg)
 
 static inline void omap_32k_timer_start(unsigned long load_val)
 {
+       if (!load_val)
+               load_val = 1;
        omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
        omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
 }
@@ -192,14 +194,11 @@ unsigned long long sched_clock(void)
  * issues with dynamic tick. In the dynamic tick case, we need to lock
  * with irqsave.
  */
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
-                                           struct pt_regs *regs)
+static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id,
+                                       struct pt_regs *regs)
 {
-       unsigned long flags;
        unsigned long now;
 
-       write_seqlock_irqsave(&xtime_lock, flags);
-
        omap_32k_timer_ack_irq();
        now = omap_32k_sync_timer_read();
 
@@ -215,6 +214,23 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
         * continuous timer can be overridden from pm_idle to be longer.
         */
        omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id,
+                                       struct pt_regs *regs)
+{
+       return _omap_32k_timer_interrupt(irq, dev_id, regs);
+}
+
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+                                           struct pt_regs *regs)
+{
+       unsigned long flags;
+
+       write_seqlock_irqsave(&xtime_lock, flags);
+       _omap_32k_timer_interrupt(irq, dev_id, regs);
        write_sequnlock_irqrestore(&xtime_lock, flags);
 
        return IRQ_HANDLED;
@@ -230,7 +246,15 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
  */
 void omap_32k_timer_reprogram(unsigned long next_tick)
 {
-       omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+       unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1;
+       unsigned long now = omap_32k_sync_timer_read();
+       unsigned long idled = now - omap_32k_last_tick;
+
+       if (idled + 1 < ticks)
+               ticks -= idled;
+       else
+               ticks = 1;
+       omap_32k_timer_start(ticks);
 }
 
 static struct irqaction omap_32k_timer_irq;
@@ -252,7 +276,7 @@ static struct dyn_tick_timer omap_dyn_tick_timer = {
        .enable         = omap_32k_timer_enable_dyn_tick,
        .disable        = omap_32k_timer_disable_dyn_tick,
        .reprogram      = omap_32k_timer_reprogram,
-       .handler        = omap_32k_timer_interrupt,
+       .handler        = omap_32k_timer_handler,
 };
 #endif /* CONFIG_NO_IDLE_HZ */
 
index 9b815327b6a58f2c23db3100a909fab29884ac5b..7e8096809be2bc227ef4e8acb310455a92d8cbfb 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
index e1372a25311d0ab1ec7f0996b64deb1278afc737..b02af1d740fab56b1f28c7525f7ac97f3006829f 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Jun 26 22:26:08 2006
+# Last update: Sat Sep 23 13:20:43 2006
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -329,7 +329,7 @@ nimbra29x           ARCH_NIMBRA29X          NIMBRA29X               311
 nimbra210              ARCH_NIMBRA210          NIMBRA210               312
 hhp_d95xx              ARCH_HHP_D95XX          HHP_D95XX               313
 labarm                 ARCH_LABARM             LABARM                  314
-comcerto               ARCH_M825XX             M825XX                  315
+m825xx                 ARCH_M825XX             M825XX                  315
 m7100                  SA1100_M7100            M7100                   316
 nipc2                  ARCH_NIPC2              NIPC2                   317
 fu7202                 ARCH_FU7202             FU7202                  318
@@ -857,12 +857,12 @@ osiris                    MACH_OSIRIS             OSIRIS                  842
 maestro                        MACH_MAESTRO            MAESTRO                 843
 tunge2                 MACH_TUNGE2             TUNGE2                  844
 ixbbm                  MACH_IXBBM              IXBBM                   845
-mx27ads                        MACH_MX27               MX27                    846
+mx27ads                        MACH_MX27ADS            MX27ADS                 846
 ax8004                 MACH_AX8004             AX8004                  847
 at91sam9261ek          MACH_AT91SAM9261EK      AT91SAM9261EK           848
 loft                   MACH_LOFT               LOFT                    849
 magpie                 MACH_MAGPIE             MAGPIE                  850
-mx21ads                        MACH_MX21               MX21                    851
+mx21ads                        MACH_MX21ADS            MX21ADS                 851
 mb87m3400              MACH_MB87M3400          MB87M3400               852
 mguard_delta           MACH_MGUARD_DELTA       MGUARD_DELTA            853
 davinci_dvdp           MACH_DAVINCI_DVDP       DAVINCI_DVDP            854
@@ -1058,7 +1058,7 @@ akai9307          MACH_AKAI9307           AKAI9307                1044
 fontaine               MACH_FONTAINE           FONTAINE                1045
 wombat                 MACH_WOMBAT             WOMBAT                  1046
 acq300                 MACH_ACQ300             ACQ300                  1047
-mod_270                        MACH_MOD_270            MOD_270                 1048
+mod272                 MACH_MOD_270            MOD_270                 1048
 vmc_vc0820             MACH_VC0820             VC0820                  1049
 ani_aim                        MACH_ANI_AIM            ANI_AIM                 1050
 jellyfish              MACH_JELLYFISH          JELLYFISH               1051
@@ -1093,3 +1093,67 @@ msm6100                  MACH_MSM6100            MSM6100                 1079
 eti_b1                 MACH_ETI_B1             ETI_B1                  1080
 za9l_series            MACH_ZILOG_ZA9L         ZILOG_ZA9L              1081
 bit2440                        MACH_BIT2440            BIT2440                 1082
+nbi                    MACH_NBI                NBI                     1083
+smdk2443               MACH_SMDK2443           SMDK2443                1084
+vdavinci               MACH_VDAVINCI           VDAVINCI                1085
+atc6                   MACH_ATC6               ATC6                    1086
+multmdw                        MACH_MULTMDW            MULTMDW                 1087
+mba2440                        MACH_MBA2440            MBA2440                 1088
+ecsd                   MACH_ECSD               ECSD                    1089
+zire31                 MACH_ZIRE31             ZIRE31                  1090
+fsg                    MACH_FSG                FSG                     1091
+razor101               MACH_RAZOR101           RAZOR101                1092
+opera_tdm              MACH_OPERA_TDM          OPERA_TDM               1093
+comcerto               MACH_COMCERTO           COMCERTO                1094
+tb0319                 MACH_TB0319             TB0319                  1095
+kws8000                        MACH_KWS8000            KWS8000                 1096
+b2                     MACH_B2                 B2                      1097
+lcl54                  MACH_LCL54              LCL54                   1098
+at91sam9260ek          MACH_AT91SAM9260EK      AT91SAM9260EK           1099
+glantank               MACH_GLANTANK           GLANTANK                1100
+n2100                  MACH_N2100              N2100                   1101
+n4100                  MACH_N4100              N4100                   1102
+rsc4                   MACH_VERTICAL_RSC4      VERTICAL_RSC4           1103
+sg8100                 MACH_SG8100             SG8100                  1104
+im42xx                 MACH_IM42XX             IM42XX                  1105
+ftxx                   MACH_FTXX               FTXX                    1106
+lwfusion               MACH_LWFUSION           LWFUSION                1107
+qt2410                 MACH_QT2410             QT2410                  1108
+kixrp435               MACH_KIXRP435           KIXRP435                1109
+ccw9c                  MACH_CCW9C              CCW9C                   1110
+dabhs                  MACH_DABHS              DABHS                   1111
+gzmx                   MACH_GZMX               GZMX                    1112
+ipnw100ap              MACH_IPNW100AP          IPNW100AP               1113
+cc9p9360dev            MACH_CC9P9360DEV        CC9P9360DEV             1114
+cc9p9750dev            MACH_CC9P9750DEV        CC9P9750DEV             1115
+cc9p9360val            MACH_CC9P9360VAL        CC9P9360VAL             1116
+cc9p9750val            MACH_CC9P9750VAL        CC9P9750VAL             1117
+nx70v                  MACH_NX70V              NX70V                   1118
+at91rm9200df           MACH_AT91RM9200DF       AT91RM9200DF            1119
+se_pilot2              MACH_SE_PILOT2          SE_PILOT2               1120
+mtcn_t800              MACH_MTCN_T800          MTCN_T800               1121
+vcmx212                        MACH_VCMX212            VCMX212                 1122
+lynx                   MACH_LYNX               LYNX                    1123
+at91sam9260id          MACH_AT91SAM9260ID      AT91SAM9260ID           1124
+hw86052                        MACH_HW86052            HW86052                 1125
+pilz_pmi3              MACH_PILZ_PMI3          PILZ_PMI3               1126
+edb9302a               MACH_EDB9302A           EDB9302A                1127
+edb9307a               MACH_EDB9307A           EDB9307A                1128
+ct_dfs                 MACH_CT_DFS             CT_DFS                  1129
+pilz_pmi4              MACH_PILZ_PMI4          PILZ_PMI4               1130
+xceednp_ixp            MACH_XCEEDNP_IXP        XCEEDNP_IXP             1131
+smdk2442b              MACH_SMDK2442B          SMDK2442B               1132
+xnode                  MACH_XNODE              XNODE                   1133
+aidx270                        MACH_AIDX270            AIDX270                 1134
+rema                   MACH_REMA               REMA                    1135
+bps1000                        MACH_BPS1000            BPS1000                 1136
+hw90350                        MACH_HW90350            HW90350                 1137
+omap_sdp3430           MACH_OMAP_SDP3430       OMAP_SDP3430            1138
+bluetouch              MACH_BLUETOUCH          BLUETOUCH               1139
+vstms                  MACH_VSTMS              VSTMS                   1140
+xsbase270              MACH_XSBASE270          XSBASE270               1141
+at91sam9260ek_cn       MACH_AT91SAM9260EK_CN   AT91SAM9260EK_CN        1142
+adsturboxb             MACH_ADSTURBOXB         ADSTURBOXB              1143
+oti4110                        MACH_OTI4110            OTI4110                 1144
+hme_pxa                        MACH_HME_PXA            HME_PXA                 1145
+deisterdca             MACH_DEISTERDCA         DEISTERDCA              1146
index 96fdf30f6a3bb2098a39c5907ea89cd983a95b90..f2797896e6d5dbcc488f5c9b0be9f1ce497d7843 100644 (file)
@@ -355,3 +355,18 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
  * we check for an error.
  */
 #define VFP_EXCEPTION_ERROR    ((u32)-1 & ~VFP_NAN_FLAG)
+
+/*
+ * A flag to tell vfp instruction type.
+ *  OP_SCALAR - this operation always operates in scalar mode
+ *  OP_SD - the instruction exceptionally writes to a single precision result.
+ *  OP_DD - the instruction exceptionally writes to a double precision result.
+ */
+#define OP_SCALAR      (1 << 0)
+#define OP_SD          (1 << 1)
+#define OP_DD          (1 << 1)
+
+struct op {
+       u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
+       u32 flags;
+};
index add48e36c2dc2e36ead54cb031e2f6bd84cf3460..4fc05ee0a2ef3c5b04db9d81993b450892b33660 100644 (file)
@@ -659,22 +659,22 @@ static u32 vfp_double_ftosiz(int dd, int unused, int dm, u32 fpscr)
 }
 
 
-static u32 (* const fop_extfns[32])(int dd, int unused, int dm, u32 fpscr) = {
-       [FEXT_TO_IDX(FEXT_FCPY)]        = vfp_double_fcpy,
-       [FEXT_TO_IDX(FEXT_FABS)]        = vfp_double_fabs,
-       [FEXT_TO_IDX(FEXT_FNEG)]        = vfp_double_fneg,
-       [FEXT_TO_IDX(FEXT_FSQRT)]       = vfp_double_fsqrt,
-       [FEXT_TO_IDX(FEXT_FCMP)]        = vfp_double_fcmp,
-       [FEXT_TO_IDX(FEXT_FCMPE)]       = vfp_double_fcmpe,
-       [FEXT_TO_IDX(FEXT_FCMPZ)]       = vfp_double_fcmpz,
-       [FEXT_TO_IDX(FEXT_FCMPEZ)]      = vfp_double_fcmpez,
-       [FEXT_TO_IDX(FEXT_FCVT)]        = vfp_double_fcvts,
-       [FEXT_TO_IDX(FEXT_FUITO)]       = vfp_double_fuito,
-       [FEXT_TO_IDX(FEXT_FSITO)]       = vfp_double_fsito,
-       [FEXT_TO_IDX(FEXT_FTOUI)]       = vfp_double_ftoui,
-       [FEXT_TO_IDX(FEXT_FTOUIZ)]      = vfp_double_ftouiz,
-       [FEXT_TO_IDX(FEXT_FTOSI)]       = vfp_double_ftosi,
-       [FEXT_TO_IDX(FEXT_FTOSIZ)]      = vfp_double_ftosiz,
+static struct op fops_ext[32] = {
+       [FEXT_TO_IDX(FEXT_FCPY)]        = { vfp_double_fcpy,   0 },
+       [FEXT_TO_IDX(FEXT_FABS)]        = { vfp_double_fabs,   0 },
+       [FEXT_TO_IDX(FEXT_FNEG)]        = { vfp_double_fneg,   0 },
+       [FEXT_TO_IDX(FEXT_FSQRT)]       = { vfp_double_fsqrt,  0 },
+       [FEXT_TO_IDX(FEXT_FCMP)]        = { vfp_double_fcmp,   OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCMPE)]       = { vfp_double_fcmpe,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCMPZ)]       = { vfp_double_fcmpz,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCMPEZ)]      = { vfp_double_fcmpez, OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCVT)]        = { vfp_double_fcvts,  OP_SCALAR|OP_SD },
+       [FEXT_TO_IDX(FEXT_FUITO)]       = { vfp_double_fuito,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FSITO)]       = { vfp_double_fsito,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FTOUI)]       = { vfp_double_ftoui,  OP_SCALAR|OP_SD },
+       [FEXT_TO_IDX(FEXT_FTOUIZ)]      = { vfp_double_ftouiz, OP_SCALAR|OP_SD },
+       [FEXT_TO_IDX(FEXT_FTOSI)]       = { vfp_double_ftosi,  OP_SCALAR|OP_SD },
+       [FEXT_TO_IDX(FEXT_FTOSIZ)]      = { vfp_double_ftosiz, OP_SCALAR|OP_SD },
 };
 
 
@@ -1108,16 +1108,16 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr)
        return FPSCR_IOC;
 }
 
-static u32 (* const fop_fns[16])(int dd, int dn, int dm, u32 fpscr) = {
-       [FOP_TO_IDX(FOP_FMAC)]  = vfp_double_fmac,
-       [FOP_TO_IDX(FOP_FNMAC)] = vfp_double_fnmac,
-       [FOP_TO_IDX(FOP_FMSC)]  = vfp_double_fmsc,
-       [FOP_TO_IDX(FOP_FNMSC)] = vfp_double_fnmsc,
-       [FOP_TO_IDX(FOP_FMUL)]  = vfp_double_fmul,
-       [FOP_TO_IDX(FOP_FNMUL)] = vfp_double_fnmul,
-       [FOP_TO_IDX(FOP_FADD)]  = vfp_double_fadd,
-       [FOP_TO_IDX(FOP_FSUB)]  = vfp_double_fsub,
-       [FOP_TO_IDX(FOP_FDIV)]  = vfp_double_fdiv,
+static struct op fops[16] = {
+       [FOP_TO_IDX(FOP_FMAC)]  = { vfp_double_fmac,  0 },
+       [FOP_TO_IDX(FOP_FNMAC)] = { vfp_double_fnmac, 0 },
+       [FOP_TO_IDX(FOP_FMSC)]  = { vfp_double_fmsc,  0 },
+       [FOP_TO_IDX(FOP_FNMSC)] = { vfp_double_fnmsc, 0 },
+       [FOP_TO_IDX(FOP_FMUL)]  = { vfp_double_fmul,  0 },
+       [FOP_TO_IDX(FOP_FNMUL)] = { vfp_double_fnmul, 0 },
+       [FOP_TO_IDX(FOP_FADD)]  = { vfp_double_fadd,  0 },
+       [FOP_TO_IDX(FOP_FSUB)]  = { vfp_double_fsub,  0 },
+       [FOP_TO_IDX(FOP_FDIV)]  = { vfp_double_fdiv,  0 },
 };
 
 #define FREG_BANK(x)   ((x) & 0x0c)
@@ -1131,69 +1131,60 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
        unsigned int dn = vfp_get_dn(inst);
        unsigned int dm = vfp_get_dm(inst);
        unsigned int vecitr, veclen, vecstride;
-       u32 (*fop)(int, int, s32, u32);
+       struct op *fop;
 
-       veclen = fpscr & FPSCR_LENGTH_MASK;
        vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
 
+       fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
+
        /*
         * fcvtds takes an sN register number as destination, not dN.
         * It also always operates on scalars.
         */
-       if ((inst & FEXT_MASK) == FEXT_FCVT) {
-               veclen = 0;
+       if (fop->flags & OP_SD)
                dest = vfp_get_sd(inst);
-       else
+       else
                dest = vfp_get_dd(inst);
 
        /*
         * If destination bank is zero, vector length is always '1'.
         * ARM DDI0100F C5.1.3, C5.3.2.
         */
-       if (FREG_BANK(dest) == 0)
+       if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
                veclen = 0;
+       else
+               veclen = fpscr & FPSCR_LENGTH_MASK;
 
        pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
                 (veclen >> FPSCR_LENGTH_BIT) + 1);
 
-       fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
-       if (!fop)
+       if (!fop->fn)
                goto invalid;
 
        for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
                u32 except;
+               char type;
 
-               if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
-                       pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
-                                vecitr >> FPSCR_LENGTH_BIT,
-                                dest, dn, dm);
-               else if (op == FOP_EXT)
-                       pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
+               type = fop->flags & OP_SD ? 's' : 'd';
+               if (op == FOP_EXT)
+                       pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n",
                                 vecitr >> FPSCR_LENGTH_BIT,
-                                dest, dn, dm);
+                                type, dest, dn, dm);
                else
-                       pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
+                       pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n",
                                 vecitr >> FPSCR_LENGTH_BIT,
-                                dest, dn, FOP_TO_IDX(op), dm);
+                                type, dest, dn, FOP_TO_IDX(op), dm);
 
-               except = fop(dest, dn, dm, fpscr);
+               except = fop->fn(dest, dn, dm, fpscr);
                pr_debug("VFP: itr%d: exceptions=%08x\n",
                         vecitr >> FPSCR_LENGTH_BIT, except);
 
                exceptions |= except;
 
-               /*
-                * This ensures that comparisons only operate on scalars;
-                * comparisons always return with one FPSCR status bit set.
-                */
-               if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
-                       break;
-
                /*
                 * CHECK: It appears to be undefined whether we stop when
                 * we encounter an exception.  We continue.
                 */
-
                dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
                dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
                if (FREG_BANK(dm) != 0)
index 6c819aeae00631cdd2a12f56320da38b9d5189e4..7f343a4beca0542151e1a57f1f2c3612159daa14 100644 (file)
 
 #define fmrx(_vfp_) ({                 \
        u32 __v;                        \
-       asm("mrc%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx %0, " #_vfp_    \
-           : "=r" (__v));              \
+       asm("mrc p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx   %0, " #_vfp_    \
+           : "=r" (__v) : : "cc");     \
        __v;                            \
  })
 
 #define fmxr(_vfp_,_var_)              \
-       asm("mcr%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \
-          : : "r" (_var_))
+       asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr   " #_vfp_ ", %0" \
+          : : "r" (_var_) : "cc")
 
 u32 vfp_single_cpdo(u32 inst, u32 fpscr);
 u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);
index 4178f6cc3d3714deec92f88f4480838b0450c447..dedbb449632edc1f65a40d39e06650df14831a98 100644 (file)
@@ -40,10 +40,19 @@ unsigned int VFP_arch;
 static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
        struct thread_info *thread = v;
-       union vfp_state *vfp = &thread->vfpstate;
+       union vfp_state *vfp;
 
-       switch (cmd) {
-       case THREAD_NOTIFY_FLUSH:
+       if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
+               /*
+                * Always disable VFP so we can lazily save/restore the
+                * old state.
+                */
+               fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+               return NOTIFY_DONE;
+       }
+
+       vfp = &thread->vfpstate;
+       if (cmd == THREAD_NOTIFY_FLUSH) {
                /*
                 * Per-thread VFP initialisation.
                 */
@@ -56,29 +65,12 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
                 * Disable VFP to ensure we initialise it first.
                 */
                fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
-
-               /*
-                * FALLTHROUGH: Ensure we don't try to overwrite our newly
-                * initialised state information on the first fault.
-                */
-
-       case THREAD_NOTIFY_RELEASE:
-               /*
-                * Per-thread VFP cleanup.
-                */
-               if (last_VFP_context == vfp)
-                       last_VFP_context = NULL;
-               break;
-
-       case THREAD_NOTIFY_SWITCH:
-               /*
-                * Always disable VFP so we can lazily save/restore the
-                * old state.
-                */
-               fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
-               break;
        }
 
+       /* flush and release case: Per-thread VFP cleanup. */
+       if (last_VFP_context == vfp)
+               last_VFP_context = NULL;
+
        return NOTIFY_DONE;
 }
 
index 8f6c179cafbe54e6b76cb09109bf4ba2d077947b..ab5e9503bae5423132a8a2388bd2ce89ebfd2a47 100644 (file)
@@ -702,22 +702,22 @@ static u32 vfp_single_ftosiz(int sd, int unused, s32 m, u32 fpscr)
        return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO);
 }
 
-static u32 (* const fop_extfns[32])(int sd, int unused, s32 m, u32 fpscr) = {
-       [FEXT_TO_IDX(FEXT_FCPY)]        = vfp_single_fcpy,
-       [FEXT_TO_IDX(FEXT_FABS)]        = vfp_single_fabs,
-       [FEXT_TO_IDX(FEXT_FNEG)]        = vfp_single_fneg,
-       [FEXT_TO_IDX(FEXT_FSQRT)]       = vfp_single_fsqrt,
-       [FEXT_TO_IDX(FEXT_FCMP)]        = vfp_single_fcmp,
-       [FEXT_TO_IDX(FEXT_FCMPE)]       = vfp_single_fcmpe,
-       [FEXT_TO_IDX(FEXT_FCMPZ)]       = vfp_single_fcmpz,
-       [FEXT_TO_IDX(FEXT_FCMPEZ)]      = vfp_single_fcmpez,
-       [FEXT_TO_IDX(FEXT_FCVT)]        = vfp_single_fcvtd,
-       [FEXT_TO_IDX(FEXT_FUITO)]       = vfp_single_fuito,
-       [FEXT_TO_IDX(FEXT_FSITO)]       = vfp_single_fsito,
-       [FEXT_TO_IDX(FEXT_FTOUI)]       = vfp_single_ftoui,
-       [FEXT_TO_IDX(FEXT_FTOUIZ)]      = vfp_single_ftouiz,
-       [FEXT_TO_IDX(FEXT_FTOSI)]       = vfp_single_ftosi,
-       [FEXT_TO_IDX(FEXT_FTOSIZ)]      = vfp_single_ftosiz,
+static struct op fops_ext[32] = {
+       [FEXT_TO_IDX(FEXT_FCPY)]        = { vfp_single_fcpy,   0 },
+       [FEXT_TO_IDX(FEXT_FABS)]        = { vfp_single_fabs,   0 },
+       [FEXT_TO_IDX(FEXT_FNEG)]        = { vfp_single_fneg,   0 },
+       [FEXT_TO_IDX(FEXT_FSQRT)]       = { vfp_single_fsqrt,  0 },
+       [FEXT_TO_IDX(FEXT_FCMP)]        = { vfp_single_fcmp,   OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCMPE)]       = { vfp_single_fcmpe,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCMPZ)]       = { vfp_single_fcmpz,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCMPEZ)]      = { vfp_single_fcmpez, OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FCVT)]        = { vfp_single_fcvtd,  OP_SCALAR|OP_DD },
+       [FEXT_TO_IDX(FEXT_FUITO)]       = { vfp_single_fuito,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FSITO)]       = { vfp_single_fsito,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FTOUI)]       = { vfp_single_ftoui,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FTOUIZ)]      = { vfp_single_ftouiz, OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FTOSI)]       = { vfp_single_ftosi,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FTOSIZ)]      = { vfp_single_ftosiz, OP_SCALAR },
 };
 
 
@@ -1151,16 +1151,16 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
        return FPSCR_IOC;
 }
 
-static u32 (* const fop_fns[16])(int sd, int sn, s32 m, u32 fpscr) = {
-       [FOP_TO_IDX(FOP_FMAC)]  = vfp_single_fmac,
-       [FOP_TO_IDX(FOP_FNMAC)] = vfp_single_fnmac,
-       [FOP_TO_IDX(FOP_FMSC)]  = vfp_single_fmsc,
-       [FOP_TO_IDX(FOP_FNMSC)] = vfp_single_fnmsc,
-       [FOP_TO_IDX(FOP_FMUL)]  = vfp_single_fmul,
-       [FOP_TO_IDX(FOP_FNMUL)] = vfp_single_fnmul,
-       [FOP_TO_IDX(FOP_FADD)]  = vfp_single_fadd,
-       [FOP_TO_IDX(FOP_FSUB)]  = vfp_single_fsub,
-       [FOP_TO_IDX(FOP_FDIV)]  = vfp_single_fdiv,
+static struct op fops[16] = {
+       [FOP_TO_IDX(FOP_FMAC)]  = { vfp_single_fmac,  0 },
+       [FOP_TO_IDX(FOP_FNMAC)] = { vfp_single_fnmac, 0 },
+       [FOP_TO_IDX(FOP_FMSC)]  = { vfp_single_fmsc,  0 },
+       [FOP_TO_IDX(FOP_FNMSC)] = { vfp_single_fnmsc, 0 },
+       [FOP_TO_IDX(FOP_FMUL)]  = { vfp_single_fmul,  0 },
+       [FOP_TO_IDX(FOP_FNMUL)] = { vfp_single_fnmul, 0 },
+       [FOP_TO_IDX(FOP_FADD)]  = { vfp_single_fadd,  0 },
+       [FOP_TO_IDX(FOP_FSUB)]  = { vfp_single_fsub,  0 },
+       [FOP_TO_IDX(FOP_FDIV)]  = { vfp_single_fdiv,  0 },
 };
 
 #define FREG_BANK(x)   ((x) & 0x18)
@@ -1174,70 +1174,63 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
        unsigned int sn = vfp_get_sn(inst);
        unsigned int sm = vfp_get_sm(inst);
        unsigned int vecitr, veclen, vecstride;
-       u32 (*fop)(int, int, s32, u32);
+       struct op *fop;
 
-       veclen = fpscr & FPSCR_LENGTH_MASK;
        vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
 
+       fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
+
        /*
         * fcvtsd takes a dN register number as destination, not sN.
         * Technically, if bit 0 of dd is set, this is an invalid
         * instruction.  However, we ignore this for efficiency.
         * It also only operates on scalars.
         */
-       if ((inst & FEXT_MASK) == FEXT_FCVT) {
-               veclen = 0;
+       if (fop->flags & OP_DD)
                dest = vfp_get_dd(inst);
-       else
+       else
                dest = vfp_get_sd(inst);
 
        /*
         * If destination bank is zero, vector length is always '1'.
         * ARM DDI0100F C5.1.3, C5.3.2.
         */
-       if (FREG_BANK(dest) == 0)
+       if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0)
                veclen = 0;
+       else
+               veclen = fpscr & FPSCR_LENGTH_MASK;
 
        pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
                 (veclen >> FPSCR_LENGTH_BIT) + 1);
 
-       fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
-       if (!fop)
+       if (!fop->fn)
                goto invalid;
 
        for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
                s32 m = vfp_get_float(sm);
                u32 except;
+               char type;
 
-               if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
-                       pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
-                                vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
-               else if (op == FOP_EXT)
-                       pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
-                                vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
+               type = fop->flags & OP_DD ? 'd' : 's';
+               if (op == FOP_EXT)
+                       pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n",
+                                vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
+                                sm, m);
                else
-                       pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
-                                vecitr >> FPSCR_LENGTH_BIT, dest, sn,
+                       pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n",
+                                vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
                                 FOP_TO_IDX(op), sm, m);
 
-               except = fop(dest, sn, m, fpscr);
+               except = fop->fn(dest, sn, m, fpscr);
                pr_debug("VFP: itr%d: exceptions=%08x\n",
                         vecitr >> FPSCR_LENGTH_BIT, except);
 
                exceptions |= except;
 
-               /*
-                * This ensures that comparisons only operate on scalars;
-                * comparisons always return with one FPSCR status bit set.
-                */
-               if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
-                       break;
-
                /*
                 * CHECK: It appears to be undefined whether we stop when
                 * we encounter an exception.  We continue.
                 */
-
                dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
                sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
                if (FREG_BANK(sm) != 0)
index db63d75d0715927bda8d6379a63dcdb8dd224822..1206469b2b86249574f0dd111a83d457b960c7a8 100644 (file)
@@ -33,8 +33,6 @@
 #include <asm/irq.h>
 #include <asm/ioc.h>
 
-extern unsigned long wall_jiffies;
-
 /* this needs a better home */
 DEFINE_SPINLOCK(rtc_lock);
 
@@ -136,16 +134,11 @@ void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
        unsigned long seq;
-       unsigned long usec, sec, lost;
+       unsigned long usec, sec;
 
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = gettimeoffset();
-
-               lost = jiffies - wall_jiffies;
-               if (lost)
-                       usec += lost * USECS_PER_JIFFY;
-
                sec = xtime.tv_sec;
                usec += xtime.tv_nsec / 1000;
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -174,8 +167,7 @@ int do_settimeofday(struct timespec *tv)
         * wall time.  Discover what correction gettimeofday() would have
         * done, and then undo it!
         */
-       tv->tv_nsec -= 1000 * (gettimeoffset() +
-                       (jiffies - wall_jiffies) * USECS_PER_JIFFY);
+       tv->tv_nsec -= 1000 * gettimeoffset();
 
        while (tv->tv_nsec < 0) {
                tv->tv_nsec += NSEC_PER_SEC;
@@ -194,7 +186,7 @@ EXPORT_SYMBOL(do_settimeofday);
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-        do_timer(regs);
+        do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
index 761938b56679453d350adb663187b4d9b52399ac..a1f6d8a9cc32919084d14b5cf9181dbceb013ca6 100644 (file)
@@ -155,7 +155,7 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
         */
 good_area:
        if (READ_FAULT(fsr)) /* read? */
-               mask = VM_READ|VM_EXEC;
+               mask = VM_READ|VM_EXEC|VM_WRITE;
        else
                mask = VM_WRITE;
 
@@ -185,7 +185,7 @@ survive:
        }
 
        fault = -3; /* out of memory */
-       if (tsk->pid != 1)
+       if (!is_init(tsk))
                goto out;
 
        /*
index b0e6b5855a381d2096c9a9b581874be3fd5b634e..3e56b9f4358af4a3728c96ed2815eb033a0fc841 100644 (file)
@@ -148,7 +148,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * Call the generic timer interrupt handler
         */
        write_seqlock(&xtime_lock);
-       do_timer(regs);
+       do_timer(1);
        write_sequnlock(&xtime_lock);
 
        /*
index 536021877df60cced06d2d841818790f2f6d9b54..8cfec65e37f76f72ac101aaacc1315affe1da913 100644 (file)
  */
 #include <linux/vmalloc.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
 #include <asm/addrspace.h>
 
-static inline int remap_area_pte(pte_t *pte, unsigned long address,
-                                 unsigned long end, unsigned long phys_addr,
-                                 pgprot_t prot)
-{
-       unsigned long pfn;
-
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               WARN_ON(!pte_none(*pte));
-
-               set_pte(pte, pfn_pte(pfn, prot));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-
-       return 0;
-}
-
-static inline int remap_area_pmd(pmd_t *pmd, unsigned long address,
-                                unsigned long end, unsigned long phys_addr,
-                                pgprot_t prot)
-{
-       unsigned long next;
-
-       phys_addr -= address;
-
-       do {
-               pte_t *pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-
-               next = (address + PMD_SIZE) & PMD_MASK;
-               if (remap_area_pte(pte, address, next,
-                                  address + phys_addr, prot))
-                       return -ENOMEM;
-
-               address = next;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int remap_area_pud(pud_t *pud, unsigned long address,
-                         unsigned long end, unsigned long phys_addr,
-                         pgprot_t prot)
-{
-       unsigned long next;
-
-       phys_addr -= address;
-
-       do {
-               pmd_t *pmd = pmd_alloc(&init_mm, pud, address);
-               if (!pmd)
-                       return -ENOMEM;
-               next = (address + PUD_SIZE) & PUD_MASK;
-               if (remap_area_pmd(pmd, address, next,
-                                  phys_addr + address, prot))
-                       return -ENOMEM;
-
-               address = next;
-               pud++;
-       } while (address && address < end);
-
-       return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                           size_t size, pgprot_t prot)
-{
-       unsigned long end = address + size;
-       unsigned long next;
-       pgd_t *pgd;
-       int err = 0;
-
-       phys_addr -= address;
-
-       pgd = pgd_offset_k(address);
-       flush_cache_all();
-       BUG_ON(address >= end);
-
-       spin_lock(&init_mm.page_table_lock);
-       do {
-               pud_t *pud = pud_alloc(&init_mm, pgd, address);
-
-               err = -ENOMEM;
-               if (!pud)
-                       break;
-
-               next = (address + PGDIR_SIZE) & PGDIR_MASK;
-               if (next < address || next > end)
-                       next = end;
-               err = remap_area_pud(pud, address, next,
-                                    phys_addr + address, prot);
-               if (err)
-                       break;
-
-               address = next;
-               pgd++;
-       } while (address && (address < end));
-
-       spin_unlock(&init_mm.page_table_lock);
-       flush_tlb_all();
-       return err;
-}
-
 /*
  * Re-map an arbitrary physical address space into the kernel virtual
  * address space. Needed when the kernel wants to access physical
@@ -128,7 +20,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
 void __iomem *__ioremap(unsigned long phys_addr, size_t size,
                        unsigned long flags)
 {
-       void *addr;
+       unsigned long addr;
        struct vm_struct *area;
        unsigned long offset, last_addr;
        pgprot_t prot;
@@ -159,7 +51,7 @@ void __iomem *__ioremap(unsigned long phys_addr, size_t size,
        phys_addr &= PAGE_MASK;
        size = PAGE_ALIGN(last_addr + 1) - phys_addr;
 
-       prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
+       prot = __pgprot(_PAGE_PRESENT | _PAGE_GLOBAL | _PAGE_RW | _PAGE_DIRTY
                        | _PAGE_ACCESSED | _PAGE_TYPE_SMALL | flags);
 
        /*
@@ -169,9 +61,9 @@ void __iomem *__ioremap(unsigned long phys_addr, size_t size,
        if (!area)
                return NULL;
        area->phys_addr = phys_addr;
-       addr = area->addr;
-       if (remap_area_pages((unsigned long)addr, phys_addr, size, prot)) {
-               vunmap(addr);
+       addr = (unsigned long )area->addr;
+       if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+               vunmap((void *)addr);
                return NULL;
        }
 
index 5d0523bbe298ad2082b3e0df33c011dae9fc7900..7b073052203d77a4d6002709b53f435afda0a10b 100644 (file)
@@ -15,7 +15,8 @@
 
 void show_dtlb_entry(unsigned int index)
 {
-       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save, flags;
+       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+       unsigned long flags;
 
        local_irq_save(flags);
        mmucr_save = sysreg_read(MMUCR);
@@ -305,7 +306,8 @@ static void tlb_stop(struct seq_file *tlb, void *v)
 
 static int tlb_show(struct seq_file *tlb, void *v)
 {
-       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save, flags;
+       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+       unsigned long flags;
        unsigned long *index = v;
 
        if (*index == 0)
index 9c22b76e129a32a18e49da042a675d23f8756ed2..ebacf1457d914cacae4069c21094639fbc906dd7 100644 (file)
@@ -227,7 +227,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        
        /* call the real timer interrupt handler */
 
-       do_timer(regs);
+       do_timer(1);
        
         cris_do_profile(regs); /* Save profiling information */
 
index 50f3f93293d64d33c8b1183a6971faf68eca0912..be0a01657d4fc88076e120b88264977acd25d2ed 100644 (file)
@@ -219,7 +219,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                return IRQ_HANDLED;
 
        /* call the real timer interrupt handler */
-       do_timer(regs);
+       do_timer(1);
 
        /*
         * If we have an externally synchronized Linux clock, then update
index 66ba8898db07ba0facf5a1edb86b31bb48a4f874..0f9213cbd48e24f9068c62125b7b9814d09ce617 100644 (file)
@@ -37,7 +37,6 @@ int have_rtc;  /* used to remember if we have an RTC or not */;
 
 #define TICK_SIZE tick
 
-extern unsigned long wall_jiffies;
 extern unsigned long loops_per_jiffy; /* init/main.c */
 unsigned long loops_per_usec;
 
@@ -58,11 +57,6 @@ void do_gettimeofday(struct timeval *tv)
        local_irq_save(flags);
        local_irq_disable();
        usec = do_gettimeoffset();
-       {
-               unsigned long lost = jiffies - wall_jiffies;
-               if (lost)
-                       usec += lost * (1000000 / HZ);
-       }
 
         /*
         * If time_adjust is negative then NTP is slowing the clock
@@ -103,7 +97,6 @@ int do_settimeofday(struct timespec *tv)
         * made, and then undo it!
         */
        nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-       nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
index 1780df3ed9e590997529aadcbd9d3a1c7f134abd..8b0b9348b574c17bb91c2cc0703a99c4f0dbe026 100644 (file)
  */
 
 #include <linux/vmalloc.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
 #include <asm/arch/memmap.h>
 
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
-       unsigned long phys_addr, pgprot_t prot)
-{
-       unsigned long end;
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-               set_pte(pte, mk_pte_phys(phys_addr, prot));
-               address += PAGE_SIZE;
-               phys_addr += PAGE_SIZE;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long phys_addr, pgprot_t prot)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, prot);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                                unsigned long size, pgprot_t prot)
-{
-       int error;
-       pgd_t * dir;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset(&init_mm, address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pud_t *pud;
-               pmd_t *pmd;
-
-               error = -ENOMEM;
-               pud = pud_alloc(&init_mm, dir, address);
-               if (!pud)
-                       break;
-               pmd = pmd_alloc(&init_mm, pud, address);
-
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                  phys_addr + address, prot))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return error;
-}
-
 /*
  * Generic mapping function (not visible outside):
  */
@@ -135,7 +52,8 @@ void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgpro
        if (!area)
                return NULL;
        addr = (void __iomem *)area->addr;
-       if (remap_area_pages((unsigned long) addr, phys_addr, size, prot)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, prot)) {
                vfree((void __force *)addr);
                return NULL;
        }
index 3d0284bccb940ba2d62c8c3e9e26f099065ff0b4..7e55884135ed8ee2cf460cd0c03c0f223853256d 100644 (file)
@@ -70,7 +70,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
         */
        write_seqlock(&xtime_lock);
 
-       do_timer(regs);
+       do_timer(1);
        update_process_times(user_mode(regs));
        profile_tick(CPU_PROFILING, regs);
 
index 688a5100604c943c614e5ffeb8fef25ba5c9b2fd..e569d17b4ae6b92b5ceccf554795d6cd83070945 100644 (file)
@@ -41,7 +41,7 @@ static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
        /* may need to kick the hardware timer */
        platform_timer_eoi();
 
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
index 758044f5e718deba9da1db551c111219f3af5c1c..3fd2f256f2be3402cea23aa3a93a21c0c161197a 100644 (file)
@@ -401,6 +401,7 @@ config X86_REBOOTFIXUPS
 
 config MICROCODE
        tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
+       select FW_LOADER
        ---help---
          If you say Y here and also to "/dev file system support" in the
          'File systems' section, you will be able to update the microcode on
@@ -416,6 +417,11 @@ config MICROCODE
          To compile this driver as a module, choose M here: the
          module will be called microcode.
 
+config MICROCODE_OLD_INTERFACE
+       bool
+       depends on MICROCODE
+       default y
+
 config X86_MSR
        tristate "/dev/cpu/*/msr - Model-specific register support"
        help
@@ -598,12 +604,10 @@ config ARCH_SELECT_MEMORY_MODEL
        def_bool y
        depends on ARCH_SPARSEMEM_ENABLE
 
-source "mm/Kconfig"
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
 
-config HAVE_ARCH_EARLY_PFN_TO_NID
-       bool
-       default y
-       depends on NUMA
+source "mm/Kconfig"
 
 config HIGHPTE
        bool "Allocate 3rd-level pagetables from highmem"
index 8c2a6faeeae51b128e27b43e4669a7ac75dcf792..2c5b5cc55f795339a30036691d0f0d45b6a48e1a 100644 (file)
@@ -11,8 +11,6 @@
  *
  */
 
-#include <linux/config.h> /* for CONFIG_VIDEO_* */
-
 /* Enable autodetection of SVGA adapters and modes. */
 #undef CONFIG_VIDEO_SVGA
 
index 1a29bfa26d0cbf4ddf54a5d7e98661f5ecf91e74..ee2d79bd8af7933dcd4250756c719496dca5502c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-git5
-# Tue Sep 26 09:30:47 2006
+# Linux kernel version: 2.6.18-git7
+# Wed Sep 27 21:53:10 2006
 #
 CONFIG_X86_32=y
 CONFIG_GENERIC_TIME=y
@@ -210,6 +210,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_PM=y
 CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
+CONFIG_PM_SYSFS_DEPRECATED=y
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
@@ -292,6 +293,7 @@ CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 CONFIG_ISA_DMA_API=y
 # CONFIG_ISA is not set
@@ -1427,6 +1429,7 @@ CONFIG_KPROBES=y
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_KERNEL=y
index ff9ce4b5eaa86489fec9dc55b272358ece1bf586..b42f2d914af3bb15eada724c854bc92581f47169 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
+#include <linux/kthread.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -402,8 +403,6 @@ static int                  realmode_power_off = 1;
 #else
 static int                     realmode_power_off;
 #endif
-static int                     exit_kapmd __read_mostly;
-static int                     kapmd_running __read_mostly;
 #ifdef CONFIG_APM_ALLOW_INTS
 static int                     allow_ints = 1;
 #else
@@ -419,6 +418,8 @@ static const struct desc_struct     bad_bios_desc = { 0, 0x00409200 };
 
 static const char              driver_version[] = "1.16ac";    /* no spaces */
 
+static struct task_struct *kapmd_task;
+
 /*
  *     APM event names taken from the APM 1.2 specification. These are
  *     the message codes that the BIOS uses to tell us about events
@@ -1423,7 +1424,7 @@ static void apm_mainloop(void)
        set_current_state(TASK_INTERRUPTIBLE);
        for (;;) {
                schedule_timeout(APM_CHECK_TIMEOUT);
-               if (exit_kapmd)
+               if (kthread_should_stop())
                        break;
                /*
                 * Ok, check all events, check for idle (and mark us sleeping
@@ -1706,12 +1707,6 @@ static int apm(void *unused)
        char *          power_stat;
        char *          bat_stat;
 
-       kapmd_running = 1;
-
-       daemonize("kapmd");
-
-       current->flags |= PF_NOFREEZE;
-
 #ifdef CONFIG_SMP
        /* 2002/08/01 - WT
         * This is to avoid random crashes at boot time during initialization
@@ -1821,7 +1816,6 @@ static int apm(void *unused)
                console_blank_hook = NULL;
 #endif
        }
-       kapmd_running = 0;
 
        return 0;
 }
@@ -2220,7 +2214,7 @@ static int __init apm_init(void)
 {
        struct proc_dir_entry *apm_proc;
        struct desc_struct *gdt;
-       int ret;
+       int err;
 
        dmi_check_system(apm_dmi_table);
 
@@ -2329,12 +2323,17 @@ static int __init apm_init(void)
        if (apm_proc)
                apm_proc->owner = THIS_MODULE;
 
-       ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD);
-       if (ret < 0) {
-               printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n");
+       kapmd_task = kthread_create(apm, NULL, "kapmd");
+       if (IS_ERR(kapmd_task)) {
+               printk(KERN_ERR "apm: disabled - Unable to start kernel "
+                               "thread.\n");
+               err = PTR_ERR(kapmd_task);
+               kapmd_task = NULL;
                remove_proc_entry("apm", NULL);
-               return -ENOMEM;
+               return err;
        }
+       kapmd_task->flags |= PF_NOFREEZE;
+       wake_up_process(kapmd_task);
 
        if (num_online_cpus() > 1 && !smp ) {
                printk(KERN_NOTICE
@@ -2384,9 +2383,10 @@ static void __exit apm_exit(void)
        remove_proc_entry("apm", NULL);
        if (power_off)
                pm_power_off = NULL;
-       exit_kapmd = 1;
-       while (kapmd_running)
-               schedule();
+       if (kapmd_task) {
+               kthread_stop(kapmd_task);
+               kapmd_task = NULL;
+       }
 #ifdef CONFIG_PM_LEGACY
        pm_active = 0;
 #endif
index ea19d091fd41e278c2e58122ccb372721b959849..57c880bf0bd69f4af7e0c2026f5ac12e2b9e2aa5 100644 (file)
@@ -396,13 +396,13 @@ static int acpi_cpufreq_early_init_acpi(void)
  */
 static int bios_with_sw_any_bug;
 
-static int __init sw_any_bug_found(struct dmi_system_id *d)
+static int sw_any_bug_found(struct dmi_system_id *d)
 {
        bios_with_sw_any_bug = 1;
        return 0;
 }
 
-static struct dmi_system_id __initdata sw_any_bug_dmi_table[] = {
+static struct dmi_system_id sw_any_bug_dmi_table[] = {
        {
                .callback = sw_any_bug_found,
                .ident = "Supermicro Server X6DLP",
@@ -597,7 +597,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
        .name   = "acpi-cpufreq",
        .owner  = THIS_MODULE,
        .attr   = acpi_cpufreq_attr,
-       .flags  = CPUFREQ_STICKY,
 };
 
 
@@ -608,7 +607,7 @@ acpi_cpufreq_init (void)
 
        acpi_cpufreq_early_init_acpi();
 
-       return cpufreq_register_driver(&acpi_cpufreq_driver);
+       return cpufreq_register_driver(&acpi_cpufreq_driver);
 }
 
 
index f5cc9f5c9bab3dae9d0cf050507ac774b945037b..7233abe5d695533a5ca701bb615681c1a156d487 100644 (file)
@@ -178,11 +178,17 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
        safe_halt();
        /* Change frequency on next halt or sleep */
        wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-       ACPI_FLUSH_CPU_CACHE();
-       /* Invoke C3 */
-       inb(cx_address);
-       /* Dummy op - must do something useless after P_LVL3 read */
-       t = inl(acpi_fadt.xpm_tmr_blk.address);
+       if (port22_en) {
+               ACPI_FLUSH_CPU_CACHE();
+               /* Invoke C1 */
+               halt();
+       } else {
+               ACPI_FLUSH_CPU_CACHE();
+               /* Invoke C3 */
+               inb(cx_address);
+               /* Dummy op - must do something useless after P_LVL3 read */
+               t = inl(acpi_fadt.xpm_tmr_blk.address);
+       }
 
        /* Disable bus ratio bit */
        local_irq_disable();
@@ -567,16 +573,23 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
 static int enable_arbiter_disable(void)
 {
        struct pci_dev *dev;
+       int reg;
        u8 pci_cmd;
 
        /* Find PLE133 host bridge */
+       reg = 0x78;
        dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
+       /* Find CLE266 host bridge */
+       if (dev == NULL) {
+               reg = 0x76;
+               dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_862X_0, NULL);
+       }
        if (dev != NULL) {
                /* Enable access to port 0x22 */
-               pci_read_config_byte(dev, 0x78, &pci_cmd);
+               pci_read_config_byte(dev, reg, &pci_cmd);
                if ( !(pci_cmd & 1<<7) ) {
                        pci_cmd |= 1<<7;
-                       pci_write_config_byte(dev, 0x78, pci_cmd);
+                       pci_write_config_byte(dev, reg, pci_cmd);
                }
                return 1;
        }
@@ -680,20 +693,25 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        if (longhaul_version == TYPE_POWERSAVER) {
                /* Check ACPI support for C3 state */
                cx = &pr->power.states[ACPI_STATE_C3];
-               if (cx->address == 0 ||
-                  (cx->latency > 1000 && ignore_latency == 0) )
+               if (cx->address > 0 &&
+                  (cx->latency <= 1000 || ignore_latency != 0) ) {
+                       goto print_support_type;
+               }
+       }
+       /* Check ACPI support for bus master arbiter disable */
+       if (!pr->flags.bm_control) {
+               if (enable_arbiter_disable()) {
+                       port22_en = 1;
+               } else {
                        goto err_acpi;
-
-       } else {
-               /* Check ACPI support for bus master arbiter disable */
-               if (!pr->flags.bm_control) {
-                       if (!enable_arbiter_disable()) {
-                               printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
-                               return -ENODEV;
-                       } else
-                               port22_en = 1;
                }
        }
+print_support_type:
+       if (!port22_en) {
+               printk (KERN_INFO PFX "Using ACPI support.\n");
+       } else {
+               printk (KERN_INFO PFX "Using northbridge support.\n");
+       }
 
        ret = longhaul_get_ranges();
        if (ret != 0)
@@ -716,7 +734,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        return 0;
 
 err_acpi:
-       printk(KERN_ERR PFX "No ACPI support for CPU frequency changes.\n");
+       printk(KERN_ERR PFX "No ACPI support. No VT8601 or VT8623 northbridge. Aborting.\n");
        return -ENODEV;
 }
 
index 7a9325349e949e8e5be8f7bb3c25e3578fd6d613..e8993baf3d1422ca7fbb1ccdf045a3676349d176 100644 (file)
@@ -386,7 +386,7 @@ static int centrino_cpu_early_init_acpi(void)
  * than OS intended it to run at. Detect it and handle it cleanly.
  */
 static int bios_with_sw_any_bug;
-static int __init sw_any_bug_found(struct dmi_system_id *d)
+static int sw_any_bug_found(struct dmi_system_id *d)
 {
        bios_with_sw_any_bug = 1;
        return 0;
index 67d297dc1003cd0d1fec64ade9fba9fd4218a33f..144b432889655aa77a6d8196ac724e383ae402ec 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
 #include <asm/kdebug.h>
+#include <asm/smp.h>
 
 #include <mach_ipi.h>
 
@@ -88,7 +89,7 @@ static void crash_save_self(struct pt_regs *regs)
 {
        int cpu;
 
-       cpu = smp_processor_id();
+       cpu = safe_smp_processor_id();
        crash_save_this_cpu(regs, cpu);
 }
 
@@ -133,7 +134,10 @@ static int crash_nmi_callback(struct notifier_block *self,
 
 static void smp_send_nmi_allbutself(void)
 {
-       send_IPI_allbutself(NMI_VECTOR);
+       cpumask_t mask = cpu_online_map;
+       cpu_clear(safe_smp_processor_id(), mask);
+       if (!cpus_empty(mask))
+               send_IPI_mask(mask, NMI_VECTOR);
 }
 
 static struct notifier_block crash_nmi_nb = {
@@ -185,7 +189,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
        local_irq_disable();
 
        /* Make a note of crashing cpu. Will be used in NMI callback.*/
-       crashing_cpu = smp_processor_id();
+       crashing_cpu = safe_smp_processor_id();
        nmi_shootdown_cpus();
        lapic_shutdown();
 #if defined(CONFIG_X86_IO_APIC)
index fe158042110bea08fd7774234dfdb3c7275712a0..f9436989473c23fa0f57ac4ddea21dc8a2f117f0 100644 (file)
@@ -65,7 +65,7 @@ static unsigned long efi_rt_eflags;
 static DEFINE_SPINLOCK(efi_rt_lock);
 static pgd_t efi_bak_pg_dir_pointer[2];
 
-static void efi_call_phys_prelog(void)
+static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
 {
        unsigned long cr4;
        unsigned long temp;
@@ -109,7 +109,7 @@ static void efi_call_phys_prelog(void)
        load_gdt(cpu_gdt_descr);
 }
 
-static void efi_call_phys_epilog(void)
+static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
 {
        unsigned long cr4;
        struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
index c36d1c006c2fba75b3549514d2f78549b0c0cab0..6f508e8d7c57433085feec900a851b9a312747d2 100644 (file)
@@ -2,6 +2,11 @@
  * i8237.c: 8237A DMA controller suspend functions.
  *
  * Written by Pierre Ossman, 2005.
+ *
+ * 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>
index 40b44cc0d14b048523f8bbf0c6935342a6067e3e..9b9479768d5ebcda920044781234b8aa2d4183d3 100644 (file)
@@ -2,6 +2,7 @@
  *     Intel CPU Microcode Update Driver for Linux
  *
  *     Copyright (C) 2000-2004 Tigran Aivazian
+ *                   2006      Shaohua Li <shaohua.li@intel.com>
  *
  *     This driver allows to upgrade microcode on Intel processors
  *     belonging to IA-32 family - PentiumPro, Pentium II, 
@@ -82,6 +83,9 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
 
 #include <asm/msr.h>
 #include <asm/uaccess.h>
@@ -91,9 +95,6 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
 MODULE_LICENSE("GPL");
 
-static int verbose;
-module_param(verbose, int, 0644);
-
 #define MICROCODE_VERSION      "1.14a"
 
 #define DEFAULT_UCODE_DATASIZE         (2000)    /* 2000 bytes */
@@ -120,55 +121,40 @@ static DEFINE_SPINLOCK(microcode_update_lock);
 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
 static DEFINE_MUTEX(microcode_mutex);
 
-static void __user *user_buffer;       /* user area microcode data buffer */
-static unsigned int user_buffer_size;  /* it's size */
-
-typedef enum mc_error_code {
-       MC_SUCCESS      = 0,
-       MC_IGNORED      = 1,
-       MC_NOTFOUND     = 2,
-       MC_MARKED       = 3,
-       MC_ALLOCATED    = 4,
-} mc_error_code_t;
-
 static struct ucode_cpu_info {
+       int valid;
        unsigned int sig;
-       unsigned int pf, orig_pf;
+       unsigned int pf;
        unsigned int rev;
-       unsigned int cksum;
-       mc_error_code_t err;
        microcode_t *mc;
 } ucode_cpu_info[NR_CPUS];
-                               
-static int microcode_open (struct inode *unused1, struct file *unused2)
-{
-       return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
-}
 
-static void collect_cpu_info (void *unused)
+static void collect_cpu_info(int cpu_num)
 {
-       int cpu_num = smp_processor_id();
        struct cpuinfo_x86 *c = cpu_data + cpu_num;
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
        unsigned int val[2];
 
-       uci->sig = uci->pf = uci->rev = uci->cksum = 0;
-       uci->err = MC_NOTFOUND; 
+       /* We should bind the task to the CPU */
+       BUG_ON(raw_smp_processor_id() != cpu_num);
+       uci->pf = uci->rev = 0;
        uci->mc = NULL;
+       uci->valid = 1;
 
        if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
                cpu_has(c, X86_FEATURE_IA64)) {
-               printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
+               printk(KERN_ERR "microcode: CPU%d not a capable Intel "
+                       "processor\n", cpu_num);
+               uci->valid = 0;
                return;
-       } else {
-               uci->sig = cpuid_eax(0x00000001);
+       }
 
-               if ((c->x86_model >= 5) || (c->x86 > 6)) {
-                       /* get processor flags from MSR 0x17 */
-                       rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-                       uci->pf = 1 << ((val[1] >> 18) & 7);
-               }
-               uci->orig_pf = uci->pf;
+       uci->sig = cpuid_eax(0x00000001);
+
+       if ((c->x86_model >= 5) || (c->x86 > 6)) {
+               /* get processor flags from MSR 0x17 */
+               rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+               uci->pf = 1 << ((val[1] >> 18) & 7);
        }
 
        wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -180,218 +166,159 @@ static void collect_cpu_info (void *unused)
                        uci->sig, uci->pf, uci->rev);
 }
 
-static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum)
+static inline int microcode_update_match(int cpu_num,
+       microcode_header_t *mc_header, int sig, int pf)
 {
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
-       pr_debug("Microcode Found.\n");
-       pr_debug("   Header Revision 0x%x\n", mc_header->hdrver);
-       pr_debug("   Loader Revision 0x%x\n", mc_header->ldrver);
-       pr_debug("   Revision 0x%x \n", mc_header->rev);
-       pr_debug("   Date %x/%x/%x\n",
-               ((mc_header->date >> 24 ) & 0xff),
-               ((mc_header->date >> 16 ) & 0xff),
-               (mc_header->date & 0xFFFF));
-       pr_debug("   Signature 0x%x\n", sig);
-       pr_debug("   Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
-               ((sig >> 12) & 0x3),
-               ((sig >> 8) & 0xf),
-               ((sig >> 4) & 0xf),
-               ((sig & 0xf)));
-       pr_debug("   Processor Flags 0x%x\n", pf);
-       pr_debug("   Checksum 0x%x\n", cksum);
-
-       if (mc_header->rev < uci->rev) {
-               if (uci->err == MC_NOTFOUND) {
-                       uci->err = MC_IGNORED;
-                       uci->cksum = mc_header->rev;
-               } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
-                       uci->cksum = mc_header->rev;
-       } else if (mc_header->rev == uci->rev) {
-               if (uci->err < MC_MARKED) {
-                       /* notify the caller of success on this cpu */
-                       uci->err = MC_SUCCESS;
-               }
-       } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
-               pr_debug("microcode: CPU%d found a matching microcode update with "
-                       " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
-               uci->cksum = cksum;
-               uci->pf = pf; /* keep the original mc pf for cksum calculation */
-               uci->err = MC_MARKED; /* found the match */
-               for_each_online_cpu(cpu_num) {
-                       if (ucode_cpu_info + cpu_num != uci
-                           && ucode_cpu_info[cpu_num].mc == uci->mc) {
-                               uci->mc = NULL;
-                               break;
-                       }
-               }
-               if (uci->mc != NULL) {
-                       vfree(uci->mc);
-                       uci->mc = NULL;
-               }
-       }
-       return;
+       if (!sigmatch(sig, uci->sig, pf, uci->pf)
+               || mc_header->rev <= uci->rev)
+               return 0;
+       return 1;
 }
 
-static int find_matching_ucodes (void) 
+static int microcode_sanity_check(void *mc)
 {
-       int cursor = 0;
-       int error = 0;
-
-       while (cursor + MC_HEADER_SIZE < user_buffer_size) {
-               microcode_header_t mc_header;
-               void *newmc = NULL;
-               int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size;
+       microcode_header_t *mc_header = mc;
+       struct extended_sigtable *ext_header = NULL;
+       struct extended_signature *ext_sig;
+       unsigned long total_size, data_size, ext_table_size;
+       int sum, orig_sum, ext_sigcount = 0, i;
+
+       total_size = get_totalsize(mc_header);
+       data_size = get_datasize(mc_header);
+       if (data_size + MC_HEADER_SIZE > total_size) {
+               printk(KERN_ERR "microcode: error! "
+                       "Bad data size in microcode data file\n");
+               return -EINVAL;
+       }
 
-               if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) {
-                       printk(KERN_ERR "microcode: error! Can not read user data\n");
-                       error = -EFAULT;
-                       goto out;
+       if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+               printk(KERN_ERR "microcode: error! "
+                       "Unknown microcode update format\n");
+               return -EINVAL;
+       }
+       ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+       if (ext_table_size) {
+               if ((ext_table_size < EXT_HEADER_SIZE)
+                || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+                       printk(KERN_ERR "microcode: error! "
+                               "Small exttable size in microcode data file\n");
+                       return -EINVAL;
                }
-
-               total_size = get_totalsize(&mc_header);
-               if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
-                       printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                       error = -EINVAL;
-                       goto out;
+               ext_header = mc + MC_HEADER_SIZE + data_size;
+               if (ext_table_size != exttable_size(ext_header)) {
+                       printk(KERN_ERR "microcode: error! "
+                               "Bad exttable size in microcode data file\n");
+                       return -EFAULT;
                }
+               ext_sigcount = ext_header->count;
+       }
 
-               data_size = get_datasize(&mc_header);
-               if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) {
-                       printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                       error = -EINVAL;
-                       goto out;
+       /* check extended table checksum */
+       if (ext_table_size) {
+               int ext_table_sum = 0;
+               int *ext_tablep = (int *)ext_header;
+
+               i = ext_table_size / DWSIZE;
+               while (i--)
+                       ext_table_sum += ext_tablep[i];
+               if (ext_table_sum) {
+                       printk(KERN_WARNING "microcode: aborting, "
+                               "bad extended signature table checksum\n");
+                       return -EINVAL;
                }
+       }
 
-               if (mc_header.ldrver != 1 || mc_header.hdrver != 1) {
-                       printk(KERN_ERR "microcode: error! Unknown microcode update format\n");
-                       error = -EINVAL;
-                       goto out;
+       /* calculate the checksum */
+       orig_sum = 0;
+       i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+       while (i--)
+               orig_sum += ((int *)mc)[i];
+       if (orig_sum) {
+               printk(KERN_ERR "microcode: aborting, bad checksum\n");
+               return -EINVAL;
+       }
+       if (!ext_table_size)
+               return 0;
+       /* check extended signature checksum */
+       for (i = 0; i < ext_sigcount; i++) {
+               ext_sig = (struct extended_signature *)((void *)ext_header
+                       + EXT_HEADER_SIZE + EXT_SIGNATURE_SIZE * i);
+               sum = orig_sum
+                       - (mc_header->sig + mc_header->pf + mc_header->cksum)
+                       + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+               if (sum) {
+                       printk(KERN_ERR "microcode: aborting, bad checksum\n");
+                       return -EINVAL;
                }
+       }
+       return 0;
+}
 
-               for_each_online_cpu(cpu_num) {
-                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-                       if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf))
-                               mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
-               }
+/*
+ * return 0 - no update found
+ * return 1 - found update
+ * return < 0 - error
+ */
+static int get_maching_microcode(void *mc, int cpu)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+       microcode_header_t *mc_header = mc;
+       struct extended_sigtable *ext_header;
+       unsigned long total_size = get_totalsize(mc_header);
+       int ext_sigcount, i;
+       struct extended_signature *ext_sig;
+       void *new_mc;
+
+       if (microcode_update_match(cpu, mc_header,
+                       mc_header->sig, mc_header->pf))
+               goto find;
+
+       if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
+               return 0;
+
+       ext_header = (struct extended_sigtable *)(mc +
+                       get_datasize(mc_header) + MC_HEADER_SIZE);
+       ext_sigcount = ext_header->count;
+       ext_sig = (struct extended_signature *)((void *)ext_header
+                       + EXT_HEADER_SIZE);
+       for (i = 0; i < ext_sigcount; i++) {
+               if (microcode_update_match(cpu, mc_header,
+                               ext_sig->sig, ext_sig->pf))
+                       goto find;
+               ext_sig++;
+       }
+       return 0;
+find:
+       pr_debug("microcode: CPU %d found a matching microcode update with"
+               " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
+       new_mc = vmalloc(total_size);
+       if (!new_mc) {
+               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+               return -ENOMEM;
+       }
 
-               ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-               if (ext_table_size) {
-                       struct extended_sigtable ext_header;
-                       struct extended_signature ext_sig;
-                       int ext_sigcount;
+       /* free previous update file */
+       vfree(uci->mc);
 
-                       if ((ext_table_size < EXT_HEADER_SIZE) 
-                                       || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
-                               printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                               error = -EINVAL;
-                               goto out;
-                       }
-                       if (copy_from_user(&ext_header, user_buffer + cursor 
-                                       + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {
-                               printk(KERN_ERR "microcode: error! Can not read user data\n");
-                               error = -EFAULT;
-                               goto out;
-                       }
-                       if (ext_table_size != exttable_size(&ext_header)) {
-                               printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                               error = -EFAULT;
-                               goto out;
-                       }
-
-                       ext_sigcount = ext_header.count;
-                       
-                       for (i = 0; i < ext_sigcount; i++) {
-                               if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE 
-                                               + EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {
-                                       printk(KERN_ERR "microcode: error! Can not read user data\n");
-                                       error = -EFAULT;
-                                       goto out;
-                               }
-                               for_each_online_cpu(cpu_num) {
-                                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-                                       if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
-                                               mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
-                                       }
-                               }
-                       }
-               }
-               /* now check if any cpu has matched */
-               allocated_flag = 0;
-               sum = 0;
-               for_each_online_cpu(cpu_num) {
-                       if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 
-                               struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-                               if (!allocated_flag) {
-                                       allocated_flag = 1;
-                                       newmc = vmalloc(total_size);
-                                       if (!newmc) {
-                                               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
-                                               error = -ENOMEM;
-                                               goto out;
-                                       }
-                                       if (copy_from_user(newmc + MC_HEADER_SIZE, 
-                                                               user_buffer + cursor + MC_HEADER_SIZE, 
-                                                               total_size - MC_HEADER_SIZE)) {
-                                               printk(KERN_ERR "microcode: error! Can not read user data\n");
-                                               vfree(newmc);
-                                               error = -EFAULT;
-                                               goto out;
-                                       }
-                                       memcpy(newmc, &mc_header, MC_HEADER_SIZE);
-                                       /* check extended table checksum */
-                                       if (ext_table_size) {
-                                               int ext_table_sum = 0;
-                                               int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);
-                                               i = ext_table_size / DWSIZE;
-                                               while (i--) ext_table_sum += ext_tablep[i];
-                                               if (ext_table_sum) {
-                                                       printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");
-                                                       vfree(newmc);
-                                                       error = -EINVAL;
-                                                       goto out;
-                                               }
-                                       }
-
-                                       /* calculate the checksum */
-                                       i = (MC_HEADER_SIZE + data_size) / DWSIZE;
-                                       while (i--) sum += ((int *)newmc)[i];
-                                       sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);
-                               }
-                               ucode_cpu_info[cpu_num].mc = newmc;
-                               ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */
-                               if (sum + uci->sig + uci->pf + uci->cksum != 0) {
-                                       printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);
-                                       error = -EINVAL;
-                                       goto out;
-                               }
-                       }
-               }
-               cursor += total_size; /* goto the next update patch */
-       } /* end of while */
-out:
-       return error;
+       memcpy(new_mc, mc, total_size);
+       uci->mc = new_mc;
+       return 1;
 }
 
-static void do_update_one (void * unused)
+static void apply_microcode(int cpu)
 {
        unsigned long flags;
        unsigned int val[2];
-       int cpu_num = smp_processor_id();
+       int cpu_num = raw_smp_processor_id();
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
-       if (uci->mc == NULL) {
-               if (verbose) {
-                       if (uci->err == MC_SUCCESS)
-                               printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
-                                       cpu_num, uci->rev);
-                       else
-                               printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
-               }
+       /* We should bind the task to the CPU */
+       BUG_ON(cpu_num != cpu);
+
+       if (uci->mc == NULL)
                return;
-       }
 
        /* serialize access to the physical write to MSR 0x79 */
        spin_lock_irqsave(&microcode_update_lock, flags);          
@@ -408,68 +335,107 @@ static void do_update_one (void * unused)
        /* get the current revision from MSR 0x8B */
        rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-       /* notify the caller of success on this cpu */
-       uci->err = MC_SUCCESS;
        spin_unlock_irqrestore(&microcode_update_lock, flags);
-       printk(KERN_INFO "microcode: CPU%d updated from revision "
+       if (val[1] != uci->mc->hdr.rev) {
+               printk(KERN_ERR "microcode: CPU%d updated from revision "
+                       "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
+               return;
+       }
+       pr_debug("microcode: CPU%d updated from revision "
               "0x%x to 0x%x, date = %08x \n", 
               cpu_num, uci->rev, val[1], uci->mc->hdr.date);
-       return;
+       uci->rev = val[1];
 }
 
-static int do_microcode_update (void)
-{
-       int i, error;
+#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+static void __user *user_buffer;       /* user area microcode data buffer */
+static unsigned int user_buffer_size;  /* it's size */
 
-       if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
-               error = -EIO;
-               goto out;
+static long get_next_ucode(void **mc, long offset)
+{
+       microcode_header_t mc_header;
+       unsigned long total_size;
+
+       /* No more data */
+       if (offset >= user_buffer_size)
+               return 0;
+       if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
+               printk(KERN_ERR "microcode: error! Can not read user data\n");
+               return -EFAULT;
        }
-
-       if ((error = find_matching_ucodes())) {
-               printk(KERN_ERR "microcode: Error in the microcode data\n");
-               goto out_free;
+       total_size = get_totalsize(&mc_header);
+       if (offset + total_size > user_buffer_size) {
+               printk(KERN_ERR "microcode: error! Bad total size in microcode "
+                               "data file\n");
+               return -EINVAL;
        }
-
-       if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
-               error = -EIO;
+       *mc = vmalloc(total_size);
+       if (!*mc)
+               return -ENOMEM;
+       if (copy_from_user(*mc, user_buffer + offset, total_size)) {
+               printk(KERN_ERR "microcode: error! Can not read user data\n");
+               vfree(*mc);
+               return -EFAULT;
        }
+       return offset + total_size;
+}
+
+static int do_microcode_update (void)
+{
+       long cursor = 0;
+       int error = 0;
+       void *new_mc;
+       int cpu;
+       cpumask_t old;
+
+       old = current->cpus_allowed;
 
-out_free:
-       for_each_online_cpu(i) {
-               if (ucode_cpu_info[i].mc) {
-                       int j;
-                       void *tmp = ucode_cpu_info[i].mc;
-                       vfree(tmp);
-                       for_each_online_cpu(j) {
-                               if (ucode_cpu_info[j].mc == tmp)
-                                       ucode_cpu_info[j].mc = NULL;
-                       }
+       while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
+               error = microcode_sanity_check(new_mc);
+               if (error)
+                       goto out;
+               /*
+                * It's possible the data file has multiple matching ucode,
+                * lets keep searching till the latest version
+                */
+               for_each_online_cpu(cpu) {
+                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+                       if (!uci->valid)
+                               continue;
+                       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+                       error = get_maching_microcode(new_mc, cpu);
+                       if (error < 0)
+                               goto out;
+                       if (error == 1)
+                               apply_microcode(cpu);
                }
-               if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
-                       printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
-                              " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
+               vfree(new_mc);
        }
 out:
+       if (cursor > 0)
+               vfree(new_mc);
+       if (cursor < 0)
+               error = cursor;
+       set_cpus_allowed(current, old);
        return error;
 }
 
+static int microcode_open (struct inode *unused1, struct file *unused2)
+{
+       return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
 static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
 {
        ssize_t ret;
 
-       if (len < DEFAULT_UCODE_TOTALSIZE) {
-               printk(KERN_ERR "microcode: not enough data\n"); 
-               return -EINVAL;
-       }
-
        if ((len >> PAGE_SHIFT) > num_physpages) {
                printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
                return -EINVAL;
        }
 
+       lock_cpu_hotplug();
        mutex_lock(&microcode_mutex);
 
        user_buffer = (void __user *) buf;
@@ -480,6 +446,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
                ret = (ssize_t)len;
 
        mutex_unlock(&microcode_mutex);
+       unlock_cpu_hotplug();
 
        return ret;
 }
@@ -496,7 +463,7 @@ static struct miscdevice microcode_dev = {
        .fops           = &microcode_fops,
 };
 
-static int __init microcode_init (void)
+static int __init microcode_dev_init (void)
 {
        int error;
 
@@ -508,6 +475,280 @@ static int __init microcode_init (void)
                return error;
        }
 
+       return 0;
+}
+
+static void __exit microcode_dev_exit (void)
+{
+       misc_deregister(&microcode_dev);
+}
+
+MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+#else
+#define microcode_dev_init() 0
+#define microcode_dev_exit() do { } while(0)
+#endif
+
+static long get_next_ucode_from_buffer(void **mc, void *buf,
+       unsigned long size, long offset)
+{
+       microcode_header_t *mc_header;
+       unsigned long total_size;
+
+       /* No more data */
+       if (offset >= size)
+               return 0;
+       mc_header = (microcode_header_t *)(buf + offset);
+       total_size = get_totalsize(mc_header);
+
+       if (offset + total_size > size) {
+               printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+               return -EINVAL;
+       }
+
+       *mc = vmalloc(total_size);
+       if (!*mc) {
+               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+               return -ENOMEM;
+       }
+       memcpy(*mc, buf + offset, total_size);
+       return offset + total_size;
+}
+
+/* fake device for request_firmware */
+static struct platform_device *microcode_pdev;
+
+static int cpu_request_microcode(int cpu)
+{
+       char name[30];
+       struct cpuinfo_x86 *c = cpu_data + cpu;
+       const struct firmware *firmware;
+       void *buf;
+       unsigned long size;
+       long offset = 0;
+       int error;
+       void *mc;
+
+       /* We should bind the task to the CPU */
+       BUG_ON(cpu != raw_smp_processor_id());
+       sprintf(name,"intel-ucode/%02x-%02x-%02x",
+               c->x86, c->x86_model, c->x86_mask);
+       error = request_firmware(&firmware, name, &microcode_pdev->dev);
+       if (error) {
+               pr_debug("ucode data file %s load failed\n", name);
+               return error;
+       }
+       buf = (void *)firmware->data;
+       size = firmware->size;
+       while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
+                       > 0) {
+               error = microcode_sanity_check(mc);
+               if (error)
+                       break;
+               error = get_maching_microcode(mc, cpu);
+               if (error < 0)
+                       break;
+               /*
+                * It's possible the data file has multiple matching ucode,
+                * lets keep searching till the latest version
+                */
+               if (error == 1) {
+                       apply_microcode(cpu);
+                       error = 0;
+               }
+               vfree(mc);
+       }
+       if (offset > 0)
+               vfree(mc);
+       if (offset < 0)
+               error = offset;
+       release_firmware(firmware);
+
+       return error;
+}
+
+static void microcode_init_cpu(int cpu)
+{
+       cpumask_t old;
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+       old = current->cpus_allowed;
+
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       mutex_lock(&microcode_mutex);
+       collect_cpu_info(cpu);
+       if (uci->valid)
+               cpu_request_microcode(cpu);
+       mutex_unlock(&microcode_mutex);
+       set_cpus_allowed(current, old);
+}
+
+static void microcode_fini_cpu(int cpu)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+       mutex_lock(&microcode_mutex);
+       uci->valid = 0;
+       vfree(uci->mc);
+       uci->mc = NULL;
+       mutex_unlock(&microcode_mutex);
+}
+
+static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+       char *end;
+       unsigned long val = simple_strtoul(buf, &end, 0);
+       int err = 0;
+       int cpu = dev->id;
+
+       if (end == buf)
+               return -EINVAL;
+       if (val == 1) {
+               cpumask_t old;
+
+               old = current->cpus_allowed;
+
+               lock_cpu_hotplug();
+               set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+               mutex_lock(&microcode_mutex);
+               if (uci->valid)
+                       err = cpu_request_microcode(cpu);
+               mutex_unlock(&microcode_mutex);
+               unlock_cpu_hotplug();
+               set_cpus_allowed(current, old);
+       }
+       if (err)
+               return err;
+       return sz;
+}
+
+static ssize_t version_show(struct sys_device *dev, char *buf)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+
+       return sprintf(buf, "0x%x\n", uci->rev);
+}
+
+static ssize_t pf_show(struct sys_device *dev, char *buf)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+
+       return sprintf(buf, "0x%x\n", uci->pf);
+}
+
+static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
+static SYSDEV_ATTR(version, 0400, version_show, NULL);
+static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
+
+static struct attribute *mc_default_attrs[] = {
+       &attr_reload.attr,
+       &attr_version.attr,
+       &attr_processor_flags.attr,
+       NULL
+};
+
+static struct attribute_group mc_attr_group = {
+       .attrs = mc_default_attrs,
+       .name = "microcode",
+};
+
+static int mc_sysdev_add(struct sys_device *sys_dev)
+{
+       int cpu = sys_dev->id;
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+       if (!cpu_online(cpu))
+               return 0;
+       pr_debug("Microcode:CPU %d added\n", cpu);
+       memset(uci, 0, sizeof(*uci));
+       sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+
+       microcode_init_cpu(cpu);
+       return 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);
+       microcode_fini_cpu(cpu);
+       sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+       return 0;
+}
+
+static int mc_sysdev_resume(struct sys_device *dev)
+{
+       int cpu = dev->id;
+
+       if (!cpu_online(cpu))
+               return 0;
+       pr_debug("Microcode:CPU %d resumed\n", cpu);
+       /* only CPU 0 will apply ucode here */
+       apply_microcode(0);
+       return 0;
+}
+
+static struct sysdev_driver mc_sysdev_driver = {
+       .add = mc_sysdev_add,
+       .remove = mc_sysdev_remove,
+       .resume = mc_sysdev_resume,
+};
+
+#ifdef CONFIG_HOTPLUG_CPU
+static __cpuinit int
+mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct sys_device *sys_dev;
+
+       sys_dev = get_cpu_sysdev(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_DOWN_FAILED:
+               mc_sysdev_add(sys_dev);
+               break;
+       case CPU_DOWN_PREPARE:
+               mc_sysdev_remove(sys_dev);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block mc_cpu_notifier = {
+       .notifier_call = mc_cpu_callback,
+};
+#endif
+
+static int __init microcode_init (void)
+{
+       int error;
+
+       error = microcode_dev_init();
+       if (error)
+               return error;
+       microcode_pdev = platform_device_register_simple("microcode", -1,
+                                                        NULL, 0);
+       if (IS_ERR(microcode_pdev)) {
+               microcode_dev_exit();
+               return PTR_ERR(microcode_pdev);
+       }
+
+       lock_cpu_hotplug();
+       error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
+       unlock_cpu_hotplug();
+       if (error) {
+               microcode_dev_exit();
+               platform_device_unregister(microcode_pdev);
+               return error;
+       }
+
+       register_hotcpu_notifier(&mc_cpu_notifier);
+
        printk(KERN_INFO 
                "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
        return 0;
@@ -515,9 +756,16 @@ static int __init microcode_init (void)
 
 static void __exit microcode_exit (void)
 {
-       misc_deregister(&microcode_dev);
+       microcode_dev_exit();
+
+       unregister_hotcpu_notifier(&mc_cpu_notifier);
+
+       lock_cpu_hotplug();
+       sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
+       unlock_cpu_hotplug();
+
+       platform_device_unregister(microcode_pdev);
 }
 
 module_init(microcode_init)
 module_exit(microcode_exit)
-MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
index dbda706fdd14e9e704ee1ab846b3ba361ddeaaf3..3e8e3adb04896243323922cc0dadf3b94429c0c1 100644 (file)
@@ -13,7 +13,6 @@
  *  Mikael Pettersson  : PM converted to driver model. Disable/enable API.
  */
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -31,6 +30,9 @@
 
 #include "mach_traps.h"
 
+int unknown_nmi_panic;
+int nmi_watchdog_enabled;
+
 /* perfctr_nmi_owner tracks the ownership of the perfctr registers:
  * evtsel_nmi_owner tracks the ownership of the event selection
  * - different performance counters/ event selection may be reserved for
index 8c190ca7ae4494b980b01c8a4c88eee291a3fd45..96cd0232e1e03ad24638a6837e024de24ecd0c79 100644 (file)
@@ -425,13 +425,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 
        tsk = current;
        if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
-               p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+               p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
+                                               IO_BITMAP_BYTES, GFP_KERNEL);
                if (!p->thread.io_bitmap_ptr) {
                        p->thread.io_bitmap_max = 0;
                        return -ENOMEM;
                }
-               memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
-                       IO_BITMAP_BYTES);
                set_tsk_thread_flag(p, TIF_IO_BITMAP);
        }
 
index 76a524b4c90f9b9401eb27a9664ffae3db52bd15..000cf03751fe9fd88280ea6938837c3f49126cac 100644 (file)
@@ -209,9 +209,6 @@ static struct resource adapter_rom_resources[] = { {
        .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
 } };
 
-#define ADAPTER_ROM_RESOURCES \
-       (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
-
 static struct resource video_rom_resource = {
        .name   = "Video ROM",
        .start  = 0xc0000,
@@ -273,9 +270,6 @@ static struct resource standard_io_resources[] = { {
        .flags  = IORESOURCE_BUSY | IORESOURCE_IO
 } };
 
-#define STANDARD_IO_RESOURCES \
-       (sizeof standard_io_resources / sizeof standard_io_resources[0])
-
 #define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
 
 static int __init romchecksum(unsigned char *rom, unsigned long length)
@@ -332,7 +326,7 @@ static void __init probe_roms(void)
        }
 
        /* check for adapter roms on 2k boundaries */
-       for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
+       for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
                rom = isa_bus_to_virt(start);
                if (!romsignature(rom))
                        continue;
@@ -1089,22 +1083,20 @@ static unsigned long __init setup_memory(void)
 
 void __init zone_sizes_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-       unsigned int max_dma, low;
-
-       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-       low = max_low_pfn;
-
-       if (low < max_dma)
-               zones_size[ZONE_DMA] = low;
-       else {
-               zones_size[ZONE_DMA] = max_dma;
-               zones_size[ZONE_NORMAL] = low - max_dma;
 #ifdef CONFIG_HIGHMEM
-               zones_size[ZONE_HIGHMEM] = highend_pfn - low;
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+                       virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+                       max_low_pfn,
+                       highend_pfn};
+       add_active_range(0, 0, highend_pfn);
+#else
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+                       virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+                       max_low_pfn};
+       add_active_range(0, 0, max_low_pfn);
 #endif
-       }
-       free_area_init(zones_size);
+
+       free_area_init_nodes(max_zone_pfns);
 }
 #else
 extern unsigned long __init setup_memory(void);
@@ -1274,7 +1266,7 @@ static int __init request_standard_resources(void)
        request_resource(&iomem_resource, &video_ram_resource);
 
        /* request I/O space for devices used on all i[345]86 PCs */
-       for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+       for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
                request_resource(&ioport_resource, &standard_io_resources[i]);
        return 0;
 }
index 465188e2d701779878b7363fd8cf46e24ae6f4e0..1b080ab8a49fad87d600b397d12748393d46ed6e 100644 (file)
@@ -700,3 +700,30 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
        return 0;
 }
 EXPORT_SYMBOL(smp_call_function_single);
+
+static int convert_apicid_to_cpu(int apic_id)
+{
+       int i;
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (x86_cpu_to_apicid[i] == apic_id)
+                       return i;
+       }
+       return -1;
+}
+
+int safe_smp_processor_id(void)
+{
+       int apicid, cpuid;
+
+       if (!boot_cpu_has(X86_FEATURE_APIC))
+               return 0;
+
+       apicid = hard_smp_processor_id();
+       if (apicid == BAD_APICID)
+               return 0;
+
+       cpuid = convert_apicid_to_cpu(apicid);
+
+       return cpuid >= 0 ? cpuid : 0;
+}
index 020d873b7d2130584e84906186703c8cd6079498..0831f709f7771493d09f6e662eddd6950aeabe81 100644 (file)
@@ -102,6 +102,8 @@ u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly =
                        { [0 ... NR_CPUS-1] = 0xff };
 EXPORT_SYMBOL(x86_cpu_to_apicid);
 
+u8 apicid_2_node[MAX_APICID];
+
 /*
  * Trampoline 80x86 program as an array.
  */
@@ -645,7 +647,7 @@ static void map_cpu_to_logical_apicid(void)
 {
        int cpu = smp_processor_id();
        int apicid = logical_smp_processor_id();
-       int node = apicid_to_node(apicid);
+       int node = apicid_to_node(hard_smp_processor_id());
 
        if (!node_online(node))
                node = first_online_node;
@@ -954,6 +956,7 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
 
        irq_ctx_init(cpu);
 
+       x86_cpu_to_apicid[cpu] = apicid;
        /*
         * This grunge runs the startup process for
         * the targeted processor.
@@ -1058,7 +1061,7 @@ static void __cpuinit do_warm_boot_cpu(void *p)
 
 static int __cpuinit __smp_prepare_cpu(int cpu)
 {
-       DECLARE_COMPLETION(done);
+       DECLARE_COMPLETION_ONSTACK(done);
        struct warm_boot_cpu_info info;
        struct work_struct task;
        int     apicid, ret;
index 83db411b3aa7a4be27fc987a14666629616ea200..f7e735c077c35df71c4ae0c2262113f3ea7a92e4 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/nodemask.h>
 #include <asm/srat.h>
 #include <asm/topology.h>
+#include <asm/smp.h>
 
 /*
  * proximity macros and definitions
@@ -54,8 +55,7 @@ struct node_memory_chunk_s {
 static struct node_memory_chunk_s node_memory_chunk[MAXCHUNKS];
 
 static int num_memory_chunks;          /* total number of memory chunks */
-static int zholes_size_init;
-static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
+static u8 __initdata apicid_to_pxm[MAX_APICID];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -71,6 +71,8 @@ static void __init parse_cpu_affinity_structure(char *p)
        /* mark this node as "seen" in node bitmap */
        BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain);
 
+       apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain;
+
        printk("CPU 0x%02X in proximity domain 0x%02X\n",
                cpu_affinity->apic_id, cpu_affinity->proximity_domain);
 }
@@ -135,47 +137,6 @@ static void __init parse_memory_affinity_structure (char *sratp)
                 "enabled and removable" : "enabled" ) );
 }
 
-/* Take a chunk of pages from page frame cstart to cend and count the number
- * of pages in each zone, returned via zones[].
- */
-static __init void chunk_to_zones(unsigned long cstart, unsigned long cend, 
-               unsigned long *zones)
-{
-       unsigned long max_dma;
-       extern unsigned long max_low_pfn;
-
-       int z;
-       unsigned long rend;
-
-       /* FIXME: MAX_DMA_ADDRESS and max_low_pfn are trying to provide
-        * similarly scoped information and should be handled in a consistant
-        * manner.
-        */
-       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
-       /* Split the hole into the zones in which it falls.  Repeatedly
-        * take the segment in which the remaining hole starts, round it
-        * to the end of that zone.
-        */
-       memset(zones, 0, MAX_NR_ZONES * sizeof(long));
-       while (cstart < cend) {
-               if (cstart < max_dma) {
-                       z = ZONE_DMA;
-                       rend = (cend < max_dma)? cend : max_dma;
-
-               } else if (cstart < max_low_pfn) {
-                       z = ZONE_NORMAL;
-                       rend = (cend < max_low_pfn)? cend : max_low_pfn;
-
-               } else {
-                       z = ZONE_HIGHMEM;
-                       rend = cend;
-               }
-               zones[z] += rend - cstart;
-               cstart = rend;
-       }
-}
-
 /*
  * The SRAT table always lists ascending addresses, so can always
  * assume that the first "start" address that you see is the real
@@ -220,7 +181,6 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 
        memset(pxm_bitmap, 0, sizeof(pxm_bitmap));      /* init proximity domain bitmap */
        memset(node_memory_chunk, 0, sizeof(node_memory_chunk));
-       memset(zholes_size, 0, sizeof(zholes_size));
 
        num_memory_chunks = 0;
        while (p < end) {
@@ -279,11 +239,15 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
        printk("Number of logical nodes in system = %d\n", num_online_nodes());
        printk("Number of memory chunks in system = %d\n", num_memory_chunks);
 
+       for (i = 0; i < MAX_APICID; i++)
+               apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]);
+
        for (j = 0; j < num_memory_chunks; j++){
                struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
                printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
                       j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
                node_read_chunk(chunk->nid, chunk);
+               add_active_range(chunk->nid, chunk->start_pfn, chunk->end_pfn);
        }
  
        for_each_online_node(nid) {
@@ -392,57 +356,7 @@ int __init get_memcfg_from_srat(void)
                return acpi20_parse_srat((struct acpi_table_srat *)header);
        }
 out_err:
+       remove_all_active_ranges();
        printk("failed to get NUMA memory information from SRAT table\n");
        return 0;
 }
-
-/* For each node run the memory list to determine whether there are
- * any memory holes.  For each hole determine which ZONE they fall
- * into.
- *
- * NOTE#1: this requires knowledge of the zone boundries and so
- * _cannot_ be performed before those are calculated in setup_memory.
- * 
- * NOTE#2: we rely on the fact that the memory chunks are ordered by
- * start pfn number during setup.
- */
-static void __init get_zholes_init(void)
-{
-       int nid;
-       int c;
-       int first;
-       unsigned long end = 0;
-
-       for_each_online_node(nid) {
-               first = 1;
-               for (c = 0; c < num_memory_chunks; c++){
-                       if (node_memory_chunk[c].nid == nid) {
-                               if (first) {
-                                       end = node_memory_chunk[c].end_pfn;
-                                       first = 0;
-
-                               } else {
-                                       /* Record any gap between this chunk
-                                        * and the previous chunk on this node
-                                        * against the zones it spans.
-                                        */
-                                       chunk_to_zones(end,
-                                               node_memory_chunk[c].start_pfn,
-                                               &zholes_size[nid * MAX_NR_ZONES]);
-                               }
-                       }
-               }
-       }
-}
-
-unsigned long * __init get_zholes_size(int nid)
-{
-       if (!zholes_size_init) {
-               zholes_size_init++;
-               get_zholes_init();
-       }
-       if (nid >= MAX_NUMNODES || !node_online(nid))
-               printk("%s: nid = %d is invalid/offline. num_online_nodes = %d",
-                      __FUNCTION__, nid, num_online_nodes());
-       return &zholes_size[nid * MAX_NR_ZONES];
-}
index 86944acfb647228186544f2c8ce3375b9c5d6efe..58a2d5582419d2051f3e8c7db7082ecaea496f40 100644 (file)
@@ -76,8 +76,6 @@ int pit_latch_buggy;              /* extern */
 unsigned int cpu_khz;  /* Detected as we calibrate the TSC */
 EXPORT_SYMBOL(cpu_khz);
 
-extern unsigned long wall_jiffies;
-
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
@@ -329,7 +327,6 @@ static int timer_resume(struct sys_device *dev)
        do_settimeofday(&ts);
        write_seqlock_irqsave(&xtime_lock, flags);
        jiffies_64 += sleep_length;
-       wall_jiffies += sleep_length;
        write_sequnlock_irqrestore(&xtime_lock, flags);
        touch_softlockup_watchdog();
        return 0;
index 21aa1cd5777317d3b079db3e781fbadae2c7e2a6..6820b8d643c7779a07328a1668fc41e4e8035542 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
 #include <linux/unwind.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -40,7 +41,6 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
 #include <asm/debugreg.h>
@@ -57,6 +57,8 @@
 
 #include "mach_traps.h"
 
+int panic_on_unrecovered_nmi;
+
 asmlinkage int system_call(void);
 
 struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
@@ -409,7 +411,7 @@ static void handle_BUG(struct pt_regs *regs)
 
        if (eip < PAGE_OFFSET)
                return;
-       if (__get_user(ud2, (unsigned short __user *)eip))
+       if (probe_kernel_address((unsigned short __user *)eip, ud2))
                return;
        if (ud2 != 0x0b0f)
                return;
@@ -422,7 +424,8 @@ static void handle_BUG(struct pt_regs *regs)
                char *file;
                char c;
 
-               if (__get_user(line, (unsigned short __user *)(eip + 2)))
+               if (probe_kernel_address((unsigned short __user *)(eip + 2),
+                                       line))
                        break;
                if (__get_user(file, (char * __user *)(eip + 4)) ||
                    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
index 3c0714c4b6691aaa7e256cce82262603cc82276c..f6edb11364dfe5edef9ffac33341b24307a85434 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 
index efc7e7d5f4d0f518847b5232f38aad75ea9367f4..08502fc6d0cb8d0fc819682d26b499e5aab08efb 100644 (file)
@@ -739,7 +739,7 @@ survive:
                        retval = get_user_pages(current, current->mm,
                                        (unsigned long )to, 1, 1, 0, &pg, NULL);
 
-                       if (retval == -ENOMEM && current->pid == 1) {
+                       if (retval == -ENOMEM && is_init(current)) {
                                up_read(&current->mm->mmap_sem);
                                blk_congestion_wait(WRITE, HZ/50);
                                goto survive;
index 6c86575ffdcb250a7168d3922d4b977a61bbed32..856c73fcb7e76b0fcc27aa7956ce1ed0258384df 100644 (file)
@@ -99,6 +99,7 @@ static void do_boot_cpu(__u8 cpuid);
 static void do_quad_bootstrap(void);
 
 int hard_smp_processor_id(void);
+int safe_smp_processor_id(void);
 
 /* Inline functions */
 static inline void
@@ -1247,6 +1248,12 @@ hard_smp_processor_id(void)
        return 0;
 }
 
+int
+safe_smp_processor_id(void)
+{
+       return hard_smp_processor_id();
+}
+
 /* broadcast a halt to all other CPUs */
 void
 smp_send_stop(void)
index 941d1a5ebabbf798b82ff4b7b35d9bdd56cd7df8..51e3739dd22700f13a28a0627163fcc6bfb94bb0 100644 (file)
@@ -157,21 +157,6 @@ static void __init find_max_pfn_node(int nid)
                BUG();
 }
 
-/* Find the owning node for a pfn. */
-int early_pfn_to_nid(unsigned long pfn)
-{
-       int nid;
-
-       for_each_node(nid) {
-               if (node_end_pfn[nid] == 0)
-                       break;
-               if (node_start_pfn[nid] <= pfn && node_end_pfn[nid] >= pfn)
-                       return nid;
-       }
-
-       return 0;
-}
-
 /* 
  * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
  * method.  For node zero take this from the bottom of memory, for
@@ -227,6 +212,8 @@ static unsigned long calculate_numa_remap_pages(void)
        unsigned long pfn;
 
        for_each_online_node(nid) {
+               unsigned old_end_pfn = node_end_pfn[nid];
+
                /*
                 * The acpi/srat node info can show hot-add memroy zones
                 * where memory could be added but not currently present.
@@ -276,6 +263,7 @@ static unsigned long calculate_numa_remap_pages(void)
 
                node_end_pfn[nid] -= size;
                node_remap_start_pfn[nid] = node_end_pfn[nid];
+               shrink_active_range(nid, old_end_pfn, node_end_pfn[nid]);
        }
        printk("Reserving total of %ld pages for numa KVA remap\n",
                        reserve_pages);
@@ -369,45 +357,22 @@ void __init numa_kva_reserve(void)
 void __init zone_sizes_init(void)
 {
        int nid;
-
-
-       for_each_online_node(nid) {
-               unsigned long zones_size[MAX_NR_ZONES] = {0, };
-               unsigned long *zholes_size;
-               unsigned int max_dma;
-
-               unsigned long low = max_low_pfn;
-               unsigned long start = node_start_pfn[nid];
-               unsigned long high = node_end_pfn[nid];
-
-               max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
-               if (node_has_online_mem(nid)){
-                       if (start > low) {
-#ifdef CONFIG_HIGHMEM
-                               BUG_ON(start > high);
-                               zones_size[ZONE_HIGHMEM] = high - start;
-#endif
-                       } else {
-                               if (low < max_dma)
-                                       zones_size[ZONE_DMA] = low;
-                               else {
-                                       BUG_ON(max_dma > low);
-                                       BUG_ON(low > high);
-                                       zones_size[ZONE_DMA] = max_dma;
-                                       zones_size[ZONE_NORMAL] = low - max_dma;
-#ifdef CONFIG_HIGHMEM
-                                       zones_size[ZONE_HIGHMEM] = high - low;
-#endif
-                               }
-                       }
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+               virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+               max_low_pfn,
+               highend_pfn
+       };
+
+       /* If SRAT has not registered memory, register it now */
+       if (find_max_pfn_with_active_regions() == 0) {
+               for_each_online_node(nid) {
+                       if (node_has_online_mem(nid))
+                               add_active_range(nid, node_start_pfn[nid],
+                                                       node_end_pfn[nid]);
                }
-
-               zholes_size = get_zholes_size(nid);
-
-               free_area_init_node(nid, NODE_DATA(nid), zones_size, start,
-                               zholes_size);
        }
+
+       free_area_init_nodes(max_zone_pfns);
        return;
 }
 
index 5e17a3f43b41ba89c15b17e7390f04dc730ada64..2581575786c135a0a0201cf63caf754a8654a755 100644 (file)
@@ -440,7 +440,7 @@ good_area:
                case 1:         /* read, present */
                        goto bad_area;
                case 0:         /* read, not present */
-                       if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                       if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                                goto bad_area;
        }
 
@@ -589,7 +589,7 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (tsk->pid == 1) {
+       if (is_init(tsk)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index ba44000b9069f5376d64304fafdf43ddcd4987f7..f9f647cdbc7ba3550e83d82c0c9e6996b3ae8878 100644 (file)
@@ -38,22 +38,19 @@ void *kmap_atomic(struct page *page, enum km_type type)
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
        if (!pte_none(*(kmap_pte-idx)))
                BUG();
-#endif
        set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
-       __flush_tlb_one(vaddr);
 
        return (void*) vaddr;
 }
 
 void kunmap_atomic(void *kvaddr, enum km_type type)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
        enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
+#ifdef CONFIG_DEBUG_HIGHMEM
        if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
                dec_preempt_count();
                preempt_check_resched();
@@ -62,14 +59,14 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
 
        if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
                BUG();
-
+#endif
        /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
+        * Force other mappings to Oops if they'll try to access this pte
+        * without first remap it.  Keeping stale mappings around is a bad idea
+        * also, in case the page changes cacheability attributes or becomes
+        * a protected page in a hypervisor.
         */
-       pte_clear(&init_mm, vaddr, kmap_pte-idx);
-       __flush_tlb_one(vaddr);
-#endif
+       kpte_clear_flush(kmap_pte-idx, vaddr);
 
        dec_preempt_count();
        preempt_check_resched();
@@ -88,7 +85,6 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
-       __flush_tlb_one(vaddr);
 
        return (void*) vaddr;
 }
index 4a5a914b34321bcc69b714ca17223b08bc898edb..90089c14c23d8612673fed024e1a59ae23c98090 100644 (file)
@@ -493,6 +493,7 @@ int __init set_kernel_exec(unsigned long vaddr, int enable)
                pte->pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
        else
                pte->pte_high |= 1 << (_PAGE_BIT_NX - 32);
+       pte_update_defer(&init_mm, vaddr, pte);
        __flush_tlb_all();
 out:
        return ret;
index 247fde76aaeddaf0c81215917a015bda7ea648ae..fff08ae7b5ed57c61767615decca493e3e9c7686 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/fixmap.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #define ISA_START_ADDRESS      0xa0000
 #define ISA_END_ADDRESS                0x100000
 
-static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
-               unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
-       pte_t *pte;
-       unsigned long pfn;
-
-       pfn = phys_addr >> PAGE_SHIFT;
-       pte = pte_alloc_kernel(pmd, addr);
-       if (!pte)
-               return -ENOMEM;
-       do {
-               BUG_ON(!pte_none(*pte));
-               set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW | 
-                                       _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
-               pfn++;
-       } while (pte++, addr += PAGE_SIZE, addr != end);
-       return 0;
-}
-
-static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
-               unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
-       pmd_t *pmd;
-       unsigned long next;
-
-       phys_addr -= addr;
-       pmd = pmd_alloc(&init_mm, pud, addr);
-       if (!pmd)
-               return -ENOMEM;
-       do {
-               next = pmd_addr_end(addr, end);
-               if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, flags))
-                       return -ENOMEM;
-       } while (pmd++, addr = next, addr != end);
-       return 0;
-}
-
-static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
-               unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
-       pud_t *pud;
-       unsigned long next;
-
-       phys_addr -= addr;
-       pud = pud_alloc(&init_mm, pgd, addr);
-       if (!pud)
-               return -ENOMEM;
-       do {
-               next = pud_addr_end(addr, end);
-               if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, flags))
-                       return -ENOMEM;
-       } while (pud++, addr = next, addr != end);
-       return 0;
-}
-
-static int ioremap_page_range(unsigned long addr,
-               unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
-       pgd_t *pgd;
-       unsigned long next;
-       int err;
-
-       BUG_ON(addr >= end);
-       flush_cache_all();
-       phys_addr -= addr;
-       pgd = pgd_offset_k(addr);
-       do {
-               next = pgd_addr_end(addr, end);
-               err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, flags);
-               if (err)
-                       break;
-       } while (pgd++, addr = next, addr != end);
-       flush_tlb_all();
-       return err;
-}
-
 /*
  * Generic mapping function (not visible outside):
  */
@@ -115,6 +39,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        void __iomem * addr;
        struct vm_struct * area;
        unsigned long offset, last_addr;
+       pgprot_t prot;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
@@ -142,6 +67,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
                                return NULL;
        }
 
+       prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
+                       | _PAGE_ACCESSED | flags);
+
        /*
         * Mappings have to be page-aligned
         */
@@ -158,7 +86,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        area->phys_addr = phys_addr;
        addr = (void __iomem *) area->addr;
        if (ioremap_page_range((unsigned long) addr,
-                       (unsigned long) addr + size, phys_addr, flags)) {
+                       (unsigned long) addr + size, phys_addr, prot)) {
                vunmap((void __force *) addr);
                return NULL;
        }
index f88e05ba8eb34acd2aac784da0e9c592dcb20ef4..ca2447e05e15d90a70012e4d2b725c8fa9a47e78 100644 (file)
@@ -138,11 +138,14 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
 static void ppro_start(struct op_msrs const * const msrs)
 {
        unsigned int low,high;
+       int i;
 
-       if (reset_value[0]) {
-               CTRL_READ(low, high, msrs, 0);
-               CTRL_SET_ACTIVE(low);
-               CTRL_WRITE(low, high, msrs, 0);
+       for (i = 0; i < NUM_COUNTERS; ++i) {
+               if (reset_value[i]) {
+                       CTRL_READ(low, high, msrs, i);
+                       CTRL_SET_ACTIVE(low);
+                       CTRL_WRITE(low, high, msrs, i);
+               }
        }
 }
 
@@ -150,11 +153,14 @@ static void ppro_start(struct op_msrs const * const msrs)
 static void ppro_stop(struct op_msrs const * const msrs)
 {
        unsigned int low,high;
+       int i;
 
-       if (reset_value[0]) {
-               CTRL_READ(low, high, msrs, 0);
+       for (i = 0; i < NUM_COUNTERS; ++i) {
+               if (!reset_value[i])
+                       continue;
+               CTRL_READ(low, high, msrs, i);
                CTRL_SET_INACTIVE(low);
-               CTRL_WRITE(low, high, msrs, 0);
+               CTRL_WRITE(low, high, msrs, i);
        }
 }
 
index 05be8db58a8cee783bde63b5f207d7e8137fd7fc..d0c3da3aa2aa9978eef4774c4a61ec97955e2df3 100644 (file)
@@ -67,7 +67,10 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
        return 0;
 }
 
-static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
+/*
+ * This is always called under pci_config_lock
+ */
+static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
 {
        u32 dev_base = base | (bus << 20) | (devfn << 12);
        if (dev_base != mmcfg_last_accessed_device) {
index f521f2f60a7802b65b20289effe6d40d1801439e..0b7f701d5cf7e38253465e82c1261c92dc854a15 100644 (file)
@@ -356,6 +356,9 @@ config NODES_SHIFT
          MAX_NUMNODES will be 2^(This value).
          If in doubt, use the default.
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 # VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
 # VIRTUAL_MEM_MAP has been retained for historical reasons.
 config VIRTUAL_MEM_MAP
@@ -420,6 +423,14 @@ config IA64_PALINFO
 config SGI_SN
        def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
 
+config IA64_ESI
+       bool "ESI (Extensible SAL Interface) support"
+       help
+         If you say Y here, support is built into the kernel to
+         make ESI calls.  ESI calls are used to support vendor-specific
+         firmware extensions, such as the ability to inject memory-errors
+         for test-purposes.  If you're unsure, say N.
+
 source "drivers/sn/Kconfig"
 
 source "drivers/firmware/Kconfig"
index b5195be6281895d3ea6fb42eca4cb4fb5b41308d..e1a1b11473e221a95e2988107f2d45a9572817e8 100644 (file)
@@ -320,7 +320,7 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
        }
 
        printk(KERN_INFO "simeth_device_event: %s ipaddr=0x%x\n",
-              dev->name, htonl(ifa->ifa_local));
+              dev->name, ntohl(ifa->ifa_local));
 
        /*
         * XXX Fix me
@@ -331,7 +331,7 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
        local = dev->priv;
        /* now do it for real */
        r = event == NETDEV_UP ?
-               netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)):
+               netdev_attach(local->simfd, dev->irq, ntohl(ifa->ifa_local)):
                netdev_detach(local->simfd);
 
        printk(KERN_INFO "simeth: netdev_attach/detach: event=%s ->%d\n",
index 6aa3c51619ca77bcb1b88410a21c43e7184aea8a..bddbd22706ed1ad76a791635b621784a80cde5a9 100644 (file)
@@ -1942,7 +1942,7 @@ struct sysctl32 {
        unsigned int    __unused[4];
 };
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 asmlinkage long
 sys32_sysctl (struct sysctl32 __user *args)
 {
index ad8215a3c586948f3cf92c2e6c80f31a5ff36aa5..31497496eb4bf2d2353b99970f84688ec8959a73 100644 (file)
@@ -32,6 +32,11 @@ obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)        += uncached.o
 obj-$(CONFIG_AUDIT)            += audit.o
 mca_recovery-y                 += mca_drv.o mca_drv_asm.o
 
+obj-$(CONFIG_IA64_ESI)         += esi.o
+ifneq ($(CONFIG_IA64_ESI),)
+obj-y                          += esi_stub.o   # must be in kernel proper
+endif
+
 # The gate DSO image is built using a special linker script.
 targets += gate.so gate-syms.o
 
index fef06571be99c9a4edc27caaf04f61e715a3eeef..12701cf32d9944de96a3fa609788d50fc79b8518 100644 (file)
@@ -1605,8 +1605,8 @@ sys_call_table:
        data8 sys_ni_syscall                    // 1295 reserved for ppoll
        data8 sys_unshare
        data8 sys_splice
-       data8 sys_ni_syscall                    // reserved for set_robust_list
-       data8 sys_ni_syscall                    // reserved for get_robust_list
+       data8 sys_set_robust_list
+       data8 sys_get_robust_list
        data8 sys_sync_file_range               // 1300
        data8 sys_tee
        data8 sys_vmsplice
diff --git a/arch/ia64/kernel/esi.c b/arch/ia64/kernel/esi.c
new file mode 100644 (file)
index 0000000..ebf4e98
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Extensible SAL Interface (ESI) support routines.
+ *
+ * Copyright (C) 2006 Hewlett-Packard Co
+ *     Alex Williamson <alex.williamson@hp.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/esi.h>
+#include <asm/sal.h>
+
+MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
+MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
+MODULE_LICENSE("GPL");
+
+#define MODULE_NAME    "esi"
+
+#define ESI_TABLE_GUID                                 \
+    EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3,         \
+            0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
+
+enum esi_systab_entry_type {
+       ESI_DESC_ENTRY_POINT = 0
+};
+
+/*
+ * Entry type: Size:
+ *     0       48
+ */
+#define ESI_DESC_SIZE(type)    "\060"[(unsigned) (type)]
+
+typedef struct ia64_esi_desc_entry_point {
+       u8 type;
+       u8 reserved1[15];
+       u64 esi_proc;
+       u64 gp;
+       efi_guid_t guid;
+} ia64_esi_desc_entry_point_t;
+
+struct pdesc {
+       void *addr;
+       void *gp;
+};
+
+static struct ia64_sal_systab *esi_systab;
+
+static int __init esi_init (void)
+{
+       efi_config_table_t *config_tables;
+       struct ia64_sal_systab *systab;
+       unsigned long esi = 0;
+       char *p;
+       int i;
+
+       config_tables = __va(efi.systab->tables);
+
+       for (i = 0; i < (int) efi.systab->nr_tables; ++i) {
+               if (efi_guidcmp(config_tables[i].guid, ESI_TABLE_GUID) == 0) {
+                       esi = config_tables[i].table;
+                       break;
+               }
+       }
+
+       if (!esi)
+               return -ENODEV;;
+
+       systab = __va(esi);
+
+       if (strncmp(systab->signature, "ESIT", 4) != 0) {
+               printk(KERN_ERR "bad signature in ESI system table!");
+               return -ENODEV;
+       }
+
+       p = (char *) (systab + 1);
+       for (i = 0; i < systab->entry_count; i++) {
+               /*
+                * The first byte of each entry type contains the type
+                * descriptor.
+                */
+               switch (*p) {
+                     case ESI_DESC_ENTRY_POINT:
+                       break;
+                     default:
+                       printk(KERN_WARNING "Unkown table type %d found in "
+                              "ESI table, ignoring rest of table\n", *p);
+                       return -ENODEV;
+               }
+
+               p += ESI_DESC_SIZE(*p);
+       }
+
+       esi_systab = systab;
+       return 0;
+}
+
+
+int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
+                  enum esi_proc_type proc_type, u64 func,
+                  u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
+                  u64 arg7)
+{
+       struct ia64_fpreg fr[6];
+       unsigned long flags = 0;
+       int i;
+       char *p;
+
+       if (!esi_systab)
+               return -1;
+
+       p = (char *) (esi_systab + 1);
+       for (i = 0; i < esi_systab->entry_count; i++) {
+               if (*p == ESI_DESC_ENTRY_POINT) {
+                       ia64_esi_desc_entry_point_t *esi = (void *)p;
+                       if (!efi_guidcmp(guid, esi->guid)) {
+                               ia64_sal_handler esi_proc;
+                               struct pdesc pdesc;
+
+                               pdesc.addr = __va(esi->esi_proc);
+                               pdesc.gp = __va(esi->gp);
+
+                               esi_proc = (ia64_sal_handler) &pdesc;
+
+                               ia64_save_scratch_fpregs(fr);
+                               if (proc_type == ESI_PROC_SERIALIZED)
+                                       spin_lock_irqsave(&sal_lock, flags);
+                               else if (proc_type == ESI_PROC_MP_SAFE)
+                                       local_irq_save(flags);
+                               else
+                                       preempt_disable();
+                               *isrvp = (*esi_proc)(func, arg1, arg2, arg3,
+                                                    arg4, arg5, arg6, arg7);
+                               if (proc_type == ESI_PROC_SERIALIZED)
+                                       spin_unlock_irqrestore(&sal_lock,
+                                                              flags);
+                               else if (proc_type == ESI_PROC_MP_SAFE)
+                                       local_irq_restore(flags);
+                               else
+                                       preempt_enable();
+                               ia64_load_scratch_fpregs(fr);
+                               return 0;
+                       }
+               }
+               p += ESI_DESC_SIZE(*p);
+       }
+       return -1;
+}
+EXPORT_SYMBOL_GPL(ia64_esi_call);
+
+int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
+                       u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
+                       u64 arg5, u64 arg6, u64 arg7)
+{
+       struct ia64_fpreg fr[6];
+       unsigned long flags;
+       u64 esi_params[8];
+       char *p;
+       int i;
+
+       if (!esi_systab)
+               return -1;
+
+       p = (char *) (esi_systab + 1);
+       for (i = 0; i < esi_systab->entry_count; i++) {
+               if (*p == ESI_DESC_ENTRY_POINT) {
+                       ia64_esi_desc_entry_point_t *esi = (void *)p;
+                       if (!efi_guidcmp(guid, esi->guid)) {
+                               ia64_sal_handler esi_proc;
+                               struct pdesc pdesc;
+
+                               pdesc.addr = (void *)esi->esi_proc;
+                               pdesc.gp = (void *)esi->gp;
+
+                               esi_proc = (ia64_sal_handler) &pdesc;
+
+                               esi_params[0] = func;
+                               esi_params[1] = arg1;
+                               esi_params[2] = arg2;
+                               esi_params[3] = arg3;
+                               esi_params[4] = arg4;
+                               esi_params[5] = arg5;
+                               esi_params[6] = arg6;
+                               esi_params[7] = arg7;
+                               ia64_save_scratch_fpregs(fr);
+                               spin_lock_irqsave(&sal_lock, flags);
+                               *isrvp = esi_call_phys(esi_proc, esi_params);
+                               spin_unlock_irqrestore(&sal_lock, flags);
+                               ia64_load_scratch_fpregs(fr);
+                               return 0;
+                       }
+               }
+               p += ESI_DESC_SIZE(*p);
+       }
+       return -1;
+}
+EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
+
+static void __exit esi_exit (void)
+{
+}
+
+module_init(esi_init);
+module_exit(esi_exit); /* makes module removable... */
diff --git a/arch/ia64/kernel/esi_stub.S b/arch/ia64/kernel/esi_stub.S
new file mode 100644 (file)
index 0000000..6b3d6c1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * ESI call stub.
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Alex Williamson <alex.williamson@hp.com>
+ *
+ * Based on EFI call stub by David Mosberger.  The stub is virtually
+ * identical to the one for EFI phys-mode calls, except that ESI
+ * calls may have up to 8 arguments, so they get passed to this routine
+ * through memory.
+ *
+ * This stub allows us to make ESI calls in physical mode with interrupts
+ * turned off.  ESI calls may not support calling from virtual mode.
+ *
+ * Google for "Extensible SAL specification" for a document describing the
+ * ESI standard.
+ */
+
+/*
+ * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
+ * Abstraction Layer Specification", revision 2.6e).  Note that
+ * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
+ * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
+ * (the br.ia instruction fails unless psr.dfl and psr.dfh are
+ * cleared).  Fortunately, SAL promises not to touch the floating
+ * point regs, so at least we don't have to save f2-f127.
+ */
+#define PSR_BITS_TO_CLEAR                                              \
+       (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT |         \
+        IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |        \
+        IA64_PSR_DFL | IA64_PSR_DFH)
+
+#define PSR_BITS_TO_SET                                                        \
+       (IA64_PSR_BN)
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+/*
+ * Inputs:
+ *     in0 = address of function descriptor of ESI routine to call
+ *     in1 = address of array of ESI parameters
+ *
+ * Outputs:
+ *     r8 = result returned by called function
+ */
+GLOBAL_ENTRY(esi_call_phys)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+       alloc loc1=ar.pfs,2,7,8,0
+       ld8 r2=[in0],8                  // load ESI function's entry point
+       mov loc0=rp
+       .body
+       ;;
+       ld8 out0=[in1],8                // ESI params loaded from array
+       ;;                              // passing all as inputs doesn't work
+       ld8 out1=[in1],8
+       ;;
+       ld8 out2=[in1],8
+       ;;
+       ld8 out3=[in1],8
+       ;;
+       ld8 out4=[in1],8
+       ;;
+       ld8 out5=[in1],8
+       ;;
+       ld8 out6=[in1],8
+       ;;
+       ld8 out7=[in1]
+       mov loc2=gp                     // save global pointer
+       mov loc4=ar.rsc                 // save RSE configuration
+       mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
+       ;;
+       ld8 gp=[in0]                    // load ESI function's global pointer
+       movl r16=PSR_BITS_TO_CLEAR
+       mov loc3=psr                    // save processor status word
+       movl r17=PSR_BITS_TO_SET
+       ;;
+       or loc3=loc3,r17
+       mov b6=r2
+       ;;
+       andcm r16=loc3,r16      // get psr with IT, DT, and RT bits cleared
+       br.call.sptk.many rp=ia64_switch_mode_phys
+.ret0: mov loc5=r19                    // old ar.bsp
+       mov loc6=r20                    // old sp
+       br.call.sptk.many rp=b6         // call the ESI function
+.ret1: mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
+       mov r16=loc3                    // save virtual mode psr
+       mov r19=loc5                    // save virtual mode bspstore
+       mov r20=loc6                    // save virtual mode sp
+       br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
+.ret2: mov ar.rsc=loc4                 // restore RSE configuration
+       mov ar.pfs=loc1
+       mov rp=loc0
+       mov gp=loc2
+       br.ret.sptk.many rp
+END(esi_call_phys)
index 3ead20fb6f4b2f45d7ec6f6bee19f82a3d4364af..879c1817bd1c8589c1ff7c85a659e777b67abc50 100644 (file)
@@ -105,5 +105,9 @@ EXPORT_SYMBOL(ia64_spinlock_contention);
 # endif
 #endif
 
+#if defined(CONFIG_IA64_ESI) || defined(CONFIG_IA64_ESI_MODULE)
+extern void esi_call_phys (void);
+EXPORT_SYMBOL_GPL(esi_call_phys);
+#endif
 extern char ia64_ivt[];
 EXPORT_SYMBOL(ia64_ivt);
index 781960f80b6f12c2d7c8be375157086c3b16a72d..169ec3a7156ce4dc349769e90ead997bed4f4329 100644 (file)
@@ -136,10 +136,8 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint  slot,
 static int __kprobes unsupported_inst(uint template, uint  slot,
                                      uint major_opcode,
                                      unsigned long kprobe_inst,
-                                     struct kprobe *p)
+                                     unsigned long addr)
 {
-       unsigned long addr = (unsigned long)p->addr;
-
        if (bundle_encoding[template][slot] == I) {
                switch (major_opcode) {
                        case 0x0: //I_UNIT_MISC_OPCODE:
@@ -217,7 +215,7 @@ static void __kprobes prepare_break_inst(uint template, uint  slot,
                                         struct kprobe *p)
 {
        unsigned long break_inst = BREAK_INST;
-       bundle_t *bundle = &p->ainsn.insn.bundle;
+       bundle_t *bundle = &p->opcode.bundle;
 
        /*
         * Copy the original kprobe_inst qualifying predicate(qp)
@@ -423,11 +421,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
        unsigned long kprobe_inst=0;
        unsigned int slot = addr & 0xf, template, major_opcode = 0;
-       bundle_t *bundle = &p->ainsn.insn.bundle;
-
-       memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
-       memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
+       bundle_t *bundle;
 
+       bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
        template = bundle->quad0.template;
 
        if(valid_kprobe_addr(template, slot, addr))
@@ -440,20 +436,19 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        /* Get kprobe_inst and major_opcode from the bundle */
        get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
 
-       if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
+       if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
                        return -EINVAL;
 
-       prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
 
-       return 0;
-}
+       p->ainsn.insn = get_insn_slot();
+       if (!p->ainsn.insn)
+               return -ENOMEM;
+       memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
+       memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
 
-void __kprobes flush_insn_slot(struct kprobe *p)
-{
-       unsigned long arm_addr;
+       prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
 
-       arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       return 0;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -461,9 +456,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
 
-       flush_insn_slot(p);
-       memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       flush_icache_range((unsigned long)p->ainsn.insn,
+                       (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
+       memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
+       flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
 }
 
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
@@ -471,11 +467,18 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
 
-       /* p->opcode contains the original unaltered bundle */
-       memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
+       memcpy((char *) arm_addr, (char *) p->ainsn.insn,
+                                        sizeof(kprobe_opcode_t));
+       flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
 }
 
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+       mutex_lock(&kprobe_mutex);
+       free_insn_slot(p->ainsn.insn);
+       mutex_unlock(&kprobe_mutex);
+}
 /*
  * We are resuming execution after a single step fault, so the pt_regs
  * structure reflects the register state after we executed the instruction
@@ -486,12 +489,12 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
  */
 static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
-       unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
+       unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
        unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
        unsigned long template;
        int slot = ((unsigned long)p->addr & 0xf);
 
-       template = p->opcode.bundle.quad0.template;
+       template = p->ainsn.insn->bundle.quad0.template;
 
        if (slot == 1 && bundle_encoding[template][1] == L)
                slot = 2;
@@ -553,7 +556,7 @@ turn_ss_off:
 
 static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
 {
-       unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
+       unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
        unsigned long slot = (unsigned long)p->addr & 0xf;
 
        /* single step inline if break instruction */
@@ -768,6 +771,12 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
                 */
                if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
                        return 1;
+               /*
+                * In case the user-specified fault handler returned
+                * zero, try to fix up.
+                */
+               if (ia64_done_with_exception(regs))
+                       return 1;
 
                /*
                 * Let ia64_do_page_fault() fix it.
index 2fbe4536fe181b5574d99a77add70e5330a5f490..663230183254c7bf9c34d85518f48e0b98995088 100644 (file)
@@ -54,6 +54,9 @@
  *
  * 2005-10-07 Keith Owens <kaos@sgi.com>
  *           Add notify_die() hooks.
+ *
+ * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
+ *           Add printing support for MCA/INIT.
  */
 #include <linux/types.h>
 #include <linux/init.h>
@@ -136,11 +139,175 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
 
 static int mca_init __initdata;
 
+/*
+ * limited & delayed printing support for MCA/INIT handler
+ */
+
+#define mprintk(fmt...) ia64_mca_printk(fmt)
+
+#define MLOGBUF_SIZE (512+256*NR_CPUS)
+#define MLOGBUF_MSGMAX 256
+static char mlogbuf[MLOGBUF_SIZE];
+static DEFINE_SPINLOCK(mlogbuf_wlock); /* mca context only */
+static DEFINE_SPINLOCK(mlogbuf_rlock); /* normal context only */
+static unsigned long mlogbuf_start;
+static unsigned long mlogbuf_end;
+static unsigned int mlogbuf_finished = 0;
+static unsigned long mlogbuf_timestamp = 0;
+
+static int loglevel_save = -1;
+#define BREAK_LOGLEVEL(__console_loglevel)             \
+       oops_in_progress = 1;                           \
+       if (loglevel_save < 0)                          \
+               loglevel_save = __console_loglevel;     \
+       __console_loglevel = 15;
+
+#define RESTORE_LOGLEVEL(__console_loglevel)           \
+       if (loglevel_save >= 0) {                       \
+               __console_loglevel = loglevel_save;     \
+               loglevel_save = -1;                     \
+       }                                               \
+       mlogbuf_finished = 0;                           \
+       oops_in_progress = 0;
+
+/*
+ * Push messages into buffer, print them later if not urgent.
+ */
+void ia64_mca_printk(const char *fmt, ...)
+{
+       va_list args;
+       int printed_len;
+       char temp_buf[MLOGBUF_MSGMAX];
+       char *p;
+
+       va_start(args, fmt);
+       printed_len = vscnprintf(temp_buf, sizeof(temp_buf), fmt, args);
+       va_end(args);
+
+       /* Copy the output into mlogbuf */
+       if (oops_in_progress) {
+               /* mlogbuf was abandoned, use printk directly instead. */
+               printk(temp_buf);
+       } else {
+               spin_lock(&mlogbuf_wlock);
+               for (p = temp_buf; *p; p++) {
+                       unsigned long next = (mlogbuf_end + 1) % MLOGBUF_SIZE;
+                       if (next != mlogbuf_start) {
+                               mlogbuf[mlogbuf_end] = *p;
+                               mlogbuf_end = next;
+                       } else {
+                               /* buffer full */
+                               break;
+                       }
+               }
+               mlogbuf[mlogbuf_end] = '\0';
+               spin_unlock(&mlogbuf_wlock);
+       }
+}
+EXPORT_SYMBOL(ia64_mca_printk);
+
+/*
+ * Print buffered messages.
+ *  NOTE: call this after returning normal context. (ex. from salinfod)
+ */
+void ia64_mlogbuf_dump(void)
+{
+       char temp_buf[MLOGBUF_MSGMAX];
+       char *p;
+       unsigned long index;
+       unsigned long flags;
+       unsigned int printed_len;
+
+       /* Get output from mlogbuf */
+       while (mlogbuf_start != mlogbuf_end) {
+               temp_buf[0] = '\0';
+               p = temp_buf;
+               printed_len = 0;
+
+               spin_lock_irqsave(&mlogbuf_rlock, flags);
+
+               index = mlogbuf_start;
+               while (index != mlogbuf_end) {
+                       *p = mlogbuf[index];
+                       index = (index + 1) % MLOGBUF_SIZE;
+                       if (!*p)
+                               break;
+                       p++;
+                       if (++printed_len >= MLOGBUF_MSGMAX - 1)
+                               break;
+               }
+               *p = '\0';
+               if (temp_buf[0])
+                       printk(temp_buf);
+               mlogbuf_start = index;
+
+               mlogbuf_timestamp = 0;
+               spin_unlock_irqrestore(&mlogbuf_rlock, flags);
+       }
+}
+EXPORT_SYMBOL(ia64_mlogbuf_dump);
+
+/*
+ * Call this if system is going to down or if immediate flushing messages to
+ * console is required. (ex. recovery was failed, crash dump is going to be
+ * invoked, long-wait rendezvous etc.)
+ *  NOTE: this should be called from monarch.
+ */
+static void ia64_mlogbuf_finish(int wait)
+{
+       BREAK_LOGLEVEL(console_loglevel);
+
+       spin_lock_init(&mlogbuf_rlock);
+       ia64_mlogbuf_dump();
+       printk(KERN_EMERG "mlogbuf_finish: printing switched to urgent mode, "
+               "MCA/INIT might be dodgy or fail.\n");
+
+       if (!wait)
+               return;
+
+       /* wait for console */
+       printk("Delaying for 5 seconds...\n");
+       udelay(5*1000000);
+
+       mlogbuf_finished = 1;
+}
+EXPORT_SYMBOL(ia64_mlogbuf_finish);
+
+/*
+ * Print buffered messages from INIT context.
+ */
+static void ia64_mlogbuf_dump_from_init(void)
+{
+       if (mlogbuf_finished)
+               return;
+
+       if (mlogbuf_timestamp && (mlogbuf_timestamp + 30*HZ > jiffies)) {
+               printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT "
+                       " and the system seems to be messed up.\n");
+               ia64_mlogbuf_finish(0);
+               return;
+       }
+
+       if (!spin_trylock(&mlogbuf_rlock)) {
+               printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT. "
+                       "Generated messages other than stack dump will be "
+                       "buffered to mlogbuf and will be printed later.\n");
+               printk(KERN_ERR "INIT: If messages would not printed after "
+                       "this INIT, wait 30sec and assert INIT again.\n");
+               if (!mlogbuf_timestamp)
+                       mlogbuf_timestamp = jiffies;
+               return;
+       }
+       spin_unlock(&mlogbuf_rlock);
+       ia64_mlogbuf_dump();
+}
 
 static void inline
 ia64_mca_spin(const char *func)
 {
-       printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
+       if (monarch_cpu == smp_processor_id())
+               ia64_mlogbuf_finish(0);
+       mprintk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
        while (1)
                cpu_relax();
 }
@@ -221,7 +388,7 @@ ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
 {
        sal_log_record_header_t     *log_buffer;
        u64                         total_len = 0;
-       int                         s;
+       unsigned long               s;
 
        IA64_LOG_LOCK(sal_info_type);
 
@@ -344,9 +511,6 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
        /* SAL spec states this should run w/ interrupts enabled */
        local_irq_enable();
 
-       /* Get the CPE error record and log it */
-       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
-
        spin_lock(&cpe_history_lock);
        if (!cpe_poll_enabled && cpe_vector >= 0) {
 
@@ -375,7 +539,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
                        mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL);
 
                        /* lock already released, get out now */
-                       return IRQ_HANDLED;
+                       goto out;
                } else {
                        cpe_history[index++] = now;
                        if (index == CPE_HISTORY_LENGTH)
@@ -383,6 +547,10 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
                }
        }
        spin_unlock(&cpe_history_lock);
+out:
+       /* Get the CPE error record and log it */
+       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
+
        return IRQ_HANDLED;
 }
 
@@ -988,18 +1156,22 @@ ia64_wait_for_slaves(int monarch, const char *type)
        }
        if (!missing)
                goto all_in;
-       printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
+       /*
+        * Maybe slave(s) dead. Print buffered messages immediately.
+        */
+       ia64_mlogbuf_finish(0);
+       mprintk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
        for_each_online_cpu(c) {
                if (c == monarch)
                        continue;
                if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
-                       printk(" %d", c);
+                       mprintk(" %d", c);
        }
-       printk("\n");
+       mprintk("\n");
        return;
 
 all_in:
-       printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
+       mprintk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
        return;
 }
 
@@ -1027,10 +1199,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        struct ia64_mca_notify_die nd =
                { .sos = sos, .monarch_cpu = &monarch_cpu };
 
-       oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
-       console_loglevel = 15;  /* make sure printks make it to console */
-       printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
-               sos->proc_state_param, cpu, sos->monarch);
+       mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
+               "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
 
        previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
        monarch_cpu = cpu;
@@ -1066,6 +1236,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                rh->severity = sal_log_severity_corrected;
                ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
                sos->os_status = IA64_MCA_CORRECTED;
+       } else {
+               /* Dump buffered message to console */
+               ia64_mlogbuf_finish(1);
        }
        if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
                        == NOTIFY_STOP)
@@ -1106,9 +1279,6 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
        /* SAL spec states this should run w/ interrupts enabled */
        local_irq_enable();
 
-       /* Get the CMC error record and log it */
-       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
-
        spin_lock(&cmc_history_lock);
        if (!cmc_polling_enabled) {
                int i, count = 1; /* we know 1 happened now */
@@ -1141,7 +1311,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
                        mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
 
                        /* lock already released, get out now */
-                       return IRQ_HANDLED;
+                       goto out;
                } else {
                        cmc_history[index++] = now;
                        if (index == CMC_HISTORY_LENGTH)
@@ -1149,6 +1319,10 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
                }
        }
        spin_unlock(&cmc_history_lock);
+out:
+       /* Get the CMC error record and log it */
+       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
+
        return IRQ_HANDLED;
 }
 
@@ -1305,6 +1479,15 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
        struct task_struct *g, *t;
        if (val != DIE_INIT_MONARCH_PROCESS)
                return NOTIFY_DONE;
+
+       /*
+        * FIXME: mlogbuf will brim over with INIT stack dumps.
+        * To enable show_stack from INIT, we use oops_in_progress which should
+        * be used in real oops. This would cause something wrong after INIT.
+        */
+       BREAK_LOGLEVEL(console_loglevel);
+       ia64_mlogbuf_dump_from_init();
+
        printk(KERN_ERR "Processes interrupted by INIT -");
        for_each_online_cpu(c) {
                struct ia64_sal_os_state *s;
@@ -1326,6 +1509,8 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
                } while_each_thread (g, t);
                read_unlock(&tasklist_lock);
        }
+       /* FIXME: This will not restore zapped printk locks. */
+       RESTORE_LOGLEVEL(console_loglevel);
        return NOTIFY_DONE;
 }
 
@@ -1357,12 +1542,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
        struct ia64_mca_notify_die nd =
                { .sos = sos, .monarch_cpu = &monarch_cpu };
 
-       oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
-       console_loglevel = 15;  /* make sure printks make it to console */
-
        (void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
 
-       printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
+       mprintk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
                sos->proc_state_param, cpu, sos->monarch);
        salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
 
@@ -1375,7 +1557,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
         * fix their proms and get their customers updated.
         */
        if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {
-               printk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
+               mprintk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
                       __FUNCTION__, cpu);
                atomic_dec(&slaves);
                sos->monarch = 1;
@@ -1387,7 +1569,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
         * fix their proms and get their customers updated.
         */
        if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {
-               printk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
+               mprintk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
                               __FUNCTION__, cpu);
                atomic_dec(&monarchs);
                sos->monarch = 0;
@@ -1408,7 +1590,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
                if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
                                == NOTIFY_STOP)
                        ia64_mca_spin(__FUNCTION__);
-               printk("Slave on cpu %d returning to normal service.\n", cpu);
+               mprintk("Slave on cpu %d returning to normal service.\n", cpu);
                set_curr_task(cpu, previous_current);
                ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
                atomic_dec(&slaves);
@@ -1426,7 +1608,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
         * same serial line, the user will need some time to switch out of the BMC before
         * the dump begins.
         */
-       printk("Delaying for 5 seconds...\n");
+       mprintk("Delaying for 5 seconds...\n");
        udelay(5*1000000);
        ia64_wait_for_slaves(cpu, "INIT");
        /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
@@ -1439,7 +1621,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
        if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
                        == NOTIFY_STOP)
                ia64_mca_spin(__FUNCTION__);
-       printk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
+       mprintk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
        atomic_dec(&monarchs);
        set_curr_task(cpu, previous_current);
        monarch_cpu = -1;
index 96047491d1b9241fd06e196672443e1d5f16d7f1..c6b607c00deea80c4268468412b60e7fff8b5128 100644 (file)
@@ -1025,18 +1025,13 @@ ia64_old_stack:
 
 ia64_set_kernel_registers:
        add temp3=MCA_SP_OFFSET, r3
-       add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3
        mov b0=r2               // save return address
        GET_IA64_MCA_DATA(temp1)
        ;;
-       add temp4=temp4, temp1  // &struct ia64_sal_os_state.os_gp
        add r12=temp1, temp3    // kernel stack pointer on MCA/INIT stack
        add r13=temp1, r3       // set current to start of MCA/INIT stack
        add r20=temp1, r3       // physical start of MCA/INIT stack
        ;;
-       ld8 r1=[temp4]          // OS GP from SAL OS state
-       ;;
-       DATA_PA_TO_VA(r1,temp1)
        DATA_PA_TO_VA(r12,temp2)
        DATA_PA_TO_VA(r13,temp3)
        ;;
@@ -1067,6 +1062,10 @@ ia64_set_kernel_registers:
        mov cr.itir=r18
        mov cr.ifa=r13
        mov r20=IA64_TR_CURRENT_STACK
+
+       movl r17=FPSR_DEFAULT
+       ;;
+       mov.m ar.fpsr=r17                       // set ar.fpsr to kernel default value
        ;;
        itr.d dtr[r20]=r21
        ;;
index 8db6e0cedadcbc3d660bd6f5621cbc496e75b466..a45009d2bc90149e5199a97c9eff86a8d552f5b0 100644 (file)
@@ -79,14 +79,30 @@ static int
 fatal_mca(const char *fmt, ...)
 {
        va_list args;
+       char buf[256];
 
        va_start(args, fmt);
-       vprintk(fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
+       ia64_mca_printk(KERN_ALERT "MCA: %s\n", buf);
 
        return MCA_NOT_RECOVERED;
 }
 
+static int
+mca_recovered(const char *fmt, ...)
+{
+       va_list args;
+       char buf[256];
+
+       va_start(args, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+       ia64_mca_printk(KERN_INFO "MCA: %s\n", buf);
+
+       return MCA_RECOVERED;
+}
+
 /**
  * mca_page_isolate - isolate a poisoned page in order not to use it later
  * @paddr:     poisoned memory location
@@ -140,6 +156,7 @@ mca_page_isolate(unsigned long paddr)
 void
 mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
 {
+       ia64_mlogbuf_dump();
        printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
                "iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
                raw_smp_processor_id(), current->pid, current->uid,
@@ -440,7 +457,7 @@ recover_from_read_error(slidx_table_t *slidx,
 
        /* Is target address valid? */
        if (!pbci->tv)
-               return fatal_mca(KERN_ALERT "MCA: target address not valid\n");
+               return fatal_mca("target address not valid");
 
        /*
         * cpu read or memory-mapped io read
@@ -458,7 +475,7 @@ recover_from_read_error(slidx_table_t *slidx,
 
        /* Is minstate valid? */
        if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
-               return fatal_mca(KERN_ALERT "MCA: minstate not valid\n");
+               return fatal_mca("minstate not valid");
        psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
        psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
 
@@ -492,13 +509,14 @@ recover_from_read_error(slidx_table_t *slidx,
                        psr2->bn  = 1;
                        psr2->i  = 0;
 
-                       return MCA_RECOVERED;
+                       return mca_recovered("user memory corruption. "
+                               "kill affected process - recovered.");
                }
 
        }
 
-       return fatal_mca(KERN_ALERT "MCA: kernel context not recovered,"
-                         " iip 0x%lx\n", pmsa->pmsa_iip);
+       return fatal_mca("kernel context not recovered, iip 0x%lx\n",
+                        pmsa->pmsa_iip);
 }
 
 /**
@@ -584,13 +602,13 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
         * The machine check is corrected.
         */
        if (psp->cm == 1)
-               return MCA_RECOVERED;
+               return mca_recovered("machine check is already corrected.");
 
        /*
         * The error was not contained.  Software must be reset.
         */
        if (psp->us || psp->ci == 0)
-               return fatal_mca(KERN_ALERT "MCA: error not contained\n");
+               return fatal_mca("error not contained");
 
        /*
         * The cache check and bus check bits have four possible states
@@ -601,22 +619,22 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
         *    1  1      Memory error, attempt recovery
         */
        if (psp->bc == 0 || pbci == NULL)
-               return fatal_mca(KERN_ALERT "MCA: No bus check\n");
+               return fatal_mca("No bus check");
 
        /*
         * Sorry, we cannot handle so many.
         */
        if (peidx_bus_check_num(peidx) > 1)
-               return fatal_mca(KERN_ALERT "MCA: Too many bus checks\n");
+               return fatal_mca("Too many bus checks");
        /*
         * Well, here is only one bus error.
         */
        if (pbci->ib)
-               return fatal_mca(KERN_ALERT "MCA: Internal Bus error\n");
+               return fatal_mca("Internal Bus error");
        if (pbci->cc)
-               return fatal_mca(KERN_ALERT "MCA: Cache-cache error\n");
+               return fatal_mca("Cache-cache error");
        if (pbci->eb && pbci->bsi > 0)
-               return fatal_mca(KERN_ALERT "MCA: External bus check fatal status\n");
+               return fatal_mca("External bus check fatal status");
 
        /*
         * This is a local MCA and estimated as recoverble external bus error.
@@ -628,7 +646,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
        /*
         * On account of strange SAL error record, we cannot recover.
         */
-       return fatal_mca(KERN_ALERT "MCA: Strange SAL record\n");
+       return fatal_mca("Strange SAL record");
 }
 
 /**
@@ -657,10 +675,10 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
 
         /* Now, OS can recover when there is one processor error section */
        if (n_proc_err > 1)
-               return fatal_mca(KERN_ALERT "MCA: Too Many Errors\n");
+               return fatal_mca("Too Many Errors");
        else if (n_proc_err == 0)
-               /* Weird SAL record ... We need not to recover */
-               return fatal_mca(KERN_ALERT "MCA: Weird SAL record\n");
+               /* Weird SAL record ... We can't do anything */
+               return fatal_mca("Weird SAL record");
 
        /* Make index of processor error section */
        mca_make_peidx((sal_log_processor_info_t*)
@@ -671,7 +689,7 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
 
        /* Check whether MCA is global or not */
        if (is_mca_global(&peidx, &pbci, sos))
-               return fatal_mca(KERN_ALERT "MCA: global MCA\n");
+               return fatal_mca("global MCA");
        
        /* Try to recover a processor error */
        return recover_from_processor_error(platform_err, &slidx, &peidx,
index 31a2e52bb16fc7c6b6af5bcfdb8a9caebd95cdb1..c85e943ba5fd93017a305b34aef00da0b56689f9 100644 (file)
@@ -118,3 +118,7 @@ struct mca_table_entry {
 
 extern const struct mca_table_entry *search_mca_tables (unsigned long addr);
 extern int mca_recover_range(unsigned long);
+extern void ia64_mca_printk(const char * fmt, ...)
+        __attribute__ ((format (printf, 1, 2)));
+extern void ia64_mlogbuf_dump(void);
+
index 7bb7696e4ce25aa3e7d0f4de86ae7970c4a3d4b5..281004ff7b00b87a46de5f91c05c90c706827474 100644 (file)
@@ -63,6 +63,9 @@
 
 #define PFM_INVALID_ACTIVATION (~0UL)
 
+#define PFM_NUM_PMC_REGS       64      /* PMC save area for ctxsw */
+#define PFM_NUM_PMD_REGS       64      /* PMD save area for ctxsw */
+
 /*
  * depth of message queue
  */
@@ -297,14 +300,17 @@ typedef struct pfm_context {
        unsigned long           ctx_reload_pmcs[4];     /* bitmask of force reload PMC on ctxsw in */
        unsigned long           ctx_used_monitors[4];   /* bitmask of monitor PMC being used */
 
-       unsigned long           ctx_pmcs[IA64_NUM_PMC_REGS];    /*  saved copies of PMC values */
+       unsigned long           ctx_pmcs[PFM_NUM_PMC_REGS];     /*  saved copies of PMC values */
 
        unsigned int            ctx_used_ibrs[1];               /* bitmask of used IBR (speedup ctxsw in) */
        unsigned int            ctx_used_dbrs[1];               /* bitmask of used DBR (speedup ctxsw in) */
        unsigned long           ctx_dbrs[IA64_NUM_DBG_REGS];    /* DBR values (cache) when not loaded */
        unsigned long           ctx_ibrs[IA64_NUM_DBG_REGS];    /* IBR values (cache) when not loaded */
 
-       pfm_counter_t           ctx_pmds[IA64_NUM_PMD_REGS]; /* software state for PMDS */
+       pfm_counter_t           ctx_pmds[PFM_NUM_PMD_REGS]; /* software state for PMDS */
+
+       unsigned long           th_pmcs[PFM_NUM_PMC_REGS];      /* PMC thread save state */
+       unsigned long           th_pmds[PFM_NUM_PMD_REGS];      /* PMD thread save state */
 
        u64                     ctx_saved_psr_up;       /* only contains psr.up value */
 
@@ -868,7 +874,6 @@ static void
 pfm_mask_monitoring(struct task_struct *task)
 {
        pfm_context_t *ctx = PFM_GET_CTX(task);
-       struct thread_struct *th = &task->thread;
        unsigned long mask, val, ovfl_mask;
        int i;
 
@@ -889,7 +894,7 @@ pfm_mask_monitoring(struct task_struct *task)
         * So in both cases, the live register contains the owner's
         * state. We can ONLY touch the PMU registers and NOT the PSR.
         *
-        * As a consequence to this call, the thread->pmds[] array
+        * As a consequence to this call, the ctx->th_pmds[] array
         * contains stale information which must be ignored
         * when context is reloaded AND monitoring is active (see
         * pfm_restart).
@@ -924,9 +929,9 @@ pfm_mask_monitoring(struct task_struct *task)
        mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;
        for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {
                if ((mask & 0x1) == 0UL) continue;
-               ia64_set_pmc(i, th->pmcs[i] & ~0xfUL);
-               th->pmcs[i] &= ~0xfUL;
-               DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, th->pmcs[i]));
+               ia64_set_pmc(i, ctx->th_pmcs[i] & ~0xfUL);
+               ctx->th_pmcs[i] &= ~0xfUL;
+               DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, ctx->th_pmcs[i]));
        }
        /*
         * make all of this visible
@@ -943,7 +948,6 @@ static void
 pfm_restore_monitoring(struct task_struct *task)
 {
        pfm_context_t *ctx = PFM_GET_CTX(task);
-       struct thread_struct *th = &task->thread;
        unsigned long mask, ovfl_mask;
        unsigned long psr, val;
        int i, is_system;
@@ -1009,9 +1013,9 @@ pfm_restore_monitoring(struct task_struct *task)
        mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;
        for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {
                if ((mask & 0x1) == 0UL) continue;
-               th->pmcs[i] = ctx->ctx_pmcs[i];
-               ia64_set_pmc(i, th->pmcs[i]);
-               DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, th->pmcs[i]));
+               ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
+               ia64_set_pmc(i, ctx->th_pmcs[i]);
+               DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, ctx->th_pmcs[i]));
        }
        ia64_srlz_d();
 
@@ -1070,7 +1074,6 @@ pfm_restore_pmds(unsigned long *pmds, unsigned long mask)
 static inline void
 pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
 {
-       struct thread_struct *thread = &task->thread;
        unsigned long ovfl_val = pmu_conf->ovfl_val;
        unsigned long mask = ctx->ctx_all_pmds[0];
        unsigned long val;
@@ -1092,11 +1095,11 @@ pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
                        ctx->ctx_pmds[i].val = val & ~ovfl_val;
                         val &= ovfl_val;
                }
-               thread->pmds[i] = val;
+               ctx->th_pmds[i] = val;
 
                DPRINT(("pmd[%d]=0x%lx soft_val=0x%lx\n",
                        i,
-                       thread->pmds[i],
+                       ctx->th_pmds[i],
                        ctx->ctx_pmds[i].val));
        }
 }
@@ -1107,7 +1110,6 @@ pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
 static inline void
 pfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx)
 {
-       struct thread_struct *thread = &task->thread;
        unsigned long mask = ctx->ctx_all_pmcs[0];
        int i;
 
@@ -1115,8 +1117,8 @@ pfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx)
 
        for (i=0; mask; i++, mask>>=1) {
                /* masking 0 with ovfl_val yields 0 */
-               thread->pmcs[i] = ctx->ctx_pmcs[i];
-               DPRINT(("pmc[%d]=0x%lx\n", i, thread->pmcs[i]));
+               ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
+               DPRINT(("pmc[%d]=0x%lx\n", i, ctx->th_pmcs[i]));
        }
 }
 
@@ -2860,7 +2862,6 @@ pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int is_long_reset)
 static int
 pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
-       struct thread_struct *thread = NULL;
        struct task_struct *task;
        pfarg_reg_t *req = (pfarg_reg_t *)arg;
        unsigned long value, pmc_pm;
@@ -2881,7 +2882,6 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        if (state == PFM_CTX_ZOMBIE) return -EINVAL;
 
        if (is_loaded) {
-               thread = &task->thread;
                /*
                 * In system wide and when the context is loaded, access can only happen
                 * when the caller is running on the CPU being monitored by the session.
@@ -3036,7 +3036,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                 *
                 * The value in ctx_pmcs[] can only be changed in pfm_write_pmcs().
                 *
-                * The value in thread->pmcs[] may be modified on overflow, i.e.,  when
+                * The value in th_pmcs[] may be modified on overflow, i.e.,  when
                 * monitoring needs to be stopped.
                 */
                if (is_monitor) CTX_USED_MONITOR(ctx, 1UL << cnum);
@@ -3050,7 +3050,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                        /*
                         * write thread state
                         */
-                       if (is_system == 0) thread->pmcs[cnum] = value;
+                       if (is_system == 0) ctx->th_pmcs[cnum] = value;
 
                        /*
                         * write hardware register if we can
@@ -3102,7 +3102,6 @@ error:
 static int
 pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
-       struct thread_struct *thread = NULL;
        struct task_struct *task;
        pfarg_reg_t *req = (pfarg_reg_t *)arg;
        unsigned long value, hw_value, ovfl_mask;
@@ -3126,7 +3125,6 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
         * the owner of the local PMU.
         */
        if (likely(is_loaded)) {
-               thread = &task->thread;
                /*
                 * In system wide and when the context is loaded, access can only happen
                 * when the caller is running on the CPU being monitored by the session.
@@ -3234,7 +3232,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                        /*
                         * write thread state
                         */
-                       if (is_system == 0) thread->pmds[cnum] = hw_value;
+                       if (is_system == 0) ctx->th_pmds[cnum] = hw_value;
 
                        /*
                         * write hardware register if we can
@@ -3300,7 +3298,6 @@ abort_mission:
 static int
 pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
-       struct thread_struct *thread = NULL;
        struct task_struct *task;
        unsigned long val = 0UL, lval, ovfl_mask, sval;
        pfarg_reg_t *req = (pfarg_reg_t *)arg;
@@ -3324,7 +3321,6 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        if (state == PFM_CTX_ZOMBIE) return -EINVAL;
 
        if (likely(is_loaded)) {
-               thread = &task->thread;
                /*
                 * In system wide and when the context is loaded, access can only happen
                 * when the caller is running on the CPU being monitored by the session.
@@ -3386,7 +3382,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                         * if context is zombie, then task does not exist anymore.
                         * In this case, we use the full value saved in the context (pfm_flush_regs()).
                         */
-                       val = is_loaded ? thread->pmds[cnum] : 0UL;
+                       val = is_loaded ? ctx->th_pmds[cnum] : 0UL;
                }
                rd_func = pmu_conf->pmd_desc[cnum].read_check;
 
@@ -4355,8 +4351,8 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        pfm_copy_pmds(task, ctx);
        pfm_copy_pmcs(task, ctx);
 
-       pmcs_source = thread->pmcs;
-       pmds_source = thread->pmds;
+       pmcs_source = ctx->th_pmcs;
+       pmds_source = ctx->th_pmds;
 
        /*
         * always the case for system-wide
@@ -5865,14 +5861,12 @@ void
 pfm_save_regs(struct task_struct *task)
 {
        pfm_context_t *ctx;
-       struct thread_struct *t;
        unsigned long flags;
        u64 psr;
 
 
        ctx = PFM_GET_CTX(task);
        if (ctx == NULL) return;
-       t = &task->thread;
 
        /*
         * we always come here with interrupts ALREADY disabled by
@@ -5930,19 +5924,19 @@ pfm_save_regs(struct task_struct *task)
         * guarantee we will be schedule at that same
         * CPU again.
         */
-       pfm_save_pmds(t->pmds, ctx->ctx_used_pmds[0]);
+       pfm_save_pmds(ctx->th_pmds, ctx->ctx_used_pmds[0]);
 
        /*
         * save pmc0 ia64_srlz_d() done in pfm_save_pmds()
         * we will need it on the restore path to check
         * for pending overflow.
         */
-       t->pmcs[0] = ia64_get_pmc(0);
+       ctx->th_pmcs[0] = ia64_get_pmc(0);
 
        /*
         * unfreeze PMU if had pending overflows
         */
-       if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
+       if (ctx->th_pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
 
        /*
         * finally, allow context access.
@@ -5987,7 +5981,6 @@ static void
 pfm_lazy_save_regs (struct task_struct *task)
 {
        pfm_context_t *ctx;
-       struct thread_struct *t;
        unsigned long flags;
 
        { u64 psr  = pfm_get_psr();
@@ -5995,7 +5988,6 @@ pfm_lazy_save_regs (struct task_struct *task)
        }
 
        ctx = PFM_GET_CTX(task);
-       t   = &task->thread;
 
        /*
         * we need to mask PMU overflow here to
@@ -6020,19 +6012,19 @@ pfm_lazy_save_regs (struct task_struct *task)
        /*
         * save all the pmds we use
         */
-       pfm_save_pmds(t->pmds, ctx->ctx_used_pmds[0]);
+       pfm_save_pmds(ctx->th_pmds, ctx->ctx_used_pmds[0]);
 
        /*
         * save pmc0 ia64_srlz_d() done in pfm_save_pmds()
         * it is needed to check for pended overflow
         * on the restore path
         */
-       t->pmcs[0] = ia64_get_pmc(0);
+       ctx->th_pmcs[0] = ia64_get_pmc(0);
 
        /*
         * unfreeze PMU if had pending overflows
         */
-       if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
+       if (ctx->th_pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
 
        /*
         * now get can unmask PMU interrupts, they will
@@ -6051,7 +6043,6 @@ void
 pfm_load_regs (struct task_struct *task)
 {
        pfm_context_t *ctx;
-       struct thread_struct *t;
        unsigned long pmc_mask = 0UL, pmd_mask = 0UL;
        unsigned long flags;
        u64 psr, psr_up;
@@ -6062,11 +6053,10 @@ pfm_load_regs (struct task_struct *task)
 
        BUG_ON(GET_PMU_OWNER());
 
-       t     = &task->thread;
        /*
         * possible on unload
         */
-       if (unlikely((t->flags & IA64_THREAD_PM_VALID) == 0)) return;
+       if (unlikely((task->thread.flags & IA64_THREAD_PM_VALID) == 0)) return;
 
        /*
         * we always come here with interrupts ALREADY disabled by
@@ -6148,21 +6138,21 @@ pfm_load_regs (struct task_struct *task)
         *
         * XXX: optimize here
         */
-       if (pmd_mask) pfm_restore_pmds(t->pmds, pmd_mask);
-       if (pmc_mask) pfm_restore_pmcs(t->pmcs, pmc_mask);
+       if (pmd_mask) pfm_restore_pmds(ctx->th_pmds, pmd_mask);
+       if (pmc_mask) pfm_restore_pmcs(ctx->th_pmcs, pmc_mask);
 
        /*
         * check for pending overflow at the time the state
         * was saved.
         */
-       if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) {
+       if (unlikely(PMC0_HAS_OVFL(ctx->th_pmcs[0]))) {
                /*
                 * reload pmc0 with the overflow information
                 * On McKinley PMU, this will trigger a PMU interrupt
                 */
-               ia64_set_pmc(0, t->pmcs[0]);
+               ia64_set_pmc(0, ctx->th_pmcs[0]);
                ia64_srlz_d();
-               t->pmcs[0] = 0UL;
+               ctx->th_pmcs[0] = 0UL;
 
                /*
                 * will replay the PMU interrupt
@@ -6215,7 +6205,6 @@ pfm_load_regs (struct task_struct *task)
 void
 pfm_load_regs (struct task_struct *task)
 {
-       struct thread_struct *t;
        pfm_context_t *ctx;
        struct task_struct *owner;
        unsigned long pmd_mask, pmc_mask;
@@ -6224,7 +6213,6 @@ pfm_load_regs (struct task_struct *task)
 
        owner = GET_PMU_OWNER();
        ctx   = PFM_GET_CTX(task);
-       t     = &task->thread;
        psr   = pfm_get_psr();
 
        BUG_ON(psr & (IA64_PSR_UP|IA64_PSR_PP));
@@ -6287,22 +6275,22 @@ pfm_load_regs (struct task_struct *task)
         */
        pmc_mask = ctx->ctx_all_pmcs[0];
 
-       pfm_restore_pmds(t->pmds, pmd_mask);
-       pfm_restore_pmcs(t->pmcs, pmc_mask);
+       pfm_restore_pmds(ctx->th_pmds, pmd_mask);
+       pfm_restore_pmcs(ctx->th_pmcs, pmc_mask);
 
        /*
         * check for pending overflow at the time the state
         * was saved.
         */
-       if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) {
+       if (unlikely(PMC0_HAS_OVFL(ctx->th_pmcs[0]))) {
                /*
                 * reload pmc0 with the overflow information
                 * On McKinley PMU, this will trigger a PMU interrupt
                 */
-               ia64_set_pmc(0, t->pmcs[0]);
+               ia64_set_pmc(0, ctx->th_pmcs[0]);
                ia64_srlz_d();
 
-               t->pmcs[0] = 0UL;
+               ctx->th_pmcs[0] = 0UL;
 
                /*
                 * will replay the PMU interrupt
@@ -6377,11 +6365,11 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
                 */
                pfm_unfreeze_pmu();
        } else {
-               pmc0 = task->thread.pmcs[0];
+               pmc0 = ctx->th_pmcs[0];
                /*
                 * clear whatever overflow status bits there were
                 */
-               task->thread.pmcs[0] = 0;
+               ctx->th_pmcs[0] = 0;
        }
        ovfl_val = pmu_conf->ovfl_val;
        /*
@@ -6402,7 +6390,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
                /*
                 * can access PMU always true in system wide mode
                 */
-               val = pmd_val = can_access_pmu ? ia64_get_pmd(i) : task->thread.pmds[i];
+               val = pmd_val = can_access_pmu ? ia64_get_pmd(i) : ctx->th_pmds[i];
 
                if (PMD_IS_COUNTING(i)) {
                        DPRINT(("[%d] pmd[%d] ctx_pmd=0x%lx hw_pmd=0x%lx\n",
@@ -6434,7 +6422,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
 
                DPRINT(("[%d] ctx_pmd[%d]=0x%lx  pmd_val=0x%lx\n", task->pid, i, val, pmd_val));
 
-               if (is_self) task->thread.pmds[i] = pmd_val;
+               if (is_self) ctx->th_pmds[i] = pmd_val;
 
                ctx->ctx_pmds[i].val = val;
        }
@@ -6678,7 +6666,7 @@ pfm_init(void)
               ffz(pmu_conf->ovfl_val));
 
        /* sanity check */
-       if (pmu_conf->num_pmds >= IA64_NUM_PMD_REGS || pmu_conf->num_pmcs >= IA64_NUM_PMC_REGS) {
+       if (pmu_conf->num_pmds >= PFM_NUM_PMD_REGS || pmu_conf->num_pmcs >= PFM_NUM_PMC_REGS) {
                printk(KERN_ERR "perfmon: not enough pmc/pmd, perfmon disabled\n");
                pmu_conf = NULL;
                return -1;
@@ -6753,7 +6741,6 @@ void
 dump_pmu_state(const char *from)
 {
        struct task_struct *task;
-       struct thread_struct *t;
        struct pt_regs *regs;
        pfm_context_t *ctx;
        unsigned long psr, dcr, info, flags;
@@ -6798,16 +6785,14 @@ dump_pmu_state(const char *from)
        ia64_psr(regs)->up = 0;
        ia64_psr(regs)->pp = 0;
 
-       t = &current->thread;
-
        for (i=1; PMC_IS_LAST(i) == 0; i++) {
                if (PMC_IS_IMPL(i) == 0) continue;
-               printk("->CPU%d pmc[%d]=0x%lx thread_pmc[%d]=0x%lx\n", this_cpu, i, ia64_get_pmc(i), i, t->pmcs[i]);
+               printk("->CPU%d pmc[%d]=0x%lx thread_pmc[%d]=0x%lx\n", this_cpu, i, ia64_get_pmc(i), i, ctx->th_pmcs[i]);
        }
 
        for (i=1; PMD_IS_LAST(i) == 0; i++) {
                if (PMD_IS_IMPL(i) == 0) continue;
-               printk("->CPU%d pmd[%d]=0x%lx thread_pmd[%d]=0x%lx\n", this_cpu, i, ia64_get_pmd(i), i, t->pmds[i]);
+               printk("->CPU%d pmd[%d]=0x%lx thread_pmd[%d]=0x%lx\n", this_cpu, i, ia64_get_pmd(i), i, ctx->th_pmds[i]);
        }
 
        if (ctx) {
index 9065f0f01ba3e7f70b48abf36af96cf46b205514..e63b8ca5344a202d85b8cb1d25a4edb08c486894 100644 (file)
@@ -266,6 +266,7 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
 /* Check for outstanding MCA/INIT records every minute (arbitrary) */
 #define SALINFO_TIMER_DELAY (60*HZ)
 static struct timer_list salinfo_timer;
+extern void ia64_mlogbuf_dump(void);
 
 static void
 salinfo_timeout_check(struct salinfo_data *data)
@@ -283,6 +284,7 @@ salinfo_timeout_check(struct salinfo_data *data)
 static void
 salinfo_timeout (unsigned long arg)
 {
+       ia64_mlogbuf_dump();
        salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
        salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
        salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
@@ -332,6 +334,8 @@ retry:
        if (cpu == -1)
                goto retry;
 
+       ia64_mlogbuf_dump();
+
        /* for next read, start checking at next CPU */
        data->cpu_check = cpu;
        if (++data->cpu_check == NR_CPUS)
index 7ad0d9cc6db65c1503cc3a69259954633c6c5991..84f93c0f2c666b15d3f70c3df47c3c17a5949ad0 100644 (file)
@@ -509,7 +509,7 @@ show_cpuinfo (struct seq_file *m, void *v)
                { 1UL << 1, "spontaneous deferral"},
                { 1UL << 2, "16-byte atomic ops" }
        };
-       char family[32], features[128], *cp, sep;
+       char features[128], *cp, sep;
        struct cpuinfo_ia64 *c = v;
        unsigned long mask;
        unsigned long proc_freq;
@@ -517,12 +517,6 @@ show_cpuinfo (struct seq_file *m, void *v)
 
        mask = c->features;
 
-       switch (c->family) {
-             case 0x07:        memcpy(family, "Itanium", 8); break;
-             case 0x1f:        memcpy(family, "Itanium 2", 10); break;
-             default:          sprintf(family, "%u", c->family); break;
-       }
-
        /* build the feature string: */
        memcpy(features, " standard", 10);
        cp = features;
@@ -553,8 +547,9 @@ show_cpuinfo (struct seq_file *m, void *v)
                   "processor  : %d\n"
                   "vendor     : %s\n"
                   "arch       : IA-64\n"
-                  "family     : %s\n"
+                  "family     : %u\n"
                   "model      : %u\n"
+                  "model name : %s\n"
                   "revision   : %u\n"
                   "archrev    : %u\n"
                   "features   :%s\n"   /* don't change this---it _is_ right! */
@@ -563,7 +558,8 @@ show_cpuinfo (struct seq_file *m, void *v)
                   "cpu MHz    : %lu.%06lu\n"
                   "itc MHz    : %lu.%06lu\n"
                   "BogoMIPS   : %lu.%02lu\n",
-                  cpunum, c->vendor, family, c->model, c->revision, c->archrev,
+                  cpunum, c->vendor, c->family, c->model,
+                  c->model_name, c->revision, c->archrev,
                   features, c->ppn, c->number,
                   proc_freq / 1000, proc_freq % 1000,
                   c->itc_freq / 1000000, c->itc_freq % 1000000,
@@ -611,6 +607,31 @@ struct seq_operations cpuinfo_op = {
        .show =         show_cpuinfo
 };
 
+static char brandname[128];
+
+static char * __cpuinit
+get_model_name(__u8 family, __u8 model)
+{
+       char brand[128];
+
+       if (ia64_pal_get_brand_info(brand)) {
+               if (family == 0x7)
+                       memcpy(brand, "Merced", 7);
+               else if (family == 0x1f) switch (model) {
+                       case 0: memcpy(brand, "McKinley", 9); break;
+                       case 1: memcpy(brand, "Madison", 8); break;
+                       case 2: memcpy(brand, "Madison up to 9M cache", 23); break;
+               } else
+                       memcpy(brand, "Unknown", 8);
+       }
+       if (brandname[0] == '\0')
+               return strcpy(brandname, brand);
+       else if (strcmp(brandname, brand) == 0)
+               return brandname;
+       else
+               return kstrdup(brand, GFP_KERNEL);
+}
+
 static void __cpuinit
 identify_cpu (struct cpuinfo_ia64 *c)
 {
@@ -640,7 +661,6 @@ identify_cpu (struct cpuinfo_ia64 *c)
        pal_status_t status;
        unsigned long impl_va_msb = 50, phys_addr_size = 44;    /* Itanium defaults */
        int i;
-
        for (i = 0; i < 5; ++i)
                cpuid.bits[i] = ia64_get_cpuid(i);
 
@@ -663,6 +683,7 @@ identify_cpu (struct cpuinfo_ia64 *c)
        c->family = cpuid.field.family;
        c->archrev = cpuid.field.archrev;
        c->features = cpuid.field.features;
+       c->model_name = get_model_name(c->family, c->model);
 
        status = ia64_pal_vm_summary(&vm1, &vm2);
        if (status == PAL_STATUS_SUCCESS) {
index 6203ed4ec8cfadbab3a6d77f055633ad055cc8c8..f7d7f5668144fcec8e76bcadb66c5df27aad17d9 100644 (file)
@@ -879,3 +879,27 @@ identify_siblings(struct cpuinfo_ia64 *c)
        c->core_id = info.log1_cid;
        c->thread_id = info.log1_tid;
 }
+
+/*
+ * returns non zero, if multi-threading is enabled
+ * on at least one physical package. Due to hotplug cpu
+ * and (maxcpus=), all threads may not necessarily be enabled
+ * even though the processor supports multi-threading.
+ */
+int is_multithreading_enabled(void)
+{
+       int i, j;
+
+       for_each_present_cpu(i) {
+               for_each_present_cpu(j) {
+                       if (j == i)
+                               continue;
+                       if ((cpu_data(j)->socket_id == cpu_data(i)->socket_id)) {
+                               if (cpu_data(j)->core_id == cpu_data(i)->core_id)
+                                       return 1;
+                       }
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(is_multithreading_enabled);
index 6928ef0d64d852abc4a41b7ff5cfc2e1f14d5249..62e07f906e05dd4debed3688c151a661c60b64db 100644 (file)
@@ -29,8 +29,6 @@
 #include <asm/sections.h>
 #include <asm/system.h>
 
-extern unsigned long wall_jiffies;
-
 volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */
 
 #ifdef CONFIG_IA64_DEBUG_IRQ
@@ -78,7 +76,7 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
                         * xtime_lock.
                         */
                        write_seqlock(&xtime_lock);
-                       do_timer(regs);
+                       do_timer(1);
                        local_cpu_data->itm_next = new_itm;
                        write_sequnlock(&xtime_lock);
                } else
index 05bdf7affb431742a7c0f7ea8c167bea6300c530..5629b45e89c6bc50892c4a8e69b66d0f0be67d86 100644 (file)
@@ -36,9 +36,7 @@ int arch_register_cpu(int num)
         */
        if (!can_cpei_retarget() && is_cpu_cpei_target(num))
                sysfs_cpus[num].cpu.no_control = 1;
-#ifdef CONFIG_NUMA
        map_cpu_to_node(num, node_cpuid[num].nid);
-#endif
 #endif
 
        return register_cpu(&sysfs_cpus[num].cpu, num);
index 5b0d5f64a9b11d7fff31532595f5fbb00a8c036a..b3b2e389d6b2e2abc690f37e7e62bb39127afaba 100644 (file)
@@ -184,7 +184,9 @@ SECTIONS
          *(.data.gate)
          __stop_gate_section = .;
        }
-  . = ALIGN(PAGE_SIZE);                /* make sure the gate page doesn't expose kernel data */
+  . = ALIGN(PAGE_SIZE);                /* make sure the gate page doesn't expose
+                                * kernel data
+                                */
 
   .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET)
         { *(.data.read_mostly) }
@@ -202,7 +204,9 @@ SECTIONS
                *(.data.percpu)
                __per_cpu_end = .;
        }
-  . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits into percpu page size */
+  . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits
+                                                * into percpu page size
+                                                */
 
   data : { } :data
   .data : AT(ADDR(.data) - LOAD_OFFSET)
index e004143ba86b7f22ce19d8a002a3cbd944b94c7a..daf977ff2920e2c88aee4c6398a7d135bc22d802 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/mca.h>
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-static unsigned long num_dma_physpages;
 static unsigned long max_gap;
 #endif
 
@@ -41,10 +40,11 @@ show_mem (void)
        int i, total = 0, reserved = 0;
        int shared = 0, cached = 0;
 
-       printk("Mem-info:\n");
+       printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
 
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Free swap:       %6ldkB\n",
+              nr_swap_pages<<(PAGE_SHIFT-10));
        i = max_mapnr;
        for (i = 0; i < max_mapnr; i++) {
                if (!pfn_valid(i)) {
@@ -63,12 +63,12 @@ show_mem (void)
                else if (page_count(mem_map + i))
                        shared += page_count(mem_map + i) - 1;
        }
-       printk("%d pages of RAM\n", total);
-       printk("%d reserved pages\n", reserved);
-       printk("%d pages shared\n", shared);
-       printk("%d pages swap cached\n", cached);
-       printk("%ld pages in page table cache\n",
-               pgtable_quicklist_total_size());
+       printk(KERN_INFO "%d pages of RAM\n", total);
+       printk(KERN_INFO "%d reserved pages\n", reserved);
+       printk(KERN_INFO "%d pages shared\n", shared);
+       printk(KERN_INFO "%d pages swap cached\n", cached);
+       printk(KERN_INFO "%ld pages in page table cache\n",
+              pgtable_quicklist_total_size());
 }
 
 /* physical address where the bootmem map is located */
@@ -218,18 +218,6 @@ count_pages (u64 start, u64 end, void *arg)
        return 0;
 }
 
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-static int
-count_dma_pages (u64 start, u64 end, void *arg)
-{
-       unsigned long *count = arg;
-
-       if (start < MAX_DMA_ADDRESS)
-               *count += (min(end, MAX_DMA_ADDRESS) - start) >> PAGE_SHIFT;
-       return 0;
-}
-#endif
-
 /*
  * Set up the page tables.
  */
@@ -238,45 +226,22 @@ void __init
 paging_init (void)
 {
        unsigned long max_dma;
-       unsigned long zones_size[MAX_NR_ZONES];
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-       unsigned long zholes_size[MAX_NR_ZONES];
-#endif
-
-       /* initialize mem_map[] */
-
-       memset(zones_size, 0, sizeof(zones_size));
+       unsigned long nid = 0;
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
        num_physpages = 0;
        efi_memmap_walk(count_pages, &num_physpages);
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+       max_zone_pfns[ZONE_DMA] = max_dma;
+       max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-       memset(zholes_size, 0, sizeof(zholes_size));
-
-       num_dma_physpages = 0;
-       efi_memmap_walk(count_dma_pages, &num_dma_physpages);
-
-       if (max_low_pfn < max_dma) {
-               zones_size[ZONE_DMA] = max_low_pfn;
-               zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages;
-       } else {
-               zones_size[ZONE_DMA] = max_dma;
-               zholes_size[ZONE_DMA] = max_dma - num_dma_physpages;
-               if (num_physpages > num_dma_physpages) {
-                       zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
-                       zholes_size[ZONE_NORMAL] =
-                               ((max_low_pfn - max_dma) -
-                                (num_physpages - num_dma_physpages));
-               }
-       }
-
+       efi_memmap_walk(register_active_ranges, &nid);
        efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
        if (max_gap < LARGE_GAP) {
                vmem_map = (struct page *) 0;
-               free_area_init_node(0, NODE_DATA(0), zones_size, 0,
-                                   zholes_size);
+               free_area_init_nodes(max_zone_pfns);
        } else {
                unsigned long map_size;
 
@@ -288,20 +253,19 @@ paging_init (void)
                vmem_map = (struct page *) vmalloc_end;
                efi_memmap_walk(create_mem_map_page_table, NULL);
 
-               NODE_DATA(0)->node_mem_map = vmem_map;
-               free_area_init_node(0, NODE_DATA(0), zones_size,
-                                   0, zholes_size);
+               /*
+                * alloc_node_mem_map makes an adjustment for mem_map
+                * which isn't compatible with vmem_map.
+                */
+               NODE_DATA(0)->node_mem_map = vmem_map +
+                       find_min_pfn_with_active_regions();
+               free_area_init_nodes(max_zone_pfns);
 
                printk("Virtual mem_map starts at 0x%p\n", mem_map);
        }
 #else /* !CONFIG_VIRTUAL_MEM_MAP */
-       if (max_low_pfn < max_dma)
-               zones_size[ZONE_DMA] = max_low_pfn;
-       else {
-               zones_size[ZONE_DMA] = max_dma;
-               zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
-       }
-       free_area_init(zones_size);
+       add_active_range(0, 0, max_low_pfn);
+       free_area_init_nodes(max_zone_pfns);
 #endif /* !CONFIG_VIRTUAL_MEM_MAP */
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
index d260bffa01ab9ffd5949eec9f411554dc84ae9a7..d497b6b0f5b2c08d4be5cd50478399db993a2dc8 100644 (file)
@@ -547,15 +547,16 @@ void show_mem(void)
        unsigned long total_present = 0;
        pg_data_t *pgdat;
 
-       printk("Mem-info:\n");
+       printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Free swap:       %6ldkB\n",
+              nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Node memory in pages:\n");
        for_each_online_pgdat(pgdat) {
                unsigned long present;
                unsigned long flags;
                int shared = 0, cached = 0, reserved = 0;
 
-               printk("Node ID: %d\n", pgdat->node_id);
                pgdat_resize_lock(pgdat, &flags);
                present = pgdat->node_present_pages;
                for(i = 0; i < pgdat->node_spanned_pages; i++) {
@@ -579,18 +580,17 @@ void show_mem(void)
                total_reserved += reserved;
                total_cached += cached;
                total_shared += shared;
-               printk("\t%ld pages of RAM\n", present);
-               printk("\t%d reserved pages\n", reserved);
-               printk("\t%d pages shared\n", shared);
-               printk("\t%d pages swap cached\n", cached);
+               printk(KERN_INFO "Node %4d:  RAM: %11ld, rsvd: %8d, "
+                      "shrd: %10d, swpd: %10d\n", pgdat->node_id,
+                      present, reserved, shared, cached);
        }
-       printk("%ld pages of RAM\n", total_present);
-       printk("%d reserved pages\n", total_reserved);
-       printk("%d pages shared\n", total_shared);
-       printk("%d pages swap cached\n", total_cached);
-       printk("Total of %ld pages in page table cache\n",
-               pgtable_quicklist_total_size());
-       printk("%d free buffer pages\n", nr_free_buffer_pages());
+       printk(KERN_INFO "%ld pages of RAM\n", total_present);
+       printk(KERN_INFO "%d reserved pages\n", total_reserved);
+       printk(KERN_INFO "%d pages shared\n", total_shared);
+       printk(KERN_INFO "%d pages swap cached\n", total_cached);
+       printk(KERN_INFO "Total of %ld pages in page table cache\n",
+              pgtable_quicklist_total_size());
+       printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
 }
 
 /**
@@ -654,6 +654,7 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
 {
        unsigned long end = start + len;
 
+       add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT);
        mem_data[node].num_physpages += len >> PAGE_SHIFT;
        if (start <= __pa(MAX_DMA_ADDRESS))
                mem_data[node].num_dma_physpages +=
@@ -678,10 +679,10 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
 void __init paging_init(void)
 {
        unsigned long max_dma;
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long zholes_size[MAX_NR_ZONES];
        unsigned long pfn_offset = 0;
+       unsigned long max_pfn = 0;
        int node;
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
@@ -698,47 +699,20 @@ void __init paging_init(void)
 #endif
 
        for_each_online_node(node) {
-               memset(zones_size, 0, sizeof(zones_size));
-               memset(zholes_size, 0, sizeof(zholes_size));
-
                num_physpages += mem_data[node].num_physpages;
-
-               if (mem_data[node].min_pfn >= max_dma) {
-                       /* All of this node's memory is above ZONE_DMA */
-                       zones_size[ZONE_NORMAL] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn;
-                       zholes_size[ZONE_NORMAL] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn -
-                               mem_data[node].num_physpages;
-               } else if (mem_data[node].max_pfn < max_dma) {
-                       /* All of this node's memory is in ZONE_DMA */
-                       zones_size[ZONE_DMA] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn;
-                       zholes_size[ZONE_DMA] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn -
-                               mem_data[node].num_dma_physpages;
-               } else {
-                       /* This node has memory in both zones */
-                       zones_size[ZONE_DMA] = max_dma -
-                               mem_data[node].min_pfn;
-                       zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -
-                               mem_data[node].num_dma_physpages;
-                       zones_size[ZONE_NORMAL] = mem_data[node].max_pfn -
-                               max_dma;
-                       zholes_size[ZONE_NORMAL] = zones_size[ZONE_NORMAL] -
-                               (mem_data[node].num_physpages -
-                                mem_data[node].num_dma_physpages);
-               }
-
                pfn_offset = mem_data[node].min_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
                NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
 #endif
-               free_area_init_node(node, NODE_DATA(node), zones_size,
-                                   pfn_offset, zholes_size);
+               if (mem_data[node].max_pfn > max_pfn)
+                       max_pfn = mem_data[node].max_pfn;
        }
 
+       max_zone_pfns[ZONE_DMA] = max_dma;
+       max_zone_pfns[ZONE_NORMAL] = max_pfn;
+       free_area_init_nodes(max_zone_pfns);
+
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
 
index 14ef7cceb208bbd45031036cecadfda5e5527487..59f3ab937615fb0fbe40ae08061b3aa47a32a775 100644 (file)
@@ -146,9 +146,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
 #              error File is out of sync with <linux/mm.h>.  Please update.
 #      endif
 
+       if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE))))
+               goto bad_area;
+
        mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
-               | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
-               | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
+               | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
 
        if ((vma->vm_flags & mask) != mask)
                goto bad_area;
@@ -278,7 +280,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
 
   out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index 30617ccb4f7e69bc5e412dbc63aae8405e1a8691..ff87a5cba399f873348858fa7775a608ab2c3fb7 100644 (file)
@@ -593,6 +593,18 @@ find_largest_hole (u64 start, u64 end, void *arg)
        last_end = end;
        return 0;
 }
+
+int __init
+register_active_ranges(u64 start, u64 end, void *nid)
+{
+       BUG_ON(nid == NULL);
+       BUG_ON(*(unsigned long *)nid >= MAX_NUMNODES);
+
+       add_active_range(*(unsigned long *)nid,
+                               __pa(start) >> PAGE_SHIFT,
+                               __pa(end) >> PAGE_SHIFT);
+       return 0;
+}
 #endif /* CONFIG_VIRTUAL_MEM_MAP */
 
 static int __init
index 64e4c21f311cdc7f328165b18ae189e07476f885..7807fc5c04224fcad33d98a83d96a48a1df25423 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/node.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/module.h>
 #include <asm/mmzone.h>
 #include <asm/numa.h>
 
@@ -69,4 +70,21 @@ int early_pfn_to_nid(unsigned long pfn)
 
        return 0;
 }
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ *  SRAT information is stored in node_memblk[], then we can use SRAT
+ *  information at memory-hot-add if necessary.
+ */
+
+int memory_add_physaddr_to_nid(u64 addr)
+{
+       int nid = paddr_to_nid(addr);
+       if (nid < 0)
+               return 0;
+       return nid;
+}
+
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
 #endif
index 60b45e79f080dbf11f60e7deb362c1efd37cbc0f..15c7c670da39e042c0173467e289be1a737efca7 100644 (file)
@@ -562,7 +562,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
 void
 pcibios_disable_device (struct pci_dev *dev)
 {
-       acpi_pci_irq_disable(dev);
+       if (dev->is_enabled)
+               acpi_pci_irq_disable(dev);
 }
 
 void
index 27dee4584061ffc918f1d9450262e7124ab8fee6..7f73ad4408aaee3ad8977ad1ef2d1a89302cfbe5 100644 (file)
@@ -277,8 +277,7 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
        }
 
        /* temporary buffer used during unaligned transfers */
-       bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES,
-                                    GFP_KERNEL | GFP_DMA);
+       bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES, GFP_KERNEL);
        if (bteBlock_unaligned == NULL) {
                return BTEFAIL_NOTAVAIL;
        }
index 1f0253bfe0a0473f1a8b83046a4ca317204d0bf4..5eb1e1e078b4a1ab511cda2d87271da5a26e6c77 100644 (file)
@@ -160,7 +160,7 @@ void pcibr_ate_free(struct pcibus_info *pcibus_info, int index)
 
        volatile u64 ate;
        int count;
-       u64 flags;
+       unsigned long flags;
 
        if (pcibr_invalidate_ate) {
                /* For debugging purposes, clear the valid bit in the ATE */
index a86c7b9459625973a06c8e0adc2a32c3af8d8549..1ee977fb6ebb8ab3d33fdf7cd184994b41856522 100644 (file)
@@ -237,7 +237,7 @@ void sn_dma_flush(u64 addr)
        int is_tio;
        int wid_num;
        int i, j;
-       u64 flags;
+       unsigned long flags;
        u64 itte;
        struct hubdev_info *hubinfo;
        struct sn_flush_device_kernel *p;
index ded0be07a476f62aca9f42ed17ea3f757f0453f0..d8af155db9846eff93a3bb1aa3ba1776d9eec403 100644 (file)
@@ -38,7 +38,6 @@ extern void send_IPI_allbutself(int, int);
 extern void smp_local_timer_interrupt(struct pt_regs *);
 #endif
 
-extern unsigned long wall_jiffies;
 #define TICK_SIZE      (tick_nsec / 1000)
 
 /*
@@ -108,24 +107,17 @@ void do_gettimeofday(struct timeval *tv)
        unsigned long max_ntp_tick = tick_usec - tickadj;
 
        do {
-               unsigned long lost;
-
                seq = read_seqbegin(&xtime_lock);
 
                usec = do_gettimeoffset();
-               lost = jiffies - wall_jiffies;
 
                /*
                 * If time_adjust is negative then NTP is slowing the clock
                 * so make sure not to go into next possible interval.
                 * Better to lose some accuracy than have time go backwards..
                 */
-               if (unlikely(time_adjust < 0)) {
+               if (unlikely(time_adjust < 0))
                        usec = min(usec, max_ntp_tick);
-                       if (lost)
-                               usec += lost * max_ntp_tick;
-               } else if (unlikely(lost))
-                       usec += lost * tick_usec;
 
                sec = xtime.tv_sec;
                usec += (xtime.tv_nsec / 1000);
@@ -158,7 +150,6 @@ int do_settimeofday(struct timespec *tv)
         * made, and then undo it!
         */
        nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-       nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
        wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -202,7 +193,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #ifndef CONFIG_SMP
        profile_tick(CPU_PROFILING, regs);
 #endif
-       do_timer(regs);
+       do_timer(1);
 
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
index dc18a33eefef36ccd10790525b2537e4cae89255..8d5f551b5754305e87474b617b8e437925b48f76 100644 (file)
@@ -299,7 +299,7 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (tsk->pid == 1) {
+       if (is_init(tsk)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index a151849a605edc794593587a5d1c6b90911fc689..5152c4e6ac80dfec69bde07efe6754edf657df37 100644 (file)
 #include <asm/byteorder.h>
 
 #include <linux/vmalloc.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-static inline void
-remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
-              unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-       unsigned long pfn;
-       pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
-                                  | _PAGE_WRITE | flags);
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-               set_pte(pte, pfn_pte(pfn, pgprot));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int
-remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
-              unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int
-remap_area_pages(unsigned long address, unsigned long phys_addr,
-                unsigned long size, unsigned long flags)
-{
-       int error;
-       pgd_t * dir;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       dir = pgd_offset(&init_mm, address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pmd_t *pmd;
-               pmd = pmd_alloc(&init_mm, dir, address);
-               error = -ENOMEM;
-               if (!pmd)
-                       break;
-               if (remap_area_pmd(pmd, address, end - address,
-                                        phys_addr + address, flags))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return error;
-}
 
 /*
  * Generic mapping function (not visible outside):
@@ -129,6 +45,7 @@ __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
        void __iomem * addr;
        struct vm_struct * area;
        unsigned long offset, last_addr;
+       pgprot_t pgprot;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
@@ -157,6 +74,9 @@ __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
                                return NULL;
        }
 
+       pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
+                         | _PAGE_WRITE | flags);
+
        /*
         * Mappings have to be page-aligned
         */
@@ -172,7 +92,8 @@ __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
                return NULL;
        area->phys_addr = phys_addr;
        addr = (void __iomem *) area->addr;
-       if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, pgprot)) {
                vunmap((void __force *) addr);
                return NULL;
        }
index 98e4b1adfa29f3836cf69ddd339f02017669bff5..6cfc984380d96619dc821d840a35825701cca28d 100644 (file)
@@ -40,7 +40,7 @@ static inline int set_rtc_mmss(unsigned long nowtime)
  */
 static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 {
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -96,31 +96,23 @@ void time_init(void)
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
-       extern unsigned long wall_jiffies;
        unsigned long seq;
-       unsigned long usec, sec, lost;
+       unsigned long usec, sec;
        unsigned long max_ntp_tick = tick_usec - tickadj;
 
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
 
                usec = mach_gettimeoffset();
-               lost = jiffies - wall_jiffies;
 
                /*
                 * If time_adjust is negative then NTP is slowing the clock
                 * so make sure not to go into next possible interval.
                 * Better to lose some accuracy than have time go backwards..
                 */
-               if (unlikely(time_adjust < 0)) {
+               if (unlikely(time_adjust < 0))
                        usec = min(usec, max_ntp_tick);
 
-                       if (lost)
-                               usec += lost * max_ntp_tick;
-               }
-               else if (unlikely(lost))
-                       usec += lost * tick_usec;
-
                sec = xtime.tv_sec;
                usec += xtime.tv_nsec/1000;
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -141,7 +133,6 @@ int do_settimeofday(struct timespec *tv)
 {
        time_t wtm_sec, sec = tv->tv_sec;
        long wtm_nsec, nsec = tv->tv_nsec;
-       extern unsigned long wall_jiffies;
 
        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
                return -EINVAL;
@@ -153,8 +144,7 @@ int do_settimeofday(struct timespec *tv)
         * Discover what correction gettimeofday
         * would have done, and then undo it!
         */
-       nsec -= 1000 * (mach_gettimeoffset() +
-                       (jiffies - wall_jiffies) * (1000000 / HZ));
+       nsec -= 1000 * mach_gettimeoffset();
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
index aec15270d334b74795fbfdf7ec214434f35a923f..911f2ce3f53e11ec6d1e0deeba875735d5c2a13b 100644 (file)
@@ -144,7 +144,7 @@ good_area:
                case 1:         /* read, present */
                        goto acc_err;
                case 0:         /* read, not present */
-                       if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                       if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                                goto acc_err;
        }
 
@@ -181,7 +181,7 @@ good_area:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index f18b9d3ef16df601915abadca0d7f9d1df2b2726..dc4ea7e074a620e21e500b66b75ab10c21a31965 100644 (file)
@@ -65,7 +65,7 @@ static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
-        do_timer(fp);
+        do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(fp));
 #endif
index 1db9872722200b91fc56dde75be3781dca13b567..c5667bdddd5ef263551ef7e6c7633d75bc64a14b 100644 (file)
@@ -26,8 +26,6 @@
 
 #define        TICK_SIZE (tick_nsec / 1000)
 
-extern unsigned long wall_jiffies;
-
 
 static inline int set_rtc_mmss(unsigned long nowtime)
 {
@@ -51,7 +49,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 
        write_seqlock(&xtime_lock);
 
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -124,15 +122,12 @@ void time_init(void)
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
-       unsigned long lost, seq;
+       unsigned long seq;
        unsigned long usec, sec;
 
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
-               lost = jiffies - wall_jiffies;
-               if (lost)
-                       usec += lost * (1000000 / HZ);
                sec = xtime.tv_sec;
                usec += (xtime.tv_nsec / 1000);
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
index 330f6abc7703c0302db441be299eafc842a3ff52..30750c54bdf5169564855012899f6e2acb42299d 100644 (file)
@@ -126,7 +126,7 @@ config BASLER_EXCITE
        select IRQ_CPU
        select IRQ_CPU_RM7K
        select IRQ_CPU_RM9K
-       select SERIAL_RM9000
+       select MIPS_RM9122
        select SYS_HAS_CPU_RM9000
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
@@ -203,26 +203,6 @@ config MIPS_EV64120
          <http://www.marvell.com/>.  Say Y here if you wish to build a
          kernel for this platform.
 
-config MIPS_EV96100
-       bool "Galileo EV96100 Evaluation board (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       select DMA_NONCOHERENT
-       select HW_HAS_PCI
-       select IRQ_CPU
-       select MIPS_GT96100
-       select RM7000_CPU_SCACHE
-       select SWAP_IO_SPACE
-       select SYS_HAS_CPU_R5000
-       select SYS_HAS_CPU_RM7000
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-       select SYS_SUPPORTS_BIG_ENDIAN
-       help
-         This is an evaluation board based on the Galileo GT-96100 LAN/WAN
-         communications controllers containing a MIPS R5000 compatible core
-         running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
-         here if you wish to build a kernel for this platform.
-
 config MIPS_IVR
        bool "Globespan IVR board"
        select DMA_NONCOHERENT
@@ -974,6 +954,12 @@ config MIPS_TX3927
        bool
        select HAS_TXX9_SERIAL
 
+config MIPS_RM9122
+       bool
+       select SERIAL_RM9000
+       select GPI_RM9000
+       select WDT_RM9000
+
 config PCI_MARVELL
        bool
 
@@ -1024,6 +1010,15 @@ config EMMA2RH
        depends on MARKEINS
        default y
 
+config SERIAL_RM9000
+       bool
+
+config GPI_RM9000
+       bool
+
+config WDT_RM9000
+       bool
+
 #
 # Unfortunately not all GT64120 systems run the chip at the same clock.
 # As the user for the clock rate and try to minimize the available options.
@@ -1054,10 +1049,6 @@ config AU1X00_USB_DEVICE
        depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
        default n
 
-config MIPS_GT96100
-       bool
-       select MIPS_GT64120
-
 config IT8172_CIR
        bool
        depends on MIPS_ITE8172 || MIPS_IVR
@@ -1527,6 +1518,7 @@ config MIPS_MT_SMTC
        select CPU_MIPSR2_SRS
        select MIPS_MT
        select SMP
+       select SYS_SUPPORTS_SMP
        help
          This is a kernel model which is known a SMTC or lately has been
          marketesed into SMVP.
@@ -1538,6 +1530,7 @@ config MIPS_MT_SMP
        select CPU_MIPSR2_SRS
        select MIPS_MT
        select SMP
+       select SYS_SUPPORTS_SMP
        help
          This is a kernel model which is also known a VSMP or lately
          has been marketesed into SMVP.
@@ -1649,9 +1642,7 @@ config GENERIC_IRQ_PROBE
        default y
 
 config IRQ_PER_CPU
-       depends on SMP
        bool
-       default y
 
 #
 # - Highmem only makes sense for the 32-bit kernel.
@@ -1719,6 +1710,7 @@ source "mm/Kconfig"
 config SMP
        bool "Multi-Processing support"
        depends on SYS_SUPPORTS_SMP
+       select IRQ_PER_CPU
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index d333ce4ba26b54dfc5b188c9cd5a856c90099da8..e521826b423459bc5e3c9ff018954420f346403c 100644 (file)
@@ -279,13 +279,6 @@ core-$(CONFIG_MIPS_EV64120)        += arch/mips/gt64120/common/
 cflags-$(CONFIG_MIPS_EV64120)  += -Iinclude/asm-mips/mach-ev64120
 load-$(CONFIG_MIPS_EV64120)    += 0xffffffff80100000
 
-#
-# Galileo EV96100 Board
-#
-core-$(CONFIG_MIPS_EV96100)    += arch/mips/galileo-boards/ev96100/
-cflags-$(CONFIG_MIPS_EV96100)  += -Iinclude/asm-mips/mach-ev96100
-load-$(CONFIG_MIPS_EV96100)    += 0xffffffff80100000
-
 #
 # Wind River PPMC Board (4KC + GT64120)
 #
@@ -330,6 +323,7 @@ load-$(CONFIG_MIPS_MALTA)   += 0xffffffff80100000
 # MIPS SEAD board
 #
 core-$(CONFIG_MIPS_SEAD)       += arch/mips/mips-boards/sead/
+cflags-$(CONFIG_MIPS_SEAD)     += -Iinclude/asm-mips/mach-mips
 load-$(CONFIG_MIPS_SEAD)       += 0xffffffff80100000
 
 #
index 7fbea1bf7b4824afb61d2bacc1c28ab40d1e9458..0a067f3113a54704a454501a14452996ec8b87c2 100644 (file)
@@ -96,7 +96,7 @@ void mips_timer_interrupt(struct pt_regs *regs)
                timerlo = count;
 
                kstat_this_cpu.irqs[irq]++;
-               do_timer(regs);
+               do_timer(1);
 #ifndef CONFIG_SMP
                update_process_times(user_mode(regs));
 #endif
@@ -137,7 +137,7 @@ irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
        }
 
        while (time_elapsed > 0) {
-               do_timer(regs);
+               do_timer(1);
 #ifndef CONFIG_SMP
                update_process_times(user_mode(regs));
 #endif
@@ -156,7 +156,7 @@ irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
 
        if (jiffie_drift >= 999) {
                jiffie_drift -= 999;
-               do_timer(regs); /* increment jiffies by one */
+               do_timer(1); /* increment jiffies by one */
 #ifndef CONFIG_SMP
                update_process_times(user_mode(regs));
 #endif
index 4c7d763f21134f34f6a38c439208549cd7eb31ce..51d62bd5d900f93ad5408e71a3df031e027ea840 100644 (file)
@@ -6,4 +6,3 @@
 # Makefile for the Alchemy Semiconductor Db1x00 board.
 
 lib-y := init.o board_setup.o irqmap.o
-obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
deleted file mode 100644 (file)
index 0942dcf..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * linux/arch/mips/au1000/db1x00/mirage_ts.c
- *
- * BRIEF MODULE DESCRIPTION
- *     Glue between Mirage board-specific touchscreen pieces
- *     and generic Wolfson Codec touchscreen support.
- *
- *     Based on pb1100_ts.c used in Hydrogen II.
- *
- * Copyright (c) 2003 Embedded Edge, LLC
- *             dan@embeddededge.com
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/wait.h>
-
-#include <asm/segment.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/au1000.h>
-
-/*
- *  Imported interface to Wolfson Codec driver.
- */
-extern void *wm97xx_ts_get_handle(int which);
-extern int wm97xx_ts_ready(void* ts_handle);
-extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
-extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
-extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
-extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
-extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
-
-int wm97xx_comodule_present = 1;
-
-
-#define TS_NAME "mirage_ts"
-
-#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
-#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
-
-
-#define PEN_DOWN_IRQ   AU1000_GPIO_7
-
-static struct task_struct *ts_task = 0;
-static DECLARE_COMPLETION(ts_complete);
-static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
-
-#ifdef CONFIG_WM97XX_FIVEWIRETS
-static int release_pressure = 1;
-#else
-static int release_pressure = 50;
-#endif
-
-typedef struct {
-   long x;
-   long y;
-} DOWN_EVENT;
-
-#define SAMPLE_RATE    50      /* samples per second */
-#define PEN_DEBOUNCE   5       /* samples for settling - fn of SAMPLE_RATE */
-#define PEN_UP_TIMEOUT 10      /* in seconds */
-#define PEN_UP_SETTLE  5       /* samples per second */
-
-static struct {
-       int xscale;
-       int xtrans;
-       int yscale;
-       int ytrans;
-} mirage_ts_cal =
-{
-#if 0
-       .xscale   = 84,
-       .xtrans = -157,
-       .yscale   = 66,
-       .ytrans = -150,
-#else
-       .xscale   = 84,
-       .xtrans = -150,
-       .yscale   = 66,
-       .ytrans = -146,
-#endif
-};
-
-
-static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
-{
-//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
-       wake_up(&pendown_wait);
-}
-
-static int ts_thread(void *id)
-{
-       static int pen_was_down = 0;
-       static DOWN_EVENT pen_xy;
-       long x, y, z;
-       void *ts;       /* handle */
-       struct task_struct *tsk = current;
-       int timeout = HZ / SAMPLE_RATE;
-
-       ts_task = tsk;
-
-       daemonize();
-       tsk->tty = NULL;
-       tsk->policy = SCHED_FIFO;
-       tsk->rt_priority = 1;
-       strcpy(tsk->comm, "touchscreen");
-
-       /* only want to receive SIGKILL */
-       spin_lock_irq(&tsk->sigmask_lock);
-       siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
-       recalc_sigpending(tsk);
-       spin_unlock_irq(&tsk->sigmask_lock);
-
-       /* get handle for codec */
-       ts = wm97xx_ts_get_handle(0);
-
-       /* proceed only after everybody is ready */
-       wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
-
-       /* board-specific calibration */
-       wm97xx_ts_set_cal(ts,
-                       mirage_ts_cal.xscale,
-                       mirage_ts_cal.xtrans,
-                       mirage_ts_cal.yscale,
-                       mirage_ts_cal.ytrans);
-
-       /* route Wolfson pendown interrupts to our GPIO */
-       au_sync();
-       wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
-       au_sync();
-       wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
-       au_sync();
-       wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
-       au_sync();
-
-       for (;;) {
-               interruptible_sleep_on_timeout(&pendown_wait, timeout);
-               disable_irq(PEN_DOWN_IRQ);
-               if (signal_pending(tsk)) {
-                       break;
-               }
-
-               /* read codec */
-               if (!wm97xx_ts_read_data(ts, &x, &y, &z))
-                       z = 0;  /* treat no-data and pen-up the same */
-
-               if (signal_pending(tsk)) {
-                       break;
-               }
-
-               if (z >= release_pressure) {
-                       y = ~y; /* top to bottom */
-                       if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
-                               /* bounce ? */
-                               x = pen_xy.x;
-                               y = pen_xy.y;
-                               --pen_was_down;
-                       } else if (pen_was_down <= 1) {
-                               pen_xy.x = x;
-                               pen_xy.y = y;
-                               if (pen_was_down)
-                                       wm97xx_ts_send_data(ts, x, y, z);
-                               pen_was_down = PEN_DEBOUNCE;
-                       }
-                       //wm97xx_ts_send_data(ts, x, y, z);
-                       timeout = HZ / SAMPLE_RATE;
-               } else {
-                       if (pen_was_down) {
-                               if (--pen_was_down)
-                                       z = release_pressure;
-                               else //THXXX
-                               wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
-                       }
-                       /* The pendown signal takes some time to settle after
-                        * reading the pen pressure so wait a little
-                        * before enabling the pen.
-                        */
-                       if (! pen_was_down) {
-//                             interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
-                               timeout = HZ * PEN_UP_TIMEOUT;
-                       }
-               }
-               enable_irq(PEN_DOWN_IRQ);
-       }
-       enable_irq(PEN_DOWN_IRQ);
-       ts_task = NULL;
-       complete(&ts_complete);
-       return 0;
-}
-
-static int __init ts_mirage_init(void)
-{
-       int ret;
-
-       /* pen down signal is connected to GPIO 7 */
-
-       ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
-       if (ret) {
-               err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
-               return ret;
-       }
-
-       lock_kernel();
-       ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
-       if (ret < 0) {
-               unlock_kernel();
-               return ret;
-       }
-       unlock_kernel();
-
-       info("Mirage touchscreen IRQ initialized.");
-
-       return 0;
-}
-
-static void __exit ts_mirage_exit(void)
-{
-       if (ts_task) {
-               send_sig(SIGKILL, ts_task, 1);
-               wait_for_completion(&ts_complete);
-       }
-
-       free_irq(PEN_DOWN_IRQ, NULL);
-}
-
-module_init(ts_mirage_init);
-module_exit(ts_mirage_exit);
-
index bbb4ea43da88e37bf8fff9ded7397209a0996f29..cc1ce77eab4a7fd3757eeba3dc6dd8b1f8505c56 100644 (file)
@@ -68,7 +68,7 @@ enum {
 
 
 static struct resource
-       excite_ctr_resource = {
+       excite_ctr_resource __attribute__((unused)) = {
                .name           = "GPI counters",
                .start          = 0,
                .end            = 5,
@@ -77,7 +77,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_gpislice_resource = {
+       excite_gpislice_resource __attribute__((unused)) = {
                .name           = "GPI slices",
                .start          = 0,
                .end            = 1,
@@ -86,7 +86,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_mdio_channel_resource = {
+       excite_mdio_channel_resource __attribute__((unused)) = {
                .name           = "MDIO channels",
                .start          = 0,
                .end            = 1,
@@ -95,7 +95,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_fifomem_resource = {
+       excite_fifomem_resource __attribute__((unused)) = {
                .name           = "FIFO memory",
                .start          = 0,
                .end            = 767,
@@ -104,7 +104,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_scram_resource = {
+       excite_scram_resource __attribute__((unused)) = {
                .name           = "Scratch RAM",
                .start          = EXCITE_PHYS_SCRAM,
                .end            = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
@@ -113,7 +113,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_fpga_resource = {
+       excite_fpga_resource __attribute__((unused)) = {
                .name           = "System FPGA",
                .start          = EXCITE_PHYS_FPGA,
                .end            = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
@@ -122,7 +122,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_nand_resource = {
+       excite_nand_resource __attribute__((unused)) = {
                .name           = "NAND flash control",
                .start          = EXCITE_PHYS_NAND,
                .end            = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
@@ -131,7 +131,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_titan_resource = {
+       excite_titan_resource __attribute__((unused)) = {
                .name           = "TITAN registers",
                .start          = EXCITE_PHYS_TITAN,
                .end            = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h
deleted file mode 100644 (file)
index 38fcda7..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef EXCITE_FPGA_H_INCLUDED
-#define EXCITE_FPGA_H_INCLUDED
-
-
-/**
- * Adress alignment of the individual FPGA bytes.
- * The address arrangement of the individual bytes of the FPGA is two
- * byte aligned at the embedded MK2 platform.
- */
-#ifdef EXCITE_CCI_FPGA_MK2
-typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
-#else
-typedef unsigned char excite_cci_fpga_align_t;
-#endif
-
-
-/**
- * Size of Dual Ported RAM.
- */
-#define EXCITE_DPR_SIZE 263
-
-
-/**
- * Size of Reserved Status Fields in Dual Ported RAM.
- */
-#define EXCITE_DPR_STATUS_SIZE 7
-
-
-
-/**
- * FPGA.
- * Hardware register layout of the FPGA interface. The FPGA must accessed
- * byte wise solely.
- * @see EXCITE_CCI_DPR_MK2
- */
-typedef struct excite_fpga {
-
-       /**
-        * Dual Ported RAM.
-        */
-       excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
-
-       /**
-        * Status.
-        */
-       excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
-
-#ifdef EXCITE_CCI_FPGA_MK2
-       /**
-        * RM9000 Interrupt.
-        * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
-        */
-       excite_cci_fpga_align_t rm9k_int;
-#else
-       /**
-        * MK2 Interrupt.
-        * Write access initiates interrupt at the ARM processor of the MK2.
-        */
-       excite_cci_fpga_align_t mk2_int;
-
-       excite_cci_fpga_align_t gap[0x1000-0x10f];
-
-       /**
-        * IRQ Source/Acknowledge.
-        */
-       excite_cci_fpga_align_t rm9k_irq_src;
-
-       /**
-        * IRQ Mask.
-        * Set bits enable the related interrupt.
-        */
-       excite_cci_fpga_align_t rm9k_irq_mask;
-#endif
-
-
-} excite_fpga;
-
-
-
-#endif /* ndef EXCITE_FPGA_H_INCLUDED */
index 54274065e9a537e66e5d8dbe47bfc922cbfe5180..d3705284de39bf45d5c09dd34a1b7c7140168113 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1193,7 +1192,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 887fd959482a953d9be9ecdcc016430212010e0b..e12a475dcbf43cf85ef65bc5842837cda761ab2c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index a01344f3a4c2c610f1533ae202ec110dfb2a31a7..bfade9abb767f7bf1c987806959f3240831113c1 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index c95682445a2802d7a1366ae9c4107683c341758f..4baf2ff1128a0ba8b24c3d854b113969402dceb0 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -828,7 +827,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index c2f33d3af62c06a5d1c7d0caf92a0a5bfe7d209a..93cca1585bc342c08fb2ea2913c1698205379deb 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1000=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 8c44d16ae9a2b8f641ded987ab6bda67c6dba2ce..ffd99252a8376c9b83bd1cbc1797bf750ca5aa41 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1100=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index c13768e75ac5742c2ce556dd6ff00237b9d4b977..63eac5e89b9cdd63ae4208f8a261d4264a0d342d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1200=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 8aea73fae7fb3b2220268cc06f1a59a409ad1bf4..25a095f7dc4ef56dcab70debf6a207ce333c1111 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1500=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 90ccb7359630fa7ebdac11d302555723a2f942e1..dda469c842b35dedff228dd521e1229d5daa2f0e 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1550=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index b598cf08f15637dfcd3762e73368efb09e4d3c3c..fcd3dd19bc744e252440c318cdcc58edabfd9c3d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 597150b140771b8cd34103c65d9a5de3db344c66..8683e0df12e07615aaff8425a1490aa070fa5c41 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index fa2996bb4b7c8162a319f323b984a112fead3548..4ace61c95778992ad929c2d11a45b9b206655569 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:02 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:15:03 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -227,7 +226,6 @@ CONFIG_MMU=y
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -254,7 +252,6 @@ CONFIG_TRAD_SIGNALS=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -284,6 +281,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -643,6 +641,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -650,7 +649,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
+CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x1f0,0x3f6,40 mem=8M"
 
 #
 # Security options
index 375b2ac24a492c3732b72053eec97f554ca77b34..5847c916c130a90bf79b9e7f84f28be32ce809f7 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index b0afc118bd5c2498dc41f30a8b78d62278640b39..bc4c4f125c480087235a66bf41f2084b4ab11be2 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 CONFIG_MIPS_EV64120=y
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
deleted file mode 100644 (file)
index 0bdc10f..0000000
+++ /dev/null
@@ -1,850 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:05 2006
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-CONFIG_MIPS_EV96100=y
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_V2PCI is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_MIPS_GT64120=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_GT96100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=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_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT 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_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=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=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
-# CONFIG_LBD is not set
-# 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"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-# CONFIG_PCI is not set
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=y
-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 is not set
-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=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# 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_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI 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
-#
-
-#
-# I2O device support
-#
-
-#
-# 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
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-CONFIG_MIPS_GT96100ETH=y
-# CONFIG_DM9000 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN 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=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=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_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK 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
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI 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
-#
-
-#
-# 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
-#
-
-#
-# 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_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_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=m
-
-#
-# 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_SYSFS=y
-# CONFIG_TMPFS 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_CIFS_DEBUG2 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
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
index 045ebd0898935e02abfc002622b29226ef0579d6..eb87cbbfd03729923e9753d635268b28595a8057 100644 (file)
@@ -26,7 +26,6 @@ CONFIG_BASLER_EXCITE=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index ef16d1fb50715a5b45520d6eaad7afd8bc62ed8d..cc9b24eda9e89480f17b0ddfb09d506d86febdae 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1013,7 +1012,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 4bf1ee7f5f0033fc0471f7b4ac69d3b91aa624e2..50092ba8aa7135e381403a2459dbf74f88ee96c0 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -900,7 +899,7 @@ CONFIG_FUSE_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index f83dc09c3ca99782ca4fd6fec3ac76fdfe13f5d5..dec2ba6ba03f428a2b72c0780d28ac9149e2255b 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index a91d72a9ca8687c940b22a7e25555d07b56fd5ec..37f9dd7187b1073d12ba0a0ffda7597cfc6372ea 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 CONFIG_MIPS_ITE8172=y
 # CONFIG_MACH_JAZZ is not set
index cebc67212d0621e536f74259791e3d113b2203e3..18874a4c24fec8978ea5539c29e36d81265026f6 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 CONFIG_MIPS_IVR=y
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 5d9eb11aba3d0d1a5f9209d7cab57d65246ec9d0..9f1e3048d62347417d464d32ec7cc9ef5fb8bea0 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -731,7 +730,7 @@ CONFIG_FUSE_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
index be45a9044d06583ecd7b42b69544348de585a8f4..fded3f73815feaf13cfda7e025d6056a5949b803 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 64dc9f45a19c66e2f27dd15a8b40b40e2749bd60..320b8cdd6e589e9bfbac7127c53bdff629693a2a 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -905,7 +904,7 @@ CONFIG_FUSE_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 2690baf15a857833777513dad397d3b7cdca0fc2..0ba1ef5048fb0a88a5cbf0c96619fb11cb0cab3d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1230,7 +1229,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index c298979c18ae2be2eedab97c9d259be23b94bd24..adbeeadddb8f3da2bb16bd1270b4973793ef1cde 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 938b38ab5239ca9c32367695cfee543ae2db986c..79fd544fcb2a186b3ca0abcb5e8d4b319137a1cb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:15 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:16:46 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -71,7 +70,6 @@ CONFIG_MACH_VR41XX=y
 CONFIG_VICTOR_MPC30X=y
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
-CONFIG_VRC4173=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
@@ -168,6 +166,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
@@ -841,7 +840,7 @@ CONFIG_USB_PEGASUS=m
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
@@ -982,7 +981,6 @@ CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1007,6 +1005,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -1014,7 +1013,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
+CONFIG_CMDLINE="mem=32M console=ttyVR0,19200 ide0=0x170,0x376,73"
 
 #
 # Security options
index ec5758f22676a98a6f9a11c85ac28eeee459e209..4d87da2b99fde8ee93cd2c14deff41256ce935bb 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 0d33d87de1a1834fe672864cba7729de097e9d7a..a7ac2b0a8273a87ad46222717021bb316e96a331 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -774,7 +773,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 4b999102715eb761cc637991551c3907101db461..853e7bba5122e3294498a9224795b641c669370e 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -723,7 +722,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 827b344f60100084b424537c3e6d519964f87f4c..8524efa23a490b7983c04d7149a6106728ca1109 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -777,7 +776,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 9ed60fef69e024091e39ab5a0516b3924668e0ad..1a16e92900cbd9140f555f77a4f3d85eb791abb9 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1100=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 6774254b1be660cbe351428e3ed4569b544e44a2..9ea8edea6f2934c03b553038e824a9d856ff5a0c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1500=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 1afe5bf6e765617fef2cdaab291d89201f5ba0ee..c4a158976f8f97209cc524b4ed14e23a322d249c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1550=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index ac616c82d348c4bc4d3aa989a951e358ef7aee01..1cbf270c301ce416b8d84300db216980cb04e302 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index a8eb51bae3f36b6a1a922d3cffad4ea153a94534..bec30b15b9bdc448225cdee4ca981ca87da62362 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 6a63a113b7ea6a8ddc6d74711caaa82ef58d5ae9..f5f799e9370728d57f0f95dfc42c2f511e8c8b7b 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -687,7 +686,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
index 6779f449bd2d8d5f45328dc3431745511b00826d..2f5650227ba36aefbd454184f95f0f09699e2c9c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index b7826d3a2b77d0366d28c786dff02eb627df1f37..4fee90b2b100920580610e49900c19f4a1ecb774 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1442,7 +1441,7 @@ CONFIG_NTFS_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 625c1c619b6be225f58932874f3b3990acf9b71c..9041f095f96fb892f7c0c04937040227c9e118b1 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 4401b602118f0e19a83725c1def2dfb6aade9455..02abb2f1bfaf017b63f4379ffd52c02a9ca2ce00 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 2ba4e25e8c34e8c7f63508af4ea3190ace23b035..ca3d0c4ba15b5861b4147bc08cd7af91b84cd291 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index fc8a407c1addad2de7e925ce0310f0639b533676..4e2009ace278d7ce076074a089400caae5e99600 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index effcb63b81a327edc78c83f46c0282c780c3ad0b..535a813d01a932ba20936f3a71fdb6ceeb96111d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 4891d02ef8caba5a7f9ede6293dbfd9ce5a9ed9d..3a3ef20b21cc0afbe9c13d6b6b1c70282dfd9eb3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:21 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:13:04 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -166,6 +165,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
@@ -379,6 +379,7 @@ CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -855,7 +856,6 @@ CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -880,6 +880,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -887,7 +888,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
+CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M"
 
 #
 # Security options
index 3e4b16b39827b5961ed891f1efc1e58abfdf52bc..e6b1dea5584245b12be1b1d688667ea8e0bc22bf 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 3a68d8a25b661fb6506d7aede28cf383ed9d2fa4..06a072b77b1c963a75a620da8fc6563c4eb6e1d8 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index fff6fcc96212e65b9f252d1c6790b4c2aeb3d3bb..cc9b24eda9e89480f17b0ddfb09d506d86febdae 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 09:49:33 2006
+# Thu Jul  6 10:04:10 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1013,7 +1012,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
deleted file mode 100644 (file)
index cd868ec..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-#  Copyright 2000 MontaVista Software Inc.
-#  Author: MontaVista Software, Inc.
-#      ppopov@mvista.com or source@mvista.com
-#
-# Makefile for the Galileo EV96100 board.
-#
-
-obj-y          += init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/init.c b/arch/mips/galileo-boards/ev96100/init.c
deleted file mode 100644 (file)
index a01fe9b..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/generic.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/gt64120.h>
-
-
-/* Environment variable */
-
-typedef struct {
-       char *name;
-       char *val;
-} t_env_var;
-
-int prom_argc;
-char **prom_argv, **prom_envp;
-
-int init_debug = 0;
-
-char * __init prom_getcmdline(void)
-{
-       return &(arcs_cmdline[0]);
-}
-
-unsigned long __init prom_free_prom_memory(void)
-{
-       return 0;
-}
-
-void  __init prom_init_cmdline(void)
-{
-       char *cp;
-       int actr;
-
-       actr = 1; /* Always ignore argv[0] */
-
-       cp = &(arcs_cmdline[0]);
-       while(actr < prom_argc) {
-               strcpy(cp, prom_argv[actr]);
-               cp += strlen(prom_argv[actr]);
-               *cp++ = ' ';
-               actr++;
-       }
-       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
-               --cp;
-       *cp = '\0';
-}
-
-char *prom_getenv(char *envname)
-{
-       /*
-        * Return a pointer to the given environment variable.
-        */
-
-       t_env_var *env = (t_env_var *) prom_envp;
-       int i;
-
-       i = strlen(envname);
-
-       while (env->name) {
-               if (strncmp(envname, env->name, i) == 0) {
-                       return (env->val);
-               }
-               env++;
-       }
-       return (NULL);
-}
-
-static inline unsigned char str2hexnum(unsigned char c)
-{
-       if (c >= '0' && c <= '9')
-               return c - '0';
-       if (c >= 'a' && c <= 'f')
-               return c - 'a' + 10;
-       return 0;               /* foo */
-}
-
-static inline void str2eaddr(unsigned char *ea, unsigned char *str)
-{
-       int i;
-
-       for (i = 0; i < 6; i++) {
-               unsigned char num;
-
-               if ((*str == '.') || (*str == ':'))
-                       str++;
-               num = str2hexnum(*str++) << 4;
-               num |= (str2hexnum(*str++));
-               ea[i] = num;
-       }
-}
-
-int get_ethernet_addr(char *ethernet_addr)
-{
-       char *ethaddr_str;
-
-       ethaddr_str = prom_getenv("ethaddr");
-       if (!ethaddr_str) {
-               printk("ethaddr not set in boot prom\n");
-               return -1;
-       }
-       str2eaddr(ethernet_addr, ethaddr_str);
-
-       if (init_debug > 1) {
-               int i;
-               printk("get_ethernet_addr: ");
-               for (i = 0; i < 5; i++)
-                       printk("%02x:",
-                              (unsigned char) *(ethernet_addr + i));
-               printk("%02x\n", *(ethernet_addr + i));
-       }
-
-       return 0;
-}
-
-const char *get_system_type(void)
-{
-       return "Galileo EV96100";
-}
-
-void __init prom_init(void)
-{
-       volatile unsigned char *uart;
-       char ppbuf[8];
-
-       prom_argc = fw_arg0;
-       prom_argv = (char **) fw_arg1;
-       prom_envp = (char **) fw_arg2;
-
-       mips_machgroup = MACH_GROUP_GALILEO;
-       mips_machtype = MACH_EV96100;
-
-       prom_init_cmdline();
-
-       /* 32 MB upgradable */
-       add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
deleted file mode 100644 (file)
index ee5d672..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_int.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <asm/irq_cpu.h>
-
-static inline unsigned int ffz8(unsigned int word)
-{
-       unsigned long k;
-
-       k = 7;
-       if (word & 0x0fUL) { k -= 4;  word <<= 4;  }
-       if (word & 0x30UL) { k -= 2;  word <<= 2;  }
-       if (word & 0x40UL) { k -= 1; }
-
-       return k;
-}
-
-extern void mips_timer_interrupt(struct pt_regs *regs);
-
-asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
-{
-       do_IRQ(ffz8(pending >> 8), regs);
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
-       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
-       if (pending & CAUSEF_IP7)
-               mips_timer_interrupt(regs);
-       else if (pending)
-               ev96100_cpu_irq(pending, regs);
-       else
-               spurious_interrupt(regs);
-}
-
-void __init arch_init_irq(void)
-{
-       mips_cpu_irq_init(0);
-}
diff --git a/arch/mips/galileo-boards/ev96100/puts.c b/arch/mips/galileo-boards/ev96100/puts.c
deleted file mode 100644 (file)
index 49dc6d1..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-
-/*
- * Debug routines which directly access the uart.
- */
-
-#include <linux/types.h>
-#include <asm/gt64120.h>
-
-
-//#define SERIAL_BASE    EV96100_UART0_REGS_BASE
-#define SERIAL_BASE    0xBD000020
-#define NS16550_BASE   SERIAL_BASE
-
-#define SERA_CMD       0x0D
-#define SERA_DATA      0x08
-//#define SERB_CMD       0x05
-#define SERB_CMD       20
-#define SERB_DATA      0x00
-#define TX_BUSY        0x20
-
-#define TIMEOUT    0xffff
-#undef SLOW_DOWN
-
-static const char digits[16] = "0123456789abcdef";
-static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE;
-
-
-#ifdef SLOW_DOWN
-static inline void slow_down()
-{
-       int k;
-       for (k = 0; k < 10000; k++);
-}
-#else
-#define slow_down()
-#endif
-
-void putch(const unsigned char c)
-{
-       unsigned char ch;
-       int i = 0;
-
-       do {
-               ch = com1[SERB_CMD];
-               slow_down();
-               i++;
-               if (i > TIMEOUT) {
-                       break;
-               }
-       } while (0 == (ch & TX_BUSY));
-       com1[SERB_DATA] = c;
-}
-
-void putchar(const unsigned char c)
-{
-       unsigned char ch;
-       int i = 0;
-
-       do {
-               ch = com1[SERB_CMD];
-               slow_down();
-               i++;
-               if (i > TIMEOUT) {
-                       break;
-               }
-       } while (0 == (ch & TX_BUSY));
-       com1[SERB_DATA] = c;
-}
-
-void puts(unsigned char *cp)
-{
-       unsigned char ch;
-       int i = 0;
-
-       while (*cp) {
-               do {
-                       ch = com1[SERB_CMD];
-                       slow_down();
-                       i++;
-                       if (i > TIMEOUT) {
-                               break;
-                       }
-               } while (0 == (ch & TX_BUSY));
-               com1[SERB_DATA] = *cp++;
-       }
-       putch('\r');
-       putch('\n');
-}
-
-void fputs(unsigned char *cp)
-{
-       unsigned char ch;
-       int i = 0;
-
-       while (*cp) {
-
-               do {
-                       ch = com1[SERB_CMD];
-                       slow_down();
-                       i++;
-                       if (i > TIMEOUT) {
-                               break;
-                       }
-               } while (0 == (ch & TX_BUSY));
-               com1[SERB_DATA] = *cp++;
-       }
-}
-
-
-void put64(uint64_t ul)
-{
-       int cnt;
-       unsigned ch;
-
-       cnt = 16;               /* 16 nibbles in a 64 bit long */
-       putch('0');
-       putch('x');
-       do {
-               cnt--;
-               ch = (unsigned char) (ul >> cnt * 4) & 0x0F;
-               putch(digits[ch]);
-       } while (cnt > 0);
-}
-
-void put32(unsigned u)
-{
-       int cnt;
-       unsigned ch;
-
-       cnt = 8;                /* 8 nibbles in a 32 bit long */
-       putch('0');
-       putch('x');
-       do {
-               cnt--;
-               ch = (unsigned char) (u >> cnt * 4) & 0x0F;
-               putch(digits[ch]);
-       } while (cnt > 0);
-}
diff --git a/arch/mips/galileo-boards/ev96100/reset.c b/arch/mips/galileo-boards/ev96100/reset.c
deleted file mode 100644 (file)
index 5ef9b7f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 reset routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/reset.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
-static void mips_machine_restart(char *command)
-{
-       set_c0_status(ST0_BEV | ST0_ERL);
-       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-       flush_cache_all();
-       write_c0_wired(0);
-       __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-       while (1);
-}
-
-static void mips_machine_halt(void)
-{
-       printk(KERN_NOTICE "You can safely turn off the power\n");
-       while (1)
-               __asm__(".set\tmips3\n\t"
-                       "wait\n\t"
-                       ".set\tmips0");
-}
-
-void mips_reboot_setup(void)
-{
-       _machine_restart = mips_machine_restart;
-       _machine_halt = mips_machine_halt;
-}
diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c
deleted file mode 100644 (file)
index 639ad55..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 setup.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_setup.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/pci.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100int.h>
-
-
-extern char *__init prom_getcmdline(void);
-
-extern void mips_reboot_setup(void);
-
-unsigned char mac_0_1[12];
-
-void __init plat_mem_setup(void)
-{
-       unsigned int config = read_c0_config();
-       unsigned int status = read_c0_status();
-       unsigned int info = read_c0_info();
-       u32 tmp;
-
-       char *argptr;
-
-       clear_c0_status(ST0_FR);
-
-       if (config & 0x8)
-               printk("Secondary cache is enabled\n");
-       else
-               printk("Secondary cache is disabled\n");
-
-       if (status & (1 << 27))
-               printk("User-mode cache ops enabled\n");
-       else
-               printk("User-mode cache ops disabled\n");
-
-       printk("CP0 info reg: %x\n", (unsigned) info);
-       if (info & (1 << 28))
-               printk("burst mode Scache RAMS\n");
-       else
-               printk("pipelined Scache RAMS\n");
-
-       if (info & 0x1)
-               printk("Atomic Enable is set\n");
-
-       argptr = prom_getcmdline();
-#ifdef CONFIG_SERIAL_CONSOLE
-       if (strstr(argptr, "console=") == NULL) {
-               argptr = prom_getcmdline();
-               strcat(argptr, " console=ttyS0,115200");
-       }
-#endif
-
-       mips_reboot_setup();
-
-       set_io_port_base(KSEG1);
-       ioport_resource.start = GT_PCI_IO_BASE;
-       ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-#endif
-
-
-       /*
-        * Setup GT controller master bit so we can do config cycles
-        */
-
-       /* Clear cause register bits */
-       GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-                                    GT_INTRCAUSE_TARABORT0_BIT));
-       /* Setup address */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-       udelay(2);
-       tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
-
-       tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-               PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-       udelay(2);
-       GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
-
-       /* Setup address */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-       udelay(2);
-       tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
-}
-
-unsigned short get_gt_devid(void)
-{
-       u32 gt_devid;
-
-       /* Figure out if this is a gt96100 or gt96100A */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-       udelay(4);
-       gt_devid = GT_READ(GT_PCI0_CFGDATA_OFS);
-
-       return gt_devid >> 16;
-}
diff --git a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c
deleted file mode 100644 (file)
index 8cbe842..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 rtc routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_rtc.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/timex.h>
-
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
-#include <asm/time.h>
-
-
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
-
-extern volatile unsigned long wall_jiffies;
-unsigned long missed_heart_beats = 0;
-
-static unsigned long r4k_offset; /* Amount to increment compare reg each time */
-static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-
-static inline void ack_r4ktimer(unsigned long newval)
-{
-       write_c0_compare(newval);
-}
-
-/*
- * There are a lot of conceptually broken versions of the MIPS timer interrupt
- * handler floating around.  This one is rather different, but the algorithm
- * is probably more robust.
- */
-void mips_timer_interrupt(struct pt_regs *regs)
-{
-        int irq = 7; /* FIX ME */
-
-       if (r4k_offset == 0) {
-            goto null;
-        }
-
-       do {
-               kstat_this_cpu.irqs[irq]++;
-               do_timer(regs);
-#ifndef CONFIG_SMP
-               update_process_times(user_mode(regs));
-#endif
-               r4k_cur += r4k_offset;
-               ack_r4ktimer(r4k_cur);
-
-       } while (((unsigned long)read_c0_count()
-                    - r4k_cur) < 0x7fffffff);
-       return;
-
-null:
-       ack_r4ktimer(0);
-}
index d837b26fbe517e5602be5aec2ae5cb4d3b4ff244..7feca49350d18b4bc6ea2ed630c09bbfb3fd1937 100644 (file)
@@ -34,7 +34,7 @@ static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
        if (irq_src & 0x00000800) {     /* Check for timer interrupt */
                handled = 1;
                irq_src &= ~0x00000800;
-               do_timer(regs);
+               do_timer(1);
 #ifndef CONFIG_SMP
                update_process_times(user_mode(regs));
 #endif
index aa2caa67299a45ec4b5d8950b82bf695d611855c..9fbf8430c8499972ab80047026c803e64306a253 100644 (file)
@@ -38,15 +38,40 @@ static void r3081_wait(void)
 
 static void r39xx_wait(void)
 {
-       unsigned long cfg = read_c0_conf();
-       write_c0_conf(cfg | TX39_CONF_HALT);
+       local_irq_disable();
+       if (!need_resched())
+               write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
+       local_irq_enable();
 }
 
+/*
+ * There is a race when WAIT instruction executed with interrupt
+ * enabled.
+ * But it is implementation-dependent wheter the pipelie restarts when
+ * a non-enabled interrupt is requested.
+ */
 static void r4k_wait(void)
 {
-       __asm__(".set\tmips3\n\t"
-               "wait\n\t"
-               ".set\tmips0");
+       __asm__("       .set    mips3                   \n"
+               "       wait                            \n"
+               "       .set    mips0                   \n");
+}
+
+/*
+ * This variant is preferable as it allows testing need_resched and going to
+ * sleep depending on the outcome atomically.  Unfortunately the "It is
+ * implementation-dependent whether the pipeline restarts when a non-enabled
+ * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
+ * using this version a gamble.
+ */
+static void r4k_wait_irqoff(void)
+{
+       local_irq_disable();
+       if (!need_resched())
+               __asm__("       .set    mips3           \n"
+                       "       wait                    \n"
+                       "       .set    mips0           \n");
+       local_irq_enable();
 }
 
 /* The Au1xxx wait is available only if using 32khz counter or
@@ -56,17 +81,17 @@ int allow_au1k_wait;
 static void au1k_wait(void)
 {
        /* using the wait instruction makes CP0 counter unusable */
-       __asm__(".set mips3\n\t"
-               "cache 0x14, 0(%0)\n\t"
-               "cache 0x14, 32(%0)\n\t"
-               "sync\n\t"
-               "nop\n\t"
-               "wait\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               ".set mips0\n\t"
+       __asm__("       .set    mips3                   \n"
+               "       cache   0x14, 0(%0)             \n"
+               "       cache   0x14, 32(%0)            \n"
+               "       sync                            \n"
+               "       nop                             \n"
+               "       wait                            \n"
+               "       nop                             \n"
+               "       nop                             \n"
+               "       nop                             \n"
+               "       nop                             \n"
+               "       .set    mips0                   \n"
                : : "r" (au1k_wait));
 }
 
@@ -111,7 +136,6 @@ static inline void check_wait(void)
        case CPU_NEVADA:
        case CPU_RM7000:
        case CPU_RM9000:
-       case CPU_TX49XX:
        case CPU_4KC:
        case CPU_4KEC:
        case CPU_4KSC:
@@ -125,6 +149,10 @@ static inline void check_wait(void)
                cpu_wait = r4k_wait;
                printk(" available.\n");
                break;
+       case CPU_TX49XX:
+               cpu_wait = r4k_wait_irqoff;
+               printk(" available.\n");
+               break;
        case CPU_AU1000:
        case CPU_AU1100:
        case CPU_AU1500:
index 676e868d26fb15ab79b23d7c69be792276185be8..2132485caa744bbeddca7b4af11070b2e8c8591f 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 #undef DEBUG_SIG
 
@@ -172,11 +173,12 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
        return ret;
 }
 
-asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
+void do_irix_signal(struct pt_regs *regs)
 {
        struct k_sigaction ka;
        siginfo_t info;
        int signr;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which is why we may in certain
@@ -184,19 +186,28 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-       if (signr > 0)
-               return handle_signal(signr, &info, &ka, oldset, regs);
+       if (signr > 0) {
+               /* Whee!  Actually deliver the signal.  */
+               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
+
+               return;
+       }
 
-no_signal:
        /*
         * Who's code doesn't conform to the restartable syscall convention
         * dies here!!!  The li instruction, a single machine instruction,
@@ -208,8 +219,22 @@ no_signal:
                    regs->regs[2] == ERESTARTNOINTR) {
                        regs->cp0_epc -= 8;
                }
+               if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+                       regs->regs[2] = __NR_restart_syscall;
+                       regs->regs[7] = regs->regs[26];
+                       regs->cp0_epc -= 4;
+               }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
+       }
+
+       /*
+       * If there's no signal to deliver, we just put the saved sigmask
+       * back
+       */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
-       return 0;
 }
 
 asmlinkage void
@@ -298,6 +323,9 @@ struct sigact_irix5 {
        int _unused0[2];
 };
 
+#define SIG_SETMASK32  256     /* Goodie from SGI for BSD compatibility:
+                                  set only the low 32 bit of the sigset.  */
+
 #ifdef DEBUG_SIG
 static inline void dump_sigact_irix5(struct sigact_irix5 *p)
 {
@@ -413,7 +441,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
 
 asmlinkage int irix_sigsuspend(struct pt_regs *regs)
 {
-       sigset_t saveset, newset;
+       sigset_t newset;
        sigset_t __user *uset;
 
        uset = (sigset_t __user *) regs->regs[4];
@@ -422,18 +450,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        current->blocked = newset;
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs->regs[2] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_irix_signal(&saveset, regs))
-                       return -EINTR;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
 /* hate hate hate... */
index 450ac592da576c8314a1cec7d0851d891e4cc1d7..43b1162d714f281db07a3bad5b53bcf0576f8423 100644 (file)
@@ -991,7 +991,7 @@ struct sysctl_args32
        unsigned int __unused[4];
 };
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 
 asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
 {
@@ -1032,7 +1032,7 @@ asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
        return error;
 }
 
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 asmlinkage long sys32_newuname(struct new_utsname __user * name)
 {
@@ -1296,9 +1296,3 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
        return do_fork(clone_flags, newsp, &regs, 0,
                       parent_tidptr, child_tidptr);
 }
-
-extern asmlinkage void sys_set_thread_area(u32 addr);
-asmlinkage void sys32_set_thread_area(u32 addr)
-{
-       sys_set_thread_area(AA(addr));
-}
index 7ab67f786bfe277327f55517364855f4fc728b2f..2613a0dd4b823bde6959cd575d194cb8cb5677b8 100644 (file)
@@ -273,104 +273,107 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 
-static struct mips_frame_info {
-       void *func;
-       unsigned long func_size;
-       int frame_size;
-       int pc_offset;
-} *schedule_frame, mfinfo[64];
-static int mfinfo_num;
-
-static int __init get_frame_info(struct mips_frame_info *info)
+/*
+ *
+ */
+struct mips_frame_info {
+       void            *func;
+       unsigned long   func_size;
+       int             frame_size;
+       int             pc_offset;
+};
+
+static inline int is_ra_save_ins(union mips_instruction *ip)
 {
-       int i;
-       void *func = info->func;
-       union mips_instruction *ip = (union mips_instruction *)func;
+       /* sw / sd $ra, offset($sp) */
+       return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
+               ip->i_format.rs == 29 &&
+               ip->i_format.rt == 31;
+}
+
+static inline int is_jal_jalr_jr_ins(union mips_instruction *ip)
+{
+       if (ip->j_format.opcode == jal_op)
+               return 1;
+       if (ip->r_format.opcode != spec_op)
+               return 0;
+       return ip->r_format.func == jalr_op || ip->r_format.func == jr_op;
+}
+
+static inline int is_sp_move_ins(union mips_instruction *ip)
+{
+       /* addiu/daddiu sp,sp,-imm */
+       if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
+               return 0;
+       if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
+               return 1;
+       return 0;
+}
+
+static int get_frame_info(struct mips_frame_info *info)
+{
+       union mips_instruction *ip = info->func;
+       unsigned max_insns = info->func_size / sizeof(union mips_instruction);
+       unsigned i;
+
        info->pc_offset = -1;
        info->frame_size = 0;
-       for (i = 0; i < 128; i++, ip++) {
-               /* if jal, jalr, jr, stop. */
-               if (ip->j_format.opcode == jal_op ||
-                   (ip->r_format.opcode == spec_op &&
-                    (ip->r_format.func == jalr_op ||
-                     ip->r_format.func == jr_op)))
-                       break;
 
-               if (info->func_size && i >= info->func_size / 4)
+       if (!ip)
+               goto err;
+
+       if (max_insns == 0)
+               max_insns = 128U;       /* unknown function size */
+       max_insns = min(128U, max_insns);
+
+       for (i = 0; i < max_insns; i++, ip++) {
+
+               if (is_jal_jalr_jr_ins(ip))
                        break;
-               if (
-#ifdef CONFIG_32BIT
-                   ip->i_format.opcode == addiu_op &&
-#endif
-#ifdef CONFIG_64BIT
-                   ip->i_format.opcode == daddiu_op &&
-#endif
-                   ip->i_format.rs == 29 &&
-                   ip->i_format.rt == 29) {
-                       /* addiu/daddiu sp,sp,-imm */
-                       if (info->frame_size)
-                               continue;
-                       info->frame_size = - ip->i_format.simmediate;
+               if (!info->frame_size) {
+                       if (is_sp_move_ins(ip))
+                               info->frame_size = - ip->i_format.simmediate;
+                       continue;
                }
-
-               if (
-#ifdef CONFIG_32BIT
-                   ip->i_format.opcode == sw_op &&
-#endif
-#ifdef CONFIG_64BIT
-                   ip->i_format.opcode == sd_op &&
-#endif
-                   ip->i_format.rs == 29 &&
-                   ip->i_format.rt == 31) {
-                       /* sw / sd $ra, offset($sp) */
-                       if (info->pc_offset != -1)
-                               continue;
+               if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
                        info->pc_offset =
                                ip->i_format.simmediate / sizeof(long);
+                       break;
                }
        }
-       if (info->pc_offset == -1 || info->frame_size == 0) {
-               if (func == schedule)
-                       printk("Can't analyze prologue code at %p\n", func);
-               info->pc_offset = -1;
-               info->frame_size = 0;
-       }
-
-       return 0;
+       if (info->frame_size && info->pc_offset >= 0) /* nested */
+               return 0;
+       if (info->pc_offset < 0) /* leaf */
+               return 1;
+       /* prologue seems boggus... */
+err:
+       return -1;
 }
 
+static struct mips_frame_info schedule_mfi __read_mostly;
+
 static int __init frame_info_init(void)
 {
-       int i;
+       unsigned long size = 0;
 #ifdef CONFIG_KALLSYMS
+       unsigned long ofs;
        char *modname;
        char namebuf[KSYM_NAME_LEN + 1];
-       unsigned long start, size, ofs;
-       extern char __sched_text_start[], __sched_text_end[];
-       extern char __lock_text_start[], __lock_text_end[];
-
-       start = (unsigned long)__sched_text_start;
-       for (i = 0; i < ARRAY_SIZE(mfinfo); i++) {
-               if (start == (unsigned long)schedule)
-                       schedule_frame = &mfinfo[i];
-               if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf))
-                       break;
-               mfinfo[i].func = (void *)(start + ofs);
-               mfinfo[i].func_size = size;
-               start += size - ofs;
-               if (start >= (unsigned long)__lock_text_end)
-                       break;
-               if (start == (unsigned long)__sched_text_end)
-                       start = (unsigned long)__lock_text_start;
-       }
-#else
-       mfinfo[0].func = schedule;
-       schedule_frame = &mfinfo[0];
+
+       kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf);
 #endif
-       for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++)
-               get_frame_info(&mfinfo[i]);
+       schedule_mfi.func = schedule;
+       schedule_mfi.func_size = size;
+
+       get_frame_info(&schedule_mfi);
+
+       /*
+        * Without schedule() frame info, result given by
+        * thread_saved_pc() and get_wchan() are not reliable.
+        */
+       if (schedule_mfi.pc_offset < 0)
+               printk("Can't analyze schedule() prologue at %p\n", schedule);
 
-       mfinfo_num = i;
        return 0;
 }
 
@@ -386,54 +389,86 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        /* New born processes are a special case */
        if (t->reg31 == (unsigned long) ret_from_fork)
                return t->reg31;
-
-       if (!schedule_frame || schedule_frame->pc_offset < 0)
+       if (schedule_mfi.pc_offset < 0)
                return 0;
-       return ((unsigned long *)t->reg29)[schedule_frame->pc_offset];
+       return ((unsigned long *)t->reg29)[schedule_mfi.pc_offset];
 }
 
-/* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
-unsigned long get_wchan(struct task_struct *p)
+
+#ifdef CONFIG_KALLSYMS
+/* used by show_backtrace() */
+unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+                          unsigned long pc, unsigned long ra)
 {
        unsigned long stack_page;
-       unsigned long pc;
-#ifdef CONFIG_KALLSYMS
-       unsigned long frame;
-#endif
+       struct mips_frame_info info;
+       char *modname;
+       char namebuf[KSYM_NAME_LEN + 1];
+       unsigned long size, ofs;
+       int leaf;
 
-       if (!p || p == current || p->state == TASK_RUNNING)
+       stack_page = (unsigned long)task_stack_page(task);
+       if (!stack_page)
                return 0;
 
-       stack_page = (unsigned long)task_stack_page(p);
-       if (!stack_page || !mfinfo_num)
+       if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf))
+               return 0;
+       /*
+        * Return ra if an exception occured at the first instruction
+        */
+       if (unlikely(ofs == 0))
+               return ra;
+
+       info.func = (void *)(pc - ofs);
+       info.func_size = ofs;   /* analyze from start to ofs */
+       leaf = get_frame_info(&info);
+       if (leaf < 0)
+               return 0;
+
+       if (*sp < stack_page ||
+           *sp + info.frame_size > stack_page + THREAD_SIZE - 32)
                return 0;
 
-       pc = thread_saved_pc(p);
+       if (leaf)
+               /*
+                * For some extreme cases, get_frame_info() can
+                * consider wrongly a nested function as a leaf
+                * one. In that cases avoid to return always the
+                * same value.
+                */
+               pc = pc != ra ? ra : 0;
+       else
+               pc = ((unsigned long *)(*sp))[info.pc_offset];
+
+       *sp += info.frame_size;
+       return __kernel_text_address(pc) ? pc : 0;
+}
+#endif
+
+/*
+ * get_wchan - a maintenance nightmare^W^Wpain in the ass ...
+ */
+unsigned long get_wchan(struct task_struct *task)
+{
+       unsigned long pc = 0;
 #ifdef CONFIG_KALLSYMS
-       if (!in_sched_functions(pc))
-               return pc;
+       unsigned long sp;
+#endif
 
-       frame = p->thread.reg29 + schedule_frame->frame_size;
-       do {
-               int i;
+       if (!task || task == current || task->state == TASK_RUNNING)
+               goto out;
+       if (!task_stack_page(task))
+               goto out;
 
-               if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
-                       return 0;
+       pc = thread_saved_pc(task);
 
-               for (i = mfinfo_num - 1; i >= 0; i--) {
-                       if (pc >= (unsigned long) mfinfo[i].func)
-                               break;
-               }
-               if (i < 0)
-                       break;
+#ifdef CONFIG_KALLSYMS
+       sp = task->thread.reg29 + schedule_mfi.frame_size;
 
-               pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
-               if (!mfinfo[i].frame_size)
-                       break;
-               frame += mfinfo[i].frame_size;
-       } while (in_sched_functions(pc));
+       while (in_sched_functions(pc))
+               pc = unwind_stack(task, &sp, pc, 0);
 #endif
 
+out:
        return pc;
 }
-
index ba1bcd83c7d3ef71587a27d272f1fa970fdfef03..e7178510220635c5da2be58e59c3b839a36a0bfa 100644 (file)
@@ -662,6 +662,8 @@ einval:     li      v0, -EINVAL
        sys     sys_tee                 4
        sys     sys_vmsplice            4
        sys     sys_move_pages          6
+       sys     sys_set_robust_list     2
+       sys     sys_get_robust_list     3
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index 939e172db9531451c8e82df36914ba7b532ab5e2..4c22d0b4825dc70bcdfb5d239dc458d60d6c185c 100644 (file)
@@ -466,3 +466,5 @@ sys_call_table:
        PTR     sys_tee                         /* 5265 */
        PTR     sys_vmsplice
        PTR     sys_move_pages
+       PTR     sys_set_robust_list
+       PTR     sys_get_robust_list
index 98abbc5a9f13007d5d6f034d5fd7d0c231c5f314..f25c2a2f10387b10128bd92251cc9ee8df45559f 100644 (file)
@@ -247,7 +247,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_capset
        PTR     sys32_rt_sigpending             /* 6125 */
        PTR     compat_sys_rt_sigtimedwait
-       PTR     sys_rt_sigqueueinfo
+       PTR     sys32_rt_sigqueueinfo
        PTR     sysn32_rt_sigsuspend
        PTR     sys32_sigaltstack
        PTR     compat_sys_utime                /* 6130 */
@@ -390,5 +390,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_splice
        PTR     sys_sync_file_range
        PTR     sys_tee
-       PTR     sys_vmsplice                    /* 6271 */
+       PTR     sys_vmsplice                    /* 6270 */
        PTR     sys_move_pages
+       PTR     compat_sys_set_robust_list
+       PTR     compat_sys_get_robust_list
index 505c9ee540095f119b303cfcbc46e9ef86e74eca..288ee4ac4dbb8cce221c6b530b3da04bdae4eea1 100644 (file)
@@ -498,7 +498,7 @@ sys_call_table:
        PTR     sys_mknodat                     /* 4290 */
        PTR     sys_fchownat
        PTR     compat_sys_futimesat
-       PTR     compat_sys_newfstatat
+       PTR     sys_newfstatat
        PTR     sys_unlinkat
        PTR     sys_renameat                    /* 4295 */
        PTR     sys_linkat
@@ -514,4 +514,6 @@ sys_call_table:
        PTR     sys_tee
        PTR     sys_vmsplice
        PTR     compat_sys_move_pages
+       PTR     compat_sys_set_robust_list
+       PTR     compat_sys_get_robust_list      /* 4310 */
        .size   sys_call_table,.-sys_call_table
index 8c2b596a136f95376c45386b3fba0703d32f4991..fdbb508661c5d111af10dc3bce6d8d815fed681c 100644 (file)
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2000 2001, 2002  Maciej W. Rozycki
  */
-#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
 #include <linux/initrd.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 #include <linux/highmem.h>
 #include <linux/console.h>
-#include <linux/mmzone.h>
 #include <linux/pfn.h>
 
 #include <asm/addrspace.h>
@@ -96,6 +82,12 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
        int x = boot_mem_map.nr_map;
        struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
 
+       /* Sanity check */
+       if (start + size < start) {
+               printk("Trying to add an invalid memory region, skipped\n");
+               return;
+       }
+
        /*
         * Try to merge with previous entry if any.  This is far less than
         * perfect but is sufficient for most real world cases.
@@ -143,167 +135,132 @@ static void __init print_memory_map(void)
        }
 }
 
-static inline void parse_cmdline_early(void)
+/*
+ * Manage initrd
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init rd_start_early(char *p)
 {
-       char c = ' ', *to = command_line, *from = saved_command_line;
-       unsigned long start_at, mem_size;
-       int len = 0;
-       int usermem = 0;
+       unsigned long start = memparse(p, &p);
 
-       printk("Determined physical RAM map:\n");
-       print_memory_map();
+#ifdef CONFIG_64BIT
+       /* HACK: Guess if the sign extension was forgotten */
+       if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+               start |= 0xffffffff00000000UL;
+#endif
+       initrd_start = start;
+       initrd_end += start;
 
-       for (;;) {
-               /*
-                * "mem=XXX[kKmM]" defines a memory region from
-                * 0 to <XXX>, overriding the determined size.
-                * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
-                * <YYY> to <YYY>+<XXX>, overriding the determined size.
-                */
-               if (c == ' ' && !memcmp(from, "mem=", 4)) {
-                       if (to != command_line)
-                               to--;
-                       /*
-                        * If a user specifies memory size, we
-                        * blow away any automatically generated
-                        * size.
-                        */
-                       if (usermem == 0) {
-                               boot_mem_map.nr_map = 0;
-                               usermem = 1;
-                       }
-                       mem_size = memparse(from + 4, &from);
-                       if (*from == '@')
-                               start_at = memparse(from + 1, &from);
-                       else
-                               start_at = 0;
-                       add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
-               }
-               c = *(from++);
-               if (!c)
-                       break;
-               if (CL_SIZE <= ++len)
-                       break;
-               *(to++) = c;
-       }
-       *to = '\0';
+       return 0;
+}
+early_param("rd_start", rd_start_early);
 
-       if (usermem) {
-               printk("User-defined physical RAM map:\n");
-               print_memory_map();
-       }
+static int __init rd_size_early(char *p)
+{
+       initrd_end += memparse(p, &p);
+
+       return 0;
 }
+early_param("rd_size", rd_size_early);
 
-static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+static unsigned long __init init_initrd(void)
 {
+       unsigned long tmp, end, size;
+       u32 *initrd_header;
+
+       ROOT_DEV = Root_RAM0;
+
        /*
-        * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
-        * "rd_size=0xNN" it's size
+        * Board specific code or command line parser should have
+        * already set up initrd_start and initrd_end. In these cases
+        * perfom sanity checks and use them if all looks good.
         */
-       unsigned long start = 0;
-       unsigned long size = 0;
-       unsigned long end;
-       char cmd_line[CL_SIZE];
-       char *start_str;
-       char *size_str;
-       char *tmp;
-
-       strcpy(cmd_line, command_line);
-       *command_line = 0;
-       tmp = cmd_line;
-       /* Ignore "rd_start=" strings in other parameters. */
-       start_str = strstr(cmd_line, "rd_start=");
-       if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
-               start_str = strstr(start_str, " rd_start=");
-       while (start_str) {
-               if (start_str != cmd_line)
-                       strncat(command_line, tmp, start_str - tmp);
-               start = memparse(start_str + 9, &start_str);
-               tmp = start_str + 1;
-               start_str = strstr(start_str, " rd_start=");
+       size = initrd_end - initrd_start;
+       if (initrd_end == 0 || size == 0) {
+               initrd_start = 0;
+               initrd_end = 0;
+       } else
+               return initrd_end;
+
+       end = (unsigned long)&_end;
+       tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
+       if (tmp < end)
+               tmp += PAGE_SIZE;
+
+       initrd_header = (u32 *)tmp;
+       if (initrd_header[0] == 0x494E5244) {
+               initrd_start = (unsigned long)&initrd_header[2];
+               initrd_end = initrd_start + initrd_header[1];
        }
-       if (*tmp)
-               strcat(command_line, tmp);
-
-       strcpy(cmd_line, command_line);
-       *command_line = 0;
-       tmp = cmd_line;
-       /* Ignore "rd_size" strings in other parameters. */
-       size_str = strstr(cmd_line, "rd_size=");
-       if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
-               size_str = strstr(size_str, " rd_size=");
-       while (size_str) {
-               if (size_str != cmd_line)
-                       strncat(command_line, tmp, size_str - tmp);
-               size = memparse(size_str + 8, &size_str);
-               tmp = size_str + 1;
-               size_str = strstr(size_str, " rd_size=");
+       return initrd_end;
+}
+
+static void __init finalize_initrd(void)
+{
+       unsigned long size = initrd_end - initrd_start;
+
+       if (size == 0) {
+               printk(KERN_INFO "Initrd not found or empty");
+               goto disable;
+       }
+       if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+               printk("Initrd extends beyond end of memory");
+               goto disable;
        }
-       if (*tmp)
-               strcat(command_line, tmp);
 
-#ifdef CONFIG_64BIT
-       /* HACK: Guess if the sign extension was forgotten */
-       if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
-               start |= 0xffffffff00000000UL;
+       reserve_bootmem(CPHYSADDR(initrd_start), size);
+       initrd_below_start_ok = 1;
+
+       printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
+              initrd_start, size);
+       return;
+disable:
+       printk(" - disabling initrd\n");
+       initrd_start = 0;
+       initrd_end = 0;
+}
+
+#else  /* !CONFIG_BLK_DEV_INITRD */
+
+#define init_initrd()          0
+#define finalize_initrd()      do {} while (0)
+
 #endif
 
-       end = start + size;
-       if (start && end) {
-               *rd_start = start;
-               *rd_end = end;
-               return 1;
-       }
-       return 0;
+/*
+ * Initialize the bootmem allocator. It also setup initrd related data
+ * if needed.
+ */
+#ifdef CONFIG_SGI_IP27
+
+static void __init bootmem_init(void)
+{
+       init_initrd();
+       finalize_initrd();
 }
 
-#define MAXMEM         HIGHMEM_START
-#define MAXMEM_PFN     PFN_DOWN(MAXMEM)
+#else  /* !CONFIG_SGI_IP27 */
 
-static inline void bootmem_init(void)
+static void __init bootmem_init(void)
 {
-       unsigned long start_pfn;
-       unsigned long reserved_end = (unsigned long)&_end;
-#ifndef CONFIG_SGI_IP27
-       unsigned long first_usable_pfn;
+       unsigned long reserved_end;
+       unsigned long highest = 0;
+       unsigned long mapstart = -1UL;
        unsigned long bootmap_size;
        int i;
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-       int initrd_reserve_bootmem = 0;
-
-       /* Board specific code should have set up initrd_start and initrd_end */
-       ROOT_DEV = Root_RAM0;
-       if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
-               reserved_end = max(reserved_end, initrd_end);
-               initrd_reserve_bootmem = 1;
-       } else {
-               unsigned long tmp;
-               u32 *initrd_header;
-
-               tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2;
-               if (tmp < reserved_end)
-                       tmp += PAGE_SIZE;
-               initrd_header = (u32 *)tmp;
-               if (initrd_header[0] == 0x494E5244) {
-                       initrd_start = (unsigned long)&initrd_header[2];
-                       initrd_end = initrd_start + initrd_header[1];
-                       reserved_end = max(reserved_end, initrd_end);
-                       initrd_reserve_bootmem = 1;
-               }
-       }
-#endif /* CONFIG_BLK_DEV_INITRD */
 
        /*
-        * Partially used pages are not usable - thus
-        * we are rounding upwards.
+        * Init any data related to initrd. It's a nop if INITRD is
+        * not selected. Once that done we can determine the low bound
+        * of usable memory.
         */
-       start_pfn = PFN_UP(CPHYSADDR(reserved_end));
+       reserved_end = init_initrd();
+       reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
 
-#ifndef CONFIG_SGI_IP27
-       /* Find the highest page frame number we have available.  */
-       max_pfn = 0;
-       first_usable_pfn = -1UL;
+       /*
+        * Find the highest page frame number we have available.
+        */
        for (i = 0; i < boot_mem_map.nr_map; i++) {
                unsigned long start, end;
 
@@ -312,56 +269,38 @@ static inline void bootmem_init(void)
 
                start = PFN_UP(boot_mem_map.map[i].addr);
                end = PFN_DOWN(boot_mem_map.map[i].addr
-                     + boot_mem_map.map[i].size);
+                               + boot_mem_map.map[i].size);
 
-               if (start >= end)
+               if (end > highest)
+                       highest = end;
+               if (end <= reserved_end)
                        continue;
-               if (end > max_pfn)
-                       max_pfn = end;
-               if (start < first_usable_pfn) {
-                       if (start > start_pfn) {
-                               first_usable_pfn = start;
-                       } else if (end > start_pfn) {
-                               first_usable_pfn = start_pfn;
-                       }
-               }
+               if (start >= mapstart)
+                       continue;
+               mapstart = max(reserved_end, start);
        }
 
        /*
         * Determine low and high memory ranges
         */
-       max_low_pfn = max_pfn;
-       if (max_low_pfn > MAXMEM_PFN) {
-               max_low_pfn = MAXMEM_PFN;
-#ifndef CONFIG_HIGHMEM
-               /* Maximum memory usable is what is directly addressable */
-               printk(KERN_WARNING "Warning only %ldMB will be used.\n",
-                      MAXMEM >> 20);
-               printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+       if (highest > PFN_DOWN(HIGHMEM_START)) {
+#ifdef CONFIG_HIGHMEM
+               highstart_pfn = PFN_DOWN(HIGHMEM_START);
+               highend_pfn = highest;
 #endif
+               highest = PFN_DOWN(HIGHMEM_START);
        }
 
-#ifdef CONFIG_HIGHMEM
        /*
-        * Crude, we really should make a better attempt at detecting
-        * highstart_pfn
+        * Initialize the boot-time allocator with low memory only.
         */
-       highstart_pfn = highend_pfn = max_pfn;
-       if (max_pfn > MAXMEM_PFN) {
-               highstart_pfn = MAXMEM_PFN;
-               printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
-                      (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT));
-       }
-#endif
-
-       /* Initialize the boot-time allocator with low memory only.  */
-       bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
+       bootmap_size = init_bootmem(mapstart, highest);
 
        /*
         * Register fully available low RAM pages with the bootmem allocator.
         */
        for (i = 0; i < boot_mem_map.nr_map; i++) {
-               unsigned long curr_pfn, last_pfn, size;
+               unsigned long start, end, size;
 
                /*
                 * Reserve usable memory.
@@ -369,85 +308,50 @@ static inline void bootmem_init(void)
                if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
                        continue;
 
-               /*
-                * We are rounding up the start address of usable memory:
-                */
-               curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
-               if (curr_pfn >= max_low_pfn)
-                       continue;
-               if (curr_pfn < start_pfn)
-                       curr_pfn = start_pfn;
-
-               /*
-                * ... and at the end of the usable range downwards:
-                */
-               last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
+               start = PFN_UP(boot_mem_map.map[i].addr);
+               end   = PFN_DOWN(boot_mem_map.map[i].addr
                                    + boot_mem_map.map[i].size);
-
-               if (last_pfn > max_low_pfn)
-                       last_pfn = max_low_pfn;
-
                /*
-                * Only register lowmem part of lowmem segment with bootmem.
+                * We are rounding up the start address of usable memory
+                * and at the end of the usable range downwards.
                 */
-               size = last_pfn - curr_pfn;
-               if (curr_pfn > PFN_DOWN(HIGHMEM_START))
-                       continue;
-               if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START))
-                       size = PFN_DOWN(HIGHMEM_START) - curr_pfn;
-               if (!size)
+               if (start >= max_low_pfn)
                        continue;
+               if (start < reserved_end)
+                       start = reserved_end;
+               if (end > max_low_pfn)
+                       end = max_low_pfn;
 
                /*
-                * ... finally, did all the rounding and playing
-                * around just make the area go away?
+                * ... finally, is the area going away?
                 */
-               if (last_pfn <= curr_pfn)
+               if (end <= start)
                        continue;
+               size = end - start;
 
                /* Register lowmem ranges */
-               free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
-               memory_present(0, curr_pfn, curr_pfn + size - 1);
+               free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT);
+               memory_present(0, start, end);
        }
 
-       /* Reserve the bootmap memory.  */
-       reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
-#endif /* CONFIG_SGI_IP27 */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       initrd_below_start_ok = 1;
-       if (initrd_start) {
-               unsigned long initrd_size = ((unsigned char *)initrd_end) -
-                       ((unsigned char *)initrd_start);
-               const int width = sizeof(long) * 2;
-
-               printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
-                      (void *)initrd_start, initrd_size);
-
-               if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
-                       printk("initrd extends beyond end of memory "
-                              "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
-                              width,
-                              (unsigned long long) CPHYSADDR(initrd_end),
-                              width,
-                              (unsigned long long) PFN_PHYS(max_low_pfn));
-                       initrd_start = initrd_end = 0;
-                       initrd_reserve_bootmem = 0;
-               }
+       /*
+        * Reserve the bootmap memory.
+        */
+       reserve_bootmem(PFN_PHYS(mapstart), bootmap_size);
 
-               if (initrd_reserve_bootmem)
-                       reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
-       }
-#endif /* CONFIG_BLK_DEV_INITRD  */
+       /*
+        * Reserve initrd memory if needed.
+        */
+       finalize_initrd();
 }
 
+#endif /* CONFIG_SGI_IP27 */
+
 /*
  * arch_mem_init - initialize memory managment subsystem
  *
  *  o plat_mem_setup() detects the memory configuration and will record detected
  *    memory areas using add_memory_region.
- *  o parse_cmdline_early() parses the command line for mem= options which,
- *    iff detected, will override the results of the automatic detection.
  *
  * At this stage the memory configuration of the system is known to the
  * kernel but generic memory managment system is still entirely uninitialized.
@@ -465,25 +369,59 @@ static inline void bootmem_init(void)
  * initialization hook for anything else was introduced.
  */
 
-extern void plat_mem_setup(void);
+static int usermem __initdata = 0;
+
+static int __init early_parse_mem(char *p)
+{
+       unsigned long start, size;
+
+       /*
+        * If a user specifies memory size, we
+        * blow away any automatically generated
+        * size.
+        */
+       if (usermem == 0) {
+               boot_mem_map.nr_map = 0;
+               usermem = 1;
+       }
+       start = 0;
+       size = memparse(p, &p);
+       if (*p == '@')
+               start = memparse(p + 1, &p);
+
+       add_memory_region(start, size, BOOT_MEM_RAM);
+       return 0;
+}
+early_param("mem", early_parse_mem);
 
 static void __init arch_mem_init(char **cmdline_p)
 {
+       extern void plat_mem_setup(void);
+
        /* call board setup routine */
        plat_mem_setup();
 
+       printk("Determined physical RAM map:\n");
+       print_memory_map();
+
        strlcpy(command_line, arcs_cmdline, sizeof(command_line));
        strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
 
        *cmdline_p = command_line;
 
-       parse_cmdline_early();
+       parse_early_param();
+
+       if (usermem) {
+               printk("User-defined physical RAM map:\n");
+               print_memory_map();
+       }
+
        bootmem_init();
        sparse_init();
        paging_init();
 }
 
-static inline void resource_init(void)
+static void __init resource_init(void)
 {
        int i;
 
@@ -504,10 +442,10 @@ static inline void resource_init(void)
 
                start = boot_mem_map.map[i].addr;
                end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1;
-               if (start >= MAXMEM)
+               if (start >= HIGHMEM_START)
                        continue;
-               if (end >= MAXMEM)
-                       end = MAXMEM - 1;
+               if (end >= HIGHMEM_START)
+                       end = HIGHMEM_START - 1;
 
                res = alloc_bootmem(sizeof(struct resource));
                switch (boot_mem_map.map[i].type) {
@@ -536,9 +474,6 @@ static inline void resource_init(void)
        }
 }
 
-#undef MAXMEM
-#undef MAXMEM_PFN
-
 void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
index 6b4d9be31615b3325d50d6fb48c6627c7f748850..b9d358e052144bb501956da1afca37553ab58394 100644 (file)
@@ -424,15 +424,11 @@ void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
 
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
@@ -446,9 +442,10 @@ void do_signal(struct pt_regs *regs)
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
                }
+
+               return;
        }
 
-no_signal:
        /*
         * Who's code doesn't conform to the restartable syscall convention
         * dies here!!!  The li instruction, a single machine instruction,
@@ -466,6 +463,7 @@ no_signal:
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*
index f32a22997c3d68d1754f745564b9dbac4e3928d2..c86a5ddff050a78661eced6ca74a68b5358b5187 100644 (file)
@@ -815,9 +815,6 @@ void do_signal32(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                oldset = &current->saved_sigmask;
        else
@@ -836,9 +833,10 @@ void do_signal32(struct pt_regs *regs)
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
                }
+
+               return;
        }
 
-no_signal:
        /*
         * Who's code doesn't conform to the restartable syscall convention
         * dies here!!!  The li instruction, a single machine instruction,
@@ -856,6 +854,7 @@ no_signal:
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*
index 477c5334ec1b459eefb010c9ef5918ca1358b47b..50c17eaa7f252c0012efb15054c25797a793cea4 100644 (file)
@@ -42,6 +42,8 @@
 
 #include "signal-common.h"
 
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
@@ -81,8 +83,6 @@ struct rt_sigframe_n32 {
 #endif
 };
 
-extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
-
 save_static_function(sysn32_rt_sigsuspend);
 __attribute_used__ noinline static int
 _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
index 93429a4d301296d2b550ce34d8f254ea93aaa8aa..766253c44f3fd8d3dcae954755702e13bb78506a 100644 (file)
@@ -203,7 +203,7 @@ void plat_smp_setup(void)
                                write_vpe_c0_config( read_c0_config());
 
                                /* make sure there are no software interrupts pending */
-                               write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+                               write_vpe_c0_cause(0);
 
                                /* Propagate Config7 */
                                write_vpe_c0_config7(read_c0_config7());
index 4cc3dea36612556925aa199e2a150d5e1918b5e4..76cb31d574824a3bb6f876d10ebacb470a0a02a6 100644 (file)
@@ -8,7 +8,7 @@
 #include <asm/regdef.h>
 #include <asm/asmmacro.h>
 #include <asm/stackframe.h>
-#include <asm/stackframe.h>
+#include <asm/irqflags.h>
 
 /*
  * "Software Interrupt" linkage.
index 0721314db6573b4c0efcd2d35dc458ee99d09474..9951240cc3fd23fde7c356542534de4c79a904af 100644 (file)
@@ -263,7 +263,7 @@ asmlinkage int sys_olduname(struct oldold_utsname __user * name)
        return error;
 }
 
-void sys_set_thread_area(unsigned long addr)
+asmlinkage int sys_set_thread_area(unsigned long addr)
 {
        struct thread_info *ti = task_thread_info(current);
 
@@ -271,6 +271,8 @@ void sys_set_thread_area(unsigned long addr)
 
        /* If some future MIPS implementation has this register in hardware,
         * we will need to update it here (and in context switches).  */
+
+       return 0;
 }
 
 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
index 170cb67f4ede504d67f38072a14735056daad8c2..845c7e55505d39f3335e66f031e723b2729d6406 100644 (file)
@@ -47,8 +47,6 @@
 /*
  * forward reference
  */
-extern volatile unsigned long wall_jiffies;
-
 DEFINE_SPINLOCK(rtc_lock);
 
 /*
@@ -159,7 +157,6 @@ void (*mips_hpt_init)(unsigned int);
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long seq;
-       unsigned long lost;
        unsigned long usec, sec;
        unsigned long max_ntp_tick;
 
@@ -168,8 +165,6 @@ void do_gettimeofday(struct timeval *tv)
 
                usec = do_gettimeoffset();
 
-               lost = jiffies - wall_jiffies;
-
                /*
                 * If time_adjust is negative then NTP is slowing the clock
                 * so make sure not to go into next possible interval.
@@ -178,11 +173,7 @@ void do_gettimeofday(struct timeval *tv)
                if (unlikely(time_adjust < 0)) {
                        max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
                        usec = min(usec, max_ntp_tick);
-
-                       if (lost)
-                               usec += lost * max_ntp_tick;
-               } else if (unlikely(lost))
-                       usec += lost * (USEC_PER_SEC / HZ);
+               }
 
                sec = xtime.tv_sec;
                usec += (xtime.tv_nsec / 1000);
@@ -217,7 +208,6 @@ int do_settimeofday(struct timespec *tv)
         * made, and then undo it!
         */
        nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-       nsec -= (jiffies - wall_jiffies) * tick_nsec;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -434,7 +424,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        /*
         * call the generic timer interrupt handling
         */
-       do_timer(regs);
+       do_timer(1);
 
        /*
         * If we have an externally synchronized Linux clock, then update
index 954a198494efb4b0569c5636a415ac1c17da8373..e51d8fd9a15234ec4d3e5fabcafb22b24010f6ed 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
 #include <linux/bootmem.h>
+#include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -72,28 +73,68 @@ void (*board_nmi_handler_setup)(void);
 void (*board_ejtag_handler_setup)(void);
 void (*board_bind_eic_interrupt)(int irq, int regset);
 
-/*
- * These constant is for searching for possible module text segments.
- * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
- */
-#define MODULE_RANGE (8*1024*1024)
+
+static void show_raw_backtrace(unsigned long reg29)
+{
+       unsigned long *sp = (unsigned long *)reg29;
+       unsigned long addr;
+
+       printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+       printk("\n");
+#endif
+       while (!kstack_end(sp)) {
+               addr = *sp++;
+               if (__kernel_text_address(addr))
+                       print_ip_sym(addr);
+       }
+       printk("\n");
+}
+
+#ifdef CONFIG_KALLSYMS
+static int raw_show_trace;
+static int __init set_raw_show_trace(char *str)
+{
+       raw_show_trace = 1;
+       return 1;
+}
+__setup("raw_show_trace", set_raw_show_trace);
+
+extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+                                 unsigned long pc, unsigned long ra);
+
+static void show_backtrace(struct task_struct *task, struct pt_regs *regs)
+{
+       unsigned long sp = regs->regs[29];
+       unsigned long ra = regs->regs[31];
+       unsigned long pc = regs->cp0_epc;
+
+       if (raw_show_trace || !__kernel_text_address(pc)) {
+               show_raw_backtrace(sp);
+               return;
+       }
+       printk("Call Trace:\n");
+       do {
+               print_ip_sym(pc);
+               pc = unwind_stack(task, &sp, pc, ra);
+               ra = 0;
+       } while (pc);
+       printk("\n");
+}
+#else
+#define show_backtrace(task, r) show_raw_backtrace((r)->regs[29]);
+#endif
 
 /*
  * This routine abuses get_user()/put_user() to reference pointers
  * with at least a bit of error checking ...
  */
-void show_stack(struct task_struct *task, unsigned long *sp)
+static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
 {
        const int field = 2 * sizeof(unsigned long);
        long stackdata;
        int i;
-
-       if (!sp) {
-               if (task && task != current)
-                       sp = (unsigned long *) task->thread.reg29;
-               else
-                       sp = (unsigned long *) &sp;
-       }
+       unsigned long *sp = (unsigned long *)regs->regs[29];
 
        printk("Stack :");
        i = 0;
@@ -114,32 +155,48 @@ void show_stack(struct task_struct *task, unsigned long *sp)
                i++;
        }
        printk("\n");
+       show_backtrace(task, regs);
 }
 
-void show_trace(struct task_struct *task, unsigned long *stack)
+static __always_inline void prepare_frametrace(struct pt_regs *regs)
 {
-       const int field = 2 * sizeof(unsigned long);
-       unsigned long addr;
-
-       if (!stack) {
-               if (task && task != current)
-                       stack = (unsigned long *) task->thread.reg29;
-               else
-                       stack = (unsigned long *) &stack;
-       }
-
-       printk("Call Trace:");
-#ifdef CONFIG_KALLSYMS
-       printk("\n");
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noat\n\t"
+#ifdef CONFIG_64BIT
+               "1: dla $1, 1b\n\t"
+               "sd $1, %0\n\t"
+               "sd $29, %1\n\t"
+               "sd $31, %2\n\t"
+#else
+               "1: la $1, 1b\n\t"
+               "sw $1, %0\n\t"
+               "sw $29, %1\n\t"
+               "sw $31, %2\n\t"
 #endif
-       while (!kstack_end(stack)) {
-               addr = *stack++;
-               if (__kernel_text_address(addr)) {
-                       printk(" [<%0*lx>] ", field, addr);
-                       print_symbol("%s\n", addr);
+               ".set pop\n\t"
+               : "=m" (regs->cp0_epc),
+               "=m" (regs->regs[29]), "=m" (regs->regs[31])
+               : : "memory");
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+       struct pt_regs regs;
+       if (sp) {
+               regs.regs[29] = (unsigned long)sp;
+               regs.regs[31] = 0;
+               regs.cp0_epc = 0;
+       } else {
+               if (task && task != current) {
+                       regs.regs[29] = task->thread.reg29;
+                       regs.regs[31] = 0;
+                       regs.cp0_epc = task->thread.reg31;
+               } else {
+                       prepare_frametrace(&regs);
                }
        }
-       printk("\n");
+       show_stacktrace(task, &regs);
 }
 
 /*
@@ -147,9 +204,15 @@ void show_trace(struct task_struct *task, unsigned long *stack)
  */
 void dump_stack(void)
 {
-       unsigned long stack;
+       struct pt_regs regs;
 
-       show_trace(current, &stack);
+       /*
+        * Remove any garbage that may be in regs (specially func
+        * addresses) to avoid show_raw_backtrace() to report them
+        */
+       memset(&regs, 0, sizeof(regs));
+       prepare_frametrace(&regs);
+       show_backtrace(current, &regs);
 }
 
 EXPORT_SYMBOL(dump_stack);
@@ -268,8 +331,7 @@ void show_registers(struct pt_regs *regs)
        print_modules();
        printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
                current->comm, current->pid, current_thread_info(), current);
-       show_stack(current, (long *) regs->regs[29]);
-       show_trace(current, (long *) regs->regs[29]);
+       show_stacktrace(current, regs);
        show_code((unsigned int *) regs->cp0_epc);
        printk("\n");
 }
@@ -292,6 +354,16 @@ NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
        printk("%s[#%d]:\n", str, ++die_counter);
        show_registers(regs);
        spin_unlock_irq(&die_lock);
+
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+
+       if (panic_on_oops) {
+               printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+               ssleep(5);
+               panic("Fatal exception");
+       }
+
        do_exit(SIGSEGV);
 }
 
index 9ee0ec2cd067ccb31e787b9ba2fbe30b6b0df52b..51ddd216689850d5d0113dee662782ef82c3da8f 100644 (file)
@@ -768,10 +768,16 @@ int vpe_run(struct vpe * v)
         */
        write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
 
+       write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA));
+
+       back_to_back_c0_hazard();
+
         /* Set up the XTC bit in vpeconf0 to point at our tc */
         write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
                                | (t->index << VPECONF0_XTC_SHIFT));
 
+       back_to_back_c0_hazard();
+
         /* enable this VPE */
         write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
 
index fb25e0377f11b3097d9dc46b1151083dac590eee..a020a3cb4f4bc4767130546fc287f0c09f1cb049 100644 (file)
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2006  MIPS Technologies, Inc.
+ *     All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
  */
 #include <linux/compiler.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
-#include <asm/irq.h>
+#include <asm/gdb-stub.h>
 #include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/msc01_ic.h>
+
 #include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
-#include <asm/gdb-stub.h>
-
+#include <asm/mips-boards/generic.h>
 
 static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
@@ -47,13 +52,13 @@ static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
 void disable_atlas_irq(unsigned int irq_nr)
 {
-       atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+       atlas_hw0_icregs->intrsten = 1 << (irq_nr - ATLAS_INT_BASE);
        iob();
 }
 
 void enable_atlas_irq(unsigned int irq_nr)
 {
-       atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+       atlas_hw0_icregs->intseten = 1 << (irq_nr - ATLAS_INT_BASE);
        iob();
 }
 
@@ -107,7 +112,7 @@ static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
        if (unlikely(int_status == 0))
                return;
 
-       irq = ATLASINT_BASE + ls1bit32(int_status);
+       irq = ATLAS_INT_BASE + ls1bit32(int_status);
 
        DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
 
@@ -161,15 +166,14 @@ static inline unsigned int irq_ffs(unsigned int pending)
 }
 
 /*
- * IRQs on the Atlas board look basically (barring software IRQs which we
- * don't use at all and all external interrupt sources are combined together
- * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ * IRQs on the Atlas board look basically like (all external interrupt
+ * sources are combined together on hardware interrupt 0 (MIPS IRQ 2)):
  *
- *     MIPS IRQ        Source
+ *      MIPS IRQ        Source
  *      --------        ------
- *             0       Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
+ *             0        Software 0 (reschedule IPI on MT)
+ *             1        Software 1 (remote call IPI on MT)
+ *             2        Combined Atlas hardware interrupt (hw0)
  *             3        Hardware (ignored)
  *             4        Hardware (ignored)
  *             5        Hardware (ignored)
@@ -179,7 +183,7 @@ static inline unsigned int irq_ffs(unsigned int pending)
  * We handle the IRQ according to _our_ priority which is:
  *
  * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
+ * Lowest  ----     Software 0
  *
  * then we just return, if multiple IRQs are pending then we will just take
  * another exception, big deal.
@@ -193,17 +197,19 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 
        if (irq == MIPSCPU_INT_ATLAS)
                atlas_hw0_irqdispatch(regs);
-       else if (irq > 0)
+       else if (irq >= 0)
                do_IRQ(MIPSCPU_INT_BASE + irq, regs);
        else
                spurious_interrupt(regs);
 }
 
-void __init arch_init_irq(void)
+static inline void init_atlas_irqs (int base)
 {
        int i;
 
-       atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+       atlas_hw0_icregs = (struct atlas_ictrl_regs *)
+                          ioremap(ATLAS_ICTRL_REGS_BASE,
+                                  sizeof(struct atlas_ictrl_regs *));
 
        /*
         * Mask out all interrupt by writing "1" to all bit position in
@@ -211,7 +217,7 @@ void __init arch_init_irq(void)
         */
        atlas_hw0_icregs->intrsten = 0xffffffff;
 
-       for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
+       for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) {
                irq_desc[i].status      = IRQ_DISABLED;
                irq_desc[i].action      = 0;
                irq_desc[i].depth       = 1;
@@ -219,3 +225,62 @@ void __init arch_init_irq(void)
                spin_lock_init(&irq_desc[i].lock);
        }
 }
+
+static struct irqaction atlasirq = {
+       .handler = no_action,
+       .name = "Atlas cascade"
+};
+
+msc_irqmap_t __initdata msc_irqmap[] = {
+       {MSC01C_INT_TMR,                MSC01_IRQ_EDGE, 0},
+       {MSC01C_INT_PCI,                MSC01_IRQ_LEVEL, 0},
+};
+int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap);
+
+msc_irqmap_t __initdata msc_eicirqmap[] = {
+       {MSC01E_INT_SW0,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_SW1,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_ATLAS,              MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_TMR,                MSC01_IRQ_EDGE, 0},
+       {MSC01E_INT_PCI,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_PERFCTR,            MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_CPUCTR,             MSC01_IRQ_LEVEL, 0}
+};
+int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap);
+
+void __init arch_init_irq(void)
+{
+       init_atlas_irqs(ATLAS_INT_BASE);
+
+       if (!cpu_has_veic)
+               mips_cpu_irq_init(MIPSCPU_INT_BASE);
+
+       switch(mips_revision_corid) {
+       case MIPS_REVISION_CORID_CORE_MSC:
+       case MIPS_REVISION_CORID_CORE_FPGA2:
+       case MIPS_REVISION_CORID_CORE_FPGA3:
+       case MIPS_REVISION_CORID_CORE_24K:
+       case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+               if (cpu_has_veic)
+                       init_msc_irqs (MSC01E_INT_BASE,
+                                      msc_eicirqmap, msc_nr_eicirqs);
+               else
+                       init_msc_irqs (MSC01C_INT_BASE,
+                                      msc_irqmap, msc_nr_irqs);
+       }
+
+
+       if (cpu_has_veic) {
+               set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
+               setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
+       } else if (cpu_has_vint) {
+               set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch);
+#ifdef CONFIG_MIPS_MT_SMTC
+               setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS,
+                               &atlasirq, (0x100 << MIPSCPU_INT_ATLAS));
+#else /* Not SMTC */
+               setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+#endif /* CONFIG_MIPS_MT_SMTC */
+       } else
+               setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+}
index 9871a91fdb07a1da931be6d5d46ecdb83efe4354..0c6b0ce15028827c6e1e069bcf2ee497d23dfc3b 100644 (file)
@@ -77,7 +77,7 @@ static void __init serial_init(void)
 #else
        s.iobase = ATLAS_UART_REGS_BASE+3;
 #endif
-       s.irq = ATLASINT_UART;
+       s.irq = ATLAS_INT_UART;
        s.uartclk = ATLAS_BASE_BAUD * 16;
        s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
        s.iotype = UPIO_PORT;
index 557bf961f36a34ad1f4b8e9484565abefbcd37de..8d15861fce618248aeab570ccee13ef637bd769f 100644 (file)
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlasint.h>
+#endif
+#ifdef CONFIG_MIPS_MALTA
 #include <asm/mips-boards/maltaint.h>
-#include <asm/mc146818-time.h>
+#endif
 
 unsigned long cpu_khz;
 
@@ -92,10 +97,9 @@ extern int (*perf_irq)(struct pt_regs *regs);
 irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        int cpu = smp_processor_id();
-       int r2 = cpu_has_mips_r2;
 
 #ifdef CONFIG_MIPS_MT_SMTC
-        /*
+       /*
         *  In an SMTC system, one Count/Compare set exists per VPE.
         *  Which TC within a VPE gets the interrupt is essentially
         *  random - we only know that it shouldn't be one with
@@ -108,29 +112,46 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         *  the general MIPS timer_interrupt routine.
         */
 
+       int vpflags;
+
        /*
-        * DVPE is necessary so long as cross-VPE interrupts
-        * are done via read-modify-write of Cause register.
+        * We could be here due to timer interrupt,
+        * perf counter overflow, or both.
         */
-       int vpflags = dvpe();
-       write_c0_compare (read_c0_count() - 1);
-       clear_c0_cause(CPUCTR_IMASKBIT);
-       evpe(vpflags);
+       if (read_c0_cause() & (1 << 26))
+               perf_irq(regs);
 
-       if (cpu_data[cpu].vpe_id == 0) {
-               timer_interrupt(irq, dev_id, regs);
-               scroll_display_message();
-       } else
-               write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
-       smtc_timer_broadcast(cpu_data[cpu].vpe_id);
-
-       if (cpu != 0)
+       if (read_c0_cause() & (1 << 30)) {
+               /* If timer interrupt, make it de-assert */
+               write_c0_compare (read_c0_count() - 1);
                /*
-                * Other CPUs should do profiling and process accounting
+                * DVPE is necessary so long as cross-VPE interrupts
+                * are done via read-modify-write of Cause register.
                 */
-               local_timer_interrupt(irq, dev_id, regs);
-
+               vpflags = dvpe();
+               clear_c0_cause(CPUCTR_IMASKBIT);
+               evpe(vpflags);
+               /*
+                * There are things we only want to do once per tick
+                * in an "MP" system.   One TC of each VPE will take
+                * the actual timer interrupt.  The others will get
+                * timer broadcast IPIs. We use whoever it is that takes
+                * the tick on VPE 0 to run the full timer_interrupt().
+                */
+               if (cpu_data[cpu].vpe_id == 0) {
+                               timer_interrupt(irq, NULL, regs);
+                               smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+                               scroll_display_message();
+               } else {
+                       write_c0_compare(read_c0_count() +
+                                        (mips_hpt_frequency/HZ));
+                       local_timer_interrupt(irq, dev_id, regs);
+                       smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+               }
+       }
 #else /* CONFIG_MIPS_MT_SMTC */
+       int r2 = cpu_has_mips_r2;
+
        if (cpu == 0) {
                /*
                 * CPU 0 handles the global timer interrupt job and process
@@ -161,9 +182,8 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                 */
                local_timer_interrupt(irq, dev_id, regs);
        }
-#endif /* CONFIG_MIPS_MT_SMTC */
-
 out:
+#endif /* CONFIG_MIPS_MT_SMTC */
        return IRQ_HANDLED;
 }
 
index bb041a22f20a55dd35f9eb28ffb3e5073abff1e8..e1f35ef81145445c5530ccbdca83b4715a040c2d 100644 (file)
@@ -335,7 +335,7 @@ void __init r3k_cache_init(void)
        flush_cache_mm = r3k_flush_cache_mm;
        flush_cache_range = r3k_flush_cache_range;
        flush_cache_page = r3k_flush_cache_page;
-       flush_icache_page = r3k_flush_icache_page;
+       __flush_icache_page = r3k_flush_icache_page;
        flush_icache_range = r3k_flush_icache_range;
 
        flush_cache_sigtramp = r3k_flush_cache_sigtramp;
index 069803f58f3b2bb2c47676d49d574f15d45433cf..0b2da53750bd4220a30d1e97d7016d436a41ce6e 100644 (file)
@@ -89,7 +89,7 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
        blast_dcache32_page(addr);
 }
 
-static inline void r4k_blast_dcache_page_setup(void)
+static void __init r4k_blast_dcache_page_setup(void)
 {
        unsigned long  dc_lsize = cpu_dcache_line_size();
 
@@ -103,7 +103,7 @@ static inline void r4k_blast_dcache_page_setup(void)
 
 static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
 
-static inline void r4k_blast_dcache_page_indexed_setup(void)
+static void __init r4k_blast_dcache_page_indexed_setup(void)
 {
        unsigned long dc_lsize = cpu_dcache_line_size();
 
@@ -117,7 +117,7 @@ static inline void r4k_blast_dcache_page_indexed_setup(void)
 
 static void (* r4k_blast_dcache)(void);
 
-static inline void r4k_blast_dcache_setup(void)
+static void __init r4k_blast_dcache_setup(void)
 {
        unsigned long dc_lsize = cpu_dcache_line_size();
 
@@ -202,7 +202,7 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page)
 
 static void (* r4k_blast_icache_page)(unsigned long addr);
 
-static inline void r4k_blast_icache_page_setup(void)
+static void __init r4k_blast_icache_page_setup(void)
 {
        unsigned long ic_lsize = cpu_icache_line_size();
 
@@ -219,7 +219,7 @@ static inline void r4k_blast_icache_page_setup(void)
 
 static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
 
-static inline void r4k_blast_icache_page_indexed_setup(void)
+static void __init r4k_blast_icache_page_indexed_setup(void)
 {
        unsigned long ic_lsize = cpu_icache_line_size();
 
@@ -243,7 +243,7 @@ static inline void r4k_blast_icache_page_indexed_setup(void)
 
 static void (* r4k_blast_icache)(void);
 
-static inline void r4k_blast_icache_setup(void)
+static void __init r4k_blast_icache_setup(void)
 {
        unsigned long ic_lsize = cpu_icache_line_size();
 
@@ -264,7 +264,7 @@ static inline void r4k_blast_icache_setup(void)
 
 static void (* r4k_blast_scache_page)(unsigned long addr);
 
-static inline void r4k_blast_scache_page_setup(void)
+static void __init r4k_blast_scache_page_setup(void)
 {
        unsigned long sc_lsize = cpu_scache_line_size();
 
@@ -282,7 +282,7 @@ static inline void r4k_blast_scache_page_setup(void)
 
 static void (* r4k_blast_scache_page_indexed)(unsigned long addr);
 
-static inline void r4k_blast_scache_page_indexed_setup(void)
+static void __init r4k_blast_scache_page_indexed_setup(void)
 {
        unsigned long sc_lsize = cpu_scache_line_size();
 
@@ -300,7 +300,7 @@ static inline void r4k_blast_scache_page_indexed_setup(void)
 
 static void (* r4k_blast_scache)(void);
 
-static inline void r4k_blast_scache_setup(void)
+static void __init r4k_blast_scache_setup(void)
 {
        unsigned long sc_lsize = cpu_scache_line_size();
 
@@ -475,7 +475,7 @@ static inline void local_r4k_flush_cache_page(void *args)
                }
        }
        if (exec) {
-               if (cpu_has_vtag_icache) {
+               if (cpu_has_vtag_icache && mm == current->active_mm) {
                        int cpu = smp_processor_id();
 
                        if (cpu_context(cpu, mm) != 0)
@@ -599,7 +599,7 @@ static inline void local_r4k_flush_icache_page(void *args)
         * We're not sure of the virtual address(es) involved here, so
         * we have to flush the entire I-cache.
         */
-       if (cpu_has_vtag_icache) {
+       if (cpu_has_vtag_icache && vma->vm_mm == current->active_mm) {
                int cpu = smp_processor_id();
 
                if (cpu_context(cpu, vma->vm_mm) != 0)
@@ -1221,7 +1221,7 @@ void au1x00_fixup_config_od(void)
        }
 }
 
-static inline void coherency_setup(void)
+static void __init coherency_setup(void)
 {
        change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
 
@@ -1242,7 +1242,7 @@ static inline void coherency_setup(void)
                clear_c0_config(CONF_CU);
                break;
        /*
-        * We need to catch the ealry Alchemy SOCs with
+        * We need to catch the early Alchemy SOCs with
         * the write-only co_config.od bit and set it back to one...
         */
        case CPU_AU1000: /* rev. DA, HA, HB */
@@ -1291,7 +1291,7 @@ void __init r4k_cache_init(void)
        __flush_cache_all       = r4k___flush_cache_all;
        flush_cache_mm          = r4k_flush_cache_mm;
        flush_cache_page        = r4k_flush_cache_page;
-       flush_icache_page       = r4k_flush_icache_page;
+       __flush_icache_page     = r4k_flush_icache_page;
        flush_cache_range       = r4k_flush_cache_range;
 
        flush_cache_sigtramp    = r4k_flush_cache_sigtramp;
index 2d71efb82ac568be0771e52be3702cbc02a39c5d..16bad7c0a63f876ec0555c247607512bae82dc8a 100644 (file)
@@ -154,6 +154,26 @@ static inline void __sb1_flush_icache_all(void)
        }
 }
 
+/*
+ * Invalidate a range of the icache.  The addresses are virtual, and
+ * the cache is virtually indexed and tagged.  However, we don't
+ * necessarily have the right ASID context, so use index ops instead
+ * of hit ops.
+ */
+static inline void __sb1_flush_icache_range(unsigned long start,
+       unsigned long end)
+{
+       start &= ~(icache_line_size - 1);
+       end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
+
+       while (start != end) {
+               cache_set_op(Index_Invalidate_I, start & icache_index_mask);
+               start += icache_line_size;
+       }
+       mispredict();
+       sync();
+}
+
 /*
  * Flush the icache for a given physical page.  Need to writeback the
  * dcache first, then invalidate the icache.  If the page isn't
@@ -173,8 +193,11 @@ static void local_sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long
        /*
         * Bumping the ASID is probably cheaper than the flush ...
         */
-       if (cpu_context(cpu, vma->vm_mm) != 0)
-               drop_mmu_context(vma->vm_mm, cpu);
+       if (vma->vm_mm == current->active_mm) {
+               if (cpu_context(cpu, vma->vm_mm) != 0)
+                       drop_mmu_context(vma->vm_mm, cpu);
+       } else
+               __sb1_flush_icache_range(addr, addr + PAGE_SIZE);
 }
 
 #ifdef CONFIG_SMP
@@ -210,26 +233,6 @@ void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsign
        __attribute__((alias("local_sb1_flush_cache_page")));
 #endif
 
-/*
- * Invalidate a range of the icache.  The addresses are virtual, and
- * the cache is virtually indexed and tagged.  However, we don't
- * necessarily have the right ASID context, so use index ops instead
- * of hit ops.
- */
-static inline void __sb1_flush_icache_range(unsigned long start,
-       unsigned long end)
-{
-       start &= ~(icache_line_size - 1);
-       end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
-
-       while (start != end) {
-               cache_set_op(Index_Invalidate_I, start & icache_index_mask);
-               start += icache_line_size;
-       }
-       mispredict();
-       sync();
-}
-
 
 /*
  * Invalidate all caches on this CPU
@@ -326,9 +329,12 @@ static void local_sb1_flush_icache_page(struct vm_area_struct *vma,
         * If there's a context, bump the ASID (cheaper than a flush,
         * since we don't know VAs!)
         */
-       if (cpu_context(cpu, vma->vm_mm) != 0) {
-               drop_mmu_context(vma->vm_mm, cpu);
-       }
+       if (vma->vm_mm == current->active_mm) {
+               if (cpu_context(cpu, vma->vm_mm) != 0)
+                       drop_mmu_context(vma->vm_mm, cpu);
+       } else
+               __sb1_flush_icache_range(start, start + PAGE_SIZE);
+
 }
 
 #ifdef CONFIG_SMP
@@ -520,7 +526,7 @@ void sb1_cache_init(void)
 
        /* These routines are for Icache coherence with the Dcache */
        flush_icache_range = sb1_flush_icache_range;
-       flush_icache_page = sb1_flush_icache_page;
+       __flush_icache_page = sb1_flush_icache_page;
        flush_icache_all = __sb1_flush_icache_all; /* local only */
 
        /* This implies an Icache flush too, so can't be nop'ed */
index 5dfc9b1901f6537554bc7e34a1820b8cc8d5a6c0..932a09d7ef84810bdb4d43c591d63badbff3892c 100644 (file)
@@ -382,7 +382,7 @@ void __init tx39_cache_init(void)
                flush_cache_mm          = (void *) tx39h_flush_icache_all;
                flush_cache_range       = (void *) tx39h_flush_icache_all;
                flush_cache_page        = (void *) tx39h_flush_icache_all;
-               flush_icache_page       = (void *) tx39h_flush_icache_all;
+               __flush_icache_page     = (void *) tx39h_flush_icache_all;
                flush_icache_range      = (void *) tx39h_flush_icache_all;
 
                flush_cache_sigtramp    = (void *) tx39h_flush_icache_all;
@@ -408,7 +408,7 @@ void __init tx39_cache_init(void)
                flush_cache_mm = tx39_flush_cache_mm;
                flush_cache_range = tx39_flush_cache_range;
                flush_cache_page = tx39_flush_cache_page;
-               flush_icache_page = tx39_flush_icache_page;
+               __flush_icache_page = tx39_flush_icache_page;
                flush_icache_range = tx39_flush_icache_range;
 
                flush_cache_sigtramp = tx39_flush_cache_sigtramp;
index ddd3a2de1d73ea8513ace939f4c40d0fd81e2205..40c8b0235183859bfc087b72a509db11fdcd4490 100644 (file)
@@ -25,7 +25,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
        unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
-void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
+void (*__flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
@@ -70,6 +70,8 @@ void __flush_dcache_page(struct page *page)
        struct address_space *mapping = page_mapping(page);
        unsigned long addr;
 
+       if (PageHighMem(page))
+               return;
        if (mapping && !mapping_mapped(mapping)) {
                SetPageDcacheDirty(page);
                return;
@@ -91,16 +93,16 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
 {
        struct page *page;
        unsigned long pfn, addr;
+       int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
 
        pfn = pte_pfn(pte);
-       if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) &&
-           Page_dcache_dirty(page)) {
-               if (pages_do_alias((unsigned long)page_address(page),
-                                  address & PAGE_MASK)) {
-                       addr = (unsigned long) page_address(page);
+       if (unlikely(!pfn_valid(pfn)))
+               return;
+       page = pfn_to_page(pfn);
+       if (page_mapping(page) && Page_dcache_dirty(page)) {
+               addr = (unsigned long) page_address(page);
+               if (exec || pages_do_alias(addr, address & PAGE_MASK))
                        flush_data_cache_page(addr);
-               }
-
                ClearPageDcacheDirty(page);
        }
 }
index e3a617224868f04643719e68c9020d9941688efc..8423d859077949520de140f5b03d7cfdecda92e1 100644 (file)
@@ -89,7 +89,7 @@ good_area:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        } else {
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+               if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
                        goto bad_area;
        }
 
@@ -171,7 +171,7 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (tsk->pid == 1) {
+       if (is_init(tsk)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index 2cde1b77244304fdd530885c0f21e567e5fb2b56..2e0e21ef433ee1451ba4e7c125e4338b01bc64e0 100644 (file)
@@ -26,11 +26,6 @@ extern void build_tlb_refill_handler(void);
  */
 #define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
 
-/* CP0 hazard avoidance. */
-#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
-                                    "nop; nop; nop; nop; nop; nop;\n\t" \
-                                    ".set reorder\n\t")
-
 /* Atomicity and interruptability */
 #ifdef CONFIG_MIPS_MT_SMTC
 
@@ -126,7 +121,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                                start += (PAGE_SIZE << 1);
                                mtc0_tlbw_hazard();
                                tlb_probe();
-                               BARRIER;
+                               tlb_probe_hazard();
                                idx = read_c0_index();
                                write_c0_entrylo0(0);
                                write_c0_entrylo1(0);
@@ -168,7 +163,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
                        start += (PAGE_SIZE << 1);
                        mtc0_tlbw_hazard();
                        tlb_probe();
-                       BARRIER;
+                       tlb_probe_hazard();
                        idx = read_c0_index();
                        write_c0_entrylo0(0);
                        write_c0_entrylo1(0);
@@ -202,7 +197,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
                write_c0_entryhi(page | newpid);
                mtc0_tlbw_hazard();
                tlb_probe();
-               BARRIER;
+               tlb_probe_hazard();
                idx = read_c0_index();
                write_c0_entrylo0(0);
                write_c0_entrylo1(0);
@@ -235,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
        write_c0_entryhi(page);
        mtc0_tlbw_hazard();
        tlb_probe();
-       BARRIER;
+       tlb_probe_hazard();
        idx = read_c0_index();
        write_c0_entrylo0(0);
        write_c0_entrylo1(0);
@@ -279,7 +274,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        pgdp = pgd_offset(vma->vm_mm, address);
        mtc0_tlbw_hazard();
        tlb_probe();
-       BARRIER;
+       tlb_probe_hazard();
        pudp = pud_offset(pgdp, address);
        pmdp = pmd_offset(pudp, address);
        idx = read_c0_index();
@@ -320,7 +315,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
        pgdp = pgd_offset(vma->vm_mm, address);
        mtc0_tlbw_hazard();
        tlb_probe();
-       BARRIER;
+       tlb_probe_hazard();
        pmdp = pmd_offset(pgdp, address);
        idx = read_c0_index();
        ptep = pte_offset_map(pmdp, address);
@@ -351,7 +346,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        wired = read_c0_wired();
        write_c0_wired(wired + 1);
        write_c0_index(wired);
-       BARRIER;
+       tlbw_use_hazard();      /* What is the hazard here? */
        write_c0_pagemask(pagemask);
        write_c0_entryhi(entryhi);
        write_c0_entrylo0(entrylo0);
@@ -361,7 +356,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        tlbw_use_hazard();
 
        write_c0_entryhi(old_ctx);
-       BARRIER;
+       tlbw_use_hazard();      /* What is the hazard here? */
        write_c0_pagemask(old_pagemask);
        local_flush_tlb_all();
        EXIT_CRITICAL(flags);
index 9fb2493fff02494c0bb8789d4e273f5ac786c4c4..6cd87cf0195a1ca8ce2dea022502527054ff1aec 100644 (file)
@@ -133,7 +133,7 @@ static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs)
                MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
 
                /* handle the timer call */
-               do_timer(regs);
+               do_timer(1);
 #ifndef CONFIG_SMP
                update_process_times(user_mode(regs));
 #endif
index 35d5927706eac8701f6442fe75620fb381445599..edefa97b233098327e0b6aefbe961403491d9501 100644 (file)
@@ -11,7 +11,6 @@ obj-$(CONFIG_ITE_BOARD_GEN)   += ops-it8172.o
 obj-$(CONFIG_MIPS_BONITO64)    += ops-bonito64.o
 obj-$(CONFIG_MIPS_GT64111)     += ops-gt64111.o
 obj-$(CONFIG_MIPS_GT64120)     += ops-gt64120.o
-obj-$(CONFIG_MIPS_GT96100)     += ops-gt96100.o
 obj-$(CONFIG_PCI_MARVELL)      += ops-marvell.o
 obj-$(CONFIG_MIPS_MSC)         += ops-msc.o
 obj-$(CONFIG_MIPS_NILE4)       += ops-nile4.o
@@ -28,8 +27,7 @@ obj-$(CONFIG_DDB5477)         += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
 obj-$(CONFIG_LASAT)            += pci-lasat.o
 obj-$(CONFIG_MIPS_ATLAS)       += fixup-atlas.o
 obj-$(CONFIG_MIPS_COBALT)      += fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV96100)     += fixup-ev64120.o
-obj-$(CONFIG_MIPS_EV96100)     += fixup-ev96100.o pci-ev96100.o
+obj-$(CONFIG_MIPS_EV64120)     += fixup-ev64120.o
 obj-$(CONFIG_MIPS_ITE8172)     += fixup-ite8172g.o
 obj-$(CONFIG_MIPS_IVR)         += fixup-ivr.o
 obj-$(CONFIG_SOC_AU1500)       += fixup-au1000.o ops-au1000.o
index 439510af30372152656f3242a6599aa603ba3679..c6cd6e9cdfbc8d4b29dc804f173e8cfbc8de596a 100644 (file)
 
 #include <asm/mips-boards/atlasint.h>
 
-#define PCIA           ATLASINT_PCIA
-#define PCIB           ATLASINT_PCIB
-#define PCIC           ATLASINT_PCIC
-#define PCID           ATLASINT_PCID
-#define INTA           ATLASINT_INTA
-#define INTB           ATLASINT_INTB
-#define ETH            ATLASINT_ETH
-#define INTC           ATLASINT_INTC
-#define SCSI           ATLASINT_SCSI
-#define INTD           ATLASINT_INTD
+#define PCIA           ATLAS_INT_PCIA
+#define PCIB           ATLAS_INT_PCIB
+#define PCIC           ATLAS_INT_PCIC
+#define PCID           ATLAS_INT_PCID
+#define INTA           ATLAS_INT_INTA
+#define INTB           ATLAS_INT_INTB
+#define ETH            ATLAS_INT_ETH
+#define INTC           ATLAS_INT_INTC
+#define SCSI           ATLAS_INT_SCSI
+#define INTD           ATLAS_INT_INTD
 
 static char irq_tab[][5] __initdata = {
        /*      INTA    INTB    INTC    INTD */
diff --git a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c
deleted file mode 100644 (file)
index e2bc977..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     EV96100 Board specific pci fixups.
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-static char irq_tab_ev96100[][5] __initdata = {
- [8] = { 0, 5, 5, 5, 5 },
- [9] = { 0, 2, 2, 2, 2 }
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       return irq_tab_ev96100[slot][pin];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       return 0;
-}
index 0c0c1e6519f9e4a35cb6a98b04b669ad4384c82a..8ae46481fcb720d98b608b5adea07458396ae59d 100644 (file)
@@ -110,7 +110,7 @@ static int config_access(unsigned char access_type, struct pci_bus *bus,
        if (first_cfg) {
                /* reserve a wired entry for pci config accesses */
                first_cfg = 0;
-               pci_cfg_vm = get_vm_area(0x2000, 0);
+               pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
                if (!pci_cfg_vm)
                        panic (KERN_ERR "PCI unable to get vm area\n");
                pci_cfg_wired_entry = read_c0_wired();
diff --git a/arch/mips/pci/ops-gt96100.c b/arch/mips/pci/ops-gt96100.c
deleted file mode 100644 (file)
index 9e4ea66..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 board specific pci support.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/pci.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/delay.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-static int static gt96100_config_access(unsigned char access_type,
-       struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
-{
-       unsigned char bus = bus->number;
-       u32 intr;
-
-       /*
-        * Because of a bug in the galileo (for slot 31).
-        */
-       if (bus == 0 && devfn >= PCI_DEVFN(31, 0))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* Clear cause register bits */
-       GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-                                    GT_INTRCAUSE_TARABORT0_BIT));
-
-       /* Setup address */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-       udelay(2);
-
-
-       if (access_type == PCI_ACCESS_WRITE) {
-               if (devfn != 0)
-                       *data = le32_to_cpu(*data);
-               GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
-       } else {
-               *data = GT_READ(GT_PCI0_CFGDATA_OFS);
-               if (devfn != 0)
-                       *data = le32_to_cpu(*data);
-       }
-
-       udelay(2);
-
-       /* Check for master or target abort */
-       intr = GT_READ(GT_INTRCAUSE_OFS);
-
-       if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
-               /* Error occured */
-
-               /* Clear bits */
-               GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-                                            GT_INTRCAUSE_TARABORT0_BIT));
-               return -1;
-       }
-       return 0;
-}
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-       int where, int size, u32 * val)
-{
-       u32 data = 0;
-
-       if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       switch (size) {
-       case 1:
-               *val = (data >> ((where & 3) << 3)) & 0xff;
-               break;
-
-       case 2:
-               *val = (data >> ((where & 3) << 3)) & 0xffff;
-               break;
-
-       case 4:
-               *val = data;
-               break;
-       }
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-       int where, int size, u32 val)
-{
-       u32 data = 0;
-
-       switch (size) {
-       case 1:
-               if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-                       return -1;
-
-               data = (data & ~(0xff << ((where & 3) << 3))) |
-                      (val << ((where & 3) << 3));
-
-               if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
-                       return -1;
-
-               return PCIBIOS_SUCCESSFUL;
-
-       case 2:
-               if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-                       return -1;
-
-               data = (data & ~(0xffff << ((where & 3) << 3))) |
-                      (val << ((where & 3) << 3));
-
-               if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
-                       return -1;
-
-
-               return PCIBIOS_SUCCESSFUL;
-
-       case 4:
-               if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val))
-                       return -1;
-
-               return PCIBIOS_SUCCESSFUL;
-       }
-}
-
-struct pci_ops gt96100_pci_ops = {
-       .read   = gt96100_pcibios_read,
-       .write  = gt96100_pcibios_write
-};
diff --git a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c
deleted file mode 100644 (file)
index f9457ea..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-static struct resource pci_io_resource = {
-       .name   = "io pci IO space",
-       .start  = 0x10000000,
-       .end    = 0x11ffffff,
-       .flags  = IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-       .name   = "ext pci memory space",
-       .start  = 0x12000000,
-       .end    = 0x13ffffff,
-       .flags  = IORESOURCE_MEM
-};
-
-extern struct pci_ops gt96100_pci_ops;
-
-struct pci_controller ev96100_controller = {
-       .pci_ops        = &gt96100_pci_ops,
-       .io_resource    = &pci_io_resource,
-       .mem_resource   = &pci_mem_resource,
-};
-
-static void ev96100_pci_init(void)
-{
-       register_pci_controller(&ev96100_controller);
-}
-
-arch_initcall(ev96100_pci_init);
index 80eb9af9ecdffb3c7ec0ab883903a6ac082f05aa..405ce0152739eee2547090c60bf6f35f7ee6ad71 100644 (file)
@@ -16,8 +16,6 @@
 #include <asm/sn/intr.h>
 #include <asm/sn/sn0/hub.h>
 
-extern unsigned int allocate_irqno(void);
-
 /*
  * Max #PCI busses we can handle; ie, max #PCI bridges.
  */
index b029ba79c27af0f685079ba562c3d980122cc884..257ce118e380fd2dd7d4e104c4eb02c87a4ec20f 100644 (file)
@@ -42,8 +42,6 @@
 static unsigned long ct_cur[NR_CPUS];  /* What counter should be at next timer irq */
 static long last_rtc_update;           /* Last time the rtc clock got updated */
 
-extern volatile unsigned long wall_jiffies;
-
 #if 0
 static int set_rtc_mmss(unsigned long nowtime)
 {
@@ -111,7 +109,7 @@ again:
        kstat_this_cpu.irqs[irq]++;             /* kstat only for bootcpu? */
 
        if (cpu == 0)
-               do_timer(regs);
+               do_timer(1);
 
        update_process_times(user_mode(regs));
 
index ed325f0ab28a48be80b366feaa0317c3b0b4f496..a0222fa4416cb62537302e01c4b5ed6a3436d491 100644 (file)
@@ -469,21 +469,6 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
 
 #endif         /* CONFIG_KGDB */
 
-static inline int dclz(unsigned long long x)
-{
-       int lz;
-
-       __asm__ (
-       "       .set    push                                            \n"
-       "       .set    mips64                                          \n"
-       "       dclz    %0, %1                                          \n"
-       "       .set    pop                                             \n"
-       : "=r" (lz)
-       : "r" (x));
-
-       return lz;
-}
-
 extern void bcm1480_timer_interrupt(struct pt_regs *regs);
 extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
 extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
@@ -536,9 +521,9 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 
                if (mask_h) {
                        if (mask_h ^ 1)
-                               do_IRQ(63 - dclz(mask_h), regs);
+                               do_IRQ(fls64(mask_h) - 1, regs);
                        else
-                               do_IRQ(127 - dclz(mask_l), regs);
+                               do_IRQ(63 + fls64(mask_l), regs);
                }
        }
 }
index 1de71adec6c665bebb1e47970bed5ae40ad85a93..a451b4c7732d9baae2127529c74f974cf2154278 100644 (file)
@@ -419,21 +419,6 @@ static void sb1250_kgdb_interrupt(struct pt_regs *regs)
 
 #endif         /* CONFIG_KGDB */
 
-static inline int dclz(unsigned long long x)
-{
-       int lz;
-
-       __asm__ (
-       "       .set    push                                            \n"
-       "       .set    mips64                                          \n"
-       "       dclz    %0, %1                                          \n"
-       "       .set    pop                                             \n"
-       : "=r" (lz)
-       : "r" (x));
-
-       return lz;
-}
-
 extern void sb1250_timer_interrupt(struct pt_regs *regs);
 extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
 extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
@@ -490,6 +475,6 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
                mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
                                              R_IMR_INTERRUPT_STATUS_BASE)));
                if (mask)
-                       do_IRQ(63 - dclz(mask), regs);
+                       do_IRQ(fls64(mask) - 1, regs);
        }
 }
index 4398d2a95789b247c2676ae4f798631e45f77af0..c2531ae032cf74895e4d6ef518607b856ba810c3 100644 (file)
@@ -1049,7 +1049,7 @@ void pdc_iodc_putc(unsigned char c)
         static int __attribute__((aligned(8)))   iodc_retbuf[32];
         static char __attribute__((aligned(64))) iodc_dbuf[4096];
         unsigned int n;
-       unsigned int flags;
+       unsigned long flags;
 
         switch (c) {
         case '\n':
@@ -1088,7 +1088,8 @@ void pdc_iodc_putc(unsigned char c)
  */
 void pdc_iodc_outc(unsigned char c)
 {
-       unsigned int n, flags;
+       unsigned int n;
+       unsigned long flags;
 
        /* fill buffer with one caracter and print it */
         static int __attribute__((aligned(8)))   iodc_retbuf[32];
@@ -1113,7 +1114,7 @@ void pdc_iodc_outc(unsigned char c)
  */
 int pdc_iodc_getc(void)
 {
-       unsigned int flags;
+       unsigned long flags;
         static int __attribute__((aligned(8)))   iodc_retbuf[32];
         static char __attribute__((aligned(64))) iodc_dbuf[4096];
        int ch;
index aee311884f3fa114c2a4fa5f5f4b0dc4fbe2d5f3..f50b982b0834ce8b2598d1b66d1c06b5306ca29f 100644 (file)
@@ -27,7 +27,7 @@
  *    - SEGREL32 handling
  *      We are not doing SEGREL32 handling correctly. According to the ABI, we
  *      should do a value offset, like this:
- *                     if (is_init(me, (void *)val))
+ *                     if (in_init(me, (void *)val))
  *                             val -= (uint32_t)me->module_init;
  *                     else
  *                             val -= (uint32_t)me->module_core;
 
 /* three functions to determine where in the module core
  * or init pieces the location is */
-static inline int is_init(struct module *me, void *loc)
+static inline int in_init(struct module *me, void *loc)
 {
        return (loc >= me->module_init &&
                loc <= (me->module_init + me->init_size));
 }
 
-static inline int is_core(struct module *me, void *loc)
+static inline int in_core(struct module *me, void *loc)
 {
        return (loc >= me->module_core &&
                loc <= (me->module_core + me->core_size));
 }
 
-static inline int is_local(struct module *me, void *loc)
+static inline int in_local(struct module *me, void *loc)
 {
-       return is_init(me, loc) || is_core(me, loc);
+       return in_init(me, loc) || in_core(me, loc);
 }
 
-static inline int is_local_section(struct module *me, void *loc, void *dot)
+static inline int in_local_section(struct module *me, void *loc, void *dot)
 {
-       return (is_init(me, loc) && is_init(me, dot)) ||
-               (is_core(me, loc) && is_core(me, dot));
+       return (in_init(me, loc) && in_init(me, dot)) ||
+               (in_core(me, loc) && in_core(me, dot));
 }
 
 
@@ -566,14 +566,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                        break;
                case R_PARISC_PCREL17F:
                        /* 17-bit PC relative address */
-                       val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
+                       val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
                        val = (val - dot - 8)/4;
                        CHECK_RELOC(val, 17)
                        *loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
                        break;
                case R_PARISC_PCREL22F:
                        /* 22-bit PC relative address; only defined for pa20 */
-                       val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
+                       val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
                        DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 
                               strtab + sym->st_name, (unsigned long)loc, addend, 
                               val)
@@ -670,9 +670,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                               strtab + sym->st_name,
                               loc, val);
                        /* can we reach it locally? */
-                       if(!is_local_section(me, (void *)val, (void *)dot)) {
+                       if(!in_local_section(me, (void *)val, (void *)dot)) {
 
-                               if (is_local(me, (void *)val))
+                               if (in_local(me, (void *)val))
                                        /* this is the case where the
                                         * symbol is local to the
                                         * module, but in a different
@@ -680,14 +680,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                                         * in case it's more than 22
                                         * bits away */
                                        val = get_stub(me, val, addend, ELF_STUB_DIRECT,
-                                                      is_init(me, loc));
+                                                      in_init(me, loc));
                                else if (strncmp(strtab + sym->st_name, "$$", 2)
                                    == 0)
                                        val = get_stub(me, val, addend, ELF_STUB_MILLI,
-                                                      is_init(me, loc));
+                                                      in_init(me, loc));
                                else
                                        val = get_stub(me, val, addend, ELF_STUB_GOT,
-                                                      is_init(me, loc));
+                                                      in_init(me, loc));
                        }
                        DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 
                               strtab + sym->st_name, loc, sym->st_value,
@@ -720,7 +720,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                        break;
                case R_PARISC_FPTR64:
                        /* 64-bit function address */
-                       if(is_local(me, (void *)(val + addend))) {
+                       if(in_local(me, (void *)(val + addend))) {
                                *loc64 = get_fdesc(me, val+addend);
                                DEBUGP("FDESC for %s at %p points to %lx\n",
                                       strtab + sym->st_name, *loc64,
index 5facc9bff4ef68b584aa32fb263b99461e90eb77..ab641d67f5516fc6fb494799edce9db1f13f08d0 100644 (file)
@@ -32,9 +32,6 @@
 
 #include <linux/timex.h>
 
-/* xtime and wall_jiffies keep wall-clock time */
-extern unsigned long wall_jiffies;
-
 static long clocktick __read_mostly;   /* timer cycles per tick */
 static long halftick __read_mostly;
 
@@ -79,7 +76,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #endif
                if (cpu == 0) {
                        write_seqlock(&xtime_lock);
-                       do_timer(regs);
+                       do_timer(1);
                        write_sequnlock(&xtime_lock);
                }
        }
@@ -112,7 +109,7 @@ EXPORT_SYMBOL(profile_pc);
 /*** converted from ia64 ***/
 /*
  * Return the number of micro-seconds that elapsed since the last
- * update to wall time (aka xtime aka wall_jiffies).  The xtime_lock
+ * update to wall time (aka xtime).  The xtime_lock
  * must be at least read-locked when calling this routine.
  */
 static inline unsigned long
index de1ef2fa1a206f2ba7031c66a304f534852371fb..a0dd1b0ee4838fc1b6f6b870354d67886c171fbe 100644 (file)
@@ -731,11 +731,10 @@ config ARCH_SPARSEMEM_DEFAULT
        def_bool y
        depends on SMP && PPC_PSERIES
 
-source "mm/Kconfig"
-
-config HAVE_ARCH_EARLY_PFN_TO_NID
+config ARCH_POPULATES_NODE_MAP
        def_bool y
-       depends on NEED_MULTIPLE_NODES
+
+source "mm/Kconfig"
 
 config ARCH_MEMORY_PROBE
        def_bool y
index e0df2ba1ab9f936f397aa547e44e3a3af2a02cc5..79a17795d17bd5bfba19c61da9bf2a61bddef2d1 100644 (file)
@@ -67,10 +67,6 @@ int have_of = 1;
 dev_t boot_dev;
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 
-#ifdef CONFIG_MAGIC_SYSRQ
-unsigned long SYSRQ_KEY = 0x54;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
 #ifdef CONFIG_VGA_CONSOLE
 unsigned long vgacon_remap_base;
 #endif
index 00d6b8addd78896ebe5d2578549f9d445446a459..962ad5ebc7678aad6df97f8640f6fb95a3261ac2 100644 (file)
@@ -93,11 +93,6 @@ int dcache_bsize;
 int icache_bsize;
 int ucache_bsize;
 
-#ifdef CONFIG_MAGIC_SYSRQ
-unsigned long SYSRQ_KEY;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
-
 #ifdef CONFIG_SMP
 
 static int smt_enabled_cmdline;
index 2e292863e982acac45b743248300d2820d73cbb7..5e391fc253407fcfa8b712363d74d46bb99ee7c5 100644 (file)
@@ -740,7 +740,7 @@ asmlinkage long compat_sys_umask(u32 mask)
        return sys_umask((int)mask);
 }
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 struct __sysctl_args32 {
        u32 name;
        int nlen;
index 7a3c3f791ade2aaac30bbadc0994da40ea12e80a..8b278d85ca4ed24b44f8b93f33257f79f6d3294c 100644 (file)
@@ -117,8 +117,6 @@ unsigned tb_to_ns_shift;
 
 struct gettimeofday_struct do_gtod;
 
-extern unsigned long wall_jiffies;
-
 extern struct timezone sys_tz;
 static long timezone_offset;
 
@@ -693,7 +691,7 @@ void timer_interrupt(struct pt_regs * regs)
                tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
                if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
                        tb_last_jiffy = tb_next_jiffy;
-                       do_timer(regs);
+                       do_timer(1);
                        timer_recalc_offset(tb_last_jiffy);
                        timer_check_rtc();
                }
@@ -816,11 +814,6 @@ int do_settimeofday(struct timespec *tv)
        /*
         * Subtract off the number of nanoseconds since the
         * beginning of the last tick.
-        * Note that since we don't increment jiffies_64 anywhere other
-        * than in do_timer (since we don't have a lost tick problem),
-        * wall_jiffies will always be the same as jiffies,
-        * and therefore the (jiffies - wall_jiffies) computation
-        * has been removed.
         */
        tb_delta = tb_ticks_since(tb_last_jiffy);
        tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
index 78a0d59903ee69d2b8ac96de20e18c17fd5f9206..e8fa50624b70dae41c27ce669e10f472b18970a8 100644 (file)
@@ -333,7 +333,7 @@ good_area:
                /* protection fault */
                if (error_code & 0x08000000)
                        goto bad_area;
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                        goto bad_area;
        }
 
@@ -386,7 +386,7 @@ bad_area_nosemaphore:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index eebd8b83a6b05243f3633bbe4578b2a0e6db0355..16fe027bbc12ffb873222dbbdc170d474028ca91 100644 (file)
@@ -256,20 +256,22 @@ void __init do_init_bootmem(void)
 
        boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
 
+       /* Add active regions with valid PFNs */
+       for (i = 0; i < lmb.memory.cnt; i++) {
+               unsigned long start_pfn, end_pfn;
+               start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+               end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+               add_active_range(0, start_pfn, end_pfn);
+       }
+
        /* Add all physical memory to the bootmem map, mark each area
         * present.
         */
-       for (i = 0; i < lmb.memory.cnt; i++) {
-               unsigned long base = lmb.memory.region[i].base;
-               unsigned long size = lmb_size_bytes(&lmb.memory, i);
 #ifdef CONFIG_HIGHMEM
-               if (base >= total_lowmem)
-                       continue;
-               if (base + size > total_lowmem)
-                       size = total_lowmem - base;
+       free_bootmem_with_active_regions(0, total_lowmem >> PAGE_SHIFT);
+#else
+       free_bootmem_with_active_regions(0, max_pfn);
 #endif
-               free_bootmem(base, size);
-       }
 
        /* reserve the sections we're already using */
        for (i = 0; i < lmb.reserved.cnt; i++)
@@ -277,9 +279,8 @@ void __init do_init_bootmem(void)
                                lmb_size_bytes(&lmb.reserved, i));
 
        /* XXX need to clip this if using highmem? */
-       for (i = 0; i < lmb.memory.cnt; i++)
-               memory_present(0, lmb_start_pfn(&lmb.memory, i),
-                              lmb_end_pfn(&lmb.memory, i));
+       sparse_memory_present_with_active_regions(0);
+
        init_bootmem_done = 1;
 }
 
@@ -288,10 +289,9 @@ void __init do_init_bootmem(void)
  */
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long zholes_size[MAX_NR_ZONES];
        unsigned long total_ram = lmb_phys_mem_size();
        unsigned long top_of_ram = lmb_end_of_DRAM();
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
 #ifdef CONFIG_HIGHMEM
        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
@@ -307,26 +307,13 @@ void __init paging_init(void)
               top_of_ram, total_ram);
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
               (top_of_ram - total_ram) >> 20);
-       /*
-        * All pages are DMA-able so we put them all in the DMA zone.
-        */
-       memset(zones_size, 0, sizeof(zones_size));
-       memset(zholes_size, 0, sizeof(zholes_size));
-
-       zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
-       zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
-
 #ifdef CONFIG_HIGHMEM
-       zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
-       zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
-       zholes_size[ZONE_HIGHMEM] = (top_of_ram - total_ram) >> PAGE_SHIFT;
+       max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
+       max_zone_pfns[1] = top_of_ram >> PAGE_SHIFT;
 #else
-       zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
-       zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
-#endif /* CONFIG_HIGHMEM */
-
-       free_area_init_node(0, NODE_DATA(0), zones_size,
-                           __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
+       max_zone_pfns[0] = top_of_ram >> PAGE_SHIFT;
+#endif
+       free_area_init_nodes(max_zone_pfns);
 }
 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 
index 6c0f1c7d83e502bf86bb14b567c91d09125a6a3e..43c272075e1ae8408baa35c8e78a2d831e24312c 100644 (file)
@@ -39,96 +39,6 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
 static int min_common_depth;
 static int n_mem_addr_cells, n_mem_size_cells;
 
-/*
- * We need somewhere to store start/end/node for each region until we have
- * allocated the real node_data structures.
- */
-#define MAX_REGIONS    (MAX_LMB_REGIONS*2)
-static struct {
-       unsigned long start_pfn;
-       unsigned long end_pfn;
-       int nid;
-} init_node_data[MAX_REGIONS] __initdata;
-
-int __init early_pfn_to_nid(unsigned long pfn)
-{
-       unsigned int i;
-
-       for (i = 0; init_node_data[i].end_pfn; i++) {
-               unsigned long start_pfn = init_node_data[i].start_pfn;
-               unsigned long end_pfn = init_node_data[i].end_pfn;
-
-               if ((start_pfn <= pfn) && (pfn < end_pfn))
-                       return init_node_data[i].nid;
-       }
-
-       return -1;
-}
-
-void __init add_region(unsigned int nid, unsigned long start_pfn,
-                      unsigned long pages)
-{
-       unsigned int i;
-
-       dbg("add_region nid %d start_pfn 0x%lx pages 0x%lx\n",
-               nid, start_pfn, pages);
-
-       for (i = 0; init_node_data[i].end_pfn; i++) {
-               if (init_node_data[i].nid != nid)
-                       continue;
-               if (init_node_data[i].end_pfn == start_pfn) {
-                       init_node_data[i].end_pfn += pages;
-                       return;
-               }
-               if (init_node_data[i].start_pfn == (start_pfn + pages)) {
-                       init_node_data[i].start_pfn -= pages;
-                       return;
-               }
-       }
-
-       /*
-        * Leave last entry NULL so we dont iterate off the end (we use
-        * entry.end_pfn to terminate the walk).
-        */
-       if (i >= (MAX_REGIONS - 1)) {
-               printk(KERN_ERR "WARNING: too many memory regions in "
-                               "numa code, truncating\n");
-               return;
-       }
-
-       init_node_data[i].start_pfn = start_pfn;
-       init_node_data[i].end_pfn = start_pfn + pages;
-       init_node_data[i].nid = nid;
-}
-
-/* We assume init_node_data has no overlapping regions */
-void __init get_region(unsigned int nid, unsigned long *start_pfn,
-                      unsigned long *end_pfn, unsigned long *pages_present)
-{
-       unsigned int i;
-
-       *start_pfn = -1UL;
-       *end_pfn = *pages_present = 0;
-
-       for (i = 0; init_node_data[i].end_pfn; i++) {
-               if (init_node_data[i].nid != nid)
-                       continue;
-
-               *pages_present += init_node_data[i].end_pfn -
-                       init_node_data[i].start_pfn;
-
-               if (init_node_data[i].start_pfn < *start_pfn)
-                       *start_pfn = init_node_data[i].start_pfn;
-
-               if (init_node_data[i].end_pfn > *end_pfn)
-                       *end_pfn = init_node_data[i].end_pfn;
-       }
-
-       /* We didnt find a matching region, return start/end as 0 */
-       if (*start_pfn == -1UL)
-               *start_pfn = 0;
-}
-
 static void __cpuinit map_cpu_to_node(int cpu, int node)
 {
        numa_cpu_lookup_table[cpu] = node;
@@ -468,8 +378,8 @@ new_range:
                                continue;
                }
 
-               add_region(nid, start >> PAGE_SHIFT,
-                          size >> PAGE_SHIFT);
+               add_active_range(nid, start >> PAGE_SHIFT,
+                               (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
 
                if (--ranges)
                        goto new_range;
@@ -482,6 +392,7 @@ static void __init setup_nonnuma(void)
 {
        unsigned long top_of_ram = lmb_end_of_DRAM();
        unsigned long total_ram = lmb_phys_mem_size();
+       unsigned long start_pfn, end_pfn;
        unsigned int i;
 
        printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
@@ -489,9 +400,11 @@ static void __init setup_nonnuma(void)
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
               (top_of_ram - total_ram) >> 20);
 
-       for (i = 0; i < lmb.memory.cnt; ++i)
-               add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT,
-                          lmb_size_pages(&lmb.memory, i));
+       for (i = 0; i < lmb.memory.cnt; ++i) {
+               start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+               end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+               add_active_range(0, start_pfn, end_pfn);
+       }
        node_set_online(0);
 }
 
@@ -630,11 +543,11 @@ void __init do_init_bootmem(void)
                          (void *)(unsigned long)boot_cpuid);
 
        for_each_online_node(nid) {
-               unsigned long start_pfn, end_pfn, pages_present;
+               unsigned long start_pfn, end_pfn;
                unsigned long bootmem_paddr;
                unsigned long bootmap_pages;
 
-               get_region(nid, &start_pfn, &end_pfn, &pages_present);
+               get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
 
                /* Allocate the node structure node local if possible */
                NODE_DATA(nid) = careful_allocation(nid,
@@ -667,19 +580,7 @@ void __init do_init_bootmem(void)
                init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
                                  start_pfn, end_pfn);
 
-               /* Add free regions on this node */
-               for (i = 0; init_node_data[i].end_pfn; i++) {
-                       unsigned long start, end;
-
-                       if (init_node_data[i].nid != nid)
-                               continue;
-
-                       start = init_node_data[i].start_pfn << PAGE_SHIFT;
-                       end = init_node_data[i].end_pfn << PAGE_SHIFT;
-
-                       dbg("free_bootmem %lx %lx\n", start, end - start);
-                       free_bootmem_node(NODE_DATA(nid), start, end - start);
-               }
+               free_bootmem_with_active_regions(nid, end_pfn);
 
                /* Mark reserved regions on this node */
                for (i = 0; i < lmb.reserved.cnt; i++) {
@@ -710,44 +611,16 @@ void __init do_init_bootmem(void)
                        }
                }
 
-               /* Add regions into sparsemem */
-               for (i = 0; init_node_data[i].end_pfn; i++) {
-                       unsigned long start, end;
-
-                       if (init_node_data[i].nid != nid)
-                               continue;
-
-                       start = init_node_data[i].start_pfn;
-                       end = init_node_data[i].end_pfn;
-
-                       memory_present(nid, start, end);
-               }
+               sparse_memory_present_with_active_regions(nid);
        }
 }
 
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long zholes_size[MAX_NR_ZONES];
-       int nid;
-
-       memset(zones_size, 0, sizeof(zones_size));
-       memset(zholes_size, 0, sizeof(zholes_size));
-
-       for_each_online_node(nid) {
-               unsigned long start_pfn, end_pfn, pages_present;
-
-               get_region(nid, &start_pfn, &end_pfn, &pages_present);
-
-               zones_size[ZONE_DMA] = end_pfn - start_pfn;
-               zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - pages_present;
-
-               dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
-                   zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
-
-               free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn,
-                                   zholes_size);
-       }
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+                               lmb_end_of_DRAM() >> PAGE_SHIFT
+       };
+       free_area_init_nodes(max_zone_pfns);
 }
 
 static int __init early_numa(char *p)
index 7b4572805db9973388267c3ae9d1cea61fea0ed7..3950ddccb2c8531d451c8a188b86ae95371ec797 100644 (file)
@@ -82,7 +82,6 @@ spufs_new_inode(struct super_block *sb, int mode)
        inode->i_mode = mode;
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 out:
@@ -120,7 +119,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry,
        ret = 0;
        inode->i_op = &spufs_file_iops;
        inode->i_fop = fops;
-       inode->u.generic_ip = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
+       inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
        d_add(dentry, inode);
 out:
        return ret;
index d30466d741942c621db357a0fc1aa18c3be21a2e..9d22361a26d6012a93393bfb664803aa6f73785a 100644 (file)
@@ -104,7 +104,7 @@ static void g5_smu_switch_volt(int speed_mode)
 {
        struct smu_simple_cmd   cmd;
 
-       DECLARE_COMPLETION(comp);
+       DECLARE_COMPLETION_ONSTACK(comp);
        smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete,
                         &comp, 'V', 'S', 'L', 'E', 'W',
                         0xff, g5_fvt_cur+1, speed_mode);
index 6a36ea9bf67339d8f5e066419db811feed612dc7..692945c149194e77914318f71a9f8240567664d8 100644 (file)
@@ -195,7 +195,7 @@ static void pmu_nvram_complete(struct adb_request *req)
 static unsigned char pmu_nvram_read_byte(int addr)
 {
        struct adb_request req;
-       DECLARE_COMPLETION(req_complete); 
+       DECLARE_COMPLETION_ONSTACK(req_complete);
        
        req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
        if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
@@ -211,7 +211,7 @@ static unsigned char pmu_nvram_read_byte(int addr)
 static void pmu_nvram_write_byte(int addr, unsigned char val)
 {
        struct adb_request req;
-       DECLARE_COMPLETION(req_complete); 
+       DECLARE_COMPLETION_ONSTACK(req_complete);
        
        req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
        if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
index 641e6511cf0660efee29227787e3a029466cdbda..446e17d162a545e004c18779e61e8c5b4e398414 100644 (file)
@@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file)
 
        rc = seq_open(file, &hcall_inst_seq_ops);
        seq = file->private_data;
-       seq->private = file->f_dentry->d_inode->u.generic_ip;
+       seq->private = file->f_dentry->d_inode->i_private;
 
        return rc;
 }
index 903115d67fdcc5230b718abb6dfb25038881d5b8..311ed1993fc036de995f444bac92d1a327236c89 100644 (file)
@@ -337,7 +337,7 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log * err)
                   err->disposition == RTAS_DISP_NOT_RECOVERED &&
                   err->target == RTAS_TARGET_MEMORY &&
                   err->type == RTAS_TYPE_ECC_UNCORR &&
-                  !(current->pid == 0 || current->pid == 1)) {
+                  !(current->pid == 0 || is_init(current))) {
                /* Kill off a user process with an ECC error */
                printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
                       current->pid);
index a6398fbe530dc55ad8a79cb6baad66e586df429e..8ed362140452e850bb44c2bc2b32b1a68ff8bef3 100644 (file)
@@ -415,6 +415,12 @@ static int pSeries_check_legacy_ioport(unsigned int baseport)
                        return -ENODEV;
                of_node_put(np);
                break;
+       case PARALLEL_BASE:
+               np = of_find_node_by_type(NULL, "parallel");
+               if (np == NULL)
+                       return -ENODEV;
+               of_node_put(np);
+               break;
        }
        return 0;
 }
index b604926401f501575c1832f23ea2b449c86504e5..723972bb5bd9c692d157a9e79bec10cba9a80ae4 100644 (file)
@@ -339,7 +339,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
        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_IRQCONF) {
+               if (id == PCI_CAP_ID_HT) {
                        id = readb(devbase + pos + 3);
                        if (id == 0x80)
                                break;
index 8fa10cf661a80191fc0912463591ff6579d1663c..fdd9e7b6624479e712031974d0029fbde452e4a6 100644 (file)
@@ -953,6 +953,9 @@ config NR_CPUS
 config HIGHMEM
        bool "High memory support"
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 source kernel/Kconfig.hz
 source kernel/Kconfig.preempt
 source "mm/Kconfig"
index 5458ac5da7c3f9f535f01c3c2b42934beee13acc..75fe13815be27c23e817ac7527c00079476f1c0b 100644 (file)
@@ -86,10 +86,6 @@ int ppc_do_canonicalize_irqs;
 EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
 #endif
 
-#ifdef CONFIG_MAGIC_SYSRQ
-unsigned long SYSRQ_KEY = 0x54;
-#endif /* CONFIG_MAGIC_SYSRQ */
-
 #ifdef CONFIG_VGA_CONSOLE
 unsigned long vgacon_remap_base;
 #endif
index 6ab8cc7226ab232b220d9d555f0ed66358c0f6c0..187388625a768ed45a15d3bb68c0c93dc491e8af 100644 (file)
@@ -80,8 +80,6 @@ unsigned tb_to_us;
 unsigned tb_last_stamp;
 unsigned long tb_to_ns_scale;
 
-extern unsigned long wall_jiffies;
-
 /* used for timezone offset */
 static long timezone_offset;
 
@@ -153,7 +151,7 @@ void timer_interrupt(struct pt_regs * regs)
                /* We are in an interrupt, no need to save/restore flags */
                write_seqlock(&xtime_lock);
                tb_last_stamp = jiffy_stamp;
-               do_timer(regs);
+               do_timer(1);
 
                /*
                 * update the rtc when needed, this should be performed on the
@@ -173,8 +171,7 @@ void timer_interrupt(struct pt_regs * regs)
                 */
                if ( ppc_md.set_rtc_time && ntp_synced() &&
                     xtime.tv_sec - last_rtc_update >= 659 &&
-                    abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ &&
-                    jiffies - wall_jiffies == 1) {
+                    abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ) {
                        if (ppc_md.set_rtc_time(xtime.tv_sec+1 + timezone_offset) == 0)
                                last_rtc_update = xtime.tv_sec+1;
                        else
@@ -200,7 +197,7 @@ void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
        unsigned long seq;
-       unsigned delta, lost_ticks, usec, sec;
+       unsigned delta, usec, sec;
 
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
@@ -214,10 +211,9 @@ void do_gettimeofday(struct timeval *tv)
                if (!smp_tb_synchronized)
                        delta = 0;
 #endif /* CONFIG_SMP */
-               lost_ticks = jiffies - wall_jiffies;
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-       usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
+       usec += mulhwu(tb_to_us, delta);
        while (usec >= 1000000) {
                sec++;
                usec -= 1000000;
@@ -258,7 +254,6 @@ int do_settimeofday(struct timespec *tv)
         * still reasonable when gettimeofday resolution is 1 jiffy.
         */
        tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
-       tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
 
        new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
 
index d7a433049b4857b3acf2caa59e6f7c981d1c5f21..aafc8e8893d1ebc0ac969b097f77d9f976d616ee 100644 (file)
@@ -119,7 +119,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
         * generate the same exception over and over again and we get
         * nowhere.  Better to kill it and let the kernel panic.
         */
-       if (current->pid == 1) {
+       if (is_init(current)) {
                __sighandler_t handler;
 
                spin_lock_irq(&current->sighand->siglock);
index 5cdfb71fcb078ca50f56059a907e0104ab452194..465f451f3bc3a8a95908dcaa4d31757e04bc9f26 100644 (file)
@@ -239,7 +239,7 @@ good_area:
                /* protection fault */
                if (error_code & 0x08000000)
                        goto bad_area;
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                        goto bad_area;
        }
 
@@ -291,7 +291,7 @@ bad_area:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index 523392d460fa129aecceb4a0c8f5e0f541f0c970..410200046af120236e44fb35d656e57f65ceb0da 100644 (file)
@@ -358,8 +358,8 @@ void __init do_init_bootmem(void)
  */
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES], i;
-
+       unsigned long start_pfn, end_pfn;
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 #ifdef CONFIG_HIGHMEM
        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
        pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
@@ -369,19 +369,18 @@ void __init paging_init(void)
                        (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
        kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
-
-       /*
-        * All pages are DMA-able so we put them all in the DMA zone.
-        */
-       zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
-       for (i = 1; i < MAX_NR_ZONES; i++)
-               zones_size[i] = 0;
+       /* All pages are DMA-able so we put them all in the DMA zone. */
+       start_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
+       end_pfn = start_pfn + (total_memory >> PAGE_SHIFT);
+       add_active_range(0, start_pfn, end_pfn);
 
 #ifdef CONFIG_HIGHMEM
-       zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
+       max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
+       max_zone_pfns[1] = total_memory >> PAGE_SHIFT;
+#else
+       max_zone_pfns[0] = total_memory >> PAGE_SHIFT;
 #endif /* CONFIG_HIGHMEM */
-
-       free_area_init(zones_size);
+       free_area_init_nodes(max_zone_pfns);
 }
 
 void __init mem_init(void)
index b216ca659cdff5876e8cbb8f04be03395fc03cc3..f900a516f099bfc6724068af74b77d6149625cf0 100644 (file)
@@ -51,6 +51,10 @@ config 64BIT
          Select this option if you have a 64 bit IBM zSeries machine
          and want to use the 64 bit addressing mode.
 
+config 32BIT
+       bool
+       default y if !64BIT
+
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
@@ -149,6 +153,14 @@ config MARCH_Z990
          This will be slightly faster but does not work on
          older machines such as the z900.
 
+config MARCH_Z9_109
+       bool "IBM System z9"
+       help
+         Select this to enable optimizations for IBM System z9-109, IBM
+         System z9 Enterprise Class (z9 EC), and IBM System z9 Business
+         Class (z9 BC). The kernel will be slightly faster but will not
+         work on older machines such as the z990, z890, z900, and z800.
+
 endchoice
 
 config PACK_STACK
index 74ef57dcfa60b5bb9527d6651440995851aa9ebd..5deb9f7544a1da444b1ba0034685d511c74fc67b 100644 (file)
@@ -33,6 +33,7 @@ endif
 cflags-$(CONFIG_MARCH_G5)   += $(call cc-option,-march=g5)
 cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
 cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
+cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
 
 #
 # Prevent tail-call optimizations, to get clearer backtraces:
index b69ed742f98179834b4317d1a0320e205e23aef9..2b1e6c9a6e0e539826a3a8d45181ec5a7c72e76c 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
-#include <linux/page-flags.h>
+#include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
 #include <linux/sysctl.h>
@@ -157,12 +157,12 @@ int appldata_diag(char record_nr, u16 function, unsigned long buffer,
                .prod_nr    = {0xD3, 0xC9, 0xD5, 0xE4,
                               0xE7, 0xD2, 0xD9},       /* "LINUXKR" */
                .prod_fn    = 0xD5D3,                   /* "NL" */
-               .record_nr  = record_nr,
                .version_nr = 0xF2F6,                   /* "26" */
                .release_nr = 0xF0F1,                   /* "01" */
-               .mod_lvl    = (mod_lvl[0]) << 8 | mod_lvl[1],
        };
 
+       id.record_nr = record_nr;
+       id.mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1];
        return appldata_asm(&id, function, (void *) buffer, length);
 }
 /************************ timer, work, DIAG <END> ****************************/
index efd836c2e4a6cf0726a55dcad3c77bdca40a202f..2b137089f6251bbd920523770fa07821d25a79d1 100644 (file)
@@ -104,63 +104,6 @@ struct crypt_s390_query_status {
        u64 low;
 };
 
-/*
- * Standard fixup and ex_table sections for crypt_s390 inline functions.
- * label 0: the s390 crypto operation
- * label 1: just after 1 to catch illegal operation exception
- *          (unsupported model)
- * label 6: the return point after fixup
- * label 7: set error value if exception _in_ crypto operation
- * label 8: set error value if illegal operation exception
- * [ret] is the variable to receive the error code
- * [ERR] is the error code value
- */
-#ifndef CONFIG_64BIT
-#define __crypt_s390_fixup \
-       ".section .fixup,\"ax\" \n"     \
-       "7:     lhi     %0,%h[e1] \n"   \
-       "       bras    1,9f \n"        \
-       "       .long   6b \n"          \
-       "8:     lhi     %0,%h[e2] \n"   \
-       "       bras    1,9f \n"        \
-       "       .long   6b \n"          \
-       "9:     l       1,0(1) \n"      \
-       "       br      1 \n"           \
-       ".previous \n"                  \
-       ".section __ex_table,\"a\" \n"  \
-       "       .align  4 \n"           \
-       "       .long   0b,7b \n"       \
-       "       .long   1b,8b \n"       \
-       ".previous"
-#else /* CONFIG_64BIT */
-#define __crypt_s390_fixup \
-       ".section .fixup,\"ax\" \n"     \
-       "7:     lhi     %0,%h[e1] \n"   \
-       "       jg      6b \n"          \
-       "8:     lhi     %0,%h[e2] \n"   \
-       "       jg      6b \n"          \
-       ".previous\n"                   \
-       ".section __ex_table,\"a\" \n"  \
-       "       .align  8 \n"           \
-       "       .quad   0b,7b \n"       \
-       "       .quad   1b,8b \n"       \
-       ".previous"
-#endif /* CONFIG_64BIT */
-
-/*
- * Standard code for setting the result of s390 crypto instructions.
- * %0: the register which will receive the result
- * [result]: the register containing the result (e.g. second operand length
- * to compute number of processed bytes].
- */
-#ifndef CONFIG_64BIT
-#define __crypt_s390_set_result \
-       "       lr      %0,%[result] \n"
-#else /* CONFIG_64BIT */
-#define __crypt_s390_set_result \
-       "       lgr     %0,%[result] \n"
-#endif
-
 /*
  * Executes the KM (CIPHER MESSAGE) operation of the CPU.
  * @param func: the function code passed to KM; see crypt_s390_km_func
@@ -176,28 +119,24 @@ crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
        register void* __param asm("1") = param;
-       register u8* __dest asm("4") = dest;
        register const u8* __src asm("2") = src;
        register long __src_len asm("3") = src_len;
+       register u8* __dest asm("4") = dest;
        int ret;
 
-       ret = 0;
-       __asm__ __volatile__ (
-               "0:     .insn   rre,0xB92E0000,%1,%2 \n" /* KM opcode */
+       asm volatile(
+               "0:     .insn   rre,0xb92e0000,%3,%1 \n" /* KM opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               __crypt_s390_set_result
-               "6:     \n"
-               __crypt_s390_fixup
-               : "+d" (ret), "+a" (__dest), "+a" (__src),
-                 [result] "+d" (__src_len)
-               : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-                 "a" (__param)
-               : "cc", "memory"
-       );
-       if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-               ret = src_len - ret;
-       }
-       return ret;
+               "       ahi     %0,%h7\n"
+               "2:     ahi     %0,%h8\n"
+               "3:\n"
+               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+               : "d" (__func), "a" (__param), "0" (-EFAULT),
+                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+       if (ret < 0)
+               return ret;
+       return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -215,28 +154,24 @@ crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
        register void* __param asm("1") = param;
-       register u8* __dest asm("4") = dest;
        register const u8* __src asm("2") = src;
        register long __src_len asm("3") = src_len;
+       register u8* __dest asm("4") = dest;
        int ret;
 
-       ret = 0;
-       __asm__ __volatile__ (
-               "0:     .insn   rre,0xB92F0000,%1,%2 \n" /* KMC opcode */
+       asm volatile(
+               "0:     .insn   rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               __crypt_s390_set_result
-               "6:     \n"
-               __crypt_s390_fixup
-               : "+d" (ret), "+a" (__dest), "+a" (__src),
-                 [result] "+d" (__src_len)
-               : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-                 "a" (__param)
-               : "cc", "memory"
-       );
-       if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-               ret = src_len - ret;
-       }
-       return ret;
+               "       ahi     %0,%h7\n"
+               "2:     ahi     %0,%h8\n"
+               "3:\n"
+               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+               : "d" (__func), "a" (__param), "0" (-EFAULT),
+                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+       if (ret < 0)
+               return ret;
+       return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -258,22 +193,19 @@ crypt_s390_kimd(long func, void* param, const u8* src, long src_len)
        register long __src_len asm("3") = src_len;
        int ret;
 
-       ret = 0;
-       __asm__ __volatile__ (
-               "0:     .insn   rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */
-               "1:     brc     1,0b \n" /* handle partical completion */
-               __crypt_s390_set_result
-               "6:     \n"
-               __crypt_s390_fixup
-               : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
-               : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-                 "a" (__param)
-               : "cc", "memory"
-       );
-       if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){
-               ret = src_len - ret;
-       }
-       return ret;
+       asm volatile(
+               "0:     .insn   rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
+               "1:     brc     1,0b \n" /* handle partial completion */
+               "       ahi     %0,%h6\n"
+               "2:     ahi     %0,%h7\n"
+               "3:\n"
+               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               : "=d" (ret), "+a" (__src), "+d" (__src_len)
+               : "d" (__func), "a" (__param), "0" (-EFAULT),
+                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+       if (ret < 0)
+               return ret;
+       return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -294,22 +226,19 @@ crypt_s390_klmd(long func, void* param, const u8* src, long src_len)
        register long __src_len asm("3") = src_len;
        int ret;
 
-       ret = 0;
-       __asm__ __volatile__ (
-               "0:     .insn   rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */
-               "1:     brc     1,0b \n" /* handle partical completion */
-               __crypt_s390_set_result
-               "6:     \n"
-               __crypt_s390_fixup
-               : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
-               : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-                 "a" (__param)
-               : "cc", "memory"
-       );
-       if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-               ret = src_len - ret;
-       }
-       return ret;
+       asm volatile(
+               "0:     .insn   rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
+               "1:     brc     1,0b \n" /* handle partial completion */
+               "       ahi     %0,%h6\n"
+               "2:     ahi     %0,%h7\n"
+               "3:\n"
+               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               : "=d" (ret), "+a" (__src), "+d" (__src_len)
+               : "d" (__func), "a" (__param), "0" (-EFAULT),
+                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+       if (ret < 0)
+               return ret;
+       return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /*
@@ -331,22 +260,19 @@ crypt_s390_kmac(long func, void* param, const u8* src, long src_len)
        register long __src_len asm("3") = src_len;
        int ret;
 
-       ret = 0;
-       __asm__ __volatile__ (
-               "0:     .insn   rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */
-               "1:     brc     1,0b \n" /* handle partical completion */
-               __crypt_s390_set_result
-               "6:     \n"
-               __crypt_s390_fixup
-               : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
-               : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
-                 "a" (__param)
-               : "cc", "memory"
-       );
-       if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
-               ret = src_len - ret;
-       }
-       return ret;
+       asm volatile(
+               "0:     .insn   rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
+               "1:     brc     1,0b \n" /* handle partial completion */
+               "       ahi     %0,%h6\n"
+               "2:     ahi     %0,%h7\n"
+               "3:\n"
+               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               : "=d" (ret), "+a" (__src), "+d" (__src_len)
+               : "d" (__func), "a" (__param), "0" (-EFAULT),
+                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+       if (ret < 0)
+               return ret;
+       return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /**
index 75144efbb92b647cd8ce83487d5bf3a2a7fd238b..443fa377d9ff893efbd09a6f7214dbbcebd53f0a 100644 (file)
@@ -333,22 +333,14 @@ static int diag204(unsigned long subcode, unsigned long size, void *addr)
        register unsigned long _subcode asm("0") = subcode;
        register unsigned long _size asm("1") = size;
 
-       asm volatile ("   diag    %2,%0,0x204\n"
-                     "0: \n" ".section __ex_table,\"a\"\n"
-#ifndef __s390x__
-                     "    .align 4\n"
-                     "    .long  0b,0b\n"
-#else
-                     "    .align 8\n"
-                     "    .quad  0b,0b\n"
-#endif
-                     ".previous":"+d" (_subcode), "+d"(_size)
-                     :"d"(addr)
-                     :"memory");
+       asm volatile(
+               "       diag    %2,%0,0x204\n"
+               "0:\n"
+               EX_TABLE(0b,0b)
+               : "+d" (_subcode), "+d" (_size) : "d" (addr) : "memory");
        if (_subcode)
                return -1;
-       else
-               return _size;
+       return _size;
 }
 
 /*
@@ -403,7 +395,8 @@ static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
                *pages = 1;
                return diag204_alloc_rbuf();
        } else {/* INFO_EXT */
-               *pages = diag204(SUBC_RSI | INFO_EXT, 0, NULL);
+               *pages = diag204((unsigned long)SUBC_RSI |
+                                (unsigned long)INFO_EXT, 0, NULL);
                if (*pages <= 0)
                        return ERR_PTR(-ENOSYS);
                else
@@ -490,8 +483,7 @@ out:
 
 static void diag224(void *ptr)
 {
-       asm volatile("   diag    %0,%1,0x224\n"
-                    : :"d" (0), "d"(ptr) : "memory");
+       asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
 }
 
 static int diag224_get_name_table(void)
index bdade5f2e325e6b43a1bef2dc7b0833491ccb644..cd702ae45d6ddda9d52df2a5632278fcd34a5414 100644 (file)
@@ -91,7 +91,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
                ret->i_mode = mode;
                ret->i_uid = hypfs_info->uid;
                ret->i_gid = hypfs_info->gid;
-               ret->i_blksize = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
                if (mode & S_IFDIR)
@@ -104,13 +103,13 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
 
 static void hypfs_drop_inode(struct inode *inode)
 {
-       kfree(inode->u.generic_ip);
+       kfree(inode->i_private);
        generic_delete_inode(inode);
 }
 
 static int hypfs_open(struct inode *inode, struct file *filp)
 {
-       char *data = filp->f_dentry->d_inode->u.generic_ip;
+       char *data = filp->f_dentry->d_inode->i_private;
        struct hypfs_sb_info *fs_info;
 
        if (filp->f_mode & FMODE_WRITE) {
@@ -135,12 +134,20 @@ static int hypfs_open(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
-                             size_t count, loff_t offset)
+static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                             unsigned long nr_segs, loff_t offset)
 {
        char *data;
        size_t len;
        struct file *filp = iocb->ki_filp;
+       /* XXX: temporary */
+       char __user *buf = iov[0].iov_base;
+       size_t count = iov[0].iov_len;
+
+       if (nr_segs != 1) {
+               count = -EINVAL;
+               goto out;
+       }
 
        data = filp->private_data;
        len = strlen(data);
@@ -159,12 +166,13 @@ static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
 out:
        return count;
 }
-static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf,
-                              size_t count, loff_t pos)
+static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                             unsigned long nr_segs, loff_t offset)
 {
        int rc;
        struct super_block *sb;
        struct hypfs_sb_info *fs_info;
+       size_t count = iov_length(iov, nr_segs);
 
        sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
        fs_info = sb->s_fs_info;
@@ -352,7 +360,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
                parent->d_inode->i_nlink++;
        } else
                BUG();
-       inode->u.generic_ip = data;
+       inode->i_private = data;
        d_instantiate(dentry, inode);
        dget(dentry);
        return dentry;
index 785c9f70ac980b328360560ffa8858191a60c382..c46e3d48e4104d827abc7c17c40bed215fe70461 100644 (file)
@@ -544,10 +544,7 @@ sys32_execve(struct pt_regs regs)
                current->ptrace &= ~PT_DTRACE;
                task_unlock(current);
                current->thread.fp_regs.fpc=0;
-               __asm__ __volatile__
-                       ("sr  0,0\n\t"
-                        "sfpc 0,0\n\t"
-                        : : :"0");
+               asm volatile("sfpc %0,0" : : "d" (0));
        }
         putname(filename);
 out:
@@ -708,7 +705,7 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
        return ret;
 }
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 struct __sysctl_args32 {
        u32 name;
        int nlen;
index 4d53b2739357d21aa707d838184dedf29486e220..4aabeeaa7cf778b56104688272a4f007e939ca83 100644 (file)
@@ -4,97 +4,97 @@
 *
 *    Copyright (C) IBM Corp. 2000,2006
 *    Author(s): Gerhard Tonn (ton@de.ibm.com),
-*               Thomas Spatzier (tspat@de.ibm.com)
-*/ 
+*              Thomas Spatzier (tspat@de.ibm.com)
+*/
 
-       .globl  sys32_exit_wrapper 
+       .globl  sys32_exit_wrapper
 sys32_exit_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_exit                # branch to sys_exit
-    
-       .globl  sys32_read_wrapper 
+
+       .globl  sys32_read_wrapper
 sys32_read_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
        jg      sys32_read              # branch to sys_read
 
-       .globl  sys32_write_wrapper 
+       .globl  sys32_write_wrapper
 sys32_write_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # size_t
        jg      sys32_write             # branch to system call
 
-       .globl  sys32_open_wrapper 
+       .globl  sys32_open_wrapper
 sys32_open_wrapper:
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
        jg      sys_open                # branch to system call
 
-       .globl  sys32_close_wrapper 
+       .globl  sys32_close_wrapper
 sys32_close_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_close               # branch to system call
 
-       .globl  sys32_creat_wrapper 
+       .globl  sys32_creat_wrapper
 sys32_creat_wrapper:
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_creat               # branch to system call
 
-       .globl  sys32_link_wrapper 
+       .globl  sys32_link_wrapper
 sys32_link_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_link                # branch to system call
 
-       .globl  sys32_unlink_wrapper 
+       .globl  sys32_unlink_wrapper
 sys32_unlink_wrapper:
        llgtr   %r2,%r2                 # const char *
        jg      sys_unlink              # branch to system call
 
-       .globl  sys32_chdir_wrapper 
+       .globl  sys32_chdir_wrapper
 sys32_chdir_wrapper:
        llgtr   %r2,%r2                 # const char *
        jg      sys_chdir               # branch to system call
 
-       .globl  sys32_time_wrapper 
+       .globl  sys32_time_wrapper
 sys32_time_wrapper:
        llgtr   %r2,%r2                 # int *
        jg      compat_sys_time         # branch to system call
 
-       .globl  sys32_mknod_wrapper 
+       .globl  sys32_mknod_wrapper
 sys32_mknod_wrapper:
        llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int 
+       lgfr    %r3,%r3                 # int
        llgfr   %r4,%r4                 # dev
        jg      sys_mknod               # branch to system call
 
-       .globl  sys32_chmod_wrapper 
+       .globl  sys32_chmod_wrapper
 sys32_chmod_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # mode_t
        jg      sys_chmod               # branch to system call
 
-       .globl  sys32_lchown16_wrapper 
+       .globl  sys32_lchown16_wrapper
 sys32_lchown16_wrapper:
        llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t 
-       llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t 
+       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
+       llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t
        jg      sys32_lchown16          # branch to system call
 
-       .globl  sys32_lseek_wrapper 
+       .globl  sys32_lseek_wrapper
 sys32_lseek_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        lgfr    %r3,%r3                 # off_t
        llgfr   %r4,%r4                 # unsigned int
        jg      sys_lseek               # branch to system call
 
-#sys32_getpid_wrapper                          # void 
+#sys32_getpid_wrapper                          # void
 
-       .globl  sys32_mount_wrapper 
+       .globl  sys32_mount_wrapper
 sys32_mount_wrapper:
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
@@ -103,19 +103,19 @@ sys32_mount_wrapper:
        llgtr   %r6,%r6                 # void *
        jg      compat_sys_mount        # branch to system call
 
-       .globl  sys32_oldumount_wrapper 
+       .globl  sys32_oldumount_wrapper
 sys32_oldumount_wrapper:
        llgtr   %r2,%r2                 # char *
        jg      sys_oldumount           # branch to system call
 
-       .globl  sys32_setuid16_wrapper 
+       .globl  sys32_setuid16_wrapper
 sys32_setuid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
        jg      sys32_setuid16          # branch to system call
 
-#sys32_getuid16_wrapper                        # void 
+#sys32_getuid16_wrapper                        # void
 
-       .globl  sys32_ptrace_wrapper 
+       .globl  sys32_ptrace_wrapper
 sys32_ptrace_wrapper:
        lgfr    %r2,%r2                 # long
        lgfr    %r3,%r3                 # long
@@ -123,168 +123,168 @@ sys32_ptrace_wrapper:
        llgfr   %r5,%r5                 # long
        jg      sys_ptrace              # branch to system call
 
-       .globl  sys32_alarm_wrapper 
+       .globl  sys32_alarm_wrapper
 sys32_alarm_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_alarm               # branch to system call
 
-#sys32_pause_wrapper                   # void 
+#sys32_pause_wrapper                   # void
 
-       .globl  compat_sys_utime_wrapper 
+       .globl  compat_sys_utime_wrapper
 compat_sys_utime_wrapper:
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct compat_utimbuf *
        jg      compat_sys_utime        # branch to system call
 
-       .globl  sys32_access_wrapper 
+       .globl  sys32_access_wrapper
 sys32_access_wrapper:
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_access              # branch to system call
 
-       .globl  sys32_nice_wrapper 
+       .globl  sys32_nice_wrapper
 sys32_nice_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_nice                # branch to system call
 
-#sys32_sync_wrapper                    # void 
+#sys32_sync_wrapper                    # void
 
-       .globl  sys32_kill_wrapper 
+       .globl  sys32_kill_wrapper
 sys32_kill_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_kill                # branch to system call
 
-       .globl  sys32_rename_wrapper 
+       .globl  sys32_rename_wrapper
 sys32_rename_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_rename              # branch to system call
 
-       .globl  sys32_mkdir_wrapper 
+       .globl  sys32_mkdir_wrapper
 sys32_mkdir_wrapper:
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_mkdir               # branch to system call
 
-       .globl  sys32_rmdir_wrapper 
+       .globl  sys32_rmdir_wrapper
 sys32_rmdir_wrapper:
        llgtr   %r2,%r2                 # const char *
        jg      sys_rmdir               # branch to system call
 
-       .globl  sys32_dup_wrapper 
+       .globl  sys32_dup_wrapper
 sys32_dup_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_dup                 # branch to system call
 
-       .globl  sys32_pipe_wrapper 
+       .globl  sys32_pipe_wrapper
 sys32_pipe_wrapper:
        llgtr   %r2,%r2                 # u32 *
        jg      sys_pipe                # branch to system call
 
-       .globl  compat_sys_times_wrapper 
+       .globl  compat_sys_times_wrapper
 compat_sys_times_wrapper:
        llgtr   %r2,%r2                 # struct compat_tms *
        jg      compat_sys_times        # branch to system call
 
-       .globl  sys32_brk_wrapper 
+       .globl  sys32_brk_wrapper
 sys32_brk_wrapper:
        llgtr   %r2,%r2                 # unsigned long
        jg      sys_brk                 # branch to system call
 
-       .globl  sys32_setgid16_wrapper 
+       .globl  sys32_setgid16_wrapper
 sys32_setgid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        jg      sys32_setgid16          # branch to system call
 
-#sys32_getgid16_wrapper                        # void 
+#sys32_getgid16_wrapper                        # void
 
        .globl sys32_signal_wrapper
 sys32_signal_wrapper:
-       lgfr    %r2,%r2                 # int 
+       lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # __sighandler_t
        jg      sys_signal
 
-#sys32_geteuid16_wrapper               # void 
+#sys32_geteuid16_wrapper               # void
 
-#sys32_getegid16_wrapper               # void 
+#sys32_getegid16_wrapper               # void
 
-       .globl  sys32_acct_wrapper 
+       .globl  sys32_acct_wrapper
 sys32_acct_wrapper:
        llgtr   %r2,%r2                 # char *
        jg      sys_acct                # branch to system call
 
-       .globl  sys32_umount_wrapper 
+       .globl  sys32_umount_wrapper
 sys32_umount_wrapper:
        llgtr   %r2,%r2                 # char *
        lgfr    %r3,%r3                 # int
        jg      sys_umount              # branch to system call
 
-       .globl  compat_sys_ioctl_wrapper
+       .globl  compat_sys_ioctl_wrapper
 compat_sys_ioctl_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        llgfr   %r4,%r4                 # unsigned int
        jg      compat_sys_ioctl        # branch to system call
 
-       .globl  compat_sys_fcntl_wrapper 
+       .globl  compat_sys_fcntl_wrapper
 compat_sys_fcntl_wrapper:
        llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int 
+       llgfr   %r3,%r3                 # unsigned int
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_fcntl        # branch to system call
 
-       .globl  sys32_setpgid_wrapper 
+       .globl  sys32_setpgid_wrapper
 sys32_setpgid_wrapper:
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # pid_t
        jg      sys_setpgid             # branch to system call
 
-       .globl  sys32_umask_wrapper 
+       .globl  sys32_umask_wrapper
 sys32_umask_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_umask               # branch to system call
 
-       .globl  sys32_chroot_wrapper 
+       .globl  sys32_chroot_wrapper
 sys32_chroot_wrapper:
        llgtr   %r2,%r2                 # char *
        jg      sys_chroot              # branch to system call
 
        .globl sys32_ustat_wrapper
 sys32_ustat_wrapper:
-       llgfr   %r2,%r2                 # dev_t 
+       llgfr   %r2,%r2                 # dev_t
        llgtr   %r3,%r3                 # struct ustat *
        jg      sys_ustat
 
-       .globl  sys32_dup2_wrapper 
+       .globl  sys32_dup2_wrapper
 sys32_dup2_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_dup2                # branch to system call
 
-#sys32_getppid_wrapper                 # void 
+#sys32_getppid_wrapper                 # void
 
-#sys32_getpgrp_wrapper                 # void 
+#sys32_getpgrp_wrapper                 # void
 
-#sys32_setsid_wrapper                  # void 
+#sys32_setsid_wrapper                  # void
 
-       .globl  sys32_sigaction_wrapper
+       .globl  sys32_sigaction_wrapper
 sys32_sigaction_wrapper:
-       lgfr    %r2,%r2                 # int 
+       lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct old_sigaction *
        llgtr   %r4,%r4                 # struct old_sigaction32 *
        jg      sys32_sigaction         # branch to system call
 
-       .globl  sys32_setreuid16_wrapper 
+       .globl  sys32_setreuid16_wrapper
 sys32_setreuid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t 
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
+       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
        jg      sys32_setreuid16        # branch to system call
 
-       .globl  sys32_setregid16_wrapper 
+       .globl  sys32_setregid16_wrapper
 sys32_setregid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t 
-       llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
+       llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
        jg      sys32_setregid16        # branch to system call
 
        .globl sys_sigsuspend_wrapper
@@ -294,95 +294,95 @@ sys_sigsuspend_wrapper:
        llgfr   %r4,%r4                 # old_sigset_t
        jg      sys_sigsuspend
 
-       .globl  compat_sys_sigpending_wrapper 
+       .globl  compat_sys_sigpending_wrapper
 compat_sys_sigpending_wrapper:
        llgtr   %r2,%r2                 # compat_old_sigset_t *
        jg      compat_sys_sigpending   # branch to system call
 
-       .globl  sys32_sethostname_wrapper 
+       .globl  sys32_sethostname_wrapper
 sys32_sethostname_wrapper:
        llgtr   %r2,%r2                 # char *
        lgfr    %r3,%r3                 # int
        jg      sys_sethostname         # branch to system call
 
-       .globl  compat_sys_setrlimit_wrapper 
+       .globl  compat_sys_setrlimit_wrapper
 compat_sys_setrlimit_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct rlimit_emu31 *
        jg      compat_sys_setrlimit    # branch to system call
 
-       .globl  compat_sys_old_getrlimit_wrapper 
+       .globl  compat_sys_old_getrlimit_wrapper
 compat_sys_old_getrlimit_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct rlimit_emu31 *
        jg      compat_sys_old_getrlimit # branch to system call
 
-       .globl  compat_sys_getrlimit_wrapper 
+       .globl  compat_sys_getrlimit_wrapper
 compat_sys_getrlimit_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct rlimit_emu31 *
        jg      compat_sys_getrlimit    # branch to system call
 
-       .globl  sys32_mmap2_wrapper 
+       .globl  sys32_mmap2_wrapper
 sys32_mmap2_wrapper:
        llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
        jg      sys32_mmap2                     # branch to system call
 
-       .globl  compat_sys_getrusage_wrapper 
+       .globl  compat_sys_getrusage_wrapper
 compat_sys_getrusage_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct rusage_emu31 *
        jg      compat_sys_getrusage    # branch to system call
 
-       .globl  sys32_gettimeofday_wrapper 
+       .globl  sys32_gettimeofday_wrapper
 sys32_gettimeofday_wrapper:
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
        jg      sys32_gettimeofday      # branch to system call
 
-       .globl  sys32_settimeofday_wrapper 
+       .globl  sys32_settimeofday_wrapper
 sys32_settimeofday_wrapper:
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
        jg      sys32_settimeofday      # branch to system call
 
-       .globl  sys32_getgroups16_wrapper 
+       .globl  sys32_getgroups16_wrapper
 sys32_getgroups16_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
        jg      sys32_getgroups16       # branch to system call
 
-       .globl  sys32_setgroups16_wrapper 
+       .globl  sys32_setgroups16_wrapper
 sys32_setgroups16_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
        jg      sys32_setgroups16       # branch to system call
 
-       .globl  sys32_symlink_wrapper 
+       .globl  sys32_symlink_wrapper
 sys32_symlink_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_symlink             # branch to system call
 
-       .globl  sys32_readlink_wrapper 
+       .globl  sys32_readlink_wrapper
 sys32_readlink_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # char *
        lgfr    %r4,%r4                 # int
        jg      sys_readlink            # branch to system call
 
-       .globl  sys32_uselib_wrapper 
+       .globl  sys32_uselib_wrapper
 sys32_uselib_wrapper:
        llgtr   %r2,%r2                 # const char *
        jg      sys_uselib              # branch to system call
 
-       .globl  sys32_swapon_wrapper 
+       .globl  sys32_swapon_wrapper
 sys32_swapon_wrapper:
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_swapon              # branch to system call
 
-       .globl  sys32_reboot_wrapper 
+       .globl  sys32_reboot_wrapper
 sys32_reboot_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
@@ -390,121 +390,121 @@ sys32_reboot_wrapper:
        llgtr   %r5,%r5                 # void *
        jg      sys_reboot              # branch to system call
 
-       .globl  old32_readdir_wrapper 
+       .globl  old32_readdir_wrapper
 old32_readdir_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # void *
        llgfr   %r4,%r4                 # unsigned int
        jg      compat_sys_old_readdir  # branch to system call
 
-       .globl  old32_mmap_wrapper 
+       .globl  old32_mmap_wrapper
 old32_mmap_wrapper:
        llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
        jg      old32_mmap              # branch to system call
 
-       .globl  sys32_munmap_wrapper 
+       .globl  sys32_munmap_wrapper
 sys32_munmap_wrapper:
        llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t 
+       llgfr   %r3,%r3                 # size_t
        jg      sys_munmap              # branch to system call
 
-       .globl  sys32_truncate_wrapper 
+       .globl  sys32_truncate_wrapper
 sys32_truncate_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # unsigned long
        jg      sys_truncate            # branch to system call
 
-       .globl  sys32_ftruncate_wrapper 
+       .globl  sys32_ftruncate_wrapper
 sys32_ftruncate_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned long
        jg      sys_ftruncate           # branch to system call
 
-       .globl  sys32_fchmod_wrapper 
+       .globl  sys32_fchmod_wrapper
 sys32_fchmod_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # mode_t
        jg      sys_fchmod              # branch to system call
 
-       .globl  sys32_fchown16_wrapper 
+       .globl  sys32_fchown16_wrapper
 sys32_fchown16_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # compat_uid_t
        llgfr   %r4,%r4                 # compat_uid_t
        jg      sys32_fchown16          # branch to system call
 
-       .globl  sys32_getpriority_wrapper 
+       .globl  sys32_getpriority_wrapper
 sys32_getpriority_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_getpriority         # branch to system call
 
-       .globl  sys32_setpriority_wrapper 
+       .globl  sys32_setpriority_wrapper
 sys32_setpriority_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
        jg      sys_setpriority         # branch to system call
 
-       .globl  compat_sys_statfs_wrapper 
+       .globl  compat_sys_statfs_wrapper
 compat_sys_statfs_wrapper:
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct compat_statfs *
        jg      compat_sys_statfs       # branch to system call
 
-       .globl  compat_sys_fstatfs_wrapper 
+       .globl  compat_sys_fstatfs_wrapper
 compat_sys_fstatfs_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct compat_statfs *
        jg      compat_sys_fstatfs      # branch to system call
 
-       .globl  compat_sys_socketcall_wrapper 
+       .globl  compat_sys_socketcall_wrapper
 compat_sys_socketcall_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # u32 *
        jg      compat_sys_socketcall   # branch to system call
 
-       .globl  sys32_syslog_wrapper 
+       .globl  sys32_syslog_wrapper
 sys32_syslog_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # char *
        lgfr    %r4,%r4                 # int
        jg      sys_syslog              # branch to system call
 
-       .globl  compat_sys_setitimer_wrapper 
+       .globl  compat_sys_setitimer_wrapper
 compat_sys_setitimer_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct itimerval_emu31 *
        llgtr   %r4,%r4                 # struct itimerval_emu31 *
        jg      compat_sys_setitimer    # branch to system call
 
-       .globl  compat_sys_getitimer_wrapper 
+       .globl  compat_sys_getitimer_wrapper
 compat_sys_getitimer_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct itimerval_emu31 *
        jg      compat_sys_getitimer    # branch to system call
 
-       .globl  compat_sys_newstat_wrapper 
+       .globl  compat_sys_newstat_wrapper
 compat_sys_newstat_wrapper:
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct stat_emu31 *
        jg      compat_sys_newstat      # branch to system call
 
-       .globl  compat_sys_newlstat_wrapper 
+       .globl  compat_sys_newlstat_wrapper
 compat_sys_newlstat_wrapper:
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct stat_emu31 *
        jg      compat_sys_newlstat     # branch to system call
 
-       .globl  compat_sys_newfstat_wrapper 
+       .globl  compat_sys_newfstat_wrapper
 compat_sys_newfstat_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct stat_emu31 *
        jg      compat_sys_newfstat     # branch to system call
 
-#sys32_vhangup_wrapper                 # void 
+#sys32_vhangup_wrapper                 # void
 
-       .globl  compat_sys_wait4_wrapper 
+       .globl  compat_sys_wait4_wrapper
 compat_sys_wait4_wrapper:
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # unsigned int *
@@ -512,17 +512,17 @@ compat_sys_wait4_wrapper:
        llgtr   %r5,%r5                 # struct rusage *
        jg      compat_sys_wait4        # branch to system call
 
-       .globl  sys32_swapoff_wrapper 
+       .globl  sys32_swapoff_wrapper
 sys32_swapoff_wrapper:
        llgtr   %r2,%r2                 # const char *
        jg      sys_swapoff             # branch to system call
 
-       .globl  sys32_sysinfo_wrapper 
+       .globl  sys32_sysinfo_wrapper
 sys32_sysinfo_wrapper:
        llgtr   %r2,%r2                 # struct sysinfo_emu31 *
        jg      sys32_sysinfo           # branch to system call
 
-       .globl  sys32_ipc_wrapper 
+       .globl  sys32_ipc_wrapper
 sys32_ipc_wrapper:
        llgfr   %r2,%r2                 # uint
        lgfr    %r3,%r3                 # int
@@ -531,59 +531,59 @@ sys32_ipc_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      sys32_ipc               # branch to system call
 
-       .globl  sys32_fsync_wrapper 
+       .globl  sys32_fsync_wrapper
 sys32_fsync_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fsync               # branch to system call
 
-#sys32_sigreturn_wrapper               # done in sigreturn_glue 
+#sys32_sigreturn_wrapper               # done in sigreturn_glue
 
-#sys32_clone_wrapper                   # done in clone_glue 
+#sys32_clone_wrapper                   # done in clone_glue
 
-       .globl  sys32_setdomainname_wrapper 
+       .globl  sys32_setdomainname_wrapper
 sys32_setdomainname_wrapper:
        llgtr   %r2,%r2                 # char *
        lgfr    %r3,%r3                 # int
        jg      sys_setdomainname       # branch to system call
 
-       .globl  sys32_newuname_wrapper 
+       .globl  sys32_newuname_wrapper
 sys32_newuname_wrapper:
        llgtr   %r2,%r2                 # struct new_utsname *
        jg      s390x_newuname          # branch to system call
 
-       .globl  compat_sys_adjtimex_wrapper
+       .globl  compat_sys_adjtimex_wrapper
 compat_sys_adjtimex_wrapper:
        llgtr   %r2,%r2                 # struct compat_timex *
        jg      compat_sys_adjtimex     # branch to system call
 
-       .globl  sys32_mprotect_wrapper 
+       .globl  sys32_mprotect_wrapper
 sys32_mprotect_wrapper:
        llgtr   %r2,%r2                 # unsigned long (actually pointer
        llgfr   %r3,%r3                 # size_t
        llgfr   %r4,%r4                 # unsigned long
        jg      sys_mprotect            # branch to system call
 
-       .globl  compat_sys_sigprocmask_wrapper 
+       .globl  compat_sys_sigprocmask_wrapper
 compat_sys_sigprocmask_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_old_sigset_t *
        llgtr   %r4,%r4                 # compat_old_sigset_t *
        jg      compat_sys_sigprocmask          # branch to system call
 
-       .globl  sys32_init_module_wrapper 
+       .globl  sys32_init_module_wrapper
 sys32_init_module_wrapper:
        llgtr   %r2,%r2                 # void *
        llgfr   %r3,%r3                 # unsigned long
        llgtr   %r4,%r4                 # char *
        jg      sys32_init_module       # branch to system call
 
-       .globl  sys32_delete_module_wrapper 
+       .globl  sys32_delete_module_wrapper
 sys32_delete_module_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # unsigned int
        jg      sys32_delete_module     # branch to system call
 
-       .globl  sys32_quotactl_wrapper 
+       .globl  sys32_quotactl_wrapper
 sys32_quotactl_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
@@ -591,45 +591,45 @@ sys32_quotactl_wrapper:
        llgtr   %r5,%r5                 # caddr_t
        jg      sys_quotactl            # branch to system call
 
-       .globl  sys32_getpgid_wrapper 
+       .globl  sys32_getpgid_wrapper
 sys32_getpgid_wrapper:
        lgfr    %r2,%r2                 # pid_t
        jg      sys_getpgid             # branch to system call
 
-       .globl  sys32_fchdir_wrapper 
+       .globl  sys32_fchdir_wrapper
 sys32_fchdir_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fchdir              # branch to system call
 
-       .globl  sys32_bdflush_wrapper 
+       .globl  sys32_bdflush_wrapper
 sys32_bdflush_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # long
        jg      sys_bdflush             # branch to system call
 
-       .globl  sys32_sysfs_wrapper 
+       .globl  sys32_sysfs_wrapper
 sys32_sysfs_wrapper:
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
        jg      sys_sysfs               # branch to system call
 
-       .globl  sys32_personality_wrapper 
+       .globl  sys32_personality_wrapper
 sys32_personality_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        jg      s390x_personality       # branch to system call
 
-       .globl  sys32_setfsuid16_wrapper 
+       .globl  sys32_setfsuid16_wrapper
 sys32_setfsuid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
        jg      sys32_setfsuid16        # branch to system call
 
-       .globl  sys32_setfsgid16_wrapper 
+       .globl  sys32_setfsgid16_wrapper
 sys32_setfsgid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        jg      sys32_setfsgid16        # branch to system call
 
-       .globl  sys32_llseek_wrapper 
+       .globl  sys32_llseek_wrapper
 sys32_llseek_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned long
@@ -638,14 +638,14 @@ sys32_llseek_wrapper:
        llgfr   %r6,%r6                 # unsigned int
        jg      sys_llseek              # branch to system call
 
-       .globl  sys32_getdents_wrapper 
+       .globl  sys32_getdents_wrapper
 sys32_getdents_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # void *
        llgfr   %r4,%r4                 # unsigned int
        jg      compat_sys_getdents     # branch to system call
 
-       .globl  compat_sys_select_wrapper
+       .globl  compat_sys_select_wrapper
 compat_sys_select_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_fd_set *
@@ -654,113 +654,113 @@ compat_sys_select_wrapper:
        llgtr   %r6,%r6                 # struct compat_timeval *
        jg      compat_sys_select       # branch to system call
 
-       .globl  sys32_flock_wrapper 
+       .globl  sys32_flock_wrapper
 sys32_flock_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_flock               # branch to system call
 
-       .globl  sys32_msync_wrapper 
+       .globl  sys32_msync_wrapper
 sys32_msync_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        lgfr    %r4,%r4                 # int
        jg      sys_msync               # branch to system call
 
-       .globl  compat_sys_readv_wrapper
+       .globl  compat_sys_readv_wrapper
 compat_sys_readv_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct compat_iovec *
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_readv        # branch to system call
 
-       .globl  compat_sys_writev_wrapper
+       .globl  compat_sys_writev_wrapper
 compat_sys_writev_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct compat_iovec *
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_writev       # branch to system call
 
-       .globl  sys32_getsid_wrapper 
+       .globl  sys32_getsid_wrapper
 sys32_getsid_wrapper:
        lgfr    %r2,%r2                 # pid_t
        jg      sys_getsid              # branch to system call
 
-       .globl  sys32_fdatasync_wrapper 
+       .globl  sys32_fdatasync_wrapper
 sys32_fdatasync_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fdatasync           # branch to system call
 
-#sys32_sysctl_wrapper                  # tbd 
+#sys32_sysctl_wrapper                  # tbd
 
-       .globl  sys32_mlock_wrapper 
+       .globl  sys32_mlock_wrapper
 sys32_mlock_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        jg      sys_mlock               # branch to system call
 
-       .globl  sys32_munlock_wrapper 
+       .globl  sys32_munlock_wrapper
 sys32_munlock_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        jg      sys_munlock             # branch to system call
 
-       .globl  sys32_mlockall_wrapper 
+       .globl  sys32_mlockall_wrapper
 sys32_mlockall_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_mlockall            # branch to system call
 
-#sys32_munlockall_wrapper              # void 
+#sys32_munlockall_wrapper              # void
 
-       .globl  sys32_sched_setparam_wrapper 
+       .globl  sys32_sched_setparam_wrapper
 sys32_sched_setparam_wrapper:
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # struct sched_param *
        jg      sys_sched_setparam      # branch to system call
 
-       .globl  sys32_sched_getparam_wrapper 
+       .globl  sys32_sched_getparam_wrapper
 sys32_sched_getparam_wrapper:
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # struct sched_param *
        jg      sys_sched_getparam      # branch to system call
 
-       .globl  sys32_sched_setscheduler_wrapper 
+       .globl  sys32_sched_setscheduler_wrapper
 sys32_sched_setscheduler_wrapper:
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # struct sched_param *
        jg      sys_sched_setscheduler  # branch to system call
 
-       .globl  sys32_sched_getscheduler_wrapper 
+       .globl  sys32_sched_getscheduler_wrapper
 sys32_sched_getscheduler_wrapper:
        lgfr    %r2,%r2                 # pid_t
        jg      sys_sched_getscheduler  # branch to system call
 
-#sys32_sched_yield_wrapper             # void 
+#sys32_sched_yield_wrapper             # void
 
-       .globl  sys32_sched_get_priority_max_wrapper 
+       .globl  sys32_sched_get_priority_max_wrapper
 sys32_sched_get_priority_max_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_sched_get_priority_max      # branch to system call
 
-       .globl  sys32_sched_get_priority_min_wrapper 
+       .globl  sys32_sched_get_priority_min_wrapper
 sys32_sched_get_priority_min_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_sched_get_priority_min      # branch to system call
 
-       .globl  sys32_sched_rr_get_interval_wrapper 
+       .globl  sys32_sched_rr_get_interval_wrapper
 sys32_sched_rr_get_interval_wrapper:
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      sys32_sched_rr_get_interval     # branch to system call
 
-       .globl  compat_sys_nanosleep_wrapper 
+       .globl  compat_sys_nanosleep_wrapper
 compat_sys_nanosleep_wrapper:
        llgtr   %r2,%r2                 # struct compat_timespec *
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      compat_sys_nanosleep            # branch to system call
 
-       .globl  sys32_mremap_wrapper 
+       .globl  sys32_mremap_wrapper
 sys32_mremap_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # unsigned long
@@ -769,49 +769,49 @@ sys32_mremap_wrapper:
        llgfr   %r6,%r6                 # unsigned long
        jg      sys_mremap              # branch to system call
 
-       .globl  sys32_setresuid16_wrapper 
+       .globl  sys32_setresuid16_wrapper
 sys32_setresuid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t 
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t 
-       llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
+       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
+       llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t
        jg      sys32_setresuid16       # branch to system call
 
-       .globl  sys32_getresuid16_wrapper 
+       .globl  sys32_getresuid16_wrapper
 sys32_getresuid16_wrapper:
        llgtr   %r2,%r2                 # __kernel_old_uid_emu31_t *
        llgtr   %r3,%r3                 # __kernel_old_uid_emu31_t *
        llgtr   %r4,%r4                 # __kernel_old_uid_emu31_t *
        jg      sys32_getresuid16       # branch to system call
 
-       .globl  sys32_poll_wrapper 
+       .globl  sys32_poll_wrapper
 sys32_poll_wrapper:
-       llgtr   %r2,%r2                 # struct pollfd * 
-       llgfr   %r3,%r3                 # unsigned int 
-       lgfr    %r4,%r4                 # long 
+       llgtr   %r2,%r2                 # struct pollfd *
+       llgfr   %r3,%r3                 # unsigned int
+       lgfr    %r4,%r4                 # long
        jg      sys_poll                # branch to system call
 
-       .globl  compat_sys_nfsservctl_wrapper
+       .globl  compat_sys_nfsservctl_wrapper
 compat_sys_nfsservctl_wrapper:
-       lgfr    %r2,%r2                 # int 
+       lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct compat_nfsctl_arg*
        llgtr   %r4,%r4                 # union compat_nfsctl_res*
        jg      compat_sys_nfsservctl   # branch to system call
 
-       .globl  sys32_setresgid16_wrapper 
+       .globl  sys32_setresgid16_wrapper
 sys32_setresgid16_wrapper:
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t 
-       llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t 
-       llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t 
+       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
+       llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
+       llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t
        jg      sys32_setresgid16       # branch to system call
 
-       .globl  sys32_getresgid16_wrapper 
+       .globl  sys32_getresgid16_wrapper
 sys32_getresgid16_wrapper:
        llgtr   %r2,%r2                 # __kernel_old_gid_emu31_t *
        llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
        llgtr   %r4,%r4                 # __kernel_old_gid_emu31_t *
        jg      sys32_getresgid16       # branch to system call
 
-       .globl  sys32_prctl_wrapper 
+       .globl  sys32_prctl_wrapper
 sys32_prctl_wrapper:
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned long
@@ -820,9 +820,9 @@ sys32_prctl_wrapper:
        llgfr   %r6,%r6                 # unsigned long
        jg      sys_prctl               # branch to system call
 
-#sys32_rt_sigreturn_wrapper            # done in rt_sigreturn_glue 
+#sys32_rt_sigreturn_wrapper            # done in rt_sigreturn_glue
 
-       .globl  sys32_rt_sigaction_wrapper 
+       .globl  sys32_rt_sigaction_wrapper
 sys32_rt_sigaction_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct sigaction_emu31 *
@@ -830,7 +830,7 @@ sys32_rt_sigaction_wrapper:
        llgfr   %r5,%r5                 # size_t
        jg      sys32_rt_sigaction      # branch to system call
 
-       .globl  sys32_rt_sigprocmask_wrapper 
+       .globl  sys32_rt_sigprocmask_wrapper
 sys32_rt_sigprocmask_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # old_sigset_emu31 *
@@ -838,13 +838,13 @@ sys32_rt_sigprocmask_wrapper:
        llgfr   %r5,%r5                 # size_t
        jg      sys32_rt_sigprocmask    # branch to system call
 
-       .globl  sys32_rt_sigpending_wrapper 
+       .globl  sys32_rt_sigpending_wrapper
 sys32_rt_sigpending_wrapper:
        llgtr   %r2,%r2                 # sigset_emu31 *
        llgfr   %r3,%r3                 # size_t
        jg      sys32_rt_sigpending     # branch to system call
 
-       .globl  compat_sys_rt_sigtimedwait_wrapper
+       .globl  compat_sys_rt_sigtimedwait_wrapper
 compat_sys_rt_sigtimedwait_wrapper:
        llgtr   %r2,%r2                 # const sigset_emu31_t *
        llgtr   %r3,%r3                 # siginfo_emu31_t *
@@ -852,7 +852,7 @@ compat_sys_rt_sigtimedwait_wrapper:
        llgfr   %r5,%r5                 # size_t
        jg      compat_sys_rt_sigtimedwait      # branch to system call
 
-       .globl  sys32_rt_sigqueueinfo_wrapper 
+       .globl  sys32_rt_sigqueueinfo_wrapper
 sys32_rt_sigqueueinfo_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
@@ -865,7 +865,7 @@ compat_sys_rt_sigsuspend_wrapper:
        llgfr   %r3,%r3                 # compat_size_t
        jg      compat_sys_rt_sigsuspend
 
-       .globl  sys32_pread64_wrapper 
+       .globl  sys32_pread64_wrapper
 sys32_pread64_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
@@ -874,7 +874,7 @@ sys32_pread64_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      sys32_pread64           # branch to system call
 
-       .globl  sys32_pwrite64_wrapper 
+       .globl  sys32_pwrite64_wrapper
 sys32_pwrite64_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
@@ -883,26 +883,26 @@ sys32_pwrite64_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      sys32_pwrite64          # branch to system call
 
-       .globl  sys32_chown16_wrapper 
+       .globl  sys32_chown16_wrapper
 sys32_chown16_wrapper:
        llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t 
-       llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t 
+       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
+       llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t
        jg      sys32_chown16           # branch to system call
 
-       .globl  sys32_getcwd_wrapper 
+       .globl  sys32_getcwd_wrapper
 sys32_getcwd_wrapper:
        llgtr   %r2,%r2                 # char *
        llgfr   %r3,%r3                 # unsigned long
        jg      sys_getcwd              # branch to system call
 
-       .globl  sys32_capget_wrapper 
+       .globl  sys32_capget_wrapper
 sys32_capget_wrapper:
        llgtr   %r2,%r2                 # cap_user_header_t
        llgtr   %r3,%r3                 # cap_user_data_t
        jg      sys_capget              # branch to system call
 
-       .globl  sys32_capset_wrapper 
+       .globl  sys32_capset_wrapper
 sys32_capset_wrapper:
        llgtr   %r2,%r2                 # cap_user_header_t
        llgtr   %r3,%r3                 # const cap_user_data_t
@@ -910,11 +910,11 @@ sys32_capset_wrapper:
 
        .globl sys32_sigaltstack_wrapper
 sys32_sigaltstack_wrapper:
-       llgtr   %r2,%r2                 # const stack_emu31_t * 
-       llgtr   %r3,%r3                 # stack_emu31_t * 
+       llgtr   %r2,%r2                 # const stack_emu31_t *
+       llgtr   %r3,%r3                 # stack_emu31_t *
        jg      sys32_sigaltstack
 
-       .globl  sys32_sendfile_wrapper 
+       .globl  sys32_sendfile_wrapper
 sys32_sendfile_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
@@ -922,33 +922,33 @@ sys32_sendfile_wrapper:
        llgfr   %r5,%r5                 # size_t
        jg      sys32_sendfile          # branch to system call
 
-#sys32_vfork_wrapper                   # done in vfork_glue 
+#sys32_vfork_wrapper                   # done in vfork_glue
 
-       .globl  sys32_truncate64_wrapper 
+       .globl  sys32_truncate64_wrapper
 sys32_truncate64_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
        jg      sys32_truncate64        # branch to system call
 
-       .globl  sys32_ftruncate64_wrapper 
+       .globl  sys32_ftruncate64_wrapper
 sys32_ftruncate64_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
        jg      sys32_ftruncate64       # branch to system call
 
-       .globl sys32_lchown_wrapper     
+       .globl sys32_lchown_wrapper
 sys32_lchown_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_lchown              # branch to system call
 
-#sys32_getuid_wrapper                  # void                   
-#sys32_getgid_wrapper                  # void 
-#sys32_geteuid_wrapper                 # void 
-#sys32_getegid_wrapper                 # void 
+#sys32_getuid_wrapper                  # void
+#sys32_getgid_wrapper                  # void
+#sys32_geteuid_wrapper                 # void
+#sys32_getegid_wrapper                 # void
 
        .globl sys32_setreuid_wrapper
 sys32_setreuid_wrapper:
@@ -962,111 +962,111 @@ sys32_setregid_wrapper:
        llgfr   %r3,%r3                 # gid_t
        jg      sys_setregid            # branch to system call
 
-       .globl  sys32_getgroups_wrapper 
+       .globl  sys32_getgroups_wrapper
 sys32_getgroups_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # gid_t *
        jg      sys_getgroups           # branch to system call
 
-       .globl  sys32_setgroups_wrapper 
+       .globl  sys32_setgroups_wrapper
 sys32_setgroups_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # gid_t *
        jg      sys_setgroups           # branch to system call
 
-       .globl sys32_fchown_wrapper     
+       .globl sys32_fchown_wrapper
 sys32_fchown_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_fchown              # branch to system call
 
-       .globl sys32_setresuid_wrapper  
+       .globl sys32_setresuid_wrapper
 sys32_setresuid_wrapper:
        llgfr   %r2,%r2                 # uid_t
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # uid_t
        jg      sys_setresuid           # branch to system call
 
-       .globl sys32_getresuid_wrapper  
+       .globl sys32_getresuid_wrapper
 sys32_getresuid_wrapper:
        llgtr   %r2,%r2                 # uid_t *
        llgtr   %r3,%r3                 # uid_t *
        llgtr   %r4,%r4                 # uid_t *
        jg      sys_getresuid           # branch to system call
 
-       .globl sys32_setresgid_wrapper  
+       .globl sys32_setresgid_wrapper
 sys32_setresgid_wrapper:
        llgfr   %r2,%r2                 # gid_t
        llgfr   %r3,%r3                 # gid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_setresgid           # branch to system call
 
-       .globl sys32_getresgid_wrapper  
+       .globl sys32_getresgid_wrapper
 sys32_getresgid_wrapper:
        llgtr   %r2,%r2                 # gid_t *
        llgtr   %r3,%r3                 # gid_t *
        llgtr   %r4,%r4                 # gid_t *
        jg      sys_getresgid           # branch to system call
 
-       .globl sys32_chown_wrapper      
+       .globl sys32_chown_wrapper
 sys32_chown_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_chown               # branch to system call
 
-       .globl sys32_setuid_wrapper     
+       .globl sys32_setuid_wrapper
 sys32_setuid_wrapper:
        llgfr   %r2,%r2                 # uid_t
        jg      sys_setuid              # branch to system call
 
-       .globl sys32_setgid_wrapper     
+       .globl sys32_setgid_wrapper
 sys32_setgid_wrapper:
        llgfr   %r2,%r2                 # gid_t
        jg      sys_setgid              # branch to system call
 
-       .globl sys32_setfsuid_wrapper   
+       .globl sys32_setfsuid_wrapper
 sys32_setfsuid_wrapper:
        llgfr   %r2,%r2                 # uid_t
        jg      sys_setfsuid            # branch to system call
 
-       .globl sys32_setfsgid_wrapper   
+       .globl sys32_setfsgid_wrapper
 sys32_setfsgid_wrapper:
        llgfr   %r2,%r2                 # gid_t
        jg      sys_setfsgid            # branch to system call
 
-       .globl  sys32_pivot_root_wrapper 
+       .globl  sys32_pivot_root_wrapper
 sys32_pivot_root_wrapper:
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_pivot_root          # branch to system call
 
-       .globl  sys32_mincore_wrapper 
+       .globl  sys32_mincore_wrapper
 sys32_mincore_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        llgtr   %r4,%r4                 # unsigned char *
        jg      sys_mincore             # branch to system call
 
-       .globl  sys32_madvise_wrapper 
+       .globl  sys32_madvise_wrapper
 sys32_madvise_wrapper:
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        lgfr    %r4,%r4                 # int
        jg      sys_madvise             # branch to system call
 
-       .globl  sys32_getdents64_wrapper 
+       .globl  sys32_getdents64_wrapper
 sys32_getdents64_wrapper:
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # void *
        llgfr   %r4,%r4                 # unsigned int
        jg      sys_getdents64          # branch to system call
 
-       .globl  compat_sys_fcntl64_wrapper 
+       .globl  compat_sys_fcntl64_wrapper
 compat_sys_fcntl64_wrapper:
        llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int 
+       llgfr   %r3,%r3                 # unsigned int
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_fcntl64      # branch to system call
 
@@ -1087,10 +1087,10 @@ sys32_stime_wrapper:
        llgtr   %r2,%r2                 # long *
        jg      compat_sys_stime        # branch to system call
 
-       .globl  sys32_sysctl_wrapper
+       .globl  sys32_sysctl_wrapper
 sys32_sysctl_wrapper:
-       llgtr   %r2,%r2                 # struct __sysctl_args32 *
-       jg      sys32_sysctl
+       llgtr   %r2,%r2                 # struct __sysctl_args32 *
+       jg      sys32_sysctl
 
        .globl  sys32_fstat64_wrapper
 sys32_fstat64_wrapper:
@@ -1098,7 +1098,7 @@ sys32_fstat64_wrapper:
        llgtr   %r3,%r3                 # struct stat64 *
        jg      sys32_fstat64           # branch to system call
 
-       .globl  compat_sys_futex_wrapper 
+       .globl  compat_sys_futex_wrapper
 compat_sys_futex_wrapper:
        llgtr   %r2,%r2                 # u32 *
        lgfr    %r3,%r3                 # int
@@ -1213,22 +1213,22 @@ sys32_sched_getaffinity_wrapper:
        llgtr   %r4,%r4                 # unsigned long *
        jg      compat_sys_sched_getaffinity
 
-       .globl  sys32_exit_group_wrapper
+       .globl  sys32_exit_group_wrapper
 sys32_exit_group_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_exit_group          # branch to system call
 
-       .globl  sys32_set_tid_address_wrapper
+       .globl  sys32_set_tid_address_wrapper
 sys32_set_tid_address_wrapper:
        llgtr   %r2,%r2                 # int *
        jg      sys_set_tid_address     # branch to system call
 
-       .globl  sys_epoll_create_wrapper
+       .globl  sys_epoll_create_wrapper
 sys_epoll_create_wrapper:
        lgfr    %r2,%r2                 # int
        jg      sys_epoll_create        # branch to system call
 
-       .globl  sys_epoll_ctl_wrapper
+       .globl  sys_epoll_ctl_wrapper
 sys_epoll_ctl_wrapper:
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
@@ -1236,7 +1236,7 @@ sys_epoll_ctl_wrapper:
        llgtr   %r5,%r5                 # struct epoll_event *
        jg      sys_epoll_ctl           # branch to system call
 
-       .globl  sys_epoll_wait_wrapper
+       .globl  sys_epoll_wait_wrapper
 sys_epoll_wait_wrapper:
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct epoll_event *
index 4ef44e536b2c6495a7ff5e05c4f7e5d444d40042..1eae74e72f9525f91a11f56a012f815582157500 100644 (file)
@@ -25,11 +25,8 @@ static char cpcmd_buf[241];
  */
 int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
-       const int mask = 0x40000000L;
-       unsigned long flags;
-       int return_code;
-       int return_len;
-       int cmdlen;
+       unsigned long flags, cmdlen;
+       int return_code, return_len;
 
        spin_lock_irqsave(&cpcmd_lock, flags);
        cmdlen = strlen(cmd);
@@ -38,64 +35,44 @@ int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
        ASCEBC(cpcmd_buf, cmdlen);
 
        if (response != NULL && rlen > 0) {
+               register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+               register unsigned long reg3 asm ("3") = (addr_t) response;
+               register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
+               register unsigned long reg5 asm ("5") = rlen;
+
                memset(response, 0, rlen);
+               asm volatile(
 #ifndef CONFIG_64BIT
-               asm volatile (  "lra    2,0(%2)\n"
-                               "lr     4,%3\n"
-                               "o      4,%6\n"
-                               "lra    3,0(%4)\n"
-                               "lr     5,%5\n"
-                               "diag   2,4,0x8\n"
-                               "brc    8, 1f\n"
-                               "ar     5, %5\n"
-                               "1: \n"
-                               "lr     %0,4\n"
-                               "lr     %1,5\n"
-                               : "=d" (return_code), "=d" (return_len)
-                               : "a" (cpcmd_buf), "d" (cmdlen),
-                               "a" (response), "d" (rlen), "m" (mask)
-                               : "cc", "2", "3", "4", "5" );
+                       "       diag    %2,%0,0x8\n"
+                       "       brc     8,1f\n"
+                       "       ar      %1,%4\n"
 #else /* CONFIG_64BIT */
-                asm volatile ( "lrag   2,0(%2)\n"
-                               "lgr    4,%3\n"
-                               "o      4,%6\n"
-                               "lrag   3,0(%4)\n"
-                               "lgr    5,%5\n"
-                               "sam31\n"
-                               "diag   2,4,0x8\n"
-                               "sam64\n"
-                               "brc    8, 1f\n"
-                               "agr    5, %5\n"
-                               "1: \n"
-                               "lgr    %0,4\n"
-                               "lgr    %1,5\n"
-                               : "=d" (return_code), "=d" (return_len)
-                               : "a" (cpcmd_buf), "d" (cmdlen),
-                               "a" (response), "d" (rlen), "m" (mask)
-                               : "cc", "2", "3", "4", "5" );
+                       "       sam31\n"
+                       "       diag    %2,%0,0x8\n"
+                       "       sam64\n"
+                       "       brc     8,1f\n"
+                       "       agr     %1,%4\n"
 #endif /* CONFIG_64BIT */
+                       "1:\n"
+                       : "+d" (reg4), "+d" (reg5)
+                       : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
+               return_code = (int) reg4;
+               return_len = (int) reg5;
                 EBCASC(response, rlen);
         } else {
+               register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+               register unsigned long reg3 asm ("3") = cmdlen;
                return_len = 0;
+               asm volatile(
 #ifndef CONFIG_64BIT
-                asm volatile ( "lra    2,0(%1)\n"
-                               "lr     3,%2\n"
-                               "diag   2,3,0x8\n"
-                               "lr     %0,3\n"
-                               : "=d" (return_code)
-                               : "a" (cpcmd_buf), "d" (cmdlen)
-                               : "2", "3"  );
+                       "       diag    %1,%0,0x8\n"
 #else /* CONFIG_64BIT */
-                asm volatile ( "lrag   2,0(%1)\n"
-                               "lgr    3,%2\n"
-                               "sam31\n"
-                               "diag   2,3,0x8\n"
-                               "sam64\n"
-                               "lgr    %0,3\n"
-                               : "=d" (return_code)
-                               : "a" (cpcmd_buf), "d" (cmdlen)
-                               : "2", "3" );
+                       "       sam31\n"
+                       "       diag    %1,%0,0x8\n"
+                       "       sam64\n"
 #endif /* CONFIG_64BIT */
+                       : "+d" (reg3) : "d" (reg2) : "cc");
+               return_code = (int) reg3;
         }
        spin_unlock_irqrestore(&cpcmd_lock, flags);
        if (response_code != NULL)
index 7ba20922a535d848a1de8316676d57cb5a9eb469..43f3d0c7e132372f05279073a6b60f869d2ef323 100644 (file)
@@ -603,7 +603,7 @@ debug_open(struct inode *inode, struct file *file)
        debug_info_t *debug_info, *debug_info_snapshot;
 
        down(&debug_lock);
-       debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip;
+       debug_info = file->f_dentry->d_inode->i_private;
        /* find debug view */
        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
                if (!debug_info->views[i])
index 0c712b78a7e82480f5392381c89112e8550d5da0..dddc3de304019d927bfe1cbec00b1ceb2d4ee1af 100644 (file)
@@ -4,8 +4,8 @@
  *
  *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Hartmut Penner (hp@de.ibm.com),
- *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *              Hartmut Penner (hp@de.ibm.com),
+ *              Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
  * Stack layout for the system_call stack entry.
  * The first few entries are identical to the user_regs_struct.
  */
-SP_PTREGS    =  STACK_FRAME_OVERHEAD
-SP_ARGS      =  STACK_FRAME_OVERHEAD + __PT_ARGS
-SP_PSW       =  STACK_FRAME_OVERHEAD + __PT_PSW
-SP_R0        =  STACK_FRAME_OVERHEAD + __PT_GPRS
-SP_R1        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 4
-SP_R2        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
-SP_R3        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 12
-SP_R4        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
-SP_R5        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 20
-SP_R6        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
-SP_R7        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 28
-SP_R8        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
-SP_R9        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 36
-SP_R10       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
-SP_R11       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 44
-SP_R12       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
-SP_R13       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 52
-SP_R14       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
-SP_R15       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 60
-SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
-SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
+SP_PTREGS    = STACK_FRAME_OVERHEAD
+SP_ARGS      = STACK_FRAME_OVERHEAD + __PT_ARGS
+SP_PSW      =  STACK_FRAME_OVERHEAD + __PT_PSW
+SP_R0       =  STACK_FRAME_OVERHEAD + __PT_GPRS
+SP_R1       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 4
+SP_R2       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
+SP_R3       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 12
+SP_R4       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
+SP_R5       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 20
+SP_R6       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
+SP_R7       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 28
+SP_R8       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
+SP_R9       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 36
+SP_R10      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
+SP_R11      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 44
+SP_R12      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
+SP_R13      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 52
+SP_R14      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
+SP_R15      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 60
+SP_ORIG_R2   = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
+SP_ILC      =  STACK_FRAME_OVERHEAD + __PT_ILC
+SP_TRAP      = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SIZE      = STACK_FRAME_OVERHEAD + __PT_SIZE
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
@@ -81,14 +81,14 @@ STACK_SIZE  = 1 << STACK_SHIFT
  *    R15 - kernel stack pointer
  */
 
-       .macro  STORE_TIMER lc_offset
+       .macro  STORE_TIMER lc_offset
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
        stpt    \lc_offset
 #endif
        .endm
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-       .macro  UPDATE_VTIME lc_from,lc_to,lc_sum
+       .macro  UPDATE_VTIME lc_from,lc_to,lc_sum
        lm      %r10,%r11,\lc_from
        sl      %r10,\lc_to
        sl      %r11,\lc_to+4
@@ -147,7 +147,7 @@ STACK_SIZE  = 1 << STACK_SHIFT
 2:
        .endm
 
-       .macro  CREATE_STACK_FRAME psworg,savearea
+       .macro  CREATE_STACK_FRAME psworg,savearea
        s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        mvc     SP_PSW(8,%r15),0(%r12)  # move user PSW to stack
        la      %r12,\psworg
@@ -160,7 +160,7 @@ STACK_SIZE  = 1 << STACK_SHIFT
        st      %r12,__SF_BACKCHAIN(%r15)       # clear back chain
        .endm
 
-       .macro  RESTORE_ALL psworg,sync
+       .macro  RESTORE_ALL psworg,sync
        mvc     \psworg(8),SP_PSW(%r15) # move user PSW to lowcore
        .if !\sync
        ni      \psworg+1,0xfd          # clear wait state bit
@@ -177,16 +177,16 @@ STACK_SIZE  = 1 << STACK_SHIFT
  * Returns:
  *  gpr2 = prev
  */
-        .globl  __switch_to
+       .globl  __switch_to
 __switch_to:
-        basr    %r1,0
+       basr    %r1,0
 __switch_to_base:
        tm      __THREAD_per(%r3),0xe8          # new process is using per ?
        bz      __switch_to_noper-__switch_to_base(%r1) # if not we're fine
-        stctl   %c9,%c11,__SF_EMPTY(%r15)      # We are using per stuff
-        clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
-        be      __switch_to_noper-__switch_to_base(%r1)        # we got away w/o bashing TLB's
-        lctl    %c9,%c11,__THREAD_per(%r3)     # Nope we didn't
+       stctl   %c9,%c11,__SF_EMPTY(%r15)       # We are using per stuff
+       clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
+       be      __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's
+       lctl    %c9,%c11,__THREAD_per(%r3)      # Nope we didn't
 __switch_to_noper:
        l       %r4,__THREAD_info(%r2)          # get thread_info of prev
        tm      __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
@@ -195,13 +195,13 @@ __switch_to_noper:
        l       %r4,__THREAD_info(%r3)          # get thread_info of next
        oi      __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
 __switch_to_no_mcck:
-        stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
+       stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
        st      %r15,__THREAD_ksp(%r2)  # store kernel stack to prev->tss.ksp
        l       %r15,__THREAD_ksp(%r3)  # load kernel stack from next->tss.ksp
        lm      %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
        st      %r3,__LC_CURRENT        # __LC_CURRENT = current task struct
        lctl    %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-       l       %r3,__THREAD_info(%r3)  # load thread_info from task struct
+       l       %r3,__THREAD_info(%r3)  # load thread_info from task struct
        st      %r3,__LC_THREAD_INFO
        ahi     %r3,STACK_SIZE
        st      %r3,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
@@ -213,7 +213,7 @@ __critical_start:
  * are executed with interrupts enabled.
  */
 
-       .globl  system_call
+       .globl  system_call
 system_call:
        STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
@@ -233,24 +233,24 @@ sysc_update:
 #endif
 sysc_do_svc:
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-       sla     %r7,2             # *4 and test for svc 0
-       bnz     BASED(sysc_nr_ok) # svc number > 0
+       sla     %r7,2                   # *4 and test for svc 0
+       bnz     BASED(sysc_nr_ok)       # svc number > 0
        # svc 0: system call number in %r1
        cl      %r1,BASED(.Lnr_syscalls)
        bnl     BASED(sysc_nr_ok)
-       lr      %r7,%r1           # copy svc number to %r7
-       sla     %r7,2             # *4
+       lr      %r7,%r1           # copy svc number to %r7
+       sla     %r7,2             # *4
 sysc_nr_ok:
        mvc     SP_ARGS(4,%r15),SP_R7(%r15)
 sysc_do_restart:
        l       %r8,BASED(.Lsysc_table)
        tm      __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
        l       %r8,0(%r7,%r8)    # get system call addr.
-        bnz     BASED(sysc_tracesys)
-        basr    %r14,%r8          # call sys_xxxx
-        st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
-                                  # ATTENTION: check sys_execve_glue before
-                                  # changing anything here !!
+       bnz     BASED(sysc_tracesys)
+       basr    %r14,%r8          # call sys_xxxx
+       st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
+                                 # ATTENTION: check sys_execve_glue before
+                                 # changing anything here !!
 
 sysc_return:
        tm      SP_PSW+1(%r15),0x01     # returning to user ?
@@ -258,14 +258,14 @@ sysc_return:
        tm      __TI_flags+3(%r9),_TIF_WORK_SVC
        bnz     BASED(sysc_work)  # there is work to do (signals etc.)
 sysc_leave:
-        RESTORE_ALL __LC_RETURN_PSW,1
+       RESTORE_ALL __LC_RETURN_PSW,1
 
 #
 # recheck if there is more work to do
 #
 sysc_work_loop:
        tm      __TI_flags+3(%r9),_TIF_WORK_SVC
-       bz      BASED(sysc_leave)      # there is no work to do
+       bz      BASED(sysc_leave)       # there is no work to do
 #
 # One of the work bits is on. Find out which one.
 #
@@ -284,11 +284,11 @@ sysc_work:
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#      
-sysc_reschedule:        
-        l       %r1,BASED(.Lschedule)
-       la      %r14,BASED(sysc_work_loop)
-       br      %r1                    # call scheduler
+#
+sysc_reschedule:
+       l       %r1,BASED(.Lschedule)
+       la      %r14,BASED(sysc_work_loop)
+       br      %r1                     # call scheduler
 
 #
 # _TIF_MCCK_PENDING is set, call handler
@@ -301,11 +301,11 @@ sysc_mcck_pending:
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-sysc_sigpending:     
+sysc_sigpending:
        ni      __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Ldo_signal)
-       basr    %r14,%r1               # call do_signal
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       l       %r1,BASED(.Ldo_signal)
+       basr    %r14,%r1                # call do_signal
        tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
        bo      BASED(sysc_restart)
        tm      __TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -317,11 +317,11 @@ sysc_sigpending:
 #
 sysc_restart:
        ni      __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-       l       %r7,SP_R2(%r15)        # load new svc number
+       l       %r7,SP_R2(%r15)         # load new svc number
        sla     %r7,2
        mvc     SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
-       lm      %r2,%r6,SP_R2(%r15)    # load svc arguments
-       b       BASED(sysc_do_restart) # restart svc
+       lm      %r2,%r6,SP_R2(%r15)     # load svc arguments
+       b       BASED(sysc_do_restart)  # restart svc
 
 #
 # _TIF_SINGLE_STEP is set, call do_single_step
@@ -338,8 +338,8 @@ sysc_singlestep:
 # call trace before and after sys_call
 #
 sysc_tracesys:
-        l       %r1,BASED(.Ltrace)
-       la      %r2,SP_PTREGS(%r15)    # load pt_regs
+       l       %r1,BASED(.Ltrace)
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        la      %r3,0
        srl     %r7,2
        st      %r7,SP_R2(%r15)
@@ -347,19 +347,19 @@ sysc_tracesys:
        clc     SP_R2(4,%r15),BASED(.Lnr_syscalls)
        bnl     BASED(sysc_tracenogo)
        l       %r8,BASED(.Lsysc_table)
-       l       %r7,SP_R2(%r15)        # strace might have changed the 
-       sll     %r7,2                  #  system call
+       l       %r7,SP_R2(%r15)         # strace might have changed the
+       sll     %r7,2                   #  system call
        l       %r8,0(%r7,%r8)
 sysc_tracego:
        lm      %r3,%r6,SP_R3(%r15)
        l       %r2,SP_ORIG_R2(%r15)
-       basr    %r14,%r8          # call sys_xxx
-       st      %r2,SP_R2(%r15)   # store return value
+       basr    %r14,%r8                # call sys_xxx
+       st      %r2,SP_R2(%r15)         # store return value
 sysc_tracenogo:
        tm      __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
-        bz      BASED(sysc_return)
+       bz      BASED(sysc_return)
        l       %r1,BASED(.Ltrace)
-       la      %r2,SP_PTREGS(%r15)    # load pt_regs
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        la      %r3,1
        la      %r14,BASED(sysc_return)
        br      %r1
@@ -367,17 +367,17 @@ sysc_tracenogo:
 #
 # a new process exits the kernel with ret_from_fork
 #
-        .globl  ret_from_fork
+       .globl  ret_from_fork
 ret_from_fork:
        l       %r13,__LC_SVC_NEW_PSW+4
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # forking a kernel thread ?
        bo      BASED(0f)
        st      %r15,SP_R15(%r15)       # store stack pointer for new kthread
-0:     l       %r1,BASED(.Lschedtail)
-       basr    %r14,%r1
+0:     l       %r1,BASED(.Lschedtail)
+       basr    %r14,%r1
        TRACE_IRQS_ON
-        stosm   __SF_EMPTY(%r15),0x03     # reenable interrupts
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        b       BASED(sysc_return)
 
 #
@@ -386,52 +386,51 @@ ret_from_fork:
 # but are called with different parameter.
 # return-address is set up above
 #
-sys_clone_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Lclone)
-        br      %r1                   # branch to sys_clone
-
-sys_fork_glue:  
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Lfork)
-        br      %r1                   # branch to sys_fork
-
-sys_vfork_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Lvfork)
-        br      %r1                   # branch to sys_vfork
-
-sys_execve_glue:        
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs
-        l       %r1,BASED(.Lexecve)
-       lr      %r12,%r14             # save return address
-        basr    %r14,%r1              # call sys_execve
-        ltr     %r2,%r2               # check if execve failed
-        bnz     0(%r12)               # it did fail -> store result in gpr2
-        b       4(%r12)               # SKIP ST 2,SP_R2(15) after BASR 14,8
-                                      # in system_call/sysc_tracesys
-
-sys_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,BASED(.Lsigreturn)
-        br      %r1                   # branch to sys_sigreturn
-
-sys_rt_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,BASED(.Lrt_sigreturn)
-        br      %r1                   # branch to sys_sigreturn
+sys_clone_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       l       %r1,BASED(.Lclone)
+       br      %r1                     # branch to sys_clone
 
-sys_sigaltstack_glue:
-        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,BASED(.Lsigaltstack)
-        br      %r1                   # branch to sys_sigreturn
+sys_fork_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       l       %r1,BASED(.Lfork)
+       br      %r1                     # branch to sys_fork
 
+sys_vfork_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       l       %r1,BASED(.Lvfork)
+       br      %r1                     # branch to sys_vfork
+
+sys_execve_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       l       %r1,BASED(.Lexecve)
+       lr      %r12,%r14               # save return address
+       basr    %r14,%r1                # call sys_execve
+       ltr     %r2,%r2                 # check if execve failed
+       bnz     0(%r12)                 # it did fail -> store result in gpr2
+       b       4(%r12)                 # SKIP ST 2,SP_R2(15) after BASR 14,8
+                                       # in system_call/sysc_tracesys
+
+sys_sigreturn_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs as parameter
+       l       %r1,BASED(.Lsigreturn)
+       br      %r1                     # branch to sys_sigreturn
+
+sys_rt_sigreturn_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs as parameter
+       l       %r1,BASED(.Lrt_sigreturn)
+       br      %r1                     # branch to sys_sigreturn
+
+sys_sigaltstack_glue:
+       la      %r4,SP_PTREGS(%r15)     # load pt_regs as parameter
+       l       %r1,BASED(.Lsigaltstack)
+       br      %r1                     # branch to sys_sigreturn
 
 /*
  * Program check handler routine
  */
 
-        .globl  pgm_check_handler
+       .globl  pgm_check_handler
 pgm_check_handler:
 /*
  * First we need to check for a special case:
@@ -448,8 +447,8 @@ pgm_check_handler:
  */
        STORE_TIMER __LC_SYNC_ENTER_TIMER
        SAVE_ALL_BASE __LC_SAVE_AREA
-        tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
-        bnz     BASED(pgm_per)           # got per exception -> special case
+       tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+       bnz     BASED(pgm_per)          # got per exception -> special case
        SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
        CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -461,29 +460,29 @@ pgm_check_handler:
 pgm_no_vtime:
 #endif
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-        l       %r3,__LC_PGM_ILC         # load program interruption code
+       l       %r3,__LC_PGM_ILC        # load program interruption code
        la      %r8,0x7f
        nr      %r8,%r3
 pgm_do_call:
-        l       %r7,BASED(.Ljump_table)
-        sll     %r8,2
-        l       %r7,0(%r8,%r7)          # load address of handler routine
-        la      %r2,SP_PTREGS(%r15)     # address of register-save area
-       la      %r14,BASED(sysc_return)
-       br      %r7                      # branch to interrupt-handler
+       l       %r7,BASED(.Ljump_table)
+       sll     %r8,2
+       l       %r7,0(%r8,%r7)          # load address of handler routine
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       la      %r14,BASED(sysc_return)
+       br      %r7                     # branch to interrupt-handler
 
 #
 # handle per exception
 #
 pgm_per:
-        tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
-        bnz     BASED(pgm_per_std)       # ok, normal per event from user space
+       tm      __LC_PGM_OLD_PSW,0x40   # test if per event recording is on
+       bnz     BASED(pgm_per_std)      # ok, normal per event from user space
 # ok its one of the special cases, now we need to find out which one
-        clc     __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
-        be      BASED(pgm_svcper)
+       clc     __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
+       be      BASED(pgm_svcper)
 # no interesting special case, ignore PER event
-        lm      %r12,%r15,__LC_SAVE_AREA
-       lpsw    0x28
+       lm      %r12,%r15,__LC_SAVE_AREA
+       lpsw    0x28
 
 #
 # Normal per exception
@@ -507,10 +506,10 @@ pgm_no_vtime2:
        oi      __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
        tm      SP_PSW+1(%r15),0x01     # kernel per event ?
        bz      BASED(kernel_per)
-       l       %r3,__LC_PGM_ILC         # load program interruption code
+       l       %r3,__LC_PGM_ILC        # load program interruption code
        la      %r8,0x7f
-       nr      %r8,%r3                  # clear per-event-bit and ilc
-       be      BASED(sysc_return)       # only per or per+check ?
+       nr      %r8,%r3                 # clear per-event-bit and ilc
+       be      BASED(sysc_return)      # only per or per+check ?
        b       BASED(pgm_do_call)
 
 #
@@ -552,7 +551,7 @@ kernel_per:
  * IO interrupt handler routine
  */
 
-        .globl io_int_handler
+       .globl io_int_handler
 io_int_handler:
        STORE_TIMER __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
@@ -569,42 +568,42 @@ io_no_vtime:
 #endif
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        TRACE_IRQS_OFF
-        l       %r1,BASED(.Ldo_IRQ)        # load address of do_IRQ
-        la      %r2,SP_PTREGS(%r15) # address of register-save area
-        basr    %r14,%r1          # branch to standard irq handler
+       l       %r1,BASED(.Ldo_IRQ)     # load address of do_IRQ
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       basr    %r14,%r1                # branch to standard irq handler
        TRACE_IRQS_ON
 
 io_return:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
 #ifdef CONFIG_PREEMPT
-       bno     BASED(io_preempt)      # no -> check for preemptive scheduling
+       bno     BASED(io_preempt)       # no -> check for preemptive scheduling
 #else
-        bno     BASED(io_leave)        # no-> skip resched & signal
+       bno     BASED(io_leave)         # no-> skip resched & signal
 #endif
        tm      __TI_flags+3(%r9),_TIF_WORK_INT
-       bnz     BASED(io_work)         # there is work to do (signals etc.)
+       bnz     BASED(io_work)          # there is work to do (signals etc.)
 io_leave:
-        RESTORE_ALL __LC_RETURN_PSW,0
+       RESTORE_ALL __LC_RETURN_PSW,0
 io_done:
 
 #ifdef CONFIG_PREEMPT
 io_preempt:
        icm     %r0,15,__TI_precount(%r9)
-       bnz     BASED(io_leave)
+       bnz     BASED(io_leave)
        l       %r1,SP_R15(%r15)
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+       xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lr      %r15,%r1
 io_resume_loop:
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bno     BASED(io_leave)
-       mvc     __TI_precount(4,%r9),BASED(.Lc_pactive)
-        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
-        l       %r1,BASED(.Lschedule)
+       mvc     __TI_precount(4,%r9),BASED(.Lc_pactive)
+       stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
+       l       %r1,BASED(.Lschedule)
        basr    %r14,%r1               # call schedule
-        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
-       xc      __TI_precount(4,%r9),__TI_precount(%r9)
+       stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
+       xc      __TI_precount(4,%r9),__TI_precount(%r9)
        b       BASED(io_resume_loop)
 #endif
 
@@ -615,16 +614,16 @@ io_work:
        l       %r1,__LC_KERNEL_STACK
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+       xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lr      %r15,%r1
 #
 # One of the work bits is on. Find out which one.
 # Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
-#              and _TIF_MCCK_PENDING
+#              and _TIF_MCCK_PENDING
 #
 io_work_loop:
        tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
-       bo      BASED(io_mcck_pending)
+       bo      BASED(io_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(io_reschedule)
        tm      __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
@@ -637,36 +636,36 @@ io_work_loop:
 io_mcck_pending:
        l       %r1,BASED(.Ls390_handle_mcck)
        la      %r14,BASED(io_work_loop)
-       br      %r1                    # TIF bit will be cleared by handler
+       br      %r1                     # TIF bit will be cleared by handler
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#      
-io_reschedule:        
-        l       %r1,BASED(.Lschedule)
-        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
-       basr    %r14,%r1               # call scheduler
-        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
+#
+io_reschedule:
+       l       %r1,BASED(.Lschedule)
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       basr    %r14,%r1                # call scheduler
+       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        tm      __TI_flags+3(%r9),_TIF_WORK_INT
-       bz      BASED(io_leave)        # there is no work to do
+       bz      BASED(io_leave)         # there is no work to do
        b       BASED(io_work_loop)
 
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-io_sigpending:     
-        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,BASED(.Ldo_signal)
-       basr    %r14,%r1               # call do_signal
-        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
+io_sigpending:
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       l       %r1,BASED(.Ldo_signal)
+       basr    %r14,%r1                # call do_signal
+       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        b       BASED(io_work_loop)
 
 /*
  * External interrupt handler routine
  */
 
-        .globl  ext_int_handler
+       .globl  ext_int_handler
 ext_int_handler:
        STORE_TIMER __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
@@ -683,8 +682,8 @@ ext_no_vtime:
 #endif
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        TRACE_IRQS_OFF
-       la      %r2,SP_PTREGS(%r15)    # address of register-save area
-       lh      %r3,__LC_EXT_INT_CODE  # get interruption code
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       lh      %r3,__LC_EXT_INT_CODE   # get interruption code
        l       %r1,BASED(.Ldo_extint)
        basr    %r14,%r1
        TRACE_IRQS_ON
@@ -696,13 +695,13 @@ __critical_end:
  * Machine check handler routines
  */
 
-        .globl mcck_int_handler
+       .globl mcck_int_handler
 mcck_int_handler:
        spt     __LC_CPU_TIMER_SAVE_AREA        # revalidate cpu timer
        lm      %r0,%r15,__LC_GPREGS_SAVE_AREA  # revalidate gprs
        SAVE_ALL_BASE __LC_SAVE_AREA+32
        la      %r12,__LC_MCK_OLD_PSW
-       tm      __LC_MCCK_CODE,0x80     # system damage?
+       tm      __LC_MCCK_CODE,0x80     # system damage?
        bo      BASED(mcck_int_main)    # yes -> rest of mcck code invalid
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
        mvc     __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER
@@ -741,7 +740,7 @@ mcck_int_main:
        l       %r15,__LC_PANIC_STACK   # load panic stack
 0:     CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-       tm      __LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
+       tm      __LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
        bno     BASED(mcck_no_vtime)    # no -> skip cleanup critical
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        bz      BASED(mcck_no_vtime)
@@ -752,14 +751,14 @@ mcck_no_vtime:
 #endif
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
-       l       %r1,BASED(.Ls390_mcck)
-       basr    %r14,%r1                # call machine check handler
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+       l       %r1,BASED(.Ls390_mcck)
+       basr    %r14,%r1                # call machine check handler
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
        bno     BASED(mcck_return)
-       l       %r1,__LC_KERNEL_STACK   # switch to kernel stack
+       l       %r1,__LC_KERNEL_STACK   # switch to kernel stack
        s       %r1,BASED(.Lc_spsize)
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-       xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+       xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lr      %r15,%r1
        stosm   __SF_EMPTY(%r15),0x04   # turn dat on
        tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
@@ -783,36 +782,36 @@ mcck_return:
        lm      %r0,%r15,SP_R0(%r15)    # load gprs 0-15
        lpsw    __LC_RETURN_MCCK_PSW    # back to caller
 
-        RESTORE_ALL __LC_RETURN_MCCK_PSW,0
+       RESTORE_ALL __LC_RETURN_MCCK_PSW,0
 
 #ifdef CONFIG_SMP
 /*
  * Restart interruption handler, kick starter for additional CPUs
  */
-        .globl restart_int_handler
+       .globl restart_int_handler
 restart_int_handler:
-        l       %r15,__LC_SAVE_AREA+60 # load ksp
-        lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
-        lam     %a0,%a15,__LC_AREGS_SAVE_AREA
-        lm      %r6,%r15,__SF_GPRS(%r15) # load registers from clone
-        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
-        basr    %r14,0
-        l       %r14,restart_addr-.(%r14)
-        br      %r14                   # branch to start_secondary
+       l       %r15,__LC_SAVE_AREA+60  # load ksp
+       lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
+       lam     %a0,%a15,__LC_AREGS_SAVE_AREA
+       lm      %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+       stosm   __SF_EMPTY(%r15),0x04   # now we can turn dat on
+       basr    %r14,0
+       l       %r14,restart_addr-.(%r14)
+       br      %r14                    # branch to start_secondary
 restart_addr:
-        .long   start_secondary
+       .long   start_secondary
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-        .globl restart_int_handler
+       .globl restart_int_handler
 restart_int_handler:
-        basr    %r1,0
+       basr    %r1,0
 restart_base:
-        lpsw    restart_crash-restart_base(%r1)
-        .align 8
+       lpsw    restart_crash-restart_base(%r1)
+       .align  8
 restart_crash:
-        .long  0x000a0000,0x00000000
+       .long   0x000a0000,0x00000000
 restart_go:
 #endif
 
@@ -834,11 +833,11 @@ stack_overflow:
        be      BASED(0f)
        la      %r1,__LC_SAVE_AREA+16
 0:     mvc     SP_R12(16,%r15),0(%r1)  # move %r12-%r15 to stack
-        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+       xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
        l       %r1,BASED(1f)           # branch to kernel_stack_overflow
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        br      %r1
-1:     .long  kernel_stack_overflow
+1:     .long   kernel_stack_overflow
 #endif
 
 cleanup_table_system_call:
@@ -940,10 +939,10 @@ cleanup_novtime:
 cleanup_system_call_insn:
        .long   sysc_saveall + 0x80000000
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-       .long   system_call + 0x80000000
-       .long   sysc_vtime + 0x80000000
-       .long   sysc_stime + 0x80000000
-       .long   sysc_update + 0x80000000
+       .long   system_call + 0x80000000
+       .long   sysc_vtime + 0x80000000
+       .long   sysc_stime + 0x80000000
+       .long   sysc_update + 0x80000000
 #endif
 
 cleanup_sysc_return:
@@ -1009,57 +1008,57 @@ cleanup_io_leave_insn:
 /*
  * Integer constants
  */
-               .align 4
-.Lc_spsize:    .long  SP_SIZE
-.Lc_overhead:  .long  STACK_FRAME_OVERHEAD
-.Lc_pactive:   .long  PREEMPT_ACTIVE
-.Lnr_syscalls: .long  NR_syscalls
-.L0x018:       .short 0x018
-.L0x020:       .short 0x020
-.L0x028:       .short 0x028
-.L0x030:       .short 0x030
-.L0x038:       .short 0x038
-.Lc_1:         .long  1
+               .align  4
+.Lc_spsize:    .long   SP_SIZE
+.Lc_overhead:  .long   STACK_FRAME_OVERHEAD
+.Lc_pactive:   .long   PREEMPT_ACTIVE
+.Lnr_syscalls: .long   NR_syscalls
+.L0x018:       .short  0x018
+.L0x020:       .short  0x020
+.L0x028:       .short  0x028
+.L0x030:       .short  0x030
+.L0x038:       .short  0x038
+.Lc_1:         .long   1
 
 /*
  * Symbol constants
  */
-.Ls390_mcck:   .long  s390_do_machine_check
+.Ls390_mcck:   .long   s390_do_machine_check
 .Ls390_handle_mcck:
-              .long  s390_handle_mcck
-.Lmck_old_psw: .long  __LC_MCK_OLD_PSW
-.Ldo_IRQ:      .long  do_IRQ
-.Ldo_extint:   .long  do_extint
-.Ldo_signal:   .long  do_signal
-.Lhandle_per:  .long  do_single_step
-.Ljump_table:  .long  pgm_check_table
-.Lschedule:    .long  schedule
-.Lclone:       .long  sys_clone
-.Lexecve:      .long  sys_execve
-.Lfork:        .long  sys_fork
-.Lrt_sigreturn:.long  sys_rt_sigreturn
+               .long   s390_handle_mcck
+.Lmck_old_psw: .long   __LC_MCK_OLD_PSW
+.Ldo_IRQ:      .long   do_IRQ
+.Ldo_extint:   .long   do_extint
+.Ldo_signal:   .long   do_signal
+.Lhandle_per:  .long   do_single_step
+.Ljump_table:  .long   pgm_check_table
+.Lschedule:    .long   schedule
+.Lclone:       .long   sys_clone
+.Lexecve:      .long   sys_execve
+.Lfork:        .long   sys_fork
+.Lrt_sigreturn: .long  sys_rt_sigreturn
 .Lrt_sigsuspend:
-               .long  sys_rt_sigsuspend
-.Lsigreturn:   .long  sys_sigreturn
-.Lsigsuspend:  .long  sys_sigsuspend
-.Lsigaltstack: .long  sys_sigaltstack
-.Ltrace:       .long  syscall_trace
-.Lvfork:       .long  sys_vfork
-.Lschedtail:   .long  schedule_tail
-.Lsysc_table:  .long  sys_call_table
+               .long   sys_rt_sigsuspend
+.Lsigreturn:   .long   sys_sigreturn
+.Lsigsuspend:  .long   sys_sigsuspend
+.Lsigaltstack: .long   sys_sigaltstack
+.Ltrace:       .long   syscall_trace
+.Lvfork:       .long   sys_vfork
+.Lschedtail:   .long   schedule_tail
+.Lsysc_table:  .long   sys_call_table
 #ifdef CONFIG_TRACE_IRQFLAGS
-.Ltrace_irq_on:.long  trace_hardirqs_on
+.Ltrace_irq_on: .long  trace_hardirqs_on
 .Ltrace_irq_off:
-              .long  trace_hardirqs_off
+               .long   trace_hardirqs_off
 #endif
 .Lcritical_start:
-               .long  __critical_start + 0x80000000
+               .long   __critical_start + 0x80000000
 .Lcritical_end:
-               .long  __critical_end + 0x80000000
+               .long   __critical_end + 0x80000000
 .Lcleanup_critical:
-               .long  cleanup_critical
+               .long   cleanup_critical
 
-              .section .rodata, "a"
+               .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esa
 sys_call_table:
 #include "syscalls.S"
index 29bbfbab733273d3a9b1c5f9386f8f13ff98bcf9..0f758c329a5d5b0beb9b05ed7b87db799fdd5cfe 100644 (file)
@@ -4,8 +4,8 @@
  *
  *    Copyright (C) IBM Corp. 1999,2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Hartmut Penner (hp@de.ibm.com),
- *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *              Hartmut Penner (hp@de.ibm.com),
+ *              Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
  * Stack layout for the system_call stack entry.
  * The first few entries are identical to the user_regs_struct.
  */
-SP_PTREGS    =  STACK_FRAME_OVERHEAD
-SP_ARGS      =  STACK_FRAME_OVERHEAD + __PT_ARGS
-SP_PSW       =  STACK_FRAME_OVERHEAD + __PT_PSW
-SP_R0        =  STACK_FRAME_OVERHEAD + __PT_GPRS
-SP_R1        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
-SP_R2        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
-SP_R3        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
-SP_R4        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
-SP_R5        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
-SP_R6        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
-SP_R7        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
-SP_R8        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 64
-SP_R9        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 72
-SP_R10       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 80
-SP_R11       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 88
-SP_R12       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 96
-SP_R13       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 104
-SP_R14       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 112
-SP_R15       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 120
-SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
-SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
+SP_PTREGS    = STACK_FRAME_OVERHEAD
+SP_ARGS      = STACK_FRAME_OVERHEAD + __PT_ARGS
+SP_PSW      =  STACK_FRAME_OVERHEAD + __PT_PSW
+SP_R0       =  STACK_FRAME_OVERHEAD + __PT_GPRS
+SP_R1       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
+SP_R2       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
+SP_R3       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
+SP_R4       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
+SP_R5       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
+SP_R6       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
+SP_R7       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
+SP_R8       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 64
+SP_R9       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 72
+SP_R10      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 80
+SP_R11      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 88
+SP_R12      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 96
+SP_R13      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 104
+SP_R14      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 112
+SP_R15      =  STACK_FRAME_OVERHEAD + __PT_GPRS + 120
+SP_ORIG_R2   = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
+SP_ILC      =  STACK_FRAME_OVERHEAD + __PT_ILC
+SP_TRAP      = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SIZE      = STACK_FRAME_OVERHEAD + __PT_SIZE
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -71,14 +71,14 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
 #define TRACE_IRQS_OFF
 #endif
 
-       .macro  STORE_TIMER lc_offset
+       .macro  STORE_TIMER lc_offset
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
        stpt    \lc_offset
 #endif
        .endm
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-       .macro  UPDATE_VTIME lc_from,lc_to,lc_sum
+       .macro  UPDATE_VTIME lc_from,lc_to,lc_sum
        lg      %r10,\lc_from
        slg     %r10,\lc_to
        alg     %r10,\lc_sum
@@ -94,7 +94,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
  *    R15 - kernel stack pointer
  */
 
-        .macro  SAVE_ALL_BASE savearea
+       .macro  SAVE_ALL_BASE savearea
        stmg    %r12,%r15,\savearea
        larl    %r13,system_call
        .endm
@@ -139,8 +139,8 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
        .endm
 
        .macro  CREATE_STACK_FRAME psworg,savearea
-       aghi    %r15,-SP_SIZE           # make room for registers & psw
-       mvc     SP_PSW(16,%r15),0(%r12) # move user PSW to stack
+       aghi    %r15,-SP_SIZE           # make room for registers & psw
+       mvc     SP_PSW(16,%r15),0(%r12) # move user PSW to stack
        la      %r12,\psworg
        stg     %r2,SP_ORIG_R2(%r15)    # store original content of gpr 2
        icm     %r12,12,__LC_SVC_ILC
@@ -149,7 +149,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
        mvc     SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
        la      %r12,0
        stg     %r12,__SF_BACKCHAIN(%r15)
-        .endm
+       .endm
 
        .macro  RESTORE_ALL psworg,sync
        mvc     \psworg(16),SP_PSW(%r15) # move user PSW to lowcore
@@ -168,29 +168,29 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
  * Returns:
  *  gpr2 = prev
  */
-        .globl  __switch_to
+       .globl  __switch_to
 __switch_to:
        tm      __THREAD_per+4(%r3),0xe8 # is the new process using per ?
        jz      __switch_to_noper               # if not we're fine
-        stctg   %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
-        clc     __THREAD_per(24,%r3),__SF_EMPTY(%r15)
-        je      __switch_to_noper            # we got away without bashing TLB's
-        lctlg   %c9,%c11,__THREAD_per(%r3)     # Nope we didn't
+       stctg   %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
+       clc     __THREAD_per(24,%r3),__SF_EMPTY(%r15)
+       je      __switch_to_noper            # we got away without bashing TLB's
+       lctlg   %c9,%c11,__THREAD_per(%r3)      # Nope we didn't
 __switch_to_noper:
-       lg      %r4,__THREAD_info(%r2)              # get thread_info of prev
+       lg      %r4,__THREAD_info(%r2)              # get thread_info of prev
        tm      __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
        jz      __switch_to_no_mcck
        ni      __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
        lg      %r4,__THREAD_info(%r3)              # get thread_info of next
        oi      __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
 __switch_to_no_mcck:
-        stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
+       stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
        stg     %r15,__THREAD_ksp(%r2)  # store kernel stack to prev->tss.ksp
        lg      %r15,__THREAD_ksp(%r3)  # load kernel stack from next->tss.ksp
-        lmg     %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
+       lmg     %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
        stg     %r3,__LC_CURRENT        # __LC_CURRENT = current task struct
        lctl    %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-       lg      %r3,__THREAD_info(%r3)  # load thread_info from task struct
+       lg      %r3,__THREAD_info(%r3)  # load thread_info from task struct
        stg     %r3,__LC_THREAD_INFO
        aghi    %r3,STACK_SIZE
        stg     %r3,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
@@ -202,14 +202,14 @@ __critical_start:
  * are executed with interrupts enabled.
  */
 
-       .globl  system_call
+       .globl  system_call
 system_call:
        STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
        SAVE_ALL_BASE __LC_SAVE_AREA
        SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-        CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-       llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
+       CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+       llgh    %r7,__LC_SVC_INT_CODE   # get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 sysc_vtime:
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
@@ -222,45 +222,45 @@ sysc_update:
 #endif
 sysc_do_svc:
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-        slag    %r7,%r7,2         # *4 and test for svc 0
+       slag    %r7,%r7,2       # *4 and test for svc 0
        jnz     sysc_nr_ok
        # svc 0: system call number in %r1
        cl      %r1,BASED(.Lnr_syscalls)
        jnl     sysc_nr_ok
-       lgfr    %r7,%r1           # clear high word in r1
-       slag    %r7,%r7,2         # svc 0: system call number in %r1
+       lgfr    %r7,%r1         # clear high word in r1
+       slag    %r7,%r7,2       # svc 0: system call number in %r1
 sysc_nr_ok:
        mvc     SP_ARGS(8,%r15),SP_R7(%r15)
 sysc_do_restart:
-       larl    %r10,sys_call_table
+       larl    %r10,sys_call_table
 #ifdef CONFIG_COMPAT
        tm      __TI_flags+5(%r9),(_TIF_31BIT>>16)  # running in 31 bit mode ?
        jno     sysc_noemu
-       larl    %r10,sys_call_table_emu  # use 31 bit emulation system calls
+       larl    %r10,sys_call_table_emu  # use 31 bit emulation system calls
 sysc_noemu:
 #endif
        tm      __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
-        lgf     %r8,0(%r7,%r10)   # load address of system call routine
-        jnz     sysc_tracesys
-        basr    %r14,%r8          # call sys_xxxx
-        stg     %r2,SP_R2(%r15)   # store return value (change R2 on stack)
-                                  # ATTENTION: check sys_execve_glue before
-                                  # changing anything here !!
+       lgf     %r8,0(%r7,%r10) # load address of system call routine
+       jnz     sysc_tracesys
+       basr    %r14,%r8        # call sys_xxxx
+       stg     %r2,SP_R2(%r15) # store return value (change R2 on stack)
+                               # ATTENTION: check sys_execve_glue before
+                               # changing anything here !!
 
 sysc_return:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
-        jno     sysc_leave
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+       jno     sysc_leave
        tm      __TI_flags+7(%r9),_TIF_WORK_SVC
-       jnz     sysc_work         # there is work to do (signals etc.)
+       jnz     sysc_work       # there is work to do (signals etc.)
 sysc_leave:
-        RESTORE_ALL __LC_RETURN_PSW,1
+       RESTORE_ALL __LC_RETURN_PSW,1
 
 #
 # recheck if there is more work to do
 #
 sysc_work_loop:
        tm      __TI_flags+7(%r9),_TIF_WORK_SVC
-       jz      sysc_leave        # there is no work to do
+       jz      sysc_leave        # there is no work to do
 #
 # One of the work bits is on. Find out which one.
 #
@@ -279,25 +279,25 @@ sysc_work:
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#      
-sysc_reschedule:        
-       larl    %r14,sysc_work_loop
-        jg      schedule            # return point is sysc_return
+#
+sysc_reschedule:
+       larl    %r14,sysc_work_loop
+       jg      schedule        # return point is sysc_return
 
 #
 # _TIF_MCCK_PENDING is set, call handler
 #
 sysc_mcck_pending:
        larl    %r14,sysc_work_loop
-       jg      s390_handle_mcck    # TIF bit will be cleared by handler
+       jg      s390_handle_mcck        # TIF bit will be cleared by handler
 
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-sysc_sigpending:     
+sysc_sigpending:
        ni      __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-       brasl   %r14,do_signal    # call do_signal
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       brasl   %r14,do_signal          # call do_signal
        tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
        jo      sysc_restart
        tm      __TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -309,11 +309,11 @@ sysc_sigpending:
 #
 sysc_restart:
        ni      __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
-       lg      %r7,SP_R2(%r15)        # load new svc number
-        slag    %r7,%r7,2              # *4
+       lg      %r7,SP_R2(%r15)         # load new svc number
+       slag    %r7,%r7,2               # *4
        mvc     SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
-       lmg     %r2,%r6,SP_R2(%r15)    # load svc arguments
-       j       sysc_do_restart        # restart svc
+       lmg     %r2,%r6,SP_R2(%r15)     # load svc arguments
+       j       sysc_do_restart         # restart svc
 
 #
 # _TIF_SINGLE_STEP is set, call do_single_step
@@ -326,49 +326,48 @@ sysc_singlestep:
        larl    %r14,sysc_return        # load adr. of system return
        jg      do_single_step          # branch to do_sigtrap
 
-
 #
 # call syscall_trace before and after system call
 # special linkage: %r12 contains the return address for trace_svc
 #
 sysc_tracesys:
-       la      %r2,SP_PTREGS(%r15)    # load pt_regs
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        la      %r3,0
        srl     %r7,2
-       stg     %r7,SP_R2(%r15)
-        brasl   %r14,syscall_trace
+       stg     %r7,SP_R2(%r15)
+       brasl   %r14,syscall_trace
        lghi    %r0,NR_syscalls
        clg     %r0,SP_R2(%r15)
        jnh     sysc_tracenogo
-       lg      %r7,SP_R2(%r15)   # strace might have changed the
-       sll     %r7,2              system call
+       lg      %r7,SP_R2(%r15)         # strace might have changed the
+       sll     %r7,2                   # system call
        lgf     %r8,0(%r7,%r10)
 sysc_tracego:
-       lmg     %r3,%r6,SP_R3(%r15)
-       lg      %r2,SP_ORIG_R2(%r15)
-        basr    %r14,%r8            # call sys_xxx
-        stg     %r2,SP_R2(%r15)     # store return value
+       lmg     %r3,%r6,SP_R3(%r15)
+       lg      %r2,SP_ORIG_R2(%r15)
+       basr    %r14,%r8                # call sys_xxx
+       stg     %r2,SP_R2(%r15)         # store return value
 sysc_tracenogo:
        tm      __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
-        jz      sysc_return
-       la      %r2,SP_PTREGS(%r15)    # load pt_regs
+       jz      sysc_return
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        la      %r3,1
-       larl    %r14,sysc_return    # return point is sysc_return
+       larl    %r14,sysc_return        # return point is sysc_return
        jg      syscall_trace
 
 #
 # a new process exits the kernel with ret_from_fork
 #
-        .globl  ret_from_fork
+       .globl  ret_from_fork
 ret_from_fork:
        lg      %r13,__LC_SVC_NEW_PSW+8
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # forking a kernel thread ?
        jo      0f
        stg     %r15,SP_R15(%r15)       # store stack pointer for new kthread
-0:     brasl   %r14,schedule_tail
+0:     brasl   %r14,schedule_tail
        TRACE_IRQS_ON
-        stosm   24(%r15),0x03     # reenable interrupts
+       stosm   24(%r15),0x03           # reenable interrupts
        j       sysc_return
 
 #
@@ -377,78 +376,78 @@ ret_from_fork:
 # but are called with different parameter.
 # return-address is set up above
 #
-sys_clone_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys_clone              # branch to sys_clone
+sys_clone_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       jg      sys_clone               # branch to sys_clone
 
 #ifdef CONFIG_COMPAT
-sys32_clone_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys32_clone            # branch to sys32_clone
+sys32_clone_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       jg      sys32_clone             # branch to sys32_clone
 #endif
 
-sys_fork_glue:  
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys_fork               # branch to sys_fork
-
-sys_vfork_glue: 
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        jg      sys_vfork              # branch to sys_vfork
-
-sys_execve_glue:        
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs
-       lgr     %r12,%r14             # save return address
-        brasl   %r14,sys_execve       # call sys_execve
-        ltgr    %r2,%r2               # check if execve failed
-        bnz     0(%r12)               # it did fail -> store result in gpr2
-        b       6(%r12)               # SKIP STG 2,SP_R2(15) in
-                                      # system_call/sysc_tracesys
+sys_fork_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       jg      sys_fork                # branch to sys_fork
+
+sys_vfork_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       jg      sys_vfork               # branch to sys_vfork
+
+sys_execve_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       lgr     %r12,%r14               # save return address
+       brasl   %r14,sys_execve         # call sys_execve
+       ltgr    %r2,%r2                 # check if execve failed
+       bnz     0(%r12)                 # it did fail -> store result in gpr2
+       b       6(%r12)                 # SKIP STG 2,SP_R2(15) in
+                                       # system_call/sysc_tracesys
 #ifdef CONFIG_COMPAT
-sys32_execve_glue:        
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs
-       lgr     %r12,%r14             # save return address
-        brasl   %r14,sys32_execve     # call sys32_execve
-        ltgr    %r2,%r2               # check if execve failed
-        bnz     0(%r12)               # it did fail -> store result in gpr2
-        b       6(%r12)               # SKIP STG 2,SP_R2(15) in
-                                      # system_call/sysc_tracesys
+sys32_execve_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+       lgr     %r12,%r14               # save return address
+       brasl   %r14,sys32_execve       # call sys32_execve
+       ltgr    %r2,%r2                 # check if execve failed
+       bnz     0(%r12)                 # it did fail -> store result in gpr2
+       b       6(%r12)                 # SKIP STG 2,SP_R2(15) in
+                                       # system_call/sysc_tracesys
 #endif
 
-sys_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys_sigreturn         # branch to sys_sigreturn
+sys_sigreturn_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs as parameter
+       jg      sys_sigreturn           # branch to sys_sigreturn
 
 #ifdef CONFIG_COMPAT
-sys32_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys32_sigreturn       # branch to sys32_sigreturn
+sys32_sigreturn_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs as parameter
+       jg      sys32_sigreturn         # branch to sys32_sigreturn
 #endif
 
-sys_rt_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys_rt_sigreturn      # branch to sys_sigreturn
+sys_rt_sigreturn_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs as parameter
+       jg      sys_rt_sigreturn        # branch to sys_sigreturn
 
 #ifdef CONFIG_COMPAT
-sys32_rt_sigreturn_glue:     
-        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys32_rt_sigreturn    # branch to sys32_sigreturn
+sys32_rt_sigreturn_glue:
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs as parameter
+       jg      sys32_rt_sigreturn      # branch to sys32_sigreturn
 #endif
 
 sys_sigaltstack_glue:
-        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys_sigaltstack       # branch to sys_sigreturn
+       la      %r4,SP_PTREGS(%r15)     # load pt_regs as parameter
+       jg      sys_sigaltstack         # branch to sys_sigreturn
 
 #ifdef CONFIG_COMPAT
 sys32_sigaltstack_glue:
-        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
-        jg      sys32_sigaltstack_wrapper # branch to sys_sigreturn
+       la      %r4,SP_PTREGS(%r15)     # load pt_regs as parameter
+       jg      sys32_sigaltstack_wrapper # branch to sys_sigreturn
 #endif
 
 /*
  * Program check handler routine
  */
 
-        .globl  pgm_check_handler
+       .globl  pgm_check_handler
 pgm_check_handler:
 /*
  * First we need to check for a special case:
@@ -465,8 +464,8 @@ pgm_check_handler:
  */
        STORE_TIMER __LC_SYNC_ENTER_TIMER
        SAVE_ALL_BASE __LC_SAVE_AREA
-        tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
-        jnz     pgm_per                  # got per exception -> special case
+       tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+       jnz     pgm_per                  # got per exception -> special case
        SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
        CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -478,29 +477,29 @@ pgm_check_handler:
 pgm_no_vtime:
 #endif
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-       lgf     %r3,__LC_PGM_ILC         # load program interruption code
+       lgf     %r3,__LC_PGM_ILC        # load program interruption code
        lghi    %r8,0x7f
        ngr     %r8,%r3
 pgm_do_call:
-        sll     %r8,3
-        larl    %r1,pgm_check_table
-        lg      %r1,0(%r8,%r1)          # load address of handler routine
-        la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       sll     %r8,3
+       larl    %r1,pgm_check_table
+       lg      %r1,0(%r8,%r1)          # load address of handler routine
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
        larl    %r14,sysc_return
-        br      %r1                     # branch to interrupt-handler
+       br      %r1                     # branch to interrupt-handler
 
 #
 # handle per exception
 #
 pgm_per:
-        tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
-        jnz     pgm_per_std              # ok, normal per event from user space
+       tm      __LC_PGM_OLD_PSW,0x40   # test if per event recording is on
+       jnz     pgm_per_std             # ok, normal per event from user space
 # ok its one of the special cases, now we need to find out which one
-        clc     __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
-        je      pgm_svcper
+       clc     __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
+       je      pgm_svcper
 # no interesting special case, ignore PER event
        lmg     %r12,%r15,__LC_SAVE_AREA
-       lpswe   __LC_PGM_OLD_PSW
+       lpswe   __LC_PGM_OLD_PSW
 
 #
 # Normal per exception
@@ -524,9 +523,9 @@ pgm_no_vtime2:
        mvc     __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
        mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
        oi      __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-       lgf     %r3,__LC_PGM_ILC         # load program interruption code
+       lgf     %r3,__LC_PGM_ILC        # load program interruption code
        lghi    %r8,0x7f
-       ngr     %r8,%r3                  # clear per-event-bit and ilc
+       ngr     %r8,%r3                 # clear per-event-bit and ilc
        je      sysc_return
        j       pgm_do_call
 
@@ -544,7 +543,7 @@ pgm_svcper:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime3:
 #endif
-       llgh    %r7,__LC_SVC_INT_CODE   # get svc number from lowcore
+       llgh    %r7,__LC_SVC_INT_CODE   # get svc number from lowcore
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        lg      %r1,__TI_task(%r9)
        mvc     __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
@@ -568,7 +567,7 @@ kernel_per:
 /*
  * IO interrupt handler routine
  */
-        .globl io_int_handler
+       .globl io_int_handler
 io_int_handler:
        STORE_TIMER __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
@@ -585,42 +584,42 @@ io_no_vtime:
 #endif
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        TRACE_IRQS_OFF
-        la      %r2,SP_PTREGS(%r15)    # address of register-save area
-       brasl   %r14,do_IRQ            # call standard irq handler
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       brasl   %r14,do_IRQ             # call standard irq handler
        TRACE_IRQS_ON
 
 io_return:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
 #ifdef CONFIG_PREEMPT
-       jno     io_preempt             # no -> check for preemptive scheduling
+       jno     io_preempt              # no -> check for preemptive scheduling
 #else
-        jno     io_leave               # no-> skip resched & signal
+       jno     io_leave                # no-> skip resched & signal
 #endif
        tm      __TI_flags+7(%r9),_TIF_WORK_INT
-       jnz     io_work                # there is work to do (signals etc.)
+       jnz     io_work                 # there is work to do (signals etc.)
 io_leave:
-        RESTORE_ALL __LC_RETURN_PSW,0
+       RESTORE_ALL __LC_RETURN_PSW,0
 io_done:
 
 #ifdef CONFIG_PREEMPT
 io_preempt:
-       icm     %r0,15,__TI_precount(%r9)       
-       jnz     io_leave
+       icm     %r0,15,__TI_precount(%r9)
+       jnz     io_leave
        # switch to kernel stack
        lg      %r1,SP_R15(%r15)
        aghi    %r1,-SP_SIZE
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+       xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lgr     %r15,%r1
 io_resume_loop:
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jno     io_leave
-       larl    %r1,.Lc_pactive
-       mvc     __TI_precount(4,%r9),0(%r1)
-        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
-       brasl   %r14,schedule          # call schedule
-        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
-       xc      __TI_precount(4,%r9),__TI_precount(%r9)
+       larl    %r1,.Lc_pactive
+       mvc     __TI_precount(4,%r9),0(%r1)
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       brasl   %r14,schedule           # call schedule
+       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
+       xc      __TI_precount(4,%r9),__TI_precount(%r9)
        j       io_resume_loop
 #endif
 
@@ -631,7 +630,7 @@ io_work:
        lg      %r1,__LC_KERNEL_STACK
        aghi    %r1,-SP_SIZE
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+       xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lgr     %r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -656,11 +655,11 @@ io_mcck_pending:
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
-#      
-io_reschedule:        
-       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
-       brasl   %r14,schedule           # call scheduler
-       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
+#
+io_reschedule:
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       brasl   %r14,schedule           # call scheduler
+       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        tm      __TI_flags+7(%r9),_TIF_WORK_INT
        jz      io_leave                # there is no work to do
        j       io_work_loop
@@ -668,17 +667,17 @@ io_reschedule:
 #
 # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
 #
-io_sigpending:     
-       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
-       la      %r2,SP_PTREGS(%r15)     # load pt_regs
+io_sigpending:
+       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        brasl   %r14,do_signal          # call do_signal
-       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
+       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        j       io_work_loop
 
 /*
  * External interrupt handler routine
  */
-        .globl  ext_int_handler
+       .globl  ext_int_handler
 ext_int_handler:
        STORE_TIMER __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
@@ -695,9 +694,9 @@ ext_no_vtime:
 #endif
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        TRACE_IRQS_OFF
-       la      %r2,SP_PTREGS(%r15)    # address of register-save area
-       llgh    %r3,__LC_EXT_INT_CODE  # get interruption code
-       brasl   %r14,do_extint
+       la      %r2,SP_PTREGS(%r15)     # address of register-save area
+       llgh    %r3,__LC_EXT_INT_CODE   # get interruption code
+       brasl   %r14,do_extint
        TRACE_IRQS_ON
        j       io_return
 
@@ -706,14 +705,14 @@ __critical_end:
 /*
  * Machine check handler routines
  */
-        .globl mcck_int_handler
+       .globl mcck_int_handler
 mcck_int_handler:
        la      %r1,4095                # revalidate r1
        spt     __LC_CPU_TIMER_SAVE_AREA-4095(%r1)      # revalidate cpu timer
-       lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
+       lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
        SAVE_ALL_BASE __LC_SAVE_AREA+64
        la      %r12,__LC_MCK_OLD_PSW
-       tm      __LC_MCCK_CODE,0x80     # system damage?
+       tm      __LC_MCCK_CODE,0x80     # system damage?
        jo      mcck_int_main           # yes -> rest of mcck code invalid
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
        la      %r14,4095
@@ -737,19 +736,19 @@ mcck_int_handler:
 #endif
        tm      __LC_MCCK_CODE+2,0x09   # mwp + ia of old psw valid?
        jno     mcck_int_main           # no -> skip cleanup critical
-       tm      __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+       tm      __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
        jnz     mcck_int_main           # from user -> load kernel stack
        clc     __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
        jhe     mcck_int_main
-       clc     __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
+       clc     __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
        jl      mcck_int_main
-       brasl   %r14,cleanup_critical
+       brasl   %r14,cleanup_critical
 mcck_int_main:
-       lg      %r14,__LC_PANIC_STACK   # are we already on the panic stack?
+       lg      %r14,__LC_PANIC_STACK   # are we already on the panic stack?
        slgr    %r14,%r15
        srag    %r14,%r14,PAGE_SHIFT
        jz      0f
-       lg      %r15,__LC_PANIC_STACK   # load panic stack
+       lg      %r15,__LC_PANIC_STACK   # load panic stack
 0:     CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
        tm      __LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
@@ -764,7 +763,7 @@ mcck_no_vtime:
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
        brasl   %r14,s390_do_machine_check
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
        jno     mcck_return
        lg      %r1,__LC_KERNEL_STACK   # switch to kernel stack
        aghi    %r1,-SP_SIZE
@@ -794,28 +793,28 @@ mcck_return:
 /*
  * Restart interruption handler, kick starter for additional CPUs
  */
-        .globl restart_int_handler
+       .globl restart_int_handler
 restart_int_handler:
-        lg      %r15,__LC_SAVE_AREA+120 # load ksp
-        lghi    %r10,__LC_CREGS_SAVE_AREA
-        lctlg   %c0,%c15,0(%r10) # get new ctl regs
-        lghi    %r10,__LC_AREGS_SAVE_AREA
-        lam     %a0,%a15,0(%r10)
-        lmg     %r6,%r15,__SF_GPRS(%r15) # load registers from clone
-        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
-       jg      start_secondary
+       lg      %r15,__LC_SAVE_AREA+120 # load ksp
+       lghi    %r10,__LC_CREGS_SAVE_AREA
+       lctlg   %c0,%c15,0(%r10) # get new ctl regs
+       lghi    %r10,__LC_AREGS_SAVE_AREA
+       lam     %a0,%a15,0(%r10)
+       lmg     %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+       stosm   __SF_EMPTY(%r15),0x04   # now we can turn dat on
+       jg      start_secondary
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-        .globl restart_int_handler
+       .globl restart_int_handler
 restart_int_handler:
-        basr    %r1,0
+       basr    %r1,0
 restart_base:
-        lpswe   restart_crash-restart_base(%r1)
-        .align 8
+       lpswe   restart_crash-restart_base(%r1)
+       .align 8
 restart_crash:
-        .long  0x000a0000,0x00000000,0x00000000,0x00000000
+       .long  0x000a0000,0x00000000,0x00000000,0x00000000
 restart_go:
 #endif
 
@@ -836,9 +835,9 @@ stack_overflow:
        chi     %r12,__LC_PGM_OLD_PSW
        je      0f
        la      %r1,__LC_SAVE_AREA+32
-0:     mvc     SP_R12(32,%r15),0(%r1)  # move %r12-%r15 to stack
-        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
-        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+0:     mvc     SP_R12(32,%r15),0(%r1)  # move %r12-%r15 to stack
+       xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+       la      %r2,SP_PTREGS(%r15)     # load pt_regs
        jg      kernel_stack_overflow
 #endif
 
@@ -941,10 +940,10 @@ cleanup_novtime:
 cleanup_system_call_insn:
        .quad   sysc_saveall
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-       .quad   system_call
-       .quad   sysc_vtime
-       .quad   sysc_stime
-       .quad   sysc_update
+       .quad   system_call
+       .quad   sysc_vtime
+       .quad   sysc_stime
+       .quad   sysc_update
 #endif
 
 cleanup_sysc_return:
@@ -1010,21 +1009,21 @@ cleanup_io_leave_insn:
 /*
  * Integer constants
  */
-               .align 4
+               .align  4
 .Lconst:
-.Lc_pactive:   .long  PREEMPT_ACTIVE
-.Lnr_syscalls: .long  NR_syscalls
-.L0x0130:      .short 0x130
-.L0x0140:      .short 0x140
-.L0x0150:      .short 0x150
-.L0x0160:      .short 0x160
-.L0x0170:      .short 0x170
+.Lc_pactive:   .long   PREEMPT_ACTIVE
+.Lnr_syscalls: .long   NR_syscalls
+.L0x0130:      .short  0x130
+.L0x0140:      .short  0x140
+.L0x0150:      .short  0x150
+.L0x0160:      .short  0x160
+.L0x0170:      .short  0x170
 .Lcritical_start:
-               .quad  __critical_start
+               .quad   __critical_start
 .Lcritical_end:
-               .quad  __critical_end
+               .quad   __critical_end
 
-              .section .rodata, "a"
+               .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esame
 sys_call_table:
 #include "syscalls.S"
index 0f1db268a8a96c9d55b75dd9c270773bc13ed64d..0cf59bb7a857d40eba3ecd9445a470af6b68d68d 100644 (file)
 #endif
 
 #ifndef CONFIG_IPL
-        .org   0
-        .long  0x00080000,0x80000000+startup   # Just a restart PSW
+       .org   0
+       .long  0x00080000,0x80000000+startup    # Just a restart PSW
 #else
 #ifdef CONFIG_IPL_TAPE
 #define IPL_BS 1024
-        .org   0
-        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x27000000,0x60000001           # by ipl to addresses 0-23.
-        .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
-        .long  0x00000000,0x00000000           # external old psw
-        .long  0x00000000,0x00000000           # svc old psw
-        .long  0x00000000,0x00000000           # program check old psw
-        .long  0x00000000,0x00000000           # machine check old psw
-        .long  0x00000000,0x00000000           # io old psw
-        .long  0x00000000,0x00000000
-        .long  0x00000000,0x00000000
-        .long  0x00000000,0x00000000
-        .long  0x000a0000,0x00000058           # external new psw
-        .long  0x000a0000,0x00000060           # svc new psw
-        .long  0x000a0000,0x00000068           # program check new psw
-        .long  0x000a0000,0x00000070           # machine check new psw
-        .long  0x00080000,0x80000000+.Lioint   # io new psw
+       .org   0
+       .long  0x00080000,0x80000000+iplstart   # The first 24 bytes are loaded
+       .long  0x27000000,0x60000001            # by ipl to addresses 0-23.
+       .long  0x02000000,0x20000000+IPL_BS     # (a PSW and two CCWs).
+       .long  0x00000000,0x00000000            # external old psw
+       .long  0x00000000,0x00000000            # svc old psw
+       .long  0x00000000,0x00000000            # program check old psw
+       .long  0x00000000,0x00000000            # machine check old psw
+       .long  0x00000000,0x00000000            # io old psw
+       .long  0x00000000,0x00000000
+       .long  0x00000000,0x00000000
+       .long  0x00000000,0x00000000
+       .long  0x000a0000,0x00000058            # external new psw
+       .long  0x000a0000,0x00000060            # svc new psw
+       .long  0x000a0000,0x00000068            # program check new psw
+       .long  0x000a0000,0x00000070            # machine check new psw
+       .long  0x00080000,0x80000000+.Lioint    # io new psw
 
-        .org   0x100
+       .org   0x100
 #
 # subroutine for loading from tape
-# Paramters:   
+# Paramters:
 #  R1 = device number
 #  R2 = load address
-.Lloader:      
-        st    %r14,.Lldret
-        la    %r3,.Lorbread                    # r3 = address of orb 
-       la    %r5,.Lirb                        # r5 = address of irb
-        st    %r2,.Lccwread+4                  # initialize CCW data addresses
-        lctl  %c6,%c6,.Lcr6               
-        slr   %r2,%r2
+.Lloader:
+       st      %r14,.Lldret
+       la      %r3,.Lorbread           # r3 = address of orb
+       la      %r5,.Lirb               # r5 = address of irb
+       st      %r2,.Lccwread+4         # initialize CCW data addresses
+       lctl    %c6,%c6,.Lcr6
+       slr     %r2,%r2
 .Lldlp:
-        la    %r6,3                            # 3 retries
+       la      %r6,3                   # 3 retries
 .Lssch:
-        ssch  0(%r3)                           # load chunk of IPL_BS bytes
-        bnz   .Llderr
+       ssch    0(%r3)                  # load chunk of IPL_BS bytes
+       bnz     .Llderr
 .Lw4end:
-        bas   %r14,.Lwait4io
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Lrecov
-        slr   %r7,%r7
-        icm   %r7,3,10(%r5)                    # get residual count
-        lcr   %r7,%r7
-        la    %r7,IPL_BS(%r7)                  # IPL_BS-residual=#bytes read
-        ar    %r2,%r7                          # add to total size
-        tm    8(%r5),0x01                      # found a tape mark ?
-        bnz   .Ldone
-        l     %r0,.Lccwread+4                  # update CCW data addresses
-        ar    %r0,%r7
-        st    %r0,.Lccwread+4                
-        b     .Lldlp
+       bas     %r14,.Lwait4io
+       tm      8(%r5),0x82             # do we have a problem ?
+       bnz     .Lrecov
+       slr     %r7,%r7
+       icm     %r7,3,10(%r5)           # get residual count
+       lcr     %r7,%r7
+       la      %r7,IPL_BS(%r7)         # IPL_BS-residual=#bytes read
+       ar      %r2,%r7                 # add to total size
+       tm      8(%r5),0x01             # found a tape mark ?
+       bnz     .Ldone
+       l       %r0,.Lccwread+4         # update CCW data addresses
+       ar      %r0,%r7
+       st      %r0,.Lccwread+4
+       b       .Lldlp
 .Ldone:
-        l     %r14,.Lldret
-        br    %r14                             # r2 contains the total size
+       l       %r14,.Lldret
+       br      %r14                    # r2 contains the total size
 .Lrecov:
-        bas   %r14,.Lsense                     # do the sensing
-        bct   %r6,.Lssch                       # dec. retry count & branch
-        b     .Llderr
+       bas     %r14,.Lsense            # do the sensing
+       bct     %r6,.Lssch              # dec. retry count & branch
+       b       .Llderr
 #
 # Sense subroutine
 #
 .Lsense:
-        st    %r14,.Lsnsret
-        la    %r7,.Lorbsense              
-        ssch  0(%r7)                           # start sense command
-        bnz   .Llderr
-        bas   %r14,.Lwait4io
-        l     %r14,.Lsnsret
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Llderr
-        br    %r14
+       st      %r14,.Lsnsret
+       la      %r7,.Lorbsense
+       ssch    0(%r7)                  # start sense command
+       bnz     .Llderr
+       bas     %r14,.Lwait4io
+       l       %r14,.Lsnsret
+       tm      8(%r5),0x82             # do we have a problem ?
+       bnz     .Llderr
+       br      %r14
 #
 # Wait for interrupt subroutine
 #
 .Lwait4io:
-        lpsw  .Lwaitpsw                 
+       lpsw    .Lwaitpsw
 .Lioint:
-        c     %r1,0xb8                         # compare subchannel number
-        bne   .Lwait4io
-        tsch  0(%r5)
-        slr   %r0,%r0
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Lwtexit
-        tm    8(%r5),0x04                      # got device end ?
-        bz    .Lwait4io
+       c       %r1,0xb8                # compare subchannel number
+       bne     .Lwait4io
+       tsch    0(%r5)
+       slr     %r0,%r0
+       tm      8(%r5),0x82             # do we have a problem ?
+       bnz     .Lwtexit
+       tm      8(%r5),0x04             # got device end ?
+       bz      .Lwait4io
 .Lwtexit:
-        br    %r14
+       br      %r14
 .Llderr:
-        lpsw  .Lcrash              
+       lpsw    .Lcrash
 
-        .align 8
+       .align  8
 .Lorbread:
-       .long  0x00000000,0x0080ff00,.Lccwread
-        .align 8
+       .long   0x00000000,0x0080ff00,.Lccwread
+       .align  8
 .Lorbsense:
-        .long  0x00000000,0x0080ff00,.Lccwsense
-        .align 8
+       .long   0x00000000,0x0080ff00,.Lccwsense
+       .align  8
 .Lccwread:
-        .long  0x02200000+IPL_BS,0x00000000
+       .long   0x02200000+IPL_BS,0x00000000
 .Lccwsense:
-        .long  0x04200001,0x00000000
+       .long   0x04200001,0x00000000
 .Lwaitpsw:
-       .long  0x020a0000,0x80000000+.Lioint
+       .long   0x020a0000,0x80000000+.Lioint
 
-.Lirb: .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:  .long  0xff000000
-        .align 8
-.Lcrash:.long  0x000a0000,0x00000000
-.Lldret:.long  0
+.Lirb: .long   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6: .long   0xff000000
+       .align  8
+.Lcrash:.long  0x000a0000,0x00000000
+.Lldret:.long  0
 .Lsnsret: .long 0
-#endif  /* CONFIG_IPL_TAPE */
+#endif /* CONFIG_IPL_TAPE */
 
 #ifdef CONFIG_IPL_VM
-#define IPL_BS 0x730
-        .org   0
-        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x02000018,0x60000050           # by ipl to addresses 0-23.
-        .long  0x02000068,0x60000050           # (a PSW and two CCWs).
-        .fill  80-24,1,0x40                    # bytes 24-79 are discarded !!
-        .long  0x020000f0,0x60000050           # The next 160 byte are loaded
-        .long  0x02000140,0x60000050           # to addresses 0x18-0xb7
-        .long  0x02000190,0x60000050           # They form the continuation
-        .long  0x020001e0,0x60000050           # of the CCW program started
-        .long  0x02000230,0x60000050           # by ipl and load the range
-        .long  0x02000280,0x60000050           # 0x0f0-0x730 from the image
-        .long  0x020002d0,0x60000050           # to the range 0x0f0-0x730
-        .long  0x02000320,0x60000050           # in memory. At the end of
-        .long  0x02000370,0x60000050           # the channel program the PSW
-        .long  0x020003c0,0x60000050           # at location 0 is loaded.
-        .long  0x02000410,0x60000050           # Initial processing starts
-        .long  0x02000460,0x60000050           # at 0xf0 = iplstart.
-        .long  0x020004b0,0x60000050
-        .long  0x02000500,0x60000050
-        .long  0x02000550,0x60000050
-        .long  0x020005a0,0x60000050
-        .long  0x020005f0,0x60000050
-        .long  0x02000640,0x60000050
-        .long  0x02000690,0x60000050
-        .long  0x020006e0,0x20000050
+#define IPL_BS 0x730
+       .org    0
+       .long   0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
+       .long   0x02000018,0x60000050           # by ipl to addresses 0-23.
+       .long   0x02000068,0x60000050           # (a PSW and two CCWs).
+       .fill   80-24,1,0x40                    # bytes 24-79 are discarded !!
+       .long   0x020000f0,0x60000050           # The next 160 byte are loaded
+       .long   0x02000140,0x60000050           # to addresses 0x18-0xb7
+       .long   0x02000190,0x60000050           # They form the continuation
+       .long   0x020001e0,0x60000050           # of the CCW program started
+       .long   0x02000230,0x60000050           # by ipl and load the range
+       .long   0x02000280,0x60000050           # 0x0f0-0x730 from the image
+       .long   0x020002d0,0x60000050           # to the range 0x0f0-0x730
+       .long   0x02000320,0x60000050           # in memory. At the end of
+       .long   0x02000370,0x60000050           # the channel program the PSW
+       .long   0x020003c0,0x60000050           # at location 0 is loaded.
+       .long   0x02000410,0x60000050           # Initial processing starts
+       .long   0x02000460,0x60000050           # at 0xf0 = iplstart.
+       .long   0x020004b0,0x60000050
+       .long   0x02000500,0x60000050
+       .long   0x02000550,0x60000050
+       .long   0x020005a0,0x60000050
+       .long   0x020005f0,0x60000050
+       .long   0x02000640,0x60000050
+       .long   0x02000690,0x60000050
+       .long   0x020006e0,0x20000050
 
-        .org   0xf0
+       .org    0xf0
 #
 # subroutine for loading cards from the reader
 #
-.Lloader:      
-       la    %r3,.Lorb                        # r2 = address of orb into r2
-       la    %r5,.Lirb                        # r4 = address of irb
-        la    %r6,.Lccws              
-        la    %r7,20
+.Lloader:
+       la      %r3,.Lorb               # r2 = address of orb into r2
+       la      %r5,.Lirb               # r4 = address of irb
+       la      %r6,.Lccws
+       la      %r7,20
 .Linit:
-        st    %r2,4(%r6)                       # initialize CCW data addresses
-        la    %r2,0x50(%r2)
-        la    %r6,8(%r6)
-        bct   7,.Linit
+       st      %r2,4(%r6)              # initialize CCW data addresses
+       la      %r2,0x50(%r2)
+       la      %r6,8(%r6)
+       bct     7,.Linit
 
-        lctl  %c6,%c6,.Lcr6                    # set IO subclass mask
-       slr   %r2,%r2
+       lctl    %c6,%c6,.Lcr6           # set IO subclass mask
+       slr     %r2,%r2
 .Lldlp:
-        ssch  0(%r3)                           # load chunk of 1600 bytes
-        bnz   .Llderr
+       ssch    0(%r3)                  # load chunk of 1600 bytes
+       bnz     .Llderr
 .Lwait4irq:
-        mvc   0x78(8),.Lnewpsw                 # set up IO interrupt psw
-        lpsw  .Lwaitpsw              
+       mvc     0x78(8),.Lnewpsw        # set up IO interrupt psw
+       lpsw    .Lwaitpsw
 .Lioint:
-        c     %r1,0xb8                         # compare subchannel number
-       bne   .Lwait4irq
-       tsch  0(%r5)
+       c       %r1,0xb8                # compare subchannel number
+       bne     .Lwait4irq
+       tsch    0(%r5)
 
-       slr   %r0,%r0
-       ic    %r0,8(%r5)                       # get device status
-       chi   %r0,8                            # channel end ?
-       be    .Lcont
-       chi   %r0,12                           # channel end + device end ?
-       be    .Lcont
+       slr     %r0,%r0
+       ic      %r0,8(%r5)              # get device status
+       chi     %r0,8                   # channel end ?
+       be      .Lcont
+       chi     %r0,12                  # channel end + device end ?
+       be      .Lcont
 
-        l     %r0,4(%r5)
-        s     %r0,8(%r3)                       # r0/8 = number of ccws executed
-        mhi   %r0,10                           # *10 = number of bytes in ccws
-        lh    %r3,10(%r5)                      # get residual count
-        sr    %r0,%r3                          # #ccws*80-residual=#bytes read
-       ar    %r2,%r0
-       
-        br    %r14                             # r2 contains the total size
+       l       %r0,4(%r5)
+       s       %r0,8(%r3)              # r0/8 = number of ccws executed
+       mhi     %r0,10                  # *10 = number of bytes in ccws
+       lh      %r3,10(%r5)             # get residual count
+       sr      %r0,%r3                 # #ccws*80-residual=#bytes read
+       ar      %r2,%r0
+
+       br      %r14                    # r2 contains the total size
 
 .Lcont:
-       ahi   %r2,0x640                        # add 0x640 to total size
-        la    %r6,.Lccws             
-        la    %r7,20
+       ahi     %r2,0x640               # add 0x640 to total size
+       la      %r6,.Lccws
+       la      %r7,20
 .Lincr:
-        l     %r0,4(%r6)                       # update CCW data addresses
-        ahi   %r0,0x640
-        st    %r0,4(%r6)
-        ahi   %r6,8
-        bct   7,.Lincr
+       l       %r0,4(%r6)              # update CCW data addresses
+       ahi     %r0,0x640
+       st      %r0,4(%r6)
+       ahi     %r6,8
+       bct     7,.Lincr
 
-        b     .Lldlp
+       b       .Lldlp
 .Llderr:
-        lpsw  .Lcrash              
+       lpsw    .Lcrash
 
-        .align 8
-.Lorb: .long  0x00000000,0x0080ff00,.Lccws
-.Lirb: .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:  .long  0xff000000
-.Lloadp:.long  0,0
-        .align 8
-.Lcrash:.long  0x000a0000,0x00000000
+       .align  8
+.Lorb: .long   0x00000000,0x0080ff00,.Lccws
+.Lirb: .long   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6: .long   0xff000000
+.Lloadp:.long  0,0
+       .align  8
+.Lcrash:.long  0x000a0000,0x00000000
 .Lnewpsw:
-        .long  0x00080000,0x80000000+.Lioint
+       .long   0x00080000,0x80000000+.Lioint
 .Lwaitpsw:
-        .long  0x020a0000,0x80000000+.Lioint
+       .long   0x020a0000,0x80000000+.Lioint
 
-        .align 8
-.Lccws: .rept  19
-        .long  0x02600050,0x00000000
-        .endr
-        .long  0x02200050,0x00000000
-#endif  /* CONFIG_IPL_VM */
+       .align  8
+.Lccws: .rept  19
+       .long   0x02600050,0x00000000
+       .endr
+       .long   0x02200050,0x00000000
+#endif /* CONFIG_IPL_VM */
 
 iplstart:
-        lh    %r1,0xb8                         # test if subchannel number
-        bct   %r1,.Lnoload                     #  is valid
-       l     %r1,0xb8                         # load ipl subchannel number
-        la    %r2,IPL_BS                       # load start address
-        bas   %r14,.Lloader                    # load rest of ipl image
-        l     %r12,.Lparm                      # pointer to parameter area
-        st    %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
+       lh      %r1,0xb8                # test if subchannel number
+       bct     %r1,.Lnoload            #  is valid
+       l       %r1,0xb8                # load ipl subchannel number
+       la      %r2,IPL_BS              # load start address
+       bas     %r14,.Lloader           # load rest of ipl image
+       l       %r12,.Lparm             # pointer to parameter area
+       st      %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
 
 #
 # load parameter file from ipl device
 #
 .Lagain1:
-       l     %r2,.Linitrd                     # ramdisk loc. is temp
-        bas   %r14,.Lloader                    # load parameter file
-        ltr   %r2,%r2                          # got anything ?
-        bz    .Lnopf
-       chi   %r2,895
-       bnh   .Lnotrunc
-       la    %r2,895
+       l       %r2,.Linitrd            # ramdisk loc. is temp
+       bas     %r14,.Lloader           # load parameter file
+       ltr     %r2,%r2                 # got anything ?
+       bz      .Lnopf
+       chi     %r2,895
+       bnh     .Lnotrunc
+       la      %r2,895
 .Lnotrunc:
-       l     %r4,.Linitrd
-       clc   0(3,%r4),.L_hdr                  # if it is HDRx
-       bz    .Lagain1                         # skip dataset header
-       clc   0(3,%r4),.L_eof                  # if it is EOFx
-       bz    .Lagain1                         # skip dateset trailer
-        la    %r5,0(%r4,%r2)
-        lr    %r3,%r2
+       l       %r4,.Linitrd
+       clc     0(3,%r4),.L_hdr         # if it is HDRx
+       bz      .Lagain1                # skip dataset header
+       clc     0(3,%r4),.L_eof         # if it is EOFx
+       bz      .Lagain1                # skip dateset trailer
+       la      %r5,0(%r4,%r2)
+       lr      %r3,%r2
 .Lidebc:
-        tm    0(%r5),0x80                      # high order bit set ?
-        bo    .Ldocv                           #  yes -> convert from EBCDIC
-        ahi   %r5,-1
-        bct   %r3,.Lidebc
-        b     .Lnocv
+       tm      0(%r5),0x80             # high order bit set ?
+       bo      .Ldocv                  #  yes -> convert from EBCDIC
+       ahi     %r5,-1
+       bct     %r3,.Lidebc
+       b       .Lnocv
 .Ldocv:
-        l     %r3,.Lcvtab
-        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
-        tr    256(256,%r4),0(%r3)
-        tr    512(256,%r4),0(%r3)
-        tr    768(122,%r4),0(%r3)
-.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
-       mvc   0(256,%r3),0(%r4)
-       mvc   256(256,%r3),256(%r4)
-       mvc   512(256,%r3),512(%r4)
-       mvc   768(122,%r3),768(%r4)
-        slr   %r0,%r0
-        b     .Lcntlp
+       l       %r3,.Lcvtab
+       tr      0(256,%r4),0(%r3)       # convert parameters to ascii
+       tr      256(256,%r4),0(%r3)
+       tr      512(256,%r4),0(%r3)
+       tr      768(122,%r4),0(%r3)
+.Lnocv: la     %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
+       mvc     0(256,%r3),0(%r4)
+       mvc     256(256,%r3),256(%r4)
+       mvc     512(256,%r3),512(%r4)
+       mvc     768(122,%r3),768(%r4)
+       slr     %r0,%r0
+       b       .Lcntlp
 .Ldelspc:
-        ic    %r0,0(%r2,%r3)
-        chi   %r0,0x20                         # is it a space ?
-        be    .Lcntlp
-        ahi   %r2,1
-        b     .Leolp
+       ic      %r0,0(%r2,%r3)
+       chi     %r0,0x20                # is it a space ?
+       be      .Lcntlp
+       ahi     %r2,1
+       b       .Leolp
 .Lcntlp:
-        brct  %r2,.Ldelspc
+       brct    %r2,.Ldelspc
 .Leolp:
-        slr   %r0,%r0
-        stc   %r0,0(%r2,%r3)                   # terminate buffer
+       slr     %r0,%r0
+       stc     %r0,0(%r2,%r3)          # terminate buffer
 .Lnopf:
 
 #
 # load ramdisk from ipl device
-#      
+#
 .Lagain2:
-       l     %r2,.Linitrd                     # addr of ramdisk
-       st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
-        bas   %r14,.Lloader                    # load ramdisk
-       st    %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk
-        ltr   %r2,%r2
-        bnz   .Lrdcont
-        st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
+       l       %r2,.Linitrd            # addr of ramdisk
+       st      %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
+       bas     %r14,.Lloader           # load ramdisk
+       st      %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd
+       ltr     %r2,%r2
+       bnz     .Lrdcont
+       st      %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
 .Lrdcont:
-       l     %r2,.Linitrd
+       l       %r2,.Linitrd
 
-       clc   0(3,%r2),.L_hdr                  # skip HDRx and EOFx 
-       bz    .Lagain2
-       clc   0(3,%r2),.L_eof
-       bz    .Lagain2
+       clc     0(3,%r2),.L_hdr         # skip HDRx and EOFx
+       bz      .Lagain2
+       clc     0(3,%r2),.L_eof
+       bz      .Lagain2
 
 #ifdef CONFIG_IPL_VM
 #
 # reset files in VM reader
 #
-        stidp __LC_CPUID                       # store cpuid
-       tm    __LC_CPUID,0xff                  # running VM ?
-       bno   .Lnoreset
-        la    %r2,.Lreset              
-        lhi   %r3,26
-       diag  %r2,%r3,8
-       la    %r5,.Lirb
-       stsch 0(%r5)                           # check if irq is pending
-       tm    30(%r5),0x0f                     # by verifying if any of the
-       bnz   .Lwaitforirq                     # activity or status control
-       tm    31(%r5),0xff                     # bits is set in the schib
-       bz    .Lnoreset
+       stidp   __LC_CPUID              # store cpuid
+       tm      __LC_CPUID,0xff         # running VM ?
+       bno     .Lnoreset
+       la      %r2,.Lreset
+       lhi     %r3,26
+       diag    %r2,%r3,8
+       la      %r5,.Lirb
+       stsch   0(%r5)                  # check if irq is pending
+       tm      30(%r5),0x0f            # by verifying if any of the
+       bnz     .Lwaitforirq            # activity or status control
+       tm      31(%r5),0xff            # bits is set in the schib
+       bz      .Lnoreset
 .Lwaitforirq:
-       mvc   0x78(8),.Lrdrnewpsw              # set up IO interrupt psw
+       mvc     0x78(8),.Lrdrnewpsw     # set up IO interrupt psw
 .Lwaitrdrirq:
-       lpsw  .Lrdrwaitpsw
+       lpsw    .Lrdrwaitpsw
 .Lrdrint:
-       c     %r1,0xb8                         # compare subchannel number
-       bne   .Lwaitrdrirq
-       la    %r5,.Lirb
-       tsch  0(%r5)
+       c       %r1,0xb8                # compare subchannel number
+       bne     .Lwaitrdrirq
+       la      %r5,.Lirb
+       tsch    0(%r5)
 .Lnoreset:
-        b     .Lnoload
+       b       .Lnoload
 
-       .align 8
+       .align  8
 .Lrdrnewpsw:
-       .long  0x00080000,0x80000000+.Lrdrint
+       .long   0x00080000,0x80000000+.Lrdrint
 .Lrdrwaitpsw:
-       .long  0x020a0000,0x80000000+.Lrdrint
+       .long   0x020a0000,0x80000000+.Lrdrint
 #endif
 
 #
 # everything loaded, go for it
 #
 .Lnoload:
-        l     %r1,.Lstartup
-        br    %r1
+       l       %r1,.Lstartup
+       br      %r1
 
-.Linitrd:.long _end + 0x400000                # default address of initrd
+.Linitrd:.long _end + 0x400000         # default address of initrd
 .Lparm:        .long  PARMAREA
 .Lstartup: .long startup
-.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
-.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
-        .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
-        .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
-.L_eof: .long  0xc5d6c600       /* C'EOF' */
-.L_hdr: .long  0xc8c4d900       /* C'HDR' */
+.Lcvtab:.long  _ebcasc                 # ebcdic to ascii table
+.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
+       .byte   0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
+       .byte   0xc8,0xd6,0xd3,0xc4     # "change rdr all keep nohold"
+.L_eof: .long  0xc5d6c600       /* C'EOF' */
+.L_hdr: .long  0xc8c4d900       /* C'HDR' */
 
-#endif  /* CONFIG_IPL */
+#endif /* CONFIG_IPL */
 
 #
 # SALIPL loader support. Based on a patch by Rob van der Heij.
 # This entry point is called directly from the SALIPL loader and
 # doesn't need a builtin ipl record.
 #
-        .org  0x800
-       .globl start
+       .org    0x800
+       .globl  start
 start:
-       stm   %r0,%r15,0x07b0           # store registers
-       basr  %r12,%r0
+       stm     %r0,%r15,0x07b0         # store registers
+       basr    %r12,%r0
 .base:
-       l     %r11,.parm
-       l     %r8,.cmd                  # pointer to command buffer
+       l       %r11,.parm
+       l       %r8,.cmd                # pointer to command buffer
 
-       ltr   %r9,%r9                   # do we have SALIPL parameters?
-       bp    .sk8x8
+       ltr     %r9,%r9                 # do we have SALIPL parameters?
+       bp      .sk8x8
 
-       mvc   0(64,%r8),0x00b0          # copy saved registers
-       xc    64(240-64,%r8),0(%r8)     # remainder of buffer
-       tr    0(64,%r8),.lowcase        
-       b     .gotr
+       mvc     0(64,%r8),0x00b0        # copy saved registers
+       xc      64(240-64,%r8),0(%r8)   # remainder of buffer
+       tr      0(64,%r8),.lowcase
+       b       .gotr
 .sk8x8:
-       mvc   0(240,%r8),0(%r9)         # copy iplparms into buffer
+       mvc     0(240,%r8),0(%r9)       # copy iplparms into buffer
 .gotr:
-       l     %r10,.tbl                 # EBCDIC to ASCII table
-       tr    0(240,%r8),0(%r10)
-       stidp __LC_CPUID                # Are we running on VM maybe
-       cli   __LC_CPUID,0xff
-       bnz   .test
-       .long 0x83300060                # diag 3,0,x'0060' - storage size
-       b     .done
+       l       %r10,.tbl               # EBCDIC to ASCII table
+       tr      0(240,%r8),0(%r10)
+       stidp   __LC_CPUID              # Are we running on VM maybe
+       cli     __LC_CPUID,0xff
+       bnz     .test
+       .long   0x83300060              # diag 3,0,x'0060' - storage size
+       b       .done
 .test:
-       mvc   0x68(8),.pgmnw            # set up pgm check handler
-       l     %r2,.fourmeg
-       lr    %r3,%r2
-       bctr  %r3,%r0                   # 4M-1
-.loop:  iske  %r0,%r3
-       ar    %r3,%r2
+       mvc     0x68(8),.pgmnw          # set up pgm check handler
+       l       %r2,.fourmeg
+       lr      %r3,%r2
+       bctr    %r3,%r0                 # 4M-1
+.loop: iske    %r0,%r3
+       ar      %r3,%r2
 .pgmx:
-       sr    %r3,%r2
-       la    %r3,1(%r3)
+       sr      %r3,%r2
+       la      %r3,1(%r3)
 .done:
-        l     %r1,.memsize
-       st    %r3,ARCH_OFFSET(%r1)
-       slr   %r0,%r0
-       st    %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
-       st    %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
-       j     startup                   # continue with startup
-.tbl:  .long _ebcasc                   # translate table
-.cmd:  .long COMMAND_LINE              # address of command line buffer
-.parm: .long PARMAREA
+       l       %r1,.memsize
+       st      %r3,ARCH_OFFSET(%r1)
+       slr     %r0,%r0
+       st      %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
+       st      %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
+       j       startup                 # continue with startup
+.tbl:  .long   _ebcasc                 # translate table
+.cmd:  .long   COMMAND_LINE            # address of command line buffer
+.parm: .long   PARMAREA
 .memsize: .long memory_size
 .fourmeg: .long 0x00400000             # 4M
-.pgmnw:        .long 0x00080000,.pgmx
+.pgmnw:        .long   0x00080000,.pgmx
 .lowcase:
-       .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 
+       .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
        .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
-       .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 
+       .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
        .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
-       .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 
+       .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
        .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
-       .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 
+       .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
        .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
-       .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 
+       .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
        .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
-       .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 
+       .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
        .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
-       .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 
+       .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
        .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
-       .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 
+       .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
        .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
 
-       .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 
+       .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
        .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
-       .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 
+       .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
        .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
-       .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 
+       .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
        .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
-       .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 
+       .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
        .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
-       .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87   # .abcdefg 
+       .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87   # .abcdefg
        .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf   # hi
-       .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97   # .jklmnop
+       .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97   # .jklmnop
        .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf   # qr
        .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7   # ..stuvwx
        .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef   # yz
-       .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
+       .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
        .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
 
 #ifdef CONFIG_64BIT
index 1fa9fa1ca740a477e8c1d30d382815340a0af8bd..1b952a3664e2dc38c0e3684427ea8dc0337b54ca 100644 (file)
@@ -254,6 +254,16 @@ startup_continue:
        oi      3(%r12),0x80            # set IDTE flag
 .Lchkidte:
 
+#
+# find out if the diag 0x9c is available
+#
+       mvc     __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13)
+       stap   __LC_CPUID+4             # store cpu address
+       lh     %r1,__LC_CPUID+4
+       diag   %r1,0,0x9c               # test diag 0x9c
+       oi     2(%r12),1                # set diag9c flag
+.Lchkdiag9c:
+
        lpsw  .Lentry-.LPG1(13)         # jump to _stext in primary-space,
                                        # virtual and never return ...
        .align  8
@@ -281,6 +291,7 @@ startup_continue:
 .Lpccsp:.long  0x00080000,0x80000000 + .Lchkcsp
 .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
 .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
+.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
 .Lmemsize:.long memory_size
 .Lmchunk:.long memory_chunk
 .Lmflags:.long machine_flags
index a8bdd96494c77dcd5b694cd2619ccad9b26b5856..b30e5897cdf75af602fb380785a72a52d2dcc09c 100644 (file)
 # this is called either by the ipl loader or directly by PSW restart
 # or linload or SALIPL
 #
-       .org  0x10000
-startup:basr  %r13,0                    # get base
-.LPG0: l     %r13,0f-.LPG0(%r13)
-       b     0(%r13)
-0:     .long startup_continue
+       .org    0x10000
+startup:basr   %r13,0                  # get base
+.LPG0: l       %r13,0f-.LPG0(%r13)
+       b       0(%r13)
+0:     .long   startup_continue
 
 #
 # params at 10400 (setup.h)
 #
-       .org   PARMAREA
-       .quad                         # IPL_DEVICE
-       .quad                         # INITRD_START
-       .quad                         # INITRD_SIZE
+       .org    PARMAREA
+       .quad   0                       # IPL_DEVICE
+       .quad   0                       # INITRD_START
+       .quad   0                       # INITRD_SIZE
 
-       .org   COMMAND_LINE
-       .byte  "root=/dev/ram0 ro"
-       .byte  0
+       .org    COMMAND_LINE
+       .byte   "root=/dev/ram0 ro"
+       .byte   0
 
-       .org   0x11000
+       .org    0x11000
 
 startup_continue:
-       basr  %r13,0                     # get base
-.LPG1:  sll   %r13,1                     # remove high order bit
-        srl   %r13,1
-        lhi   %r1,1                      # mode 1 = esame
-       mvi   __LC_AR_MODE_ID,1          # set esame flag
-        slr   %r0,%r0                    # set cpuid to zero
-        sigp  %r1,%r0,0x12               # switch to esame mode
-       sam64                            # switch to 64 bit mode
-       lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
-       lg    %r12,.Lparmaddr-.LPG1(%r13)# pointer to parameter area
-                                        # move IPL device to lowcore
-        mvc   __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
+       basr    %r13,0                  # get base
+.LPG1: sll     %r13,1                  # remove high order bit
+       srl     %r13,1
+       lhi     %r1,1                   # mode 1 = esame
+       mvi     __LC_AR_MODE_ID,1       # set esame flag
+       slr     %r0,%r0                 # set cpuid to zero
+       sigp    %r1,%r0,0x12            # switch to esame mode
+       sam64                           # switch to 64 bit mode
+       lctlg   %c0,%c15,.Lctl-.LPG1(%r13)      # load control registers
+       lg      %r12,.Lparmaddr-.LPG1(%r13)     # pointer to parameter area
+                                       # move IPL device to lowcore
+       mvc     __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
 #
 # Setup stack
 #
-       larl  %r15,init_thread_union
-       lg    %r14,__TI_task(%r15)      # cache current in lowcore
-       stg   %r14,__LC_CURRENT
-       aghi  %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
-       stg   %r15,__LC_KERNEL_STACK    # set end of kernel stack
-       aghi  %r15,-160
-       xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
+       larl    %r15,init_thread_union
+       lg      %r14,__TI_task(%r15)    # cache current in lowcore
+       stg     %r14,__LC_CURRENT
+       aghi    %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
+       stg     %r15,__LC_KERNEL_STACK  # set end of kernel stack
+       aghi    %r15,-160
+       xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
 
-       brasl %r14,ipl_save_parameters
+       brasl   %r14,ipl_save_parameters
 #
 # clear bss memory
 #
-       larl  %r2,__bss_start           # start of bss segment
-        larl  %r3,_end                  # end of bss segment
-        sgr   %r3,%r2                   # length of bss
-        sgr   %r4,%r4                   #
-        sgr   %r5,%r5                   # set src,length and pad to zero
-        mvcle %r2,%r4,0                 # clear mem
-        jo    .-4                       # branch back, if not finish
+       larl    %r2,__bss_start         # start of bss segment
+       larl    %r3,_end                # end of bss segment
+       sgr     %r3,%r2                 # length of bss
+       sgr     %r4,%r4                 #
+       sgr     %r5,%r5                 # set src,length and pad to zero
+       mvcle   %r2,%r4,0               # clear mem
+       jo      .-4                     # branch back, if not finish
 
-       l     %r2,.Lrcp-.LPG1(%r13)     # Read SCP forced command word
+       l       %r2,.Lrcp-.LPG1(%r13)   # Read SCP forced command word
 .Lservicecall:
-       stosm .Lpmask-.LPG1(%r13),0x01  # authorize ext interrupts
+       stosm   .Lpmask-.LPG1(%r13),0x01        # authorize ext interrupts
 
-       stctg %r0,%r0,.Lcr-.LPG1(%r13)  # get cr0
-       la    %r1,0x200                 # set bit 22
-       og    %r1,.Lcr-.LPG1(%r13)      # or old cr0 with r1
-       stg   %r1,.Lcr-.LPG1(%r13)
-       lctlg %r0,%r0,.Lcr-.LPG1(%r13)  # load modified cr0
+       stctg   %r0,%r0,.Lcr-.LPG1(%r13)        # get cr0
+       la      %r1,0x200               # set bit 22
+       og      %r1,.Lcr-.LPG1(%r13)    # or old cr0 with r1
+       stg     %r1,.Lcr-.LPG1(%r13)
+       lctlg   %r0,%r0,.Lcr-.LPG1(%r13)        # load modified cr0
 
-       mvc   __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
-       larl  %r1,.Lsclph
-       stg   %r1,__LC_EXT_NEW_PSW+8    # set handler
+       mvc     __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
+       larl    %r1,.Lsclph
+       stg     %r1,__LC_EXT_NEW_PSW+8  # set handler
 
-       larl  %r4,.Lsccb                # %r4 is our index for sccb stuff
-       lgr   %r1,%r4                   # our sccb
-       .insn rre,0xb2200000,%r2,%r1    # service call
-       ipm   %r1
-       srl   %r1,28                    # get cc code
-       xr    %r3,%r3
-       chi   %r1,3
-       be    .Lfchunk-.LPG1(%r13)      # leave
-       chi   %r1,2
-       be    .Lservicecall-.LPG1(%r13)
-       lpswe .Lwaitsclp-.LPG1(%r13)
+       larl    %r4,.Lsccb              # %r4 is our index for sccb stuff
+       lgr     %r1,%r4                 # our sccb
+       .insn   rre,0xb2200000,%r2,%r1  # service call
+       ipm     %r1
+       srl     %r1,28                  # get cc code
+       xr      %r3,%r3
+       chi     %r1,3
+       be      .Lfchunk-.LPG1(%r13)    # leave
+       chi     %r1,2
+       be      .Lservicecall-.LPG1(%r13)
+       lpswe   .Lwaitsclp-.LPG1(%r13)
 .Lsclph:
-       lh    %r1,.Lsccbr-.Lsccb(%r4)
-       chi   %r1,0x10                  # 0x0010 is the sucess code
-       je    .Lprocsccb                # let's process the sccb
-       chi   %r1,0x1f0
-       bne   .Lfchunk-.LPG1(%r13)      # unhandled error code
-       c     %r2,.Lrcp-.LPG1(%r13)     # Did we try Read SCP forced
-       bne   .Lfchunk-.LPG1(%r13)      # if no, give up
-       l     %r2,.Lrcp2-.LPG1(%r13)    # try with Read SCP
-       b     .Lservicecall-.LPG1(%r13)
+       lh      %r1,.Lsccbr-.Lsccb(%r4)
+       chi     %r1,0x10                # 0x0010 is the sucess code
+       je      .Lprocsccb              # let's process the sccb
+       chi     %r1,0x1f0
+       bne     .Lfchunk-.LPG1(%r13)    # unhandled error code
+       c       %r2,.Lrcp-.LPG1(%r13)   # Did we try Read SCP forced
+       bne     .Lfchunk-.LPG1(%r13)    # if no, give up
+       l       %r2,.Lrcp2-.LPG1(%r13)  # try with Read SCP
+       b       .Lservicecall-.LPG1(%r13)
 .Lprocsccb:
-       lghi  %r1,0
-       icm   %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
-       jnz   .Lscnd
-       lg    %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
+       lghi    %r1,0
+       icm     %r1,3,.Lscpincr1-.Lsccb(%r4)    # use this one if != 0
+       jnz     .Lscnd
+       lg      %r1,.Lscpincr2-.Lsccb(%r4)      # otherwise use this one
 .Lscnd:
-       xr    %r3,%r3                   # same logic
-       ic    %r3,.Lscpa1-.Lsccb(%r4)
-       chi   %r3,0x00
-       jne   .Lcompmem
-       l     %r3,.Lscpa2-.Lsccb(%r4)
+       xr      %r3,%r3                 # same logic
+       ic      %r3,.Lscpa1-.Lsccb(%r4)
+       chi     %r3,0x00
+       jne     .Lcompmem
+       l       %r3,.Lscpa2-.Lsccb(%r4)
 .Lcompmem:
-       mlgr  %r2,%r1                   # mem in MB on 128-bit
-       l     %r1,.Lonemb-.LPG1(%r13)
-       mlgr  %r2,%r1                   # mem size in bytes in %r3
-       b     .Lfchunk-.LPG1(%r13)
+       mlgr    %r2,%r1                 # mem in MB on 128-bit
+       l       %r1,.Lonemb-.LPG1(%r13)
+       mlgr    %r2,%r1                 # mem size in bytes in %r3
+       b       .Lfchunk-.LPG1(%r13)
 
-       .align 4
+       .align  4
 .Lpmask:
-       .byte 0
-       .align 8
+       .byte   0
+       .align  8
 .Lcr:
-       .quad 0x00  # place holder for cr0
+       .quad   0x00  # place holder for cr0
 .Lwaitsclp:
-       .quad  0x0102000180000000,.Lsclph
+       .quad   0x0102000180000000,.Lsclph
 .Lrcp:
-       .int 0x00120001 # Read SCP forced code
+       .int    0x00120001 # Read SCP forced code
 .Lrcp2:
-       .int 0x00020001 # Read SCP code
+       .int    0x00020001 # Read SCP code
 .Lonemb:
-       .int 0x100000
+       .int    0x100000
 
 .Lfchunk:
-                                        # set program check new psw mask
-       mvc   __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
+                                       # set program check new psw mask
+       mvc     __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
 
 #
 # find memory chunks.
 #
-       lgr   %r9,%r3                    # end of mem
-       larl  %r1,.Lchkmem               # set program check address
-       stg   %r1,__LC_PGM_NEW_PSW+8
-       la    %r1,1                      # test in increments of 128KB
-       sllg  %r1,%r1,17
-       larl  %r3,memory_chunk
-       slgr  %r4,%r4                    # set start of chunk to zero
-       slgr  %r5,%r5                    # set end of chunk to zero
-       slr  %r6,%r6                     # set access code to zero
-       la    %r10,MEMORY_CHUNKS         # number of chunks
+       lgr     %r9,%r3                 # end of mem
+       larl    %r1,.Lchkmem            # set program check address
+       stg     %r1,__LC_PGM_NEW_PSW+8
+       la      %r1,1                   # test in increments of 128KB
+       sllg    %r1,%r1,17
+       larl    %r3,memory_chunk
+       slgr    %r4,%r4                 # set start of chunk to zero
+       slgr    %r5,%r5                 # set end of chunk to zero
+       slr     %r6,%r6                 # set access code to zero
+       la      %r10,MEMORY_CHUNKS      # number of chunks
 .Lloop:
-       tprot 0(%r5),0                   # test protection of first byte
-       ipm   %r7
-       srl   %r7,28
-       clr   %r6,%r7                    # compare cc with last access code
-       je    .Lsame
-       j     .Lchkmem
+       tprot   0(%r5),0                # test protection of first byte
+       ipm     %r7
+       srl     %r7,28
+       clr     %r6,%r7                 # compare cc with last access code
+       je      .Lsame
+       j       .Lchkmem
 .Lsame:
-       algr  %r5,%r1                    # add 128KB to end of chunk
-                                        # no need to check here,
-       brc   12,.Lloop                  # this is the same chunk
-.Lchkmem:                               # > 16EB or tprot got a program check
-       clgr  %r4,%r5                    # chunk size > 0?
-       je    .Lchkloop
-       stg   %r4,0(%r3)                 # store start address of chunk
-       lgr   %r0,%r5
-       slgr  %r0,%r4
-       stg   %r0,8(%r3)                 # store size of chunk
-       st    %r6,20(%r3)                # store type of chunk
-       la    %r3,24(%r3)
-       larl  %r8,memory_size
-       stg   %r5,0(%r8)                 # store memory size
-       ahi   %r10,-1                    # update chunk number
+       algr    %r5,%r1                 # add 128KB to end of chunk
+                                       # no need to check here,
+       brc     12,.Lloop               # this is the same chunk
+.Lchkmem:                              # > 16EB or tprot got a program check
+       clgr    %r4,%r5                 # chunk size > 0?
+       je      .Lchkloop
+       stg     %r4,0(%r3)              # store start address of chunk
+       lgr     %r0,%r5
+       slgr    %r0,%r4
+       stg     %r0,8(%r3)              # store size of chunk
+       st      %r6,20(%r3)             # store type of chunk
+       la      %r3,24(%r3)
+       larl    %r8,memory_size
+       stg     %r5,0(%r8)              # store memory size
+       ahi     %r10,-1                 # update chunk number
 .Lchkloop:
-       lr    %r6,%r7                    # set access code to last cc
+       lr      %r6,%r7                 # set access code to last cc
        # we got an exception or we're starting a new
        # chunk , we must check if we should
        # still try to find valid memory (if we detected
        # the amount of available storage), and if we
        # have chunks left
-       lghi  %r4,1
-       sllg  %r4,%r4,31
-       clgr  %r5,%r4
-       je    .Lhsaskip
-       xr    %r0, %r0
-       clgr  %r0, %r9                   # did we detect memory?
-       je    .Ldonemem                  # if not, leave
-       chi   %r10, 0                    # do we have chunks left?
-       je    .Ldonemem
+       lghi    %r4,1
+       sllg    %r4,%r4,31
+       clgr    %r5,%r4
+       je      .Lhsaskip
+       xr      %r0, %r0
+       clgr    %r0, %r9                # did we detect memory?
+       je      .Ldonemem               # if not, leave
+       chi     %r10, 0                 # do we have chunks left?
+       je      .Ldonemem
 .Lhsaskip:
-       algr  %r5,%r1                    # add 128KB to end of chunk
-       lgr   %r4,%r5                    # potential new chunk
-       clgr  %r5,%r9                    # should we go on?
-       jl    .Lloop
-.Ldonemem:             
+       algr    %r5,%r1                 # add 128KB to end of chunk
+       lgr     %r4,%r5                 # potential new chunk
+       clgr    %r5,%r9                 # should we go on?
+       jl      .Lloop
+.Ldonemem:
 
-       larl  %r12,machine_flags
+       larl    %r12,machine_flags
 #
 # find out if we are running under VM
 #
-        stidp  __LC_CPUID               # store cpuid
-       tm     __LC_CPUID,0xff          # running under VM ?
-       bno    0f-.LPG1(%r13)
-        oi     7(%r12),1                # set VM flag
-0:      lh     %r0,__LC_CPUID+4         # get cpu version
-        chi    %r0,0x7490               # running on a P/390 ?
-        bne    1f-.LPG1(%r13)
-        oi     7(%r12),4                # set P/390 flag
+       stidp   __LC_CPUID              # store cpuid
+       tm      __LC_CPUID,0xff         # running under VM ?
+       bno     0f-.LPG1(%r13)
+       oi      7(%r12),1               # set VM flag
+0:     lh      %r0,__LC_CPUID+4        # get cpu version
+       chi     %r0,0x7490              # running on a P/390 ?
+       bne     1f-.LPG1(%r13)
+       oi      7(%r12),4               # set P/390 flag
 1:
 
 #
 # find out if we have the MVPG instruction
 #
-       la     %r1,0f-.LPG1(%r13)       # set program check address
-       stg    %r1,__LC_PGM_NEW_PSW+8
-       sgr    %r0,%r0
-       lghi   %r1,0
-       lghi   %r2,0
-       mvpg   %r1,%r2                  # test MVPG instruction
-       oi     7(%r12),16               # set MVPG flag
+       la      %r1,0f-.LPG1(%r13)      # set program check address
+       stg     %r1,__LC_PGM_NEW_PSW+8
+       sgr     %r0,%r0
+       lghi    %r1,0
+       lghi    %r2,0
+       mvpg    %r1,%r2                 # test MVPG instruction
+       oi      7(%r12),16              # set MVPG flag
 0:
 
 #
 # find out if the diag 0x44 works in 64 bit mode
 #
-       la     %r1,0f-.LPG1(%r13)       # set program check address
-       stg    %r1,__LC_PGM_NEW_PSW+8
-       diag   0,0,0x44                 # test diag 0x44
-       oi     7(%r12),32               # set diag44 flag
-0:     
+       la      %r1,0f-.LPG1(%r13)      # set program check address
+       stg     %r1,__LC_PGM_NEW_PSW+8
+       diag    0,0,0x44                # test diag 0x44
+       oi      7(%r12),32              # set diag44 flag
+0:
 
 #
 # find out if we have the IDTE instruction
 #
-       la     %r1,0f-.LPG1(%r13)       # set program check address
-       stg    %r1,__LC_PGM_NEW_PSW+8
+       la      %r1,0f-.LPG1(%r13)      # set program check address
+       stg     %r1,__LC_PGM_NEW_PSW+8
        .long   0xb2b10000              # store facility list
        tm      0xc8,0x08               # check bit for clearing-by-ASCE
        bno     0f-.LPG1(%r13)
@@ -250,6 +250,17 @@ startup_continue:
        oi      7(%r12),0x80            # set IDTE flag
 0:
 
+#
+# find out if the diag 0x9c is available
+#
+       la     %r1,0f-.LPG1(%r13)       # set program check address
+       stg    %r1,__LC_PGM_NEW_PSW+8
+       stap   __LC_CPUID+4             # store cpu address
+       lh     %r1,__LC_CPUID+4
+       diag   %r1,0,0x9c               # test diag 0x9c
+       oi     6(%r12),1                # set diag9c flag
+0:
+
 #
 # find out if we have the MVCOS instruction
 #
@@ -263,45 +274,45 @@ startup_continue:
        oi      6(%r12),2               # set MVCOS flag
 1:
 
-        lpswe .Lentry-.LPG1(13)         # jump to _stext in primary-space,
-                                        # virtual and never return ...
-        .align 16
-.Lentry:.quad  0x0000000180000000,_stext
-.Lctl:  .quad  0x04b50002               # cr0: various things
-        .quad  0                        # cr1: primary space segment table
-        .quad  .Lduct                   # cr2: dispatchable unit control table
-        .quad  0                        # cr3: instruction authorization
-        .quad  0                        # cr4: instruction authorization
-        .quad  0xffffffffffffffff       # cr5: primary-aste origin
-        .quad  0                        # cr6:  I/O interrupts
-        .quad  0                        # cr7:  secondary space segment table
-        .quad  0                        # cr8:  access registers translation
-        .quad  0                        # cr9:  tracing off
-        .quad  0                        # cr10: tracing off
-        .quad  0                        # cr11: tracing off
-        .quad  0                        # cr12: tracing off
-        .quad  0                        # cr13: home space segment table
-        .quad  0xc0000000               # cr14: machine check handling off
-        .quad  0                        # cr15: linkage stack operations
-.Lduct: .long 0,0,0,0,0,0,0,0
-       .long 0,0,0,0,0,0,0,0
-.Lpcmsk:.quad  0x0000000180000000
+       lpswe   .Lentry-.LPG1(13)       # jump to _stext in primary-space,
+                                       # virtual and never return ...
+       .align  16
+.Lentry:.quad  0x0000000180000000,_stext
+.Lctl: .quad   0x04b50002              # cr0: various things
+       .quad   0                       # cr1: primary space segment table
+       .quad   .Lduct                  # cr2: dispatchable unit control table
+       .quad   0                       # cr3: instruction authorization
+       .quad   0                       # cr4: instruction authorization
+       .quad   0xffffffffffffffff      # cr5: primary-aste origin
+       .quad   0                       # cr6:  I/O interrupts
+       .quad   0                       # cr7:  secondary space segment table
+       .quad   0                       # cr8:  access registers translation
+       .quad   0                       # cr9:  tracing off
+       .quad   0                       # cr10: tracing off
+       .quad   0                       # cr11: tracing off
+       .quad   0                       # cr12: tracing off
+       .quad   0                       # cr13: home space segment table
+       .quad   0xc0000000              # cr14: machine check handling off
+       .quad   0                       # cr15: linkage stack operations
+.Lduct: .long  0,0,0,0,0,0,0,0
+       .long   0,0,0,0,0,0,0,0
+.Lpcmsk:.quad  0x0000000180000000
 .L4malign:.quad 0xffffffffffc00000
-.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
-.Lnop: .long  0x07000700
+.Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
+.Lnop: .long   0x07000700
 .Lparmaddr:
        .quad   PARMAREA
 
-       .globl ipl_schib
+       .globl  ipl_schib
 ipl_schib:
        .rept 13
        .long 0
        .endr
 
-       .globl ipl_flags
+       .globl  ipl_flags
 ipl_flags:
-       .long 0
-       .globl ipl_devno
+       .long   0
+       .globl  ipl_devno
 ipl_devno:
        .word 0
 
@@ -309,47 +320,47 @@ ipl_devno:
 .globl s390_readinfo_sccb
 s390_readinfo_sccb:
 .Lsccb:
-       .hword 0x1000                   # length, one page
-       .byte 0x00,0x00,0x00
-       .byte 0x80                      # variable response bit set
+       .hword  0x1000                  # length, one page
+       .byte   0x00,0x00,0x00
+       .byte   0x80                    # variable response bit set
 .Lsccbr:
-       .hword 0x00                     # response code
+       .hword  0x00                    # response code
 .Lscpincr1:
-       .hword 0x00
+       .hword  0x00
 .Lscpa1:
-       .byte 0x00
-       .fill 89,1,0
+       .byte   0x00
+       .fill   89,1,0
 .Lscpa2:
-       .int 0x00
+       .int    0x00
 .Lscpincr2:
-       .quad 0x00
-       .fill 3984,1,0
+       .quad   0x00
+       .fill   3984,1,0
        .org    0x13000
 
 #ifdef CONFIG_SHARED_KERNEL
-       .org   0x100000
+       .org    0x100000
 #endif
-       
+
 #
 # startup-code, running in absolute addressing mode
 #
-        .globl _stext
-_stext:        basr  %r13,0                    # get base
+       .globl  _stext
+_stext:        basr    %r13,0                  # get base
 .LPG3:
 # check control registers
-        stctg  %c0,%c15,0(%r15)
-       oi     6(%r15),0x40             # enable sigp emergency signal
-       oi     4(%r15),0x10             # switch on low address proctection
-        lctlg  %c0,%c15,0(%r15)
+       stctg   %c0,%c15,0(%r15)
+       oi      6(%r15),0x40            # enable sigp emergency signal
+       oi      4(%r15),0x10            # switch on low address proctection
+       lctlg   %c0,%c15,0(%r15)
 
-        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
-        brasl  %r14,start_kernel        # go to C code
+       lam     0,15,.Laregs-.LPG3(%r13)        # load acrs needed by uaccess
+       brasl   %r14,start_kernel       # go to C code
 #
 # We returned from start_kernel ?!? PANIK
 #
-        basr  %r13,0
-       lpswe .Ldw-.(%r13)           # load disabled wait psw
+       basr    %r13,0
+       lpswe   .Ldw-.(%r13)            # load disabled wait psw
 
-            .align 8
-.Ldw:       .quad  0x0002000180000000,0x0000000000000000
-.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+       .align  8
+.Ldw:  .quad   0x0002000180000000,0x0000000000000000
+.Laregs:.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
index 6555cc48e28f8ed40d8d74723222aac20ac6a52e..1f5e782b3d050173741898bfb4ca4fdb6af0e963 100644 (file)
@@ -120,24 +120,15 @@ static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
 
 static int diag308(unsigned long subcode, void *addr)
 {
-       register unsigned long _addr asm("0") = (unsigned long)addr;
+       register unsigned long _addr asm("0") = (unsigned long) addr;
        register unsigned long _rc asm("1") = 0;
 
-       asm volatile (
-               "   diag %0,%2,0x308\n"
-               "0: \n"
-               ".section __ex_table,\"a\"\n"
-#ifdef CONFIG_64BIT
-               "   .align 8\n"
-               "   .quad 0b, 0b\n"
-#else
-               "   .align 4\n"
-               "   .long 0b, 0b\n"
-#endif
-               ".previous\n"
+       asm volatile(
+               "       diag    %0,%2,0x308\n"
+               "0:\n"
+               EX_TABLE(0b,0b)
                : "+d" (_addr), "+d" (_rc)
-               : "d" (subcode) : "cc", "memory" );
-
+               : "d" (subcode) : "cc", "memory");
        return _rc;
 }
 
index d3cbfa3005eca0017fb63ca6ddfe88d979659bcc..6603fbb41d070d202a834b9ec4ef380775645663 100644 (file)
@@ -45,7 +45,7 @@
 #include <asm/irq.h>
 #include <asm/timer.h>
 
-asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
 
 /*
  * Return saved PC of a blocked thread. used in kernel/sched.
@@ -177,7 +177,8 @@ void show_regs(struct pt_regs *regs)
 
 extern void kernel_thread_starter(void);
 
-__asm__(".align 4\n"
+asm(
+       ".align 4\n"
        "kernel_thread_starter:\n"
        "    la    2,0(10)\n"
        "    basr  14,9\n"
index 4562cdbce8eb4400f1dc9d20cf3a3ab485bfc9c7..0340477f3b084d7f35498dff495d9755928647d7 100644 (file)
@@ -32,58 +32,58 @@ do_reipl_asm:       basr    %r13,0
                st      %r13, __LC_PSW_SAVE_AREA+4
 
                lctl    %c6,%c6,.Lall-.Lpg0(%r13)
-                lr      %r1,%r2
-               mvc     __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
-                stsch   .Lschib-.Lpg0(%r13)                                    
-               oi      .Lschib+5-.Lpg0(%r13),0x84 
-.Lecs:         xi      .Lschib+27-.Lpg0(%r13),0x01 
-               msch    .Lschib-.Lpg0(%r13) 
-                lhi     %r0,5
-.Lssch:                ssch    .Liplorb-.Lpg0(%r13)           
+               lr      %r1,%r2
+               mvc     __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
+               stsch   .Lschib-.Lpg0(%r13)
+               oi      .Lschib+5-.Lpg0(%r13),0x84
+.Lecs:         xi      .Lschib+27-.Lpg0(%r13),0x01
+               msch    .Lschib-.Lpg0(%r13)
+               lhi     %r0,5
+.Lssch:                ssch    .Liplorb-.Lpg0(%r13)
                jz      .L001
-                brct    %r0,.Lssch  
+               brct    %r0,.Lssch
                bas     %r14,.Ldisab-.Lpg0(%r13)
-.L001:         mvc     __LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)  
-.Ltpi:         lpsw    .Lwaitpsw-.Lpg0(%r13)          
+.L001:         mvc     __LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)
+.Ltpi:         lpsw    .Lwaitpsw-.Lpg0(%r13)
 .Lcont:                c       %r1,__LC_SUBCHANNEL_ID
                jnz     .Ltpi
                clc     __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
                jnz     .Ltpi
-               tsch    .Liplirb-.Lpg0(%r13)           
+               tsch    .Liplirb-.Lpg0(%r13)
                tm      .Liplirb+9-.Lpg0(%r13),0xbf
-                jz      .L002
-                bas     %r14,.Ldisab-.Lpg0(%r13)    
-.L002:         tm      .Liplirb+8-.Lpg0(%r13),0xf3    
-                jz      .L003
-                bas     %r14,.Ldisab-.Lpg0(%r13)       
+               jz      .L002
+               bas     %r14,.Ldisab-.Lpg0(%r13)
+.L002:         tm      .Liplirb+8-.Lpg0(%r13),0xf3
+               jz      .L003
+               bas     %r14,.Ldisab-.Lpg0(%r13)
 .L003:         spx     .Lnull-.Lpg0(%r13)
-               st      %r1,__LC_SUBCHANNEL_ID
-                lpsw   0
-               sigp    0,0,0(6)               
-.Ldisab:       st      %r14,.Ldispsw+4-.Lpg0(%r13)
+               st      %r1,__LC_SUBCHANNEL_ID
+               lpsw    0
+               sigp    0,0,0(6)
+.Ldisab:       st      %r14,.Ldispsw+4-.Lpg0(%r13)
                lpsw    .Ldispsw-.Lpg0(%r13)
-                .align         8
+               .align  8
 .Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .long   0xff000000
-.Lnull:                .long   0x00000000
+.Lnull:                .long   0x00000000
 .Lctlsave1:    .long   0x00000000
 .Lctlsave2:    .long   0x00000000
-                .align         8
-.Lnewpsw:      .long   0x00080000,0x80000000+.Lpg1
-.Lpcnew:       .long   0x00080000,0x80000000+.Lecs
-.Lionew:       .long   0x00080000,0x80000000+.Lcont
+               .align  8
+.Lnewpsw:      .long   0x00080000,0x80000000+.Lpg1
+.Lpcnew:       .long   0x00080000,0x80000000+.Lecs
+.Lionew:       .long   0x00080000,0x80000000+.Lcont
 .Lwaitpsw:     .long   0x020a0000,0x00000000+.Ltpi
-.Ldispsw:      .long   0x000a0000,0x00000000
-.Liplccws:     .long   0x02000000,0x60000018
-               .long   0x08000008,0x20000001
+.Ldispsw:      .long   0x000a0000,0x00000000
+.Liplccws:     .long   0x02000000,0x60000018
+               .long   0x08000008,0x20000001
 .Liplorb:      .long   0x0049504c,0x0040ff80
                .long   0x00000000+.Liplccws
-.Lschib:        .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
+.Lschib:       .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
 .Liplirb:      .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
@@ -92,6 +92,3 @@ do_reipl_asm: basr    %r13,0
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
-       
-
-       
index 95bd1e234f6320ded22f19dd1ea616145d2e2db1..de7435054f7ccd4c45754824d8808d7ee83cfb8e 100644 (file)
@@ -4,7 +4,7 @@
  *  S390 version
  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
-                Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+                Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  */
 
 #include <asm/lowcore.h>
@@ -32,46 +32,46 @@ do_reipl_asm:       basr    %r13,0
                stctg   %c0,%c0,.Lregsave-.Lpg0(%r13)
                ni      .Lregsave+4-.Lpg0(%r13),0xef
                lctlg   %c0,%c0,.Lregsave-.Lpg0(%r13)
-                lgr     %r1,%r2
-               mvc     __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
-                stsch   .Lschib-.Lpg0(%r13)                                    
-               oi      .Lschib+5-.Lpg0(%r13),0x84 
-.Lecs:         xi      .Lschib+27-.Lpg0(%r13),0x01 
-               msch    .Lschib-.Lpg0(%r13) 
-               lghi    %r0,5
-.Lssch:                ssch    .Liplorb-.Lpg0(%r13)           
+               lgr     %r1,%r2
+               mvc     __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
+               stsch   .Lschib-.Lpg0(%r13)
+               oi      .Lschib+5-.Lpg0(%r13),0x84
+.Lecs:         xi      .Lschib+27-.Lpg0(%r13),0x01
+               msch    .Lschib-.Lpg0(%r13)
+               lghi    %r0,5
+.Lssch:                ssch    .Liplorb-.Lpg0(%r13)
                jz      .L001
-               brct    %r0,.Lssch   
+               brct    %r0,.Lssch
                bas     %r14,.Ldisab-.Lpg0(%r13)
-.L001:         mvc     __LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13) 
-.Ltpi:         lpswe   .Lwaitpsw-.Lpg0(%r13)          
+.L001:         mvc     __LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)
+.Ltpi:         lpswe   .Lwaitpsw-.Lpg0(%r13)
 .Lcont:                c       %r1,__LC_SUBCHANNEL_ID
                jnz     .Ltpi
                clc     __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
                jnz     .Ltpi
-               tsch    .Liplirb-.Lpg0(%r13)           
+               tsch    .Liplirb-.Lpg0(%r13)
                tm      .Liplirb+9-.Lpg0(%r13),0xbf
-                jz      .L002
-                bas     %r14,.Ldisab-.Lpg0(%r13)    
-.L002:         tm      .Liplirb+8-.Lpg0(%r13),0xf3    
-                jz      .L003
-                bas     %r14,.Ldisab-.Lpg0(%r13)       
+               jz      .L002
+               bas     %r14,.Ldisab-.Lpg0(%r13)
+.L002:         tm      .Liplirb+8-.Lpg0(%r13),0xf3
+               jz      .L003
+               bas     %r14,.Ldisab-.Lpg0(%r13)
 .L003:         spx     .Lnull-.Lpg0(%r13)
-               st      %r1,__LC_SUBCHANNEL_ID
-                lhi     %r1,0            # mode 0 = esa
-                slr     %r0,%r0          # set cpuid to zero
-                sigp    %r1,%r0,0x12     # switch to esa mode
-                lpsw   0
-.Ldisab:       sll    %r14,1
-               srl    %r14,1            # need to kill hi bit to avoid specification exceptions.
-               st     %r14,.Ldispsw+12-.Lpg0(%r13)
+               st      %r1,__LC_SUBCHANNEL_ID
+               lhi     %r1,0            # mode 0 = esa
+               slr     %r0,%r0          # set cpuid to zero
+               sigp    %r1,%r0,0x12     # switch to esa mode
+               lpsw    0
+.Ldisab:       sll     %r14,1
+               srl     %r14,1           # need to kill hi bit to avoid specification exceptions.
+               st      %r14,.Ldispsw+12-.Lpg0(%r13)
                lpswe   .Ldispsw-.Lpg0(%r13)
-                .align         8
+               .align  8
 .Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .quad   0x00000000ff000000
 .Lregsave:     .quad   0x0000000000000000
-.Lnull:                .long   0x0000000000000000
-                .align         16
+.Lnull:                .long   0x0000000000000000
+               .align  16
 /*
  * These addresses have to be 31 bit otherwise
  * the sigp will throw a specifcation exception
@@ -81,26 +81,26 @@ do_reipl_asm:       basr    %r13,0
  * 31bit lpswe instruction a fact they appear to have
  * ommited from the pop.
  */
-.Lnewpsw:      .quad   0x0000000080000000
-               .quad   .Lpg1
-.Lpcnew:       .quad   0x0000000080000000
-               .quad   .Lecs
-.Lionew:       .quad   0x0000000080000000
-               .quad   .Lcont
+.Lnewpsw:      .quad   0x0000000080000000
+               .quad   .Lpg1
+.Lpcnew:       .quad   0x0000000080000000
+               .quad   .Lecs
+.Lionew:       .quad   0x0000000080000000
+               .quad   .Lcont
 .Lwaitpsw:     .quad   0x0202000080000000
-               .quad   .Ltpi
-.Ldispsw:      .quad   0x0002000080000000
-               .quad   0x0000000000000000
-.Liplccws:     .long   0x02000000,0x60000018
-               .long   0x08000008,0x20000001
+               .quad   .Ltpi
+.Ldispsw:      .quad   0x0002000080000000
+               .quad   0x0000000000000000
+.Liplccws:     .long   0x02000000,0x60000018
+               .long   0x08000008,0x20000001
 .Liplorb:      .long   0x0049504c,0x0040ff80
                .long   0x00000000+.Liplccws
-.Lschib:        .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
-               .long   0x00000000,0x00000000
+.Lschib:       .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
+               .long   0x00000000,0x00000000
 .Liplirb:      .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
@@ -109,4 +109,3 @@ do_reipl_asm:       basr    %r13,0
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
                .long   0x00000000,0x00000000
-       
index 2a25ec7147ffef7be275feeb9a915dfaec6f70b3..f9899ff2e5b0a928a297e2998a5f6b8bb40f7363 100644 (file)
@@ -3,7 +3,7 @@
  *
  * (C) Copyright IBM Corp. 2005
  *
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Author(s): Rolf Adelsberger,
  *           Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  */
        .text
        .globl          relocate_kernel
        relocate_kernel:
-               basr    %r13,0          #base address
+               basr    %r13,0          # base address
        .base:
-               stnsm   sys_msk-.base(%r13),0xf8        #disable DAT and IRQ (external)
-               spx     zero64-.base(%r13)      #absolute addressing mode
+               stnsm   sys_msk-.base(%r13),0xf8        # disable DAT and IRQ (external)
+               spx     zero64-.base(%r13)      # absolute addressing mode
                stctl   %c0,%c15,ctlregs-.base(%r13)
                stm     %r0,%r15,gprregs-.base(%r13)
                la      %r1,load_psw-.base(%r13)
-               mvc     0(8,%r0),0(%r1)
+               mvc     0(8,%r0),0(%r1)
                la      %r0,.back-.base(%r13)
                st      %r0,4(%r0)
                oi      4(%r0),0x80
        .back_pgm:
                lm      %r0,%r15,gprregs-.base(%r13)
        .start_reloc:
-               lhi     %r10,-1         #preparing the mask
-               sll     %r10,12         #shift it such that it becomes 0xf000
+               lhi     %r10,-1         # preparing the mask
+               sll     %r10,12         # shift it such that it becomes 0xf000
        .top:
-               lhi     %r7,4096        #load PAGE_SIZE in r7
-               lhi     %r9,4096        #load PAGE_SIZE in r9
-               l       %r5,0(%r2)      #read another word for indirection page
-               ahi     %r2,4           #increment pointer
-               tml     %r5,0x1         #is it a destination page?
-               je      .indir_check    #NO, goto "indir_check"
-               lr      %r6,%r5         #r6 = r5
-               nr      %r6,%r10        #mask it out and...
-               j       .top            #...next iteration
+               lhi     %r7,4096        # load PAGE_SIZE in r7
+               lhi     %r9,4096        # load PAGE_SIZE in r9
+               l       %r5,0(%r2)      # read another word for indirection page
+               ahi     %r2,4           # increment pointer
+               tml     %r5,0x1         # is it a destination page?
+               je      .indir_check    # NO, goto "indir_check"
+               lr      %r6,%r5         # r6 = r5
+               nr      %r6,%r10        # mask it out and...
+               j       .top            # ...next iteration
        .indir_check:
-               tml     %r5,0x2         #is it a indirection page?
-               je      .done_test      #NO, goto "done_test"
-               nr      %r5,%r10        #YES, mask out,
-               lr      %r2,%r5         #move it into the right register,
-               j       .top            #and read next...
+               tml     %r5,0x2         # is it a indirection page?
+               je      .done_test      # NO, goto "done_test"
+               nr      %r5,%r10        # YES, mask out,
+               lr      %r2,%r5         # move it into the right register,
+               j       .top            # and read next...
        .done_test:
-               tml     %r5,0x4         #is it the done indicator?
-               je      .source_test    #NO! Well, then it should be the source indicator...
-               j       .done           #ok, lets finish it here...
+               tml     %r5,0x4         # is it the done indicator?
+               je      .source_test    # NO! Well, then it should be the source indicator...
+               j       .done           # ok, lets finish it here...
        .source_test:
-               tml     %r5,0x8         #it should be a source indicator...
-               je      .top            #NO, ignore it...
-               lr      %r8,%r5         #r8 = r5
-               nr      %r8,%r10        #masking
-       0:      mvcle   %r6,%r8,0x0     #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+               tml     %r5,0x8         # it should be a source indicator...
+               je      .top            # NO, ignore it...
+               lr      %r8,%r5         # r8 = r5
+               nr      %r8,%r10        # masking
+       0:      mvcle   %r6,%r8,0x0     # copy PAGE_SIZE bytes from r8 to r6 - pad with 0
                jo      0b
                j       .top
        .done:
-               sr      %r0,%r0         #clear register r0
-               la      %r4,load_psw-.base(%r13)        #load psw-address into the register
-               o       %r3,4(%r4)      #or load address into psw
+               sr      %r0,%r0         # clear register r0
+               la      %r4,load_psw-.base(%r13)        # load psw-address into the register
+               o       %r3,4(%r4)      # or load address into psw
                st      %r3,4(%r4)
-               mvc     0(8,%r0),0(%r4) #copy psw to absolute address 0
+               mvc     0(8,%r0),0(%r4) # copy psw to absolute address 0
                tm      have_diag308-.base(%r13),0x01
                jno     .no_diag308
                diag    %r0,%r0,0x308
        .no_diag308:
-               sr      %r1,%r1         #clear %r1
-               sr      %r2,%r2         #clear %r2
-               sigp    %r1,%r2,0x12    #set cpuid to zero
-               lpsw    0               #hopefully start new kernel...
+               sr      %r1,%r1         # clear %r1
+               sr      %r2,%r2         # clear %r2
+               sigp    %r1,%r2,0x12    # set cpuid to zero
+               lpsw    0               # hopefully start new kernel...
 
                .align  8
        zero64:
index 8cdb86e8911ff98ec92c39ae3db8be106c76f836..4fb443042d9cc39bd64cf8502aed48636cd608bd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * (C) Copyright IBM Corp. 2005
  *
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Author(s): Rolf Adelsberger,
  *           Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  */
        .text
        .globl          relocate_kernel
        relocate_kernel:
-               basr    %r13,0          #base address
+               basr    %r13,0          # base address
        .base:
-               stnsm   sys_msk-.base(%r13),0xf8        #disable DAT and IRQs
-               spx     zero64-.base(%r13)      #absolute addressing mode
+               stnsm   sys_msk-.base(%r13),0xf8        # disable DAT and IRQs
+               spx     zero64-.base(%r13)      # absolute addressing mode
                stctg   %c0,%c15,ctlregs-.base(%r13)
                stmg    %r0,%r15,gprregs-.base(%r13)
                lghi    %r0,3
                la      %r0,.back_pgm-.base(%r13)
                stg     %r0,0x1d8(%r0)
                la      %r1,load_psw-.base(%r13)
-               mvc     0(8,%r0),0(%r1)
+               mvc     0(8,%r0),0(%r1)
                la      %r0,.back-.base(%r13)
                st      %r0,4(%r0)
                oi      4(%r0),0x80
                lghi    %r0,0
                diag    %r0,%r0,0x308
        .back:
-               lhi     %r1,1           #mode 1 = esame
-               sigp    %r1,%r0,0x12    #switch to esame mode
-               sam64                   #switch to 64 bit addressing mode
+               lhi     %r1,1           # mode 1 = esame
+               sigp    %r1,%r0,0x12    # switch to esame mode
+               sam64                   # switch to 64 bit addressing mode
                basr    %r13,0
        .back_base:
                oi      have_diag308-.back_base(%r13),0x01
        .back_pgm:
                lmg     %r0,%r15,gprregs-.base(%r13)
        .top:
-               lghi    %r7,4096        #load PAGE_SIZE in r7
-               lghi    %r9,4096        #load PAGE_SIZE in r9
-               lg      %r5,0(%r2)      #read another word for indirection page
-               aghi    %r2,8           #increment pointer
-               tml     %r5,0x1         #is it a destination page?
-               je      .indir_check    #NO, goto "indir_check"
-               lgr     %r6,%r5         #r6 = r5
-               nill    %r6,0xf000      #mask it out and...
-               j       .top            #...next iteration
+               lghi    %r7,4096        # load PAGE_SIZE in r7
+               lghi    %r9,4096        # load PAGE_SIZE in r9
+               lg      %r5,0(%r2)      # read another word for indirection page
+               aghi    %r2,8           # increment pointer
+               tml     %r5,0x1         # is it a destination page?
+               je      .indir_check    # NO, goto "indir_check"
+               lgr     %r6,%r5         # r6 = r5
+               nill    %r6,0xf000      # mask it out and...
+               j       .top            # ...next iteration
        .indir_check:
-               tml     %r5,0x2         #is it a indirection page?
-               je      .done_test      #NO, goto "done_test"
-               nill    %r5,0xf000      #YES, mask out,
-               lgr     %r2,%r5         #move it into the right register,
-               j       .top            #and read next...
+               tml     %r5,0x2         # is it a indirection page?
+               je      .done_test      # NO, goto "done_test"
+               nill    %r5,0xf000      # YES, mask out,
+               lgr     %r2,%r5         # move it into the right register,
+               j       .top            # and read next...
        .done_test:
-               tml     %r5,0x4         #is it the done indicator?
-               je      .source_test    #NO! Well, then it should be the source indicator...
-               j       .done           #ok, lets finish it here...
+               tml     %r5,0x4         # is it the done indicator?
+               je      .source_test    # NO! Well, then it should be the source indicator...
+               j       .done           # ok, lets finish it here...
        .source_test:
-               tml     %r5,0x8         #it should be a source indicator...
-               je      .top            #NO, ignore it...
-               lgr     %r8,%r5         #r8 = r5
-               nill    %r8,0xf000      #masking
-       0:      mvcle   %r6,%r8,0x0     #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+               tml     %r5,0x8         # it should be a source indicator...
+               je      .top            # NO, ignore it...
+               lgr     %r8,%r5         # r8 = r5
+               nill    %r8,0xf000      # masking
+       0:      mvcle   %r6,%r8,0x0     # copy PAGE_SIZE bytes from r8 to r6 - pad with 0
                jo      0b
-               j       .top
+               j       .top
        .done:
-               sgr     %r0,%r0         #clear register r0
-               la      %r4,load_psw-.base(%r13)        #load psw-address into the register
-               o       %r3,4(%r4)      #or load address into psw
+               sgr     %r0,%r0         # clear register r0
+               la      %r4,load_psw-.base(%r13)        # load psw-address into the register
+               o       %r3,4(%r4)      # or load address into psw
                st      %r3,4(%r4)
-               mvc     0(8,%r0),0(%r4) #copy psw to absolute address 0
+               mvc     0(8,%r0),0(%r4) # copy psw to absolute address 0
                tm      have_diag308-.base(%r13),0x01
                jno     .no_diag308
                diag    %r0,%r0,0x308
        .no_diag308:
-               sam31                   #31 bit mode
-               sr      %r1,%r1         #erase register r1
-               sr      %r2,%r2         #erase register r2
-               sigp    %r1,%r2,0x12    #set cpuid to zero
-               lpsw    0               #hopefully start new kernel...
+               sam31                   # 31 bit mode
+               sr      %r1,%r1         # erase register r1
+               sr      %r2,%r2         # erase register r2
+               sigp    %r1,%r2,0x12    # set cpuid to zero
+               lpsw    0               # hopefully start new kernel...
 
-               .align  8
+               .align  8
        zero64:
                .quad   0
        load_psw:
index 8dfb690c159f339e0db0fe83d416f6fc82df8ebb..191303f6c1d8b87fab68349af8c220c0b9dc0e4b 100644 (file)
@@ -26,17 +26,17 @@ static inline int __sem_update_count(struct semaphore *sem, int incr)
 {
        int old_val, new_val;
 
-        __asm__ __volatile__("   l     %0,0(%3)\n"
-                             "0: ltr   %1,%0\n"
-                            "   jhe   1f\n"
-                            "   lhi   %1,0\n"
-                            "1: ar    %1,%4\n"
-                             "   cs    %0,%1,0(%3)\n"
-                             "   jl    0b\n"
-                             : "=&d" (old_val), "=&d" (new_val),
-                              "=m" (sem->count)
-                            : "a" (&sem->count), "d" (incr), "m" (sem->count)
-                            : "cc" );
+       asm volatile(
+               "       l       %0,0(%3)\n"
+               "0:     ltr     %1,%0\n"
+               "       jhe     1f\n"
+               "       lhi     %1,0\n"
+               "1:     ar      %1,%4\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b\n"
+               : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count)
+               : "a" (&sem->count), "d" (incr), "m" (sem->count)
+               : "cc");
        return old_val;
 }
 
index e3d9325f6022b04e3bf307bdc3549362231c75ea..a21cfbb9d97edd97b30111bb492392fe5deb8bae 100644 (file)
@@ -101,7 +101,7 @@ void __devinit cpu_init (void)
         /*
          * Store processor id in lowcore (used e.g. in timer_interrupt)
          */
-        asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+       asm volatile("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
         S390_lowcore.cpu_data.cpu_addr = addr;
 
         /*
index b2e6f4c8d382a463976a6ed74341f87f331ef81f..a8e6199755d4ecc86197aa0f95cfad26314df31b 100644 (file)
@@ -63,7 +63,7 @@ static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
- * Structure and data for smp_call_function(). This is designed to minimise
+5B * Structure and data for smp_call_function(). This is designed to minimise
  * static memory requirements. It also looks cleaner.
  */
 static DEFINE_SPINLOCK(call_lock);
@@ -418,59 +418,49 @@ void smp_send_reschedule(int cpu)
 /*
  * parameter area for the set/clear control bit callbacks
  */
-typedef struct
-{
-       __u16 start_ctl;
-       __u16 end_ctl;
+struct ec_creg_mask_parms {
        unsigned long orvals[16];
        unsigned long andvals[16];
-} ec_creg_mask_parms;
+};
 
 /*
  * callback for setting/clearing control bits
  */
 void smp_ctl_bit_callback(void *info) {
-       ec_creg_mask_parms *pp;
+       struct ec_creg_mask_parms *pp = info;
        unsigned long cregs[16];
        int i;
        
-       pp = (ec_creg_mask_parms *) info;
-       __ctl_store(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
-       for (i = pp->start_ctl; i <= pp->end_ctl; i++)
+       __ctl_store(cregs, 0, 15);
+       for (i = 0; i <= 15; i++)
                cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
-       __ctl_load(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
+       __ctl_load(cregs, 0, 15);
 }
 
 /*
  * Set a bit in a control register of all cpus
  */
-void smp_ctl_set_bit(int cr, int bit) {
-        ec_creg_mask_parms parms;
+void smp_ctl_set_bit(int cr, int bit)
+{
+       struct ec_creg_mask_parms parms;
 
-       parms.start_ctl = cr;
-       parms.end_ctl = cr;
+       memset(&parms.orvals, 0, sizeof(parms.orvals));
+       memset(&parms.andvals, 0xff, sizeof(parms.andvals));
        parms.orvals[cr] = 1 << bit;
-       parms.andvals[cr] = -1L;
-       preempt_disable();
-       smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_set_bit(cr, bit);
-       preempt_enable();
+       on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
  * Clear a bit in a control register of all cpus
  */
-void smp_ctl_clear_bit(int cr, int bit) {
-        ec_creg_mask_parms parms;
+void smp_ctl_clear_bit(int cr, int bit)
+{
+       struct ec_creg_mask_parms parms;
 
-       parms.start_ctl = cr;
-       parms.end_ctl = cr;
-       parms.orvals[cr] = 0;
+       memset(&parms.orvals, 0, sizeof(parms.orvals));
+       memset(&parms.andvals, 0xff, sizeof(parms.andvals));
        parms.andvals[cr] = ~(1L << bit);
-       preempt_disable();
-       smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_clear_bit(cr, bit);
-       preempt_enable();
+       on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
@@ -650,9 +640,9 @@ __cpu_up(unsigned int cpu)
        sf->gprs[9] = (unsigned long) sf;
        cpu_lowcore->save_area[15] = (unsigned long) sf;
        __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
-       __asm__ __volatile__("stam  0,15,0(%0)"
-                            : : "a" (&cpu_lowcore->access_regs_save_area)
-                            : "memory");
+       asm volatile(
+               "       stam    0,15,0(%0)"
+               : : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
        cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
         cpu_lowcore->current_task = (unsigned long) idle;
         cpu_lowcore->cpu_data.cpu_nr = cpu;
@@ -708,7 +698,7 @@ int
 __cpu_disable(void)
 {
        unsigned long flags;
-       ec_creg_mask_parms cr_parms;
+       struct ec_creg_mask_parms cr_parms;
        int cpu = smp_processor_id();
 
        spin_lock_irqsave(&smp_reserve_lock, flags);
@@ -724,30 +714,21 @@ __cpu_disable(void)
                pfault_fini();
 #endif
 
-       /* disable all external interrupts */
+       memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
+       memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
 
-       cr_parms.start_ctl = 0;
-       cr_parms.end_ctl = 0;
+       /* disable all external interrupts */
        cr_parms.orvals[0] = 0;
        cr_parms.andvals[0] = ~(1<<15 | 1<<14 | 1<<13 | 1<<12 |
                                1<<11 | 1<<10 | 1<< 6 | 1<< 4);
-       smp_ctl_bit_callback(&cr_parms);
-
        /* disable all I/O interrupts */
-
-       cr_parms.start_ctl = 6;
-       cr_parms.end_ctl = 6;
        cr_parms.orvals[6] = 0;
        cr_parms.andvals[6] = ~(1<<31 | 1<<30 | 1<<29 | 1<<28 |
                                1<<27 | 1<<26 | 1<<25 | 1<<24);
-       smp_ctl_bit_callback(&cr_parms);
-
        /* disable most machine checks */
-
-       cr_parms.start_ctl = 14;
-       cr_parms.end_ctl = 14;
        cr_parms.orvals[14] = 0;
        cr_parms.andvals[14] = ~(1<<28 | 1<<27 | 1<<26 | 1<<25 | 1<<24);
+
        smp_ctl_bit_callback(&cr_parms);
 
        spin_unlock_irqrestore(&smp_reserve_lock, flags);
index 74e6178fbaf25c11ee55e9b320c38a5437cd571a..4bf66cc4a267ee9d8fed39992e52a84c74b4dbd6 100644 (file)
@@ -53,8 +53,6 @@ static u64 init_timer_cc;
 static u64 jiffies_timer_cc;
 static u64 xtime_cc;
 
-extern unsigned long wall_jiffies;
-
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
@@ -87,9 +85,8 @@ static inline unsigned long do_gettimeoffset(void)
 {
        __u64 now;
 
-        now = (get_clock() - jiffies_timer_cc) >> 12;
-       /* We require the offset from the latest update of xtime */
-       now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
+       now = (get_clock() - jiffies_timer_cc) >> 12;
+       now -= (__u64) jiffies * USECS_PER_JIFFY;
        return (unsigned long) now;
 }
 
@@ -166,7 +163,7 @@ EXPORT_SYMBOL(do_settimeofday);
 void account_ticks(struct pt_regs *regs)
 {
        __u64 tmp;
-       __u32 ticks, xticks;
+       __u32 ticks;
 
        /* Calculate how many ticks have passed. */
        if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
@@ -204,6 +201,7 @@ void account_ticks(struct pt_regs *regs)
         */
        write_seqlock(&xtime_lock);
        if (S390_lowcore.jiffy_timer > xtime_cc) {
+               __u32 xticks;
                tmp = S390_lowcore.jiffy_timer - xtime_cc;
                if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
                        xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
@@ -212,13 +210,11 @@ void account_ticks(struct pt_regs *regs)
                        xticks = 1;
                        xtime_cc += CLK_TICKS_PER_JIFFY;
                }
-               while (xticks--)
-                       do_timer(regs);
+               do_timer(xticks);
        }
        write_sequnlock(&xtime_lock);
 #else
-       for (xticks = ticks; xticks > 0; xticks--)
-               do_timer(regs);
+       do_timer(ticks);
 #endif
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -351,10 +347,12 @@ void __init time_init(void)
        int cc;
 
         /* kick the TOD clock */
-        asm volatile ("STCK 0(%1)\n\t"
-                      "IPM  %0\n\t"
-                      "SRL  %0,28" : "=r" (cc) : "a" (&init_timer_cc) 
-                                  : "memory", "cc");
+       asm volatile(
+               "       stck    0(%2)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (cc), "=m" (init_timer_cc)
+               : "a" (&init_timer_cc) : "cc");
         switch (cc) {
         case 0: /* clock in set state: all is fine */
                 break;
index c4982c963424921aebaaad4fa15560b05ca22bd5..3eb4fab048b8c18f16c6327fb5bc4c096eb11579 100644 (file)
@@ -597,8 +597,7 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
                local_irq_enable();
 
        if (MACHINE_HAS_IEEE)
-               __asm__ volatile ("stfpc %0\n\t" 
-                                 : "=m" (current->thread.fp_regs.fpc));
+               asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
 
 #ifdef CONFIG_MATHEMU
         else if (regs->psw.mask & PSW_MASK_PSTATE) {
index c42ffedfdb4940988178ee325802634d06bcf4e2..b0cfa6c4883d57e7a848970beca6657c3907b0b5 100644 (file)
@@ -5,5 +5,6 @@
 EXTRA_AFLAGS := -traditional
 
 lib-y += delay.o string.o uaccess_std.o
+lib-$(CONFIG_32BIT) += div64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
index 468f4ea33f99efdf1f83802ed4433146ac485b57..027c4742a0017a2cdef12b51a4dd282709dc59b9 100644 (file)
@@ -27,9 +27,7 @@ void __delay(unsigned long loops)
          * yield the megahertz number of the cpu. The important function
          * is udelay and that is done using the tod clock. -- martin.
          */
-        __asm__ __volatile__(
-                "0: brct %0,0b"
-                : /* no outputs */ : "r" ((loops/2) + 1));
+       asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
 }
 
 /*
@@ -38,13 +36,12 @@ void __delay(unsigned long loops)
  */
 void __udelay(unsigned long usecs)
 {
-        uint64_t start_cc, end_cc;
+       uint64_t start_cc;
 
         if (usecs == 0)
                 return;
-        asm volatile ("STCK %0" : "=m" (start_cc));
+       start_cc = get_clock();
         do {
                cpu_relax();
-                asm volatile ("STCK %0" : "=m" (end_cc));
-        } while (((end_cc - start_cc)/4096) < usecs);
+       } while (((get_clock() - start_cc)/4096) < usecs);
 }
diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c
new file mode 100644 (file)
index 0000000..0481f34
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *  arch/s390/lib/div64.c
+ *
+ *  __div64_32 implementation for 31 bit.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_MARCH_G5
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 31 bit integer using signed 64/32 bit division.
+ */
+static uint32_t __div64_31(uint64_t *n, uint32_t base)
+{
+       register uint32_t reg2 asm("2");
+       register uint32_t reg3 asm("3");
+       uint32_t *words = (uint32_t *) n;
+       uint32_t tmp;
+
+       /* Special case base==1, remainder = 0, quotient = n */
+       if (base == 1)
+               return 0;
+       /*
+        * Special case base==0 will cause a fixed point divide exception
+        * on the dr instruction and may not happen anyway. For the
+        * following calculation we can assume base > 1. The first
+        * signed 64 / 32 bit division with an upper half of 0 will
+        * give the correct upper half of the 64 bit quotient.
+        */
+       reg2 = 0UL;
+       reg3 = words[0];
+       asm volatile(
+               "       dr      %0,%2\n"
+               : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+       words[0] = reg3;
+       reg3 = words[1];
+       /*
+        * To get the lower half of the 64 bit quotient and the 32 bit
+        * remainder we have to use a little trick. Since we only have
+        * a signed division the quotient can get too big. To avoid this
+        * the 64 bit dividend is halved, then the signed division will
+        * work. Afterwards the quotient and the remainder are doubled.
+        * If the last bit of the dividend has been one the remainder
+        * is increased by one then checked against the base. If the
+        * remainder has overflown subtract base and increase the
+        * quotient. Simple, no ?
+        */
+       asm volatile(
+               "       nr      %2,%1\n"
+               "       srdl    %0,1\n"
+               "       dr      %0,%3\n"
+               "       alr     %0,%0\n"
+               "       alr     %1,%1\n"
+               "       alr     %0,%2\n"
+               "       clr     %0,%3\n"
+               "       jl      0f\n"
+               "       slr     %0,%3\n"
+               "       alr     %1,%2\n"
+               "0:\n"
+               : "+d" (reg2), "+d" (reg3), "=d" (tmp)
+               : "d" (base), "2" (1UL) : "cc" );
+       words[1] = reg3;
+       return reg2;
+}
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 32 bit integer using the unsigned 64/31 bit division.
+ */
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+       uint32_t r;
+
+       /*
+        * If the most significant bit of base is set, divide n by
+        * (base/2). That allows to use 64/31 bit division and gives a
+        * good approximation of the result: n = (base/2)*q + r. The
+        * result needs to be corrected with two simple transformations.
+        * If base is already < 2^31-1 __div64_31 can be used directly.
+        */
+       r = __div64_31(n, ((signed) base < 0) ? (base/2) : base);
+       if ((signed) base < 0) {
+               uint64_t q = *n;
+               /*
+                * First transformation:
+                * n = (base/2)*q + r
+                *   = ((base/2)*2)*(q/2) + ((q&1) ? (base/2) : 0) + r
+                * Since r < (base/2), r + (base/2) < base.
+                * With q1 = (q/2) and r1 = r + ((q&1) ? (base/2) : 0)
+                * n = ((base/2)*2)*q1 + r1 with r1 < base.
+                */
+               if (q & 1)
+                       r += base/2;
+               q >>= 1;
+               /*
+                * Second transformation. ((base/2)*2) could have lost the
+                * last bit.
+                * n = ((base/2)*2)*q1 + r1
+                *   = base*q1 - ((base&1) ? q1 : 0) + r1
+                */
+               if (base & 1) {
+                       int64_t rx = r - q;
+                       /*
+                        * base is >= 2^31. The worst case for the while
+                        * loop is n=2^64-1 base=2^31+1. That gives a
+                        * maximum for q=(2^64-1)/2^31 = 0x1ffffffff. Since
+                        * base >= 2^31 the loop is finished after a maximum
+                        * of three iterations.
+                        */
+                       while (rx < 0) {
+                               rx += base;
+                               q--;
+                       }
+                       r = rx;
+               }
+               *n = q;
+       }
+       return r;
+}
+
+#else /* MARCH_G5 */
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+       register uint32_t reg2 asm("2");
+       register uint32_t reg3 asm("3");
+       uint32_t *words = (uint32_t *) n;
+
+       reg2 = 0UL;
+       reg3 = words[0];
+       asm volatile(
+               "       dlr     %0,%2\n"
+               : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+       words[0] = reg3;
+       reg3 = words[1];
+       asm volatile(
+               "       dlr     %0,%2\n"
+               : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+       words[1] = reg3;
+       return reg2;
+}
+
+#endif /* MARCH_G5 */
+
+EXPORT_SYMBOL(__div64_32);
index b9b7958a226a75a5787129404b1eb525c95832b4..8d76403fcf89b5900f02f6084312049791b8dc4e 100644 (file)
@@ -24,57 +24,76 @@ static int __init spin_retry_setup(char *str)
 }
 __setup("spin_retry=", spin_retry_setup);
 
-static inline void
-_diag44(void)
+static inline void _raw_yield(void)
 {
-#ifdef CONFIG_64BIT
        if (MACHINE_HAS_DIAG44)
-#endif
                asm volatile("diag 0,0,0x44");
 }
 
-void
-_raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
+static inline void _raw_yield_cpu(int cpu)
+{
+       if (MACHINE_HAS_DIAG9C)
+               asm volatile("diag %0,0,0x9c"
+                            : : "d" (__cpu_logical_map[cpu]));
+       else
+               _raw_yield();
+}
+
+void _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
 {
        int count = spin_retry;
+       unsigned int cpu = ~smp_processor_id();
 
        while (1) {
                if (count-- <= 0) {
-                       _diag44();
+                       unsigned int owner = lp->owner_cpu;
+                       if (owner != 0)
+                               _raw_yield_cpu(~owner);
                        count = spin_retry;
                }
                if (__raw_spin_is_locked(lp))
                        continue;
-               if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
+               if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) {
+                       lp->owner_pc = pc;
                        return;
+               }
        }
 }
 EXPORT_SYMBOL(_raw_spin_lock_wait);
 
-int
-_raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
+int _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
 {
-       int count = spin_retry;
+       unsigned int cpu = ~smp_processor_id();
+       int count;
 
-       while (count-- > 0) {
+       for (count = spin_retry; count > 0; count--) {
                if (__raw_spin_is_locked(lp))
                        continue;
-               if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
+               if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) {
+                       lp->owner_pc = pc;
                        return 1;
+               }
        }
        return 0;
 }
 EXPORT_SYMBOL(_raw_spin_trylock_retry);
 
-void
-_raw_read_lock_wait(raw_rwlock_t *rw)
+void _raw_spin_relax(raw_spinlock_t *lock)
+{
+       unsigned int cpu = lock->owner_cpu;
+       if (cpu != 0)
+               _raw_yield_cpu(~cpu);
+}
+EXPORT_SYMBOL(_raw_spin_relax);
+
+void _raw_read_lock_wait(raw_rwlock_t *rw)
 {
        unsigned int old;
        int count = spin_retry;
 
        while (1) {
                if (count-- <= 0) {
-                       _diag44();
+                       _raw_yield();
                        count = spin_retry;
                }
                if (!__raw_read_can_lock(rw))
@@ -86,8 +105,7 @@ _raw_read_lock_wait(raw_rwlock_t *rw)
 }
 EXPORT_SYMBOL(_raw_read_lock_wait);
 
-int
-_raw_read_trylock_retry(raw_rwlock_t *rw)
+int _raw_read_trylock_retry(raw_rwlock_t *rw)
 {
        unsigned int old;
        int count = spin_retry;
@@ -103,14 +121,13 @@ _raw_read_trylock_retry(raw_rwlock_t *rw)
 }
 EXPORT_SYMBOL(_raw_read_trylock_retry);
 
-void
-_raw_write_lock_wait(raw_rwlock_t *rw)
+void _raw_write_lock_wait(raw_rwlock_t *rw)
 {
        int count = spin_retry;
 
        while (1) {
                if (count-- <= 0) {
-                       _diag44();
+                       _raw_yield();
                        count = spin_retry;
                }
                if (!__raw_write_can_lock(rw))
@@ -121,8 +138,7 @@ _raw_write_lock_wait(raw_rwlock_t *rw)
 }
 EXPORT_SYMBOL(_raw_write_lock_wait);
 
-int
-_raw_write_trylock_retry(raw_rwlock_t *rw)
+int _raw_write_trylock_retry(raw_rwlock_t *rw)
 {
        int count = spin_retry;
 
index 86c96d6c191a3819bb094cb7d0698b3401a0c147..121b2935a422a2e724ce97cd9dd49aaa61cc26a7 100644 (file)
@@ -35,7 +35,7 @@ size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
        tmp1 = -4096UL;
        asm volatile(
                "0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
-               "   jz    4f\n"
+               "   jz    7f\n"
                "1:"ALR"  %0,%3\n"
                "  "SLR"  %1,%3\n"
                "  "SLR"  %2,%3\n"
@@ -44,13 +44,23 @@ size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
                "   nr    %4,%3\n"      /* %4 = (ptr + 4095) & -4096 */
                "  "SLR"  %4,%1\n"
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
-               "   jnh   5f\n"
+               "   jnh   4f\n"
                "3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
                "  "SLR"  %0,%4\n"
-               "   j     5f\n"
-               "4:"SLR"  %0,%0\n"
-               "5: \n"
-               EX_TABLE(0b,2b) EX_TABLE(3b,5b)
+               "  "ALR"  %2,%4\n"
+               "4:"LHI"  %4,-1\n"
+               "  "ALR"  %4,%0\n"      /* copy remaining size, subtract 1 */
+               "   bras  %3,6f\n"      /* memset loop */
+               "   xc    0(1,%2),0(%2)\n"
+               "5: xc    0(256,%2),0(%2)\n"
+               "   la    %2,256(%2)\n"
+               "6:"AHI"  %4,-256\n"
+               "   jnm   5b\n"
+               "   ex    %4,0(%3)\n"
+               "   j     8f\n"
+               "7:"SLR"  %0,%0\n"
+               "8: \n"
+               EX_TABLE(0b,2b) EX_TABLE(3b,4b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : "d" (reg0) : "cc", "memory");
        return size;
index 9a4d4a29ea79d6c8a6760c0b8122ed1b586d4f3e..f44f0078b354538d86908b949e4d6f4a4cee8d7e 100644 (file)
@@ -35,25 +35,35 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
        tmp1 = -256UL;
        asm volatile(
                "0: mvcp  0(%0,%2),0(%1),%3\n"
-               "   jz    5f\n"
+               "   jz    8f\n"
                "1:"ALR"  %0,%3\n"
                "   la    %1,256(%1)\n"
                "   la    %2,256(%2)\n"
                "2: mvcp  0(%0,%2),0(%1),%3\n"
                "   jnz   1b\n"
-               "   j     5f\n"
+               "   j     8f\n"
                "3: la    %4,255(%1)\n" /* %4 = ptr + 255 */
                "  "LHI"  %3,-4096\n"
                "   nr    %4,%3\n"      /* %4 = (ptr + 255) & -4096 */
                "  "SLR"  %4,%1\n"
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
-               "   jnh   6f\n"
+               "   jnh   5f\n"
                "4: mvcp  0(%4,%2),0(%1),%3\n"
                "  "SLR"  %0,%4\n"
-               "   j     6f\n"
-               "5:"SLR"  %0,%0\n"
-               "6: \n"
-               EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
+               "  "ALR"  %2,%4\n"
+               "5:"LHI"  %4,-1\n"
+               "  "ALR"  %4,%0\n"      /* copy remaining size, subtract 1 */
+               "   bras  %3,7f\n"      /* memset loop */
+               "   xc    0(1,%2),0(%2)\n"
+               "6: xc    0(256,%2),0(%2)\n"
+               "   la    %2,256(%2)\n"
+               "7:"AHI"  %4,-256\n"
+               "   jnm   6b\n"
+               "   ex    %4,0(%3)\n"
+               "   j     9f\n"
+               "8:"SLR"  %0,%0\n"
+               "9: \n"
+               EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : : "cc", "memory");
        return size;
@@ -67,16 +77,22 @@ size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x)
        asm volatile(
                "0: mvcp  0(%0,%2),0(%1),%3\n"
                "  "SLR"  %0,%0\n"
-               "   j     3f\n"
+               "   j     5f\n"
                "1: la    %4,255(%1)\n" /* %4 = ptr + 255 */
                "  "LHI"  %3,-4096\n"
                "   nr    %4,%3\n"      /* %4 = (ptr + 255) & -4096 */
                "  "SLR"  %4,%1\n"
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
-               "   jnh   3f\n"
+               "   jnh   5f\n"
                "2: mvcp  0(%4,%2),0(%1),%3\n"
                "  "SLR"  %0,%4\n"
-               "3:\n"
+               "  "ALR"  %2,%4\n"
+               "3:"LHI"  %4,-1\n"
+               "  "ALR"  %4,%0\n"      /* copy remaining size, subtract 1 */
+               "   bras  %3,4f\n"
+               "   xc    0(1,%2),0(%2)\n"
+               "4: ex    %4,0(%3)\n"
+               "5:\n"
                EX_TABLE(0b,1b) EX_TABLE(2b,3b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : : "cc", "memory");
index b4957c84e4d66395a7633752079742ae5db77316..6b9aec5a2c18dae0283d61904b37b6018691e36c 100644 (file)
@@ -1564,52 +1564,52 @@ static int emu_tceb (struct pt_regs *regs, int rx, long val) {
 }
 
 static inline void emu_load_regd(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+       if ((reg&9) != 0)       /* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* load reg from fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     ld    0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
-                : "1" );
+       asm volatile(           /* load reg from fp_regs.fprs[reg] */
+               "       bras    1,0f\n"
+               "       ld      0,0(%1)\n"
+               "0:     ex      %0,0(1)"
+               : /* no output */
+               : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
+               : "1");
 }
 
 static inline void emu_load_rege(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+       if ((reg&9) != 0)       /* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* load reg from fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     le    0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
-                : "1" );
+       asm volatile(           /* load reg from fp_regs.fprs[reg] */
+               "       bras    1,0f\n"
+               "       le      0,0(%1)\n"
+               "0:     ex      %0,0(1)"
+               : /* no output */
+               : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+               : "1");
 }
 
 static inline void emu_store_regd(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+       if ((reg&9) != 0)       /* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* store reg to fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     std   0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
-                : "1" );
+       asm volatile(           /* store reg to fp_regs.fprs[reg] */
+               "       bras    1,0f\n"
+               "       std     0,0(%1)\n"
+               "0:     ex      %0,0(1)"
+               : /* no output */
+               : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
+               : "1");
 }
 
 
 static inline void emu_store_rege(int reg) {
-        if ((reg&9) != 0)         /* test if reg in {0,2,4,6} */
+       if ((reg&9) != 0)       /* test if reg in {0,2,4,6} */
                 return;
-        asm volatile (            /* store reg to fp_regs.fprs[reg] */
-                "     bras  1,0f\n"
-                "     ste   0,0(%1)\n"
-                "0:   ex    %0,0(1)"
-                : /* no output */
-                : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
-                : "1" );
+       asm volatile(           /* store reg to fp_regs.fprs[reg] */
+               "       bras    1,0f\n"
+               "       ste     0,0(%1)\n"
+               "0:     ex      %0,0(1)"
+               : /* no output */
+               : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+               : "1");
 }
 
 int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
@@ -2089,23 +2089,22 @@ int math_emu_ldr(__u8 *opcode) {
 
         if ((opc & 0x90) == 0) {           /* test if rx in {0,2,4,6} */
                 /* we got an exception therfore ry can't be in {0,2,4,6} */
-                __asm__ __volatile (       /* load rx from fp_regs.fprs[ry] */
-                        "     bras  1,0f\n"
-                        "     ld    0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" (opc & 0xf0),
-                          "a" (&fp_regs->fprs[opc & 0xf].d)
-                        : "1" );
+               asm volatile(           /* load rx from fp_regs.fprs[ry] */
+                       "       bras    1,0f\n"
+                       "       ld      0,0(%1)\n"
+                       "0:     ex      %0,0(1)"
+                       : /* no output */
+                       : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].d)
+                       : "1");
         } else if ((opc & 0x9) == 0) {     /* test if ry in {0,2,4,6} */
-                __asm__ __volatile (       /* store ry to fp_regs.fprs[rx] */
-                        "     bras  1,0f\n"
-                        "     std   0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" ((opc & 0xf) << 4),
-                          "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
-                        : "1" );
+               asm volatile (          /* store ry to fp_regs.fprs[rx] */
+                       "       bras    1,0f\n"
+                       "       std     0,0(%1)\n"
+                       "0:     ex      %0,0(1)"
+                       : /* no output */
+                       : "a" ((opc & 0xf) << 4),
+                         "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
+                       : "1");
         } else  /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
                 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
        return 0;
@@ -2120,23 +2119,22 @@ int math_emu_ler(__u8 *opcode) {
 
         if ((opc & 0x90) == 0) {           /* test if rx in {0,2,4,6} */
                 /* we got an exception therfore ry can't be in {0,2,4,6} */
-                __asm__ __volatile (       /* load rx from fp_regs.fprs[ry] */
-                        "     bras  1,0f\n"
-                        "     le    0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" (opc & 0xf0),
-                          "a" (&fp_regs->fprs[opc & 0xf].f)
-                        : "1" );
+               asm volatile(           /* load rx from fp_regs.fprs[ry] */
+                       "       bras    1,0f\n"
+                       "       le      0,0(%1)\n"
+                       "0:     ex      %0,0(1)"
+                       : /* no output */
+                       : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].f)
+                       : "1");
         } else if ((opc & 0x9) == 0) {     /* test if ry in {0,2,4,6} */
-                __asm__ __volatile (       /* store ry to fp_regs.fprs[rx] */
-                        "     bras  1,0f\n"
-                        "     ste   0,0(%1)\n"
-                        "0:   ex    %0,0(1)"
-                        : /* no output */
-                        : "a" ((opc & 0xf) << 4),
-                          "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
-                        : "1" );
+               asm volatile(           /* store ry to fp_regs.fprs[rx] */
+                       "       bras    1,0f\n"
+                       "       ste     0,0(%1)\n"
+                       "0:     ex      %0,0(1)"
+                       : /* no output */
+                       : "a" ((opc & 0xf) << 4),
+                         "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
+                       : "1");
         } else  /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
                 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
        return 0;
index ab556b600f738651d1e5b4ea8e8390b25757bf88..5b6ca4570ea41e6b44aba008cf0ce520f7a86580 100644 (file)
@@ -4,48 +4,51 @@
 #include <asm/byteorder.h>
 
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) ({          \
-        unsigned int __sh = (ah);                      \
-        unsigned int __sl = (al);                      \
-        __asm__ ("   alr  %1,%3\n"                     \
-                 "   brc  12,0f\n"                     \
-                 "   ahi  %0,1\n"                      \
-                 "0: alr  %0,%2"                       \
-                 : "+&d" (__sh), "+d" (__sl)           \
-                 : "d" (bh), "d" (bl) : "cc" );                \
-        (sh) = __sh;                                   \
-        (sl) = __sl;                                   \
+       unsigned int __sh = (ah);                       \
+       unsigned int __sl = (al);                       \
+       asm volatile(                                   \
+               "       alr     %1,%3\n"                \
+               "       brc     12,0f\n"                \
+               "       ahi     %0,1\n"                 \
+               "0:     alr  %0,%2"                     \
+               : "+&d" (__sh), "+d" (__sl)             \
+               : "d" (bh), "d" (bl) : "cc");           \
+       (sh) = __sh;                                    \
+       (sl) = __sl;                                    \
 })
 
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) ({          \
-       unsigned int __sh = (ah);                       \
-       unsigned int __sl = (al);                       \
-       __asm__ ("   slr  %1,%3\n"                      \
-                "   brc  3,0f\n"                       \
-                "   ahi  %0,-1\n"                      \
-                "0: slr  %0,%2"                                \
-                : "+&d" (__sh), "+d" (__sl)            \
-                : "d" (bh), "d" (bl) : "cc" );         \
-       (sh) = __sh;                                    \
-       (sl) = __sl;                                    \
+       unsigned int __sh = (ah);                       \
+       unsigned int __sl = (al);                       \
+       asm volatile(                                   \
+               "       slr     %1,%3\n"                \
+               "       brc     3,0f\n"                 \
+               "       ahi     %0,-1\n"                \
+               "0:     slr     %0,%2"                  \
+               : "+&d" (__sh), "+d" (__sl)             \
+               : "d" (bh), "d" (bl) : "cc");           \
+       (sh) = __sh;                                    \
+       (sl) = __sl;                                    \
 })
 
 /* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */
 #define umul_ppmm(wh, wl, u, v) ({                     \
-        unsigned int __wh = u;                         \
-        unsigned int __wl = v;                         \
-        __asm__ ("   ltr  1,%0\n"                      \
-                 "   mr   0,%1\n"                      \
-                 "   jnm  0f\n"                                \
-                 "   alr  0,%1\n"                      \
-                 "0: ltr  %1,%1\n"                     \
-                 "   jnm  1f\n"                                \
-                 "   alr  0,%0\n"                      \
-                 "1: lr   %0,0\n"                      \
-                 "   lr   %1,1\n"                      \
-                 : "+d" (__wh), "+d" (__wl)            \
-                 : : "0", "1", "cc" );                 \
-        wh = __wh;                                     \
-        wl = __wl;                                     \
+       unsigned int __wh = u;                          \
+       unsigned int __wl = v;                          \
+       asm volatile(                                   \
+               "       ltr     1,%0\n"                 \
+               "       mr      0,%1\n"                 \
+               "       jnm     0f\n"                           \
+               "       alr     0,%1\n"                 \
+               "0:     ltr     %1,%1\n"                        \
+               "       jnm     1f\n"                           \
+               "       alr     0,%0\n"                 \
+               "1:     lr      %0,0\n"                 \
+               "       lr      %1,1\n"                 \
+               : "+d" (__wh), "+d" (__wl)              \
+               : : "0", "1", "cc");                    \
+       wh = __wh;                                      \
+       wl = __wl;                                      \
 })
 
 #define udiv_qrnnd(q, r, n1, n0, d)                    \
index 9b11e3e20903f0305916fcd6e6037a71cefdf43f..226275d5c4f60a39a506635d961399e51479e25c 100644 (file)
@@ -142,17 +142,17 @@ dcss_diag (__u8 func, void *parameter,
 
        rx = (unsigned long) parameter;
        ry = (unsigned long) func;
-       __asm__ __volatile__(
+       asm volatile(
 #ifdef CONFIG_64BIT
-               "   sam31\n" // switch to 31 bit
-               "   diag    %0,%1,0x64\n"
-               "   sam64\n" // switch back to 64 bit
+               "       sam31\n"
+               "       diag    %0,%1,0x64\n"
+               "       sam64\n"
 #else
-               "   diag    %0,%1,0x64\n"
+               "       diag    %0,%1,0x64\n"
 #endif
-               "   ipm     %2\n"
-               "   srl     %2,28\n"
-               : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
+               "       ipm     %2\n"
+               "       srl     %2,28\n"
+               : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
        *ret1 = rx;
        *ret2 = ry;
        return rc;
index 44f0cda7e72e44bb9ae47e6fc42fd284ceb430ab..9c3c19fe62fcd99dfb3893730d7f54b354b731f5 100644 (file)
@@ -353,8 +353,9 @@ no_context:
 */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (tsk->pid == 1) {
+       if (is_init(tsk)) {
                yield();
+               down_read(&mm->mmap_sem);
                goto survive;
        }
        printk("VM: killing process %s\n", tsk->comm);
@@ -423,20 +424,13 @@ int pfault_init(void)
 
        if (pfault_disable)
                return -1;
-        __asm__ __volatile__(
-                "    diag  %1,%0,0x258\n"
-               "0:  j     2f\n"
-               "1:  la    %0,8\n"
+       asm volatile(
+               "       diag    %1,%0,0x258\n"
+               "0:     j       2f\n"
+               "1:     la      %0,8\n"
                "2:\n"
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-#ifndef CONFIG_64BIT
-               "   .long  0b,1b\n"
-#else /* CONFIG_64BIT */
-               "   .quad  0b,1b\n"
-#endif /* CONFIG_64BIT */
-               ".previous"
-                : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" );
+               EX_TABLE(0b,1b)
+               : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc");
         __ctl_set_bit(0, 9);
         return rc;
 }
@@ -449,18 +443,11 @@ void pfault_fini(void)
        if (pfault_disable)
                return;
        __ctl_clear_bit(0,9);
-        __asm__ __volatile__(
-                "    diag  %0,0,0x258\n"
+       asm volatile(
+               "       diag    %0,0,0x258\n"
                "0:\n"
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-#ifndef CONFIG_64BIT
-               "   .long  0b,0b\n"
-#else /* CONFIG_64BIT */
-               "   .quad  0b,0b\n"
-#endif /* CONFIG_64BIT */
-               ".previous"
-               : : "a" (&refbk), "m" (refbk) : "cc" );
+               EX_TABLE(0b,0b)
+               : : "a" (&refbk), "m" (refbk) : "cc");
 }
 
 asmlinkage void
index cfd9b8f7a5239b11b7c81272f65474ab80423a02..127044e1707cd075fc7717b3a38321e3b6688ba2 100644 (file)
@@ -45,26 +45,17 @@ void diag10(unsigned long addr)
 {
         if (addr >= 0x7ff00000)
                 return;
+       asm volatile(
 #ifdef CONFIG_64BIT
-        asm volatile (
-               "   sam31\n"
-               "   diag %0,%0,0x10\n"
-               "0: sam64\n"
-               ".section __ex_table,\"a\"\n"
-               "   .align 8\n"
-               "   .quad 0b, 0b\n"
-               ".previous\n"
-               : : "a" (addr));
+               "       sam31\n"
+               "       diag    %0,%0,0x10\n"
+               "0:     sam64\n"
 #else
-        asm volatile (
-               "   diag %0,%0,0x10\n"
+               "       diag    %0,%0,0x10\n"
                "0:\n"
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-               "   .long 0b, 0b\n"
-               ".previous\n"
-               : : "a" (addr));
 #endif
+               EX_TABLE(0b,0b)
+               : : "a" (addr));
 }
 
 void show_mem(void)
@@ -156,11 +147,10 @@ void __init paging_init(void)
        S390_lowcore.kernel_asce = pgdir_k;
 
         /* enable virtual mapping in kernel mode */
-        __asm__ __volatile__("    LCTL  1,1,%0\n"
-                             "    LCTL  7,7,%0\n"
-                             "    LCTL  13,13,%0\n"
-                             "    SSM   %1" 
-                            : : "m" (pgdir_k), "m" (ssm_mask));
+       __ctl_load(pgdir_k, 1, 1);
+       __ctl_load(pgdir_k, 7, 7);
+       __ctl_load(pgdir_k, 13, 13);
+       __raw_local_irq_ssm(ssm_mask);
 
         local_flush_tlb();
         return;
@@ -241,11 +231,10 @@ void __init paging_init(void)
        S390_lowcore.kernel_asce = pgdir_k;
 
         /* enable virtual mapping in kernel mode */
-        __asm__ __volatile__("lctlg 1,1,%0\n\t"
-                             "lctlg 7,7,%0\n\t"
-                             "lctlg 13,13,%0\n\t"
-                             "ssm   %1"
-                            : :"m" (pgdir_k), "m" (ssm_mask));
+       __ctl_load(pgdir_k, 1, 1);
+       __ctl_load(pgdir_k, 7, 7);
+       __ctl_load(pgdir_k, 13, 13);
+       __raw_local_irq_ssm(ssm_mask);
 
         local_flush_tlb();
 
index 1a0db1d4c952fe31e91729e3489e985aee32d31d..1cc5c9b27bfdeae32671c58e61263d929c92f6e2 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "Linux/SuperH Kernel Configuration"
 config SUPERH
        bool
        default y
+       select EMBEDDED
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
@@ -51,18 +52,23 @@ source "init/Kconfig"
 
 menu "System type"
 
+config SOLUTION_ENGINE
+       bool
+
 choice
        prompt "SuperH system type"
        default SH_UNKNOWN
 
 config SH_SOLUTION_ENGINE
        bool "SolutionEngine"
+       select SOLUTION_ENGINE
        help
          Select SolutionEngine if configuring for a Hitachi SH7709
          or SH7750 evaluation board.
 
 config SH_7751_SOLUTION_ENGINE
        bool "SolutionEngine7751"
+       select SOLUTION_ENGINE
        select CPU_SUBTYPE_SH7751
        help
          Select 7751 SolutionEngine if configuring for a Hitachi SH7751
@@ -70,17 +76,27 @@ config SH_7751_SOLUTION_ENGINE
 
 config SH_7300_SOLUTION_ENGINE
        bool "SolutionEngine7300"
+       select SOLUTION_ENGINE
        select CPU_SUBTYPE_SH7300
        help
-         Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
-         evaluation board.
+         Select 7300 SolutionEngine if configuring for a Hitachi
+         SH7300(SH-Mobile V) evaluation board.
+
+config SH_7343_SOLUTION_ENGINE
+       bool "SolutionEngine7343"
+       select SOLUTION_ENGINE
+       select CPU_SUBTYPE_SH7343
+       help
+         Select 7343 SolutionEngine if configuring for a Hitachi
+         SH7343 (SH-Mobile 3AS) evaluation board.
 
 config SH_73180_SOLUTION_ENGINE
        bool "SolutionEngine73180"
-       select CPU_SUBTYPE_SH73180
-       help
-         Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
-         evaluation board.
+       select SOLUTION_ENGINE
+       select CPU_SUBTYPE_SH73180
+       help
+         Select 73180 SolutionEngine if configuring for a Hitachi
+         SH73180(SH-Mobile 3) evaluation board.
 
 config SH_7751_SYSTEMH
        bool "SystemH7751R"
@@ -89,12 +105,6 @@ config SH_7751_SYSTEMH
          Select SystemH if you are configuring for a Renesas SystemH
          7751R evaluation board.
 
-config SH_STB1_HARP
-       bool "STB1_Harp"
-
-config SH_STB1_OVERDRIVE
-       bool "STB1_Overdrive"
-
 config SH_HP6XX
        bool "HP6XX"
        help
@@ -102,19 +112,6 @@ config SH_HP6XX
          More information (hardware only) at
          <http://www.hp.com/jornada/>.
 
-config SH_CQREEK
-       bool "CqREEK"
-       help
-         Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
-         More information at
-         <http://sources.redhat.com/ecos/hardware.html#SuperH>.
-
-config SH_DMIDA
-       bool "DMIDA"
-       help
-         Select DMIDA if configuring for a DataMyte 4000 Industrial
-         Digital Assistant. More information at <http://www.dmida.com/>.
-
 config SH_EC3104
        bool "EC3104"
        help
@@ -136,25 +133,9 @@ config SH_DREAMCAST
          <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
          Dreamcast project is at <http://linuxdc.sourceforge.net/>.
 
-config SH_CAT68701
-       bool "CAT68701"
-
 config SH_BIGSUR
        bool "BigSur"
 
-config SH_SH2000
-       bool "SH2000"
-       select CPU_SUBTYPE_SH7709
-       help
-         SH-2000 is a single-board computer based around SH7709A chip
-         intended for embedded applications.
-         It has an Ethernet interface (CS8900A), direct connected
-         Compact Flash socket, three serial ports and PC-104 bus.
-         More information at <http://sh2000.sh-linux.org>.
-
-config SH_ADX
-       bool "ADX"
-
 config SH_MPC1211
        bool "Interface MPC1211"
        help
@@ -184,6 +165,13 @@ config SH_HS7751RVOIP
          Select HS7751RVOIP if configuring for a Renesas Technology
          Sales VoIP board.
 
+config SH_7710VOIPGW
+       bool "SH7710-VOIP-GW"
+       select CPU_SUBTYPE_SH7710
+       help
+         Select this option to build a kernel for the SH7710 based
+         VOIP GW.
+
 config SH_RTS7751R2D
        bool "RTS7751R2D"
        select CPU_SUBTYPE_SH7751R
@@ -222,6 +210,12 @@ config SH_TITAN
          Select Titan if you are configuring for a Nimble Microsystems
          NetEngine NP51R.
 
+config SH_SHMIN
+       bool "SHMIN"
+       select CPU_SUBTYPE_SH7706
+       help
+         Select SHMIN if configureing for the SHMIN board
+
 config SH_UNKNOWN
        bool "BareCPU"
        help
@@ -238,35 +232,9 @@ endchoice
 
 source "arch/sh/mm/Kconfig"
 
-config MEMORY_START
-       hex "Physical memory start address"
-       default "0x08000000"
-       ---help---
-         Computers built with Hitachi SuperH processors always
-         map the ROM starting at address zero.  But the processor
-         does not specify the range that RAM takes.
-
-         The physical memory (RAM) start address will be automatically
-         set to 08000000. Other platforms, such as the Solution Engine
-         boards typically map RAM at 0C000000.
-
-         Tweak this only when porting to a new machine which does not
-         already have a defconfig. Changing it from the known correct
-         value on any of the known systems will only lead to disaster.
-
-config MEMORY_SIZE
-       hex "Physical memory size"
-       default "0x00400000"
-       help
-         This sets the default memory size assumed by your SH kernel. It can
-         be overridden as normal by the 'mem=' argument on the kernel command
-         line. If unsure, consult your board specifications or just leave it
-         as 0x00400000 which was the default value before this became
-         configurable.
-
 config CF_ENABLER
        bool "Compact Flash Enabler support"
-       depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03
+       depends on SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_SH03
        ---help---
          Compact Flash is a small, removable mass storage device introduced
          in 1994 originally as a PCMCIA device.  If you say `Y' here, you
@@ -294,7 +262,7 @@ config CF_AREA5
          - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
          - "Area6" if it is connected to Area 6 (0x18000000)
 
-         "Area6" will work for most boards. For ADX, select "Area5".
+         "Area6" will work for most boards.
 
 config CF_AREA6
        bool "Area6"
@@ -316,19 +284,6 @@ config CPU_LITTLE_ENDIAN
          endian byte order. These modes require different kernels. Say Y if
          your machine is little endian, N if it's a big endian machine.
 
-# The SH7750 RTC module is disabled in the Dreamcast
-config SH_RTC
-       bool
-       depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \
-                  !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \
-                  !SH_R7780RP
-       default y
-       help
-         Selecting this option will allow the Linux kernel to emulate
-         PC's RTC.
-
-         If unsure, say N.
-
 config SH_FPU
        bool "FPU support"
        depends on !CPU_SH3
@@ -339,14 +294,22 @@ config SH_FPU
 
          This option must be set in order to enable the FPU.
 
+config SH_FPU_EMU
+       bool "FPU emulation support"
+       depends on !SH_FPU && EXPERIMENTAL
+       default n
+       help
+         Selecting this option will enable support for software FPU emulation.
+         Most SH-3 users will want to say Y here, whereas most SH-4 users will
+         want to say N.
+
 config SH_DSP
        bool "DSP support"
-       depends on !CPU_SH4
-       default y
+       default y if SH4AL_DSP || !CPU_SH4
+       default n
        help
          Selecting this option will enable support for SH processors that
-         have DSP units (ie, SH2-DSP and SH3-DSP). It is safe to say Y here
-         by default, as the existance of the DSP will be probed at runtime.
+         have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP).
 
          This option must be set in order to enable the DSP.
 
@@ -373,6 +336,9 @@ config CPU_HAS_INTEVT
 config CPU_HAS_PINT_IRQ
        bool
 
+config CPU_HAS_MASKREG_IRQ
+       bool
+
 config CPU_HAS_INTC2_IRQ
        bool
 
@@ -400,16 +366,19 @@ config SH_TMU
 
 endmenu
 
-#source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
 
-#source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+source "arch/sh/boards/renesas/r7780rp/Kconfig"
 
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
        default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
        default "60000000" if CPU_SUBTYPE_SH7751
-       default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
-       default "27000000" if CPU_SUBTYPE_SH73180
+       default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
+                             CPU_SUBTYPE_SH7760
+       default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
        default "66000000" if CPU_SUBTYPE_SH4_202
        help
          This option is used to specify the peripheral clock frequency.
@@ -440,10 +409,8 @@ source "arch/sh/cchips/Kconfig"
 
 config HEARTBEAT
        bool "Heartbeat LED"
-       depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \
-                  SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \
-                  SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \
-                  SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \
+       depends on SH_MPC1211 || SH_SH03 || \
+                  SH_BIGSUR || SOLUTION_ENGINE || \
                   SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
        help
          Use the power-on LED on your machine as a load meter.  The exact
@@ -459,6 +426,8 @@ config ISA_DMA_API
 
 menu "Kernel features"
 
+source kernel/Kconfig.hz
+
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
        depends on EXPERIMENTAL
@@ -476,10 +445,6 @@ config KEXEC
          support.  As of this writing the exact hardware interface is
          strongly in flux, so no good recommendation can be made.
 
-config PREEMPT
-       bool "Preemptible Kernel (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
@@ -515,6 +480,8 @@ config NR_CPUS
          This is purely to save memory - each supported CPU adds
          approximately eight kilobytes to the kernel image.
 
+source "kernel/Kconfig.preempt"
+
 config CPU_HAS_SR_RB
        bool "CPU has SR.RB"
        depends on CPU_SH3 || CPU_SH4
@@ -636,6 +603,16 @@ source "fs/Kconfig.binfmt"
 
 endmenu
 
+menu "Power management options (EXPERIMENTAL)"
+depends on EXPERIMENTAL
+
+source kernel/power/Kconfig
+
+config APM
+       bool "Advanced Power Management Emulation"
+       depends on PM
+endmenu
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
index 8fb31ab2c02c1fa4031013310f8a07df42291b36..48479e014dac657f3b36dc4252801ed38e61b1b9 100644 (file)
@@ -30,8 +30,35 @@ config EARLY_PRINTK
          when the kernel may crash or hang before the serial console is
          initialised. If unsure, say N.
 
+config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+       help
+         This option will cause messages to be printed if free stack space
+         drops below a certain limit.
+
+config DEBUG_STACK_USAGE
+       bool "Stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+config 4KSTACKS
+       bool "Use 4Kb for kernel stacks instead of 8Kb"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here the kernel will use a 4Kb stacksize for the
+         kernel stack attached to each process/thread. This facilitates
+         running more threads on a system and also reduces the pressure
+         on the VM subsystem for higher order allocations. This option
+         will also use IRQ stacks to compensate for the reduced stackspace.
+
 config KGDB
        bool "Include KGDB kernel debugger"
+       select FRAME_POINTER
        help
          Include in-kernel hooks for kgdb, the Linux kernel source level
          debugger.  See <http://kgdb.sourceforge.net/> for more information.
@@ -112,13 +139,4 @@ endchoice
 
 endmenu
 
-config FRAME_POINTER
-       bool "Compile the kernel with frame pointers"
-       default y if KGDB
-       help
-         If you say Y here the resulting kernel image will be slightly larger
-         and slower, but it will give very useful debugging information.
-         If you don't debug the kernel, you can say N, but we may not be able
-         to solve problems without frame pointers.
-
 endmenu
index e467a450662bee9e6538bd0f1a8be279972f1a70..26d62ff51a64e951b96aa90d1620365f15c7a1a1 100644 (file)
@@ -18,11 +18,13 @@ cflags-y                            := -mb
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)     := -ml
 
 isa-y                                  := any
+isa-$(CONFIG_SH_DSP)                   := sh
 isa-$(CONFIG_CPU_SH2)                  := sh2
+isa-$(CONFIG_CPU_SH2A)                 := sh2a
 isa-$(CONFIG_CPU_SH3)                  := sh3
 isa-$(CONFIG_CPU_SH4)                  := sh4
 isa-$(CONFIG_CPU_SH4A)                 := sh4a
-isa-$(CONFIG_CPU_SH2A)                 := sh2a
+isa-$(CONFIG_CPU_SH4AL_DSP)            := sh4al
 
 isa-$(CONFIG_SH_DSP)                   := $(isa-y)-dsp
 
@@ -30,9 +32,11 @@ ifndef CONFIG_MMU
 isa-y                  := $(isa-y)-nommu
 endif
 
+ifndef CONFIG_SH_DSP
 ifndef CONFIG_SH_FPU
 isa-y                  := $(isa-y)-nofpu
 endif
+endif
 
 cflags-y       += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
 
@@ -79,24 +83,19 @@ head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o
 LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 
 core-y                         += arch/sh/kernel/ arch/sh/mm/
+core-$(CONFIG_SH_FPU_EMU)      += arch/sh/math-emu/
 
 # Boards
 machdir-$(CONFIG_SH_SOLUTION_ENGINE)           := se/770x
 machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)      := se/7751
 machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)      := se/7300
+machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)      := se/7343
 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)     := se/73180
-machdir-$(CONFIG_SH_STB1_HARP)                 := harp
-machdir-$(CONFIG_SH_STB1_OVERDRIVE)            := overdrive
 machdir-$(CONFIG_SH_HP6XX)                     := hp6xx
-machdir-$(CONFIG_SH_CQREEK)                    := cqreek
-machdir-$(CONFIG_SH_DMIDA)                     := dmida
 machdir-$(CONFIG_SH_EC3104)                    := ec3104
 machdir-$(CONFIG_SH_SATURN)                    := saturn
 machdir-$(CONFIG_SH_DREAMCAST)                 := dreamcast
-machdir-$(CONFIG_SH_CAT68701)                  := cat68701
 machdir-$(CONFIG_SH_BIGSUR)                    := bigsur
-machdir-$(CONFIG_SH_SH2000)                    := sh2000
-machdir-$(CONFIG_SH_ADX)                       := adx
 machdir-$(CONFIG_SH_MPC1211)                   := mpc1211
 machdir-$(CONFIG_SH_SH03)                      := sh03
 machdir-$(CONFIG_SH_SECUREEDGE5410)            := snapgear
@@ -104,16 +103,16 @@ machdir-$(CONFIG_SH_HS7751RVOIP)          := renesas/hs7751rvoip
 machdir-$(CONFIG_SH_RTS7751R2D)                        := renesas/rts7751r2d
 machdir-$(CONFIG_SH_7751_SYSTEMH)              := renesas/systemh
 machdir-$(CONFIG_SH_EDOSK7705)                 := renesas/edosk7705
+machdir-$(CONFIG_SH_R7780RP)                   := renesas/r7780rp
+machdir-$(CONFIG_SH_7710VOIPGW)                        := renesas/sh7710voipgw
 machdir-$(CONFIG_SH_SH4202_MICRODEV)           := superh/microdev
+machdir-$(CONFIG_SH_LANDISK)                   := landisk
+machdir-$(CONFIG_SH_TITAN)                     := titan
+machdir-$(CONFIG_SH_SHMIN)                     := shmin
 machdir-$(CONFIG_SH_UNKNOWN)                   := unknown
 
 incdir-y                       := $(notdir $(machdir-y))
-
-incdir-$(CONFIG_SH_SOLUTION_ENGINE)            := se
-incdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)       := se7751
-incdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)        := se7300
-incdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)      := se73180
-incdir-$(CONFIG_SH_HP600)                      := hp6xx
+incdir-$(CONFIG_SH_HP6XX)                      := hp6xx
 
 ifneq ($(machdir-y),)
 core-y                         += arch/sh/boards/$(machdir-y)/
@@ -137,17 +136,14 @@ boot := arch/sh/boot
 
 CPPFLAGS_vmlinux.lds := -traditional
 
-ifneq ($(KBUILD_SRC),)
 incdir-prefix  := $(srctree)/include/asm-sh/
-else
-incdir-prefix  :=
-endif
 
 #      Update machine arch and proc symlinks if something which affects
 #      them changed.  We use .arch and .mach to indicate when they were
 #      updated last, otherwise make uses the target directory mtime.
 
-include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
+include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) \
+                    include/config/auto.conf FORCE
        @echo '  SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
        $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
        $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
@@ -157,7 +153,8 @@ include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
 #      don't, just reference the parent directory so the semantics are
 #      kept roughly the same.
 
-include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
+include/asm-sh/.mach: $(wildcard include/config/sh/*.h) \
+                     include/config/auto.conf FORCE
        @echo -n '  SYMLINK include/asm-sh/mach -> '
        $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
        $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
@@ -170,7 +167,7 @@ include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
        fi
        @touch $@
 
-archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
+archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools
 
 PHONY += maketools FORCE
 maketools:  include/linux/version.h FORCE
@@ -191,4 +188,3 @@ CLEAN_FILES += include/asm-sh/machtypes.h
 define archhelp
        @echo '  zImage                    - Compressed kernel image (arch/sh/boot/zImage)'
 endef
-
diff --git a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile
deleted file mode 100644 (file)
index 5b1c531..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for ADX boards
-#
-
-obj-y   := setup.o irq.o irq_maskreq.o
-
diff --git a/arch/sh/boards/adx/irq.c b/arch/sh/boards/adx/irq.c
deleted file mode 100644 (file)
index c6ca409..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * linux/arch/sh/boards/adx/irq.c
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * I/O routine and setup routines for A&D ADX Board
- *
- * 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 <asm/irq.h>
-
-void init_adx_IRQ(void)
-{
-        int i;
-
-/*      printk("init_adx_IRQ()\n");*/
-        /* setup irq_mask_register */
-        irq_mask_register = (unsigned short *)0xa6000008;
-
-        /* cover all external interrupt area by maskreg_irq_type
-         * (Actually, irq15 doesn't exist)
-         */
-        for (i = 0; i < 16; i++) {
-                make_maskreg_irq(i);
-                disable_irq(i);
-        }
-}
diff --git a/arch/sh/boards/adx/irq_maskreg.c b/arch/sh/boards/adx/irq_maskreg.c
deleted file mode 100644 (file)
index 4b2abe5..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * linux/arch/sh/kernel/irq_maskreg.c
- *
- * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
- *
- * This file may be copied or modified under the terms of the GNU
- * General Public License.  See linux/COPYING for more information.
- *
- * Interrupt handling for Simple external interrupt mask register
- *
- * This is for the machine which have single 16 bit register
- * for masking external IRQ individually.
- * Each bit of the register is for masking each interrupt.  
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-
-/* address of external interrupt mask register
- * address must be set prior to use these (maybe in init_XXX_irq())
- * XXX : is it better to use .config than specifying it in code? */
-unsigned short *irq_mask_register = 0;
-
-/* forward declaration */
-static unsigned int startup_maskreg_irq(unsigned int irq);
-static void shutdown_maskreg_irq(unsigned int irq);
-static void enable_maskreg_irq(unsigned int irq);
-static void disable_maskreg_irq(unsigned int irq);
-static void mask_and_ack_maskreg(unsigned int);
-static void end_maskreg_irq(unsigned int irq);
-
-/* hw_interrupt_type */
-static struct hw_interrupt_type maskreg_irq_type = {
-       .typename = " Mask Register",
-       .startup = startup_maskreg_irq,
-       .shutdown = shutdown_maskreg_irq,
-       .enable = enable_maskreg_irq,
-       .disable = disable_maskreg_irq,
-       .ack = mask_and_ack_maskreg,
-       .end = end_maskreg_irq
-};
-
-/* actual implementatin */
-static unsigned int startup_maskreg_irq(unsigned int irq)
-{ 
-       enable_maskreg_irq(irq);
-       return 0; /* never anything pending */
-}
-
-static void shutdown_maskreg_irq(unsigned int irq)
-{
-       disable_maskreg_irq(irq);
-}
-
-static void disable_maskreg_irq(unsigned int irq)
-{
-       if (irq_mask_register) {
-               unsigned long flags;
-               unsigned short val, mask = 0x01 << irq;
-
-               /* Set "irq"th bit */
-               local_irq_save(flags);
-               val = ctrl_inw((unsigned long)irq_mask_register);
-               val |= mask;
-               ctrl_outw(val, (unsigned long)irq_mask_register);
-               local_irq_restore(flags);
-       }
-}
-
-static void enable_maskreg_irq(unsigned int irq)
-{
-       if (irq_mask_register) {
-               unsigned long flags;
-               unsigned short val, mask = ~(0x01 << irq);
-
-               /* Clear "irq"th bit */
-               local_irq_save(flags);
-               val = ctrl_inw((unsigned long)irq_mask_register);
-               val &= mask;
-               ctrl_outw(val, (unsigned long)irq_mask_register);
-               local_irq_restore(flags);
-       }
-}
-
-static void mask_and_ack_maskreg(unsigned int irq)
-{
-       disable_maskreg_irq(irq);
-}
-
-static void end_maskreg_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_maskreg_irq(irq);
-}
-
-void make_maskreg_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &maskreg_irq_type;
-       disable_maskreg_irq(irq);
-}
diff --git a/arch/sh/boards/adx/setup.c b/arch/sh/boards/adx/setup.c
deleted file mode 100644 (file)
index 4938d95..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 
- * linux/arch/sh/board/adx/setup.c
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * I/O routine and setup routines for A&D ADX Board
- *
- * 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 <asm/machvec.h>
-#include <linux/module.h>
-
-extern void init_adx_IRQ(void);
-extern void *cf_io_base;
-
-const char *get_system_type(void)
-{
-       return "A&D ADX";
-}
-
-unsigned long adx_isa_port2addr(unsigned long offset)
-{
-       /* CompactFlash (IDE) */
-       if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) {
-               return (unsigned long)cf_io_base + offset;
-       }
-
-       /* eth0 */
-       if ((offset >= 0x300) && (offset <= 0x30f)) {
-               return 0xa5000000 + offset;     /* COMM BOARD (AREA1) */
-       }
-
-       return offset + 0xb0000000; /* IOBUS (AREA 4)*/
-}
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_adx __initmv = {
-       .mv_nr_irqs             = 48,
-       .mv_isa_port2addr       = adx_isa_port2addr,
-       .mv_init_irq            = init_adx_IRQ,
-};
-ALIAS_MV(adx)
-
-int __init platform_setup(void)
-{
-       /* Nothing to see here .. */
-       return 0;
-}
-
index ac946a2201c7077d2e7af1f4e9c9d47da25dc59a..1ab04da36382c7ad96df8698231fd9bb4ff38e2f 100644 (file)
@@ -19,6 +19,7 @@
  * IRQ functions for a Hitachi Big Sur Evaluation Board.
  *
  */
+#undef DEBUG
 
 #include <linux/sched.h>
 #include <linux/module.h>
 #undef BIGSUR_DEBUG
 
 #ifdef BIGSUR_DEBUG
-#define DPRINTK(args...)        printk(args)
 #define DIPRINTK(n, args...)    if (BIGSUR_DEBUG>(n)) printk(args)
 #else
-#define DPRINTK(args...)
 #define DIPRINTK(n, args...)
 #endif /* BIGSUR_DEBUG */
 
@@ -60,45 +59,39 @@ extern int hd64465_irq_demux(int irq);
 /* Level 1 IRQ routines */
 static void disable_bigsur_l1irq(unsigned int irq)
 {
-        unsigned long flags;
         unsigned char mask;
         unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
         unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
 
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                DPRINTK("Disable L1 IRQ %d\n", irq);
+                pr_debug("Disable L1 IRQ %d\n", irq);
                 DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
                         mask_port, bit);
-                local_irq_save(flags);
 
                 /* Disable IRQ - set mask bit */
                 mask = inb(mask_port) | bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+        pr_debug("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
 }
 
 static void enable_bigsur_l1irq(unsigned int irq)
 {
-        unsigned long flags;
         unsigned char mask;
         unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
         unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
 
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
-                DPRINTK("Enable L1 IRQ %d\n", irq);
+                pr_debug("Enable L1 IRQ %d\n", irq);
                 DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
                         mask_port, bit);
-                local_irq_save(flags);
                 /* Enable L1 IRQ - clear mask bit */
                 mask = inb(mask_port) & ~bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+        pr_debug("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
 }
 
 
@@ -126,51 +119,45 @@ static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
 /* Level 2 IRQ routines */
 static void disable_bigsur_l2irq(unsigned int irq)
 {
-        unsigned long flags;
         unsigned char mask;
         unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
         unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
 
-    if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                DPRINTK("Disable L2 IRQ %d\n", irq);
+       if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+                pr_debug("Disable L2 IRQ %d\n", irq);
                 DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
                         mask_port, bit);
-                local_irq_save(flags);
 
                 /* Disable L2 IRQ - set mask bit */
                 mask = inb(mask_port) | bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+        pr_debug("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
 }
 
 static void enable_bigsur_l2irq(unsigned int irq)
 {
-        unsigned long flags;
         unsigned char mask;
         unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
         unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
 
-    if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
-                DPRINTK("Enable L2 IRQ %d\n", irq);
+       if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+                pr_debug("Enable L2 IRQ %d\n", irq);
                 DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n",
                         mask_port, bit);
-                local_irq_save(flags);
 
                 /* Enable L2 IRQ - clear mask bit */
                 mask = inb(mask_port) & ~bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+        pr_debug("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
 }
 
 static void mask_and_ack_bigsur(unsigned int irq)
 {
-        DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq);
+        pr_debug("mask_and_ack_bigsur IRQ %d\n", irq);
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
                 disable_bigsur_l1irq(irq);
         else
@@ -179,7 +166,7 @@ static void mask_and_ack_bigsur(unsigned int irq)
 
 static void end_bigsur_irq(unsigned int irq)
 {
-        DPRINTK("end_bigsur_irq IRQ %d\n", irq);
+        pr_debug("end_bigsur_irq IRQ %d\n", irq);
         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
                 if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
                         enable_bigsur_l1irq(irq);
@@ -193,7 +180,7 @@ static unsigned int startup_bigsur_irq(unsigned int irq)
         u8 mask;
         u32 reg;
 
-        DPRINTK("startup_bigsur_irq IRQ %d\n", irq);
+        pr_debug("startup_bigsur_irq IRQ %d\n", irq);
 
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
                 /* Enable the L1 IRQ */
@@ -218,7 +205,7 @@ static unsigned int startup_bigsur_irq(unsigned int irq)
 
 static void shutdown_bigsur_irq(unsigned int irq)
 {
-        DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq);
+        pr_debug("shutdown_bigsur_irq IRQ %d\n", irq);
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
                 disable_bigsur_l1irq(irq);
         else
@@ -260,7 +247,7 @@ static void make_bigsur_l1isr(unsigned int irq) {
                 disable_bigsur_l1irq(irq);
                 return;
         }
-        DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq);
+        pr_debug("make_bigsur_l1isr: bad irq, %d\n", irq);
         return;
 }
 
@@ -277,7 +264,7 @@ static void make_bigsur_l2isr(unsigned int irq) {
                 disable_bigsur_l2irq(irq);
                 return;
         }
-        DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq);
+        pr_debug("make_bigsur_l2isr: bad irq, %d\n", irq);
         return;
 }
 
index dfeede9da50f5129d570b61ee7a1d46d04448160..9711c20fc9e4b758a0e8e4b6f68ec024478f0b67 100644 (file)
 //             Big Sur Init Routines   
 /*===========================================================*/
 
-const char *get_system_type(void)
-{
-       return "Big Sur";
-}
-
-/*
- * The Machine Vector
- */
-extern void heartbeat_bigsur(void);
-extern void init_bigsur_IRQ(void);
-
-struct sh_machine_vector mv_bigsur __initmv = {
-       .mv_nr_irqs             = NR_IRQS,     // Defined in <asm/irq.h>
-
-       .mv_isa_port2addr       = bigsur_isa_port2addr,
-       .mv_irq_demux           = bigsur_irq_demux,
-
-       .mv_init_irq            = init_bigsur_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_bigsur,
-#endif
-};
-ALIAS_MV(bigsur)
-
-int __init platform_setup(void)
+static void __init bigsur_setup(char **cmdline_p)
 {
        /* Mask all 2nd level IRQ's */
        outb(-1,BIGSUR_IMR0);
@@ -89,7 +65,24 @@ int __init platform_setup(void)
        outw(1, BIGSUR_ETHR+0xe);
        /* set the IO port to BIGSUR_ETHER_IOPORT */
        outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
-
-       return 0;
 }
 
+/*
+ * The Machine Vector
+ */
+extern void heartbeat_bigsur(void);
+extern void init_bigsur_IRQ(void);
+
+struct sh_machine_vector mv_bigsur __initmv = {
+       .mv_name                = "Big Sur",
+       .mv_setup               = bigsur_setup,
+
+       .mv_isa_port2addr       = bigsur_isa_port2addr,
+       .mv_irq_demux           = bigsur_irq_demux,
+
+       .mv_init_irq            = init_bigsur_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_bigsur,
+#endif
+};
+ALIAS_MV(bigsur)
diff --git a/arch/sh/boards/cat68701/Makefile b/arch/sh/boards/cat68701/Makefile
deleted file mode 100644 (file)
index 52c1de0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the CAT-68701 specific parts of the kernel
-#
-
-obj-y   := setup.o irq.o
-
diff --git a/arch/sh/boards/cat68701/irq.c b/arch/sh/boards/cat68701/irq.c
deleted file mode 100644 (file)
index f9a6d18..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/sh/boards/cat68701/irq.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *               2001  Yutaro Ebihara
- *
- * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
- *
- * 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 <asm/irq.h>
-
-int cat68701_irq_demux(int irq)
-{
-        if(irq==13) return 14;
-        if(irq==7)  return 10;
-        return irq;
-}
-
-void init_cat68701_IRQ()
-{
-        make_imask_irq(10);
-        make_imask_irq(14);
-}
diff --git a/arch/sh/boards/cat68701/setup.c b/arch/sh/boards/cat68701/setup.c
deleted file mode 100644 (file)
index 90e5175..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 
- * linux/arch/sh/boards/cat68701/setup.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *               2001  Yutaro Ebihara
- *
- * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
- *
- * 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 <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/io.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-const char *get_system_type(void)
-{
-       return "CAT-68701";
-}
-
-#ifdef CONFIG_HEARTBEAT
-void heartbeat_cat68701()
-{
-        static unsigned int cnt = 0, period = 0 , bit = 0;
-        cnt += 1;
-        if (cnt < period) {
-                return;
-        }
-        cnt = 0;
-
-        /* Go through the points (roughly!):
-         * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
-         */
-        period = 110 - ( (300<<FSHIFT)/
-                         ((avenrun[0]/5) + (3<<FSHIFT)) );
-
-       if(bit){ bit=0; }else{ bit=1; }
-       outw(bit<<15,0x3fe);
-}
-#endif /* CONFIG_HEARTBEAT */
-
-unsigned long cat68701_isa_port2addr(unsigned long offset)
-{
-       /* CompactFlash (IDE) */
-       if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6))
-               return 0xba000000 + offset;
-
-       /* INPUT PORT */
-       if ((offset >= 0x3fc) && (offset <= 0x3fd))
-               return 0xb4007000 + offset;
-
-       /* OUTPUT PORT */
-       if ((offset >= 0x3fe) && (offset <= 0x3ff))
-               return 0xb4007400 + offset;
-
-       return offset + 0xb4000000; /* other I/O (EREA 5)*/
-}
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_cat68701 __initmv = {
-       .mv_nr_irqs             = 32,
-       .mv_isa_port2addr       = cat68701_isa_port2addr,
-       .mv_irq_demux           = cat68701_irq_demux,
-
-       .mv_init_irq            = init_cat68701_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_cat68701,
-#endif
-};
-ALIAS_MV(cat68701)
-
-int __init platform_setup(void)
-{
-       /* dummy read erea5 (CS8900A) */
-}
-
diff --git a/arch/sh/boards/cqreek/Makefile b/arch/sh/boards/cqreek/Makefile
deleted file mode 100644 (file)
index 1a788a8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the CqREEK specific parts of the kernel
-#
-
-obj-y   := setup.o irq.o
-
diff --git a/arch/sh/boards/cqreek/irq.c b/arch/sh/boards/cqreek/irq.c
deleted file mode 100644 (file)
index 2955adc..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $Id: irq.c,v 1.1.2.4 2002/11/04 20:33:56 lethal Exp $
- *
- * arch/sh/boards/cqreek/irq.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *
- * CqREEK IDE/ISA Bridge Support.
- *
- */
-
-#include <linux/irq.h>
-#include <linux/init.h>
-
-#include <asm/cqreek/cqreek.h>
-#include <asm/io.h>
-#include <asm/io_generic.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/rtc.h>
-
-struct cqreek_irq_data {
-       unsigned short mask_port;       /* Port of Interrupt Mask Register */
-       unsigned short stat_port;       /* Port of Interrupt Status Register */
-       unsigned short bit;             /* Value of the bit */
-};
-static struct cqreek_irq_data cqreek_irq_data[NR_IRQS];
-
-static void disable_cqreek_irq(unsigned int irq)
-{
-       unsigned long flags;
-       unsigned short mask;
-       unsigned short mask_port = cqreek_irq_data[irq].mask_port;
-       unsigned short bit = cqreek_irq_data[irq].bit;
-
-       local_irq_save(flags);
-       /* Disable IRQ */
-       mask = inw(mask_port) & ~bit;
-       outw_p(mask, mask_port);
-       local_irq_restore(flags);
-}
-
-static void enable_cqreek_irq(unsigned int irq)
-{
-       unsigned long flags;
-       unsigned short mask;
-       unsigned short mask_port = cqreek_irq_data[irq].mask_port;
-       unsigned short bit = cqreek_irq_data[irq].bit;
-
-       local_irq_save(flags);
-       /* Enable IRQ */
-       mask = inw(mask_port) | bit;
-       outw_p(mask, mask_port);
-       local_irq_restore(flags);
-}
-
-static void mask_and_ack_cqreek(unsigned int irq)
-{
-       unsigned short stat_port = cqreek_irq_data[irq].stat_port;
-       unsigned short bit = cqreek_irq_data[irq].bit;
-
-       disable_cqreek_irq(irq);
-       /* Clear IRQ (it might be edge IRQ) */
-       inw(stat_port);
-       outw_p(bit, stat_port);
-}
-
-static void end_cqreek_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_cqreek_irq(irq);
-}
-
-static unsigned int startup_cqreek_irq(unsigned int irq)
-{ 
-       enable_cqreek_irq(irq);
-       return 0;
-}
-
-static void shutdown_cqreek_irq(unsigned int irq)
-{
-       disable_cqreek_irq(irq);
-}
-
-static struct hw_interrupt_type cqreek_irq_type = {
-       .typename = "CqREEK-IRQ",
-       .startup = startup_cqreek_irq,
-       .shutdown = shutdown_cqreek_irq,
-       .enable = enable_cqreek_irq,
-       .disable = disable_cqreek_irq,
-       .ack = mask_and_ack_cqreek,
-       .end = end_cqreek_irq
-};
-
-int cqreek_has_ide, cqreek_has_isa;
-
-/* XXX: This is just for test for my NE2000 ISA board
-   What we really need is virtualized IRQ and demultiplexer like HP600 port */
-void __init init_cqreek_IRQ(void)
-{
-       if (cqreek_has_ide) {
-               cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK;
-               cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT;
-               cqreek_irq_data[14].bit = 1;
-
-               irq_desc[14].chip = &cqreek_irq_type;
-               irq_desc[14].status = IRQ_DISABLED;
-               irq_desc[14].action = 0;
-               irq_desc[14].depth = 1;
-
-               disable_cqreek_irq(14);
-       }
-
-       if (cqreek_has_isa) {
-               cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK;
-               cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT;
-               cqreek_irq_data[10].bit = (1 << 10);
-
-               /* XXX: Err... we may need demultiplexer for ISA irq... */
-               irq_desc[10].chip = &cqreek_irq_type;
-               irq_desc[10].status = IRQ_DISABLED;
-               irq_desc[10].action = 0;
-               irq_desc[10].depth = 1;
-
-               disable_cqreek_irq(10);
-       }
-}
-
diff --git a/arch/sh/boards/cqreek/setup.c b/arch/sh/boards/cqreek/setup.c
deleted file mode 100644 (file)
index eff4ed9..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* $Id: setup.c,v 1.5 2003/08/04 01:51:58 lethal Exp $
- *
- * arch/sh/kernel/setup_cqreek.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *
- * CqREEK IDE/ISA Bridge Support.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/mach/cqreek.h>
-#include <asm/machvec.h>
-#include <asm/io.h>
-#include <asm/io_generic.h>
-#include <asm/irq.h>
-#include <asm/rtc.h>
-
-#define IDE_OFFSET 0xA4000000UL
-#define ISA_OFFSET 0xA4A00000UL
-
-const char *get_system_type(void)
-{
-       return "CqREEK";
-}
-
-static unsigned long cqreek_port2addr(unsigned long port)
-{
-       if (0x0000<=port && port<=0x0040)
-               return IDE_OFFSET + port;
-       if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
-               return IDE_OFFSET + port;
-
-       return ISA_OFFSET + port;
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_cqreek __initmv = {
-#if defined(CONFIG_CPU_SH4)
-       .mv_nr_irqs             = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-       .mv_nr_irqs             = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
-       .mv_nr_irqs             = 61,
-#endif
-
-       .mv_init_irq            = init_cqreek_IRQ,
-
-       .mv_isa_port2addr       = cqreek_port2addr,
-};
-ALIAS_MV(cqreek)
-
-/*
- * Initialize the board
- */
-void __init platform_setup(void)
-{
-       int i;
-/* udelay is not available at setup time yet... */
-#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
-
-       if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
-               outw_p(0, BRIDGE_IDE_INTR_LVL);
-               outw_p(0, BRIDGE_IDE_INTR_MASK);
-
-               outw_p(0, BRIDGE_IDE_CTRL);
-               DELAY();
-
-               outw_p(0x8000, BRIDGE_IDE_CTRL);
-               DELAY();
-
-               outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
-               outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
-               outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
-               cqreek_has_ide=1;
-       }
-
-       if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
-               outw_p(0, BRIDGE_ISA_INTR_LVL);
-               outw_p(0, BRIDGE_ISA_INTR_MASK);
-
-               outw_p(0, BRIDGE_ISA_CTRL);
-               DELAY();
-               outw_p(0x8000, BRIDGE_ISA_CTRL);
-               DELAY();
-
-               outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
-               outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
-               outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
-               cqreek_has_isa=1;
-       }
-
-       printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", cqreek_has_ide, cqreek_has_isa);
-}
-
diff --git a/arch/sh/boards/dmida/Makefile b/arch/sh/boards/dmida/Makefile
deleted file mode 100644 (file)
index 75999aa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
-# of the kernel
-#
-
-obj-y   := mach.o
-
diff --git a/arch/sh/boards/dmida/mach.c b/arch/sh/boards/dmida/mach.c
deleted file mode 100644 (file)
index d03a25f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * linux/arch/sh/boards/dmida/mach.c
- *
- * by Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc
- *
- * Derived from mach_hp600.c, which bore the message:
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the DataMyte Industrial Digital Assistant(tm).
- * See http://www.dmida.com
- *
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/irq.h>
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_dmida __initmv = {
-       .mv_nr_irqs             = HD64465_IRQ_BASE+HD64465_IRQ_NUM,
-
-       .mv_inb                 = hd64465_inb,
-       .mv_inw                 = hd64465_inw,
-       .mv_inl                 = hd64465_inl,
-       .mv_outb                = hd64465_outb,
-       .mv_outw                = hd64465_outw,
-       .mv_outl                = hd64465_outl,
-
-       .mv_inb_p               = hd64465_inb_p,
-       .mv_inw_p               = hd64465_inw,
-       .mv_inl_p               = hd64465_inl,
-       .mv_outb_p              = hd64465_outb_p,
-       .mv_outw_p              = hd64465_outw,
-       .mv_outl_p              = hd64465_outl,
-
-       .mv_insb                = hd64465_insb,
-       .mv_insw                = hd64465_insw,
-       .mv_insl                = hd64465_insl,
-       .mv_outsb               = hd64465_outsb,
-       .mv_outsw               = hd64465_outsw,
-       .mv_outsl               = hd64465_outsl,
-
-       .mv_irq_demux           = hd64465_irq_demux,
-};
-ALIAS_MV(dmida)
-
index b10a6b11c0343e8c4390d5b550790e8cf2390dfb..5bf01f86c20c52cc4eb53969141838b9dc65884a 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/irq.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dreamcast/sysasic.h>
    event.
 
    There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908.  Event
-   types can be found in include/asm-sh/dc_sysasic.h.  There are three groups
-   of EMRs that parallel the ESRs.  Each EMR group corresponds to an IRQ, so
-   0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers
-   IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
+   types can be found in include/asm-sh/dreamcast/sysasic.h. There are three
+   groups of EMRs that parallel the ESRs.  Each EMR group corresponds to an
+   IRQ, so 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928
+   triggers IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
 
    In the kernel, these events are mapped to virtual IRQs so that drivers can
    respond to them as they would a normal interrupt.  In order to keep this
 /* Disable the hardware event by masking its bit in its EMR */
 static inline void disable_systemasic_irq(unsigned int irq)
 {
-        unsigned long flags;
         __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
         __u32 mask;
 
-        local_irq_save(flags);
         mask = inl(emr);
         mask &= ~(1 << EVENT_BIT(irq));
         outl(mask, emr);
-        local_irq_restore(flags);
 }
 
 /* Enable the hardware event by setting its bit in its EMR */
 static inline void enable_systemasic_irq(unsigned int irq)
 {
-        unsigned long flags;
         __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
         __u32 mask;
 
-        local_irq_save(flags);
         mask = inl(emr);
         mask |= (1 << EVENT_BIT(irq));
         outl(mask, emr);
-        local_irq_restore(flags);
 }
 
 /* Acknowledge a hardware event by writing its bit back to its ESR */
index 379de1629134daa5b91c645a3ba228e0d55192d3..b3a876a3b85978363e7b9de6ccf5a464a026b55c 100644 (file)
@@ -1,4 +1,5 @@
-/* arch/sh/kernel/rtc-aica.c
+/*
+ * arch/sh/boards/dreamcast/rtc.c
  *
  * Dreamcast AICA RTC routines.
  *
  */
 
 #include <linux/time.h>
-
+#include <asm/rtc.h>
 #include <asm/io.h>
 
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
-
 /* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in
-   seconds to get the standard Unix Epoch when getting the time, and add 20
-   years when setting the time. */
+   seconds) to get the standard Unix Epoch when getting the time, and add
+   20 years when setting the time. */
 #define TWENTY_YEARS ((20 * 365LU + 5) * 86400)
 
 /* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit
@@ -32,7 +30,8 @@ extern int (*rtc_set_time)(const time_t);
  *
  * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
  */
-void aica_rtc_gettimeofday(struct timespec *ts) {
+void aica_rtc_gettimeofday(struct timespec *ts)
+{
        unsigned long val1, val2;
 
        do {
@@ -55,7 +54,8 @@ void aica_rtc_gettimeofday(struct timespec *ts) {
  *
  * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter.
  */
-int aica_rtc_settimeofday(const time_t secs) {
+int aica_rtc_settimeofday(const time_t secs)
+{
        unsigned long val1, val2;
        unsigned long adj = secs + TWENTY_YEARS;
 
@@ -75,7 +75,7 @@ int aica_rtc_settimeofday(const time_t secs) {
 
 void aica_time_init(void)
 {
-       rtc_get_time = aica_rtc_gettimeofday;
-       rtc_set_time = aica_rtc_settimeofday;
+       rtc_sh_get_time = aica_rtc_gettimeofday;
+       rtc_sh_set_time = aica_rtc_settimeofday;
 }
 
index 0027b80a23435cfd005e45f255ddd62fd5801a52..f13017eeeb27ebba6cb68571044155fcf7d6a5a0 100644 (file)
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/device.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/rtc.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
 #include <asm/mach/sysasic.h>
 
 extern struct hw_interrupt_type systemasic_int;
-/* XXX: Move this into it's proper header. */
-extern void (*board_time_init)(void);
 extern void aica_time_init(void);
 extern int gapspci_init(void);
 extern int systemasic_irq_demux(int);
 
-void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
 int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
-const char *get_system_type(void)
-{
-       return "Sega Dreamcast";
-}
-
-struct sh_machine_vector mv_dreamcast __initmv = {
-       .mv_nr_irqs             = NR_IRQS,
-
-       .mv_irq_demux           = systemasic_irq_demux,
-
-#ifdef CONFIG_PCI
-       .mv_consistent_alloc    = dreamcast_consistent_alloc,
-       .mv_consistent_free     = dreamcast_consistent_free,
-#endif
-};
-ALIAS_MV(dreamcast)
-
-int __init platform_setup(void)
+static void __init dreamcast_setup(char **cmdline_p)
 {
        int i;
 
@@ -78,6 +58,16 @@ int __init platform_setup(void)
        if (gapspci_init() < 0)
                printk(KERN_WARNING "GAPSPCI was not detected.\n");
 #endif
-
-       return 0;
 }
+
+struct sh_machine_vector mv_dreamcast __initmv = {
+       .mv_name                = "Sega Dreamcast",
+       .mv_setup               = dreamcast_setup,
+       .mv_irq_demux           = systemasic_irq_demux,
+
+#ifdef CONFIG_PCI
+       .mv_consistent_alloc    = dreamcast_consistent_alloc,
+       .mv_consistent_free     = dreamcast_consistent_free,
+#endif
+};
+ALIAS_MV(dreamcast)
index 4b3ef16a0e960dc11d207966454e902dfc3e42c2..902bc975a13e0b82a03cae13bc1dbd06bceca698 100644 (file)
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/types.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/machvec.h>
 #include <asm/mach/ec3104.h>
 
-const char *get_system_type(void)
+static void __init ec3104_setup(char **cmdline_p)
 {
-       return "EC3104";
+       char str[8];
+       int i;
+
+       for (i=0; i<8; i++)
+               str[i] = ctrl_readb(EC3104_BASE + i);
+
+       for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
+               irq_desc[i].handler = &ec3104_int;
+
+       printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
+              str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
+
+       /* mask all interrupts.  this should have been done by the boot
+        * loader for us but we want to be sure ... */
+       ctrl_writel(0xffffffff, EC3104_IMR);
 }
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_ec3104 __initmv = {
+       .mv_name        = "EC3104",
+       .mv_setup       = ec3104_setup,
        .mv_nr_irqs     = 96,
 
        .mv_inb         = ec3104_inb,
@@ -48,31 +62,4 @@ struct sh_machine_vector mv_ec3104 __initmv = {
 
        .mv_irq_demux   = ec3104_irq_demux,
 };
-
 ALIAS_MV(ec3104)
-
-int __init platform_setup(void)
-{
-       char str[8];
-       int i;
-       
-       if (0)
-               return 0;
-
-       for (i=0; i<8; i++)
-               str[i] = ctrl_readb(EC3104_BASE + i);
-
-       for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++)
-               irq_desc[i].chip = &ec3104_int;
-
-       printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n",
-              str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE);
-
-
-       /* mask all interrupts.  this should have been done by the boot
-        * loader for us but we want to be sure ... */
-       ctrl_writel(0xffffffff, EC3104_IMR);
-       
-       return 0;
-}
-
diff --git a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile
deleted file mode 100644 (file)
index eb753d3..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for STMicroelectronics board specific parts of the kernel
-#
-
-obj-y := irq.o setup.o mach.o led.o
-
-obj-$(CONFIG_PCI) += pcidma.o
-
diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c
deleted file mode 100644 (file)
index 96bb41c..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Looks after interrupts on the HARP board.
- *
- * Bases on the IPR irq system
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-
-#define NUM_EXTERNAL_IRQS 16
-
-// Early versions of the STB1 Overdrive required this nasty frig
-//#define INVERT_INTMASK_WRITES
-
-static void enable_harp_irq(unsigned int irq);
-static void disable_harp_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_harp_irq disable_harp_irq
-
-static void mask_and_ack_harp(unsigned int);
-static void end_harp_irq(unsigned int irq);
-
-static unsigned int startup_harp_irq(unsigned int irq)
-{
-       enable_harp_irq(irq);
-       return 0;               /* never anything pending */
-}
-
-static struct hw_interrupt_type harp_irq_type = {
-       .typename = "Harp-IRQ",
-       .startup = startup_harp_irq,
-       .shutdown = shutdown_harp_irq,
-       .enable = enable_harp_irq,
-       .disable = disable_harp_irq,
-       .ack = mask_and_ack_harp,
-       .end = end_harp_irq
-};
-
-static void disable_harp_irq(unsigned int irq)
-{
-       unsigned val, flags;
-       unsigned maskReg;
-       unsigned mask;
-       int pri;
-
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-       pri = 15 - irq;
-
-       if (pri < 8) {
-               maskReg = EPLD_INTMASK0;
-       } else {
-               maskReg = EPLD_INTMASK1;
-               pri -= 8;
-       }
-
-       local_irq_save(flags);
-       mask = ctrl_inl(maskReg);
-       mask &= (~(1 << pri));
-#if defined(INVERT_INTMASK_WRITES)
-       mask ^= 0xff;
-#endif
-       ctrl_outl(mask, maskReg);
-       local_irq_restore(flags);
-}
-
-static void enable_harp_irq(unsigned int irq)
-{
-       unsigned flags;
-       unsigned maskReg;
-       unsigned mask;
-       int pri;
-
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-       pri = 15 - irq;
-
-       if (pri < 8) {
-               maskReg = EPLD_INTMASK0;
-       } else {
-               maskReg = EPLD_INTMASK1;
-               pri -= 8;
-       }
-
-       local_irq_save(flags);
-       mask = ctrl_inl(maskReg);
-
-
-       mask |= (1 << pri);
-
-#if defined(INVERT_INTMASK_WRITES)
-       mask ^= 0xff;
-#endif
-       ctrl_outl(mask, maskReg);
-
-       local_irq_restore(flags);
-}
-
-/* This functions sets the desired irq handler to be an overdrive type */
-static void __init make_harp_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &harp_irq_type;
-       disable_harp_irq(irq);
-}
-
-static void mask_and_ack_harp(unsigned int irq)
-{
-       disable_harp_irq(irq);
-}
-
-static void end_harp_irq(unsigned int irq)
-{
-       enable_harp_irq(irq);
-}
-
-void __init init_harp_irq(void)
-{
-       int i;
-
-#if !defined(INVERT_INTMASK_WRITES)
-       // On the harp these are set to enable an interrupt
-       ctrl_outl(0x00, EPLD_INTMASK0);
-       ctrl_outl(0x00, EPLD_INTMASK1);
-#else
-       // On the Overdrive the data is inverted before being stored in the reg
-       ctrl_outl(0xff, EPLD_INTMASK0);
-       ctrl_outl(0xff, EPLD_INTMASK1);
-#endif
-
-       for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
-               make_harp_irq(i);
-       }
-}
diff --git a/arch/sh/boards/harp/led.c b/arch/sh/boards/harp/led.c
deleted file mode 100644 (file)
index aeb7b39..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/arch/sh/stboards/led.c
- *
- * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains ST40STB1 HARP and compatible code.
- */
-
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */
-/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */
-/* Works for HARP and overdrive */
-static void mach_led(int position, int value)
-{
-       if (value) {
-               ctrl_outl(EPLD_LED_ON, EPLD_LED);
-       } else {
-               ctrl_outl(EPLD_LED_OFF, EPLD_LED);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* acts like an actual heart beat -- ie thump-thump-pause... */
-void heartbeat_harp(void)
-{
-       static unsigned cnt = 0, period = 0, dist = 0;
-
-       if (cnt == 0 || cnt == dist)
-               mach_led( -1, 1);
-       else if (cnt == 7 || cnt == dist+7)
-               mach_led( -1, 0);
-
-       if (++cnt > period) {
-               cnt = 0;
-               /* The hyperbolic function below modifies the heartbeat period
-                * length in dependency of the current (5min) load. It goes
-                * through the points f(0)=126, f(1)=86, f(5)=51,
-                * f(inf)->30. */
-               period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-               dist = period / 4;
-       }
-}
-#endif
diff --git a/arch/sh/boards/harp/mach.c b/arch/sh/boards/harp/mach.c
deleted file mode 100644 (file)
index a946dd1..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/arch/sh/boards/harp/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the STMicroelectronics STB1 HARP and compatible boards
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-#include <asm/hd64465/io.h>
-#include <asm/hd64465/hd64465.h>
-
-void setup_harp(void);
-void init_harp_irq(void);
-void heartbeat_harp(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_harp __initmv = {
-       .mv_nr_irqs             = 89 + HD64465_IRQ_NUM,
-
-       .mv_inb                 = hd64465_inb,
-       .mv_inw                 = hd64465_inw,
-       .mv_inl                 = hd64465_inl,
-       .mv_outb                = hd64465_outb,
-       .mv_outw                = hd64465_outw,
-       .mv_outl                = hd64465_outl,
-
-       .mv_inb_p               = hd64465_inb_p,
-       .mv_inw_p               = hd64465_inw,
-       .mv_inl_p               = hd64465_inl,
-       .mv_outb_p              = hd64465_outb_p,
-       .mv_outw_p              = hd64465_outw,
-       .mv_outl_p              = hd64465_outl,
-
-       .mv_insb                = hd64465_insb,
-       .mv_insw                = hd64465_insw,
-       .mv_insl                = hd64465_insl,
-       .mv_outsb               = hd64465_outsb,
-       .mv_outsw               = hd64465_outsw,
-       .mv_outsl               = hd64465_outsl,
-
-        .mv_isa_port2addr       = hd64465_isa_port2addr,
-
-#ifdef CONFIG_PCI
-       .mv_init_irq            = init_harp_irq,
-#endif
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_harp,
-#endif
-};
-
-ALIAS_MV(harp)
diff --git a/arch/sh/boards/harp/pcidma.c b/arch/sh/boards/harp/pcidma.c
deleted file mode 100644 (file)
index 4753113..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Dynamic DMA mapping support.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                          dma_addr_t * dma_handle)
-{
-       void *ret;
-       int gfp = GFP_ATOMIC;
-
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               /* Is it neccessary to do the memset? */
-               memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-       }
-       /* We must flush the cache before we pass it on to the device */
-       flush_cache_all();
-       return  P2SEGADDR(ret);
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle)
-{
-        unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
-
-       free_pages(p1addr, get_order(size));
-}
diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c
deleted file mode 100644 (file)
index 886e450..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * arch/sh/stboard/setup.c
- *
- * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * STMicroelectronics ST40STB1 HARP and compatible support.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-const char *get_system_type(void)
-{
-       return "STB1 Harp";
-}
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-#ifdef CONFIG_SH_STB1_HARP
-       unsigned long ic8_version, ic36_version;
-
-       ic8_version = ctrl_inl(EPLD_REVID2);
-       ic36_version = ctrl_inl(EPLD_REVID1);
-
-        printk("STMicroelectronics STB1 HARP initialisaton\n");
-        printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n",
-               (ic8_version >> 4) & 0xf, ic8_version & 0xf,
-               (ic36_version >> 4) & 0xf, ic36_version & 0xf);
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-       unsigned long version;
-
-       version = ctrl_inl(EPLD_REVID);
-
-        printk("STMicroelectronics STB1 Overdrive initialisaton\n");
-        printk("EPLD version: %d.%02d\n",
-              (version >> 4) & 0xf, version & 0xf);
-#else
-#error Undefined machine
-#endif
-        /* Currently all STB1 chips have problems with the sleep instruction,
-         * so disable it here.
-         */
-       disable_hlt();
-
-       return 0;
-}
-
-/*
- * pcibios_map_platform_irq
- *
- * This is board specific and returns the IRQ for a given PCI device.
- * It is used by the PCI code (arch/sh/kernel/st40_pci*)
- *
- */
-
-#define HARP_PCI_IRQ    1
-#define HARP_BRIDGE_IRQ 2
-#define OVERDRIVE_SLOT0_IRQ 0
-
-
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       switch (slot) {
-#ifdef CONFIG_SH_STB1_HARP
-       case 2:         /*This is the PCI slot on the */
-               return HARP_PCI_IRQ;
-       case 1:         /* this is the bridge */
-               return HARP_BRIDGE_IRQ;
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-       case 1:
-       case 2:
-       case 3:
-               return slot - 1;
-#else
-#error Unknown board
-#endif
-       default:
-               return -1;
-       }
-}
-
index 927fe0aa5dfa7ba65daddf881d9ca41577cedd4d..ff1b7f5b4e918a03378d78c50efb9772b7a85fcf 100644 (file)
@@ -2,5 +2,6 @@
 # Makefile for the HP6xx specific parts of the kernel
 #
 
-obj-y   := mach.o setup.o
-
+obj-y                  := setup.o
+obj-$(CONFIG_PM)       += pm.o pm_wakeup.o
+obj-$(CONFIG_APM)      += hp6xx_apm.o
diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c
new file mode 100644 (file)
index 0000000..ad0e712
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * bios-less APM driver for hp680
+ *
+ * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/apm_bios.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/apm.h>
+#include <asm/adc.h>
+#include <asm/hp6xx/hp6xx.h>
+
+#define SH7709_PGDR                    0xa400012c
+
+#define APM_CRITICAL                   10
+#define APM_LOW                                30
+
+#define HP680_BATTERY_MAX              875
+#define HP680_BATTERY_MIN              600
+#define HP680_BATTERY_AC_ON            900
+
+#define MODNAME "hp6x0_apm"
+
+static int hp6x0_apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+       u8 pgdr;
+       char *p;
+       int battery_status;
+       int battery_flag;
+       int ac_line_status;
+       int time_units = APM_BATTERY_LIFE_UNKNOWN;
+
+       int battery = adc_single(ADC_CHANNEL_BATTERY);
+       int backup = adc_single(ADC_CHANNEL_BACKUP);
+       int charging = adc_single(ADC_CHANNEL_CHARGE);
+       int percentage;
+
+       percentage = 100 * (battery - HP680_BATTERY_MIN) /
+                          (HP680_BATTERY_MAX - HP680_BATTERY_MIN);
+
+       ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
+                        APM_AC_ONLINE : APM_AC_OFFLINE;
+
+       p = buf;
+
+       pgdr = ctrl_inb(SH7709_PGDR);
+       if (pgdr & PGDR_MAIN_BATTERY_OUT) {
+               battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
+               battery_flag = 0x80;
+               percentage = -1;
+       } else if (charging < 8 ) {
+               battery_status = APM_BATTERY_STATUS_CHARGING;
+               battery_flag = 0x08;
+               ac_line_status = 0xff;
+       } else if (percentage <= APM_CRITICAL) {
+               battery_status = APM_BATTERY_STATUS_CRITICAL;
+               battery_flag = 0x04;
+       } else if (percentage <= APM_LOW) {
+               battery_status = APM_BATTERY_STATUS_LOW;
+               battery_flag = 0x02;
+       } else {
+               battery_status = APM_BATTERY_STATUS_HIGH;
+               battery_flag = 0x01;
+       }
+
+       p += sprintf(p, "1.0 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+                    APM_32_BIT_SUPPORT,
+                    ac_line_status,
+                    battery_status,
+                    battery_flag,
+                    percentage,
+                    time_units,
+                    "min");
+       p += sprintf(p, "bat=%d backup=%d charge=%d\n",
+                    battery, backup, charging);
+
+       return p - buf;
+}
+
+static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+       if (!apm_suspended)
+               apm_queue_event(APM_USER_SUSPEND);
+
+       return IRQ_HANDLED;
+}
+
+static int __init hp6x0_apm_init(void)
+{
+       int ret;
+
+       ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
+                         SA_INTERRUPT, MODNAME, 0);
+       if (unlikely(ret < 0)) {
+               printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
+                      HP680_BTN_IRQ);
+               return ret;
+       }
+
+       apm_get_info = hp6x0_apm_get_info;
+
+       return ret;
+}
+
+static void __exit hp6x0_apm_exit(void)
+{
+       free_irq(HP680_BTN_IRQ, 0);
+       apm_get_info = 0;
+}
+
+module_init(hp6x0_apm_init);
+module_exit(hp6x0_apm_exit);
+
+MODULE_AUTHOR("Adriy Skulysh");
+MODULE_DESCRIPTION("hp6xx Advanced Power Management");
+MODULE_LICENSE("GPL");
diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c
new file mode 100644 (file)
index 0000000..0e501bc
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * hp6x0 Power Management Routines
+ *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <asm/hd64461.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/cpu/dac.h>
+#include <asm/pm.h>
+
+#define STBCR          0xffffff82
+#define STBCR2         0xffffff88
+
+static int hp6x0_pm_enter(suspend_state_t state)
+{
+       u8 stbcr, stbcr2;
+#ifdef CONFIG_HD64461_ENABLER
+       u8 scr;
+       u16 hd64461_stbcr;
+#endif
+
+       if (state != PM_SUSPEND_MEM)
+               return -EINVAL;
+
+#ifdef CONFIG_HD64461_ENABLER
+       outb(0, HD64461_PCC1CSCIER);
+
+       scr = inb(HD64461_PCC1SCR);
+       scr |= HD64461_PCCSCR_VCC1;
+       outb(scr, HD64461_PCC1SCR);
+
+       hd64461_stbcr = inw(HD64461_STBCR);
+       hd64461_stbcr |= HD64461_STBCR_SPC1ST;
+       outw(hd64461_stbcr, HD64461_STBCR);
+#endif
+
+       ctrl_outb(0x1f, DACR);
+
+       stbcr = ctrl_inb(STBCR);
+       ctrl_outb(0x01, STBCR);
+
+       stbcr2 = ctrl_inb(STBCR2);
+       ctrl_outb(0x7f , STBCR2);
+
+       outw(0xf07f, HD64461_SCPUCR);
+
+       pm_enter();
+
+       outw(0, HD64461_SCPUCR);
+       ctrl_outb(stbcr, STBCR);
+       ctrl_outb(stbcr2, STBCR2);
+
+#ifdef CONFIG_HD64461_ENABLER
+       hd64461_stbcr = inw(HD64461_STBCR);
+       hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
+       outw(hd64461_stbcr, HD64461_STBCR);
+
+       outb(0x4c, HD64461_PCC1CSCIER);
+       outb(0x00, HD64461_PCC1CSCR);
+#endif
+
+       return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops hp6x0_pm_ops = {
+       .pm_disk_mode   = PM_DISK_FIRMWARE,
+       .enter          = hp6x0_pm_enter,
+};
+
+static int __init hp6x0_pm_init(void)
+{
+       pm_set_ops(&hp6x0_pm_ops);
+       return 0;
+}
+
+late_initcall(hp6x0_pm_init);
diff --git a/arch/sh/boards/hp6xx/pm_wakeup.S b/arch/sh/boards/hp6xx/pm_wakeup.S
new file mode 100644 (file)
index 0000000..45e9bf0
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.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/linkage.h>
+#include <asm/cpu/mmu_context.h>
+
+#define k0     r0
+#define k1     r1
+#define k2     r2
+#define k3     r3
+#define k4     r4
+
+/*
+ * Kernel mode register usage:
+ *     k0      scratch
+ *     k1      scratch
+ *     k2      scratch (Exception code)
+ *     k3      scratch (Return address)
+ *     k4      scratch
+ *     k5      reserved
+ *     k6      Global Interrupt Mask (0--15 << 4)
+ *     k7      CURRENT_THREAD_INFO (pointer to current thread info)
+ */
+
+ENTRY(wakeup_start)
+! clear STBY bit
+       mov     #-126, k2
+       and     #127, k0
+       mov.b   k0, @k2
+! enable refresh
+       mov.l   5f, k1
+       mov.w   6f, k0
+       mov.w   k0, @k1
+! jump to handler
+       mov.l   2f, k2
+       mov.l   3f, k3
+       mov.l   @k2, k2
+
+       mov.l   4f, k1
+       jmp     @k1
+       nop
+
+       .align  2
+1:     .long   EXPEVT
+2:     .long   INTEVT
+3:     .long   ret_from_irq
+4:     .long   handle_exception
+5:     .long   0xffffff68
+6:     .word   0x0524
+
+ENTRY(wakeup_end)
+       nop
index 71f315663cc964fb3c51f4b40963ea015b522b8c..60ab17ad60544d79111f8ab807943875f1fa8780 100644 (file)
@@ -8,22 +8,22 @@
  *
  * Setup code for an HP680  (internal peripherials only)
  */
-
+#include <linux/types.h>
 #include <linux/init.h>
-#include <asm/io.h>
 #include <asm/hd64461.h>
+#include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/hp6xx/hp6xx.h>
 #include <asm/cpu/dac.h>
 
-const char *get_system_type(void)
-{
-       return "HP6xx";
-}
+#define        SCPCR   0xa4000116
+#define SCPDR  0xa4000136
 
-int __init platform_setup(void)
+static void __init hp6xx_setup(char **cmdline_p)
 {
        u8 v8;
        u16 v;
+
        v = inw(HD64461_STBCR);
        v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
            HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
@@ -50,5 +50,51 @@ int __init platform_setup(void)
        v8 &= ~DACR_DAE;
        ctrl_outb(v8,DACR);
 
-       return 0;
+       v8 = ctrl_inb(SCPDR);
+       v8 |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
+       v8 &= ~SCPDR_TS_SCAN_ENABLE;
+       ctrl_outb(v8, SCPDR);
+
+       v = ctrl_inw(SCPCR);
+       v &= ~SCPCR_TS_MASK;
+       v |= SCPCR_TS_ENABLE;
+       ctrl_outw(v, SCPCR);
 }
+
+/*
+ * XXX: This is stupid, we should have a generic machine vector for the cchips
+ * and just wrap the platform setup code in to this, as it's the only thing
+ * that ends up being different.
+ */
+struct sh_machine_vector mv_hp6xx __initmv = {
+       .mv_name = "hp6xx",
+       .mv_setup = hp6xx_setup,
+       .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
+
+       .mv_inb = hd64461_inb,
+       .mv_inw = hd64461_inw,
+       .mv_inl = hd64461_inl,
+       .mv_outb = hd64461_outb,
+       .mv_outw = hd64461_outw,
+       .mv_outl = hd64461_outl,
+
+       .mv_inb_p = hd64461_inb_p,
+       .mv_inw_p = hd64461_inw,
+       .mv_inl_p = hd64461_inl,
+       .mv_outb_p = hd64461_outb_p,
+       .mv_outw_p = hd64461_outw,
+       .mv_outl_p = hd64461_outl,
+
+       .mv_insb = hd64461_insb,
+       .mv_insw = hd64461_insw,
+       .mv_insl = hd64461_insl,
+       .mv_outsb = hd64461_outsb,
+       .mv_outsw = hd64461_outsw,
+       .mv_outsl = hd64461_outsl,
+
+       .mv_readw = hd64461_readw,
+       .mv_writew = hd64461_writew,
+
+       .mv_irq_demux = hd64461_irq_demux,
+};
+ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/landisk/Makefile b/arch/sh/boards/landisk/Makefile
new file mode 100644 (file)
index 0000000..89e4beb
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
+#
+
+obj-y   := setup.o io.o irq.o rtc.o landisk_pwb.o
diff --git a/arch/sh/boards/landisk/io.c b/arch/sh/boards/landisk/io.c
new file mode 100644 (file)
index 0000000..92498b4
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * arch/sh/boards/landisk/io.c
+ *
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for I-O Data Device, Inc. LANDISK.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_landisk.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+/*
+ * modifed by kogiidena
+ * 2005.03.03
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+extern void *area5_io_base;    /* Area 5 I/O Base address */
+extern void *area6_io_base;    /* Area 6 I/O Base address */
+
+static inline unsigned long port2adr(unsigned int port)
+{
+       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+               if (port == 0x3f6)
+                       return ((unsigned long)area5_io_base + 0x2c);
+               else
+                       return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
+                               ((port - 0x1f0) << 1));
+       else if ((0x170 <= port && port < 0x178) || port == 0x376)
+               if (port == 0x376)
+                       return ((unsigned long)area6_io_base + 0x2c);
+               else
+                       return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
+                               ((port - 0x170) << 1));
+       else
+               maybebadio((unsigned long)port);
+
+       return port;
+}
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used  w/o translation for
+ * compatibility.
+ */
+u8 landisk_inb(unsigned long port)
+{
+       if (PXSEG(port))
+               return ctrl_inb(port);
+       else if (is_pci_ioaddr(port))
+               return ctrl_inb(pci_ioaddr(port));
+
+       return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 landisk_inb_p(unsigned long port)
+{
+       u8 v;
+
+       if (PXSEG(port))
+               v = ctrl_inb(port);
+       else if (is_pci_ioaddr(port))
+               v = ctrl_inb(pci_ioaddr(port));
+       else
+               v = ctrl_inw(port2adr(port)) & 0xff;
+
+       ctrl_delay();
+
+       return v;
+}
+
+u16 landisk_inw(unsigned long port)
+{
+       if (PXSEG(port))
+               return ctrl_inw(port);
+       else if (is_pci_ioaddr(port))
+               return ctrl_inw(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+u32 landisk_inl(unsigned long port)
+{
+       if (PXSEG(port))
+               return ctrl_inl(port);
+       else if (is_pci_ioaddr(port))
+               return ctrl_inl(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+void landisk_outb(u8 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outb(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(port));
+}
+
+void landisk_outb_p(u8 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outb(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(port));
+       ctrl_delay();
+}
+
+void landisk_outw(u16 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outw(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outw(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void landisk_outl(u32 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outl(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outl(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void landisk_insb(unsigned long port, void *dst, unsigned long count)
+{
+        volatile u16 *p;
+        u8 *buf = dst;
+
+        if (PXSEG(port)) {
+                while (count--)
+                        *buf++ = *(volatile u8 *)port;
+       } else if (is_pci_ioaddr(port)) {
+                volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+                while (count--)
+                        *buf++ = *bp;
+       } else {
+                p = (volatile u16 *)port2adr(port);
+                while (count--)
+                        *buf++ = *p & 0xff;
+       }
+}
+
+void landisk_insw(unsigned long port, void *dst, unsigned long count)
+{
+        volatile u16 *p;
+        u16 *buf = dst;
+
+       if (PXSEG(port))
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port))
+               p = (volatile u16 *)pci_ioaddr(port);
+       else
+               p = (volatile u16 *)port2adr(port);
+       while (count--)
+               *buf++ = *p;
+}
+
+void landisk_insl(unsigned long port, void *dst, unsigned long count)
+{
+        u32 *buf = dst;
+
+       if (is_pci_ioaddr(port)) {
+                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+                while (count--)
+                        *buf++ = *p;
+       } else
+               maybebadio(port);
+}
+
+void landisk_outsb(unsigned long port, const void *src, unsigned long count)
+{
+        volatile u16 *p;
+        const u8 *buf = src;
+
+       if (PXSEG(port))
+                while (count--)
+                        ctrl_outb(*buf++, port);
+       else if (is_pci_ioaddr(port)) {
+                volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+                while (count--)
+                        *bp = *buf++;
+       } else {
+                p = (volatile u16 *)port2adr(port);
+                while (count--)
+                        *p = *buf++;
+       }
+}
+
+void landisk_outsw(unsigned long port, const void *src, unsigned long count)
+{
+        volatile u16 *p;
+        const u16 *buf = src;
+
+       if (PXSEG(port))
+                p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port))
+                p = (volatile u16 *)pci_ioaddr(port);
+       else
+                p = (volatile u16 *)port2adr(port);
+
+        while (count--)
+                *p = *buf++;
+}
+
+void landisk_outsl(unsigned long port, const void *src, unsigned long count)
+{
+        const u32 *buf = src;
+
+       if (is_pci_ioaddr(port)) {
+                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+                while (count--)
+                        *p = *buf++;
+       } else
+               maybebadio(port);
+}
+
+void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
+{
+        if (PXSEG(port))
+                return (void __iomem *)port;
+        else if (is_pci_ioaddr(port))
+                return (void __iomem *)pci_ioaddr(port);
+
+        return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
new file mode 100644 (file)
index 0000000..a006d64
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/boards/landisk/irq.c
+ *
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for I-O Data Device, Inc. LANDISK.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_landisk.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+/*
+ * modified by kogiidena
+ * 2005.03.03
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/landisk/iodata_landisk.h>
+
+static void enable_landisk_irq(unsigned int irq);
+static void disable_landisk_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_landisk_irq disable_landisk_irq
+
+static void ack_landisk_irq(unsigned int irq);
+static void end_landisk_irq(unsigned int irq);
+
+static unsigned int startup_landisk_irq(unsigned int irq)
+{
+       enable_landisk_irq(irq);
+       return 0;               /* never anything pending */
+}
+
+static void disable_landisk_irq(unsigned int irq)
+{
+       unsigned char val;
+       unsigned char mask = 0xff ^ (0x01 << (irq - 5));
+
+       /* Set the priority in IPR to 0 */
+       val = ctrl_inb(PA_IMASK);
+       val &= mask;
+       ctrl_outb(val, PA_IMASK);
+}
+
+static void enable_landisk_irq(unsigned int irq)
+{
+       unsigned char val;
+       unsigned char value = (0x01 << (irq - 5));
+
+       /* Set priority in IPR back to original value */
+       val = ctrl_inb(PA_IMASK);
+       val |= value;
+       ctrl_outb(val, PA_IMASK);
+}
+
+static void ack_landisk_irq(unsigned int irq)
+{
+       disable_landisk_irq(irq);
+}
+
+static void end_landisk_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               enable_landisk_irq(irq);
+}
+
+static struct hw_interrupt_type landisk_irq_type = {
+       .typename = "LANDISK IRQ",
+       .startup = startup_landisk_irq,
+       .shutdown = shutdown_landisk_irq,
+       .enable = enable_landisk_irq,
+       .disable = disable_landisk_irq,
+       .ack = ack_landisk_irq,
+       .end = end_landisk_irq
+};
+
+static void make_landisk_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &landisk_irq_type;
+       disable_landisk_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_landisk_IRQ(void)
+{
+       int i;
+
+       for (i = 5; i < 14; i++)
+               make_landisk_irq(i);
+}
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
new file mode 100644 (file)
index 0000000..e75cb57
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * arch/sh/boards/landisk/landisk_pwb.c -- driver for the Power control switch.
+ *
+ * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
+ *
+ * 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.
+ *
+ * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
+ *
+ * LED control drive function added by kogiidena
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/major.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/landisk/iodata_landisk.h>
+
+#define SHUTDOWN_BTN_MINOR     1       /* Shutdown button device minor no. */
+#define LED_MINOR             21       /* LED minor no. */
+#define BTN_MINOR             22       /* BUTTON minor no. */
+#define GIO_MINOR             40       /* GIO minor no. */
+
+static int openCnt;
+static int openCntLED;
+static int openCntGio;
+static int openCntBtn;
+static int landisk_btn;
+static int landisk_btnctrlpid;
+/*
+ * Functions prototypes
+ */
+
+static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+                    unsigned long arg);
+
+static int swdrv_open(struct inode *inode, struct file *filp)
+{
+       int minor;
+
+       minor = MINOR(inode->i_rdev);
+       filp->private_data = (void *)minor;
+
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               if (openCnt > 0) {
+                       return -EALREADY;
+               } else {
+                       openCnt++;
+                       return 0;
+               }
+       } else if (minor == LED_MINOR) {
+               if (openCntLED > 0) {
+                       return -EALREADY;
+               } else {
+                       openCntLED++;
+                       return 0;
+               }
+       } else if (minor == BTN_MINOR) {
+               if (openCntBtn > 0) {
+                       return -EALREADY;
+               } else {
+                       openCntBtn++;
+                       return 0;
+               }
+       } else if (minor == GIO_MINOR) {
+               if (openCntGio > 0) {
+                       return -EALREADY;
+               } else {
+                       openCntGio++;
+                       return 0;
+               }
+       }
+       return -ENOENT;
+
+}
+
+static int swdrv_close(struct inode *inode, struct file *filp)
+{
+       int minor;
+
+       minor = MINOR(inode->i_rdev);
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               openCnt--;
+       } else if (minor == LED_MINOR) {
+               openCntLED--;
+       } else if (minor == BTN_MINOR) {
+               openCntBtn--;
+       } else if (minor == GIO_MINOR) {
+               openCntGio--;
+       }
+       return 0;
+}
+
+static int swdrv_read(struct file *filp, char *buff, size_t count,
+                     loff_t * ppos)
+{
+       int minor;
+       minor = (int)(filp->private_data);
+
+       if (!access_ok(VERIFY_WRITE, (void *)buff, count))
+               return -EFAULT;
+
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               if (landisk_btn & 0x10) {
+                       put_user(1, buff);
+                       return 1;
+               } else {
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+static int swdrv_write(struct file *filp, const char *buff, size_t count,
+                      loff_t * ppos)
+{
+       int minor;
+       minor = (int)(filp->private_data);
+
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               return count;
+       }
+       return count;
+}
+
+static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
+       disable_irq(IRQ_BUTTON);
+       disable_irq(IRQ_POWER);
+       ctrl_outb(0x00, PA_PWRINT_CLR);
+
+       if (landisk_btnctrlpid != 0) {
+               kill_proc(landisk_btnctrlpid, SIGUSR1, 1);
+               landisk_btnctrlpid = 0;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct file_operations swdrv_fops = {
+       .read = swdrv_read,     /* read */
+       .write = swdrv_write,   /* write */
+       .open = swdrv_open,     /* open */
+       .release = swdrv_close, /* release */
+       .ioctl = gio_ioctl,     /* ioctl */
+
+};
+
+static char banner[] __initdata =
+    KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
+
+int __init swdrv_init(void)
+{
+       int error;
+
+       printk("%s", banner);
+
+       openCnt = 0;
+       openCntLED = 0;
+       openCntBtn = 0;
+       openCntGio = 0;
+       landisk_btn = 0;
+       landisk_btnctrlpid = 0;
+
+       if ((error = register_chrdev(SHUTDOWN_BTN_MAJOR, "swdrv", &swdrv_fops))) {
+               printk(KERN_ERR
+                      "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
+                      error);
+               return 1;
+       }
+
+       if (request_irq(IRQ_POWER, sw_interrupt, 0, "SHUTDOWNSWITCH", NULL)) {
+               printk(KERN_ERR "Unable to get IRQ 11.\n");
+               return 1;
+       }
+       if (request_irq(IRQ_BUTTON, sw_interrupt, 0, "USL-5P BUTTON", NULL)) {
+               printk(KERN_ERR "Unable to get IRQ 12.\n");
+               return 1;
+       }
+       ctrl_outb(0x00, PA_PWRINT_CLR);
+
+       return 0;
+}
+
+module_init(swdrv_init);
+
+/*
+ * gio driver
+ *
+ */
+
+#include <asm/landisk/gio.h>
+
+static int gio_ioctl(struct inode *inode, struct file *filp,
+                    unsigned int cmd, unsigned long arg)
+{
+       int minor;
+       unsigned int data, mask;
+       static unsigned int addr = 0;
+
+       minor = (int)(filp->private_data);
+
+       /* access control */
+       if (minor == GIO_MINOR) {
+               ;
+       } else if (minor == LED_MINOR) {
+               if (((cmd & 0x0ff) >= 9) && ((cmd & 0x0ff) < 20)) {
+                       ;
+               } else {
+                       return -EINVAL;
+               }
+       } else if (minor == BTN_MINOR) {
+               if (((cmd & 0x0ff) >= 20) && ((cmd & 0x0ff) < 30)) {
+                       ;
+               } else {
+                       return -EINVAL;
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       if (cmd & 0x01) {       /* write */
+               if (copy_from_user(&data, (int *)arg, sizeof(int))) {
+                       return -EFAULT;
+               }
+       }
+
+       switch (cmd) {
+       case GIODRV_IOCSGIOSETADDR:     /* addres set */
+               addr = data;
+               break;
+
+       case GIODRV_IOCSGIODATA1:       /* write byte */
+               ctrl_outb((unsigned char)(0x0ff & data), addr);
+               break;
+
+       case GIODRV_IOCSGIODATA2:       /* write word */
+               if (addr & 0x01) {
+                       return -EFAULT;
+               }
+               ctrl_outw((unsigned short int)(0x0ffff & data), addr);
+               break;
+
+       case GIODRV_IOCSGIODATA4:       /* write long */
+               if (addr & 0x03) {
+                       return -EFAULT;
+               }
+               ctrl_outl(data, addr);
+               break;
+
+       case GIODRV_IOCGGIODATA1:       /* read byte */
+               data = ctrl_inb(addr);
+               break;
+
+       case GIODRV_IOCGGIODATA2:       /* read word */
+               if (addr & 0x01) {
+                       return -EFAULT;
+               }
+               data = ctrl_inw(addr);
+               break;
+
+       case GIODRV_IOCGGIODATA4:       /* read long */
+               if (addr & 0x03) {
+                       return -EFAULT;
+               }
+               data = ctrl_inl(addr);
+               break;
+       case GIODRV_IOCSGIO_LED:        /* write */
+               mask = ((data & 0x00ffffff) << 8)
+                   | ((data & 0x0000ffff) << 16)
+                   | ((data & 0x000000ff) << 24);
+               landisk_ledparam = data & (~mask);
+               if (landisk_arch == 0) {        /* arch == landisk */
+                       landisk_ledparam &= 0x03030303;
+                       mask = (~(landisk_ledparam >> 22)) & 0x000c;
+                       landisk_ledparam |= mask;
+               } else {                        /* arch == usl-5p */
+                       mask = (landisk_ledparam >> 24) & 0x0001;
+                       landisk_ledparam |= mask;
+                       landisk_ledparam &= 0x007f7f7f;
+               }
+               landisk_ledparam |= 0x80;
+               break;
+       case GIODRV_IOCGGIO_LED:        /* read */
+               data = landisk_ledparam;
+               if (landisk_arch == 0) {        /* arch == landisk */
+                       data &= 0x03030303;
+               } else {                        /* arch == usl-5p */
+                       ;
+               }
+               data &= (~0x080);
+               break;
+       case GIODRV_IOCSGIO_BUZZER:     /* write */
+               landisk_buzzerparam = data;
+               landisk_ledparam |= 0x80;
+               break;
+       case GIODRV_IOCGGIO_LANDISK:    /* read */
+               data = landisk_arch & 0x01;
+               break;
+       case GIODRV_IOCGGIO_BTN:        /* read */
+               data = (0x0ff & ctrl_inb(PA_PWRINT_CLR));
+               data <<= 8;
+               data |= (0x0ff & ctrl_inb(PA_IMASK));
+               data <<= 8;
+               data |= (0x0ff & landisk_btn);
+               data <<= 8;
+               data |= (0x0ff & (~ctrl_inb(PA_STATUS)));
+               break;
+       case GIODRV_IOCSGIO_BTNPID:     /* write */
+               landisk_btnctrlpid = data;
+               landisk_btn = 0;
+               if (irq_desc[IRQ_BUTTON].depth) {
+                       enable_irq(IRQ_BUTTON);
+               }
+               if (irq_desc[IRQ_POWER].depth) {
+                       enable_irq(IRQ_POWER);
+               }
+               break;
+       case GIODRV_IOCGGIO_BTNPID:     /* read */
+               data = landisk_btnctrlpid;
+               break;
+       default:
+               return -EFAULT;
+               break;
+       }
+
+       if ((cmd & 0x01) == 0) {        /* read */
+               if (copy_to_user((int *)arg, &data, sizeof(int))) {
+                       return -EFAULT;
+               }
+       }
+       return 0;
+}
diff --git a/arch/sh/boards/landisk/rtc.c b/arch/sh/boards/landisk/rtc.c
new file mode 100644 (file)
index 0000000..35ba726
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * arch/sh/boards/landisk/rtc.c --  RTC support
+ *
+ *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ */
+/*
+ * modifed by kogiidena
+ * 2005.09.16
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/bcd.h>
+#include <asm/rtc.h>
+
+extern spinlock_t rtc_lock;
+
+extern void
+rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
+                     unsigned int BCD_day, unsigned int BCD_hr,
+                     unsigned int BCD_min, unsigned int BCD_sec);
+
+extern unsigned long
+rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
+                     unsigned int *BCD_day, unsigned int *BCD_hr,
+                     unsigned int *BCD_min, unsigned int *BCD_sec);
+
+void landisk_rtc_gettimeofday(struct timespec *tv)
+{
+       unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       tv->tv_sec = rs5c313_get_cmos_time
+           (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
+       tv->tv_nsec = 0;
+       spin_unlock_irqrestore(&rtc_lock, flags);
+}
+
+int landisk_rtc_settimeofday(const time_t secs)
+{
+       int retval = 0;
+       int real_seconds, real_minutes, cmos_minutes;
+       unsigned long flags;
+       unsigned long nowtime = secs;
+       unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+
+       rs5c313_get_cmos_time
+         (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
+       cmos_minutes = BCD_min;
+       BCD_TO_BIN(cmos_minutes);
+
+       /*
+        * since we're only adjusting minutes and seconds,
+        * don't interfere with hour overflow. This avoids
+        * messing with unknown time zones but requires your
+        * RTC not to be off by more than 15 minutes
+        */
+       real_seconds = nowtime % 60;
+       real_minutes = nowtime / 60;
+       if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+               real_minutes += 30;     /* correct for half hour time zone */
+       real_minutes %= 60;
+
+       if (abs(real_minutes - cmos_minutes) < 30) {
+               BIN_TO_BCD(real_seconds);
+               BIN_TO_BCD(real_minutes);
+               rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
+                                     real_minutes, real_seconds);
+       } else {
+               printk(KERN_WARNING
+                      "set_rtc_time: can't update from %d to %d\n",
+                      cmos_minutes, real_minutes);
+               retval = -1;
+       }
+
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return retval;
+}
+
+void landisk_time_init(void)
+{
+       rtc_sh_get_time = landisk_rtc_gettimeofday;
+       rtc_sh_set_time = landisk_rtc_settimeofday;
+}
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
new file mode 100644 (file)
index 0000000..127b9e0
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * arch/sh/boards/landisk/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * I-O DATA Device, Inc. LANDISK Support.
+ *
+ * Modified for LANDISK by
+ * Atom Create Engineering Co., Ltd. 2002.
+ *
+ * modifed by kogiidena
+ * 2005.09.16
+ *
+ * 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/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/mm.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/io.h>
+
+void landisk_time_init(void);
+void init_landisk_IRQ(void);
+
+int landisk_ledparam;
+int landisk_buzzerparam;
+int landisk_arch;
+
+/* cycle the led's in the clasic knightrider/sun pattern */
+static void heartbeat_landisk(void)
+{
+       static unsigned int cnt = 0, blink = 0x00, period = 25;
+        volatile u8 *p = (volatile u8 *)PA_LED;
+       char data;
+
+        if ((landisk_ledparam & 0x080) == 0)
+               return;
+
+       cnt += 1;
+
+        if (cnt < period)
+               return;
+
+       cnt = 0;
+       blink++;
+
+       data = (blink & 0x01) ? (landisk_ledparam >> 16) : 0;
+       data |= (blink & 0x02) ? (landisk_ledparam >> 8) : 0;
+       data |= landisk_ledparam;
+
+       /* buzzer */
+       if (landisk_buzzerparam & 0x1) {
+               data |= 0x80;
+       } else {
+               data &= 0x7f;
+       }
+       *p = data;
+
+        if (((landisk_ledparam & 0x007f7f00) == 0) &&
+             (landisk_buzzerparam == 0))
+               landisk_ledparam &= (~0x0080);
+
+       landisk_buzzerparam >>= 1;
+}
+
+static void landisk_power_off(void)
+{
+        ctrl_outb(0x01, PA_SHUTDOWN);
+}
+
+static void check_usl5p(void)
+{
+        volatile u8 *p = (volatile u8 *)PA_LED;
+        u8 tmp1, tmp2;
+
+        tmp1 = *p;
+        *p = 0x40;
+        tmp2 = *p;
+        *p = tmp1;
+
+        landisk_arch = (tmp2 == 0x40);
+        if (landisk_arch == 1) {
+                /* arch == usl-5p */
+                landisk_ledparam = 0x00000380;
+                landisk_ledparam |= (tmp1 & 0x07c);
+        } else {
+                /* arch == landisk */
+                landisk_ledparam = 0x02000180;
+                landisk_ledparam |= 0x04;
+        }
+}
+
+void *area5_io_base;
+void *area6_io_base;
+
+static int __init landisk_cf_init(void)
+{
+       pgprot_t prot;
+       unsigned long paddrbase, psize;
+
+       /* open I/O area window */
+       paddrbase = virt_to_phys((void *)PA_AREA5_IO);
+       psize = PAGE_SIZE;
+       prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
+       area5_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       if (!area5_io_base) {
+               printk("allocate_cf_area : can't open CF I/O window!\n");
+               return -ENOMEM;
+       }
+
+       paddrbase = virt_to_phys((void *)PA_AREA6_IO);
+       psize = PAGE_SIZE;
+       prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
+       area6_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       if (!area6_io_base) {
+               printk("allocate_cf_area : can't open HDD I/O window!\n");
+               return -ENOMEM;
+       }
+
+       printk(KERN_INFO "Allocate Area5/6 success.\n");
+
+       /* XXX : do we need attribute and common-memory area also? */
+
+       return 0;
+}
+
+static void __init landisk_setup(char **cmdline_p)
+{
+       device_initcall(landisk_cf_init);
+
+       landisk_buzzerparam = 0;
+       check_usl5p();
+
+       printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
+
+       board_time_init = landisk_time_init;
+       pm_power_off = landisk_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_landisk __initmv = {
+       .mv_name = "LANDISK",
+       .mv_setup = landisk_setup,
+       .mv_nr_irqs = 72,
+       .mv_inb = landisk_inb,
+       .mv_inw = landisk_inw,
+       .mv_inl = landisk_inl,
+       .mv_outb = landisk_outb,
+       .mv_outw = landisk_outw,
+       .mv_outl = landisk_outl,
+       .mv_inb_p = landisk_inb_p,
+       .mv_inw_p = landisk_inw,
+       .mv_inl_p = landisk_inl,
+       .mv_outb_p = landisk_outb_p,
+       .mv_outw_p = landisk_outw,
+       .mv_outl_p = landisk_outl,
+       .mv_insb = landisk_insb,
+       .mv_insw = landisk_insw,
+       .mv_insl = landisk_insl,
+       .mv_outsb = landisk_outsb,
+       .mv_outsw = landisk_outsw,
+       .mv_outsl = landisk_outsl,
+       .mv_ioport_map = landisk_ioport_map,
+       .mv_init_irq = init_landisk_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat = heartbeat_landisk,
+#endif
+};
+ALIAS_MV(landisk)
index a76c655dceeeba4790a2654b03e525f824bf24ee..03b123a4bba42d54bd2757dc514da30fe1f7a998 100644 (file)
@@ -130,7 +130,7 @@ int mpc1211_rtc_settimeofday(const struct timeval *tv)
 
 void mpc1211_time_init(void)
 {
-       rtc_get_time = mpc1211_rtc_gettimeofday;
-       rtc_set_time = mpc1211_rtc_settimeofday;
+       rtc_sh_get_time = mpc1211_rtc_gettimeofday;
+       rtc_sh_set_time = mpc1211_rtc_settimeofday;
 }
 
index 2bfb221cc35cbfd75890d0ceaae3f9e0a3a7409d..8eb5d430397257f0884400a5e6abc2ee72d915ec 100644 (file)
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/interrupt.h>
-
 #include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mpc1211/mpc1211.h>
 #include <asm/mpc1211/pci.h>
 #include <asm/mpc1211/m1543c.h>
 
-
 /* ALI15X3 SMBus address offsets */
 #define SMBHSTSTS   (0 + 0x3100)
 #define SMBHSTCNT   (1 + 0x3100)
 #define ALI15X3_STS_TERM       0x80    /* terminated by abort */
 #define ALI15X3_STS_ERR                0xE0    /* all the bad error bits */
 
-const char *get_system_type(void)
-{
-       return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
-}
-
 static void __init pci_write_config(unsigned long busNo,
                                    unsigned long devNo,
                                    unsigned long fncNo,
@@ -80,9 +73,6 @@ volatile unsigned long irq_err_count;
 
 static void disable_mpc1211_irq(unsigned int irq)
 {
-       unsigned long flags;
-
-       save_and_cli(flags);
        if( irq < 8) {
                m_irq_mask |= (1 << irq);
                outb(m_irq_mask,I8259_M_MR);
@@ -90,16 +80,11 @@ static void disable_mpc1211_irq(unsigned int irq)
                s_irq_mask |= (1 << (irq - 8));
                outb(s_irq_mask,I8259_S_MR);
        }
-       restore_flags(flags);
 
 }
 
 static void enable_mpc1211_irq(unsigned int irq)
 {
-       unsigned long flags;
-
-       save_and_cli(flags);
-
        if( irq < 8) {
                m_irq_mask &= ~(1 << irq);
                outb(m_irq_mask,I8259_M_MR);
@@ -107,7 +92,6 @@ static void enable_mpc1211_irq(unsigned int irq)
                s_irq_mask &= ~(1 << (irq - 8));
                outb(s_irq_mask,I8259_S_MR);
        }
-       restore_flags(flags);
 }
 
 static inline int mpc1211_irq_real(unsigned int irq)
@@ -131,10 +115,6 @@ static inline int mpc1211_irq_real(unsigned int irq)
 
 static void mask_and_ack_mpc1211(unsigned int irq)
 {
-       unsigned long flags;
-
-       save_and_cli(flags);
-
        if(irq < 8) {
                if(m_irq_mask & (1<<irq)){
                  if(!mpc1211_irq_real(irq)){
@@ -162,7 +142,6 @@ static void mask_and_ack_mpc1211(unsigned int irq)
                outb(0x60+(irq-8),I8259_S_CR);  /* EOI */
                outb(0x60+2,I8259_M_CR);
        }
-       restore_flags(flags);
 }
 
 static void end_mpc1211_irq(unsigned int irq)
@@ -219,7 +198,7 @@ int mpc1211_irq_demux(int irq)
        return irq;
 }
 
-void __init init_mpc1211_IRQ(void)
+static void __init init_mpc1211_IRQ(void)
 {
        int i;
        /*
@@ -255,23 +234,12 @@ void __init init_mpc1211_IRQ(void)
        }
 }
 
-/*
-  Initialize the board
-*/
-
-
-static void delay (void)
-{
-       volatile unsigned short tmp;
-       tmp = *(volatile unsigned short *) 0xa0000000;
-}
-
-static void delay1000 (void)
+static void delay1000(void)
 {
        int i;
 
        for (i=0; i<1000; i++)
-               delay ();
+               ctrl_delay();
 }
 
 static int put_smb_blk(unsigned char *p, int address, int command, int no)
@@ -314,26 +282,10 @@ static int put_smb_blk(unsigned char *p, int address, int command, int no)
        return 0;
 }
 
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_mpc1211 __initmv = {
-       .mv_nr_irqs             = 48,
-       .mv_irq_demux           = mpc1211_irq_demux,
-       .mv_init_irq            = init_mpc1211_IRQ,
-
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_mpc1211,
-#endif
-};
-
-ALIAS_MV(mpc1211)
-
 /* arch/sh/boards/mpc1211/rtc.c */
 void mpc1211_time_init(void);
 
-int __init platform_setup(void)
+static void __init mpc1211_setup(char **cmdline_p)
 {
        unsigned char spd_buf[128];
 
@@ -357,3 +309,18 @@ int __init platform_setup(void)
        return 0;
 }
 
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_mpc1211 __initmv = {
+       .mv_name                = "Interface MPC-1211(CTP/PCI/MPC-SH02)",
+       .mv_setup               = mpc1211_setup,
+       .mv_nr_irqs             = 48,
+       .mv_irq_demux           = mpc1211_irq_demux,
+       .mv_init_irq            = init_mpc1211_IRQ,
+
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_mpc1211,
+#endif
+};
+ALIAS_MV(mpc1211)
diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile
deleted file mode 100644 (file)
index 245f03b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
-#
-
-obj-y   := mach.o setup.o io.o irq.o led.o
-
-obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
-
diff --git a/arch/sh/boards/overdrive/fpga.c b/arch/sh/boards/overdrive/fpga.c
deleted file mode 100644 (file)
index 956c239..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * This file handles programming up the Altera Flex10K that interfaces to
- * the Galileo, and does the PS/2 keyboard and mouse
- *
- */
-
-
-#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>
-#include <linux/delay.h>
-
-
-#include <asm/overdriver/gt64111.h>
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/fpga.h>
-
-#define FPGA_NotConfigHigh()  (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT
-#define FPGA_NotConfigLow()   (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK
-
-/* I need to find out what (if any) the real delay factor here is */
-/* The delay is definately not critical */
-#define long_delay() {int i;for(i=0;i<10000;i++);}
-#define short_delay() {int i;for(i=0;i<100;i++);}
-
-static void __init program_overdrive_fpga(const unsigned char *fpgacode,
-                                         int size)
-{
-       int timeout = 0;
-       int i, j;
-       unsigned char b;
-       static volatile unsigned char *FPGA_ControlReg =
-           (volatile unsigned char *) (OVERDRIVE_CTRL);
-       static volatile unsigned char *FPGA_ProgramReg =
-           (volatile unsigned char *) (FPGA_DCLK_ADDRESS);
-
-       printk("FPGA:  Commencing FPGA Programming\n");
-
-       /* The PCI reset but MUST be low when programming the FPGA !!! */
-       b = (*FPGA_ControlReg) & RESET_PCI_MASK;
-
-       (*FPGA_ControlReg) = b;
-
-       /* Prepare FPGA to program */
-
-       FPGA_NotConfigHigh();
-       long_delay();
-
-       FPGA_NotConfigLow();
-       short_delay();
-
-       while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) {
-               printk("FPGA:  Waiting for NotStatus to go Low ... \n");
-       }
-
-       FPGA_NotConfigHigh();
-
-       /* Wait for FPGA "ready to be programmed" signal */
-       printk("FPGA:  Waiting for NotStatus to go high (FPGA ready)... \n");
-
-       for (timeout = 0;
-            (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0)
-             && (timeout < FPGA_TIMEOUT)); timeout++);
-
-       /* Check if timeout condition occured - i.e. an error */
-
-       if (timeout == FPGA_TIMEOUT) {
-               printk
-                   ("FPGA:  Failed to program - Timeout waiting for notSTATUS to go high\n");
-               return;
-       }
-
-       printk("FPGA:  Copying data to FPGA ... %d bytes\n", size);
-
-       /* Copy array to FPGA - bit at a time */
-
-       for (i = 0; i < size; i++) {
-               volatile unsigned w = 0;
-
-               for (j = 0; j < 8; j++) {
-                       *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01;
-                       short_delay();
-               }
-               if ((i & 0x3ff) == 0) {
-                       printk(".");
-               }
-       }
-
-       /* Waiting for CONFDONE to go high - means the program is complete  */
-
-       for (timeout = 0;
-            (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0)
-             && (timeout < FPGA_TIMEOUT)); timeout++) {
-
-               *FPGA_ProgramReg = 0x0;
-               long_delay();
-       }
-
-       if (timeout == FPGA_TIMEOUT) {
-               printk
-                   ("FPGA:  Failed to program - Timeout waiting for CONFDONE to go high\n");
-               return;
-       } else {                /* Clock another 10 times - gets the device into a working state      */
-               for (i = 0; i < 10; i++) {
-                       *FPGA_ProgramReg = 0x0;
-                       short_delay();
-               }
-       }
-
-       printk("FPGA:  Programming complete\n");
-}
-
-
-static const unsigned char __init fpgacode[] = {
-#include "./overdrive.ttf"     /* Code from maxplus2 compiler */
-       , 0, 0
-};
-
-
-int __init init_overdrive_fpga(void)
-{
-       program_overdrive_fpga(fpgacode, sizeof(fpgacode));
-
-       return 0;
-}
diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
deleted file mode 100644 (file)
index 29e4897..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * This file contains the PCI routines required for the Galileo GT6411 
- * PCI bridge as used on the Orion and Overdrive boards.
- *
- */
-
-#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>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/gt64111.h>
-
-
-/* After boot, we shift the Galileo registers so that they appear 
- * in BANK6, along with IO space. This means we can have one contingous
- * lump of PCI address space without these registers appearing in the 
- * middle of them 
- */
-
-#define GT64111_BASE_ADDRESS  0xbb000000
-#define GT64111_IO_BASE_ADDRESS  0x1000
-/* The GT64111 registers appear at this address to the SH4 after reset */
-#define RESET_GT64111_BASE_ADDRESS           0xb4000000
-
-/* Macros used to access the Galileo registers */
-#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x)
-#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x)
-
-#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x))
-
-#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x))
-
-#define GT_WRITE(x,v) writel((v),GT64111_REG(x))
-#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x))
-#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x))
-
-#define GT_READ(x)    readl(GT64111_REG(x))
-#define GT_READ_BYTE(x)  readb(GT64111_REG(x))
-#define GT_READ_SHORT(x) readw(GT64111_REG(x))
-
-
-/* Where the various SH banks start at */
-#define SH_BANK4_ADR 0xb0000000
-#define SH_BANK5_ADR 0xb4000000
-#define SH_BANK6_ADR 0xb8000000
-
-/* Masks out everything but lines 28,27,26 */
-#define BANK_SELECT_MASK 0x1c000000
-
-#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK)
-
-/* 
- * Masks used for address conversaion. Bank 6 is used for IO and 
- * has all the address bits zeroed by the FPGA. Special case this
- */
-#define MEMORY_BANK_MASK 0x1fffffff
-#define IO_BANK_MASK  0x03ffffff
-
-/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code
- * if you want 
- */
-#define IO_BANK_ADR PCI_GTIO_BASE
-
-/* Will select the correct mask to apply depending on the SH$ address */
-#define SELECT_BANK_MASK(x) \
-   ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK)
-
-/* Converts between PCI space and P2 region */
-#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x))
-
-/* Various macros for figuring out what to stick in the Galileo registers. 
- * You *really* don't want to figure this stuff out by hand, you always get
- * it wrong
- */
-#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff)
-#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f)
-#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff)
-
-#define PROGRAM_HI_LO(block,a,s) \
-    GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\
-    GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1))
-
-#define PROGRAM_SUB_HI_LO(block,a,s) \
-    GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\
-    GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1))
-
-/* We need to set the size, and the offset register */
-
-#define GT_BAR_MASK(x) ((x)&~0xfff)
-
-/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */
-#define PROGRAM_GT_BAR(block,a,s) \
-  GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\
-  write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\
-                            GT_BAR_MASK(a))
-
-#define DISABLE_GT_BAR(block) \
-  GT_WRITE(PCI_##block##_BANK_SIZE,0),\
-  GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\
-    0x80000000)
-
-/* Macros to disable things we are not going to use */
-#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\
-                          GT_WRITE(x##_HI_DEC_ADR,0x00)
-
-#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\
-                              GT_WRITE(x##_HI_DEC_ADR,0x00)
-
-static void __init reset_pci(void)
-{
-       /* Set RESET_PCI bit high */
-       writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
-       udelay(250);
-
-       /* Set RESET_PCI bit low */
-       writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL);
-       udelay(250);
-
-       writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
-       udelay(250);
-}
-
-static int write_config_to_galileo(int where, u32 val);
-#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val)
-
-#define ENABLE_PCI_DRAM
-
-
-#ifdef TEST_DRAM
-/* Test function to check out if the PCI DRAM is working OK */
-static int  /* __init */ test_dram(unsigned *base, unsigned size)
-{
-       unsigned *p = base;
-       unsigned *end = (unsigned *) (((unsigned) base) + size);
-       unsigned w;
-
-       for (p = base; p < end; p++) {
-               *p = 0xffffffff;
-               if (*p != 0xffffffff) {
-                       printk("AAARGH -write failed!!! at %p is %x\n", p,
-                              *p);
-                       return 0;
-               }
-               *p = 0x0;
-               if (*p != 0x0) {
-                       printk("AAARGH -write failed!!!\n");
-                       return 0;
-               }
-       }
-
-       for (p = base; p < end; p++) {
-               *p = (unsigned) p;
-               if (*p != (unsigned) p) {
-                       printk("Failed at 0x%p, actually is 0x%x\n", p,
-                              *p);
-                       return 0;
-               }
-       }
-
-       for (p = base; p < end; p++) {
-               w = ((unsigned) p & 0xffff0000);
-               *p = w | (w >> 16);
-       }
-
-       for (p = base; p < end; p++) {
-               w = ((unsigned) p & 0xffff0000);
-               w |= (w >> 16);
-               if (*p != w) {
-                       printk
-                           ("Failed at 0x%p, should be 0x%x actually is 0x%x\n",
-                            p, w, *p);
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-#endif
-
-
-/* Function to set up and initialise the galileo. This sets up the BARS,
- * maps the DRAM into the address space etc,etc
- */
-int __init galileo_init(void)
-{
-       reset_pci();
-
-       /* Now shift the galileo regs into this block */
-       RESET_GT_WRITE(INTERNAL_SPACE_DEC,
-                      GT_MEM_LO_ADR(GT64111_BASE_ADDRESS));
-
-       /* Should have a sanity check here, that you can read back  at the new
-        * address what you just wrote 
-        */
-
-       /* Disable decode for all regions */
-       DISABLE_DECODE(RAS10);
-       DISABLE_DECODE(RAS32);
-       DISABLE_DECODE(CS20);
-       DISABLE_DECODE(CS3);
-       DISABLE_DECODE(PCI_IO);
-       DISABLE_DECODE(PCI_MEM0);
-       DISABLE_DECODE(PCI_MEM1);
-
-       /* Disable all BARS */
-       GT_WRITE(BAR_ENABLE_ADR, 0x1ff);
-       DISABLE_GT_BAR(RAS10);
-       DISABLE_GT_BAR(RAS32);
-       DISABLE_GT_BAR(CS20);
-       DISABLE_GT_BAR(CS3);
-
-       /* Tell the BAR where the IO registers now are */
-       GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK(
-                                           (GT64111_IO_BASE_ADDRESS &
-                                            IO_BANK_MASK)));
-       /* set up a 112 Mb decode */
-       PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024);
-
-       /* Set up a 32 MB io space decode */
-       PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024);
-
-#ifdef ENABLE_PCI_DRAM
-       /* Program up the DRAM configuration - there is DRAM only in bank 0 */
-       /* Now set up the DRAM decode */
-       PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE);
-       /* And the sub decode */
-       PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE);
-
-       DISABLE_SUB_DECODE(RAS1);
-
-       /* Set refresh rate */
-       GT_WRITE(DRAM_BANK0_PARMS, 0x3f);
-       GT_WRITE(DRAM_CFG, 0x100);
-
-       /* we have to lob off the top bits rememeber!! */
-       PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE);
-
-#endif
-
-       /* We are only interested in decoding RAS10 and the Galileo's internal 
-        * registers (as IO) on the PCI bus
-        */
-#ifdef ENABLE_PCI_DRAM
-       GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff);
-#else
-       GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff);
-#endif
-
-       /* Change the class code to host bridge, it actually powers up 
-        * as a memory controller
-         */
-       GT_CONFIG_WRITE(8, 0x06000011);
-
-       /* Allow the galileo to master the PCI bus */
-       GT_CONFIG_WRITE(PCI_COMMAND,
-                       PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
-                       PCI_COMMAND_IO);
-
-
-#if 0
-        printk("Testing PCI DRAM - ");
-       if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
-               printk("Passed\n");
-       }else {
-               printk("FAILED\n");
-       }
-#endif
-       return 0;
-
-}
-
-
-#define SET_CONFIG_BITS(bus,devfn,where)\
-  ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3))
-
-#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
-
-/* This write to the galileo config registers, unlike the functions below, can
- * be used before the PCI subsystem has started up
- */
-static int __init write_config_to_galileo(int where, u32 val)
-{
-       GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where));
-
-       GT_WRITE(PCI_CFG_DATA, val);
-       return 0;
-}
-
-/* We exclude the galileo and slot 31, the galileo because I don't know how to stop
- * the setup code shagging up the setup I have done on it, and 31 because the whole
- * thing locks up if you try to access that slot (which doesn't exist of course anyway
- */
-
-#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31)))
-
-static int galileo_read_config_byte(struct pci_dev *dev, int where,
-                                   u8 * val)
-{
-
-        
-       /* I suspect this doesn't work because this drives a special cycle ? */
-       if (EXCLUDED_DEV(dev)) {
-               *val = 0xff;
-               return PCIBIOS_SUCCESSFUL;
-       }
-       /* Start the config cycle */
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-       /* Read back the result */
-       *val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_read_config_word(struct pci_dev *dev, int where,
-                                   u16 * val)
-{
-
-        if (EXCLUDED_DEV(dev)) {
-               *val = 0xffff;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-       *val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_read_config_dword(struct pci_dev *dev, int where,
-                                    u32 * val)
-{
-       if (EXCLUDED_DEV(dev)) {
-               *val = 0xffffffff;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-       *val = GT_READ(PCI_CFG_DATA);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_write_config_byte(struct pci_dev *dev, int where,
-                                    u8 val)
-{
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
-       GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_write_config_word(struct pci_dev *dev, int where,
-                                    u16 val)
-{
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
-       GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_write_config_dword(struct pci_dev *dev, int where,
-                                     u32 val)
-{
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
-       GT_WRITE(PCI_CFG_DATA, val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_config_ops = {
-       galileo_read_config_byte,
-       galileo_read_config_word,
-       galileo_read_config_dword,
-       galileo_write_config_byte,
-       galileo_write_config_word,
-       galileo_write_config_dword
-};
-
-
-/* Everything hangs off this */
-static struct pci_bus *pci_root_bus;
-
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
-{
-       return PCI_SLOT(dev->devfn);
-}
-
-static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       /* Slot 1: Galileo 
-        * Slot 2: PCI Slot 1
-        * Slot 3: PCI Slot 2
-        * Slot 4: ESS
-        */
-       switch (slot) {
-       case 2: 
-               return OVERDRIVE_PCI_IRQ1;
-       case 3:
-               /* Note this assumes you have a hacked card in slot 2 */
-               return OVERDRIVE_PCI_IRQ2;
-       case 4:
-               return OVERDRIVE_ESS_IRQ;
-       default:
-               /* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */
-               return -1;
-       }
-}
-
-
-
-void __init
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-        ranges->io_start -= bus->resource[0]->start;
-        ranges->io_end -= bus->resource[0]->start;
-        ranges->mem_start -= bus->resource[1]->start;
-        ranges->mem_end -= bus->resource[1]->start;
-}                                                                                
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
-       int i;
-
-       /*
-        * PCI IDE controllers use non-standard I/O port decoding, respect it.
-        */
-       if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
-               return;
-       printk("PCI: IDE base address fixup for %s\n", pci_name(d));
-       for(i=0; i<4; i++) {
-               struct resource *r = &d->resource[i];
-               if ((r->start & ~0x80) == 0x374) {
-                       r->start |= 2;
-                       r->end = r->start;
-               }
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-void __init pcibios_init(void)
-{
-       static struct resource galio,galmem;
-
-        /* Allocate the registers used by the Galileo */
-        galio.flags = IORESOURCE_IO;
-        galio.name  = "Galileo GT64011";
-        galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
-        galmem.name  = "Galileo GT64011 DRAM";
-
-        allocate_resource(&ioport_resource, &galio, 256,
-                   GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL);
-        allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE,
-                   PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE, 
-                            PCI_DRAM_SIZE, NULL, NULL);
-
-       /* ok, do the scan man */
-       pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
-
-        pci_assign_unassigned_resources();
-       pci_fixup_irqs(no_swizzle, map_od_irq);
-
-#ifdef TEST_DRAM
-        printk("Testing PCI DRAM - ");
-       if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
-               printk("Passed\n");
-       }else {
-               printk("FAILED\n");
-       }
-#endif
-
-}
-
-char * __init pcibios_setup(char *str)
-{
-       return str;
-}
-
-
-
-int pcibios_enable_device(struct pci_dev *dev)
-{
-
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx = 0; idx < 6; idx++) {
-               r = dev->resource + idx;
-               if (!r->start && r->end) {
-                       printk(KERN_ERR
-                              "PCI: Device %s not available because"
-                              " of resource collisions\n",
-                              pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (cmd != old_cmd) {
-               printk("PCI: enabling device %s (%04x -> %04x)\n",
-                      pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-
-}
-
-/* We should do some optimisation work here I think. Ok for now though */
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-                           resource_size_t size)
-{
-}
-
-void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                            struct resource *res, int resource)
-{
-
-       unsigned long where, size;
-       u32 reg;
-       
-
-       printk("PCI: Assigning %3s %08lx to %s\n",
-              res->flags & IORESOURCE_IO ? "IO" : "MEM",
-              res->start, dev->name);
-
-       where = PCI_BASE_ADDRESS_0 + resource * 4;
-       size = res->end - res->start;
-
-       pci_read_config_dword(dev, where, &reg);
-       reg = (reg & size) | (((u32) (res->start - root->start)) & ~size);
-       pci_write_config_dword(dev, where, reg);
-}
-
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-       printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
-       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-/*
- *  If we set up a device for bus mastering, we need to check the latency
- *  timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
-       u8 lat;
-       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-       if (lat < 16)
-               lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
-       else if (lat > pcibios_max_latency)
-               lat = pcibios_max_latency;
-       else
-               return;
-       printk("PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
diff --git a/arch/sh/boards/overdrive/io.c b/arch/sh/boards/overdrive/io.c
deleted file mode 100644 (file)
index 4671b6b..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * This file contains the I/O routines for use on the overdrive board
- *
- */
-
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-
-#include <asm/overdrive/overdrive.h>
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the SuperH architecture, we just read/write the
- * memory location directly.
- */
-
-#define dprintk(x...)
-
-/* Translates an IO address to where it is mapped in memory */
-
-#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
-
-unsigned char od_inb(unsigned long port)
-{
-dprintk("od_inb(%x)\n", port);
-       return readb(io_addr(port)) & 0xff;
-}
-
-
-unsigned short od_inw(unsigned long port)
-{
-dprintk("od_inw(%x)\n", port);
-       return readw(io_addr(port)) & 0xffff;
-}
-
-unsigned int od_inl(unsigned long port)
-{
-dprintk("od_inl(%x)\n", port);
-       return readl(io_addr(port));
-}
-
-void od_outb(unsigned char value, unsigned long port)
-{
-dprintk("od_outb(%x, %x)\n", value, port);
-       writeb(value, io_addr(port));
-}
-
-void od_outw(unsigned short value, unsigned long port)
-{
-dprintk("od_outw(%x, %x)\n", value, port);
-       writew(value, io_addr(port));
-}
-
-void od_outl(unsigned int value, unsigned long port)
-{
-dprintk("od_outl(%x, %x)\n", value, port);
-       writel(value, io_addr(port));
-}
-
-/* This is horrible at the moment - needs more work to do something sensible */
-#define IO_DELAY() udelay(10)
-
-#define OUT_DELAY(x,type) \
-void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
-
-#define IN_DELAY(x,type) \
-unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
-
-
-OUT_DELAY(b,char)
-OUT_DELAY(w,short)
-OUT_DELAY(l,int)
-
-IN_DELAY(b,char)
-IN_DELAY(w,short)
-IN_DELAY(l,int)
-
-
-/*  Now for the string version of these functions */
-void od_outsb(unsigned long port, const void *addr, unsigned long count)
-{
-       int i;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p++) {
-               outb(*p, port);
-       }
-}
-
-
-void od_insb(unsigned long port, void *addr, unsigned long count)
-{
-       int i;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p++) {
-               *p = inb(port);
-       }
-}
-
-/* For the 16 and 32 bit string functions, we have to worry about alignment.
- * The SH does not do unaligned accesses, so we have to read as bytes and
- * then write as a word or dword. 
- * This can be optimised a lot more, especially in the case where the data
- * is aligned
- */
-
-void od_outsw(unsigned long port, const void *addr, unsigned long count)
-{
-       int i;
-       unsigned short tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 2) {
-               tmp = (*p) | ((*(p + 1)) << 8);
-               outw(tmp, port);
-       }
-}
-
-
-void od_insw(unsigned long port, void *addr, unsigned long count)
-{
-       int i;
-       unsigned short tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 2) {
-               tmp = inw(port);
-               p[0] = tmp & 0xff;
-               p[1] = (tmp >> 8) & 0xff;
-       }
-}
-
-
-void od_outsl(unsigned long port, const void *addr, unsigned long count)
-{
-       int i;
-       unsigned tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 4) {
-               tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
-                     ((*(p + 3)) << 24);
-               outl(tmp, port);
-       }
-}
-
-
-void od_insl(unsigned long port, void *addr, unsigned long count)
-{
-       int i;
-       unsigned tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 4) {
-               tmp = inl(port);
-               p[0] = tmp & 0xff;
-               p[1] = (tmp >> 8) & 0xff;
-               p[2] = (tmp >> 16) & 0xff;
-               p[3] = (tmp >> 24) & 0xff;
-
-       }
-}
diff --git a/arch/sh/boards/overdrive/irq.c b/arch/sh/boards/overdrive/irq.c
deleted file mode 100644 (file)
index 5d730c7..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Looks after interrupts on the overdrive board.
- *
- * Bases on the IPR irq system
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/overdrive/overdrive.h>
-
-struct od_data {
-       int overdrive_irq;
-       int irq_mask;
-};
-
-#define NUM_EXTERNAL_IRQS 16
-#define EXTERNAL_IRQ_NOT_IN_USE (-1)
-#define EXTERNAL_IRQ_NOT_ASSIGNED (-1)
-
-/*
- * This table is used to determine what to program into the FPGA's CT register
- * for the specified Linux IRQ.
- *
- * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0))
- * but is one greater than that because the because the FPGA treats 0
- * as disabled, a value of 1 asserts PCI_Int0, and so on.
- *
- * The overdrive_irq specifies which of the eight interrupt sources generates
- * that interrupt, and but is multiplied by four to give the bit offset into
- * the CT register.
- *
- * The seven interrupts levels (SH4 IRL's) we have available here is hardwired
- * by the EPLD. The assignments here of which PCI interrupt generates each
- * level is arbitary.
- */
-static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = {
-       /*    overdrive_irq       , irq_mask */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 0 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 7}, /* 1 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 6}, /* 2 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 3 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 5}, /* 4 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 5 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 6 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 4}, /* 7 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 8 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 9 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 3}, /* 10 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 2}, /* 11 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 12 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 1}, /* 13 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 14 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}    /* 15 */
-};
-
-static void set_od_data(int overdrive_irq, int irq)
-{
-       if (irq >= NUM_EXTERNAL_IRQS || irq < 0)
-               return;
-       od_data_table[irq].overdrive_irq = overdrive_irq << 2;
-}
-
-static void enable_od_irq(unsigned int irq);
-void disable_od_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_od_irq disable_od_irq
-
-static void mask_and_ack_od(unsigned int);
-static void end_od_irq(unsigned int irq);
-
-static unsigned int startup_od_irq(unsigned int irq)
-{
-       enable_od_irq(irq);
-       return 0;               /* never anything pending */
-}
-
-static struct hw_interrupt_type od_irq_type = {
-       .typename = "Overdrive-IRQ",
-       .startup = startup_od_irq,
-       .shutdown = shutdown_od_irq,
-       .enable = enable_od_irq,
-       .disable = disable_od_irq,
-       .ack = mask_and_ack_od,
-       .end = end_od_irq
-};
-
-static void disable_od_irq(unsigned int irq)
-{
-       unsigned val, flags;
-       int overdrive_irq;
-       unsigned mask;
-
-       /* Not a valid interrupt */
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-        /* Is is necessary to use a cli here? Would a spinlock not be 
-         * mroe efficient?
-         */
-       local_irq_save(flags);
-       overdrive_irq = od_data_table[irq].overdrive_irq;
-       if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
-               mask = ~(0x7 << overdrive_irq);
-               val = ctrl_inl(OVERDRIVE_INT_CT);
-               val &= mask;
-               ctrl_outl(val, OVERDRIVE_INT_CT);
-       }
-       local_irq_restore(flags);
-}
-
-static void enable_od_irq(unsigned int irq)
-{
-       unsigned val, flags;
-       int overdrive_irq;
-       unsigned mask;
-
-       /* Not a valid interrupt */
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-       /* Set priority in OD back to original value */
-       local_irq_save(flags);
-       /* This one is not in use currently */
-       overdrive_irq = od_data_table[irq].overdrive_irq;
-       if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
-               val = ctrl_inl(OVERDRIVE_INT_CT);
-               mask = ~(0x7 << overdrive_irq);
-               val &= mask;
-               mask = od_data_table[irq].irq_mask << overdrive_irq;
-               val |= mask;
-               ctrl_outl(val, OVERDRIVE_INT_CT);
-       }
-       local_irq_restore(flags);
-}
-
-
-
-/* this functions sets the desired irq handler to be an overdrive type */
-static void __init make_od_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &od_irq_type;
-       disable_od_irq(irq);
-}
-
-
-static void mask_and_ack_od(unsigned int irq)
-{
-       disable_od_irq(irq);
-}
-
-static void end_od_irq(unsigned int irq)
-{
-       enable_od_irq(irq);
-}
-
-void __init init_overdrive_irq(void)
-{
-       int i;
-
-       /* Disable all interrupts */
-       ctrl_outl(0, OVERDRIVE_INT_CT);
-
-       /* Update interrupt pin mode to use encoded interrupts */
-       i = ctrl_inw(INTC_ICR);
-       i &= ~INTC_ICR_IRLM;
-       ctrl_outw(i, INTC_ICR);
-
-       for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
-               if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) {
-                       make_od_irq(i);
-               } else if (i != 15) {   // Cannot use imask on level 15
-                       make_imask_irq(i);
-               }
-       }
-
-       /* Set up the interrupts */
-       set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1);
-       set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2);
-       set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ);
-}
diff --git a/arch/sh/boards/overdrive/led.c b/arch/sh/boards/overdrive/led.c
deleted file mode 100644 (file)
index 860d7f2..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * linux/arch/sh/overdrive/led.c
- *
- * Copyright (C) 1999 Stuart Menefy <stuart.menefy@st.com>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * This file contains an Overdrive specific LED feature.
- */
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/overdrive/overdrive.h>
-
-static void mach_led(int position, int value)
-{
-       unsigned long flags;
-       unsigned long reg;
-
-       local_irq_save(flags);
-       
-       reg = readl(OVERDRIVE_CTRL);
-       if (value) {
-               reg |= (1<<3);
-       } else {
-               reg &= ~(1<<3);
-       }
-       writel(reg, OVERDRIVE_CTRL);
-
-       local_irq_restore(flags);
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* acts like an actual heart beat -- ie thump-thump-pause... */
-void heartbeat_od(void)
-{
-       static unsigned cnt = 0, period = 0, dist = 0;
-
-       if (cnt == 0 || cnt == dist)
-               mach_led( -1, 1);
-       else if (cnt == 7 || cnt == dist+7)
-               mach_led( -1, 0);
-
-       if (++cnt > period) {
-               cnt = 0;
-               /* The hyperbolic function below modifies the heartbeat period
-                * length in dependency of the current (5min) load. It goes
-                * through the points f(0)=126, f(1)=86, f(5)=51,
-                * f(inf)->30. */
-               period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-               dist = period / 4;
-       }
-}
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/overdrive/mach.c b/arch/sh/boards/overdrive/mach.c
deleted file mode 100644 (file)
index 2834a03..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/arch/sh/overdrive/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the STMicroelectronics Overdrive
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io_unknown.h>
-#include <asm/io_generic.h>
-#include <asm/overdrive/io.h>
-
-void heartbeat_od(void);
-void init_overdrive_irq(void);
-void galileo_pcibios_init(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_od __initmv = {
-       .mv_nr_irqs             = 48,
-
-       .mv_inb                 = od_inb,
-       .mv_inw                 = od_inw,
-       .mv_inl                 = od_inl,
-       .mv_outb                = od_outb,
-       .mv_outw                = od_outw,
-       .mv_outl                = od_outl,
-
-       .mv_inb_p               = od_inb_p,
-       .mv_inw_p               = od_inw_p,
-       .mv_inl_p               = od_inl_p,
-       .mv_outb_p              = od_outb_p,
-       .mv_outw_p              = od_outw_p,
-       .mv_outl_p              = od_outl_p,
-
-       .mv_insb                = od_insb,
-       .mv_insw                = od_insw,
-       .mv_insl                = od_insl,
-       .mv_outsb               = od_outsb,
-       .mv_outsw               = od_outsw,
-       .mv_outsl               = od_outsl,
-
-#ifdef CONFIG_PCI
-       .mv_init_irq            = init_overdrive_irq,
-#endif
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_od,
-#endif
-};
-
-ALIAS_MV(od)
diff --git a/arch/sh/boards/overdrive/pcidma.c b/arch/sh/boards/overdrive/pcidma.c
deleted file mode 100644 (file)
index 1c9bfed..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Dynamic DMA mapping support.
- *
- * On the overdrive, we can only DMA from memory behind the PCI bus!
- * this means that all DMA'able memory must come from there. 
- * this restriction will not apply to later boards.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                          dma_addr_t * dma_handle)
-{
-       void *ret;
-       int gfp = GFP_ATOMIC;
-
-        printk("BUG: pci_alloc_consistent() called - not yet supported\n");
-       /* We ALWAYS need DMA memory on the overdrive hardware,
-        * due to it's extreme weirdness
-        * Need to flush the cache here as well, since the memory
-        * can still be seen through the cache!
-        */
-       gfp |= GFP_DMA;
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-       }
-       return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle)
-{
-       free_pages((unsigned long) vaddr, get_order(size));
-}
diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c
deleted file mode 100644 (file)
index a3a7744..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/sh/overdrive/setup.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * STMicroelectronics Overdrive Support.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/fpga.h>
-
-const char *get_system_type(void)
-{
-       return "SH7750 Overdrive";
-}
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-#ifdef CONFIG_PCI
-       init_overdrive_fpga();
-       galileo_init();
-#endif
-
-        /* Enable RS232 receive buffers */
-       writel(0x1e, OVERDRIVE_CTRL);
-}
index 7fccbf2e4a1db776906a1c41eadd39cafbb8bd83..14bdd531f11627be815e69df5206bff15c3deeaf 100644 (file)
@@ -1,10 +1,6 @@
 #
 # Makefile for the EDOSK7705 specific parts of the kernel
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
 
 obj-y   := setup.o io.o
 
index ba143fa4afaafd99f23ae0120c992778b45c00c3..ec5be0107719ecea1d340d4e68e78ecc6c832c64 100644 (file)
@@ -8,19 +8,21 @@
  * Modified for edosk7705 development
  * board by S. Dunn, 2003.
  */
-
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
 #include <asm/edosk7705/io.h>
 
-static void init_edosk7705(void);
+static void __init sh_edosk7705_init_irq(void)
+{
+       /* This is the Ethernet interrupt */
+       make_imask_irq(0x09);
+}
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_edosk7705 __initmv = {
+       .mv_name                = "EDOSK7705",
        .mv_nr_irqs             = 80,
 
        .mv_inb                 = sh_edosk7705_inb,
@@ -37,23 +39,6 @@ struct sh_machine_vector mv_edosk7705 __initmv = {
        .mv_outsl               = sh_edosk7705_outsl,
 
        .mv_isa_port2addr       = sh_edosk7705_isa_port2addr,
-       .mv_init_irq            = init_edosk7705,
+       .mv_init_irq            = sh_edosk7705_init_irq,
 };
 ALIAS_MV(edosk7705)
-
-static void __init init_edosk7705(void)
-{
-       /* This is the Ethernet interrupt */
-       make_imask_irq(0x09);
-}
-
-const char *get_system_type(void)
-{
-       return "EDOSK7705";
-}
-
-void __init platform_setup(void)
-{
-       /* Nothing .. */
-}
-
diff --git a/arch/sh/boards/renesas/hs7751rvoip/Kconfig b/arch/sh/boards/renesas/hs7751rvoip/Kconfig
new file mode 100644 (file)
index 0000000..1743be4
--- /dev/null
@@ -0,0 +1,12 @@
+if SH_HS7751RVOIP
+
+menu "HS7751RVoIP options"
+
+config HS7751RVOIP_CODEC
+       bool "Support VoIP Codec section"
+       help
+         Selecting this option will support CODEC section.
+
+endmenu
+
+endif
index e8b4109ace117c662068b1fa78d43f639cc85f1f..e626377c55eecc1e591fda6b2ee25523f3ac4139 100644 (file)
@@ -1,12 +1,8 @@
 #
 # Makefile for the HS7751RVoIP specific parts of the kernel
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
 
-obj-y   := mach.o setup.o io.o irq.o led.o
+obj-y   := setup.o io.o irq.o
 
 obj-$(CONFIG_PCI) += pci.o
 
index 3a1abfa2fefb99917b4df26e990b44acab14b899..9ea1136b219b2ca9fa78cbbeda1d2127aa237fb3 100644 (file)
  * placeholder code from io_hs7751rvoip.c left in with the
  * expectation of later SuperIO and PCMCIA access.
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/hs7751rvoip/hs7751rvoip.h>
 #include <asm/addrspace.h>
 
-#include <linux/module.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-extern void *area5_io8_base;   /* Area 5 8bit I/O Base address */
 extern void *area6_io8_base;   /* Area 6 8bit I/O Base address */
 extern void *area5_io16_base;  /* Area 5 16bit I/O Base address */
-extern void *area6_io16_base;  /* Area 6 16bit I/O Base address */
 
 /*
  * The 7751R HS7751RVoIP uses the built-in PCI controller (PCIC)
@@ -33,25 +28,8 @@ extern void *area6_io16_base;        /* Area 6 16bit I/O Base address */
  * like the other Solution Engine boards.
  */
 
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#if defined(CONFIG_HS7751RVOIP_CODEC)
 #define CODEC_IO_BASE  0x1000
-#endif
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
+#define CODEC_IOMAP(a) ((unsigned long)area6_io8_base + ((a) - CODEC_IO_BASE))
 
 static inline unsigned long port2adr(unsigned int port)
 {
@@ -59,9 +37,10 @@ static inline unsigned long port2adr(unsigned int port)
                if (port == 0x3f6)
                        return ((unsigned long)area5_io16_base + 0x0c);
                else
-                       return ((unsigned long)area5_io16_base + 0x800 + ((port-0x1f0) << 1));
+                       return ((unsigned long)area5_io16_base + 0x800 +
+                               ((port-0x1f0) << 1));
        else
-               maybebadio(port2adr, (unsigned long)port);
+               maybebadio((unsigned long)port);
        return port;
 }
 
@@ -78,25 +57,10 @@ static inline int shifted_port(unsigned long port)
 }
 
 #if defined(CONFIG_HS7751RVOIP_CODEC)
-static inline int
-codec_port(unsigned long port)
-{
-       if (CODEC_IO_BASE <= port && port < (CODEC_IO_BASE+0x20))
-               return 1;
-       else
-               return 0;
-}
-#endif
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#define codec_port(port)       \
+       ((CODEC_IO_BASE <= (port)) && ((port) < (CODEC_IO_BASE + 0x20)))
 #else
-#define CHECK_SH7751_PCIIO(port) (0)
+#define codec_port(port)       (0)
 #endif
 
 /*
@@ -109,15 +73,13 @@ codec_port(unsigned long port)
 unsigned char hs7751rvoip_inb(unsigned long port)
 {
        if (PXSEG(port))
-               return *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               return ctrl_inb(port);
        else if (codec_port(port))
-               return *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+               return ctrl_inb(CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inb(pci_ioaddr(port));
        else
-               return (*(volatile unsigned short *)port2adr(port) & 0xff);
+               return ctrl_inw(port2adr(port)) & 0xff;
 }
 
 unsigned char hs7751rvoip_inb_p(unsigned long port)
@@ -125,38 +87,36 @@ unsigned char hs7751rvoip_inb_p(unsigned long port)
        unsigned char v;
 
         if (PXSEG(port))
-                v = *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               v = ctrl_inb(port);
        else if (codec_port(port))
-               v = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-                v = *(volatile unsigned char *)PCI_IOMAP(port);
+               v = ctrl_inb(CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               v = ctrl_inb(pci_ioaddr(port));
        else
-               v = (*(volatile unsigned short *)port2adr(port) & 0xff);
-       delay();
+               v = ctrl_inw(port2adr(port)) & 0xff;
+       ctrl_delay();
        return v;
 }
 
 unsigned short hs7751rvoip_inw(unsigned long port)
 {
         if (PXSEG(port))
-                return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-                return *(volatile unsigned short *)PCI_IOMAP(port);
+               return ctrl_inw(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inw(pci_ioaddr(port));
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
 unsigned int hs7751rvoip_inl(unsigned long port)
 {
         if (PXSEG(port))
-                return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-                return *(volatile unsigned long *)PCI_IOMAP(port);
+               return ctrl_inl(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inl(pci_ioaddr(port));
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -164,146 +124,160 @@ void hs7751rvoip_outb(unsigned char value, unsigned long port)
 {
 
         if (PXSEG(port))
-                *(volatile unsigned char *)port = value;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               ctrl_outb(value, port);
        else if (codec_port(port))
-               *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(unsigned char *)PCI_IOMAP(port) = value;
+               ctrl_outb(value, CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outb(value, pci_ioaddr(port));
        else
-               *(volatile unsigned short *)port2adr(port) = value;
+               ctrl_outb(value, port2adr(port));
 }
 
 void hs7751rvoip_outb_p(unsigned char value, unsigned long port)
 {
         if (PXSEG(port))
-                *(volatile unsigned char *)port = value;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               ctrl_outb(value, port);
        else if (codec_port(port))
-               *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(unsigned char *)PCI_IOMAP(port) = value;
+               ctrl_outb(value, CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outb(value, pci_ioaddr(port));
        else
-               *(volatile unsigned short *)port2adr(port) = value;
-       delay();
+               ctrl_outw(value, port2adr(port));
+
+       ctrl_delay();
 }
 
 void hs7751rvoip_outw(unsigned short value, unsigned long port)
 {
         if (PXSEG(port))
-                *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(unsigned short *)PCI_IOMAP(port) = value;
+               ctrl_outw(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outw(value, pci_ioaddr(port));
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void hs7751rvoip_outl(unsigned int value, unsigned long port)
 {
         if (PXSEG(port))
-                *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *((unsigned long *)PCI_IOMAP(port)) = value;
+               ctrl_outl(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outl(value, pci_ioaddr(port));
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void hs7751rvoip_insb(unsigned long port, void *addr, unsigned long count)
 {
+       u8 *buf = addr;
+
        if (PXSEG(port))
-               while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               while (count--)
+                       *buf++ = ctrl_inb(port);
        else if (codec_port(port))
-               while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+               while (count--)
+                       *buf++ = ctrl_inb(CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
-               while (count--) *((volatile unsigned char *) addr)++ = *bp;
+               while (count--)
+                       *buf++ = *bp;
        } else {
-               volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+               volatile u16 *p = (volatile u16 *)port2adr(port);
 
-               while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+               while (count--)
+                       *buf++ = *p & 0xff;
        }
 }
 
 void hs7751rvoip_insw(unsigned long port, void *addr, unsigned long count)
 {
-       volatile __u16 *p;
+       volatile u16 *p;
+       u16 *buf = addr;
 
        if (PXSEG(port))
-               p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(port);
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile u16 *)pci_ioaddr(port);
        else
-               p = (volatile unsigned short *)port2adr(port);
-       while (count--) *((__u16 *) addr)++ = *p;
+               p = (volatile u16 *)port2adr(port);
+       while (count--)
+               *buf++ = *p;
 }
 
 void hs7751rvoip_insl(unsigned long port, void *addr, unsigned long count)
 {
-       if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
 
-               while (count--) *((__u32 *) addr)++ = *p;
+       if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+               u32 *buf = addr;
+
+               while (count--)
+                       *buf++ = *p;
        } else
-               maybebadio(insl, port);
+               maybebadio(port);
 }
 
 void hs7751rvoip_outsb(unsigned long port, const void *addr, unsigned long count)
 {
+       const u8 *buf = addr;
+
        if (PXSEG(port))
-               while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               while (count--)
+                       ctrl_outb(*buf++, port);
        else if (codec_port(port))
-               while (count--) *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = *((unsigned char *) addr)++;
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+               while (count--)
+                       ctrl_outb(*buf++, CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
-               while (count--) *bp = *((volatile unsigned char *) addr)++;
+               while (count--)
+                       *bp = *buf++;
        } else {
-               volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+               volatile u16 *p = (volatile u16 *)port2adr(port);
 
-               while (count--) *p = *((unsigned char *) addr)++;
+               while (count--)
+                       *p = *buf++;
        }
 }
 
 void hs7751rvoip_outsw(unsigned long port, const void *addr, unsigned long count)
 {
-       volatile __u16 *p;
+       volatile u16 *p;
+       const u16 *buf = addr;
 
        if (PXSEG(port))
-               p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(port);
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile u16 *)pci_ioaddr(port);
        else
-               p = (volatile unsigned short *)port2adr(port);
-       while (count--) *p = *((__u16 *) addr)++;
+               p = (volatile u16 *)port2adr(port);
+
+       while (count--)
+               *p = *buf++;
 }
 
 void hs7751rvoip_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+       const u32 *buf = addr;
 
-               while (count--) *p = *((__u32 *) addr)++;
+       if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+               while (count--)
+                       *p = *buf++;
        } else
-               maybebadio(outsl, port);
+               maybebadio(port);
 }
 
-void *hs7751rvoip_ioremap(unsigned long offset, unsigned long size)
+void __iomem *hs7751rvoip_ioport_map(unsigned long port, unsigned int size)
 {
-       if (offset >= 0xfd000000)
-               return (void *)offset;
-       else
-               return (void *)P2SEGADDR(offset);
-}
-EXPORT_SYMBOL(hs7751rvoip_ioremap);
+        if (PXSEG(port))
+                return (void __iomem *)port;
+       else if (unlikely(codec_port(port) && (size == 1)))
+               return (void __iomem *)CODEC_IOMAP(port);
+        else if (is_pci_ioaddr(port))
+                return (void __iomem *)pci_ioaddr(port);
 
-unsigned long hs7751rvoip_isa_port2addr(unsigned long offset)
-{
-       return port2adr(offset);
+        return (void __iomem *)port2adr(port);
 }
index 705b7ddcb0d28a4f17dd9197fbd9124238063d2d..c617b188258a0e4a27bbb731f4ec99e48c0cdad3 100644 (file)
@@ -35,30 +35,24 @@ static unsigned int startup_hs7751rvoip_irq(unsigned int irq)
 
 static void disable_hs7751rvoip_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
 
        /* Set the priority in IPR to 0 */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR3);
        val &= mask;
        ctrl_outw(val, IRLCNTR3);
-       local_irq_restore(flags);
 }
 
 static void enable_hs7751rvoip_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short value = (0x0001 << mask_pos[irq]);
 
        /* Set priority in IPR back to original value */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR3);
        val |= value;
        ctrl_outw(val, IRLCNTR3);
-       local_irq_restore(flags);
 }
 
 static void ack_hs7751rvoip_irq(unsigned int irq)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/led.c b/arch/sh/boards/renesas/hs7751rvoip/led.c
deleted file mode 100644 (file)
index b6608ff..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/arch/sh/kernel/setup_hs7751rvoip.c
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
- * Renesas Technology Sales HS7751RVoIP Support.
- *
- * Modified for HS7751RVoIP by
- * Atom Create Engineering Co., Ltd. 2002.
- * Lineo uSolutions, Inc. 2003.
- */
-
-#include <asm/io.h>
-#include <asm/hs7751rvoip/hs7751rvoip.h>
-
-extern unsigned int debug_counter;
-
-void debug_led_disp(void)
-{
-       unsigned short value;
-
-       value = (unsigned char)debug_counter++;
-       ctrl_outb((0xf0|value), PA_OUTPORTR);
-       if (value == 0x0f)
-               debug_counter = 0;
-}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/mach.c b/arch/sh/boards/renesas/hs7751rvoip/mach.c
deleted file mode 100644 (file)
index caf967f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_hs7751rvoip.c
- *
- * Minor tweak of mach_se.c file to reference hs7751rvoip-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Renesas Technology sales HS7751RVoIP
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
-#include <asm/hs7751rvoip/io.h>
-
-extern void init_hs7751rvoip_IRQ(void);
-extern void *hs7751rvoip_ioremap(unsigned long, unsigned long);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_hs7751rvoip __initmv = {
-       .mv_nr_irqs             = 72,
-
-       .mv_inb                 = hs7751rvoip_inb,
-       .mv_inw                 = hs7751rvoip_inw,
-       .mv_inl                 = hs7751rvoip_inl,
-       .mv_outb                = hs7751rvoip_outb,
-       .mv_outw                = hs7751rvoip_outw,
-       .mv_outl                = hs7751rvoip_outl,
-
-       .mv_inb_p               = hs7751rvoip_inb_p,
-       .mv_inw_p               = hs7751rvoip_inw,
-       .mv_inl_p               = hs7751rvoip_inl,
-       .mv_outb_p              = hs7751rvoip_outb_p,
-       .mv_outw_p              = hs7751rvoip_outw,
-       .mv_outl_p              = hs7751rvoip_outl,
-
-       .mv_insb                = hs7751rvoip_insb,
-       .mv_insw                = hs7751rvoip_insw,
-       .mv_insl                = hs7751rvoip_insl,
-       .mv_outsb               = hs7751rvoip_outsb,
-       .mv_outsw               = hs7751rvoip_outsw,
-       .mv_outsl               = hs7751rvoip_outsl,
-
-       .mv_ioremap             = hs7751rvoip_ioremap,
-       .mv_isa_port2addr       = hs7751rvoip_isa_port2addr,
-       .mv_init_irq            = init_hs7751rvoip_IRQ,
-};
-ALIAS_MV(hs7751rvoip)
index 29fb5ff70fb54fc9f7b19f2ac3612820c7deb925..0414c15c3458da63969f97c7cf3ddb923646bbdb 100644 (file)
@@ -1,44 +1,38 @@
 /*
- * linux/arch/sh/kernel/setup_hs7751rvoip.c
+ * Renesas Technology Sales HS7751RVoIP Support.
  *
  * Copyright (C) 2000  Kazumoto Kojima
  *
- * Renesas Technology Sales HS7751RVoIP Support.
- *
  * Modified for HS7751RVoIP by
  * Atom Create Engineering Co., Ltd. 2002.
  * Lineo uSolutions, Inc. 2003.
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
-
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/pm.h>
 #include <asm/io.h>
 #include <asm/hs7751rvoip/hs7751rvoip.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/irq.h>
 
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-
-/* defined in mm/ioremap.c */
-extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-
-unsigned int debug_counter;
-
-const char *get_system_type(void)
+static void __init hs7751rvoip_init_irq(void)
 {
-       return "HS7751RVoIP";
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+       make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+#endif
+
+       init_hs7751rvoip_IRQ();
 }
 
-/*
- * Initialize the board
- */
-void __init platform_setup(void)
+static void hs7751rvoip_power_off(void)
 {
-       printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
-       ctrl_outb(0xf0, PA_OUTPORTR);
-       debug_counter = 0;
+       ctrl_outw(ctrl_inw(PA_OUTPORTR) & 0xffdf, PA_OUTPORTR);
 }
 
 void *area5_io8_base;
@@ -46,16 +40,15 @@ void *area6_io8_base;
 void *area5_io16_base;
 void *area6_io16_base;
 
-int __init cf_init(void)
+static int __init hs7751rvoip_cf_init(void)
 {
        pgprot_t prot;
-       unsigned long paddrbase, psize;
+       unsigned long paddrbase;
 
        /* open I/O area window */
        paddrbase = virt_to_phys((void *)(PA_AREA5_IO+0x00000800));
-       psize = PAGE_SIZE;
        prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_COM16);
-       area5_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       area5_io16_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
        if (!area5_io16_base) {
                printk("allocate_cf_area : can't open CF I/O window!\n");
                return -ENOMEM;
@@ -64,19 +57,18 @@ int __init cf_init(void)
        /* XXX : do we need attribute and common-memory area also? */
 
        paddrbase = virt_to_phys((void *)PA_AREA6_IO);
-       psize = PAGE_SIZE;
 #if defined(CONFIG_HS7751RVOIP_CODEC)
        prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_COM8);
 #else
        prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO8);
 #endif
-       area6_io8_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       area6_io8_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
        if (!area6_io8_base) {
                printk("allocate_cf_area : can't open CODEC I/O 8bit window!\n");
                return -ENOMEM;
        }
        prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
-       area6_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       area6_io16_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
        if (!area6_io16_base) {
                printk("allocate_cf_area : can't open CODEC I/O 16bit window!\n");
                return -ENOMEM;
@@ -85,4 +77,46 @@ int __init cf_init(void)
        return 0;
 }
 
-__initcall (cf_init);
+/*
+ * Initialize the board
+ */
+static void __init hs7751rvoip_setup(char **cmdline_p)
+{
+       device_initcall(hs7751rvoip_cf_init);
+
+       ctrl_outb(0xf0, PA_OUTPORTR);
+       pm_power_off = hs7751rvoip_power_off;
+
+       printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
+}
+
+struct sh_machine_vector mv_hs7751rvoip __initmv = {
+       .mv_name                = "HS7751RVoIP",
+       .mv_setup               = hs7751rvoip_setup,
+       .mv_nr_irqs             = 72,
+
+       .mv_inb                 = hs7751rvoip_inb,
+       .mv_inw                 = hs7751rvoip_inw,
+       .mv_inl                 = hs7751rvoip_inl,
+       .mv_outb                = hs7751rvoip_outb,
+       .mv_outw                = hs7751rvoip_outw,
+       .mv_outl                = hs7751rvoip_outl,
+
+       .mv_inb_p               = hs7751rvoip_inb_p,
+       .mv_inw_p               = hs7751rvoip_inw,
+       .mv_inl_p               = hs7751rvoip_inl,
+       .mv_outb_p              = hs7751rvoip_outb_p,
+       .mv_outw_p              = hs7751rvoip_outw,
+       .mv_outl_p              = hs7751rvoip_outl,
+
+       .mv_insb                = hs7751rvoip_insb,
+       .mv_insw                = hs7751rvoip_insw,
+       .mv_insl                = hs7751rvoip_insl,
+       .mv_outsb               = hs7751rvoip_outsb,
+       .mv_outsw               = hs7751rvoip_outsw,
+       .mv_outsl               = hs7751rvoip_outsl,
+
+       .mv_init_irq            = hs7751rvoip_init_irq,
+       .mv_ioport_map          = hs7751rvoip_ioport_map,
+};
+ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/r7780rp/Kconfig b/arch/sh/boards/renesas/r7780rp/Kconfig
new file mode 100644 (file)
index 0000000..c26d981
--- /dev/null
@@ -0,0 +1,14 @@
+if SH_R7780RP
+
+menu "R7780RP options"
+
+config SH_R7780MP
+       bool "R7780MP board support"
+       default y
+       help
+         Selecting this option will enable support for the mass-production
+         version of the R7780RP. If in doubt, say Y.
+
+endmenu
+
+endif
diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile
new file mode 100644 (file)
index 0000000..f1776d0
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the R7780RP-1 specific parts of the kernel
+#
+
+obj-y   := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT)        += led.o
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c
new file mode 100644 (file)
index 0000000..db92d6e
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Renesas Solutions Highlander R7780RP-1
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_r7780rp.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+static inline unsigned long port2adr(unsigned int port)
+{
+       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+               if (port == 0x3f6)
+                       return (PA_AREA5_IO + 0x80c);
+               else
+                       return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
+       else
+               maybebadio((unsigned long)port);
+
+       return port;
+}
+
+static inline unsigned long port88796l(unsigned int port, int flag)
+{
+       unsigned long addr;
+
+       if (flag)
+               addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1);
+       else
+               addr = PA_AX88796L + ((port - AX88796L_IO_BASE) << 1) + 0x1000;
+
+       return addr;
+}
+
+/* The 7780 R7780RP-1 seems to have everything hooked */
+/* up pretty normally (nothing on high-bytes only...) so this */
+/* shouldn't be needed */
+static inline int shifted_port(unsigned long port)
+{
+       /* For IDE registers, value is not shifted */
+       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+               return 0;
+       else
+               return 1;
+}
+
+#if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
+#define CHECK_AX88796L_PORT(port) \
+  ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
+#else
+#define CHECK_AX88796L_PORT(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used  w/o translation for
+ * compatibility.
+ */
+u8 r7780rp_inb(unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               return ctrl_inw(port88796l(port, 0)) & 0xff;
+       else if (PXSEG(port))
+               return ctrl_inb(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inb(pci_ioaddr(port));
+
+       return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 r7780rp_inb_p(unsigned long port)
+{
+       u8 v;
+
+       if (CHECK_AX88796L_PORT(port))
+               v = ctrl_inw(port88796l(port, 0)) & 0xff;
+       else if (PXSEG(port))
+               v = ctrl_inb(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               v = ctrl_inb(pci_ioaddr(port));
+       else
+               v = ctrl_inw(port2adr(port)) & 0xff;
+
+       ctrl_delay();
+
+       return v;
+}
+
+u16 r7780rp_inw(unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (PXSEG(port))
+               return ctrl_inw(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inw(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+u32 r7780rp_inl(unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (PXSEG(port))
+               return ctrl_inl(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inl(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+void r7780rp_outb(u8 value, unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               ctrl_outw(value, port88796l(port, 0));
+       else if (PXSEG(port))
+               ctrl_outb(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(port));
+}
+
+void r7780rp_outb_p(u8 value, unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               ctrl_outw(value, port88796l(port, 0));
+       else if (PXSEG(port))
+               ctrl_outb(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(port));
+
+       ctrl_delay();
+}
+
+void r7780rp_outw(u16 value, unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (PXSEG(port))
+               ctrl_outw(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outw(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void r7780rp_outl(u32 value, unsigned long port)
+{
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (PXSEG(port))
+               ctrl_outl(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outl(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
+{
+       volatile u16 *p;
+       u8 *buf = dst;
+
+       if (CHECK_AX88796L_PORT(port)) {
+               p = (volatile u16 *)port88796l(port, 0);
+               while (count--)
+                       *buf++ = *p & 0xff;
+       } else if (PXSEG(port)) {
+               while (count--)
+                       *buf++ = *(volatile u8 *)port;
+       } else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+               while (count--)
+                       *buf++ = *bp;
+       } else {
+               p = (volatile u16 *)port2adr(port);
+               while (count--)
+                       *buf++ = *p & 0xff;
+       }
+}
+
+void r7780rp_insw(unsigned long port, void *dst, unsigned long count)
+{
+       volatile u16 *p;
+       u16 *buf = dst;
+
+       if (CHECK_AX88796L_PORT(port))
+               p = (volatile u16 *)port88796l(port, 1);
+       else if (PXSEG(port))
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile u16 *)pci_ioaddr(port);
+       else
+               p = (volatile u16 *)port2adr(port);
+
+       while (count--)
+               *buf++ = *p;
+}
+
+void r7780rp_insl(unsigned long port, void *dst, unsigned long count)
+{
+       u32 *buf = dst;
+
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+               while (count--)
+                       *buf++ = *p;
+       } else
+               maybebadio(port);
+}
+
+void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
+{
+       volatile u16 *p;
+       const u8 *buf = src;
+
+       if (CHECK_AX88796L_PORT(port)) {
+               p = (volatile u16 *)port88796l(port, 0);
+               while (count--)
+                       *p = *buf++;
+       } else if (PXSEG(port))
+               while (count--)
+                       ctrl_outb(*buf++, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+               while (count--)
+                       *bp = *buf++;
+       } else {
+               p = (volatile u16 *)port2adr(port);
+               while (count--)
+                       *p = *buf++;
+       }
+}
+
+void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
+{
+       volatile u16 *p;
+       const u16 *buf = src;
+
+       if (CHECK_AX88796L_PORT(port))
+               p = (volatile u16 *)port88796l(port, 1);
+       else if (PXSEG(port))
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile u16 *)pci_ioaddr(port);
+       else
+               p = (volatile u16 *)port2adr(port);
+
+       while (count--)
+               *p = *buf++;
+}
+
+void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
+{
+       const u32 *buf = src;
+
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+               while (count--)
+                       *p = *buf++;
+       } else
+               maybebadio(port);
+}
+
+void __iomem *r7780rp_ioport_map(unsigned long port, unsigned int size)
+{
+       if (CHECK_AX88796L_PORT(port))
+               return (void __iomem *)port88796l(port, size > 1);
+       else if (PXSEG(port))
+               return (void __iomem *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return (void __iomem *)pci_ioaddr(port);
+
+       return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c
new file mode 100644 (file)
index 0000000..61d5e5d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * linux/arch/sh/boards/renesas/r7780rp/irq.c
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * Modified for R7780RP-1 by
+ * Atom Create Engineering Co., Ltd. 2002.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/r7780rp/r7780rp.h>
+
+#ifdef CONFIG_SH_R7780MP
+static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
+#else
+static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0};
+#endif
+
+static void enable_r7780rp_irq(unsigned int irq);
+static void disable_r7780rp_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_r7780rp_irq disable_r7780rp_irq
+
+static void ack_r7780rp_irq(unsigned int irq);
+static void end_r7780rp_irq(unsigned int irq);
+
+static unsigned int startup_r7780rp_irq(unsigned int irq)
+{
+       enable_r7780rp_irq(irq);
+       return 0; /* never anything pending */
+}
+
+static void disable_r7780rp_irq(unsigned int irq)
+{
+       unsigned short val;
+       unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
+
+       /* Set the priority in IPR to 0 */
+       val = ctrl_inw(IRLCNTR1);
+       val &= mask;
+       ctrl_outw(val, IRLCNTR1);
+}
+
+static void enable_r7780rp_irq(unsigned int irq)
+{
+       unsigned short val;
+       unsigned short value = (0x0001 << mask_pos[irq]);
+
+       /* Set priority in IPR back to original value */
+       val = ctrl_inw(IRLCNTR1);
+       val |= value;
+       ctrl_outw(val, IRLCNTR1);
+}
+
+static void ack_r7780rp_irq(unsigned int irq)
+{
+       disable_r7780rp_irq(irq);
+}
+
+static void end_r7780rp_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               enable_r7780rp_irq(irq);
+}
+
+static struct hw_interrupt_type r7780rp_irq_type = {
+       .typename = "R7780RP-IRQ",
+       .startup = startup_r7780rp_irq,
+       .shutdown = shutdown_r7780rp_irq,
+       .enable = enable_r7780rp_irq,
+       .disable = disable_r7780rp_irq,
+       .ack = ack_r7780rp_irq,
+       .end = end_r7780rp_irq,
+};
+
+static void make_r7780rp_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &r7780rp_irq_type;
+       disable_r7780rp_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_r7780rp_IRQ(void)
+{
+       int i;
+
+       /* IRL0=PCI Slot #A
+        * IRL1=PCI Slot #B
+        * IRL2=PCI Slot #C
+        * IRL3=PCI Slot #D
+        * IRL4=CF Card
+        * IRL5=CF Card Insert
+        * IRL6=M66596
+        * IRL7=SD Card
+        * IRL8=Touch Panel
+        * IRL9=SCI
+        * IRL10=Serial
+        * IRL11=Extention #A
+        * IRL11=Extention #B
+        * IRL12=Debug LAN
+        * IRL13=Push Switch
+        * IRL14=ZiggBee IO
+        */
+
+       for (i=0; i<15; i++)
+               make_r7780rp_irq(i);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/led.c b/arch/sh/boards/renesas/r7780rp/led.c
new file mode 100644 (file)
index 0000000..9f02766
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) Atom Create Engineering Co., Ltd.
+ *
+ * May be copied or modified under the terms of GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains Renesas Solutions HIGHLANDER R7780RP-1 specific LED code.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/r7780rp/r7780rp.h>
+
+/* Cycle the LED's in the clasic Knightriger/Sun pattern */
+void heartbeat_r7780rp(void)
+{
+       static unsigned int cnt = 0, period = 0;
+       volatile unsigned short *p = (volatile unsigned short *)PA_OBLED;
+       static unsigned bit = 0, up = 1;
+       unsigned bit_pos[] = {2, 1, 0, 3, 6, 5, 4, 7};
+
+       cnt += 1;
+       if (cnt < period)
+               return;
+
+       cnt = 0;
+
+       /* Go through the points (roughly!):
+        * f(0)=10, f(1)=16, f(2)=20, f(5)=35, f(int)->110
+        */
+       period = 110 - ((300 << FSHIFT)/((avenrun[0]/5) + (3<<FSHIFT)));
+
+       *p = 1 << bit_pos[bit];
+       if (up)
+               if (bit == 7) {
+                       bit--;
+                       up = 0;
+               } else
+                       bit++;
+       else if (bit == 0)
+               up = 1;
+       else
+               bit--;
+}
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
new file mode 100644 (file)
index 0000000..b941aa0
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * arch/sh/boards/renesas/r7780rp/setup.c
+ *
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * 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/init.h>
+#include <linux/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/clock.h>
+#include <asm/io.h>
+
+extern void heartbeat_r7780rp(void);
+extern void init_r7780rp_IRQ(void);
+
+static struct resource m66596_usb_host_resources[] = {
+       [0] = {
+               .start  = 0xa4800000,
+               .end    = 0xa4ffffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 6,            /* irq number */
+               .end    = 6,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device m66596_usb_host_device = {
+       .name           = "m66596-hcd",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /* don't use dma */
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(m66596_usb_host_resources),
+       .resource       = m66596_usb_host_resources,
+};
+
+static struct platform_device *r7780rp_devices[] __initdata = {
+       &m66596_usb_host_device,
+};
+
+static int __init r7780rp_devices_setup(void)
+{
+       return platform_add_devices(r7780rp_devices,
+                                   ARRAY_SIZE(r7780rp_devices));
+}
+
+/*
+ * Platform specific clocks
+ */
+static void ivdr_clk_enable(struct clk *clk)
+{
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << 8), PA_IVDRCTL);
+}
+
+static void ivdr_clk_disable(struct clk *clk)
+{
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) & ~(1 << 8), PA_IVDRCTL);
+}
+
+static struct clk_ops ivdr_clk_ops = {
+       .enable         = ivdr_clk_enable,
+       .disable        = ivdr_clk_disable,
+};
+
+static struct clk ivdr_clk = {
+       .name           = "ivdr_clk",
+       .ops            = &ivdr_clk_ops,
+};
+
+static struct clk *r7780rp_clocks[] = {
+       &ivdr_clk,
+};
+
+static void r7780rp_power_off(void)
+{
+#ifdef CONFIG_SH_R7780MP
+       ctrl_outw(0x0001, PA_POFF);
+#endif
+}
+
+/*
+ * Initialize the board
+ */
+static void __init r7780rp_setup(char **cmdline_p)
+{
+       u16 ver = ctrl_inw(PA_VERREG);
+       int i;
+
+       device_initcall(r7780rp_devices_setup);
+
+       printk(KERN_INFO "Renesas Solutions Highlander R7780RP-1 support.\n");
+
+       printk(KERN_INFO "Board version: %d (revision %d), "
+                        "FPGA version: %d (revision %d)\n",
+                        (ver >> 12) & 0xf, (ver >> 8) & 0xf,
+                        (ver >>  4) & 0xf, ver & 0xf);
+
+       /*
+        * Enable the important clocks right away..
+        */
+       for (i = 0; i < ARRAY_SIZE(r7780rp_clocks); i++) {
+               struct clk *clk = r7780rp_clocks[i];
+
+               clk_register(clk);
+               clk_enable(clk);
+       }
+
+       ctrl_outw(0x0000, PA_OBLED);    /* Clear LED. */
+#ifndef CONFIG_SH_R7780MP
+       ctrl_outw(0x0001, PA_SDPOW);    /* SD Power ON */
+#endif
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x0100, PA_IVDRCTL);   /* Si13112 */
+
+       pm_power_off = r7780rp_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_r7780rp __initmv = {
+       .mv_name                = "Highlander R7780RP-1",
+       .mv_setup               = r7780rp_setup,
+
+       .mv_nr_irqs             = 109,
+
+       .mv_inb                 = r7780rp_inb,
+       .mv_inw                 = r7780rp_inw,
+       .mv_inl                 = r7780rp_inl,
+       .mv_outb                = r7780rp_outb,
+       .mv_outw                = r7780rp_outw,
+       .mv_outl                = r7780rp_outl,
+
+       .mv_inb_p               = r7780rp_inb_p,
+       .mv_inw_p               = r7780rp_inw,
+       .mv_inl_p               = r7780rp_inl,
+       .mv_outb_p              = r7780rp_outb_p,
+       .mv_outw_p              = r7780rp_outw,
+       .mv_outl_p              = r7780rp_outl,
+
+       .mv_insb                = r7780rp_insb,
+       .mv_insw                = r7780rp_insw,
+       .mv_insl                = r7780rp_insl,
+       .mv_outsb               = r7780rp_outsb,
+       .mv_outsw               = r7780rp_outsw,
+       .mv_outsl               = r7780rp_outsl,
+
+       .mv_ioport_map          = r7780rp_ioport_map,
+       .mv_init_irq            = init_r7780rp_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_r7780rp,
+#endif
+};
+ALIAS_MV(r7780rp)
diff --git a/arch/sh/boards/renesas/rts7751r2d/Kconfig b/arch/sh/boards/renesas/rts7751r2d/Kconfig
new file mode 100644 (file)
index 0000000..7780d1f
--- /dev/null
@@ -0,0 +1,12 @@
+if SH_RTS7751R2D
+
+menu "RTS7751R2D options"
+
+config RTS7751R2D_REV11
+       bool "RTS7751R2D Rev. 1.1 board support"
+       help
+         Selecting this option will support version rev. 1.1.
+endmenu
+
+endif
+
index daa53334bdc31e23cc6506a9e863180fb0ab0cad..686fc9ea5989c01e1968c739eb8d1bd091c5bb5f 100644 (file)
@@ -1,10 +1,6 @@
 #
 # Makefile for the RTS7751R2D specific parts of the kernel
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-obj-y   := mach.o setup.o io.o irq.o led.o
 
+obj-y   := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
index 123abbbc91e0c0b4dcec41827ed9a7c92814508f..135aa0b5e62dcc926d7df4f3c4996c70c1433c96 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/sh/kernel/io_rts7751r2d.c
- *
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  *
  * placeholder code from io_rts7751r2d.c left in with the
  * expectation of later SuperIO and PCMCIA access.
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <asm/io.h>
+#include <linux/pci.h>
 #include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
 #include <asm/addrspace.h>
 
-#include <linux/module.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
 /*
  * The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
  * of the 7751R processor, and has a SuperIO accessible via the PCI.
  * like the other Solution Engine boards.
  */
 
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 static inline unsigned long port2adr(unsigned int port)
 {
        if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
@@ -52,7 +30,7 @@ static inline unsigned long port2adr(unsigned int port)
                else
                        return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
        else
-               maybebadio(port2adr, (unsigned long)port);
+               maybebadio((unsigned long)port);
 
        return port;
 }
@@ -81,17 +59,6 @@ static inline int shifted_port(unsigned long port)
                return 1;
 }
 
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
 #if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
 #define CHECK_AX88796L_PORT(port) \
   ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
@@ -112,8 +79,8 @@ unsigned char rts7751r2d_inb(unsigned long port)
                return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
        else if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else
                return (*(volatile unsigned short *)port2adr(port) & 0xff);
 }
@@ -126,11 +93,12 @@ unsigned char rts7751r2d_inb_p(unsigned long port)
                v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
         else if (PXSEG(port))
                v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               v = *(volatile unsigned char *)pci_ioaddr(port);
        else
                v = (*(volatile unsigned short *)port2adr(port) & 0xff);
-       delay();
+
+       ctrl_delay();
 
        return v;
 }
@@ -138,13 +106,13 @@ unsigned char rts7751r2d_inb_p(unsigned long port)
 unsigned short rts7751r2d_inw(unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(inw, port);
+               maybebadio(port);
         else if (PXSEG(port))
                return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return *(volatile unsigned short *)pci_ioaddr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
 
        return 0;
 }
@@ -152,13 +120,13 @@ unsigned short rts7751r2d_inw(unsigned long port)
 unsigned int rts7751r2d_inl(unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(inl, port);
+               maybebadio(port);
         else if (PXSEG(port))
                return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned long *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return *(volatile unsigned long *)pci_ioaddr(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
 
        return 0;
 }
@@ -169,8 +137,8 @@ void rts7751r2d_outb(unsigned char value, unsigned long port)
                *((volatile unsigned short *)port88796l(port, 0)) = value;
         else if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned char *)PCI_IOMAP(port) = value;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               *(volatile unsigned char *)pci_ioaddr(port) = value;
        else
                *(volatile unsigned short *)port2adr(port) = value;
 }
@@ -181,143 +149,152 @@ void rts7751r2d_outb_p(unsigned char value, unsigned long port)
                *((volatile unsigned short *)port88796l(port, 0)) = value;
         else if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned char *)PCI_IOMAP(port) = value;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               *(volatile unsigned char *)pci_ioaddr(port) = value;
        else
                *(volatile unsigned short *)port2adr(port) = value;
-       delay();
+
+       ctrl_delay();
 }
 
 void rts7751r2d_outw(unsigned short value, unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(outw, port);
+               maybebadio(port);
         else if (PXSEG(port))
                *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned short *)PCI_IOMAP(port) = value;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               *(volatile unsigned short *)pci_ioaddr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void rts7751r2d_outl(unsigned int value, unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(outl, port);
+               maybebadio(port);
         else if (PXSEG(port))
                *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned long *)PCI_IOMAP(port) = value;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               *(volatile unsigned long *)pci_ioaddr(port) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void rts7751r2d_insb(unsigned long port, void *addr, unsigned long count)
 {
+       unsigned long a = (unsigned long)addr;
        volatile __u8 *bp;
        volatile __u16 *p;
-       unsigned char *s = addr;
 
        if (CHECK_AX88796L_PORT(port)) {
                p = (volatile unsigned short *)port88796l(port, 0);
-               while (count--) *s++ = *p & 0xff;
+               while (count--)
+                       ctrl_outb(*p & 0xff, a++);
        } else if (PXSEG(port))
-               while (count--) *s++ = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               bp = (__u8 *)PCI_IOMAP(port);
-               while (count--) *s++ = *bp;
+               while (count--)
+                       ctrl_outb(ctrl_inb(port), a++);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               bp = (__u8 *)pci_ioaddr(port);
+               while (count--)
+                       ctrl_outb(*bp, a++);
        } else {
                p = (volatile unsigned short *)port2adr(port);
-               while (count--) *s++ = *p & 0xff;
+               while (count--)
+                       ctrl_outb(*p & 0xff, a++);
        }
 }
 
 void rts7751r2d_insw(unsigned long port, void *addr, unsigned long count)
 {
+       unsigned long a = (unsigned long)addr;
        volatile __u16 *p;
-       __u16 *s = addr;
 
        if (CHECK_AX88796L_PORT(port))
                p = (volatile unsigned short *)port88796l(port, 1);
        else if (PXSEG(port))
                p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile unsigned short *)pci_ioaddr(port);
        else
                p = (volatile unsigned short *)port2adr(port);
-       while (count--) *s++ = *p;
+       while (count--)
+               ctrl_outw(*p, a++);
 }
 
 void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(insl, port);
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
-               __u32 *s = addr;
-
-               while (count--) *s++ = *p;
+               maybebadio(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               unsigned long a = (unsigned long)addr;
+
+               while (count--) {
+                       ctrl_outl(ctrl_inl(pci_ioaddr(port)), a);
+                       a += 4;
+               }
        } else
-               maybebadio(insl, port);
+               maybebadio(port);
 }
 
 void rts7751r2d_outsb(unsigned long port, const void *addr, unsigned long count)
 {
+       unsigned long a = (unsigned long)addr;
        volatile __u8 *bp;
        volatile __u16 *p;
-       const __u8 *s = addr;
 
        if (CHECK_AX88796L_PORT(port)) {
                p = (volatile unsigned short *)port88796l(port, 0);
-               while (count--) *p = *s++;
+               while (count--)
+                       *p = ctrl_inb(a++);
        } else if (PXSEG(port))
-               while (count--) *(volatile unsigned char *)port = *s++;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               bp = (__u8 *)PCI_IOMAP(port);
-               while (count--) *bp = *s++;
+               while (count--)
+                       ctrl_outb(a++, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               bp = (__u8 *)pci_ioaddr(port);
+               while (count--)
+                       *bp = ctrl_inb(a++);
        } else {
                p = (volatile unsigned short *)port2adr(port);
-               while (count--) *p = *s++;
+               while (count--)
+                       *p = ctrl_inb(a++);
        }
 }
 
 void rts7751r2d_outsw(unsigned long port, const void *addr, unsigned long count)
 {
+       unsigned long a = (unsigned long)addr;
        volatile __u16 *p;
-       const __u16 *s = addr;
 
        if (CHECK_AX88796L_PORT(port))
                p = (volatile unsigned short *)port88796l(port, 1);
        else if (PXSEG(port))
                p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile unsigned short *)pci_ioaddr(port);
        else
                p = (volatile unsigned short *)port2adr(port);
-       while (count--) *p = *s++;
+
+       while (count--) {
+               ctrl_outw(*p, a);
+               a += 2;
+       }
 }
 
 void rts7751r2d_outsl(unsigned long port, const void *addr, unsigned long count)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(outsl, port);
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
-               const __u32 *s = addr;
-
-               while (count--) *p = *s++;
+               maybebadio(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               unsigned long a = (unsigned long)addr;
+
+               while (count--) {
+                       ctrl_outl(ctrl_inl(a), pci_ioaddr(port));
+                       a += 4;
+               }
        } else
-               maybebadio(outsl, port);
-}
-
-void *rts7751r2d_ioremap(unsigned long offset, unsigned long size)
-{
-       if (offset >= 0xfd000000)
-               return (void *)offset;
-       else
-               return (void *)P2SEGADDR(offset);
+               maybebadio(port);
 }
-EXPORT_SYMBOL(rts7751r2d_ioremap);
 
 unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
 {
index 154535440bbf7a626c76272e6b9c9ed36545c45b..c915e7a3693a0648b8f52e090cdc4add9b72ac09 100644 (file)
@@ -41,30 +41,24 @@ static unsigned int startup_rts7751r2d_irq(unsigned int irq)
 
 static void disable_rts7751r2d_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
 
        /* Set the priority in IPR to 0 */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR1);
        val &= mask;
        ctrl_outw(val, IRLCNTR1);
-       local_irq_restore(flags);
 }
 
 static void enable_rts7751r2d_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short value = (0x0001 << mask_pos[irq]);
 
        /* Set priority in IPR back to original value */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR1);
        val |= value;
        ctrl_outw(val, IRLCNTR1);
-       local_irq_restore(flags);
 }
 
 int rts7751r2d_irq_demux(int irq)
index 4d16de71fac10df3484af2c33cf330f4448c0fa0..e14a13d12d4ad228351b90ee957304275e30bda7 100644 (file)
@@ -12,8 +12,6 @@
 #include <asm/io.h>
 #include <asm/rts7751r2d/rts7751r2d.h>
 
-extern unsigned int debug_counter;
-
 #ifdef CONFIG_HEARTBEAT
 
 #include <linux/sched.h>
@@ -55,12 +53,3 @@ void rts7751r2d_led(unsigned short value)
        ctrl_outw(value, PA_OUTPORT);
 }
 
-void debug_led_disp(void)
-{
-       unsigned short value;
-
-       value = (unsigned short)debug_counter++;
-       rts7751r2d_led(value);
-       if (value == 0xff)
-               debug_counter = 0;
-}
diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c
deleted file mode 100644 (file)
index 5ed9e97..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_rts7751r2d.c
- *
- * Minor tweak of mach_se.c file to reference rts7751r2d-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Renesas Technology sales RTS7751R2D
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
-#include <asm/rts7751r2d/io.h>
-
-extern void heartbeat_rts7751r2d(void);
-extern void init_rts7751r2d_IRQ(void);
-extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
-extern int rts7751r2d_irq_demux(int irq);
-
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
-extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_rts7751r2d __initmv = {
-       .mv_nr_irqs             = 72,
-
-       .mv_inb                 = rts7751r2d_inb,
-       .mv_inw                 = rts7751r2d_inw,
-       .mv_inl                 = rts7751r2d_inl,
-       .mv_outb                = rts7751r2d_outb,
-       .mv_outw                = rts7751r2d_outw,
-       .mv_outl                = rts7751r2d_outl,
-
-       .mv_inb_p               = rts7751r2d_inb_p,
-       .mv_inw_p               = rts7751r2d_inw,
-       .mv_inl_p               = rts7751r2d_inl,
-       .mv_outb_p              = rts7751r2d_outb_p,
-       .mv_outw_p              = rts7751r2d_outw,
-       .mv_outl_p              = rts7751r2d_outl,
-
-       .mv_insb                = rts7751r2d_insb,
-       .mv_insw                = rts7751r2d_insw,
-       .mv_insl                = rts7751r2d_insl,
-       .mv_outsb               = rts7751r2d_outsb,
-       .mv_outsw               = rts7751r2d_outsw,
-       .mv_outsl               = rts7751r2d_outsl,
-
-       .mv_ioremap             = rts7751r2d_ioremap,
-       .mv_isa_port2addr       = rts7751r2d_isa_port2addr,
-       .mv_init_irq            = init_rts7751r2d_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_rts7751r2d,
-#endif
-       .mv_irq_demux           = rts7751r2d_irq_demux,
-
-#ifdef CONFIG_USB_OHCI_HCD
-       .mv_consistent_alloc    = voyagergx_consistent_alloc,
-       .mv_consistent_free     = voyagergx_consistent_free,
-#endif
-};
-ALIAS_MV(rts7751r2d)
index 2587fd1a0240ea61deca57837f90dfb16e1230f4..20597a6e6702c40e76f5cab65a2b396f668b3c08 100644 (file)
 /*
- * linux/arch/sh/kernel/setup_rts7751r2d.c
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
  * Renesas Technology Sales RTS7751R2D Support.
  *
- * Modified for RTS7751R2D by
- * Atom Create Engineering Co., Ltd. 2002.
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2004 - 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/pm.h>
 #include <asm/io.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/machvec.h>
+#include <asm/mach/rts7751r2d.h>
+#include <asm/voyagergx.h>
+
+extern void heartbeat_rts7751r2d(void);
+extern void init_rts7751r2d_IRQ(void);
+extern int rts7751r2d_irq_demux(int irq);
+
+extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
+extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
+
+static struct plat_serial8250_port uart_platform_data[] = {
+       {
+               .membase        = (void *)VOYAGER_UART_BASE,
+               .mapbase        = VOYAGER_UART_BASE,
+               .iotype         = UPIO_MEM,
+               .irq            = VOYAGER_UART0_IRQ,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .regshift       = 2,
+               .uartclk        = (9600 * 16),
+       }, {
+               .flags          = 0,
+       },
+};
+
+static void __init voyagergx_serial_init(void)
+{
+       unsigned long val;
+
+       /*
+        * GPIO Control
+        */
+       val = inl(GPIO_MUX_HIGH);
+       val |= 0x00001fe0;
+       outl(val, GPIO_MUX_HIGH);
+
+       /*
+        * Power Mode Gate
+        */
+       val = inl(POWER_MODE0_GATE);
+       val |= (POWER_MODE0_GATE_U0 | POWER_MODE0_GATE_U1);
+       outl(val, POWER_MODE0_GATE);
+
+       val = inl(POWER_MODE1_GATE);
+       val |= (POWER_MODE1_GATE_U0 | POWER_MODE1_GATE_U1);
+       outl(val, POWER_MODE1_GATE);
+}
+
+static struct platform_device uart_device = {
+       .name           = "serial8250",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = uart_platform_data,
+       },
+};
+
+static struct platform_device *rts7751r2d_devices[] __initdata = {
+       &uart_device,
+};
 
-unsigned int debug_counter;
+static int __init rts7751r2d_devices_setup(void)
+{
+       return platform_add_devices(rts7751r2d_devices,
+                                   ARRAY_SIZE(rts7751r2d_devices));
+}
 
-const char *get_system_type(void)
+static void rts7751r2d_power_off(void)
 {
-       return "RTS7751R2D";
+       ctrl_outw(0x0001, PA_POWOFF);
 }
 
 /*
  * Initialize the board
  */
-void __init platform_setup(void)
+static void __init rts7751r2d_setup(char **cmdline_p)
 {
-       printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
+       device_initcall(rts7751r2d_devices_setup);
+
        ctrl_outw(0x0000, PA_OUTPORT);
-       debug_counter = 0;
+       pm_power_off = rts7751r2d_power_off;
+
+       voyagergx_serial_init();
+
+       printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
 }
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_rts7751r2d __initmv = {
+       .mv_name                = "RTS7751R2D",
+       .mv_setup               = rts7751r2d_setup,
+       .mv_nr_irqs             = 72,
+
+       .mv_inb                 = rts7751r2d_inb,
+       .mv_inw                 = rts7751r2d_inw,
+       .mv_inl                 = rts7751r2d_inl,
+       .mv_outb                = rts7751r2d_outb,
+       .mv_outw                = rts7751r2d_outw,
+       .mv_outl                = rts7751r2d_outl,
+
+       .mv_inb_p               = rts7751r2d_inb_p,
+       .mv_inw_p               = rts7751r2d_inw,
+       .mv_inl_p               = rts7751r2d_inl,
+       .mv_outb_p              = rts7751r2d_outb_p,
+       .mv_outw_p              = rts7751r2d_outw,
+       .mv_outl_p              = rts7751r2d_outl,
+
+       .mv_insb                = rts7751r2d_insb,
+       .mv_insw                = rts7751r2d_insw,
+       .mv_insl                = rts7751r2d_insl,
+       .mv_outsb               = rts7751r2d_outsb,
+       .mv_outsw               = rts7751r2d_outsw,
+       .mv_outsl               = rts7751r2d_outsl,
+
+       .mv_init_irq            = init_rts7751r2d_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_rts7751r2d,
+#endif
+       .mv_irq_demux           = rts7751r2d_irq_demux,
+
+#ifdef CONFIG_USB_SM501
+       .mv_consistent_alloc    = voyagergx_consistent_alloc,
+       .mv_consistent_free     = voyagergx_consistent_free,
+#endif
+};
+ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/sh7710voipgw/Makefile b/arch/sh/boards/renesas/sh7710voipgw/Makefile
new file mode 100644 (file)
index 0000000..7703756
--- /dev/null
@@ -0,0 +1 @@
+obj-y   := setup.o
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
new file mode 100644 (file)
index 0000000..e57e7af
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Renesas Technology SH7710 VoIP Gateway
+ *
+ * Copyright (C) 2006  Ranjit Deshpande
+ * Kenati Technologies Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/*
+ * Initialize IRQ setting
+ */
+static void __init sh7710voipgw_init_irq(void)
+{
+       /* Disable all interrupts in IPR registers */
+       ctrl_outw(0x0, INTC_IPRA);
+       ctrl_outw(0x0, INTC_IPRB);
+       ctrl_outw(0x0, INTC_IPRC);
+       ctrl_outw(0x0, INTC_IPRD);
+       ctrl_outw(0x0, INTC_IPRE);
+       ctrl_outw(0x0, INTC_IPRF);
+       ctrl_outw(0x0, INTC_IPRG);
+       ctrl_outw(0x0, INTC_IPRH);
+       ctrl_outw(0x0, INTC_IPRI);
+
+       /* Ack all interrupt sources in the IRR0 register */
+       ctrl_outb(0x3f, INTC_IRR0);
+
+       /* Use IRQ0 - IRQ3 as active low interrupt lines i.e. disable
+        * IRL mode.
+        */
+       ctrl_outw(0x2aa, INTC_ICR1);
+
+       /* Now make IPR interrupts */
+       make_ipr_irq(TIMER2_IRQ, TIMER2_IPR_ADDR,
+                       TIMER2_IPR_POS, TIMER2_PRIORITY);
+       make_ipr_irq(WDT_IRQ, WDT_IPR_ADDR, WDT_IPR_POS, WDT_PRIORITY);
+
+       /* SCIF0 */
+       make_ipr_irq(SCIF0_ERI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+       make_ipr_irq(SCIF0_RXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+       make_ipr_irq(SCIF0_BRI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+       make_ipr_irq(SCIF0_TXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+
+       /* DMAC-1 */
+       make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE2_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE3_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+
+       /* DMAC-2 */
+       make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+       make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+
+       /* IPSEC */
+       make_ipr_irq(IPSEC_IRQ, IPSEC_IPR_ADDR, IPSEC_IPR_POS, IPSEC_PRIORITY);
+
+       /* EDMAC */
+       make_ipr_irq(EDMAC0_IRQ, EDMAC0_IPR_ADDR, EDMAC0_IPR_POS,
+                       EDMAC0_PRIORITY);
+       make_ipr_irq(EDMAC1_IRQ, EDMAC1_IPR_ADDR, EDMAC1_IPR_POS,
+                       EDMAC1_PRIORITY);
+       make_ipr_irq(EDMAC2_IRQ, EDMAC2_IPR_ADDR, EDMAC2_IPR_POS,
+                       EDMAC2_PRIORITY);
+
+       /* SIOF0 */
+       make_ipr_irq(SIOF0_ERI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+       make_ipr_irq(SIOF0_TXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+       make_ipr_irq(SIOF0_RXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+       make_ipr_irq(SIOF0_CCI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+
+       /* SIOF1 */
+       make_ipr_irq(SIOF1_ERI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+       make_ipr_irq(SIOF1_TXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+       make_ipr_irq(SIOF1_RXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+       make_ipr_irq(SIOF1_CCI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+
+       /* SLIC IRQ's */
+       make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+       make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_sh7710voipgw __initmv = {
+       .mv_name                = "SH7710 VoIP Gateway",
+       .mv_nr_irqs             = 104,
+       .mv_init_irq            = sh7710voipgw_init_irq,
+};
+ALIAS_MV(sh7710voipgw)
index cf979011aa943de88bda3d9d01daf0628706e4a0..cde6e5d192c417475286380ac46dcb32c7f39ca3 100644 (file)
@@ -5,66 +5,25 @@
  * Based largely on io_se.c.
  *
  * I/O routine for Hitachi 7751 Systemh.
- *
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <asm/systemh/7751systemh.h>
+#include <linux/pci.h>
+#include <asm/systemh7751.h>
 #include <asm/addrspace.h>
 #include <asm/io.h>
 
-#include <linux/pci.h>
-#include "../../drivers/pci/pci-sh7751.h"
-
-/*
- * The 7751 SystemH Engine uses the built-in PCI controller (PCIC)
- * of the 7751 processor, and has a SuperIO accessible on its memory
- * bus.
- */
-
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
 #define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
                                                 of smc lan chip*/
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 static inline volatile __u16 *
 port2adr(unsigned int port)
 {
        if (port >= 0x2000)
                return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#if 0
-       else
-               return (volatile __u16 *) (PA_SUPERIO + (port << 1));
-#endif
-       maybebadio(name,(unsigned long)port);
+       maybebadio((unsigned long)port);
        return (volatile __u16*)port;
 }
 
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
 /*
  * General outline: remap really low stuff [eventually] to SuperIO,
  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
@@ -76,8 +35,8 @@ unsigned char sh7751systemh_inb(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else if (port <= 0x3F1)
                return *(volatile unsigned char *)ETHER_IOMAP(port);
        else
@@ -90,13 +49,13 @@ unsigned char sh7751systemh_inb_p(unsigned long port)
 
         if (PXSEG(port))
                 v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                v = *(volatile unsigned char *)pci_ioaddr(port);
        else if (port <= 0x3F1)
                v = *(volatile unsigned char *)ETHER_IOMAP(port);
        else
                v = (*port2adr(port))&0xff;
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -104,14 +63,14 @@ unsigned short sh7751systemh_inw(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned short *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else if (port <= 0x3F1)
                return *(volatile unsigned int *)ETHER_IOMAP(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -119,14 +78,14 @@ unsigned int sh7751systemh_inl(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned int *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned int *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else if (port <= 0x3F1)
                return *(volatile unsigned int *)ETHER_IOMAP(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -135,8 +94,8 @@ void sh7751systemh_outb(unsigned char value, unsigned long port)
 
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else if (port <= 0x3F1)
                *(volatile unsigned char *)ETHER_IOMAP(port) = value;
        else
@@ -147,37 +106,37 @@ void sh7751systemh_outb_p(unsigned char value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else if (port <= 0x3F1)
                *(volatile unsigned char *)ETHER_IOMAP(port) = value;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
 void sh7751systemh_outw(unsigned short value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned short *)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned short *)pci_ioaddr(port)) = value;
        else if (port >= 0x2000)
                *port2adr(port) = value;
        else if (port <= 0x3F1)
                *(volatile unsigned short *)ETHER_IOMAP(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void sh7751systemh_outl(unsigned int value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned long*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned long*)pci_ioaddr(port)) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
@@ -194,7 +153,7 @@ void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
 
 void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
@@ -211,73 +170,5 @@ void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long cou
 
 void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* For read/write calls, just copy generic (pass-thru); PCIMBR is  */
-/* already set up.  For a larger memory space, these would need to */
-/* reset PCIMBR as needed on a per-call basis...                   */
-
-unsigned char sh7751systemh_readb(unsigned long addr)
-{
-       return *(volatile unsigned char*)addr;
-}
-
-unsigned short sh7751systemh_readw(unsigned long addr)
-{
-       return *(volatile unsigned short*)addr;
-}
-
-unsigned int sh7751systemh_readl(unsigned long addr)
-{
-       return *(volatile unsigned long*)addr;
-}
-
-void sh7751systemh_writeb(unsigned char b, unsigned long addr)
-{
-       *(volatile unsigned char*)addr = b;
-}
-
-void sh7751systemh_writew(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned short*)addr = b;
-}
-
-void sh7751systemh_writel(unsigned int b, unsigned long addr)
-{
-        *(volatile unsigned long*)addr = b;
-}
-
-\f
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-#if 0
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-       return 0;
-}
-#endif
-
-unsigned long
-sh7751systemh_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index 8372d967f60120f249e71c0135578ca36459da04..8d016dae23334731a15564e2a64fad25a7665091 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <asm/io.h>
-#include <asm/mach/7751systemh.h>
+#include <asm/systemh7751.h>
 #include <asm/smc37c93x.h>
 
 /* address of external interrupt mask register
@@ -57,12 +57,9 @@ static void shutdown_systemh_irq(unsigned int irq)
 static void disable_systemh_irq(unsigned int irq)
 {
        if (systemh_irq_mask_register) {
-               unsigned long flags;
                unsigned long val, mask = 0x01 << 1;
 
                /* Clear the "irq"th bit in the mask and set it in the request */
-               local_irq_save(flags);
-
                val = ctrl_inl((unsigned long)systemh_irq_mask_register);
                val &= ~mask;
                ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
@@ -70,23 +67,18 @@ static void disable_systemh_irq(unsigned int irq)
                val = ctrl_inl((unsigned long)systemh_irq_request_register);
                val |= mask;
                ctrl_outl(val, (unsigned long)systemh_irq_request_register);
-
-               local_irq_restore(flags);
        }
 }
 
 static void enable_systemh_irq(unsigned int irq)
 {
        if (systemh_irq_mask_register) {
-               unsigned long flags;
                unsigned long val, mask = 0x01 << 1;
 
                /* Set "irq"th bit in the mask register */
-               local_irq_save(flags);
                val = ctrl_inl((unsigned long)systemh_irq_mask_register);
                val |= mask;
                ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
-               local_irq_restore(flags);
        }
 }
 
index 826fa3d7669c7952fee3655d8b7c126077a297b6..a8467bf90c2515d00df03feb1926931e9e7321f3 100644 (file)
  * for more details.
  */
 #include <linux/init.h>
-#include <asm/mach/7751systemh.h>
-#include <asm/mach/io.h>
 #include <asm/machvec.h>
+#include <asm/systemh7751.h>
 
 extern void make_systemh_irq(unsigned int irq);
 
-const char *get_system_type(void)
-{
-       return "7751 SystemH";
-}
-
 /*
  * Initialize IRQ setting
  */
-void __init init_7751systemh_IRQ(void)
+static void __init sh7751systemh_init_irq(void)
 {
-/*     make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); LAN */
-/*     make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-4); */
        make_systemh_irq(0xb);  /* Ethernet interrupt */
 }
 
 struct sh_machine_vector mv_7751systemh __initmv = {
+       .mv_name                = "7751 SystemH",
        .mv_nr_irqs             = 72,
 
        .mv_inb                 = sh7751systemh_inb,
@@ -60,21 +53,6 @@ struct sh_machine_vector mv_7751systemh __initmv = {
        .mv_outsw               = sh7751systemh_outsw,
        .mv_outsl               = sh7751systemh_outsl,
 
-       .mv_readb               = sh7751systemh_readb,
-       .mv_readw               = sh7751systemh_readw,
-       .mv_readl               = sh7751systemh_readl,
-       .mv_writeb              = sh7751systemh_writeb,
-       .mv_writew              = sh7751systemh_writew,
-       .mv_writel              = sh7751systemh_writel,
-
-       .mv_isa_port2addr       = sh7751systemh_isa_port2addr,
-
-       .mv_init_irq            = init_7751systemh_IRQ,
+       .mv_init_irq            = sh7751system_init_irq,
 };
 ALIAS_MV(7751systemh)
-
-int __init platform_setup(void)
-{
-       return 0;
-}
-
index bea6c572ad82a805a28fd6ae51e185d6d3e0e421..a3a37c9aad2eea672bd36a9d9665b7ffdb0521f2 100644 (file)
@@ -9,22 +9,17 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-
 #include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mach/io.h>
 
 extern int saturn_irq_demux(int irq_nr);
 
-const char *get_system_type(void)
-{
-       return "Sega Saturn";
-}
-
 /*
  * The Machine Vector
  */
 struct sh_machine_vector mv_saturn __initmv = {
+       .mv_name                = "Sega Saturn",
        .mv_nr_irqs             = 80,   /* Fix this later */
 
        .mv_isa_port2addr       = saturn_isa_port2addr,
@@ -33,11 +28,4 @@ struct sh_machine_vector mv_saturn __initmv = {
        .mv_ioremap             = saturn_ioremap,
        .mv_iounmap             = saturn_iounmap,
 };
-
 ALIAS_MV(saturn)
-
-int __init platform_setup(void)
-{
-       return 0;
-}
-
index f449a94ddffde4822cc037ba5677c78627b106d0..8a03d7a52a7ca441ecf24bcc2d6f57e15bcd0be1 100644 (file)
@@ -9,8 +9,8 @@
  */
 
 #include <linux/kernel.h>
-#include <asm/mach/se7300.h>
 #include <asm/io.h>
+#include <asm/se7300.h>
 
 #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
 
@@ -99,6 +99,7 @@ bad_outb(struct iop *p, unsigned char value, unsigned long port)
        badio(inw, port);
 }
 
+#ifdef CONFIG_SMC91X
 /* MSTLANEX01 LAN at 0xb400:0000 */
 static struct iop laniop = {
        .start = 0x300,
@@ -110,6 +111,7 @@ static struct iop laniop = {
        .outb = simple_outb,
        .outw = simple_outw,
 };
+#endif
 
 /* NE2000 pc card NIC */
 static struct iop neiop = {
@@ -123,6 +125,7 @@ static struct iop neiop = {
        .outw = simple_outw,
 };
 
+#ifdef CONFIG_IDE
 /* CF in CF slot */
 static struct iop cfiop = {
        .base = 0xb0600000,
@@ -132,12 +135,13 @@ static struct iop cfiop = {
        .outb = pcc_outb,
        .outw = simple_outw,
 };
+#endif
 
 static __inline__ struct iop *
 port2iop(unsigned long port)
 {
        if (0) ;
-#if defined(CONFIG_SMC91111)
+#if defined(CONFIG_SMC91X)
        else if (laniop.check(&laniop, port))
                return &laniop;
 #endif
index 216a78d1a108c26c3ff4ab1cc0b74e7cfd958a00..ad1034f98a293ba4dfeb0259369538458e299f83 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/mach/se7300.h>
+#include <asm/se7300.h>
 
 /*
  * Initialize IRQ setting
index ad51f0a9c1e31999041ac59b5e408679bee4dcba..4d03bb7774be781dcf5c3a599a603b3134389970 100644 (file)
  */
 
 #include <linux/sched.h>
-#include <asm/mach/se7300.h>
-
-static void
-mach_led(int position, int value)
-{
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-
-       if (value) {
-               *p |= (1 << 8);
-       } else {
-               *p &= ~(1 << 8);
-       }
-}
-
+#include <asm/se7300.h>
 
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void
-heartbeat_7300se(void)
+void heartbeat_7300se(void)
 {
        static unsigned int cnt = 0, period = 0;
        volatile unsigned short *p = (volatile unsigned short *) PA_LED;
index ebcd98d4c0818601535bfb52e051004d7579a9e7..6f082a722d42842f5502ff9b0a7497f3f35fd659 100644 (file)
@@ -9,23 +9,16 @@
 
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/mach/io.h>
+#include <asm/se7300.h>
 
 void heartbeat_7300se(void);
 void init_7300se_IRQ(void);
 
-const char *
-get_system_type(void)
-{
-       return "SolutionEngine 7300";
-}
-
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_7300se __initmv = {
+       .mv_name = "SolutionEngine 7300",
        .mv_nr_irqs = 109,
        .mv_inb = sh7300se_inb,
        .mv_inw = sh7300se_inw,
@@ -53,13 +46,4 @@ struct sh_machine_vector mv_7300se __initmv = {
        .mv_heartbeat = heartbeat_7300se,
 #endif
 };
-
 ALIAS_MV(7300se)
-/*
- * Initialize the board
- */
-void __init
-platform_setup(void)
-{
-
-}
index 755df5ac4a4e81c1d6c12341a60b79ec51a58ead..72715575458b81b2f217738d2fb6dd0df0bb8566 100644 (file)
@@ -99,6 +99,7 @@ bad_outb(struct iop *p, unsigned char value, unsigned long port)
        badio(inw, port);
 }
 
+#ifdef CONFIG_SMC91X
 /* MSTLANEX01 LAN at 0xb400:0000 */
 static struct iop laniop = {
        .start = 0x300,
@@ -110,6 +111,7 @@ static struct iop laniop = {
        .outb = simple_outb,
        .outw = simple_outw,
 };
+#endif
 
 /* NE2000 pc card NIC */
 static struct iop neiop = {
@@ -123,6 +125,7 @@ static struct iop neiop = {
        .outw = simple_outw,
 };
 
+#ifdef CONFIG_IDE
 /* CF in CF slot */
 static struct iop cfiop = {
        .base = 0xb0600000,
@@ -132,12 +135,13 @@ static struct iop cfiop = {
        .outb = pcc_outb,
        .outw = simple_outw,
 };
+#endif
 
 static __inline__ struct iop *
 port2iop(unsigned long port)
 {
        if (0) ;
-#if defined(CONFIG_SMC91111)
+#if defined(CONFIG_SMC91X)
        else if (laniop.check(&laniop, port))
                return &laniop;
 #endif
index 4344d0ef24aa05ea8845632e8996bb3d15f570c7..2c62b8ea350ee8e3d214ed9de51b31d920035f7a 100644 (file)
@@ -7,7 +7,6 @@
  * Modified for SH-Mobile SolutionEngine 73180 Support
  *              by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
  *
- *
  */
 
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/mach/se73180.h>
 
-static int
-intreq2irq(int i)
-{
-       if (i == 5)
-               return 10;
-       return 32 + 7 - i;
-}
-
 static int
 irq2intreq(int irq)
 {
index 610439fde6ee5f3fc6ef7ece6e3be5455a41301f..4b72e9a3ead9ba7a1fa41739c72d6bd66fa275ae 100644 (file)
 #include <linux/sched.h>
 #include <asm/mach/se73180.h>
 
-static void
-mach_led(int position, int value)
-{
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-
-       if (value) {
-               *p |= (1 << LED_SHIFT);
-       } else {
-               *p &= ~(1 << LED_SHIFT);
-       }
-}
-
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void
-heartbeat_73180se(void)
+void heartbeat_73180se(void)
 {
        static unsigned int cnt = 0, period = 0;
        volatile unsigned short *p = (volatile unsigned short *) PA_LED;
index cdb7b5f8d942f7cf1520aa16c7661d95b6a4b142..b38ef50a160a2114b4c7a290d420797de3871e12 100644 (file)
 
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/mach/io.h>
+#include <asm/se73180.h>
+#include <asm/irq.h>
 
 void heartbeat_73180se(void);
 void init_73180se_IRQ(void);
 
-const char *
-get_system_type(void)
-{
-       return "SolutionEngine 73180";
-}
-
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_73180se __initmv = {
+       .mv_name = "SolutionEngine 73180",
        .mv_nr_irqs = 108,
        .mv_inb = sh73180se_inb,
        .mv_inw = sh73180se_inw,
@@ -51,17 +45,9 @@ struct sh_machine_vector mv_73180se __initmv = {
        .mv_outsl = sh73180se_outsl,
 
        .mv_init_irq = init_73180se_IRQ,
+       .mv_irq_demux = shmse_irq_demux,
 #ifdef CONFIG_HEARTBEAT
        .mv_heartbeat = heartbeat_73180se,
 #endif
 };
-
 ALIAS_MV(73180se)
-/*
- * Initialize the board
- */
-void __init
-platform_setup(void)
-{
-
-}
diff --git a/arch/sh/boards/se/7343/Makefile b/arch/sh/boards/se/7343/Makefile
new file mode 100644 (file)
index 0000000..4291069
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the 7343 SolutionEngine specific parts of the kernel
+#
+
+obj-y   := setup.o io.o irq.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7343/io.c b/arch/sh/boards/se/7343/io.c
new file mode 100644 (file)
index 0000000..646661a
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * arch/sh/boards/se/7343/io.c
+ *
+ * I/O routine for SH-Mobile3AS 7343 SolutionEngine.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/mach/se7343.h>
+
+#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
+
+struct iop {
+       unsigned long start, end;
+       unsigned long base;
+       struct iop *(*check) (struct iop * p, unsigned long port);
+       unsigned char (*inb) (struct iop * p, unsigned long port);
+       unsigned short (*inw) (struct iop * p, unsigned long port);
+       void (*outb) (struct iop * p, unsigned char value, unsigned long port);
+       void (*outw) (struct iop * p, unsigned short value, unsigned long port);
+};
+
+struct iop *
+simple_check(struct iop *p, unsigned long port)
+{
+       static int count;
+
+       if (count < 100)
+               count++;
+
+       port &= 0xFFFF;
+
+       if ((p->start <= port) && (port <= p->end))
+               return p;
+       else
+               badio(check, port);
+}
+
+struct iop *
+ide_check(struct iop *p, unsigned long port)
+{
+       if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
+               return p;
+       return NULL;
+}
+
+unsigned char
+simple_inb(struct iop *p, unsigned long port)
+{
+       return *(unsigned char *) (p->base + port);
+}
+
+unsigned short
+simple_inw(struct iop *p, unsigned long port)
+{
+       return *(unsigned short *) (p->base + port);
+}
+
+void
+simple_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+       *(unsigned char *) (p->base + port) = value;
+}
+
+void
+simple_outw(struct iop *p, unsigned short value, unsigned long port)
+{
+       *(unsigned short *) (p->base + port) = value;
+}
+
+unsigned char
+pcc_inb(struct iop *p, unsigned long port)
+{
+       unsigned long addr = p->base + port + 0x40000;
+       unsigned long v;
+
+       if (port & 1)
+               addr += 0x00400000;
+       v = *(volatile unsigned char *) addr;
+       return v;
+}
+
+void
+pcc_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+       unsigned long addr = p->base + port + 0x40000;
+
+       if (port & 1)
+               addr += 0x00400000;
+       *(volatile unsigned char *) addr = value;
+}
+
+unsigned char
+bad_inb(struct iop *p, unsigned long port)
+{
+       badio(inb, port);
+}
+
+void
+bad_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+       badio(inw, port);
+}
+
+#ifdef CONFIG_SMC91X
+/* MSTLANEX01 LAN at 0xb400:0000 */
+static struct iop laniop = {
+       .start = 0x00,
+       .end = 0x0F,
+       .base = 0x04000000,
+       .check = simple_check,
+       .inb = simple_inb,
+       .inw = simple_inw,
+       .outb = simple_outb,
+       .outw = simple_outw,
+};
+#endif
+
+#ifdef CONFIG_NE2000
+/* NE2000 pc card NIC */
+static struct iop neiop = {
+       .start = 0x280,
+       .end = 0x29f,
+       .base = 0xb0600000 + 0x80,      /* soft 0x280 -> hard 0x300 */
+       .check = simple_check,
+       .inb = pcc_inb,
+       .inw = simple_inw,
+       .outb = pcc_outb,
+       .outw = simple_outw,
+};
+#endif
+
+#ifdef CONFIG_IDE
+/* CF in CF slot */
+static struct iop cfiop = {
+       .base = 0xb0600000,
+       .check = ide_check,
+       .inb = pcc_inb,
+       .inw = simple_inw,
+       .outb = pcc_outb,
+       .outw = simple_outw,
+};
+#endif
+
+static __inline__ struct iop *
+port2iop(unsigned long port)
+{
+       if (0) ;
+#if defined(CONFIG_SMC91X)
+       else if (laniop.check(&laniop, port))
+               return &laniop;
+#endif
+#if defined(CONFIG_NE2000)
+       else if (neiop.check(&neiop, port))
+               return &neiop;
+#endif
+#if defined(CONFIG_IDE)
+       else if (cfiop.check(&cfiop, port))
+               return &cfiop;
+#endif
+       else
+               return NULL;
+}
+
+static inline void
+delay(void)
+{
+       ctrl_inw(0xac000000);
+       ctrl_inw(0xac000000);
+}
+
+unsigned char
+sh7343se_inb(unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       return (p->inb) (p, port);
+}
+
+unsigned char
+sh7343se_inb_p(unsigned long port)
+{
+       unsigned char v = sh7343se_inb(port);
+       delay();
+       return v;
+}
+
+unsigned short
+sh7343se_inw(unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       return (p->inw) (p, port);
+}
+
+unsigned int
+sh7343se_inl(unsigned long port)
+{
+       badio(inl, port);
+}
+
+void
+sh7343se_outb(unsigned char value, unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       (p->outb) (p, value, port);
+}
+
+void
+sh7343se_outb_p(unsigned char value, unsigned long port)
+{
+       sh7343se_outb(value, port);
+       delay();
+}
+
+void
+sh7343se_outw(unsigned short value, unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       (p->outw) (p, value, port);
+}
+
+void
+sh7343se_outl(unsigned int value, unsigned long port)
+{
+       badio(outl, port);
+}
+
+void
+sh7343se_insb(unsigned long port, void *addr, unsigned long count)
+{
+       unsigned char *a = addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               *a++ = (p->inb) (p, port);
+}
+
+void
+sh7343se_insw(unsigned long port, void *addr, unsigned long count)
+{
+       unsigned short *a = addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               *a++ = (p->inw) (p, port);
+}
+
+void
+sh7343se_insl(unsigned long port, void *addr, unsigned long count)
+{
+       badio(insl, port);
+}
+
+void
+sh7343se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+       unsigned char *a = (unsigned char *) addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               (p->outb) (p, *a++, port);
+}
+
+void
+sh7343se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+       unsigned short *a = (unsigned short *) addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               (p->outw) (p, *a++, port);
+}
+
+void
+sh7343se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+       badio(outsw, port);
+}
diff --git a/arch/sh/boards/se/7343/irq.c b/arch/sh/boards/se/7343/irq.c
new file mode 100644 (file)
index 0000000..b41e3d4
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * arch/sh/boards/se/7343/irq.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/se7343.h>
+
+static void
+disable_intreq_irq(unsigned int irq)
+{
+       int bit = irq - OFFCHIP_IRQ_BASE;
+       u16 val;
+
+       val = ctrl_inw(PA_CPLD_IMSK);
+       val |= 1 << bit;
+       ctrl_outw(val, PA_CPLD_IMSK);
+}
+
+static void
+enable_intreq_irq(unsigned int irq)
+{
+       int bit = irq - OFFCHIP_IRQ_BASE;
+       u16 val;
+
+       val = ctrl_inw(PA_CPLD_IMSK);
+       val &= ~(1 << bit);
+       ctrl_outw(val, PA_CPLD_IMSK);
+}
+
+static void
+mask_and_ack_intreq_irq(unsigned int irq)
+{
+       disable_intreq_irq(irq);
+}
+
+static unsigned int
+startup_intreq_irq(unsigned int irq)
+{
+       enable_intreq_irq(irq);
+       return 0;
+}
+
+static void
+shutdown_intreq_irq(unsigned int irq)
+{
+       disable_intreq_irq(irq);
+}
+
+static void
+end_intreq_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               enable_intreq_irq(irq);
+}
+
+static struct hw_interrupt_type intreq_irq_type = {
+       .typename = "FPGA-IRQ",
+       .startup = startup_intreq_irq,
+       .shutdown = shutdown_intreq_irq,
+       .enable = enable_intreq_irq,
+       .disable = disable_intreq_irq,
+       .ack = mask_and_ack_intreq_irq,
+       .end = end_intreq_irq
+};
+
+static void
+make_intreq_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &intreq_irq_type;
+       disable_intreq_irq(irq);
+}
+
+int
+shmse_irq_demux(int irq)
+{
+       int bit;
+       volatile u16 val;
+
+       if (irq == IRQ5_IRQ) {
+               /* Read status Register */
+               val = ctrl_inw(PA_CPLD_ST);
+               bit = ffs(val);
+               if (bit != 0)
+                       return OFFCHIP_IRQ_BASE + bit - 1;
+       }
+       return irq;
+}
+
+/* IRQ5 is multiplexed between the following sources:
+ * 1. PC Card socket
+ * 2. Extension slot
+ * 3. USB Controller
+ * 4. Serial Controller
+ *
+ * We configure IRQ5 as a cascade IRQ.
+ */
+static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade",
+                               NULL, NULL};
+
+/*
+ * Initialize IRQ setting
+ */
+void __init
+init_7343se_IRQ(void)
+{
+       /* Setup Multiplexed interrupts */
+       ctrl_outw(8, PA_CPLD_MODESET);  /* Set all CPLD interrupts to active
+                                        * low.
+                                        */
+       /* Mask all CPLD controller interrupts */
+       ctrl_outw(0x0fff, PA_CPLD_IMSK);
+
+       /* PC Card interrupts */
+       make_intreq_irq(PC_IRQ0);
+       make_intreq_irq(PC_IRQ1);
+       make_intreq_irq(PC_IRQ2);
+       make_intreq_irq(PC_IRQ3);
+
+       /* Extension Slot Interrupts */
+       make_intreq_irq(EXT_IRQ0);
+       make_intreq_irq(EXT_IRQ1);
+       make_intreq_irq(EXT_IRQ2);
+       make_intreq_irq(EXT_IRQ3);
+
+       /* USB Controller interrupts */
+       make_intreq_irq(USB_IRQ0);
+       make_intreq_irq(USB_IRQ1);
+
+       /* Serial Controller interrupts */
+       make_intreq_irq(UART_IRQ0);
+       make_intreq_irq(UART_IRQ1);
+
+       /* Setup all external interrupts to be active low */
+       ctrl_outw(0xaaaa, INTC_ICR1);
+
+       make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY);
+       setup_irq(IRQ5_IRQ, &irq5);
+       /* Set port control to use IRQ5 */
+       *(u16 *)0xA4050108 &= ~0xc;
+
+       make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+       make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);
+
+       ctrl_outb(0x0f, INTC_IMCR5);    /* enable SCIF IRQ */
+
+       make_ipr_irq(DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+       make_ipr_irq(DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+
+       /* I2C block */
+       make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+       make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+                    IIC0_PRIORITY);
+       make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+                    IIC0_PRIORITY);
+       make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+
+       make_ipr_irq(IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
+       make_ipr_irq(IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
+                    IIC1_PRIORITY);
+       make_ipr_irq(IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
+                    IIC1_PRIORITY);
+       make_ipr_irq(IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
+
+       /* SIOF */
+       make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+
+       /* SIU */
+       make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY);
+
+       /* VIO interrupt */
+       make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+       make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+       make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+
+       /*MFI interrupt*/
+
+       make_ipr_irq(MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY);
+
+       /* LCD controller */
+       make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
+       ctrl_outw(0x2000, PA_MRSHPC + 0x0c);    /* mrshpc irq enable */
+}
diff --git a/arch/sh/boards/se/7343/led.c b/arch/sh/boards/se/7343/led.c
new file mode 100644 (file)
index 0000000..6a439cf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * arch/sh/boards/se/7343/led.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/mach/se7343.h>
+
+/* Cycle the LED's in the clasic Knightrider/Sun pattern */
+void heartbeat_7343se(void)
+{
+       static unsigned int cnt = 0, period = 0;
+       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
+       static unsigned bit = 0, up = 1;
+
+       cnt += 1;
+       if (cnt < period) {
+               return;
+       }
+
+       cnt = 0;
+
+       /* Go through the points (roughly!):
+        * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
+        */
+       period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
+
+       if (up) {
+               if (bit == 7) {
+                       bit--;
+                       up = 0;
+               } else {
+                       bit++;
+               }
+       } else {
+               if (bit == 0) {
+                       bit++;
+                       up = 1;
+               } else {
+                       bit--;
+               }
+       }
+       *p = 1 << (bit + LED_SHIFT);
+
+}
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
new file mode 100644 (file)
index 0000000..7873222
--- /dev/null
@@ -0,0 +1,84 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/mach/se7343.h>
+#include <asm/irq.h>
+
+void heartbeat_7343se(void);
+void init_7343se_IRQ(void);
+
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = 0x10000000,
+               .end    = 0x1000000F,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /*
+                * shared with other devices via externel
+                * interrupt controller in FPGA...
+                */
+               .start  = EXT_IRQ2,
+               .end    = EXT_IRQ2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static struct platform_device *smc91x_platform_devices[] __initdata = {
+       &smc91x_device,
+};
+
+static int __init sh7343se_devices_setup(void)
+{
+       return platform_add_devices(smc91x_platform_devices,
+                                   ARRAY_SIZE(smc91x_platform_devices));
+}
+
+static void __init sh7343se_setup(char **cmdline_p)
+{
+       device_initcall(sh7343se_devices_setup);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_7343se __initmv = {
+       .mv_name = "SolutionEngine 7343",
+       .mv_setup = sh7343se_setup,
+       .mv_nr_irqs = 108,
+       .mv_inb = sh7343se_inb,
+       .mv_inw = sh7343se_inw,
+       .mv_inl = sh7343se_inl,
+       .mv_outb = sh7343se_outb,
+       .mv_outw = sh7343se_outw,
+       .mv_outl = sh7343se_outl,
+
+       .mv_inb_p = sh7343se_inb_p,
+       .mv_inw_p = sh7343se_inw,
+       .mv_inl_p = sh7343se_inl,
+       .mv_outb_p = sh7343se_outb_p,
+       .mv_outw_p = sh7343se_outw,
+       .mv_outl_p = sh7343se_outl,
+
+       .mv_insb = sh7343se_insb,
+       .mv_insw = sh7343se_insw,
+       .mv_insl = sh7343se_insl,
+       .mv_outsb = sh7343se_outsb,
+       .mv_outsw = sh7343se_outsw,
+       .mv_outsl = sh7343se_outsl,
+
+       .mv_init_irq = init_7343se_IRQ,
+       .mv_irq_demux = shmse_irq_demux,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat = heartbeat_7343se,
+#endif
+};
+ALIAS_MV(7343se)
index be89a73cc418aede40d3cbbfd0f2baec468b4352..9a5035f80ec03987aadf37f3e72623a76c6ed179 100644 (file)
@@ -2,5 +2,5 @@
 # Makefile for the 770x SolutionEngine specific parts of the kernel
 #
 
-obj-y   := mach.o setup.o io.o irq.o led.o
-
+obj-y   := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
index 9a39ee963143fa4169bae4e9bb46abaabcf27a68..9941949331abee325bea7f35f97a52b2673a6b01 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
+/* $Id: io.c,v 1.7 2006/02/05 21:55:29 lethal Exp $
  *
  * linux/arch/sh/kernel/io_se.c
  *
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
 
 /* SH pcmcia io window base, start and end.  */
 int sh_pcic_io_wbase = 0xb8400000;
@@ -20,11 +20,6 @@ int sh_pcic_io_stop;
 int sh_pcic_io_type;
 int sh_pcic_io_dummy;
 
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 /* MS7750 requires special versions of in*, out* routines, since
    PC-like io ports are located at upper half byte of 16-bit word which
    can be accessed only with 16-bit wide.  */
@@ -52,10 +47,6 @@ shifted_port(unsigned long port)
                return 1;
 }
 
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
 unsigned char se_inb(unsigned long port)
 {
        if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
@@ -76,7 +67,7 @@ unsigned char se_inb_p(unsigned long port)
                v = (*port2adr(port) >> 8); 
        else
                v = (*port2adr(port))&0xff; 
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -86,13 +77,13 @@ unsigned short se_inw(unsigned long port)
            (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
                return *port2adr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
 unsigned int se_inl(unsigned long port)
 {
-       maybebadio(inl, port);
+       maybebadio(port);
        return 0;
 }
 
@@ -114,7 +105,7 @@ void se_outb_p(unsigned char value, unsigned long port)
                *(port2adr(port)) = value << 8;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
 void se_outw(unsigned short value, unsigned long port)
@@ -123,12 +114,12 @@ void se_outw(unsigned short value, unsigned long port)
            (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
                *port2adr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void se_outl(unsigned int value, unsigned long port)
 {
-       maybebadio(outl, port);
+       maybebadio(port);
 }
 
 void se_insb(unsigned long port, void *addr, unsigned long count)
@@ -159,7 +150,7 @@ void se_insw(unsigned long port, void *addr, unsigned long count)
 
 void se_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void se_outsb(unsigned long port, const void *addr, unsigned long count)
@@ -190,37 +181,5 @@ void se_outsw(unsigned long port, const void *addr, unsigned long count)
 
 void se_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
-       return 0;
-}
-
-unsigned long
-se_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index 3e558716ce100fac939c084ecb8285cf382094a4..cff6700bbafd4f98878e462c9121a3057bd87acf 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
 
 /*
  * Initialize IRQ setting
index 3cddbda025fc28d1cd8b7ee431a49042b30199fd..daf7b1ee786a3f7f1d833cc4a1712cbf5d6ae6e1 100644 (file)
@@ -9,22 +9,8 @@
  * This file contains Solution Engine specific LED code.
  */
 
-#include <asm/se/se.h>
-
-static void mach_led(int position, int value)
-{
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-
-       if (value) {
-               *p |= (1<<8);
-       } else {
-               *p &= ~(1<<8);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
 #include <linux/sched.h>
+#include <asm/se.h>
 
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
 void heartbeat_se(void)
@@ -64,4 +50,3 @@ void heartbeat_se(void)
        *p = 1<<(bit+8);
 
 }
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c
deleted file mode 100644 (file)
index 6ec07bd..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_se.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Hitachi SolutionEngine
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/se/io.h>
-
-void heartbeat_se(void);
-void setup_se(void);
-void init_se_IRQ(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_se __initmv = {
-#if defined(CONFIG_CPU_SH4)
-       .mv_nr_irqs             = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-       .mv_nr_irqs             = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
-       .mv_nr_irqs             = 61,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-       .mv_nr_irqs             = 86,
-#endif
-
-       .mv_inb                 = se_inb,
-       .mv_inw                 = se_inw,
-       .mv_inl                 = se_inl,
-       .mv_outb                = se_outb,
-       .mv_outw                = se_outw,
-       .mv_outl                = se_outl,
-
-       .mv_inb_p               = se_inb_p,
-       .mv_inw_p               = se_inw,
-       .mv_inl_p               = se_inl,
-       .mv_outb_p              = se_outb_p,
-       .mv_outw_p              = se_outw,
-       .mv_outl_p              = se_outl,
-
-       .mv_insb                = se_insb,
-       .mv_insw                = se_insw,
-       .mv_insl                = se_insl,
-       .mv_outsb               = se_outsb,
-       .mv_outsw               = se_outsw,
-       .mv_outsl               = se_outsl,
-
-       .mv_isa_port2addr       = se_isa_port2addr,
-
-       .mv_init_irq            = init_se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_se,
-#endif
-};
-ALIAS_MV(se)
index 7d1a071727cc57da4ed3bf18c7fc52f4e99c1217..f3f82b7c821740b22849caadb665d82330fdca0c 100644 (file)
@@ -7,15 +7,17 @@
  * Hitachi SolutionEngine Support.
  *
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
-#include <asm/se/smc37c93x.h>
+#include <asm/se.h>
+#include <asm/smc37c93x.h>
+#include <asm/machvec.h>
+
+void heartbeat_se(void);
+void init_se_IRQ(void);
 
 /*
  * Configure the Super I/O chip
@@ -26,7 +28,8 @@ static void __init smsc_config(int index, int data)
        outb_p(data, DATA_PORT);
 }
 
-static void __init init_smsc(void)
+/* XXX: Another candidate for a more generic cchip machine vector */
+static void __init smsc_setup(char **cmdline_p)
 {
        outb_p(CONFIG_ENTER, CONFIG_PORT);
        outb_p(CONFIG_ENTER, CONFIG_PORT);
@@ -69,16 +72,46 @@ static void __init init_smsc(void)
        outb_p(CONFIG_EXIT, CONFIG_PORT);
 }
 
-const char *get_system_type(void)
-{
-       return "SolutionEngine";
-}
-
 /*
- * Initialize the board
+ * The Machine Vector
  */
-void __init platform_setup(void)
-{
-       init_smsc();
-       /* XXX: RTC setting comes here */
-}
+struct sh_machine_vector mv_se __initmv = {
+       .mv_name                = "SolutionEngine",
+       .mv_setup               = smsc_setup,
+#if defined(CONFIG_CPU_SH4)
+       .mv_nr_irqs             = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+       .mv_nr_irqs             = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+       .mv_nr_irqs             = 61,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+       .mv_nr_irqs             = 86,
+#endif
+
+       .mv_inb                 = se_inb,
+       .mv_inw                 = se_inw,
+       .mv_inl                 = se_inl,
+       .mv_outb                = se_outb,
+       .mv_outw                = se_outw,
+       .mv_outl                = se_outl,
+
+       .mv_inb_p               = se_inb_p,
+       .mv_inw_p               = se_inw,
+       .mv_inl_p               = se_inl,
+       .mv_outb_p              = se_outb_p,
+       .mv_outw_p              = se_outw,
+       .mv_outl_p              = se_outl,
+
+       .mv_insb                = se_insb,
+       .mv_insw                = se_insw,
+       .mv_insl                = se_insl,
+       .mv_outsb               = se_outsb,
+       .mv_outsw               = se_outsw,
+       .mv_outsl               = se_outsl,
+
+       .mv_init_irq            = init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_se,
+#endif
+};
+ALIAS_MV(se)
index ce7ca247f84d04dfbe722f689655eb39b56e1d72..188900c48321335bca050c9d1b8b161d9fec7c3a 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the 7751 SolutionEngine specific parts of the kernel
 #
 
-obj-y   := mach.o setup.o io.o irq.o led.o
+obj-y   := setup.o io.o irq.o
 
 obj-$(CONFIG_PCI) += pci.o
-
+obj-$(CONFIG_HEARTBEAT) += led.o
index 99041b26926121f33be525e3432daaa656a11f7f..e8d846cec89d1b82c6d323a22e4f0e74c7abea54 100644 (file)
@@ -1,6 +1,4 @@
-/* 
- * linux/arch/sh/kernel/io_7751se.c
- *
+/*
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  *
  * placeholder code from io_se.c left in with the
  * expectation of later SuperIO and PCMCIA access.
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/pci.h>
 #include <asm/io.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
 #include <asm/addrspace.h>
 
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-#if 0
-/******************************************************************
- * Variables from io_se.c, related to PCMCIA (not PCI); we're not
- * compiling them in, and have removed references from functions
- * which follow.  [Many checked for IO ports in the range bounded
- * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
- * As start/stop are uninitialized, only port 0x0 would match?]
- * When used, remember to adjust names to avoid clash with io_se?
- *****************************************************************/
-/* SH pcmcia io window base, start and end.  */
-int sh_pcic_io_wbase = 0xb8400000;
-int sh_pcic_io_start;
-int sh_pcic_io_stop;
-int sh_pcic_io_type;
-int sh_pcic_io_dummy;
-/*************************************************************/
-#endif
-
-/*
- * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
- * of the 7751 processor, and has a SuperIO accessible via the PCI.
- * The board also includes a PCMCIA controller on its memory bus,
- * like the other Solution Engine boards.
- */ 
-
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
-static inline volatile __u16 *
-port2adr(unsigned int port)
+static inline volatile u16 *port2adr(unsigned int port)
 {
        if (port >= 0x2000)
                return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#if 0
-       else
-               return (volatile __u16 *) (PA_SUPERIO + (port << 1));
-#endif
-       maybebadio(name,(unsigned long)port);
+       maybebadio((unsigned long)port);
        return (volatile __u16*)port;
 }
 
-#if 0
-/* The 7751 Solution Engine seems to have everything hooked */
-/* up pretty normally (nothing on high-bytes only...) so this */
-/* shouldn't be needed */
-static inline int
-shifted_port(unsigned long port)
-{
-       /* For IDE registers, value is not shifted */
-       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
-               return 0;
-       else
-               return 1;
-}
-#endif
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
 /*
  * General outline: remap really low stuff [eventually] to SuperIO,
  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
@@ -111,10 +34,10 @@ unsigned char sh7751se_inb(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else
-               return (*port2adr(port))&0xff; 
+               return (*port2adr(port)) & 0xff;
 }
 
 unsigned char sh7751se_inb_p(unsigned long port)
@@ -123,11 +46,11 @@ unsigned char sh7751se_inb_p(unsigned long port)
 
         if (PXSEG(port))
                 v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                v = *(volatile unsigned char *)pci_ioaddr(port);
        else
-               v = (*port2adr(port))&0xff; 
-       delay();
+               v = (*port2adr(port)) & 0xff;
+       ctrl_delay();
        return v;
 }
 
@@ -135,12 +58,12 @@ unsigned short sh7751se_inw(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned short *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -148,12 +71,12 @@ unsigned int sh7751se_inl(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned int *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned int *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -162,8 +85,8 @@ void sh7751se_outb(unsigned char value, unsigned long port)
 
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
 }
@@ -172,73 +95,41 @@ void sh7751se_outb_p(unsigned char value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
 void sh7751se_outw(unsigned short value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned short *)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned short *)pci_ioaddr(port)) = value;
        else if (port >= 0x2000)
                *port2adr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void sh7751se_outl(unsigned int value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned long*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned long*)pci_ioaddr(port)) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-#if 0
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-       return 0;
-}
-#endif
-
-unsigned long
-sh7751se_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index bf6c023615df87306125654263eca40d0421ff7e..c607b0a48479d87b14ebff2d81263f8ae650cca1 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/irq.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
 
 /*
  * Initialize IRQ setting
index a878726d3c7c8d5019be1d96bbc94cb0d496a20c..ff0355dea81b37ba235c0c53953917a44cb1a786 100644 (file)
@@ -8,23 +8,8 @@
  *
  * This file contains Solution Engine specific LED code.
  */
-
-#include <asm/se7751/se7751.h>
-
-static void mach_led(int position, int value)
-{
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-
-       if (value) {
-               *p |= (1<<8);
-       } else {
-               *p &= ~(1<<8);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
 #include <linux/sched.h>
+#include <asm/se7751.h>
 
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
 void heartbeat_7751se(void)
@@ -64,4 +49,3 @@ void heartbeat_7751se(void)
        *p = 1<<(bit+8);
 
 }
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7751/mach.c b/arch/sh/boards/se/7751/mach.c
deleted file mode 100644 (file)
index 62d8d3e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_7751se.c
- *
- * Minor tweak of mach_se.c file to reference 7751se-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Hitachi 7751 SolutionEngine
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/se7751/io.h>
-
-void heartbeat_7751se(void);
-void init_7751se_IRQ(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_7751se __initmv = {
-       .mv_nr_irqs             = 72,
-
-       .mv_inb                 = sh7751se_inb,
-       .mv_inw                 = sh7751se_inw,
-       .mv_inl                 = sh7751se_inl,
-       .mv_outb                = sh7751se_outb,
-       .mv_outw                = sh7751se_outw,
-       .mv_outl                = sh7751se_outl,
-
-       .mv_inb_p               = sh7751se_inb_p,
-       .mv_inw_p               = sh7751se_inw,
-       .mv_inl_p               = sh7751se_inl,
-       .mv_outb_p              = sh7751se_outb_p,
-       .mv_outw_p              = sh7751se_outw,
-       .mv_outl_p              = sh7751se_outl,
-
-       .mv_insl                = sh7751se_insl,
-       .mv_outsl               = sh7751se_outsl,
-
-       .mv_isa_port2addr       = sh7751se_isa_port2addr,
-
-       .mv_init_irq            = init_7751se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_7751se,
-#endif
-};
-ALIAS_MV(7751se)
index 48dc5aee67d4d6c6cd4edc3225cd3749cfe29af3..73e826310ba8748379395871c663681cbfa99939 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * linux/arch/sh/kernel/setup_7751se.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
 
 #include <linux/init.h>
 #include <linux/irq.h>
-
-#include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <asm/io.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#endif
-
-/*
- * Configure the Super I/O chip
- */
-#if 0
-/* Leftover code from regular Solution Engine, for reference. */
-/* The SH7751 Solution Engine has a different SuperIO. */
-static void __init smsc_config(int index, int data)
-{
-       outb_p(index, INDEX_PORT);
-       outb_p(data, DATA_PORT);
-}
-
-static void __init init_smsc(void)
-{
-       outb_p(CONFIG_ENTER, CONFIG_PORT);
-       outb_p(CONFIG_ENTER, CONFIG_PORT);
-
-       /* FDC */
-       smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
-
-       /* IDE1 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
-
-       /* AUXIO (GPIO): to use IDE1 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
-       smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
-       smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
-
-       /* COM1 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IO_BASE_HI_INDEX, 0x03);
-       smsc_config(IO_BASE_LO_INDEX, 0xf8);
-       smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
-
-       /* COM2 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IO_BASE_HI_INDEX, 0x02);
-       smsc_config(IO_BASE_LO_INDEX, 0xf8);
-       smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
-
-       /* RTC */
-       smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
-
-       /* XXX: PARPORT, KBD, and MOUSE will come here... */
-       outb_p(CONFIG_EXIT, CONFIG_PORT);
-}
-#endif
-
-const char *get_system_type(void)
-{
-       return "7751 SolutionEngine";
-}
+void heartbeat_7751se(void);
+void init_7751se_IRQ(void);
 
 #ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
 static int kgdb_uart_setup(void);
 static struct kgdb_sermap kgdb_uart_sermap = 
 { "ttyS", 0, kgdb_uart_setup, NULL };
@@ -91,7 +28,7 @@ static struct kgdb_sermap kgdb_uart_sermap =
 /*
  * Initialize the board
  */
-void __init platform_setup(void)
+static void __init sh7751se_setup(char **cmdline_p)
 {
        /* Call init_smsc() replacement to set up SuperIO. */
        /* XXX: RTC setting comes here */
@@ -225,3 +162,37 @@ static int kgdb_uart_setup(void)
        return 0;
 }
 #endif /* CONFIG_SH_KGDB */
+
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_7751se __initmv = {
+       .mv_name                = "7751 SolutionEngine",
+       .mv_setup               = sh7751se_setup,
+       .mv_nr_irqs             = 72,
+
+       .mv_inb                 = sh7751se_inb,
+       .mv_inw                 = sh7751se_inw,
+       .mv_inl                 = sh7751se_inl,
+       .mv_outb                = sh7751se_outb,
+       .mv_outw                = sh7751se_outw,
+       .mv_outl                = sh7751se_outl,
+
+       .mv_inb_p               = sh7751se_inb_p,
+       .mv_inw_p               = sh7751se_inw,
+       .mv_inl_p               = sh7751se_inl,
+       .mv_outb_p              = sh7751se_outb_p,
+       .mv_outw_p              = sh7751se_outw,
+       .mv_outl_p              = sh7751se_outl,
+
+       .mv_insl                = sh7751se_insl,
+       .mv_outsl               = sh7751se_outsl,
+
+       .mv_init_irq            = init_7751se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_7751se,
+#endif
+};
+ALIAS_MV(7751se)
index d609863cfe53fba5ba3068da2d1d78a95d2bade5..0a9266bb51c58bcd7309dcf15b5870b563a08f11 100644 (file)
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/bcd.h>
-#include <asm/io.h>
 #include <linux/rtc.h>
 #include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/rtc.h>
 
 #define RTC_BASE       0xb0000000
 #define RTC_SEC1       (RTC_BASE + 0)
@@ -34,8 +35,6 @@
 #define RTC_BUSY       1
 #define RTC_STOP       2
 
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
 extern spinlock_t rtc_lock;
 
 unsigned long get_cmos_time(void)
@@ -128,6 +127,6 @@ int sh03_rtc_settimeofday(const time_t secs)
 
 void sh03_time_init(void)
 {
-       rtc_get_time = sh03_rtc_gettimeofday;
-       rtc_set_time = sh03_rtc_settimeofday;
+       rtc_sh_get_time = sh03_rtc_gettimeofday;
+       rtc_sh_set_time = sh03_rtc_settimeofday;
 }
index 60290f8f289c49fda70b3f6ee6912b6f6b63ea8a..6c310587ddfe72ecc15848d34297e1e52ec7f2b0 100644 (file)
@@ -7,22 +7,13 @@
 
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
 #include <asm/io.h>
+#include <asm/rtc.h>
 #include <asm/sh03/io.h>
 #include <asm/sh03/sh03.h>
 #include <asm/addrspace.h>
-#include "../../drivers/pci/pci-sh7751.h"
 
-extern void (*board_time_init)(void);
-
-const char *get_system_type(void)
-{
-       return "Interface CTP/PCI-SH03)";
-}
-
-void init_sh03_IRQ(void)
+static void __init init_sh03_IRQ(void)
 {
        ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 
@@ -34,38 +25,34 @@ void init_sh03_IRQ(void)
 
 extern void *cf_io_base;
 
-unsigned long sh03_isa_port2addr(unsigned long port)
+static void __iomem *sh03_ioport_map(unsigned long port, unsigned int size)
 {
        if (PXSEG(port))
-               return port;
+               return (void __iomem *)port;
        /* CompactFlash (IDE) */
-       if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6)) {
-               return (unsigned long)cf_io_base + port;
-       }
-        return port + SH7751_PCI_IO_BASE;
+       if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6))
+               return (void __iomem *)((unsigned long)cf_io_base + port);
+
+        return (void __iomem *)(port + PCI_IO_BASE);
 }
 
-/*
- * The Machine Vector
- */
+/* arch/sh/boards/sh03/rtc.c */
+void sh03_time_init(void);
+
+static void __init sh03_setup(char **cmdline_p)
+{
+       board_time_init = sh03_time_init;
+}
 
 struct sh_machine_vector mv_sh03 __initmv = {
+       .mv_name                = "Interface (CTP/PCI-SH03)",
+       .mv_setup               = sh03_setup,
        .mv_nr_irqs             = 48,
-       .mv_isa_port2addr       = sh03_isa_port2addr,
+       .mv_ioport_map          = sh03_ioport_map,
        .mv_init_irq            = init_sh03_IRQ,
 
 #ifdef CONFIG_HEARTBEAT
        .mv_heartbeat           = heartbeat_sh03,
 #endif
 };
-
 ALIAS_MV(sh03)
-
-/* arch/sh/boards/sh03/rtc.c */
-void sh03_time_init(void);
-
-int __init platform_setup(void)
-{
-       board_time_init = sh03_time_init;
-       return 0;
-}
diff --git a/arch/sh/boards/sh2000/Makefile b/arch/sh/boards/sh2000/Makefile
deleted file mode 100644 (file)
index 05d390c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the SH2000 specific parts of the kernel
-#
-
-obj-y   := setup.o
-
diff --git a/arch/sh/boards/sh2000/setup.c b/arch/sh/boards/sh2000/setup.c
deleted file mode 100644 (file)
index 2fe6a11..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * linux/arch/sh/kernel/setup_sh2000.c
- *
- * Copyright (C) 2001  SUGIOKA Tochinobu
- *
- * SH-2000 Support.
- *
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/sh2000.h>
-
-#define CF_CIS_BASE    0xb4200000
-
-#define PORT_PECR      0xa4000108
-#define PORT_PHCR      0xa400010E
-#define        PORT_ICR1       0xa4000010
-#define        PORT_IRR0       0xa4000004
-
-#define IDE_OFFSET     0xb6200000
-#define NIC_OFFSET     0xb6000000
-#define EXTBUS_OFFSET  0xba000000
-
-
-const char *get_system_type(void)
-{
-       return "sh2000";
-}
-
-static unsigned long sh2000_isa_port2addr(unsigned long offset)
-{
-       if((offset & ~7) == 0x1f0 || offset == 0x3f6)
-               return IDE_OFFSET + offset;
-       else if((offset & ~0x1f) == 0x300)
-               return NIC_OFFSET + offset;
-       return EXTBUS_OFFSET + offset;
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_sh2000 __initmv = {
-        .mv_nr_irqs            = 80,
-        .mv_isa_port2addr      = sh2000_isa_port2addr,
-};
-ALIAS_MV(sh2000)
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-       /* XXX: RTC setting comes here */
-
-       /* These should be done by BIOS/IPL ... */
-       /* Enable nCE2A, nCE2B output */
-       ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR);
-       /* Enable the Compact Flash card, and set the level interrupt */
-       ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
-       /* Enable interrupt */
-       ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR);
-       ctrl_outw(1, PORT_ICR1);
-       ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0);
-       printk(KERN_INFO "SH-2000 Setup...done\n");
-       return 0;
-}
diff --git a/arch/sh/boards/shmin/Makefile b/arch/sh/boards/shmin/Makefile
new file mode 100644 (file)
index 0000000..3190cc7
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the SHMIN board.
+#
+
+obj-y   := setup.o
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
new file mode 100644 (file)
index 0000000..2f0c197
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/boards/shmin/setup.c
+ *
+ * Copyright (C) 2006 Takashi YOSHII
+ *
+ * SHMIN Support.
+ */
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/shmin/shmin.h>
+#include <asm/clock.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#define PFC_PHCR       0xa400010e
+
+static void __init init_shmin_irq(void)
+{
+       ctrl_outw(0x2a00, PFC_PHCR);    // IRQ0-3=IRQ
+       ctrl_outw(0x0aaa, INTC_ICR1);   // IRQ0-3=IRQ-mode,Low-active.
+}
+
+static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
+{
+       static int dummy;
+
+       if ((port & ~0x1f) == SHMIN_NE_BASE)
+               return (void __iomem *)(SHMIN_IO_BASE + port);
+
+       dummy = 0;
+
+       return &dummy;
+
+}
+
+struct sh_machine_vector mv_shmin __initmv = {
+       .mv_name        = "SHMIN",
+       .mv_init_irq    = init_shmin_irq,
+       .mv_ioport_map  = shmin_ioport_map,
+};
+ALIAS_MV(shmin)
index e2eb78fc381d6573b072cadcbc6e5fbdb7bacd7c..0f4824264557deae48a2b6719a475ea3f0b21175 100644 (file)
@@ -1,6 +1,4 @@
-/* 
- * linux/arch/sh/kernel/io_7751se.c
- *
+/*
  * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  * placeholder code from io_se.c left in with the
  * expectation of later SuperIO and PCMCIA access.
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/addrspace.h>
 
-#include <asm/pci.h>
-#include "../../drivers/pci/pci-sh7751.h"
-
 #ifdef CONFIG_SH_SECUREEDGE5410
 unsigned short secureedge5410_ioport;
 #endif
 
-/*
- * The SnapGear uses the built-in PCI controller (PCIC)
- * of the 7751 processor
- */ 
-
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
-
 static inline volatile __u16 *port2adr(unsigned int port)
 {
-#if 0
-       if (port >= 0x2000)
-               return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#endif
-       maybebadio(name,(unsigned long)port);
+       maybebadio((unsigned long)port);
        return (volatile __u16*)port;
 }
 
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
 /*
  * General outline: remap really low stuff [eventually] to SuperIO,
  * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
@@ -79,148 +32,106 @@ static inline volatile __u16 *port2adr(unsigned int port)
  * should be way beyond the window, and is used  w/o translation for
  * compatibility.
  */
-
 unsigned char snapgear_inb(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else
-               return (*port2adr(port))&0xff; 
+               return (*port2adr(port)) & 0xff;
 }
 
-
 unsigned char snapgear_inb_p(unsigned long port)
 {
        unsigned char v;
 
        if (PXSEG(port))
                v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               v = *(volatile unsigned char *)pci_ioaddr(port);
        else
-               v = (*port2adr(port))&0xff; 
-       delay();
+               v = (*port2adr(port))&0xff;
+       ctrl_delay();
        return v;
 }
 
-
 unsigned short snapgear_inw(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned short *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
-
 unsigned int snapgear_inl(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned int *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned int *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
-
 void snapgear_outb(unsigned char value, unsigned long port)
 {
 
        if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
 }
 
-
 void snapgear_outb_p(unsigned char value, unsigned long port)
 {
        if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
-
 void snapgear_outw(unsigned short value, unsigned long port)
 {
        if (PXSEG(port))
                *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned short *)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned short *)pci_ioaddr(port)) = value;
        else if (port >= 0x2000)
                *port2adr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
-
 void snapgear_outl(unsigned int value, unsigned long port)
 {
        if (PXSEG(port))
                *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned long*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned long*)pci_ioaddr(port)) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void snapgear_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void snapgear_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-
-#if 0
-static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
-       return 0;
-}
-#endif
-
-unsigned long snapgear_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index b71e009da35cb265dfbcb208527451bff2dbc69f..1659fdd6695a14fcf3ac687016f2bd1a6a3db3b7 100644 (file)
 #include <linux/time.h>
 #include <linux/rtc.h>
 #include <linux/mc146818rtc.h>
-
 #include <asm/io.h>
-#include <asm/rtc.h>
-#include <asm/mc146818rtc.h>
-
-/****************************************************************************/
 
-static int use_ds1302 = 0;
+static int use_ds1302;
 
 /****************************************************************************/
 /*
@@ -82,10 +77,6 @@ static unsigned int ds1302_readbyte(unsigned int addr)
        unsigned int    val;
        unsigned long   flags;
 
-#if 0
-       printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr);
-#endif
-
        local_irq_save(flags);
        set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
        set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -104,10 +95,6 @@ static void ds1302_writebyte(unsigned int addr, unsigned int val)
 {
        unsigned long   flags;
 
-#if 0
-       printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr);
-#endif
-
        local_irq_save(flags);
        set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
        set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -168,11 +155,8 @@ void __init secureedge5410_rtc_init(void)
                }
 
        if (use_ds1302) {
-               rtc_get_time = snapgear_rtc_gettimeofday;
-               rtc_set_time = snapgear_rtc_settimeofday;
-       } else {
-               rtc_get_time = sh_rtc_gettimeofday;
-               rtc_set_time = sh_rtc_settimeofday;
+               rtc_sh_get_time = snapgear_rtc_gettimeofday;
+               rtc_sh_set_time = snapgear_rtc_settimeofday;
        }
                
        printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
@@ -187,10 +171,8 @@ void snapgear_rtc_gettimeofday(struct timespec *ts)
 {
        unsigned int sec, min, hr, day, mon, yr;
 
-       if (!use_ds1302) {
-               sh_rtc_gettimeofday(ts);
+       if (!use_ds1302)
                return;
-       }
 
        sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
        min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
@@ -231,7 +213,7 @@ int snapgear_rtc_settimeofday(const time_t secs)
        unsigned long nowtime;
 
        if (!use_ds1302)
-               return sh_rtc_settimeofday(secs);
+               return 0;
 
 /*
  *     This is called direct from the kernel timer handling code.
@@ -240,10 +222,6 @@ int snapgear_rtc_settimeofday(const time_t secs)
 
        nowtime = secs;
 
-#if 1
-       printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime);
-#endif
-
        /* STOP RTC */
        ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
 
@@ -329,5 +307,3 @@ void secureedge5410_cmos_write(unsigned char val, int addr)
        default:                                                      break;
        }
 }
-
-/****************************************************************************/
index f1f7c70c9402d61384776b0c3ba7927729771d45..f5e98c56b530a7c23d3e43b77e2b063cf19a448f 100644 (file)
@@ -1,5 +1,4 @@
-/****************************************************************************/
-/* 
+/*
  * linux/arch/sh/boards/snapgear/setup.c
  *
  * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
@@ -12,8 +11,6 @@
  *           Modified for 7751 Solution Engine by
  *           Ian da Silva and Jeremy Siegel, 2001.
  */
-/****************************************************************************/
-
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-
 #include <asm/machvec.h>
-#include <asm/mach/io.h>
+#include <asm/snapgear.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/rtc.h>
 #include <asm/cpu/timer.h>
 
-extern void (*board_time_init)(void);
 extern void secureedge5410_rtc_init(void);
 extern void pcibios_init(void);
 
@@ -85,101 +81,20 @@ static void __init init_snapgear_IRQ(void)
        make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
 }
 
-/****************************************************************************/
-/*
- *     Fast poll interrupt simulator.
- */
-
 /*
- * Leave all of the fast timer/fast poll stuff commented out for now, since
- * it's not clear whether it actually works or not. Since it wasn't being used
- * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM
- */
-#if 0
-#define FAST_POLL      1000
-//#define FAST_POLL_INTR
-
-#define FASTTIMER_IRQ   17
-#define FASTTIMER_IPR_ADDR  INTC_IPRA
-#define FASTTIMER_IPR_POS    2
-#define FASTTIMER_PRIORITY   3
-
-#ifdef FAST_POLL_INTR
-#define TMU1_TCR_INIT  0x0020
-#else
-#define TMU1_TCR_INIT  0
-#endif
-#define TMU_TSTR_INIT  1
-#define TMU1_TCR_CALIB 0x0000
-
-
-#ifdef FAST_POLL_INTR
-static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       unsigned long timer_status;
-    timer_status = ctrl_inw(TMU1_TCR);
-       timer_status &= ~0x100;
-       ctrl_outw(timer_status, TMU1_TCR);
-}
-#endif
-
-/*
- * return the current ticks on the fast timer
- */
-
-unsigned long fast_timer_count(void)
-{
-       return(ctrl_inl(TMU1_TCNT));
-}
-
-/*
- * setup a fast timer for profiling etc etc
+ * Initialize the board
  */
-
-static void setup_fast_timer()
-{
-       unsigned long interval;
-
-#ifdef FAST_POLL_INTR
-       interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL;
-
-       make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS,
-                       FASTTIMER_PRIORITY);
-
-       printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ);
-
-       if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer",
-                       NULL) != 0)
-               printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__);
-#else
-       printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ);
-       interval = 0xffffffff;
-#endif
-
-       ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */
-       ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
-       ctrl_outl(interval, TMU1_TCOR);
-       ctrl_outl(interval, TMU1_TCNT);
-       ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */
-
-       printk("Timer count 1 = 0x%x\n", fast_timer_count());
-       udelay(1000);
-       printk("Timer count 2 = 0x%x\n", fast_timer_count());
-}
-#endif
-
-/****************************************************************************/
-
-const char *get_system_type(void)
+static void __init snapgear_setup(char **cmdline_p)
 {
-       return "SnapGear SecureEdge5410";
+       board_time_init = secureedge5410_rtc_init;
 }
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_snapgear __initmv = {
+       .mv_name                = "SnapGear SecureEdge5410",
+       .mv_setup               = snapgear_setup,
        .mv_nr_irqs             = 72,
 
        .mv_inb                 = snapgear_inb,
@@ -196,20 +111,6 @@ struct sh_machine_vector mv_snapgear __initmv = {
        .mv_outw_p              = snapgear_outw,
        .mv_outl_p              = snapgear_outl,
 
-       .mv_isa_port2addr       = snapgear_isa_port2addr,
-
        .mv_init_irq            = init_snapgear_IRQ,
 };
 ALIAS_MV(snapgear)
-
-/*
- * Initialize the board
- */
-
-int __init platform_setup(void)
-{
-       board_time_init = secureedge5410_rtc_init;
-
-       return 0;
-}
-
index 236398fbc0834c00f94021bc7738f8dbacd27b30..8c64baa30364719da119296f487daeb9d8298426 100644 (file)
 
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/microdev.h>
 
 #define NUM_EXTERNAL_IRQS 16   /* IRL0 .. IRL15 */
 
-
 static const struct {
        unsigned char fpgaIrq;
        unsigned char mapped;
@@ -93,53 +91,42 @@ static struct hw_interrupt_type microdev_irq_type = {
 
 static void disable_microdev_irq(unsigned int irq)
 {
-       unsigned int flags;
        unsigned int fpgaIrq;
 
-       if (irq >= NUM_EXTERNAL_IRQS) return;
-       if (!fpgaIrqTable[irq].mapped) return;
+       if (irq >= NUM_EXTERNAL_IRQS)
+               return;
+       if (!fpgaIrqTable[irq].mapped)
+               return;
 
        fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
 
-               /* disable interrupts */
-       local_irq_save(flags);
-
-               /* disable interupts on the FPGA INTC register */
+       /* disable interupts on the FPGA INTC register */
        ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
-
-               /* restore interrupts */
-       local_irq_restore(flags);
 }
 
 static void enable_microdev_irq(unsigned int irq)
 {
        unsigned long priorityReg, priorities, pri;
-       unsigned int flags;
        unsigned int fpgaIrq;
 
-
-       if (irq >= NUM_EXTERNAL_IRQS) return;
-       if (!fpgaIrqTable[irq].mapped) return;
+       if (unlikely(irq >= NUM_EXTERNAL_IRQS))
+               return;
+       if (unlikely(!fpgaIrqTable[irq].mapped))
+               return;
 
        pri = 15 - irq;
 
        fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
        priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
 
-               /* disable interrupts */
-       local_irq_save(flags);
-
-               /* set priority for the interrupt */
+       /* set priority for the interrupt */
        priorities = ctrl_inl(priorityReg);
        priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
        priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
        ctrl_outl(priorities, priorityReg);
 
-               /* enable interupts on the FPGA INTC register */
+       /* enable interupts on the FPGA INTC register */
        ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
-
-               /* restore interrupts */
-       local_irq_restore(flags);
 }
 
        /* This functions sets the desired irq handler to be a MicroDev type */
@@ -158,9 +145,7 @@ static void mask_and_ack_microdev(unsigned int irq)
 static void end_microdev_irq(unsigned int irq)
 {
        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-       {
                enable_microdev_irq(irq);
-       }
 }
 
 extern void __init init_microdev_irq(void)
@@ -171,9 +156,7 @@ extern void __init init_microdev_irq(void)
        ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
 
        for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
-       {
                make_microdev_irq(i);
-       }
 }
 
 extern void microdev_print_fpga_intc_status(void)
index 61b402a3f5d734ac689ea9ac7f68f7bfb2fafc2e..031c814e6e76317aaca6cefb5c4362efa6965cac 100644 (file)
@@ -10,7 +10,6 @@
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  */
-
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
 
 extern void microdev_heartbeat(void);
 
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_sh4202_microdev __initmv = {
-       .mv_nr_irqs             = 72,           /* QQQ need to check this - use the MACRO */
-
-       .mv_inb                 = microdev_inb,
-       .mv_inw                 = microdev_inw,
-       .mv_inl                 = microdev_inl,
-       .mv_outb                = microdev_outb,
-       .mv_outw                = microdev_outw,
-       .mv_outl                = microdev_outl,
-
-       .mv_inb_p               = microdev_inb_p,
-       .mv_inw_p               = microdev_inw_p,
-       .mv_inl_p               = microdev_inl_p,
-       .mv_outb_p              = microdev_outb_p,
-       .mv_outw_p              = microdev_outw_p,
-       .mv_outl_p              = microdev_outl_p,
-
-       .mv_insb                = microdev_insb,
-       .mv_insw                = microdev_insw,
-       .mv_insl                = microdev_insl,
-       .mv_outsb               = microdev_outsb,
-       .mv_outsw               = microdev_outsw,
-       .mv_outsl               = microdev_outsl,
-
-       .mv_init_irq            = init_microdev_irq,
-
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = microdev_heartbeat,
-#endif
-};
-ALIAS_MV(sh4202_microdev)
 
 /****************************************************************************/
 
@@ -113,11 +77,6 @@ ALIAS_MV(sh4202_microdev)
        /* assume a Keyboard Controller is present */
 int microdev_kbd_controller_present = 1;
 
-const char *get_system_type(void)
-{
-       return "SH4-202 MicroDev";
-}
-
 static struct resource smc91x_resources[] = {
        [0] = {
                .start          = 0x300,
@@ -291,25 +250,9 @@ static int __init microdev_devices_setup(void)
        return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
 }
 
-__initcall(microdev_devices_setup);
-
-void __init platform_setup(void)
-{
-       int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
-       const int fpgaRevision = *fpgaRevisionRegister;
-       int * const CacheControlRegister = (int*)CCR;
-
-       printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
-               get_system_type(), fpgaRevision, *CacheControlRegister);
-}
-
-
-/****************************************************************************/
-
-
-       /*
-        * Setup for the SMSC FDC37C93xAPM
-        */
+/*
+ * Setup for the SMSC FDC37C93xAPM
+ */
 static int __init smsc_superio_setup(void)
 {
 
@@ -412,8 +355,52 @@ static int __init smsc_superio_setup(void)
        return 0;
 }
 
+static void __init microdev_setup(char **cmdline_p)
+{
+       int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
+       const int fpgaRevision = *fpgaRevisionRegister;
+       int * const CacheControlRegister = (int*)CCR;
+
+       device_initcall(microdev_devices_setup);
+       device_initcall(smsc_superio_setup);
 
-/* This is grotty, but, because kernel is always referenced on the link line
- * before any devices, this is safe.
+       printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
+               get_system_type(), fpgaRevision, *CacheControlRegister);
+}
+
+/*
+ * The Machine Vector
  */
-__initcall(smsc_superio_setup);
+struct sh_machine_vector mv_sh4202_microdev __initmv = {
+       .mv_name                = "SH4-202 MicroDev",
+       .mv_setup               = microdev_setup,
+       .mv_nr_irqs             = 72,           /* QQQ need to check this - use the MACRO */
+
+       .mv_inb                 = microdev_inb,
+       .mv_inw                 = microdev_inw,
+       .mv_inl                 = microdev_inl,
+       .mv_outb                = microdev_outb,
+       .mv_outw                = microdev_outw,
+       .mv_outl                = microdev_outl,
+
+       .mv_inb_p               = microdev_inb_p,
+       .mv_inw_p               = microdev_inw_p,
+       .mv_inl_p               = microdev_inl_p,
+       .mv_outb_p              = microdev_outb_p,
+       .mv_outw_p              = microdev_outw_p,
+       .mv_outl_p              = microdev_outl_p,
+
+       .mv_insb                = microdev_insb,
+       .mv_insw                = microdev_insw,
+       .mv_insl                = microdev_insl,
+       .mv_outsb               = microdev_outsb,
+       .mv_outsw               = microdev_outsw,
+       .mv_outsl               = microdev_outsl,
+
+       .mv_init_irq            = init_microdev_irq,
+
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = microdev_heartbeat,
+#endif
+};
+ALIAS_MV(sh4202_microdev)
diff --git a/arch/sh/boards/titan/Makefile b/arch/sh/boards/titan/Makefile
new file mode 100644 (file)
index 0000000..08d7537
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Nimble Microsystems TITAN specific parts of the kernel
+#
+
+obj-y   := setup.o io.o
diff --git a/arch/sh/boards/titan/io.c b/arch/sh/boards/titan/io.c
new file mode 100644 (file)
index 0000000..4730c1d
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *     I/O routines for Titan
+ */
+#include <linux/pci.h>
+#include <asm/machvec.h>
+#include <asm/addrspace.h>
+#include <asm/titan.h>
+#include <asm/io.h>
+
+static inline unsigned int port2adr(unsigned int port)
+{
+        maybebadio((unsigned long)port);
+        return port;
+}
+
+u8 titan_inb(unsigned long port)
+{
+        if (PXSEG(port))
+                return ctrl_inb(port);
+        else if (is_pci_ioaddr(port))
+                return ctrl_inb(pci_ioaddr(port));
+        return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 titan_inb_p(unsigned long port)
+{
+        u8 v;
+
+        if (PXSEG(port))
+                v = ctrl_inb(port);
+        else if (is_pci_ioaddr(port))
+                v = ctrl_inb(pci_ioaddr(port));
+        else
+                v = ctrl_inw(port2adr(port)) & 0xff;
+        ctrl_delay();
+        return v;
+}
+
+u16 titan_inw(unsigned long port)
+{
+        if (PXSEG(port))
+                return ctrl_inw(port);
+        else if (is_pci_ioaddr(port))
+                return ctrl_inw(pci_ioaddr(port));
+        else if (port >= 0x2000)
+                return ctrl_inw(port2adr(port));
+        else
+                maybebadio(port);
+        return 0;
+}
+
+u32 titan_inl(unsigned long port)
+{
+        if (PXSEG(port))
+                return ctrl_inl(port);
+        else if (is_pci_ioaddr(port))
+                return ctrl_inl(pci_ioaddr(port));
+        else if (port >= 0x2000)
+                return ctrl_inw(port2adr(port));
+        else
+                maybebadio(port);
+        return 0;
+}
+
+void titan_outb(u8 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outb(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outb(value, pci_ioaddr(port));
+        else
+                ctrl_outw(value, port2adr(port));
+}
+
+void titan_outb_p(u8 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outb(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outb(value, pci_ioaddr(port));
+        else
+                ctrl_outw(value, port2adr(port));
+        ctrl_delay();
+}
+
+void titan_outw(u16 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outw(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outw(value, pci_ioaddr(port));
+        else if (port >= 0x2000)
+                ctrl_outw(value, port2adr(port));
+        else
+                maybebadio(port);
+}
+
+void titan_outl(u32 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outl(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outl(value, pci_ioaddr(port));
+        else
+                maybebadio(port);
+}
+
+void titan_insl(unsigned long port, void *dst, unsigned long count)
+{
+        maybebadio(port);
+}
+
+void titan_outsl(unsigned long port, const void *src, unsigned long count)
+{
+        maybebadio(port);
+}
+
+void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
+{
+       if (PXSEG(port) || is_pci_memaddr(port))
+               return (void __iomem *)port;
+       else if (is_pci_ioaddr(port))
+               return (void __iomem *)pci_ioaddr(port);
+
+       return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
new file mode 100644 (file)
index 0000000..52b66d8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *     Setup for Titan
+ */
+
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/titan.h>
+#include <asm/io.h>
+
+extern void __init pcibios_init_platform(void);
+
+static void __init init_titan_irq(void)
+{
+       /* enable individual interrupt mode for externals */
+       ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+
+       make_ipr_irq( TITAN_IRQ_WAN,   IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); /* PCIRQ0 */
+       make_ipr_irq( TITAN_IRQ_LAN,   IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); /* PCIRQ1 */
+       make_ipr_irq( TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); /* PCIRQ2 */
+       make_ipr_irq( TITAN_IRQ_USB,   IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); /* PCIRQ3 */
+}
+
+struct sh_machine_vector mv_titan __initmv = {
+       .mv_name =      "Titan",
+
+       .mv_inb =       titan_inb,
+       .mv_inw =       titan_inw,
+       .mv_inl =       titan_inl,
+       .mv_outb =      titan_outb,
+       .mv_outw =      titan_outw,
+       .mv_outl =      titan_outl,
+
+       .mv_inb_p =     titan_inb_p,
+       .mv_inw_p =     titan_inw,
+       .mv_inl_p =     titan_inl,
+       .mv_outb_p =    titan_outb_p,
+       .mv_outw_p =    titan_outw,
+       .mv_outl_p =    titan_outl,
+
+       .mv_insl =      titan_insl,
+       .mv_outsl =     titan_outsl,
+
+       .mv_ioport_map = titan_ioport_map,
+
+       .mv_init_irq =  init_titan_irq,
+       .mv_init_pci =  pcibios_init_platform,
+};
+ALIAS_MV(titan)
index c5e4ed10876befa7665a83e0ba5f84bc24b792fa..1c941370a2e32a8bc0ea9b55a200dd6907be9a42 100644 (file)
  */
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/irq.h>
 
 struct sh_machine_vector mv_unknown __initmv = {
-       .mv_nr_irqs             = NR_IRQS,
+       .mv_name                = "Unknown",
 };
 ALIAS_MV(unknown)
-
-const char *get_system_type(void)
-{
-       return "Unknown";
-}
-
-void __init platform_setup(void)
-{
-}
-
index 75a6876bf6c6356d3f9f9605c46154211aea82a0..e5f4437900794a66874de91e62a557572f5b0e81 100644 (file)
@@ -18,13 +18,20 @@ endif
 # Assign dummy values if these 2 variables are not defined,
 # in order to suppress error message.
 #
+CONFIG_PAGE_OFFSET     ?= 0x80000000
 CONFIG_MEMORY_START     ?= 0x0c000000
 CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
-IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
+
+IMAGE_OFFSET   := $(shell printf "0x%08x" $$[$(CONFIG_PAGE_OFFSET)  + \
+                                             $(CONFIG_MEMORY_START) + \
+                                             $(CONFIG_BOOT_LINK_OFFSET)])
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 
 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
 
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
        $(call if_changed,ld)
        @:
 
index 155d139884c34f8b440a7cc8a1f2d33567964c06..0582ca8346b697e99a21f24208e2c3c22231fe86 100644 (file)
@@ -65,6 +65,11 @@ config HD64461_IRQ
 
          Do not change this unless you know what you are doing.
 
+config HD64461_IOBASE
+       hex "HD64461 start address"
+       depends on HD64461
+       default "0xb0000000"
+
 config HD64461_ENABLER
        bool "HD64461 PCMCIA enabler"
        depends on HD64461
@@ -73,7 +78,6 @@ config HD64461_ENABLER
          via the HD64461 companion chip.
          Otherwise, say N.
 
-
 config HD64465_IOBASE
        hex "HD64465 start address"
        depends on HD64465
index ac3062671db7ae122001c862e6d5b94f7469a666..7909a1b7b512a57018ffe7a12bcd34d8eb742072 100644 (file)
@@ -1,11 +1,10 @@
 /*
- *     $Id: io.c,v 1.6 2004/03/16 00:07:50 lethal Exp $
  *     Copyright (C) 2000 YAEGASHI Takeshi
  *     Typical I/O routines for HD64461 system.
  */
 
 #include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
 
 #define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)
 
@@ -54,11 +53,6 @@ static __inline__ unsigned long PORT2ADDR(unsigned long port)
        return 0xa0000000 + (port & 0x1fffffff);
 }
 
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 unsigned char hd64461_inb(unsigned long port)
 {
        return *(volatile unsigned char*)PORT2ADDR(port);
@@ -67,7 +61,7 @@ unsigned char hd64461_inb(unsigned long port)
 unsigned char hd64461_inb_p(unsigned long port)
 {
        unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -89,7 +83,7 @@ void hd64461_outb(unsigned char b, unsigned long port)
 void hd64461_outb_p(unsigned char b, unsigned long port)
 {
        *(volatile unsigned char*)PORT2ADDR(port) = b;
-       delay();
+       ctrl_delay();
 }
 
 void hd64461_outw(unsigned short b, unsigned long port)
@@ -144,13 +138,13 @@ void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
        while(count--) *addr=*buf++;
 }
 
-unsigned short hd64461_readw(unsigned long addr)
+unsigned short hd64461_readw(void __iomem *addr)
 {
-       return *(volatile unsigned short*)(MEM_BASE+addr);
+       return ctrl_inw(MEM_BASE+(unsigned long __force)addr);
 }
 
-void hd64461_writew(unsigned short b, unsigned long addr)
+void hd64461_writew(unsigned short b, void __iomem *addr)
 {
-       *(volatile unsigned short*)(MEM_BASE+addr) = b;
+       ctrl_outw(b, MEM_BASE+(unsigned long __force)addr);
 }
 
index ad126016720ff227438c356b0a2398a2564756fe..38f1e8171a3abbf361ac628e2b1f63c24c4b9f92 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
-
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
 
 static void disable_hd64461_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64461_IRQBASE);
 
-       local_irq_save(flags);
        nimr = inw(HD64461_NIMR);
        nimr |= mask;
        outw(nimr, HD64461_NIMR);
-       local_irq_restore(flags);
 }
 
 static void enable_hd64461_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64461_IRQBASE);
 
-       local_irq_save(flags);
        nimr = inw(HD64461_NIMR);
        nimr &= ~mask;
        outw(nimr, HD64461_NIMR);
-       local_irq_restore(flags);
 }
 
 static void mask_and_ack_hd64461(unsigned int irq)
index d2b2851bc44bcf702ba21c35ca282841401b2b02..30573d3e1966717c46c420703972166625cb785f 100644 (file)
 
 static void disable_hd64465_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
 
        pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
-       local_irq_save(flags);
        nimr = inw(HD64465_REG_NIMR);
        nimr |= mask;
        outw(nimr, HD64465_REG_NIMR);
-       local_irq_restore(flags);
 }
 
 
 static void enable_hd64465_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
 
        pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
-       local_irq_save(flags);
        nimr = inw(HD64465_REG_NIMR);
        nimr &= ~mask;
        outw(nimr, HD64465_REG_NIMR);
-       local_irq_restore(flags);
 }
 
 
index 0dc1fb8f9687626a71d6e1905bd52dc049c9e1a3..392c8b12ce36789dea7dbe0b8b3a25084f49371b 100644 (file)
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
-#include <asm/rts7751r2d/voyagergx_reg.h>
+#include <asm/voyagergx.h>
 
 static void disable_voyagergx_irq(unsigned int irq)
 {
-       unsigned long flags, val;
-       unsigned long  mask = 1 << (irq - VOYAGER_IRQ_BASE);
+       unsigned long val;
+       unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
        pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
-       local_irq_save(flags);
         val = inl(VOYAGER_INT_MASK);
         val &= ~mask;
         outl(val, VOYAGER_INT_MASK);
-       local_irq_restore(flags);
 }
 
-
 static void enable_voyagergx_irq(unsigned int irq)
 {
-        unsigned long flags, val;
-        unsigned long  mask = 1 << (irq - VOYAGER_IRQ_BASE);
+        unsigned long val;
+        unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
 
         pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
-        local_irq_save(flags);
         val = inl(VOYAGER_INT_MASK);
         val |= mask;
         outl(val, VOYAGER_INT_MASK);
-        local_irq_restore(flags);
 }
 
-
 static void mask_and_ack_voyagergx(unsigned int irq)
 {
        disable_voyagergx_irq(irq);
@@ -95,7 +88,8 @@ static struct hw_interrupt_type voyagergx_irq_type = {
        .end = end_voyagergx_irq,
 };
 
-static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t voyagergx_interrupt(int irq, void *dev_id,
+                                     struct pt_regs *regs)
 {
        printk(KERN_INFO
               "VoyagerGX: spurious interrupt, status: 0x%x\n",
@@ -103,9 +97,6 @@ static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *re
        return IRQ_HANDLED;
 }
 
-
-/*====================================================*/
-
 static struct {
        int (*func)(int, void *);
        void *dev;
index 139ca88ac9e6217709783ca84f629cb3975c4ec6..66b2fedd7ad9308c53648116d56c317a15c3b533 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <asm/io.h>
-#include <asm/rts7751r2d/voyagergx_reg.h>
+#include <asm/voyagergx.h>
 
 static int __init setup_voyagergx(void)
 {
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
new file mode 100644 (file)
index 0000000..6b43316
--- /dev/null
@@ -0,0 +1,1373 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-sh
+# Sun Sep 11 13:00:46 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+CONFIG_SH_LANDISK=y
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Kernel features
+#
+CONFIG_KEXEC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# 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=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+# CONFIG_IP_NF_MATCH_CONNBYTES is not set
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+# CONFIG_IP_NF_MATCH_STRING is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+# CONFIG_IP_NF_TARGET_NFQUEUE is not set
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_TARGET_CONNMARK=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_IDEDMA_ONLYDISK=y
+CONFIG_BLK_DEV_AEC62XX=y
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_SH=y
+# 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=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X 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_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM 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
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# 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_SMC91X 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 is not set
+# CONFIG_NE2000 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
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA 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
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+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_RTC is not set
+CONFIG_RS5C313_RTC=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C 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_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_OBSOLETE_OSS_USB_DRIVER=y
+CONFIG_USB_AUDIO=m
+# CONFIG_USB_BLUETOOTH_TTY is not set
+CONFIG_USB_MIDI=m
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+# CONFIG_USB_STORAGE_USBAT is not set
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# 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
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_PWC=m
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# 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_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_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=m
+CONFIG_UFS_FS_WRITE=y
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+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=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT 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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig
new file mode 100644 (file)
index 0000000..d597fc5
--- /dev/null
@@ -0,0 +1,1099 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-sh
+# Sat Jan  7 19:47:53 2006
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R77703DRP is not set
+CONFIG_SH_R7780RP=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_32BIT=y
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_FPU=y
+CONFIG_SH_STORE_QUEUES=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=32000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=6
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+CONFIG_PREEMPT=y
+# CONFIG_SMP is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="mem=128M console=ttySC0,115200 root=/dev/hda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# 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=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 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
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# 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=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDE_SATA=y
+CONFIG_BLK_DEV_IDEDISK=m
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=m
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=m
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=m
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=m
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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=m
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX 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
+
+#
+# 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
+
+#
+# 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 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NE2000=y
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# 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
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON 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=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW 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 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+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_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C 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_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=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
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# 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_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=y
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_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=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+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_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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# 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_DES=y
+# 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_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
index d217e44c89a6a4caabc902d1502fe543b20bedfd..fe19feb95ca9a4a918761a23459d284db9c809c6 100644 (file)
@@ -78,6 +78,7 @@ CONFIG_SH_73180_SOLUTION_ENGINE=y
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
 # CONFIG_SH_EDOSK7705 is not set
 # CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig
new file mode 100644 (file)
index 0000000..948e507
--- /dev/null
@@ -0,0 +1,997 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Aug  7 20:14:44 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# 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 is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# 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 is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+CONFIG_SOLUTION_ENGINE=y
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+CONFIG_SH_7343_SOLUTION_ENGINE=y
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+CONFIG_CPU_SUBTYPE_SH7343=y
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_32BIT=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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=27000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+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 is not set
+# 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=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_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# 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_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# 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
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+CONFIG_SMC91X=y
+# CONFIG_NE2000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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=y
+
+#
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SH7343=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# 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
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+
+#
+# Encoders and Decoders
+#
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_CX25840 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_SEQUENCER_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_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SuperH devices
+#
+CONFIG_SH7343_SIU=m
+CONFIG_AK4537_CODEC=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI 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
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# 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 is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS 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=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig
new file mode 100644 (file)
index 0000000..ec9a303
--- /dev/null
@@ -0,0 +1,913 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Aug  7 17:07:06 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# 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 is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# 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 is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+CONFIG_SH_7710VOIPGW=y
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7710=y
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00800000
+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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=32768000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE 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_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_IRC is not set
+# CONFIG_IP_NF_NETBIOS_NS is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_QUEUE 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=y
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=y
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_NET_CLS_FW is not set
+CONFIG_NET_CLS_U32=y
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+CONFIG_MTD_SH7710VOIPGW=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# 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_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# 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
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NE2000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK 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
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI 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
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# 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 is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS 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 is not set
+# CONFIG_NFSD 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/shmin_defconfig b/arch/sh/configs/shmin_defconfig
new file mode 100644 (file)
index 0000000..382b3bd
--- /dev/null
@@ -0,0 +1,827 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Wed Aug  2 01:45:03 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PTRACE=y
+
+#
+# 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 is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_UID16 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+# CONFIG_SLAB is not set
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7709_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+CONFIG_SH_SHMIN=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+CONFIG_CPU_SUBTYPE_SH7706=y
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00800000
+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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=32000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00210000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200 root=1f01 mtdparts=phys_mapped_flash:64k(firm)ro,-(sys) netdev=34,0x300,eth0 "
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET 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 is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xa0000000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# 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_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# 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
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+CONFIG_NE2000=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=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_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK 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
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI 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
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# 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 is not set
+# CONFIG_SYSFS is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS is not set
+# CONFIG_JFFS2_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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_UNWIND_INFO is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
new file mode 100644 (file)
index 0000000..1db2904
--- /dev/null
@@ -0,0 +1,1367 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-sh
+# Wed Nov  9 00:35:56 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+CONFIG_SH_TITAN=y
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08030000
+CONFIG_MEMORY_SIZE=0x7fd0000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=30000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=8
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x009e0000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+#CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=m
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_DRR=m
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_TARGET_NFQUEUE=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_NFQUEUE=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+# CONFIG_NET_ACT_SIMP 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_SSFDC=y
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# SCSI low-level drivers
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX 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
+
+#
+# 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
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_CASSINI=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NE2000 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_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+CONFIG_8139_OLD_RX_RESET=y
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# 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
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+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_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# 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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+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
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID 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
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+
+#
+# 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=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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=m
+# CONFIG_SMB_NLS_DEFAULT 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=m
+
+#
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
index 0f15216cd39dea589d2c165739d6b1d5fae6ae15..defc13c37d483c3d4b064f1035609546ba3d4633 100644 (file)
@@ -11,6 +11,8 @@ config SH_DMA
 config NR_ONCHIP_DMA_CHANNELS
        depends on SH_DMA
        int "Number of on-chip DMAC channels"
+       default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
+       default "12" if CPU_SUBTYPE_SH7780
        default "4"
        help
          This allows you to specify the number of channels that the on-chip
@@ -52,4 +54,3 @@ config DMA_PAGE_OPS_CHANNEL
          are dual-address capable.
 
 endmenu
-
index 0f866f8789f0de6e4338fab51cb40490290ed055..9cb0709241808b6365e1a024f048722cbffb8a94 100644 (file)
@@ -3,7 +3,7 @@
  *
  * G2 bus DMA support
  *
- * Copyright (C) 2003, 2004  Paul Mundt
+ * 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
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-
+#include <asm/cacheflush.h>
 #include <asm/mach/sysasic.h>
 #include <asm/mach/dma.h>
 #include <asm/dma.h>
@@ -47,17 +47,31 @@ struct g2_dma_info {
 
 static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800;
 
+#define g2_bytes_remaining(i) \
+       ((g2_dma->channel[i].size - \
+         g2_dma->status[i].size) & 0x0fffffff)
+
 static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       /* FIXME: Do some meaningful completion work here.. */
-       return IRQ_HANDLED;
-}
+       int i;
 
-static struct irqaction g2_dma_irq = {
-       .name           = "g2 DMA handler",
-       .handler        = g2_dma_interrupt,
-       .flags          = IRQF_DISABLED,
-};
+       for (i = 0; i < G2_NR_DMA_CHANNELS; i++) {
+               if (g2_dma->status[i].status & 0x20000000) {
+                       unsigned int bytes = g2_bytes_remaining(i);
+
+                       if (likely(bytes == 0)) {
+                               struct dma_info *info = dev_id;
+                               struct dma_channel *chan = info->channels + i;
+
+                               wake_up(&chan->wait_queue);
+
+                               return IRQ_HANDLED;
+                       }
+               }
+       }
+
+       return IRQ_NONE;
+}
 
 static int g2_enable_dma(struct dma_channel *chan)
 {
@@ -135,8 +149,14 @@ static int g2_xfer_dma(struct dma_channel *chan)
        return 0;
 }
 
+static int g2_get_residue(struct dma_channel *chan)
+{
+       return g2_bytes_remaining(chan->chan);
+}
+
 static struct dma_ops g2_dma_ops = {
        .xfer           = g2_xfer_dma,
+       .get_residue    = g2_get_residue,
 };
 
 static struct dma_info g2_dma_info = {
@@ -148,13 +168,22 @@ static struct dma_info g2_dma_info = {
 
 static int __init g2_dma_init(void)
 {
-       setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq);
+       int ret;
+
+       ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+                         "g2 DMA handler", &g2_dma_info);
+       if (unlikely(ret))
+               return -EINVAL;
 
        /* Magic */
        g2_dma->wait_state      = 27;
        g2_dma->magic           = 0x4659404f;
 
-       return register_dmac(&g2_dma_info);
+       ret = register_dmac(&g2_dma_info);
+       if (unlikely(ret != 0))
+               free_irq(HW_EVENT_G2_DMA, 0);
+
+       return ret;
 }
 
 static void __exit g2_dma_exit(void)
@@ -169,4 +198,3 @@ module_exit(g2_dma_exit);
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("G2 bus DMA driver");
 MODULE_LICENSE("GPL");
-
index 30a580aa7cbd04d81f7396616415c1bee24ac91e..3b0b0f60bb3c4293af34c9a6b0f9e610b6c71af6 100644 (file)
@@ -18,8 +18,8 @@
 #include <asm/dma.h>
 #include <asm/io.h>
 
-static unsigned int xfer_complete = 0;
-static int count = 0;
+static unsigned int xfer_complete;
+static int count;
 
 static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -107,4 +107,3 @@ module_exit(pvr2_dma_exit);
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
 MODULE_LICENSE("GPL");
-
index e028a2d2a4eac949d362f1fa7bfec19dc722896d..cbbe8bce3d679fd7d5b77e4f40363fd314dc3dee 100644 (file)
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <asm/dreamcast/dma.h>
-#include <asm/signal.h>
-#include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include "dma-sh.h"
@@ -84,18 +80,23 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
 
 static int sh_dmac_request_dma(struct dma_channel *chan)
 {
-       char name[32];
+       if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
+               return 0;
 
-       snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)",
+       chan->name = kzalloc(32, GFP_KERNEL);
+       if (unlikely(chan->name == NULL))
+               return -ENOMEM;
+       snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)",
                 chan->chan);
 
        return request_irq(get_dmte_irq(chan->chan), dma_tei,
-                          IRQF_DISABLED, name, chan);
+                          IRQF_DISABLED, chan->name, chan);
 }
 
 static void sh_dmac_free_dma(struct dma_channel *chan)
 {
        free_irq(get_dmte_irq(chan->chan), chan);
+       kfree(chan->name);
 }
 
 static void
@@ -259,7 +260,7 @@ static int __init sh_dmac_init(void)
 #ifdef CONFIG_CPU_SH4
        make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
        i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
-       if (i < 0)
+       if (unlikely(i < 0))
                return i;
 #endif
 
@@ -274,7 +275,7 @@ static int __init sh_dmac_init(void)
         * been set.
         */
        i = dmaor_reset();
-       if (i < 0)
+       if (unlikely(i != 0))
                return i;
 
        return register_dmac(info);
index 365bc16a4a83baee91b0dcbeb0ae9c08776e6336..9e00cb8a39e90365f8745d42f76cae5e2b24d411 100644 (file)
@@ -6,7 +6,8 @@ obj-y                                   += pci.o
 obj-$(CONFIG_PCI_AUTO)                 += pci-auto.o
 
 obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)     += pci-st40.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += pci-sh7751.o 
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += pci-sh7751.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += pci-sh7780.o ops-sh4.o
 
 obj-$(CONFIG_SH_DREAMCAST)             += ops-dreamcast.o fixups-dreamcast.o \
                                           dma-dreamcast.o
@@ -14,3 +15,6 @@ obj-$(CONFIG_SH_SECUREEDGE5410)               += ops-snapgear.o
 obj-$(CONFIG_SH_BIGSUR)                        += ops-bigsur.o
 obj-$(CONFIG_SH_RTS7751R2D)            += ops-rts7751r2d.o fixups-rts7751r2d.o
 obj-$(CONFIG_SH_SH03)                  += ops-sh03.o fixups-sh03.o
+obj-$(CONFIG_SH_R7780RP)               += ops-r7780rp.o fixups-r7780rp.o
+obj-$(CONFIG_SH_TITAN)                 += ops-titan.o
+obj-$(CONFIG_SH_LANDISK)               += ops-landisk.o
index 63b1c6f4b8d255e71fd787b3cc0a1759bb3f6c98..c0af5f7ef4142175cfb1c863827f4b9bbc0e550e 100644 (file)
@@ -4,7 +4,7 @@
  * PCI fixups for the Sega Dreamcast
  *
  * Copyright (C) 2001, 2002  M. R. Brown
- * Copyright (C) 2002, 2003  Paul Mundt
+ * Copyright (C) 2002, 2003, 2006  Paul Mundt
  *
  * This file originally bore the message (with enclosed-$):
  *     Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
@@ -45,36 +45,16 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
                printk("PCI: Failed resource fixup\n");
        }
 }
-
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-       /* 
-        * We don't have any sub bus to fix up, and this is a rather
-        * stupid place to put general device fixups. Don't do it.
-        * Use the pcibios_fixups table or suffer the consequences.
+       /*
+        * The interrupt routing semantics here are quite trivial.
+        *
+        * We basically only support one interrupt, so we only bother
+        * updating a device's interrupt line with this single shared
+        * interrupt. Keeps routing quite simple, doesn't it?
         */
+       return GAPSPCI_IRQ;
 }
-
-void __init pcibios_fixup_irqs(void)
-{
-       struct pci_dev *dev = 0;
-
-       for_each_pci_dev(dev) {
-               /*
-                * The interrupt routing semantics here are quite trivial.
-                *
-                * We basically only support one interrupt, so we only bother
-                * updating a device's interrupt line with this single shared
-                * interrupt. Keeps routing quite simple, doesn't it?
-                */
-               printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n",
-                      pci_name(dev));
-
-               dev->irq = GAPSPCI_IRQ;
-
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-       }
-}
-
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
new file mode 100644 (file)
index 0000000..3e321df
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * arch/sh/drivers/pci/fixups-r7780rp.c
+ *
+ * Highlander R7780RP-1 PCI fixups
+ *
+ * Copyright (C) 2003  Lineo uSolutions, Inc.
+ * Copyright (C) 2004 - 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/pci.h>
+#include "pci-sh4.h"
+#include <asm/io.h>
+
+int pci_fixup_pcic(void)
+{
+       pci_write_reg(0x000043ff, SH4_PCIINTM);
+       pci_write_reg(0x0000380f, SH4_PCIAINTM);
+
+       pci_write_reg(0xfbb00047, SH7780_PCICMD);
+       pci_write_reg(0x00000000, SH7780_PCIIBAR);
+
+       pci_write_reg(0x00011912, SH7780_PCISVID);
+       pci_write_reg(0x08000000, SH7780_PCICSCR0);
+       pci_write_reg(0x0000001b, SH7780_PCICSAR0);
+       pci_write_reg(0xfd000000, SH7780_PCICSCR1);
+       pci_write_reg(0x0000000f, SH7780_PCICSAR1);
+
+       pci_write_reg(0xfd000000, SH7780_PCIMBR0);
+       pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+       pci_write_reg(0xc0000000, SH7780_PCIMBR2);
+       pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
+
+       /* Set IOBR for windows containing area specified in pci.h */
+       pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
+                     SH7780_PCIIOBR);
+       pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR);
+
+       return 0;
+}
index 0c590fc7a0812f518499fbc099758a9b397241c1..e72ceb560d5b737b2d822524ceb0d9bce2c4c0e7 100644 (file)
@@ -10,8 +10,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-#include "pci-sh7751.h"
-#include <asm/io.h>
+#include "pci-sh4.h"
 
 #define PCIMCR_MRSET_OFF       0xBFFFFFFF
 #define PCIMCR_RFSH_OFF                0xFFFFFFFB
@@ -22,22 +21,23 @@ int pci_fixup_pcic(void)
 
        bcr1 = inl(SH7751_BCR1);
        bcr1 |= 0x40080000;     /* Enable Bit 19 BREQEN, set PCIC to slave */
-       outl(bcr1, PCI_REG(SH7751_PCIBCR1));
+       pci_write_reg(bcr1, SH4_PCIBCR1);
 
        /* Enable all interrupts, so we known what to fix */
-       outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM));
-       outl(0x0000380f, PCI_REG(SH7751_PCIAINTM));
+       pci_write_reg(0x0000c3ff, SH4_PCIINTM);
+       pci_write_reg(0x0000380f, SH4_PCIAINTM);
 
-       outl(0xfb900047, PCI_REG(SH7751_PCICONF1));
-       outl(0xab000001, PCI_REG(SH7751_PCICONF4));
+       pci_write_reg(0xfb900047, SH7751_PCICONF1);
+       pci_write_reg(0xab000001, SH7751_PCICONF4);
 
        mcr = inl(SH7751_MCR);
        mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
-       outl(mcr, PCI_REG(SH7751_PCIMCR));
+       pci_write_reg(mcr, SH4_PCIMCR);
+
+       pci_write_reg(0x0c000000, SH7751_PCICONF5);
+       pci_write_reg(0xd0000000, SH7751_PCICONF6);
+       pci_write_reg(0x0c000000, SH4_PCILAR0);
+       pci_write_reg(0x00000000, SH4_PCILAR1);
 
-       outl(0x0c000000, PCI_REG(SH7751_PCICONF5));
-       outl(0xd0000000, PCI_REG(SH7751_PCICONF6));
-       outl(0x0c000000, PCI_REG(SH7751_PCILAR0));
-       outl(0x00000000, PCI_REG(SH7751_PCILAR1));
        return 0;
 }
index 57ac26c2171f7f3c20e05da84fa32e6d20a2215c..2e8a18b7ee53e48941bc3671776c01908070e1e0 100644 (file)
@@ -3,11 +3,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-/*
- *     IRQ functions
- */
-
-int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
@@ -17,8 +13,9 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
                case 8: return 5;       /* eth1       */
                case 6: return 2;       /* PCI bridge */
                default:
-                       printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
-                       return 2;
+                       printk(KERN_ERR "PCI: Bad IRQ mapping request "
+                                       "for slot %d\n", slot);
+                       return 2;
                }
        } else {
                switch (pin) {
@@ -32,30 +29,3 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
        }
        return irq;
 }
-
-static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
-       /* no swizzling */
-       return PCI_SLOT(dev->devfn);
-}
-
-static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       int irq = -1;
-
-       /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
-       irq = pcibios_map_platform_irq(slot, pin, dev);
-       if( irq < 0 ) {
-               pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
-               return irq;
-       }
-
-       pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
-       return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-       pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq);
-}
index ae82c6ca05e593932f10d2b5a2ec7dd9a1c81c0c..5da501bd77b56cd281507a2d2c66ea323608b635 100644 (file)
  *
  * PCI initialization for the Hitachi Big Sur Evaluation Board
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-
 #include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
 #include <asm/bigsur/bigsur.h>
 
 #define BIGSUR_PCI_IO  0x4000
@@ -41,11 +38,11 @@ static struct resource sh7751_mem_resource = {
 extern struct pci_ops sh7751_pci_ops;
 
 struct pci_channel board_pci_channels[] = {
-       { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
        { 0, }
 };
 
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
        .window0        = {
                .base   = SH7751_CS3_BASE_ADDR,
                .size   = BIGSUR_LSR0_SIZE,
@@ -58,7 +55,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
 };
 
 /*
- * Initialize the Big Sur PCI interface 
+ * Initialize the Big Sur PCI interface
  * Setup hardware to be Central Funtion
  * Copy the BSR regs to the PCI interface
  * Setup PCI windows into local RAM
@@ -68,15 +65,15 @@ int __init pcibios_init_platform(void)
        return sh7751_pcic_init(&sh7751_pci_map);
 }
 
-int pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
-       /* 
+       /*
         * The Big Sur can be used in a CPCI chassis, but the SH7751 PCI
         * interface is on the wrong end of the board so that it can also
         * support a V320 CPI interface chip...  Therefor the IRQ mapping is
         * somewhat use dependent... I'l assume a linear map for now, i.e.
         * INTA=slot0,pin0... INTD=slot3,pin0...
-        */ 
+        */
        int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE;
 
        PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n",
@@ -84,4 +81,3 @@ int pcibios_map_platform_irq(u8 slot, u8 pin)
 
        return irq;
 }
-
diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/ops-landisk.c
new file mode 100644 (file)
index 0000000..ada301c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/drivers/pci/ops-landisk.c
+ *
+ * PCI initialization for the I-O DATA Device, Inc. LANDISK board
+ *
+ * Copyright (C) 2006 kogiidena
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+static struct resource sh7751_io_resource = {
+       .name = "SH7751 IO",
+       .start = 0x4000,
+       .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+       .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+       .name = "SH7751 mem",
+       .start = SH7751_PCI_MEMORY_BASE,
+       .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+       .flags = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+       {&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff},
+       {NULL, NULL, NULL, 0, 0},
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+       .window0 = {
+               .base   = SH7751_CS3_BASE_ADDR,
+               .size   = (64 << 20),   /* 64MB */
+       },
+
+       .flags = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7751_pcic_init(&sh7751_pci_map);
+}
+
+int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       /*
+        * slot0: pin1-4 = irq5,6,7,8
+        * slot1: pin1-4 = irq6,7,8,5
+        * slot2: pin1-4 = irq7,8,5,6
+        * slot3: pin1-4 = irq8,5,6,7
+        */
+       int irq = ((slot + pin - 1) & 0x3) + 5;
+
+       if ((slot | (pin - 1)) > 0x3) {
+               printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
+                      slot, pin - 1 + 'A');
+               return -1;
+       }
+       return irq;
+}
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
new file mode 100644 (file)
index 0000000..554d5ed
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Author:  Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+        switch (slot) {
+       case 0: return IRQ_PCISLOT1;            /* PCI Interrupt #1 */
+       case 1: return IRQ_PCISLOT2;            /* PCI Interrupt #2 */
+       case 2: return IRQ_PCISLOT3;            /* PCI Interrupt #3 */
+       case 3: return IRQ_PCISLOT4;            /* PCI Interrupt E4 */
+       default:
+               printk(KERN_ERR "PCI: Bad IRQ mapping "
+                      "request for slot %d, func %d\n", slot, pin-1);
+               return -1;
+       }
+}
+
+static struct resource sh7780_io_resource = {
+       .name   = "SH7780_IO",
+       .start  = 0x2000,
+       .end    = 0x2000 + SH7780_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource sh7780_mem_resource = {
+       .name   = "SH7780_mem",
+       .start  = SH7780_PCI_MEMORY_BASE,
+       .end    = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7780_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7780_pci_map = {
+       .window0        = {
+               .base   = SH7780_CS2_BASE_ADDR,
+               .size   = 0x04000000,
+       },
+
+       .window1        = {
+               .base   = SH7780_CS3_BASE_ADDR,
+               .size   = 0x04000000,
+       },
+
+       .flags  = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7780_pcic_init(&sh7780_pci_map);
+}
index 83171d10141ac5223d1f991ef2fc3c5091695415..88f44e2454244f355d3911753798c324389fecb7 100644 (file)
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/module.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
 #include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
         switch (slot) {
        case 0: return IRQ_PCISLOT1;    /* PCI Extend slot #1 */
@@ -52,12 +51,12 @@ static struct resource sh7751_mem_resource = {
 extern struct pci_ops sh7751_pci_ops;
 
 struct pci_channel board_pci_channels[] = {
-       { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
        { NULL, NULL, NULL, 0, 0 },
 };
 EXPORT_SYMBOL(board_pci_channels);
 
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
        .window0        = {
                .base   = SH7751_CS3_BASE_ADDR,
                .size   = 0x04000000,
@@ -68,7 +67,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
                .size   = 0x00000000,   /* Unused */
        },
 
-       .flags  = SH7751_PCIC_NO_RESET,
+       .flags  = SH4_PCIC_NO_RESET,
 };
 
 int __init pcibios_init_platform(void)
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
new file mode 100644 (file)
index 0000000..2d43710
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
+ *
+ * Copyright (C) 2002 - 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/pci.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+/*
+ * Direct access to PCI hardware...
+ */
+#define CONFIG_CMD(bus, devfn, where) \
+       P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static DEFINE_SPINLOCK(sh4_pci_lock);
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
+                          int where, int size, u32 *val)
+{
+       unsigned long flags;
+       u32 data;
+
+       /*
+        * PCIPDR may only be accessed as 32 bit words,
+        * so we must do byte alignment by hand
+        */
+       spin_lock_irqsave(&sh4_pci_lock, flags);
+       pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+       data = pci_read_reg(SH4_PCIPDR);
+       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+
+       switch (size) {
+       case 1:
+               *val = (data >> ((where & 3) << 3)) & 0xff;
+               break;
+       case 2:
+               *val = (data >> ((where & 2) << 3)) & 0xffff;
+               break;
+       case 4:
+               *val = data;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Since SH4 only does 32bit access we'll have to do a read,
+ * mask,write operation.
+ * We'll allow an odd byte offset, though it should be illegal.
+ */
+static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
+                        int where, int size, u32 val)
+{
+       unsigned long flags;
+       int shift;
+       u32 data;
+
+       spin_lock_irqsave(&sh4_pci_lock, flags);
+       pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+       data = pci_read_reg(SH4_PCIPDR);
+       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+
+       switch (size) {
+       case 1:
+               shift = (where & 3) << 3;
+               data &= ~(0xff << shift);
+               data |= ((val & 0xff) << shift);
+               break;
+       case 2:
+               shift = (where & 2) << 3;
+               data &= ~(0xffff << shift);
+               data |= ((val & 0xffff) << shift);
+               break;
+       case 4:
+               data = val;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       pci_write_reg(data, SH4_PCIPDR);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sh4_pci_ops = {
+       .read           = sh4_pci_read,
+       .write          = sh4_pci_write,
+};
+
+/*
+ * Not really related to pci_ops, but it's common and not worth shoving
+ * somewhere else for now..
+ */
+static unsigned int pci_probe = PCI_PROBE_CONF1;
+
+int __init sh4_pci_check_direct(void)
+{
+       /*
+        * Check if configuration works.
+        */
+       if (pci_probe & PCI_PROBE_CONF1) {
+               unsigned int tmp = pci_read_reg(SH4_PCIPAR);
+
+               pci_write_reg(P1SEG, SH4_PCIPAR);
+
+               if (pci_read_reg(SH4_PCIPAR) == P1SEG) {
+                       pci_write_reg(tmp, SH4_PCIPAR);
+                       printk(KERN_INFO "PCI: Using configuration type 1\n");
+                       request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1");
+
+                       return 0;
+               }
+
+               pci_write_reg(tmp, SH4_PCIPAR);
+       }
+
+       pr_debug("PCI: pci_check_direct failed\n");
+       return -EINVAL;
+}
+
+/* Handle generic fixups */
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+       int i;
+
+       /*
+        * PCI IDE controllers use non-standard I/O port decoding, respect it.
+        */
+       if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+               return;
+       pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
+       for(i = 0; i < 4; i++) {
+               struct resource *r = &d->resource[i];
+
+               if ((r->start & ~0x80) == 0x374) {
+                       r->start |= 2;
+                       r->end = r->start;
+               }
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+char * __init pcibios_setup(char *str)
+{
+       if (!strcmp(str, "off")) {
+               pci_probe = 0;
+               return NULL;
+       }
+
+       return str;
+}
index 3cbd14dd28fe709a71e0fc7d5655d72cde034147..53dd893d4e549feddec846c29d8408ab7e865e47 100644 (file)
@@ -2,7 +2,7 @@
  * arch/sh/drivers/pci/ops-snapgear.c
  *
  * Author:  David McCullough <davidm@snapgear.com>
- * 
+ *
  * Ported to new API by Paul Mundt <lethal@linux-sh.org>
  *
  * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
  *
  * PCI initialization for the SnapGear boards
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
 
 #define SNAPGEAR_PCI_IO                0x4000
 #define SNAPGEAR_PCI_MEM       0xfd000000
@@ -43,14 +39,12 @@ static struct resource sh7751_mem_resource = {
        .flags          = IORESOURCE_MEM,
 };
 
-extern struct pci_ops sh7751_pci_ops;
-
 struct pci_channel board_pci_channels[] = {
-       { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
        { 0, }
 };
 
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
        .window0        = {
                .base   = SH7751_CS2_BASE_ADDR,
                .size   = SNAPGEAR_LSR0_SIZE,
@@ -61,11 +55,11 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
                .size   = SNAPGEAR_LSR1_SIZE,
        },
 
-       .flags  = SH7751_PCIC_NO_RESET,
+       .flags  = SH4_PCIC_NO_RESET,
 };
 
 /*
- * Initialize the SnapGear PCI interface 
+ * Initialize the SnapGear PCI interface
  * Setup hardware to be Central Funtion
  * Copy the BSR regs to the PCI interface
  * Setup PCI windows into local RAM
@@ -75,7 +69,7 @@ int __init pcibios_init_platform(void)
        return sh7751_pcic_init(&sh7751_pci_map);
 }
 
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
        int irq = -1;
 
@@ -98,4 +92,3 @@ void __init pcibios_fixup(void)
 {
        /* Nothing to fixup .. */
 }
-
diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c
new file mode 100644 (file)
index 0000000..c6097bc
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * arch/sh/drivers/pci/ops-titan.c
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Modified from ops-snapgear.c written by  David McCullough
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Titan boards
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/titan.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       int irq = -1;
+
+       switch (slot) {
+       case 0: irq = TITAN_IRQ_WAN;   break;   /* eth0 (WAN) */
+       case 1: irq = TITAN_IRQ_LAN;   break;   /* eth1 (LAN) */
+       case 2: irq = TITAN_IRQ_MPCIA; break;   /* mPCI A */
+       case 3: irq = TITAN_IRQ_MPCIB; break;   /* mPCI B */
+       case 4: irq = TITAN_IRQ_USB;   break;   /* USB */
+       default:
+               printk(KERN_INFO "PCI: Bad IRQ mapping "
+                                "request for slot %d\n", slot);
+               return -1;
+       }
+
+       printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
+               slot, pin - 1 + 'A', irq);
+
+       return irq;
+}
+
+static struct resource sh7751_io_resource = {
+       .name   = "SH7751_IO",
+       .start  = SH7751_PCI_IO_BASE,
+       .end    = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+       .name   = "SH7751_mem",
+       .start  = SH7751_PCI_MEMORY_BASE,
+       .end    = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+       .window0        = {
+               .base   = SH7751_CS2_BASE_ADDR,
+               .size   = SH7751_MEM_REGION_SIZE*2,     /* cs2 and cs3 */
+       },
+
+       .window1        = {
+               .base   = SH7751_CS2_BASE_ADDR,
+               .size   = SH7751_MEM_REGION_SIZE*2,
+       },
+
+       .flags  = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7751_pcic_init(&sh7751_pci_map);
+}
index 4cef4d1d8c841bedf4dc794140e68728f245b047..ecf16344f94a7347ea389e6dca256d6045787012 100644 (file)
 #include <linux/types.h>
 #include <linux/pci.h>
 
-#undef DEBUG
-#ifdef         DEBUG
+#define        DEBUG
+#ifdef DEBUG
 #define        DBG(x...)       printk(x)
 #else
-#define        DBG(x...)       
+#define        DBG(x...)
 #endif
 
 /*
@@ -102,7 +102,7 @@ static u32 pciauto_upper_iospc;
 static u32 pciauto_lower_memspc;
 static u32 pciauto_upper_memspc;
 
-static void __init 
+static void __init
 pciauto_setup_bars(struct pci_channel *hose,
                   int top_bus,
                   int current_bus,
@@ -116,7 +116,6 @@ pciauto_setup_bars(struct pci_channel *hose,
        int found_mem64 = 0;
 
        for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
                u32 bar_addr;
 
                /* Read the old BAR value */
@@ -125,7 +124,6 @@ pciauto_setup_bars(struct pci_channel *hose,
                                        pci_devfn,
                                        bar,
                                        &bar_addr);
-#endif
 
                /* Tickle the BAR and get the response */
                early_write_config_dword(hose, top_bus,
@@ -140,8 +138,7 @@ pciauto_setup_bars(struct pci_channel *hose,
                                        bar,
                                        &bar_response);
 
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
-               /* 
+               /*
                 * Write the old BAR value back out, only update the BAR
                 * if we implicitly want resources to be updated, which
                 * is done by the generic code further down. -- PFM.
@@ -151,7 +148,6 @@ pciauto_setup_bars(struct pci_channel *hose,
                                         pci_devfn,
                                         bar,
                                         bar_addr);
-#endif
 
                /* If BAR is not implemented go to the next BAR */
                if (!bar_response)
@@ -177,7 +173,7 @@ retry:
                            PCI_BASE_ADDRESS_MEM_TYPE_64)
                                found_mem64 = 1;
 
-                       addr_mask = PCI_BASE_ADDRESS_MEM_MASK;          
+                       addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
                        upper_limit = &pciauto_upper_memspc;
                        lower_limit = &pciauto_lower_memspc;
                        DBG("        Mem");
@@ -193,22 +189,22 @@ retry:
                if ((bar_value + bar_size) > *upper_limit) {
                        if (bar_response & PCI_BASE_ADDRESS_SPACE) {
                                if (io_resource_inuse->child) {
-                                       io_resource_inuse = 
+                                       io_resource_inuse =
                                                io_resource_inuse->child;
-                                       pciauto_lower_iospc = 
+                                       pciauto_lower_iospc =
                                                io_resource_inuse->start;
-                                       pciauto_upper_iospc = 
+                                       pciauto_upper_iospc =
                                                io_resource_inuse->end + 1;
                                        goto retry;
                                }
 
                        } else {
                                if (mem_resource_inuse->child) {
-                                       mem_resource_inuse = 
+                                       mem_resource_inuse =
                                                mem_resource_inuse->child;
-                                       pciauto_lower_memspc = 
+                                       pciauto_lower_memspc =
                                                mem_resource_inuse->start;
-                                       pciauto_upper_memspc = 
+                                       pciauto_upper_memspc =
                                                mem_resource_inuse->end + 1;
                                        goto retry;
                                }
@@ -230,7 +226,7 @@ retry:
                 * If we are a 64-bit decoder then increment to the
                 * upper 32 bits of the bar and force it to locate
                 * in the lower 4GB of memory.
-                */ 
+                */
                if (found_mem64) {
                        bar += 4;
                        early_write_config_dword(hose, top_bus,
@@ -362,7 +358,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
 {
        u32 temp;
 
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
        /*
         * [jsun] we always bump up baselines a little, so that if there
         * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
@@ -370,7 +365,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
         */
        pciauto_lower_memspc += 1;
        pciauto_lower_iospc += 1;
-#endif
 
        /*
         * Configure subordinate bus number.  The PCI subsystem
@@ -396,11 +390,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
         * configured by this routine to happily live behind a
         * P2P bridge in a system.
         */
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
-       pciauto_lower_memspc += 0x00400000;
-       pciauto_lower_iospc += 0x00004000;
-#endif
-
        /* Align memory and I/O to 4KB and 4 byte boundaries. */
        pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
                & ~(0x1000 - 1);
@@ -433,12 +422,12 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
        int devfn_stop = 0xff;
 
        sub_bus = current_bus;
-       
+
        if (hose->first_devfn)
                devfn_start = hose->first_devfn;
        if (hose->last_devfn)
                devfn_stop = hose->last_devfn;
-       
+
        for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
 
                if (PCI_FUNC(pci_devfn) && !found_multi)
@@ -471,9 +460,6 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
                if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
                        DBG("        Bridge: primary=%.2x, secondary=%.2x\n",
                                current_bus, sub_bus + 1);
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
-                       pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
-#endif
                        pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
                                                     pci_devfn, sub_bus);
                        DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
@@ -490,10 +476,10 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
                        DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
                        /* Place CardBus Socket/ExCA registers */
                        pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
+
                        pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
                                        current_bus, pci_devfn, sub_bus);
+
                        DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
                                sub_bus + 1,
                                pciauto_lower_iospc, pciauto_lower_memspc);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
new file mode 100644 (file)
index 0000000..5a61d60
--- /dev/null
@@ -0,0 +1,180 @@
+#ifndef __PCI_SH4_H
+#define __PCI_SH4_H
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#include "pci-sh7780.h"
+#else
+#include "pci-sh7751.h"
+#endif
+
+#include <asm/io.h>
+
+/* startup values */
+#define PCI_PROBE_BIOS         1
+#define PCI_PROBE_CONF1                2
+#define PCI_PROBE_CONF2                4
+#define PCI_NO_SORT            0x100
+#define PCI_BIOS_SORT          0x200
+#define PCI_NO_CHECKS          0x400
+#define PCI_ASSIGN_ROMS                0x1000
+#define PCI_BIOS_IRQ_SCAN      0x2000
+
+#define SH4_PCICR              0x100           /* PCI Control Register */
+  #define SH4_PCICR_PREFIX       0xA5000000    /* CR prefix for write */
+  #define SH4_PCICR_FTO                  0x00000400    /* TRDY/IRDY Enable */
+  #define SH4_PCICR_TRSB         0x00000200    /* Target Read Single */
+  #define SH4_PCICR_BSWP         0x00000100    /* Target Byte Swap */
+  #define SH4_PCICR_PLUP         0x00000080    /* Enable PCI Pullup */
+  #define SH4_PCICR_ARBM         0x00000040    /* PCI Arbitration Mode */
+  #define SH4_PCICR_MD           0x00000030    /* MD9 and MD10 status */
+  #define SH4_PCICR_SERR         0x00000008    /* SERR output assert */
+  #define SH4_PCICR_INTA         0x00000004    /* INTA output assert */
+  #define SH4_PCICR_PRST         0x00000002    /* PCI Reset Assert */
+  #define SH4_PCICR_CFIN         0x00000001    /* Central Fun. Init Done */
+#define SH4_PCILSR0            0x104           /* PCI Local Space Register0 */
+#define SH4_PCILSR1            0x108           /* PCI Local Space Register1 */
+#define SH4_PCILAR0            0x10C           /* PCI Local Addr Register1 */
+#define SH4_PCILAR1            0x110           /* PCI Local Addr Register1 */
+#define SH4_PCIINT             0x114           /* PCI Interrupt Register */
+  #define SH4_PCIINT_MLCK        0x00008000    /* Master Lock Error */
+  #define SH4_PCIINT_TABT        0x00004000    /* Target Abort Error */
+  #define SH4_PCIINT_TRET        0x00000200    /* Target Retry Error */
+  #define SH4_PCIINT_MFDE        0x00000100    /* Master Func. Disable Error */
+  #define SH4_PCIINT_PRTY        0x00000080    /* Address Parity Error */
+  #define SH4_PCIINT_SERR        0x00000040    /* SERR Detection Error */
+  #define SH4_PCIINT_TWDP        0x00000020    /* Tgt. Write Parity Error */
+  #define SH4_PCIINT_TRDP        0x00000010    /* Tgt. Read Parity Err Det. */
+  #define SH4_PCIINT_MTABT       0x00000008    /* Master-Tgt. Abort Error */
+  #define SH4_PCIINT_MMABT       0x00000004    /* Master-Master Abort Error */
+  #define SH4_PCIINT_MWPD        0x00000002    /* Master Write PERR Detect */
+  #define SH4_PCIINT_MRPD        0x00000001    /* Master Read PERR Detect */
+#define SH4_PCIINTM            0x118           /* PCI Interrupt Mask */
+#define SH4_PCIALR             0x11C           /* Error Address Register */
+#define SH4_PCICLR             0x120           /* Error Command/Data */
+  #define SH4_PCICLR_MPIO        0x80000000
+  #define SH4_PCICLR_MDMA0       0x40000000    /* DMA0 Transfer Error */
+  #define SH4_PCICLR_MDMA1       0x20000000    /* DMA1 Transfer Error */
+  #define SH4_PCICLR_MDMA2       0x10000000    /* DMA2 Transfer Error */
+  #define SH4_PCICLR_MDMA3       0x08000000    /* DMA3 Transfer Error */
+  #define SH4_PCICLR_TGT         0x04000000    /* Target Transfer Error */
+  #define SH4_PCICLR_CMDL        0x0000000F    /* PCI Command at Error */
+#define SH4_PCIAINT            0x130           /* Arbiter Interrupt Register */
+  #define SH4_PCIAINT_MBKN       0x00002000    /* Master Broken Interrupt */
+  #define SH4_PCIAINT_TBTO       0x00001000    /* Target Bus Time Out */
+  #define SH4_PCIAINT_MBTO       0x00001000    /* Master Bus Time Out */
+  #define SH4_PCIAINT_TABT       0x00000008    /* Target Abort */
+  #define SH4_PCIAINT_MABT       0x00000004    /* Master Abort */
+  #define SH4_PCIAINT_RDPE       0x00000002    /* Read Data Parity Error */
+  #define SH4_PCIAINT_WDPE       0x00000001    /* Write Data Parity Error */
+#define SH4_PCIAINTM            0x134          /* Arbiter Int. Mask Register */
+#define SH4_PCIBMLR            0x138           /* Error Bus Master Register */
+  #define SH4_PCIBMLR_REQ4       0x00000010    /* REQ4 bus master at error */
+  #define SH4_PCIBMLR_REQ3       0x00000008    /* REQ3 bus master at error */
+  #define SH4_PCIBMLR_REQ2       0x00000004    /* REQ2 bus master at error */
+  #define SH4_PCIBMLR_REQ1       0x00000002    /* REQ1 bus master at error */
+  #define SH4_PCIBMLR_REQ0       0x00000001    /* REQ0 bus master at error */
+#define SH4_PCIDMABT           0x140           /* DMA Transfer Arb. Register */
+  #define SH4_PCIDMABT_RRBN      0x00000001    /* DMA Arbitor Round-Robin */
+#define SH4_PCIDPA0            0x180           /* DMA0 Transfer Addr. */
+#define SH4_PCIDLA0            0x184           /* DMA0 Local Addr. */
+#define SH4_PCIDTC0            0x188           /* DMA0 Transfer Cnt. */
+#define SH4_PCIDCR0            0x18C           /* DMA0 Control Register */
+  #define SH4_PCIDCR_ALGN        0x00000600    /* DMA Alignment Mode */
+  #define SH4_PCIDCR_MAST        0x00000100    /* DMA Termination Type */
+  #define SH4_PCIDCR_INTM        0x00000080    /* DMA Interrupt Done Mask*/
+  #define SH4_PCIDCR_INTS        0x00000040    /* DMA Interrupt Done Status */
+  #define SH4_PCIDCR_LHLD        0x00000020    /* Local Address Control */
+  #define SH4_PCIDCR_PHLD        0x00000010    /* PCI Address Control*/
+  #define SH4_PCIDCR_IOSEL       0x00000008    /* PCI Address Space Type */
+  #define SH4_PCIDCR_DIR         0x00000004    /* DMA Transfer Direction */
+  #define SH4_PCIDCR_STOP        0x00000002    /* Force DMA Stop */
+  #define SH4_PCIDCR_STRT        0x00000001    /* DMA Start */
+#define SH4_PCIDPA1            0x190           /* DMA1 Transfer Addr. */
+#define SH4_PCIDLA1            0x194           /* DMA1 Local Addr. */
+#define SH4_PCIDTC1            0x198           /* DMA1 Transfer Cnt. */
+#define SH4_PCIDCR1            0x19C           /* DMA1 Control Register */
+#define SH4_PCIDPA2            0x1A0           /* DMA2 Transfer Addr. */
+#define SH4_PCIDLA2            0x1A4           /* DMA2 Local Addr. */
+#define SH4_PCIDTC2            0x1A8           /* DMA2 Transfer Cnt. */
+#define SH4_PCIDCR2            0x1AC           /* DMA2 Control Register */
+#define SH4_PCIDPA3            0x1B0           /* DMA3 Transfer Addr. */
+#define SH4_PCIDLA3            0x1B4           /* DMA3 Local Addr. */
+#define SH4_PCIDTC3            0x1B8           /* DMA3 Transfer Cnt. */
+#define SH4_PCIDCR3            0x1BC           /* DMA3 Control Register */
+#define SH4_PCIPAR             0x1C0           /* PIO Address Register */
+  #define SH4_PCIPAR_CFGEN       0x80000000    /* Configuration Enable */
+  #define SH4_PCIPAR_BUSNO       0x00FF0000    /* Config. Bus Number */
+  #define SH4_PCIPAR_DEVNO       0x0000FF00    /* Config. Device Number */
+  #define SH4_PCIPAR_REGAD       0x000000FC    /* Register Address Number */
+#define SH4_PCIMBR             0x1C4           /* Memory Base Address */
+  #define SH4_PCIMBR_MASK        0xFF000000    /* Memory Space Mask */
+  #define SH4_PCIMBR_LOCK        0x00000001    /* Lock Memory Space */
+#define SH4_PCIIOBR            0x1C8           /* I/O Base Address Register */
+  #define SH4_PCIIOBR_MASK       0xFFFC0000    /* IO Space Mask */
+  #define SH4_PCIIOBR_LOCK       0x00000001    /* Lock IO Space */
+#define SH4_PCIPINT            0x1CC           /* Power Mgmnt Int. Register */
+  #define SH4_PCIPINT_D3         0x00000002    /* D3 Pwr Mgmt. Interrupt */
+  #define SH4_PCIPINT_D0         0x00000001    /* D0 Pwr Mgmt. Interrupt */
+#define SH4_PCIPINTM           0x1D0           /* Power Mgmnt Mask Register */
+#define SH4_PCICLKR            0x1D4           /* Clock Ctrl. Register */
+  #define SH4_PCICLKR_PCSTP      0x00000002    /* PCI Clock Stop */
+  #define SH4_PCICLKR_BCSTP      0x00000001    /* BCLK Clock Stop */
+/* For definitions of BCR, MCR see ... */
+#define SH4_PCIBCR1            0x1E0           /* Memory BCR1 Register */
+  #define SH4_PCIMBR0          SH4_PCIBCR1
+#define SH4_PCIBCR2            0x1E4           /* Memory BCR2 Register */
+  #define SH4_PCIMBMR0         SH4_PCIBCR2
+#define SH4_PCIWCR1            0x1E8           /* Wait Control 1 Register */
+#define SH4_PCIWCR2            0x1EC           /* Wait Control 2 Register */
+#define SH4_PCIWCR3            0x1F0           /* Wait Control 3 Register */
+  #define SH4_PCIMBR2          SH4_PCIWCR3
+#define SH4_PCIMCR             0x1F4           /* Memory Control Register */
+#define SH4_PCIBCR3            0x1f8           /* Memory BCR3 Register */
+#define SH4_PCIPCTR             0x200          /* Port Control Register */
+  #define SH4_PCIPCTR_P2EN       0x000400000   /* Port 2 Enable */
+  #define SH4_PCIPCTR_P1EN       0x000200000   /* Port 1 Enable */
+  #define SH4_PCIPCTR_P0EN       0x000100000   /* Port 0 Enable */
+  #define SH4_PCIPCTR_P2UP       0x000000020   /* Port2 Pull Up Enable */
+  #define SH4_PCIPCTR_P2IO       0x000000010   /* Port2 Output Enable */
+  #define SH4_PCIPCTR_P1UP       0x000000008   /* Port1 Pull Up Enable */
+  #define SH4_PCIPCTR_P1IO       0x000000004   /* Port1 Output Enable */
+  #define SH4_PCIPCTR_P0UP       0x000000002   /* Port0 Pull Up Enable */
+  #define SH4_PCIPCTR_P0IO       0x000000001   /* Port0 Output Enable */
+#define SH4_PCIPDTR            0x204           /* Port Data Register */
+  #define SH4_PCIPDTR_PB5        0x000000020   /* Port 5 Enable */
+  #define SH4_PCIPDTR_PB4        0x000000010   /* Port 4 Enable */
+  #define SH4_PCIPDTR_PB3        0x000000008   /* Port 3 Enable */
+  #define SH4_PCIPDTR_PB2        0x000000004   /* Port 2 Enable */
+  #define SH4_PCIPDTR_PB1        0x000000002   /* Port 1 Enable */
+  #define SH4_PCIPDTR_PB0        0x000000001   /* Port 0 Enable */
+#define SH4_PCIPDR             0x220           /* Port IO Data Register */
+
+/* Flags */
+#define SH4_PCIC_NO_RESET      0x0001
+
+/* arch/sh/kernel/drivers/pci/ops-sh4.c */
+extern struct pci_ops sh4_pci_ops;
+int sh4_pci_check_direct(void);
+int pci_fixup_pcic(void);
+
+struct sh4_pci_address_space {
+       unsigned long base;
+       unsigned long size;
+};
+
+struct sh4_pci_address_map {
+       struct sh4_pci_address_space window0;
+       struct sh4_pci_address_space window1;
+       unsigned long flags;
+};
+
+static inline void pci_write_reg(unsigned long val, unsigned long reg)
+{
+       outl(val, PCI_REG(reg));
+}
+
+static inline unsigned long pci_read_reg(unsigned long reg)
+{
+       return inl(PCI_REG(reg));
+}
+#endif /* __PCI_SH4_H */
index 682f3dae305db3a0aa15c1a1b7804ae67e7c7152..dbe837884983285c302cc60d64e900fbd7ccc94c 100644 (file)
 
 #undef DEBUG
 
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
+#include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
-
-#include <asm/machvec.h>
+#include "pci-sh4.h"
+#include <asm/addrspace.h>
 #include <asm/io.h>
-#include "pci-sh7751.h"
-
-static unsigned int pci_probe = PCI_PROBE_CONF1;
-extern int pci_fixup_pcic(void);
-
-void pcibios_fixup_irqs(void) __attribute__ ((weak));
-
-/*
- * Direct access to PCI hardware...
- */
-
-#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
-
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
-static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn,
-                          int where, int size, u32 *val)
-{
-       unsigned long flags;
-       u32 data;
-
-       /* 
-        * PCIPDR may only be accessed as 32 bit words, 
-        * so we must do byte alignment by hand 
-        */
-       local_irq_save(flags);
-       outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
-       data = inl(PCI_REG(SH7751_PCIPDR));
-       local_irq_restore(flags);
-
-       switch (size) {
-       case 1:
-               *val = (data >> ((where & 3) << 3)) & 0xff;
-               break;
-       case 2:
-               *val = (data >> ((where & 2) << 3)) & 0xffff;
-               break;
-       case 4:
-               *val = data;
-               break;
-       default:
-               return PCIBIOS_FUNC_NOT_SUPPORTED;
-       }
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-/* 
- * Since SH7751 only does 32bit access we'll have to do a read,
- * mask,write operation.
- * We'll allow an odd byte offset, though it should be illegal.
- */ 
-static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn,
-                           int where, int size, u32 val)
-{
-       unsigned long flags;
-       int shift;
-       u32 data;
-
-       local_irq_save(flags);
-       outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
-       data = inl(PCI_REG(SH7751_PCIPDR));
-       local_irq_restore(flags);
-
-       switch (size) {
-       case 1:
-               shift = (where & 3) << 3;
-               data &= ~(0xff << shift);
-               data |= ((val & 0xff) << shift);
-               break;
-       case 2:
-               shift = (where & 2) << 3;
-               data &= ~(0xffff << shift);
-               data |= ((val & 0xffff) << shift);
-               break;
-       case 4:
-               data = val;
-               break;
-       default:
-               return PCIBIOS_FUNC_NOT_SUPPORTED;
-       }
-
-       outl(data, PCI_REG(SH7751_PCIPDR));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-#undef CONFIG_CMD
-
-struct pci_ops sh7751_pci_ops = {
-       .read           = sh7751_pci_read,
-       .write          = sh7751_pci_write,
-};
-
-static int __init pci_check_direct(void)
-{
-       unsigned int tmp, id;
-
-       /* check for SH7751/SH7751R hardware */
-       id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0);
-       if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
-           id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
-               pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
-               return -ENODEV;
-       }
-
-       /*
-        * Check if configuration works.
-        */
-       if (pci_probe & PCI_PROBE_CONF1) {
-               tmp = inl (PCI_REG(SH7751_PCIPAR));
-               outl (0x80000000, PCI_REG(SH7751_PCIPAR));
-               if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) {
-                       outl (tmp, PCI_REG(SH7751_PCIPAR));
-                       printk(KERN_INFO "PCI: Using configuration type 1\n");
-                       request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1");
-                       return 0;
-               }
-               outl (tmp, PCI_REG(SH7751_PCIPAR));
-       }
-
-       pr_debug("PCI: pci_check_direct failed\n");
-       return -EINVAL;
-}
-
-/***************************************************************************************/
-
-/*
- *  Handle bus scanning and fixups ....
- */
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
-       int i;
-
-       /*
-        * PCI IDE controllers use non-standard I/O port decoding, respect it.
-        */
-       if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
-               return;
-       pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
-       for(i=0; i<4; i++) {
-               struct resource *r = &d->resource[i];
-               if ((r->start & ~0x80) == 0x374) {
-                       r->start |= 2;
-                       r->end = r->start;
-               }
-       }
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-
-void __init pcibios_fixup_bus(struct pci_bus *b)
-{
-       pci_read_bridge_bases(b);
-}
 
 /*
  * Initialization. Try all known PCI access methods. Note that we support
@@ -196,25 +30,29 @@ void __init pcibios_fixup_bus(struct pci_bus *b)
  * to access config space.
  * 
  * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
- * exitst and via the platform defined function pcibios_init_platform().  
- * See pci_bigsur.c for implementation;
- * 
- * The BIOS version of the pci functions is not yet implemented but it is left
- * in for completeness.  Currently an error will be genereated at compile time. 
+ * space mapping) will be called via the platform defined function
+ * pcibios_init_platform().
  */
-
 static int __init sh7751_pci_init(void)
 {
+       unsigned int id;
        int ret;
 
        pr_debug("PCI: Starting intialization.\n");
-       if ((ret = pci_check_direct()) != 0)
+
+       /* check for SH7751/SH7751R hardware */
+       id = pci_read_reg(SH7751_PCICONF0);
+       if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+           id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+               pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+               return -ENODEV;
+       }
+
+       if ((ret = sh4_pci_check_direct()) != 0)
                return ret;
 
        return pcibios_init_platform();
 }
-
 subsys_initcall(sh7751_pci_init);
 
 static int __init __area_sdram_check(unsigned int area)
@@ -223,26 +61,26 @@ static int __init __area_sdram_check(unsigned int area)
 
        word = inl(SH7751_BCR1);
        /* check BCR for SDRAM in area */
-       if(((word >> area) & 1) == 0) {
+       if (((word >> area) & 1) == 0) {
                printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
                       area, word);
                return 0;
        }
-       outl(word, PCI_REG(SH7751_PCIBCR1));
+       pci_write_reg(word, SH4_PCIBCR1);
 
        word = (u16)inw(SH7751_BCR2);
        /* check BCR2 for 32bit SDRAM interface*/
-       if(((word >> (area << 1)) & 0x3) != 0x3) {
+       if (((word >> (area << 1)) & 0x3) != 0x3) {
                printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
                       area, word);
                return 0;
        }
-       outl(word, PCI_REG(SH7751_PCIBCR2));
+       pci_write_reg(word, SH4_PCIBCR2);
 
        return 1;
 }
 
-int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
+int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
 {
        u32 reg;
        u32 word;
@@ -251,39 +89,39 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
        reg = inl(SH7751_BCR1);
        reg |= 0x80000;
        outl(reg, SH7751_BCR1);
-       
+
        /* Turn the clocks back on (not done in reset)*/
-       outl(0, PCI_REG(SH7751_PCICLKR));
+       pci_write_reg(0, SH4_PCICLKR);
        /* Clear Powerdown IRQ's (not done in reset) */
-       word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0;
-       outl(word, PCI_REG(SH7751_PCIPINT));
+       word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
+       pci_write_reg(word, SH4_PCIPINT);
 
        /*
         * This code is unused for some boards as it is done in the
         * bootloader and doing it here means the MAC addresses loaded
         * by the bootloader get lost.
         */
-       if (!(map->flags & SH7751_PCIC_NO_RESET)) {
+       if (!(map->flags & SH4_PCIC_NO_RESET)) {
                /* toggle PCI reset pin */
-               word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
-               outl(word,PCI_REG(SH7751_PCICR));
+               word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
+               pci_write_reg(word, SH4_PCICR);
                /* Wait for a long time... not 1 sec. but long enough */
                mdelay(100);
-               word = SH7751_PCICR_PREFIX;
-               outl(word,PCI_REG(SH7751_PCICR));
+               word = SH4_PCICR_PREFIX;
+               pci_write_reg(word, SH4_PCICR);
        }
-       
+
        /* set the command/status bits to:
         * Wait Cycle Control + Parity Enable + Bus Master +
         * Mem space enable
         */
        word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | 
               SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
-       outl(word, PCI_REG(SH7751_PCICONF1));
+       pci_write_reg(word, SH7751_PCICONF1);
 
        /* define this host as the host bridge */
-       word = SH7751_PCI_HOST_BRIDGE << 24;
-       outl(word, PCI_REG(SH7751_PCICONF2));
+       word = PCI_BASE_CLASS_BRIDGE << 24;
+       pci_write_reg(word, SH7751_PCICONF2);
 
        /* Set IO and Mem windows to local address 
         * Make PCI and local address the same for easy 1 to 1 mapping 
@@ -291,46 +129,49 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
         * Window1 = map->window1.size @ cached area base = SDRAM 
         */
        word = map->window0.size - 1;
-       outl(word, PCI_REG(SH7751_PCILSR0));
+       pci_write_reg(word, SH4_PCILSR0);
        word = map->window1.size - 1;
-       outl(word, PCI_REG(SH7751_PCILSR1));
+       pci_write_reg(word, SH4_PCILSR1);
        /* Set the values on window 0 PCI config registers */
        word = P2SEGADDR(map->window0.base);
-       outl(word, PCI_REG(SH7751_PCILAR0));
-       outl(word, PCI_REG(SH7751_PCICONF5));
+       pci_write_reg(word, SH4_PCILAR0);
+       pci_write_reg(word, SH7751_PCICONF5);
        /* Set the values on window 1 PCI config registers */
        word =  PHYSADDR(map->window1.base);
-       outl(word, PCI_REG(SH7751_PCILAR1));
-       outl(word, PCI_REG(SH7751_PCICONF6));
+       pci_write_reg(word, SH4_PCILAR1);
+       pci_write_reg(word, SH7751_PCICONF6);
 
-       /* Set the local 16MB PCI memory space window to 
+       /* Set the local 16MB PCI memory space window to
         * the lowest PCI mapped address
         */
-       word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK;
-       PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word);
-       outl(word , PCI_REG(SH7751_PCIMBR));
+       word = PCIBIOS_MIN_MEM & SH4_PCIMBR_MASK;
+       pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
+       pci_write_reg(word , SH4_PCIMBR);
 
        /* Map IO space into PCI IO window
         * The IO window is 64K-PCIBIOS_MIN_IO in size
-        * IO addresses will be translated to the 
+        * IO addresses will be translated to the
         * PCI IO window base address
         */
-       PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
-           (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO);
+       pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
+                PCIBIOS_MIN_IO, (64 << 10),
+                SH4_PCI_IO_BASE + PCIBIOS_MIN_IO);
 
-       /* 
+       /*
         * XXX: For now, leave this board-specific. In the event we have other
         * boards that need to do similar work, this can be wrapped.
         */
 #ifdef CONFIG_SH_BIGSUR
-       bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0);
+       bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
+                       SH4_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
 #endif
 
-       /* Make sure the MSB's of IO window are set to access PCI space correctly */
-       word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK;
-       PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word);
-       outl(word, PCI_REG(SH7751_PCIIOBR));
-       
+       /* Make sure the MSB's of IO window are set to access PCI space
+        * correctly */
+       word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
+       pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
+       pci_write_reg(word, SH4_PCIIOBR);
+
        /* Set PCI WCRx, BCRx's, copy from BSC locations */
 
        /* check BCR for SDRAM in specified area */
@@ -349,13 +190,13 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
 
        /* configure the wait control registers */
        word = inl(SH7751_WCR1);
-       outl(word, PCI_REG(SH7751_PCIWCR1));
+       pci_write_reg(word, SH4_PCIWCR1);
        word = inl(SH7751_WCR2);
-       outl(word, PCI_REG(SH7751_PCIWCR2));
+       pci_write_reg(word, SH4_PCIWCR2);
        word = inl(SH7751_WCR3);
-       outl(word, PCI_REG(SH7751_PCIWCR3));
+       pci_write_reg(word, SH4_PCIWCR3);
        word = inl(SH7751_MCR);
-       outl(word, PCI_REG(SH7751_PCIMCR));
+       pci_write_reg(word, SH4_PCIMCR);
 
        /* NOTE: I'm ignoring the PCI error IRQs for now..
         * TODO: add support for the internal error interrupts and
@@ -368,49 +209,8 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
 
        /* SH7751 init done, set central function init complete */
        /* use round robin mode to stop a device starving/overruning */
-       word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM;
-       outl(word,PCI_REG(SH7751_PCICR)); 
+       word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
+       pci_write_reg(word, SH4_PCICR);
 
        return 1;
 }
-
-char * __init pcibios_setup(char *str)
-{
-       if (!strcmp(str, "off")) {
-               pci_probe = 0;
-               return NULL;
-       }
-
-       return str;
-}
-
-/* 
- *     IRQ functions 
- */
-static u8 __init sh7751_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
-       /* no swizzling */
-       return PCI_SLOT(dev->devfn);
-}
-
-static int sh7751_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       int irq = -1;
-
-       /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
-       irq = pcibios_map_platform_irq(slot,pin);
-       if( irq < 0 ) {
-               pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
-               return irq;
-       }
-
-       pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
-       return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-       pci_fixup_irqs(sh7751_no_swizzle, sh7751_pci_lookup_irq);
-}
-
index 1fee5cae10d18c42005408103740cbfb10def672..68e3cb5e6bec2f5c7804c4b7cb3cff60235ae534 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Dustin McIntire (dustin@sensoria.com) (c) 2001
  *  Paul Mundt (lethal@linux-sh.org) (c) 2003
- *     
+ *
  *  May be copied or modified under the terms of the GNU General Public
  *  License.  See linux/COPYING for more information.
  *
 #ifndef _PCI_SH7751_H_
 #define _PCI_SH7751_H_
 
-#include <linux/pci.h>
-
-/* set debug level 4=verbose...1=terse */
-//#define DEBUG_PCI 3
-#undef DEBUG_PCI
-
-#ifdef DEBUG_PCI
-#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
-#else
-#define PCIDBG(n, x...)
-#endif
-
-/* startup values */
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_SORT 0x100
-#define PCI_BIOS_SORT 0x200
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-
 /* Platform Specific Values */
 #define SH7751_VENDOR_ID             0x1054
 #define SH7751_DEVICE_ID             0x3505
   #define SH7751_PCICONF17_PMEN      0x00010000  /* PME Enable */
   #define SH7751_PCICONF17_PWST      0x00000003  /* Power State */
 /* SH7715 Internal PCI Registers */
-#define SH7751_PCICR               0x100         /* PCI Control Register */
-  #define SH7751_PCICR_PREFIX        0xA5000000  /* CR prefix for write */
-  #define SH7751_PCICR_TRSB          0x00000200  /* Target Read Single */
-  #define SH7751_PCICR_BSWP          0x00000100  /* Target Byte Swap */
-  #define SH7751_PCICR_PLUP          0x00000080  /* Enable PCI Pullup */
-  #define SH7751_PCICR_ARBM          0x00000040  /* PCI Arbitration Mode */
-  #define SH7751_PCICR_MD            0x00000030  /* MD9 and MD10 status */
-  #define SH7751_PCICR_SERR          0x00000008  /* SERR output assert */
-  #define SH7751_PCICR_INTA          0x00000004  /* INTA output assert */
-  #define SH7751_PCICR_PRST          0x00000002  /* PCI Reset Assert */
-  #define SH7751_PCICR_CFIN          0x00000001  /* Central Fun. Init Done */
-#define SH7751_PCILSR0             0x104         /* PCI Local Space Register0 */
-#define SH7751_PCILSR1             0x108         /* PCI Local Space Register1 */
-#define SH7751_PCILAR0             0x10C         /* PCI Local Address Register1 */
-#define SH7751_PCILAR1             0x110         /* PCI Local Address Register1 */
-#define SH7751_PCIINT              0x114         /* PCI Interrupt Register */
-  #define SH7751_PCIINT_MLCK         0x00008000  /* Master Lock Error */
-  #define SH7751_PCIINT_TABT         0x00004000  /* Target Abort Error */
-  #define SH7751_PCIINT_TRET         0x00000200  /* Target Retry Error */
-  #define SH7751_PCIINT_MFDE         0x00000100  /* Master Func. Disable Error */
-  #define SH7751_PCIINT_PRTY         0x00000080  /* Address Parity Error */
-  #define SH7751_PCIINT_SERR         0x00000040  /* SERR Detection Error */
-  #define SH7751_PCIINT_TWDP         0x00000020  /* Tgt. Write Parity Error */
-  #define SH7751_PCIINT_TRDP         0x00000010  /* Tgt. Read Parity Error Det. */
-  #define SH7751_PCIINT_MTABT        0x00000008  /* Master-Tgt. Abort Error */
-  #define SH7751_PCIINT_MMABT        0x00000004  /* Master-Master Abort Error */
-  #define SH7751_PCIINT_MWPD         0x00000002  /* Master Write PERR Detect */
-  #define SH7751_PCIINT_MRPD         0x00000002  /* Master Read PERR Detect */
-#define SH7751_PCIINTM             0x118         /* PCI Interrupt Mask Register */
-#define SH7751_PCIALR              0x11C         /* Error Address Register */
-#define SH7751_PCICLR              0x120         /* Error Command/Data Register */
-  #define SH7751_PCICLR_MPIO         0x80000000  /* Error Command/Data Register */
-  #define SH7751_PCICLR_MDMA0        0x40000000  /* DMA0 Transfer Error */
-  #define SH7751_PCICLR_MDMA1        0x20000000  /* DMA1 Transfer Error */
-  #define SH7751_PCICLR_MDMA2        0x10000000  /* DMA2 Transfer Error */
-  #define SH7751_PCICLR_MDMA3        0x08000000  /* DMA3 Transfer Error */
-  #define SH7751_PCICLR_TGT          0x04000000  /* Target Transfer Error */
-  #define SH7751_PCICLR_CMDL         0x0000000F  /* PCI Command at Error */
-#define SH7751_PCIAINT             0x130         /* Arbiter Interrupt Register */
-  #define SH7751_PCIAINT_MBKN        0x00002000  /* Master Broken Interrupt */
-  #define SH7751_PCIAINT_TBTO        0x00001000  /* Target Bus Time Out */
-  #define SH7751_PCIAINT_MBTO        0x00001000  /* Master Bus Time Out */
-  #define SH7751_PCIAINT_TABT        0x00000008  /* Target Abort */
-  #define SH7751_PCIAINT_MABT        0x00000004  /* Master Abort */
-  #define SH7751_PCIAINT_RDPE        0x00000002  /* Read Data Parity Error */
-  #define SH7751_PCIAINT_WDPE        0x00000002  /* Write Data Parity Error */
-#define SH7751_PCIAINTM            0x134         /* Arbiter Int. Mask Register */
-#define SH7751_PCIBMLR             0x138         /* Error Bus Master Register */
-  #define SH7751_PCIBMLR_REQ4        0x00000010  /* REQ4 bus master at error */
-  #define SH7751_PCIBMLR_REQ3        0x00000008  /* REQ3 bus master at error */
-  #define SH7751_PCIBMLR_REQ2        0x00000004  /* REQ2 bus master at error */
-  #define SH7751_PCIBMLR_REQ1        0x00000002  /* REQ1 bus master at error */
-  #define SH7751_PCIBMLR_REQ0        0x00000001  /* REQ0 bus master at error */
-#define SH7751_PCIDMABT            0x140         /* DMA Transfer Arb. Register */
-  #define SH7751_PCIDMABT_RRBN       0x00000001  /* DMA Arbitor Round-Robin */
-#define SH7751_PCIDPA0             0x180         /* DMA0 Transfer Addr. Register */
-#define SH7751_PCIDLA0             0x184         /* DMA0 Local Addr. Register */
-#define SH7751_PCIDTC0             0x188         /* DMA0 Transfer Cnt. Register */
-#define SH7751_PCIDCR0             0x18C         /* DMA0 Control Register */
-  #define SH7751_PCIDCR_ALGN         0x00000600  /* DMA Alignment Mode */
-  #define SH7751_PCIDCR_MAST         0x00000100  /* DMA Termination Type */
-  #define SH7751_PCIDCR_INTM         0x00000080  /* DMA Interrupt Done Mask*/
-  #define SH7751_PCIDCR_INTS         0x00000040  /* DMA Interrupt Done Status */
-  #define SH7751_PCIDCR_LHLD         0x00000020  /* Local Address Control */
-  #define SH7751_PCIDCR_PHLD         0x00000010  /* PCI Address Control*/
-  #define SH7751_PCIDCR_IOSEL        0x00000008  /* PCI Address Space Type */
-  #define SH7751_PCIDCR_DIR          0x00000004  /* DMA Transfer Direction */
-  #define SH7751_PCIDCR_STOP         0x00000002  /* Force DMA Stop */
-  #define SH7751_PCIDCR_STRT         0x00000001  /* DMA Start */
-#define SH7751_PCIDPA1             0x190         /* DMA1 Transfer Addr. Register */
-#define SH7751_PCIDLA1             0x194         /* DMA1 Local Addr. Register */
-#define SH7751_PCIDTC1             0x198         /* DMA1 Transfer Cnt. Register */
-#define SH7751_PCIDCR1             0x19C         /* DMA1 Control Register */
-#define SH7751_PCIDPA2             0x1A0         /* DMA2 Transfer Addr. Register */
-#define SH7751_PCIDLA2             0x1A4         /* DMA2 Local Addr. Register */
-#define SH7751_PCIDTC2             0x1A8         /* DMA2 Transfer Cnt. Register */
-#define SH7751_PCIDCR2             0x1AC         /* DMA2 Control Register */
-#define SH7751_PCIDPA3             0x1B0         /* DMA3 Transfer Addr. Register */
-#define SH7751_PCIDLA3             0x1B4         /* DMA3 Local Addr. Register */
-#define SH7751_PCIDTC3             0x1B8         /* DMA3 Transfer Cnt. Register */
-#define SH7751_PCIDCR3             0x1BC         /* DMA3 Control Register */
-#define SH7751_PCIPAR              0x1C0         /* PIO Address Register */
-  #define SH7751_PCIPAR_CFGEN        0x80000000  /* Configuration Enable */
-  #define SH7751_PCIPAR_BUSNO        0x00FF0000  /* Config. Bus Number */
-  #define SH7751_PCIPAR_DEVNO        0x0000FF00  /* Config. Device Number */
-  #define SH7751_PCIPAR_REGAD        0x000000FC  /* Register Address Number */
-#define SH7751_PCIMBR              0x1C4         /* Memory Base Address Register */
-  #define SH7751_PCIMBR_MASK         0xFF000000  /* Memory Space Mask */
-  #define SH7751_PCIMBR_LOCK         0x00000001  /* Lock Memory Space */
-#define SH7751_PCIIOBR             0x1C8         /* I/O Base Address Register */
-  #define SH7751_PCIIOBR_MASK         0xFFFC0000 /* IO Space Mask */
-  #define SH7751_PCIIOBR_LOCK         0x00000001 /* Lock IO Space */
-#define SH7751_PCIPINT             0x1CC         /* Power Mgmnt Int. Register */
-  #define SH7751_PCIPINT_D3           0x00000002 /* D3 Pwr Mgmt. Interrupt */
-  #define SH7751_PCIPINT_D0           0x00000001 /* D0 Pwr Mgmt. Interrupt */  
-#define SH7751_PCIPINTM            0x1D0         /* Power Mgmnt Mask Register */
-#define SH7751_PCICLKR             0x1D4         /* Clock Ctrl. Register */
-  #define SH7751_PCICLKR_PCSTP        0x00000002 /* PCI Clock Stop */
-  #define SH7751_PCICLKR_BCSTP        0x00000002 /* BCLK Clock Stop */
-/* For definitions of BCR, MCR see ... */
-#define SH7751_PCIBCR1             0x1E0         /* Memory BCR1 Register */
-#define SH7751_PCIBCR2             0x1E4         /* Memory BCR2 Register */
-#define SH7751_PCIWCR1             0x1E8         /* Wait Control 1 Register */
-#define SH7751_PCIWCR2             0x1EC         /* Wait Control 2 Register */
-#define SH7751_PCIWCR3             0x1F0         /* Wait Control 3 Register */
-#define SH7751_PCIMCR              0x1F4         /* Memory Control Register */
-#define SH7751_PCIBCR3            0x1f8         /* Memory BCR3 Register */
-#define SH7751_PCIPCTR             0x200         /* Port Control Register */
-  #define SH7751_PCIPCTR_P2EN        0x000400000 /* Port 2 Enable */
-  #define SH7751_PCIPCTR_P1EN        0x000200000 /* Port 1 Enable */
-  #define SH7751_PCIPCTR_P0EN        0x000100000 /* Port 0 Enable */
-  #define SH7751_PCIPCTR_P2UP        0x000000020 /* Port2 Pull Up Enable */
-  #define SH7751_PCIPCTR_P2IO        0x000000010 /* Port2 Output Enable */
-  #define SH7751_PCIPCTR_P1UP        0x000000008 /* Port1 Pull Up Enable */
-  #define SH7751_PCIPCTR_P1IO        0x000000004 /* Port1 Output Enable */
-  #define SH7751_PCIPCTR_P0UP        0x000000002 /* Port0 Pull Up Enable */
-  #define SH7751_PCIPCTR_P0IO        0x000000001 /* Port0 Output Enable */
-#define SH7751_PCIPDTR             0x204         /* Port Data Register */
-  #define SH7751_PCIPDTR_PB5         0x000000020 /* Port 5 Enable */
-  #define SH7751_PCIPDTR_PB4         0x000000010 /* Port 4 Enable */
-  #define SH7751_PCIPDTR_PB3         0x000000008 /* Port 3 Enable */
-  #define SH7751_PCIPDTR_PB2         0x000000004 /* Port 2 Enable */
-  #define SH7751_PCIPDTR_PB1         0x000000002 /* Port 1 Enable */
-  #define SH7751_PCIPDTR_PB0         0x000000001 /* Port 0 Enable */
-#define SH7751_PCIPDR              0x220         /* Port IO Data Register */
 
 /* Memory Control Registers */
 #define SH7751_BCR1                0xFF800000    /* Memory BCR1 Register */
 #define SH7751_CS5_BASE_ADDR       (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
 #define SH7751_CS6_BASE_ADDR       (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
 
-/* General PCI values */
-#define SH7751_PCI_HOST_BRIDGE         0x6
-
-/* Flags */
-#define SH7751_PCIC_NO_RESET   0x0001
-
-/* External functions defined per platform i.e. Big Sur, SE... (these could be routed 
- * through the machine vectors... */
-extern int pcibios_init_platform(void);
-extern int pcibios_map_platform_irq(u8 slot, u8 pin);
-
-struct sh7751_pci_address_space {
-       unsigned long base;
-       unsigned long size;
-};
-
-struct sh7751_pci_address_map {
-       struct sh7751_pci_address_space window0;
-       struct sh7751_pci_address_space window1;
-       unsigned long flags;
-};
+struct sh4_pci_address_map;
 
 /* arch/sh/drivers/pci/pci-sh7751.c */
-extern int sh7751_pcic_init(struct sh7751_pci_address_map *map);
+int sh7751_pcic_init(struct sh4_pci_address_map *map);
 
 #endif /* _PCI_SH7751_H_ */
-
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
new file mode 100644 (file)
index 0000000..bd3064a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *     Low-Level PCI Support for the SH7780
+ *
+ *  Dustin McIntire (dustin@sensoria.com)
+ *     Derived from arch/i386/kernel/pci-*.c which bore the message:
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ *  Ported to the new API by Paul Mundt <lethal@linux-sh.org>
+ *  With cleanup by Paul van Gool <pvangool@mimotech.com>
+ *
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include "pci-sh4.h"
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space.
+ *
+ * Note that the platform specific initialization (BSC registers, and memory
+ * space mapping) will be called via the platform defined function
+ * pcibios_init_platform().
+ */
+static int __init sh7780_pci_init(void)
+{
+       unsigned int id;
+       int ret;
+
+       pr_debug("PCI: Starting intialization.\n");
+
+       outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
+
+       /* check for SH7780/SH7780R hardware */
+       id = pci_read_reg(SH7780_PCIVID);
+       if ((id != ((SH7780_DEVICE_ID << 16) | SH7780_VENDOR_ID)) &&
+           (id != ((SH7781_DEVICE_ID << 16) | SH7780_VENDOR_ID))) {
+               printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
+               return -ENODEV;
+       }
+
+       /* Setup the INTC */
+       ctrl_outl(0x00200000, INTC_ICR0);       /* INTC SH-4 Mode */
+       ctrl_outl(0x00078000, INTC_INT2MSKCR);  /* enable PCIINTA - PCIINTD */
+       ctrl_outl(0x40000000, INTC_INTMSK1);    /* disable IRL4-7 Interrupt */
+       ctrl_outl(0x0000fffe, INTC_INTMSK2);    /* disable IRL4-7 Interrupt */
+       ctrl_outl(0x80000000, INTC_INTMSKCLR1); /* enable IRL0-3 Interrupt */
+       ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); /* enable IRL0-3 Interrupt */
+
+       if ((ret = sh4_pci_check_direct()) != 0)
+               return ret;
+
+       return pcibios_init_platform();
+}
+core_initcall(sh7780_pci_init);
+
+int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
+{
+       u32 word;
+
+       /*
+        * This code is unused for some boards as it is done in the
+        * bootloader and doing it here means the MAC addresses loaded
+        * by the bootloader get lost.
+        */
+       if (!(map->flags & SH4_PCIC_NO_RESET)) {
+               /* toggle PCI reset pin */
+               word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
+               pci_write_reg(word, SH4_PCICR);
+               /* Wait for a long time... not 1 sec. but long enough */
+               mdelay(100);
+               word = SH4_PCICR_PREFIX;
+               pci_write_reg(word, SH4_PCICR);
+       }
+
+       /* set the command/status bits to:
+        * Wait Cycle Control + Parity Enable + Bus Master +
+        * Mem space enable
+        */
+       pci_write_reg(0x00000046, SH7780_PCICMD);
+
+       /* define this host as the host bridge */
+       word = PCI_BASE_CLASS_BRIDGE << 24;
+       pci_write_reg(word, SH7780_PCIRID);
+
+       /* Set IO and Mem windows to local address
+        * Make PCI and local address the same for easy 1 to 1 mapping
+        * Window0 = map->window0.size @ non-cached area base = SDRAM
+        * Window1 = map->window1.size @ cached area base = SDRAM
+        */
+       word = ((map->window0.size - 1) & 0x1ff00001) | 0x01;
+       pci_write_reg(0x07f00001, SH4_PCILSR0);
+       word = ((map->window1.size - 1) & 0x1ff00001) | 0x01;
+       pci_write_reg(0x00000001, SH4_PCILSR1);
+       /* Set the values on window 0 PCI config registers */
+       word = P2SEGADDR(map->window0.base);
+       pci_write_reg(0xa8000000, SH4_PCILAR0);
+       pci_write_reg(0x08000000, SH7780_PCIMBAR0);
+       /* Set the values on window 1 PCI config registers */
+       word = P2SEGADDR(map->window1.base);
+       pci_write_reg(0x00000000, SH4_PCILAR1);
+       pci_write_reg(0x00000000, SH7780_PCIMBAR1);
+
+       /* Map IO space into PCI IO window
+        * The IO window is 64K-PCIBIOS_MIN_IO in size
+        * IO addresses will be translated to the
+        * PCI IO window base address
+        */
+       pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
+                PCIBIOS_MIN_IO, (64 << 10),
+                SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO);
+
+       /* NOTE: I'm ignoring the PCI error IRQs for now..
+        * TODO: add support for the internal error interrupts and
+        * DMA interrupts...
+        */
+
+#ifdef CONFIG_SH_R7780RP
+       pci_fixup_pcic();
+#endif
+
+       /* SH7780 init done, set central function init complete */
+       /* use round robin mode to stop a device starving/overruning */
+       word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO;
+       pci_write_reg(word, SH4_PCICR);
+
+       return 1;
+}
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
new file mode 100644 (file)
index 0000000..f02d218
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *     Low-Level PCI Support for SH7780 targets
+ *
+ *  Dustin McIntire (dustin@sensoria.com) (c) 2001
+ *  Paul Mundt (lethal@linux-sh.org) (c) 2003
+ *
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+
+#ifndef _PCI_SH7780_H_
+#define _PCI_SH7780_H_
+
+/* Platform Specific Values */
+#define SH7780_VENDOR_ID       0x1912
+#define SH7780_DEVICE_ID       0x0002
+#define SH7781_DEVICE_ID       0x0001
+
+/* SH7780 Control Registers */
+#define        SH7780_PCI_VCR0         0xFE000000
+#define        SH7780_PCI_VCR1         0xFE000004
+#define        SH7780_PCI_VCR2         0xFE000008
+
+/* SH7780 Specific Values */
+#define SH7780_PCI_CONFIG_BASE 0xFD000000      /* Config space base addr */
+#define SH7780_PCI_CONFIG_SIZE 0x01000000      /* Config space size */
+
+#define SH7780_PCI_MEMORY_BASE 0xFD000000      /* Memory space base addr */
+#define SH7780_PCI_MEM_SIZE    0x01000000      /* Size of Memory window */
+
+#define SH7780_PCI_IO_BASE     0xFE400000      /* IO space base address */
+#define SH7780_PCI_IO_SIZE     0x00400000      /* Size of IO window */
+
+#define SH7780_PCIREG_BASE     0xFE040000      /* PCI regs base address */
+#define PCI_REG(n)             (SH7780_PCIREG_BASE+n)
+
+/* SH7780 PCI Config Registers */
+#define SH7780_PCIVID          0x000           /* Vendor ID */
+#define SH7780_PCIDID          0x002           /* Device ID */
+#define SH7780_PCICMD          0x004           /* Command */
+#define SH7780_PCISTATUS       0x006           /* Status */
+#define SH7780_PCIRID          0x008           /* Revision ID */
+#define SH7780_PCIPIF          0x009           /* Program Interface */
+#define SH7780_PCISUB          0x00a           /* Sub class code */
+#define SH7780_PCIBCC          0x00b           /* Base class code */
+#define SH7780_PCICLS          0x00c           /* Cache line size */
+#define SH7780_PCILTM          0x00d           /* latency timer */
+#define SH7780_PCIHDR          0x00e           /* Header type */
+#define SH7780_PCIBIST         0x00f           /* BIST */
+#define SH7780_PCIIBAR         0x010           /* IO Base address */
+#define SH7780_PCIMBAR0                0x014           /* Memory base address0 */
+#define SH7780_PCIMBAR1                0x018           /* Memory base address1 */
+#define SH7780_PCISVID         0x02c           /* Sub system vendor ID */
+#define SH7780_PCISID          0x02e           /* Sub system ID */
+#define SH7780_PCICP           0x034
+#define SH7780_PCIINTLINE      0x03c           /* Interrupt line */
+#define SH7780_PCIINTPIN       0x03d           /* Interrupt pin */
+#define SH7780_PCIMINGNT       0x03e           /* Minumum grand */
+#define SH7780_PCIMAXLAT       0x03f           /* Maxmum latency */
+#define SH7780_PCICID          0x040
+#define SH7780_PCINIP          0x041
+#define SH7780_PCIPMC          0x042
+#define SH7780_PCIPMCSR                0x044
+#define SH7780_PCIPMCSR_BSE    0x046
+#define SH7780_PCICDD          0x047
+
+#define SH7780_PCIMBR0         0x1E0
+#define SH7780_PCIMBMR0                0x1E4
+#define SH7780_PCIMBR2         0x1F0
+#define SH7780_PCIMBMR2                0x1F4
+#define SH7780_PCIIOBR         0x1F8
+#define SH7780_PCIIOBMR                0x1FC
+#define SH7780_PCICSCR0                0x210           /* Cache Snoop1 Cnt. Register */
+#define SH7780_PCICSCR1                0x214           /* Cache Snoop2 Cnt. Register */
+#define SH7780_PCICSAR0                0x218   /* Cache Snoop1 Addr. Register */
+#define SH7780_PCICSAR1                0x21C   /* Cache Snoop2 Addr. Register */
+
+/* General Memory Config Addresses */
+#define SH7780_CS0_BASE_ADDR   0x0
+#define SH7780_MEM_REGION_SIZE 0x04000000
+#define SH7780_CS1_BASE_ADDR   (SH7780_CS0_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS2_BASE_ADDR   (SH7780_CS1_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS3_BASE_ADDR   (SH7780_CS2_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS4_BASE_ADDR   (SH7780_CS3_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS5_BASE_ADDR   (SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS6_BASE_ADDR   (SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+
+struct sh4_pci_address_map;
+
+/* arch/sh/drivers/pci/pci-sh7780.c */
+int sh7780_pcic_init(struct sh4_pci_address_map *map);
+
+#endif /* _PCI_SH7780_H_ */
index 7c81b8b65bb505cbcaf58fad69364ee148cbc434..4ab5ea6b35fb5eeaf22fa5dd5889803f4d9555c1 100644 (file)
 static void pci_set_rbar_region(unsigned int region,     unsigned long localAddr,
                         unsigned long pciOffset, unsigned long regionSize);
 
-/*
- * The pcibios_map_platform_irq function is defined in the appropriate
- * board specific code and referenced here
- */
-extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
-
 static __init void SetPCIPLL(void)
 {
        {
@@ -422,13 +416,6 @@ struct pci_ops st40pci_config_ops = {
 /* Everything hangs off this */
 static struct pci_bus *pci_root_bus;
 
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
-{
-       return PCI_SLOT(dev->devfn);
-}
-
-
 static int __init pcibios_init(void)
 {
        extern unsigned long memory_start, memory_end;
@@ -465,17 +452,11 @@ static int __init pcibios_init(void)
        /* ok, do the scan man */
        pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL);
        pci_assign_unassigned_resources();
-       pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
 
        return 0;
 }
-
 subsys_initcall(pcibios_init);
 
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
 /*
  * Publish a region of local address space over the PCI bus
  * to other devices.
index 3d546ba329cfb866a9457751f6ab888523b867cd..d439336d2e18258c1a19865c529b12a59fb78544 100644 (file)
@@ -1,21 +1,45 @@
-/* arch/sh/kernel/pci.c
- * $Id: pci.c,v 1.1 2003/08/24 19:15:45 lethal Exp $
+/*
+ * arch/sh/drivers/pci/pci.c
  *
  * Copyright (c) 2002 M. R. Brown  <mrbrown@linux-sh.org>
- * 
- * 
+ * Copyright (c) 2004 - 2006 Paul Mundt  <lethal@linux-sh.org>
+ *
  * These functions are collected here to reduce duplication of common
  * code amongst the many platform-specific PCI support code files.
- * 
+ *
  * These routines require the following board-specific routines:
  * void pcibios_fixup_irqs();
  *
  * See include/asm-sh/pci.h for more information.
+ *
+ * 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/pci.h>
 #include <linux/init.h>
+#include <asm/io.h>
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+       return (((pin - 1) + slot) % 4) + 1;
+}
+
+static u8 __init simple_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+       u8 pin = *pinp;
+
+       while (dev->bus->parent) {
+               pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+               /* Move up the chain of bridges. */
+               dev = dev->bus->self;
+       }
+       *pinp = pin;
+
+       /* The slot is the slot of the last bridge. */
+       return PCI_SLOT(dev->devfn);
+}
 
 static int __init pcibios_init(void)
 {
@@ -26,26 +50,32 @@ static int __init pcibios_init(void)
 #ifdef CONFIG_PCI_AUTO
        /* assign resources */
        busno = 0;
-       for (p = board_pci_channels; p->pci_ops != NULL; p++) {
+       for (p = board_pci_channels; p->pci_ops != NULL; p++)
                busno = pciauto_assign_resources(busno, p) + 1;
-       }
 #endif
 
        /* scan the buses */
        busno = 0;
-       for (p= board_pci_channels; p->pci_ops != NULL; p++) {
+       for (p = board_pci_channels; p->pci_ops != NULL; p++) {
                bus = pci_scan_bus(busno, p->pci_ops, p);
-               busno = bus->subordinate+1;
+               busno = bus->subordinate + 1;
        }
 
-       /* board-specific fixups */
-       pcibios_fixup_irqs();
+       pci_fixup_irqs(simple_swizzle, pcibios_map_platform_irq);
 
        return 0;
 }
-
 subsys_initcall(pcibios_init);
 
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+       pci_read_bridge_bases(bus);
+}
+
 void
 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                        struct resource *res, int resource)
@@ -61,13 +91,17 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                new |= PCI_ROM_ADDRESS_ENABLE;
                reg = dev->rom_base_reg;
        } else {
-               /* Somebody might have asked allocation of a non-standard resource */
+               /*
+                * Somebody might have asked allocation of a non-standard
+                * resource
+                */
                return;
        }
-       
+
        pci_write_config_dword(dev, reg, new);
        pci_read_config_dword(dev, reg, &check);
-       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ?
+               PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
                printk(KERN_ERR "PCI: Error while updating region "
                       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
                       new, check);
@@ -145,7 +179,8 @@ void pcibios_set_master(struct pci_dev *dev)
                lat = pcibios_max_latency;
        else
                return;
-       printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
+       printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n",
+              pci_name(dev), lat);
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 
@@ -153,3 +188,39 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 {
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (unlikely(!len || !start))
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+
+       /*
+        * Presently the IORESOURCE_MEM case is a bit special, most
+        * SH7751 style PCI controllers have PCI memory at a fixed
+        * location in the address space where no remapping is desired
+        * (typically at 0xfd000000, but is_pci_memaddr() will know
+        * best). With the IORESOURCE_MEM case more care has to be taken
+        * to inhibit page table mapping for legacy cores, but this is
+        * punted off to __ioremap().
+        *                                      -- PFM.
+        */
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM)
+               return ioremap(start, len);
+
+       return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
index f05cd96f8867a5647b0adace1e3141bc1b38e405..5da88a43d350f4d38d92956090f4dce201e17d6e 100644 (file)
@@ -6,9 +6,10 @@ extra-y        := head.o init_task.o vmlinux.lds
 
 obj-y  := process.o signal.o entry.o traps.o irq.o \
        ptrace.o setup.o time.o sys_sh.o semaphore.o \
-       io.o io_generic.o sh_ksyms.o
+       io.o io_generic.o sh_ksyms.o syscalls.o
 
 obj-y                          += cpu/ timers/
+obj-$(CONFIG_VSYSCALL)         += vsyscall/
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_CF_ENABLER)       += cf-enabler.o
@@ -18,3 +19,5 @@ obj-$(CONFIG_SH_CPU_FREQ)     += cpufreq.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_APM)              += apm.o
+obj-$(CONFIG_PM)               += pm.o
diff --git a/arch/sh/kernel/apm.c b/arch/sh/kernel/apm.c
new file mode 100644 (file)
index 0000000..871e7d6
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ * bios-less APM driver for hp680
+ *
+ * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * based on ARM APM driver by
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *
+ * adapted from the APM BIOS driver for Linux by
+ *  Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/pm.h>
+#include <linux/pm_legacy.h>
+#include <asm/apm.h>
+
+#define MODNAME "apm"
+
+/*
+ * 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                 16
+
+struct apm_queue {
+       unsigned int            event_head;
+       unsigned int            event_tail;
+       apm_event_t             events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+       struct list_head        list;
+
+       unsigned int            suser: 1;
+       unsigned int            writer: 1;
+       unsigned int            reader: 1;
+
+       int                     suspend_result;
+       unsigned int            suspend_state;
+#define SUSPEND_NONE   0               /* no suspend pending */
+#define SUSPEND_PENDING        1               /* suspend pending read */
+#define SUSPEND_READ   2               /* suspend read, pending ack */
+#define SUSPEND_ACKED  3               /* suspend acked */
+#define SUSPEND_DONE   4               /* suspend completed */
+
+       struct apm_queue        queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DECLARE_COMPLETION(kapmd_exit);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+int apm_suspended;
+EXPORT_SYMBOL(apm_suspended);
+
+/* Platform-specific apm_read_proc(). */
+int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
+EXPORT_SYMBOL(apm_get_info);
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+       return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+       q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+       q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+       if (q->event_head == q->event_tail) {
+               static int notified;
+
+               if (notified++ == 0)
+                       printk(KERN_ERR "apm: an event queue overflowed\n");
+
+               q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       }
+       q->events[q->event_head] = event;
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+       if (as->suser && as->writer) {
+               switch (event) {
+               case APM_SYS_SUSPEND:
+               case APM_USER_SUSPEND:
+                       /*
+                        * If this user already has a suspend pending,
+                        * don't queue another one.
+                        */
+                       if (as->suspend_state != SUSPEND_NONE)
+                               return;
+
+                       as->suspend_state = SUSPEND_PENDING;
+                       suspends_pending++;
+                       break;
+               }
+       }
+       queue_add_event(&as->queue, event);
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+       struct apm_user *as;
+
+       down_read(&user_list_lock);
+
+       list_for_each_entry(as, &apm_user_list, list)
+               if (as != sender && as->reader)
+                       queue_event_one_user(as, event);
+
+       up_read(&user_list_lock);
+       wake_up_interruptible(&apm_waitqueue);
+}
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+       spin_lock_irq(&kapmd_queue_lock);
+       queue_add_event(&kapmd_queue, event);
+       spin_unlock_irq(&kapmd_queue_lock);
+
+       wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
+
+static void apm_suspend(void)
+{
+       struct apm_user *as;
+       int err;
+
+       apm_suspended = 1;
+       err = pm_suspend(PM_SUSPEND_MEM);
+
+       /*
+        * Anyone on the APM queues will think we're still suspended.
+        * Send a message so everyone knows we're now awake again.
+        */
+       queue_event(APM_NORMAL_RESUME, NULL);
+
+       /*
+        * Finally, wake up anyone who is sleeping on the suspend.
+        */
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               as->suspend_result = err;
+               as->suspend_state = SUSPEND_DONE;
+       }
+       up_read(&user_list_lock);
+
+       wake_up(&apm_suspend_waitqueue);
+       apm_suspended = 0;
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct apm_user *as = fp->private_data;
+       apm_event_t event;
+       int i = count, ret = 0;
+
+       if (count < sizeof(apm_event_t))
+               return -EINVAL;
+
+       if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+               return -EAGAIN;
+
+       wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+       while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+               event = queue_get_event(&as->queue);
+
+               ret = -EFAULT;
+               if (copy_to_user(buf, &event, sizeof(event)))
+                       break;
+
+               if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+                       as->suspend_state = SUSPEND_READ;
+
+               buf += sizeof(event);
+               i -= sizeof(event);
+       }
+
+       if (i < count)
+               ret = count - i;
+
+       return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+       struct apm_user *as = fp->private_data;
+
+       poll_wait(fp, &apm_waitqueue, wait);
+       return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+       struct apm_user *as = filp->private_data;
+       unsigned long flags;
+       int err = -EINVAL;
+
+       if (!as->suser || !as->writer)
+               return -EPERM;
+
+       switch (cmd) {
+       case APM_IOC_SUSPEND:
+               as->suspend_result = -EINTR;
+
+               if (as->suspend_state == SUSPEND_READ) {
+                       /*
+                        * If we read a suspend command from /dev/apm_bios,
+                        * then the corresponding APM_IOC_SUSPEND ioctl is
+                        * interpreted as an acknowledge.
+                        */
+                       as->suspend_state = SUSPEND_ACKED;
+                       suspends_pending--;
+               } else {
+                       /*
+                        * Otherwise it is a request to suspend the system.
+                        * Queue an event for all readers, and expect an
+                        * acknowledge from all writers who haven't already
+                        * acknowledged.
+                        */
+                       queue_event(APM_USER_SUSPEND, as);
+               }
+
+               /*
+                * If there are no further acknowledges required, suspend
+                * the system.
+                */
+               if (suspends_pending == 0)
+                       apm_suspend();
+
+               /*
+                * Wait for the suspend/resume to complete.  If there are
+                * pending acknowledges, we wait here for them.
+                *
+                * Note that we need to ensure that the PM subsystem does
+                * not kick us out of the wait when it suspends the threads.
+                */
+               flags = current->flags;
+               current->flags |= PF_NOFREEZE;
+
+               /*
+                * Note: do not allow a thread which is acking the suspend
+                * to escape until the resume is complete.
+                */
+               if (as->suspend_state == SUSPEND_ACKED)
+                       wait_event(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+               else
+                       wait_event_interruptible(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+
+               current->flags = flags;
+               err = as->suspend_result;
+               as->suspend_state = SUSPEND_NONE;
+               break;
+       }
+
+       return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as = filp->private_data;
+       filp->private_data = NULL;
+
+       down_write(&user_list_lock);
+       list_del(&as->list);
+       up_write(&user_list_lock);
+
+       /*
+        * We are now unhooked from the chain.  As far as new
+        * events are concerned, we no longer exist.  However, we
+        * need to balance suspends_pending, which means the
+        * possibility of sleeping.
+        */
+       if (as->suspend_state != SUSPEND_NONE) {
+               suspends_pending -= 1;
+               if (suspends_pending == 0)
+                       apm_suspend();
+       }
+
+       kfree(as);
+       return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as;
+
+       as = kzalloc(sizeof(*as), GFP_KERNEL);
+       if (as) {
+               /*
+                * 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->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+               as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+               down_write(&user_list_lock);
+               list_add(&as->list, &apm_user_list);
+               up_write(&user_list_lock);
+
+               filp->private_data = as;
+       }
+
+       return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+       .owner          = THIS_MODULE,
+       .read           = apm_read,
+       .poll           = apm_poll,
+       .ioctl          = apm_ioctl,
+       .open           = apm_open,
+       .release        = apm_release,
+};
+
+static struct miscdevice apm_device = {
+       .minor          = APM_MINOR_DEV,
+       .name           = "apm_bios",
+       .fops           = &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   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
+ */
+static int apm_read_proc(char *buf, char **start, off_t fpos, int length)
+{
+       if (likely(apm_get_info))
+               return apm_get_info(buf, start, fpos, length);
+
+       return -EINVAL;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+       daemonize("kapmd");
+       current->flags |= PF_NOFREEZE;
+
+       do {
+               apm_event_t event;
+
+               wait_event_interruptible(kapmd_wait,
+                               !queue_empty(&kapmd_queue) || !pm_active);
+
+               if (!pm_active)
+                       break;
+
+               spin_lock_irq(&kapmd_queue_lock);
+               event = 0;
+               if (!queue_empty(&kapmd_queue))
+                       event = queue_get_event(&kapmd_queue);
+               spin_unlock_irq(&kapmd_queue_lock);
+
+               switch (event) {
+               case 0:
+                       break;
+
+               case APM_LOW_BATTERY:
+               case APM_POWER_STATUS_CHANGE:
+                       queue_event(event, NULL);
+                       break;
+
+               case APM_USER_SUSPEND:
+               case APM_SYS_SUSPEND:
+                       queue_event(event, NULL);
+                       if (suspends_pending == 0)
+                               apm_suspend();
+                       break;
+
+               case APM_CRITICAL_SUSPEND:
+                       apm_suspend();
+                       break;
+               }
+       } while (1);
+
+       complete_and_exit(&kapmd_exit, 0);
+}
+
+static int __init apm_init(void)
+{
+       int ret;
+
+       pm_active = 1;
+
+       ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+       if (unlikely(ret < 0)) {
+               pm_active = 0;
+               return ret;
+       }
+
+       create_proc_info_entry("apm", 0, NULL, apm_read_proc);
+
+       ret = misc_register(&apm_device);
+       if (unlikely(ret != 0)) {
+               remove_proc_entry("apm", NULL);
+
+               pm_active = 0;
+               wake_up(&kapmd_wait);
+               wait_for_completion(&kapmd_exit);
+       }
+
+       return ret;
+}
+
+static void __exit apm_exit(void)
+{
+       misc_deregister(&apm_device);
+       remove_proc_entry("apm", NULL);
+
+       pm_active = 0;
+       wake_up(&kapmd_wait);
+       wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell, Andriy Skulysh");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
index f1f9ab87f0b0fb3025bd7fe71690a7f0a809c0dd..3e5fa1e24df097b450c5a33dd035d94cd04f2d09 100644 (file)
@@ -10,7 +10,8 @@
  */
 
 #include <linux/init.h>
-
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -32,8 +33,6 @@
 /* SH4 can't access PCMCIA interface through P2 area.
  * we must remap it with appropreate attribute bit of the page set.
  * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
 
 #if defined(CONFIG_CF_AREA6)
 #define slot_no 0
@@ -41,9 +40,6 @@
 #define slot_no 1
 #endif
 
-/* defined in mm/ioremap.c */
-extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-
 /* use this pointer to access to directly connected compact flash io area*/
 void *cf_io_base;
 
@@ -62,7 +58,7 @@ static int __init allocate_cf_area(void)
                return -ENOMEM;
        }
 /*     printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n",
-               paddrbase, psize, prot.pgprot, cf_io_base);*/
+               paddrbase, psize, prot.pgprot, cf_io_base);*/
 
        /* XXX : do we need attribute and common-memory area also? */
 
@@ -87,7 +83,7 @@ static int __init cf_init_default(void)
 }
 
 #if defined(CONFIG_SH_SOLUTION_ENGINE)
-#include <asm/se/se.h>
+#include <asm/se.h>
 
 /*
  * SolutionEngine
index 59d5b748752fee2f271889b9150923d276763249..fb5dac0693827df8316d15ec253b7005c0349b39 100644 (file)
@@ -8,6 +8,5 @@ obj-$(CONFIG_CPU_SH2)           += sh2/
 obj-$(CONFIG_CPU_SH3)          += sh3/
 obj-$(CONFIG_CPU_SH4)          += sh4/
 
-obj-$(CONFIG_SH_RTC)           += rtc.o
 obj-$(CONFIG_UBC_WAKEUP)       += ubc.o
 obj-$(CONFIG_SH_ADC)           += adc.o
index 97fa37f42b841e2bcaabbef4e07a933fad0fb73b..51ec64cdf348ebb30c61ffab7be21e4dc2ffa1d6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/cpu/clock.c - SuperH clock framework
  *
- *  Copyright (C) 2005  Paul Mundt
+ *  Copyright (C) 2005, 2006  Paul Mundt
  *
  * This clock framework is derived from the OMAP version by:
  *
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/kref.h>
 #include <linux/seq_file.h>
@@ -24,7 +25,7 @@
 
 static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
-static DECLARE_MUTEX(clock_list_sem);
+static DEFINE_MUTEX(clock_list_sem);
 
 /*
  * Each subtype is expected to define the init routines for these clocks,
@@ -140,21 +141,21 @@ void clk_disable(struct clk *clk)
 
 int clk_register(struct clk *clk)
 {
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
 
        list_add(&clk->node, &clock_list);
        kref_init(&clk->kref);
 
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 
        return 0;
 }
 
 void clk_unregister(struct clk *clk)
 {
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
        list_del(&clk->node);
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 }
 
 inline unsigned long clk_get_rate(struct clk *clk)
@@ -198,14 +199,14 @@ struct clk *clk_get(const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
        list_for_each_entry(p, &clock_list, node) {
                if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
                        clk = p;
                        break;
                }
        }
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 
        return clk;
 }
@@ -225,7 +226,7 @@ int __init clk_init(void)
 {
        int i, ret = 0;
 
-       BUG_ON(unlikely(!master_clk.rate));
+       BUG_ON(!master_clk.rate);
 
        for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
                struct clk *clk = onchip_clocks[i];
index 868e68b288809a406fe01801d50c87f393ec9cf4..bfb90eb0b7a6caabc529f33e49c5371a74f62208 100644 (file)
@@ -4,6 +4,7 @@
  * CPU init code
  *
  * Copyright (C) 2002, 2003  Paul Mundt
+ * Copyright (C) 2003  Richard Curnow
  *
  * 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
@@ -13,6 +14,7 @@
 #include <linux/kernel.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
+#include <asm/page.h>
 #include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
@@ -51,7 +53,15 @@ static void __init cache_init(void)
        ccr = ctrl_inl(CCR);
 
        /*
-        * If the cache is already enabled .. flush it.
+        * At this point we don't know whether the cache is enabled or not - a
+        * bootloader may have enabled it.  There are at least 2 things that
+        * could be dirty in the cache at this point:
+        * 1. kernel command line set up by boot loader
+        * 2. spilled registers from the prolog of this function
+        * => before re-initialising the cache, we must do a purge of the whole
+        * cache out to memory for safety.  As long as nothing is spilled
+        * during the loop to lines that have already been done, this is safe.
+        * - RPC
         */
        if (ccr & CCR_CACHE_ENABLE) {
                unsigned long ways, waysize, addrstart;
@@ -98,6 +108,8 @@ static void __init cache_init(void)
        /* Force EMODE if possible */
        if (cpu_data->dcache.ways > 1)
                flags |= CCR_CACHE_EMODE;
+       else
+               flags &= ~CCR_CACHE_EMODE;
 #endif
 
 #ifdef CONFIG_SH_WRITETHROUGH
@@ -112,6 +124,9 @@ static void __init cache_init(void)
        /* Turn on OCRAM -- halve the OC */
        flags |= CCR_CACHE_ORA;
        cpu_data->dcache.sets >>= 1;
+
+       cpu_data->dcache.way_size = cpu_data->dcache.sets *
+                                   cpu_data->dcache.linesz;
 #endif
 
        ctrl_outl(flags, CCR);
@@ -184,6 +199,10 @@ asmlinkage void __init sh_cpu_init(void)
        /* Init the cache */
        cache_init();
 
+       shm_align_mask = max_t(unsigned long,
+                              cpu_data->dcache.way_size - 1,
+                              PAGE_SIZE - 1);
+
        /* Disable the FPU */
        if (fpu_disabled) {
                printk("FPU Disabled\n");
index e3cccea15e1d1dd670792f92314dc463efeb2f66..1c034c283f594aee3b73ac546909dfb173bfbd17 100644 (file)
@@ -3,5 +3,6 @@
 #
 obj-y  += ipr.o imask.o
 
-obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
-obj-$(CONFIG_CPU_HAS_INTC2_IRQ)        += intc2.o
+obj-$(CONFIG_CPU_HAS_PINT_IRQ)         += pint.o
+obj-$(CONFIG_CPU_HAS_MASKREG_IRQ)      += maskreg.o
+obj-$(CONFIG_CPU_HAS_INTC2_IRQ)                += intc2.o
index 30064bf6e154bf5f46a2f5c0cfea97bf50c616d4..e30e4b7aa70e739be7ed77211b32d5cc04f1801f 100644 (file)
@@ -241,9 +241,9 @@ static struct intc2_init {
        /* 110-111 reserved/unused */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
        { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
-#ifdef CONFIG_SH_RTC
-       { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
-#endif
+       { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+       { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+       { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
        { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
        { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
        { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
index 0f545941fb4fdbcd2444f1a085c36da650108db1..f785822cd5dea4fb32e908a93f328c00ec3ffa4d 100644 (file)
@@ -57,31 +57,27 @@ static struct hw_interrupt_type ipr_irq_type = {
 
 static void disable_ipr_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
        unsigned int addr = ipr_data[irq].addr;
        unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
 
        /* Set the priority in IPR to 0 */
-       local_irq_save(flags);
        val = ctrl_inw(addr);
        val &= mask;
        ctrl_outw(val, addr);
-       local_irq_restore(flags);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
        unsigned int addr = ipr_data[irq].addr;
        int priority = ipr_data[irq].priority;
        unsigned short value = (priority << ipr_data[irq].shift);
 
        /* Set priority in IPR back to original value */
-       local_irq_save(flags);
        val = ctrl_inw(addr);
        val |= value;
        ctrl_outw(val, addr);
-       local_irq_restore(flags);
 }
 
 static void mask_and_ack_ipr(unsigned int irq)
@@ -89,6 +85,7 @@ static void mask_and_ack_ipr(unsigned int irq)
        disable_ipr_irq(irq);
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
        /* This is needed when we use edge triggered setting */
        /* XXX: Is it really needed? */
@@ -123,7 +120,7 @@ void __init init_IRQ(void)
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
        make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
        make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
-#if defined(CONFIG_SH_RTC)
+#ifdef RTC_IRQ
        make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
 #endif
 
@@ -162,6 +159,7 @@ void __init init_IRQ(void)
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
        /*
         * Initialize the Interrupt Controller (INTC)
@@ -192,6 +190,8 @@ void __init init_IRQ(void)
        /* Perform the machine specific initialisation */
        if (sh_mv.mv_init_irq != NULL)
                sh_mv.mv_init_irq();
+
+       irq_ctx_init(smp_processor_id());
 }
 
 #if !defined(CONFIG_CPU_HAS_PINT_IRQ)
diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c
new file mode 100644 (file)
index 0000000..492db31
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Interrupt handling for Simple external interrupt mask register
+ *
+ * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
+ *
+ * This is for the machine which have single 16 bit register
+ * for masking external IRQ individually.
+ * Each bit of the register is for masking each interrupt.
+ *
+ * This file may be copied or modified under the terms of the GNU
+ * General Public License.  See linux/COPYING for more information.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+/* address of external interrupt mask register */
+unsigned long irq_mask_register;
+
+/* forward declaration */
+static unsigned int startup_maskreg_irq(unsigned int irq);
+static void shutdown_maskreg_irq(unsigned int irq);
+static void enable_maskreg_irq(unsigned int irq);
+static void disable_maskreg_irq(unsigned int irq);
+static void mask_and_ack_maskreg(unsigned int);
+static void end_maskreg_irq(unsigned int irq);
+
+/* hw_interrupt_type */
+static struct hw_interrupt_type maskreg_irq_type = {
+       .typename = "Mask Register",
+       .startup = startup_maskreg_irq,
+       .shutdown = shutdown_maskreg_irq,
+       .enable = enable_maskreg_irq,
+       .disable = disable_maskreg_irq,
+       .ack = mask_and_ack_maskreg,
+       .end = end_maskreg_irq
+};
+
+/* actual implementatin */
+static unsigned int startup_maskreg_irq(unsigned int irq)
+{
+       enable_maskreg_irq(irq);
+       return 0; /* never anything pending */
+}
+
+static void shutdown_maskreg_irq(unsigned int irq)
+{
+       disable_maskreg_irq(irq);
+}
+
+static void disable_maskreg_irq(unsigned int irq)
+{
+       unsigned short val, mask = 0x01 << irq;
+
+       BUG_ON(!irq_mask_register);
+
+       /* Set "irq"th bit */
+       val = ctrl_inw(irq_mask_register);
+       val |= mask;
+       ctrl_outw(val, irq_mask_register);
+}
+
+static void enable_maskreg_irq(unsigned int irq)
+{
+       unsigned short val, mask = ~(0x01 << irq);
+
+       BUG_ON(!irq_mask_register);
+
+       /* Clear "irq"th bit */
+       val = ctrl_inw(irq_mask_register);
+       val &= mask;
+       ctrl_outw(val, irq_mask_register);
+}
+
+static void mask_and_ack_maskreg(unsigned int irq)
+{
+       disable_maskreg_irq(irq);
+}
+
+static void end_maskreg_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               enable_maskreg_irq(irq);
+}
+
+void make_maskreg_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &maskreg_irq_type;
+       disable_maskreg_irq(irq);
+}
index 80cd8108d36aca86a86e45da2decc7418b620135..17f47b373d6ed2cb0ea49bfb8f05f0f5a799e9d8 100644 (file)
@@ -48,26 +48,22 @@ static struct hw_interrupt_type pint_irq_type = {
 
 static void disable_pint_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
 
-       local_irq_save(flags);
        val = ctrl_inw(INTC_INTER);
        val &= ~(1 << (irq - PINT_IRQ_BASE));
        ctrl_outw(val, INTC_INTER);     /* disable PINTn */
        portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
-       local_irq_restore(flags);
 }
 
 static void enable_pint_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
 
-       local_irq_save(flags);
        val = ctrl_inw(INTC_INTER);
        val |= 1 << (irq - PINT_IRQ_BASE);
        ctrl_outw(val, INTC_INTER);     /* enable PINTn */
        portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
-       local_irq_restore(flags);
 }
 
 static void mask_and_ack_pint(unsigned int irq)
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c
deleted file mode 100644 (file)
index 4304cf7..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * linux/arch/sh/kernel/rtc.c -- SH3 / SH4 on-chip RTC support
- *
- *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/io.h>
-#include <asm/rtc.h>
-
-void sh_rtc_gettimeofday(struct timespec *ts)
-{
-       unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
-       unsigned long flags;
-
- again:
-       do {
-               local_irq_save(flags);
-               ctrl_outb(0, RCR1);  /* Clear CF-bit */
-               sec128 = ctrl_inb(R64CNT);
-               sec = ctrl_inb(RSECCNT);
-               min = ctrl_inb(RMINCNT);
-               hr  = ctrl_inb(RHRCNT);
-               wk  = ctrl_inb(RWKCNT);
-               day = ctrl_inb(RDAYCNT);
-               mon = ctrl_inb(RMONCNT);
-#if defined(CONFIG_CPU_SH4)
-               yr  = ctrl_inw(RYRCNT);
-               yr100 = (yr >> 8);
-               yr &= 0xff;
-#else
-               yr  = ctrl_inb(RYRCNT);
-               yr100 = (yr == 0x99) ? 0x19 : 0x20;
-#endif
-               sec2 = ctrl_inb(R64CNT);
-               cf_bit = ctrl_inb(RCR1) & RCR1_CF;
-               local_irq_restore(flags);
-       } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
-
-       BCD_TO_BIN(yr100);
-       BCD_TO_BIN(yr);
-       BCD_TO_BIN(mon);
-       BCD_TO_BIN(day);
-       BCD_TO_BIN(hr);
-       BCD_TO_BIN(min);
-       BCD_TO_BIN(sec);
-
-       if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
-           hr > 23 || min > 59 || sec > 59) {
-               printk(KERN_ERR
-                      "SH RTC: invalid value, resetting to 1 Jan 2000\n");
-               local_irq_save(flags);
-               ctrl_outb(RCR2_RESET, RCR2);  /* Reset & Stop */
-               ctrl_outb(0, RSECCNT);
-               ctrl_outb(0, RMINCNT);
-               ctrl_outb(0, RHRCNT);
-               ctrl_outb(6, RWKCNT);
-               ctrl_outb(1, RDAYCNT);
-               ctrl_outb(1, RMONCNT);
-#if defined(CONFIG_CPU_SH4)
-               ctrl_outw(0x2000, RYRCNT);
-#else
-               ctrl_outb(0, RYRCNT);
-#endif
-               ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start */
-               goto again;
-       }
-
-#if RTC_BIT_INVERTED != 0
-       if ((sec128 & RTC_BIT_INVERTED))
-               sec--;
-#endif
-
-       ts->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
-       ts->tv_nsec = ((sec128 * 1000000) / 128) * 1000;
-}
-
-/*
- * Changed to only care about tv_sec, and not the full timespec struct
- * (i.e. tv_nsec).  It can easily be switched to timespec for future cpus
- * that support setting usec or nsec RTC values.
- */
-int sh_rtc_settimeofday(const time_t secs)
-{
-       int retval = 0;
-       int real_seconds, real_minutes, cmos_minutes;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ctrl_outb(RCR2_RESET, RCR2);  /* Reset pre-scaler & stop RTC */
-
-       cmos_minutes = ctrl_inb(RMINCNT);
-       BCD_TO_BIN(cmos_minutes);
-
-       /*
-        * since we're only adjusting minutes and seconds,
-        * don't interfere with hour overflow. This avoids
-        * messing with unknown time zones but requires your
-        * RTC not to be off by more than 15 minutes
-        */
-       real_seconds = secs % 60;
-       real_minutes = secs / 60;
-       if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-               real_minutes += 30;     /* correct for half hour time zone */
-       real_minutes %= 60;
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               BIN_TO_BCD(real_seconds);
-               BIN_TO_BCD(real_minutes);
-               ctrl_outb(real_seconds, RSECCNT);
-               ctrl_outb(real_minutes, RMINCNT);
-       } else {
-               printk(KERN_WARNING
-                      "set_rtc_time: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
-       }
-
-       ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start RTC */
-       local_irq_restore(flags);
-
-       return retval;
-}
index b54dbb9a0c8612232bf14b003dee3ec0c23c21f6..58d3815695ffa70d21f15f4243461223b0b70064 100644 (file)
@@ -4,10 +4,21 @@
 
 obj-y  := ex.o probe.o
 
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7706)       += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7707)       += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7708)       += setup-sh7708.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7300)       += setup-sh7300.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o
+
+# Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH3)                        := clock-sh3.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7300)     := clock-sh7300.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7705)     := clock-sh7705.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7706)     := clock-sh7706.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7709)     := clock-sh7709.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7710)     := clock-sh7300.o
 
 obj-y  += $(clock-y)
-
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7706.c b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
new file mode 100644 (file)
index 0000000..0cf96f9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh7706.c
+ *
+ * SH7706 support for the clock framework
+ *
+ *  Copyright (C) 2006  Takashi YOSHII
+ *
+ * Based on arch/sh/kernel/cpu/sh3/clock-sh7709.c
+ *  Copyright (C) 2005  Andriy Skulysh
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int stc_multipliers[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+static int ifc_divisors[]    = { 1, 2, 4, 1, 3, 1, 1, 1 };
+static int pfc_divisors[]    = { 1, 2, 4, 1, 3, 6, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+       clk->rate *= pfc_divisors[idx];
+}
+
+static struct clk_ops sh7706_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+       clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7706_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
+
+       clk->rate = clk->parent->rate / stc_multipliers[idx];
+}
+
+static struct clk_ops sh7706_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
+
+       clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7706_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7706_clk_ops[] = {
+       &sh7706_master_clk_ops,
+       &sh7706_module_clk_ops,
+       &sh7706_bus_clk_ops,
+       &sh7706_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7706_clk_ops))
+               *ops = sh7706_clk_ops[idx];
+}
index cc04e9e239ffb13e7c0b4cea5b362d71a5541829..44daf44833f90852e0f39557784fab51e2fc8ae2 100644 (file)
@@ -84,8 +84,12 @@ ENTRY(interrupt_table)
        .long   do_IRQ  !      rovi
        .long   do_IRQ                  
        .long   do_IRQ                  /* 5E0 */
-#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7710)
        .long   do_IRQ  ! 32 IRQ  irq0  /* 600 */
        .long   do_IRQ  ! 33      irq1
        .long   do_IRQ  ! 34      irq2
@@ -147,6 +151,51 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 62 PCC  pcc0i
        .long   do_IRQ  ! 63      pcc1i /* 9E0 */
 #endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+       .long   exception_none  ! 61    /* 9A0 */
+       .long   exception_none  ! 62
+       .long   exception_none  ! 63
+       .long   exception_none  ! 64    /* A00 */
+       .long   exception_none  ! 65
+       .long   exception_none  ! 66
+       .long   exception_none  ! 67
+       .long   exception_none  ! 68
+       .long   exception_none  ! 69
+       .long   exception_none  ! 70
+       .long   exception_none  ! 71
+       .long   exception_none  ! 72    /* B00 */
+       .long   exception_none  ! 73
+       .long   exception_none  ! 74
+       .long   exception_none  ! 75
+       .long   do_IRQ  ! 76 DMAC2 dei4 /* B80 */
+       .long   do_IRQ  ! 77 DMAC2 dei5
+       .long   exception_none  ! 78
+       .long   do_IRQ  ! 79 IPSEC ipseci /* BE0 */
+       .long   do_IRQ  ! 80 EDMAC eint0 /* C00 */
+       .long   do_IRQ  ! 81 EDMAC eint1
+       .long   do_IRQ  ! 82 EDMAC eint2
+       .long   exception_none  ! 83    /* C60 */
+       .long   exception_none  ! 84
+       .long   exception_none  ! 85
+       .long   exception_none  ! 86
+       .long   exception_none  ! 87
+       .long   exception_none  ! 88    /* D00 */
+       .long   exception_none  ! 89
+       .long   exception_none  ! 90
+       .long   exception_none  ! 91
+       .long   exception_none  ! 92
+       .long   exception_none  ! 93
+       .long   exception_none  ! 94
+       .long   exception_none  ! 95
+       .long   do_IRQ  ! 96 SIOF eri0  /* E00 */
+       .long   do_IRQ  ! 97      txi0
+       .long   do_IRQ  ! 98      rxi0
+       .long   do_IRQ  ! 99      cci0
+       .long   do_IRQ  ! 100     eri1  /* E80 */
+       .long   do_IRQ  ! 101     txi1
+       .long   do_IRQ  ! 102     rxi2
+       .long   do_IRQ  ! 103     cci3
+#endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7300)
        .long   do_IRQ  ! 64
        .long   do_IRQ  ! 65
@@ -195,4 +244,3 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 108
 #endif
 #endif
-
index 5cdc8863860120b7e77e9444e75960f98fd340c0..e67098836290ea9ff583991fe0a6e05c27876175 100644 (file)
@@ -72,6 +72,12 @@ int __init detect_cpu_and_cache_system(void)
                cpu_data->dcache.sets           = 256;
                cpu_data->type = CPU_SH7729;
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7706)
+               cpu_data->type = CPU_SH7706;
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+               cpu_data->type = CPU_SH7710;
+#endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
                cpu_data->type = CPU_SH7705;
 
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7300.c b/arch/sh/kernel/cpu/sh3/setup-sh7300.c
new file mode 100644 (file)
index 0000000..ab4d204
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7300 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xa4430000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 80, 80, 80, 80 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7300_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7300_devices_setup(void)
+{
+       return platform_add_devices(sh7300_devices,
+                                   ARRAY_SIZE(sh7300_devices));
+}
+__initcall(sh7300_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
new file mode 100644 (file)
index 0000000..a8e41c5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SH7705 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xa4400000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .mapbase        = 0xa4410000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 56, 57, 59, 58 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7705_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7705_devices_setup(void)
+{
+       return platform_add_devices(sh7705_devices,
+                                   ARRAY_SIZE(sh7705_devices));
+}
+__initcall(sh7705_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7708.c b/arch/sh/kernel/cpu/sh3/setup-sh7708.c
new file mode 100644 (file)
index 0000000..f933723
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7708 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfffffe80,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 23, 24, 25, 0 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7708_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7708_devices_setup(void)
+{
+       return platform_add_devices(sh7708_devices,
+                                   ARRAY_SIZE(sh7708_devices));
+}
+__initcall(sh7708_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
new file mode 100644 (file)
index 0000000..ff43ef2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7707/SH7709 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfffffe80,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 23, 24, 25, 0 },
+       }, {
+               .mapbase        = 0xa4000150,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 56, 57, 59, 58 },
+       }, {
+               .mapbase        = 0xa4000140,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_IRDA,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7709_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7709_devices_setup(void)
+{
+       return platform_add_devices(sh7709_devices,
+                                   ARRAY_SIZE(sh7709_devices));
+}
+__initcall(sh7709_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
new file mode 100644 (file)
index 0000000..895f99e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7710 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xa4400000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7710_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7710_devices_setup(void)
+{
+       return platform_add_devices(sh7710_devices,
+                                   ARRAY_SIZE(sh7710_devices));
+}
+__initcall(sh7710_devices_setup);
index 3d5cafc71ae307d8c9c2abc6c730a889436b8ffb..8dbf3895ece7406c248e2405f8bc18b2392f0f81 100644 (file)
@@ -7,6 +7,16 @@ obj-y  := ex.o probe.o
 obj-$(CONFIG_SH_FPU)                    += fpu.o
 obj-$(CONFIG_SH_STORE_QUEUES)          += sq.o
 
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7750)       += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7760)       += setup-sh7760.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180)      += setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH4_202)      += setup-sh4-202.o
+
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH4)                        := clock-sh4.o
 clock-$(CONFIG_CPU_SUBTYPE_SH73180)    := clock-sh73180.o
index 26a27df0650509c127f3339cd90a821365ca2b62..7146893a6cca5c3ebf33b78565eb2144c2f2f188 100644 (file)
@@ -72,6 +72,7 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 1110
        .long   exception_error         
        ! Internal hardware
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
        .long   do_IRQ  ! TMU0 tuni0    /* 400 */
        .long   do_IRQ  ! TMU1 tuni1
        .long   do_IRQ  ! TMU2 tuni2
@@ -122,6 +123,13 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 45      dmte5
        .long   do_IRQ  ! 46      dmte6
        .long   do_IRQ  ! 47      dmte7         /* 7E0 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+       .long   do_IRQ  ! 44 IIC1 ali           /* 780 */
+       .long   do_IRQ  ! 45      tacki
+       .long   do_IRQ  ! 46      waiti
+       .long   do_IRQ  ! 47      dtei          /* 7E0 */
+       .long   do_IRQ  ! 48 DMAC dei0          /* 800 */
+       .long   do_IRQ  ! 49      dei1          /* 820 */
 #else
        .long   exception_error                 ! 44    /* 780 */
        .long   exception_error                 ! 45
@@ -131,7 +139,8 @@ ENTRY(interrupt_table)
 #if defined(CONFIG_SH_FPU)
        .long   do_fpu_state_restore    ! 48    /* 800 */
        .long   do_fpu_state_restore    ! 49    /* 820 */
-#else
+#elif !defined(CONFIG_CPU_SUBTYPE_SH7343) && \
+      !defined(CONFIG_CPU_SUBTYPE_SH73180)
        .long   exception_error
        .long   exception_error
 #endif
@@ -224,7 +233,7 @@ ENTRY(interrupt_table)
        .long   exception_error
        .long   do_IRQ  ! ADC   adi
        .long   do_IRQ  ! CMT   cmti    /* FA0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
+#elif defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7343)
        .long   do_IRQ  !  50 0x840
        .long   do_IRQ  !  51 0x860
        .long   do_IRQ  !  52 0x880
@@ -379,5 +388,168 @@ ENTRY(interrupt_table)
        .long   exception_error                 ! 141 0x13a0
        .long   exception_error                 ! 142 0x13c0
        .long   exception_error                 ! 143 0x13e0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+       .long   do_IRQ  !  50 0x840
+       .long   do_IRQ  !  51 0x860
+       .long   do_IRQ  !  52 0x880
+       .long   do_IRQ  !  53 0x8a0
+       .long   do_IRQ  !  54 0x8c0
+       .long   do_IRQ  !  55 0x8e0
+       .long   do_IRQ  !  56 0x900
+       .long   do_IRQ  !  57 0x920
+       .long   do_IRQ  !  58 0x940
+       .long   do_IRQ  !  59 0x960
+       .long   do_IRQ  !  60 0x980
+       .long   do_IRQ  !  61 0x9a0
+       .long   do_IRQ  !  62 0x9c0
+       .long   do_IRQ  !  63 0x9e0
+       .long   do_IRQ  !  64 0xa00
+       .long   do_IRQ  !  65 0xa20
+       .long   do_IRQ  !  66 0xa4d
+       .long   do_IRQ  !  67 0xa60
+       .long   do_IRQ  !  68 0xa80
+       .long   do_IRQ  !  69 0xaa0
+       .long   do_IRQ  !  70 0xac0
+       .long   do_IRQ  !  71 0xae0
+       .long   do_IRQ  !  72 0xb00
+       .long   do_IRQ  !  73 0xb20
+       .long   do_IRQ  !  74 0xb40
+       .long   do_IRQ  !  75 0xb60
+       .long   do_IRQ  !  76 0xb80
+       .long   do_IRQ  !  77 0xba0
+       .long   do_IRQ  !  78 0xbc0
+       .long   do_IRQ  !  79 0xbe0
+       .long   do_IRQ  !  80 0xc00
+       .long   do_IRQ  !  81 0xc20
+       .long   do_IRQ  !  82 0xc40
+       .long   do_IRQ  !  83 0xc60
+       .long   do_IRQ  !  84 0xc80
+       .long   do_IRQ  !  85 0xca0
+       .long   do_IRQ  !  86 0xcc0
+       .long   do_IRQ  !  87 0xce0
+       .long   do_IRQ  !  88 0xd00
+       .long   do_IRQ  !  89 0xd20
+       .long   do_IRQ  !  90 0xd40
+       .long   do_IRQ  !  91 0xd60
+       .long   do_IRQ  !  92 0xd80
+       .long   do_IRQ  !  93 0xda0
+       .long   do_IRQ  !  94 0xdc0
+       .long   do_IRQ  !  95 0xde0
+       .long   do_IRQ  !  96 0xe00
+       .long   do_IRQ  !  97 0xe20
+       .long   do_IRQ  !  98 0xe40
+       .long   do_IRQ  !  99 0xe60
+       .long   do_IRQ  ! 100 0xe80
+       .long   do_IRQ  ! 101 0xea0
+       .long   do_IRQ  ! 102 0xec0
+       .long   do_IRQ  ! 103 0xee0
+       .long   do_IRQ  ! 104 0xf00
+       .long   do_IRQ  ! 105 0xf20
+       .long   do_IRQ  ! 106 0xf40
+       .long   do_IRQ  ! 107 0xf60
+       .long   do_IRQ  ! 108 0xf80
+#endif
+#else
+       .long   exception_error         /* 400 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! RTC   ati
+       .long   do_IRQ  !       pri
+       .long   do_IRQ  !       cui
+       .long   exception_error
+       .long   exception_error         /* 500 */
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! WDT   iti     /* 560 */
+       .long   do_IRQ  ! TMU-ch0
+       .long   do_IRQ  ! TMU-ch1
+       .long   do_IRQ  ! TMU-ch2
+       .long   do_IRQ  ! ticpi2        /* 5E0 */
+       .long   do_IRQ  ! 32 Hitachi UDI        /* 600 */
+       .long   exception_error
+       .long   do_IRQ  ! 34 DMAC dmte0
+       .long   do_IRQ  ! 35      dmte1
+       .long   do_IRQ  ! 36      dmte2
+       .long   do_IRQ  ! 37      dmte3
+       .long   do_IRQ  ! 38      dmae
+       .long   exception_error                 ! 39    /* 6E0 */
+       .long   do_IRQ  ! 40 SCIF-ch0 eri               /* 700 */
+       .long   do_IRQ  ! 41          rxi
+       .long   do_IRQ  ! 42          bri
+       .long   do_IRQ  ! 43          txi
+       .long   do_IRQ  ! 44 DMAC dmte4         /* 780 */
+       .long   do_IRQ  ! 45      dmte5
+       .long   do_IRQ  ! 46      dmte6
+       .long   do_IRQ  ! 47      dmte7         /* 7E0 */
+#if defined(CONFIG_SH_FPU)
+       .long   do_fpu_state_restore    ! 48    /* 800 */
+       .long   do_fpu_state_restore    ! 49    /* 820 */
+#else
+       .long   exception_error
+       .long   exception_error
+#endif
+       .long   exception_error                 /* 840 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! 56 CMT        /* 900 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! 60 HAC
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! PCI serr      /* A00 */
+       .long   do_IRQ  !     INTA
+       .long   do_IRQ  !     INTB
+       .long   do_IRQ  !     INTC
+       .long   do_IRQ  !     INTD
+       .long   do_IRQ  !     err
+       .long   do_IRQ  !     pwd3
+       .long   do_IRQ  !     pwd2
+       .long   do_IRQ  !     pwd1      /* B00 */
+       .long   do_IRQ  !     pwd0
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! SCIF-ch1 eri  /* B80 */
+       .long   do_IRQ  !          rxi
+       .long   do_IRQ  !          bri
+       .long   do_IRQ  !          txi
+       .long   do_IRQ  ! SIOF          /* C00 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! HSPI          /* C80 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! MMCIF fatat   /* D00 */
+       .long   do_IRQ  !       tran
+       .long   do_IRQ  !       err
+       .long   do_IRQ  !       frdy
+       .long   do_IRQ  ! DMAC dmint8   /* D80 */
+       .long   do_IRQ  !      dmint9
+       .long   do_IRQ  !      dmint10
+       .long   do_IRQ  !      dmint11
+       .long   do_IRQ  ! TMU-ch3       /* E00 */
+       .long   do_IRQ  ! TMU-ch4
+       .long   do_IRQ  ! TMU-ch5
+       .long   exception_error
+       .long   do_IRQ  ! SSI
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! FLCTL flste   /* F00 */
+       .long   do_IRQ  !       fltend
+       .long   do_IRQ  !       fltrq0
+       .long   do_IRQ  !       fltrq1
+       .long   do_IRQ  ! GPIO gpioi0   /* F80 */
+       .long   do_IRQ  !      gpioi1
+       .long   do_IRQ  !      gpioi2
+       .long   do_IRQ  !      gpioi3
 #endif
 
index 42427b79697bfca67abd57c3358463f8a9363f5b..c294de1e14a3c2ae8d994e25a7f238fcbce9b8b6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * CPU Subtype Probing for SH-4.
  *
- * Copyright (C) 2001, 2002, 2003, 2004  Paul Mundt
+ * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -29,7 +29,7 @@ int __init detect_cpu_and_cache_system(void)
                [9] = (1 << 16)
        };
 
-       pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff;
+       pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff;
        prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
        cvr = (ctrl_inl(CCN_CVR));
 
@@ -38,7 +38,6 @@ int __init detect_cpu_and_cache_system(void)
         */
        cpu_data->icache.way_incr       = (1 << 13);
        cpu_data->icache.entry_shift    = 5;
-       cpu_data->icache.entry_mask     = 0x1fe0;
        cpu_data->icache.sets           = 256;
        cpu_data->icache.ways           = 1;
        cpu_data->icache.linesz         = L1_CACHE_BYTES;
@@ -48,13 +47,29 @@ int __init detect_cpu_and_cache_system(void)
         */
        cpu_data->dcache.way_incr       = (1 << 14);
        cpu_data->dcache.entry_shift    = 5;
-       cpu_data->dcache.entry_mask     = 0x3fe0;
        cpu_data->dcache.sets           = 512;
        cpu_data->dcache.ways           = 1;
        cpu_data->dcache.linesz         = L1_CACHE_BYTES;
 
-       /* Set the FPU flag, virtually all SH-4's have one */
-       cpu_data->flags |= CPU_HAS_FPU;
+       /*
+        * Setup some generic flags we can probe
+        * (L2 and DSP detection only work on SH-4A)
+        */
+       if (((pvr >> 16) & 0xff) == 0x10) {
+               if ((cvr & 0x02000000) == 0)
+                       cpu_data->flags |= CPU_HAS_L2_CACHE;
+               if ((cvr & 0x10000000) == 0)
+                       cpu_data->flags |= CPU_HAS_DSP;
+
+               cpu_data->flags |= CPU_HAS_LLSC;
+       }
+
+       /* FPU detection works for everyone */
+       if ((cvr & 0x20000000) == 1)
+               cpu_data->flags |= CPU_HAS_FPU;
+
+       /* Mask off the upper chip ID */
+       pvr &= 0xffff;
 
        /*
         * Probe the underlying processor version/revision and
@@ -63,56 +78,101 @@ int __init detect_cpu_and_cache_system(void)
        switch (pvr) {
        case 0x205:
                cpu_data->type = CPU_SH7750;
-               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+                                  CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
                break;
        case 0x206:
                cpu_data->type = CPU_SH7750S;
-               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+                                  CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
                break;
        case 0x1100:
                cpu_data->type = CPU_SH7751;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x2000:
                cpu_data->type = CPU_SH73180;
                cpu_data->icache.ways = 4;
                cpu_data->dcache.ways = 4;
-               cpu_data->flags &= ~CPU_HAS_FPU;
+               cpu_data->flags |= CPU_HAS_LLSC;
+               break;
+       case 0x2001:
+       case 0x2004:
+               cpu_data->type = CPU_SH7770;
+               cpu_data->icache.ways = 4;
+               cpu_data->dcache.ways = 4;
+
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
+               break;
+       case 0x2006:
+       case 0x200A:
+               if (prr == 0x61)
+                       cpu_data->type = CPU_SH7781;
+               else
+                       cpu_data->type = CPU_SH7780;
+
+               cpu_data->icache.ways = 4;
+               cpu_data->dcache.ways = 4;
+
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+                                  CPU_HAS_LLSC;
+               break;
+       case 0x3000:
+       case 0x3003:
+               cpu_data->type = CPU_SH7343;
+               cpu_data->icache.ways = 4;
+               cpu_data->dcache.ways = 4;
+               cpu_data->flags |= CPU_HAS_LLSC;
                break;
        case 0x8000:
                cpu_data->type = CPU_ST40RA;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x8100:
                cpu_data->type = CPU_ST40GX1;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x700:
                cpu_data->type = CPU_SH4_501;
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
-
-               /* No FPU on the SH4-500 series.. */
-               cpu_data->flags &= ~CPU_HAS_FPU;
+               cpu_data->flags |= CPU_HAS_PTEA;
                break;
        case 0x600:
                cpu_data->type = CPU_SH4_202;
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x500 ... 0x501:
                switch (prr) {
-                   case 0x10: cpu_data->type = CPU_SH7750R; break;
-                   case 0x11: cpu_data->type = CPU_SH7751R; break;
-                   case 0x50: cpu_data->type = CPU_SH7760;  break;
+               case 0x10:
+                       cpu_data->type = CPU_SH7750R;
+                       break;
+               case 0x11:
+                       cpu_data->type = CPU_SH7751R;
+                       break;
+               case 0x50 ... 0x5f:
+                       cpu_data->type = CPU_SH7760;
+                       break;
                }
 
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
 
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+
                break;
        default:
                cpu_data->type = CPU_SH_NONE;
                break;
        }
 
+#ifdef CONFIG_SH_DIRECT_MAPPED
+       cpu_data->icache.ways = 1;
+       cpu_data->dcache.ways = 1;
+#endif
+
        /*
         * On anything that's not a direct-mapped cache, look to the CVR
         * for I/D-cache specifics.
@@ -121,18 +181,56 @@ int __init detect_cpu_and_cache_system(void)
                size = sizes[(cvr >> 20) & 0xf];
                cpu_data->icache.way_incr       = (size >> 1);
                cpu_data->icache.sets           = (size >> 6);
-               cpu_data->icache.entry_mask     =
-                       (cpu_data->icache.way_incr - (1 << 5));
+
        }
 
+       /* Setup the rest of the I-cache info */
+       cpu_data->icache.entry_mask = cpu_data->icache.way_incr -
+                                     cpu_data->icache.linesz;
+
+       cpu_data->icache.way_size = cpu_data->icache.sets *
+                                   cpu_data->icache.linesz;
+
+       /* And the rest of the D-cache */
        if (cpu_data->dcache.ways > 1) {
                size = sizes[(cvr >> 16) & 0xf];
                cpu_data->dcache.way_incr       = (size >> 1);
                cpu_data->dcache.sets           = (size >> 6);
-               cpu_data->dcache.entry_mask     =
-                       (cpu_data->dcache.way_incr - (1 << 5));
+       }
+
+       cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr -
+                                     cpu_data->dcache.linesz;
+
+       cpu_data->dcache.way_size = cpu_data->dcache.sets *
+                                   cpu_data->dcache.linesz;
+
+       /*
+        * Setup the L2 cache desc
+        *
+        * SH-4A's have an optional PIPT L2.
+        */
+       if (cpu_data->flags & CPU_HAS_L2_CACHE) {
+               /*
+                * Size calculation is much more sensible
+                * than it is for the L1.
+                *
+                * Sizes are 128KB, 258KB, 512KB, and 1MB.
+                */
+               size = (cvr & 0xf) << 17;
+
+               BUG_ON(!size);
+
+               cpu_data->scache.way_incr       = (1 << 16);
+               cpu_data->scache.entry_shift    = 5;
+               cpu_data->scache.ways           = 4;
+               cpu_data->scache.linesz         = L1_CACHE_BYTES;
+               cpu_data->scache.entry_mask     =
+                       (cpu_data->scache.way_incr - cpu_data->scache.linesz);
+               cpu_data->scache.sets           = size /
+                       (cpu_data->scache.linesz * cpu_data->scache.ways);
+               cpu_data->scache.way_size       =
+                       (cpu_data->scache.sets * cpu_data->scache.linesz);
        }
 
        return 0;
 }
-
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
new file mode 100644 (file)
index 0000000..6e4e965
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH4-202 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe80000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh4202_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh4202_devices_setup(void)
+{
+       return platform_add_devices(sh4202_devices,
+                                   ARRAY_SIZE(sh4202_devices));
+}
+__initcall(sh4202_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4/setup-sh73180.c
new file mode 100644 (file)
index 0000000..cc9ea1e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH73180 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe80000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 80, 81, 83, 82 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh73180_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh73180_devices_setup(void)
+{
+       return platform_add_devices(sh73180_devices,
+                                   ARRAY_SIZE(sh73180_devices));
+}
+__initcall(sh73180_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4/setup-sh7343.c
new file mode 100644 (file)
index 0000000..91d61cf
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7343 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 80, 81, 83, 82 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7343_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7343_devices_setup(void)
+{
+       return platform_add_devices(sh7343_devices,
+                                   ARRAY_SIZE(sh7343_devices));
+}
+__initcall(sh7343_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
new file mode 100644 (file)
index 0000000..50812d5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SH7750/SH7751 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 23, 24, 25, 0 },
+       }, {
+               .mapbase        = 0xffe80000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7750_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7750_devices_setup(void)
+{
+       return platform_add_devices(sh7750_devices,
+                                   ARRAY_SIZE(sh7750_devices));
+}
+__initcall(sh7750_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
new file mode 100644 (file)
index 0000000..97f1c9a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7760 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfe600000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .mapbase        = 0xfe610000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 72, 73, 75, 74 },
+       }, {
+               .mapbase        = 0xfe620000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 76, 77, 79, 78 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7760_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7760_devices_setup(void)
+{
+       return platform_add_devices(sh7760_devices,
+                                   ARRAY_SIZE(sh7760_devices));
+}
+__initcall(sh7760_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4/setup-sh7770.c
new file mode 100644 (file)
index 0000000..6a04cc5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7770 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xff923000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 61, 61, 61, 61 },
+       }, {
+               .mapbase        = 0xff924000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 62, 62, 62, 62 },
+       }, {
+               .mapbase        = 0xff925000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 63, 63, 63, 63 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7770_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7770_devices_setup(void)
+{
+       return platform_add_devices(sh7770_devices,
+                                   ARRAY_SIZE(sh7770_devices));
+}
+__initcall(sh7770_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
new file mode 100644 (file)
index 0000000..72493f2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * SH7780 Setup
+ *
+ *  Copyright (C) 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct resource rtc_resources[] = {
+       [0] = {
+               .start  = 0xffe80000,
+               .end    = 0xffe80000 + 0x58 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       [1] = {
+               /* Period IRQ */
+               .start  = 21,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* Carry IRQ */
+               .start  = 22,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [3] = {
+               /* Alarm IRQ */
+               .start  = 23,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device rtc_device = {
+       .name           = "sh-rtc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(rtc_resources),
+       .resource       = rtc_resources,
+};
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .mapbase        = 0xffe10000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 76, 77, 79, 78 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7780_devices[] __initdata = {
+       &rtc_device,
+       &sci_device,
+};
+
+static int __init sh7780_devices_setup(void)
+{
+       return platform_add_devices(sh7780_devices,
+                                   ARRAY_SIZE(sh7780_devices));
+}
+__initcall(sh7780_devices_setup);
index b09805f3ee23799e8a78379856211d2b967a30f0..7bcc73f9b8df535ad8887383aeac71a8b2491ef5 100644 (file)
@@ -1,49 +1,52 @@
 /*
- * arch/sh/kernel/cpu/sq.c
+ * arch/sh/kernel/cpu/sh4/sq.c
  *
  * General management API for SH-4 integrated Store Queues
  *
- * Copyright (C) 2001, 2002, 2003, 2004  Paul Mundt
+ * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2001, 2002  M. R. Brown
  *
- * Some of this code has been adopted directly from the old arch/sh/mm/sq.c
- * hack that was part of the LinuxDC project. For all intents and purposes,
- * this is a completely new interface that really doesn't have much in common
- * with the old zone-based approach at all. In fact, it's only listed here for
- * general completeness.
- *
  * 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/init.h>
+#include <linux/cpu.h>
+#include <linux/bitmap.h>
+#include <linux/sysdev.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
 #include <linux/vmalloc.h>
-
+#include <linux/mm.h>
 #include <asm/io.h>
 #include <asm/page.h>
-#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
 #include <asm/cpu/sq.h>
 
-static LIST_HEAD(sq_mapping_list);
+struct sq_mapping;
+
+struct sq_mapping {
+       const char *name;
+
+       unsigned long sq_addr;
+       unsigned long addr;
+       unsigned int size;
+
+       struct sq_mapping *next;
+};
+
+static struct sq_mapping *sq_mapping_list;
 static DEFINE_SPINLOCK(sq_mapping_lock);
+static kmem_cache_t *sq_cache;
+static unsigned long *sq_bitmap;
 
-/**
- * sq_flush - Flush (prefetch) the store queue cache
- * @addr: the store queue address to flush
- *
- * Executes a prefetch instruction on the specified store queue cache,
- * so that the cached data is written to physical memory.
- */
-inline void sq_flush(void *addr)
-{
-       __asm__ __volatile__ ("pref @%0" : : "r" (addr) : "memory");
-}
+#define store_queue_barrier()                  \
+do {                                           \
+       (void)ctrl_inl(P4SEG_STORE_QUE);        \
+       ctrl_outl(0, P4SEG_STORE_QUE + 0);      \
+       ctrl_outl(0, P4SEG_STORE_QUE + 8);      \
+} while (0);
 
 /**
  * sq_flush_range - Flush (prefetch) a specific SQ range
@@ -56,152 +59,73 @@ inline void sq_flush(void *addr)
 void sq_flush_range(unsigned long start, unsigned int len)
 {
        volatile unsigned long *sq = (unsigned long *)start;
-       unsigned long dummy;
 
        /* Flush the queues */
        for (len >>= 5; len--; sq += 8)
-               sq_flush((void *)sq);
+               prefetchw((void *)sq);
 
        /* Wait for completion */
-       dummy = ctrl_inl(P4SEG_STORE_QUE);
-
-       ctrl_outl(0, P4SEG_STORE_QUE + 0);
-       ctrl_outl(0, P4SEG_STORE_QUE + 8);
+       store_queue_barrier();
 }
 
-static struct sq_mapping *__sq_alloc_mapping(unsigned long virt, unsigned long phys, unsigned long size, const char *name)
+static inline void sq_mapping_list_add(struct sq_mapping *map)
 {
-       struct sq_mapping *map;
-
-       if (virt + size > SQ_ADDRMAX)
-               return ERR_PTR(-ENOSPC);
-
-       map = kmalloc(sizeof(struct sq_mapping), GFP_KERNEL);
-       if (!map)
-               return ERR_PTR(-ENOMEM);
+       struct sq_mapping **p, *tmp;
 
-       INIT_LIST_HEAD(&map->list);
+       spin_lock_irq(&sq_mapping_lock);
 
-       map->sq_addr    = virt;
-       map->addr       = phys;
-       map->size       = size + 1;
-       map->name       = name;
+       p = &sq_mapping_list;
+       while ((tmp = *p) != NULL)
+               p = &tmp->next;
 
-       list_add(&map->list, &sq_mapping_list);
+       map->next = tmp;
+       *p = map;
 
-       return map;
+       spin_unlock_irq(&sq_mapping_lock);
 }
 
-static unsigned long __sq_get_next_addr(void)
+static inline void sq_mapping_list_del(struct sq_mapping *map)
 {
-       if (!list_empty(&sq_mapping_list)) {
-               struct list_head *pos, *tmp;
-
-               /*
-                * Read one off the list head, as it will have the highest
-                * mapped allocation. Set the next one up right above it.
-                *
-                * This is somewhat sub-optimal, as we don't look at
-                * gaps between allocations or anything lower then the
-                * highest-level allocation.
-                *
-                * However, in the interest of performance and the general
-                * lack of desire to do constant list rebalancing, we don't
-                * worry about it.
-                */
-               list_for_each_safe(pos, tmp, &sq_mapping_list) {
-                       struct sq_mapping *entry;
-
-                       entry = list_entry(pos, typeof(*entry), list);
-
-                       return entry->sq_addr + entry->size;
+       struct sq_mapping **p, *tmp;
+
+       spin_lock_irq(&sq_mapping_lock);
+
+       for (p = &sq_mapping_list; (tmp = *p); p = &tmp->next)
+               if (tmp == map) {
+                       *p = tmp->next;
+                       break;
                }
-       }
 
-       return P4SEG_STORE_QUE;
+       spin_unlock_irq(&sq_mapping_lock);
 }
 
-/**
- * __sq_remap - Perform a translation from the SQ to a phys addr
- * @map: sq mapping containing phys and store queue addresses.
- *
- * Maps the store queue address specified in the mapping to the physical
- * address specified in the mapping.
- */
-static struct sq_mapping *__sq_remap(struct sq_mapping *map)
+static int __sq_remap(struct sq_mapping *map, unsigned long flags)
 {
-       unsigned long flags, pteh, ptel;
+#if defined(CONFIG_MMU)
        struct vm_struct *vma;
-       pgprot_t pgprot;
-
-       /*
-        * Without an MMU (or with it turned off), this is much more
-        * straightforward, as we can just load up each queue's QACR with
-        * the physical address appropriately masked.
-        */
-
-       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
-       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
 
-#ifdef CONFIG_MMU
-       /*
-        * With an MMU on the other hand, things are slightly more involved.
-        * Namely, we have to have a direct mapping between the SQ addr and
-        * the associated physical address in the UTLB by way of setting up
-        * a virt<->phys translation by hand. We do this by simply specifying
-        * the SQ addr in UTLB.VPN and the associated physical address in
-        * UTLB.PPN.
-        *
-        * Notably, even though this is a special case translation, and some
-        * of the configuration bits are meaningless, we're still required
-        * to have a valid ASID context in PTEH.
-        *
-        * We could also probably get by without explicitly setting PTEA, but
-        * we do it here just for good measure.
-        */
-       spin_lock_irqsave(&sq_mapping_lock, flags);
-
-       pteh = map->sq_addr;
-       ctrl_outl((pteh & MMU_VPN_MASK) | get_asid(), MMU_PTEH);
-
-       ptel = map->addr & PAGE_MASK;
-       ctrl_outl(((ptel >> 28) & 0xe) | (ptel & 0x1), MMU_PTEA);
-
-       pgprot = pgprot_noncached(PAGE_KERNEL);
-
-       ptel &= _PAGE_FLAGS_HARDWARE_MASK;
-       ptel |= pgprot_val(pgprot);
-       ctrl_outl(ptel, MMU_PTEL);
-
-       __asm__ __volatile__ ("ldtlb" : : : "memory");
-
-       spin_unlock_irqrestore(&sq_mapping_lock, flags);
-
-       /*
-        * Next, we need to map ourselves in the kernel page table, so that
-        * future accesses after a TLB flush will be handled when we take a
-        * page fault.
-        *
-        * Theoretically we could just do this directly and not worry about
-        * setting up the translation by hand ahead of time, but for the
-        * cases where we want a one-shot SQ mapping followed by a quick
-        * writeout before we hit the TLB flush, we do it anyways. This way
-        * we at least save ourselves the initial page fault overhead.
-        */
        vma = __get_vm_area(map->size, VM_ALLOC, map->sq_addr, SQ_ADDRMAX);
        if (!vma)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
        vma->phys_addr = map->addr;
 
        if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr,
-                            map->size, pgprot_val(pgprot))) {
+                            map->size, flags)) {
                vunmap(vma->addr);
-               return NULL;
+               return -EAGAIN;
        }
-#endif /* CONFIG_MMU */
+#else
+       /*
+        * Without an MMU (or with it turned off), this is much more
+        * straightforward, as we can just load up each queue's QACR with
+        * the physical address appropriately masked.
+        */
+       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
+       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
+#endif
 
-       return map;
+       return 0;
 }
 
 /**
@@ -209,42 +133,65 @@ static struct sq_mapping *__sq_remap(struct sq_mapping *map)
  * @phys: Physical address of mapping.
  * @size: Length of mapping.
  * @name: User invoking mapping.
+ * @flags: Protection flags.
  *
  * Remaps the physical address @phys through the next available store queue
  * address of @size length. @name is logged at boot time as well as through
- * the procfs interface.
- *
- * A pre-allocated and filled sq_mapping pointer is returned, and must be
- * cleaned up with a call to sq_unmap() when the user is done with the
- * mapping.
+ * the sysfs interface.
  */
-struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name)
+unsigned long sq_remap(unsigned long phys, unsigned int size,
+                      const char *name, unsigned long flags)
 {
        struct sq_mapping *map;
-       unsigned long virt, end;
+       unsigned long end;
        unsigned int psz;
+       int ret, page;
 
        /* Don't allow wraparound or zero size */
        end = phys + size - 1;
-       if (!size || end < phys)
-               return NULL;
+       if (unlikely(!size || end < phys))
+               return -EINVAL;
        /* Don't allow anyone to remap normal memory.. */
-       if (phys < virt_to_phys(high_memory))
-               return NULL;
+       if (unlikely(phys < virt_to_phys(high_memory)))
+               return -EINVAL;
 
        phys &= PAGE_MASK;
+       size = PAGE_ALIGN(end + 1) - phys;
+
+       map = kmem_cache_alloc(sq_cache, GFP_KERNEL);
+       if (unlikely(!map))
+               return -ENOMEM;
+
+       map->addr = phys;
+       map->size = size;
+       map->name = name;
+
+       page = bitmap_find_free_region(sq_bitmap, 0x04000000,
+                                      get_order(map->size));
+       if (unlikely(page < 0)) {
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
+
+       ret = __sq_remap(map, flags);
+       if (unlikely(ret != 0))
+               goto out;
+
+       psz = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+       pr_info("sqremap: %15s  [%4d page%s]  va 0x%08lx   pa 0x%08lx\n",
+               likely(map->name) ? map->name : "???",
+               psz, psz == 1 ? " " : "s",
+               map->sq_addr, map->addr);
 
-       size  = PAGE_ALIGN(end + 1) - phys;
-       virt  = __sq_get_next_addr();
-       psz   = (size + (PAGE_SIZE - 1)) / PAGE_SIZE;
-       map   = __sq_alloc_mapping(virt, phys, size, name);
+       sq_mapping_list_add(map);
 
-       printk("sqremap: %15s  [%4d page%s]  va 0x%08lx   pa 0x%08lx\n",
-              map->name ? map->name : "???",
-              psz, psz == 1 ? " " : "s",
-              map->sq_addr, map->addr);
+       return map->sq_addr;
 
-       return __sq_remap(map);
+out:
+       kmem_cache_free(sq_cache, map);
+       return ret;
 }
 
 /**
@@ -255,188 +202,198 @@ struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *n
  * sq_remap(). Also frees up the pte that was previously inserted into
  * the kernel page table and discards the UTLB translation.
  */
-void sq_unmap(struct sq_mapping *map)
+void sq_unmap(unsigned long vaddr)
 {
-       if (map->sq_addr > (unsigned long)high_memory)
-               vfree((void *)(map->sq_addr & PAGE_MASK));
+       struct sq_mapping **p, *map;
+       struct vm_struct *vma;
+       int page;
 
-       list_del(&map->list);
-       kfree(map);
-}
+       for (p = &sq_mapping_list; (map = *p); p = &map->next)
+               if (map->sq_addr == vaddr)
+                       break;
 
-/**
- * sq_clear - Clear a store queue range
- * @addr: Address to start clearing from.
- * @len: Length to clear.
- *
- * A quick zero-fill implementation for clearing out memory that has been
- * remapped through the store queues.
- */
-void sq_clear(unsigned long addr, unsigned int len)
-{
-       int i;
+       if (unlikely(!map)) {
+               printk("%s: bad store queue address 0x%08lx\n",
+                      __FUNCTION__, vaddr);
+               return;
+       }
 
-       /* Clear out both queues linearly */
-       for (i = 0; i < 8; i++) {
-               ctrl_outl(0, addr + i + 0);
-               ctrl_outl(0, addr + i + 8);
+       page = (map->sq_addr - P4SEG_STORE_QUE) >> PAGE_SHIFT;
+       bitmap_release_region(sq_bitmap, page, get_order(map->size));
+
+#ifdef CONFIG_MMU
+       vma = remove_vm_area((void *)(map->sq_addr & PAGE_MASK));
+       if (!vma) {
+               printk(KERN_ERR "%s: bad address 0x%08lx\n",
+                      __FUNCTION__, map->sq_addr);
+               return;
        }
+#endif
+
+       sq_mapping_list_del(map);
 
-       sq_flush_range(addr, len);
+       kmem_cache_free(sq_cache, map);
 }
 
-/**
- * sq_vma_unmap - Unmap a VMA range
- * @area: VMA containing range.
- * @addr: Start of range.
- * @len: Length of range.
+/*
+ * Needlessly complex sysfs interface. Unfortunately it doesn't seem like
+ * there is any other easy way to add things on a per-cpu basis without
+ * putting the directory entries somewhere stupid and having to create
+ * links in sysfs by hand back in to the per-cpu directories.
  *
- * Searches the sq_mapping_list for a mapping matching the sq addr @addr,
- * and subsequently frees up the entry. Further cleanup is done by generic
- * code.
+ * Some day we may want to have an additional abstraction per store
+ * queue, but considering the kobject hell we already have to deal with,
+ * it's simply not worth the trouble.
  */
-static void sq_vma_unmap(struct vm_area_struct *area,
-                        unsigned long addr, size_t len)
-{
-       struct list_head *pos, *tmp;
+static struct kobject *sq_kobject[NR_CPUS];
 
-       list_for_each_safe(pos, tmp, &sq_mapping_list) {
-               struct sq_mapping *entry;
+struct sq_sysfs_attr {
+       struct attribute attr;
+       ssize_t (*show)(char *buf);
+       ssize_t (*store)(const char *buf, size_t count);
+};
 
-               entry = list_entry(pos, typeof(*entry), list);
+#define to_sq_sysfs_attr(attr) container_of(attr, struct sq_sysfs_attr, attr)
 
-               if (entry->sq_addr == addr) {
-                       /*
-                        * We could probably get away without doing the tlb flush
-                        * here, as generic code should take care of most of this
-                        * when unmapping the rest of the VMA range for us. Leave
-                        * it in for added sanity for the time being..
-                        */
-                       __flush_tlb_page(get_asid(), entry->sq_addr & PAGE_MASK);
+static ssize_t sq_sysfs_show(struct kobject *kobj, struct attribute *attr,
+                            char *buf)
+{
+       struct sq_sysfs_attr *sattr = to_sq_sysfs_attr(attr);
 
-                       list_del(&entry->list);
-                       kfree(entry);
+       if (likely(sattr->show))
+               return sattr->show(buf);
 
-                       return;
-               }
-       }
+       return -EIO;
 }
 
-/**
- * sq_vma_sync - Sync a VMA range
- * @area: VMA containing range.
- * @start: Start of range.
- * @len: Length of range.
- * @flags: Additional flags.
- *
- * Synchronizes an sq mapped range by flushing the store queue cache for
- * the duration of the mapping.
- *
- * Used internally for user mappings, which must use msync() to prefetch
- * the store queue cache.
- */
-static int sq_vma_sync(struct vm_area_struct *area,
-                      unsigned long start, size_t len, unsigned int flags)
+static ssize_t sq_sysfs_store(struct kobject *kobj, struct attribute *attr,
+                             const char *buf, size_t count)
 {
-       sq_flush_range(start, len);
+       struct sq_sysfs_attr *sattr = to_sq_sysfs_attr(attr);
 
-       return 0;
+       if (likely(sattr->store))
+               return sattr->store(buf, count);
+
+       return -EIO;
 }
 
-static struct vm_operations_struct sq_vma_ops = {
-       .unmap  = sq_vma_unmap,
-       .sync   = sq_vma_sync,
-};
+static ssize_t mapping_show(char *buf)
+{
+       struct sq_mapping **list, *entry;
+       char *p = buf;
 
-/**
- * sq_mmap - mmap() for /dev/cpu/sq
- * @file: unused.
- * @vma: VMA to remap.
- *
- * Remap the specified vma @vma through the store queues, and setup associated
- * information for the new mapping. Also build up the page tables for the new
- * area.
- */
-static int sq_mmap(struct file *file, struct vm_area_struct *vma)
+       for (list = &sq_mapping_list; (entry = *list); list = &entry->next)
+               p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n",
+                            entry->sq_addr, entry->sq_addr + entry->size,
+                            entry->addr, entry->name);
+
+       return p - buf;
+}
+
+static ssize_t mapping_store(const char *buf, size_t count)
 {
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long size = vma->vm_end - vma->vm_start;
-       struct sq_mapping *map;
+       unsigned long base = 0, len = 0;
 
-       /*
-        * We're not interested in any arbitrary virtual address that has
-        * been stuck in the VMA, as we already know what addresses we
-        * want. Save off the size, and reposition the VMA to begin at
-        * the next available sq address.
-        */
-       vma->vm_start = __sq_get_next_addr();
-       vma->vm_end   = vma->vm_start + size;
+       sscanf(buf, "%lx %lx", &base, &len);
+       if (!base)
+               return -EIO;
 
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       if (likely(len)) {
+               int ret = sq_remap(base, len, "Userspace",
+                                  pgprot_val(PAGE_SHARED));
+               if (ret < 0)
+                       return ret;
+       } else
+               sq_unmap(base);
 
-       vma->vm_flags |= VM_IO | VM_RESERVED;
+       return count;
+}
 
-       map = __sq_alloc_mapping(vma->vm_start, offset, size, "Userspace");
+static struct sq_sysfs_attr mapping_attr =
+       __ATTR(mapping, 0644, mapping_show, mapping_store);
 
-       if (io_remap_pfn_range(vma, map->sq_addr, map->addr >> PAGE_SHIFT,
-                               size, vma->vm_page_prot))
-               return -EAGAIN;
+static struct attribute *sq_sysfs_attrs[] = {
+       &mapping_attr.attr,
+       NULL,
+};
 
-       vma->vm_ops = &sq_vma_ops;
+static struct sysfs_ops sq_sysfs_ops = {
+       .show   = sq_sysfs_show,
+       .store  = sq_sysfs_store,
+};
 
-       return 0;
-}
+static struct kobj_type ktype_percpu_entry = {
+       .sysfs_ops      = &sq_sysfs_ops,
+       .default_attrs  = sq_sysfs_attrs,
+};
 
-#ifdef CONFIG_PROC_FS
-static int sq_mapping_read_proc(char *buf, char **start, off_t off,
-                               int len, int *eof, void *data)
+static int __devinit sq_sysdev_add(struct sys_device *sysdev)
 {
-       struct list_head *pos;
-       char *p = buf;
+       unsigned int cpu = sysdev->id;
+       struct kobject *kobj;
 
-       list_for_each_prev(pos, &sq_mapping_list) {
-               struct sq_mapping *entry;
+       sq_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+       if (unlikely(!sq_kobject[cpu]))
+               return -ENOMEM;
 
-               entry = list_entry(pos, typeof(*entry), list);
+       kobj = sq_kobject[cpu];
+       kobj->parent = &sysdev->kobj;
+       kobject_set_name(kobj, "%s", "sq");
+       kobj->ktype = &ktype_percpu_entry;
 
-               p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n", entry->sq_addr,
-                            entry->sq_addr + entry->size - 1, entry->addr,
-                            entry->name);
-       }
-
-       return p - buf;
+       return kobject_register(kobj);
 }
-#endif
 
-static struct file_operations sq_fops = {
-       .owner          = THIS_MODULE,
-       .mmap           = sq_mmap,
-};
+static int __devexit sq_sysdev_remove(struct sys_device *sysdev)
+{
+       unsigned int cpu = sysdev->id;
+       struct kobject *kobj = sq_kobject[cpu];
 
-static struct miscdevice sq_dev = {
-       .minor          = STORE_QUEUE_MINOR,
-       .name           = "sq",
-       .fops           = &sq_fops,
+       kobject_unregister(kobj);
+       return 0;
+}
+
+static struct sysdev_driver sq_sysdev_driver = {
+       .add            = sq_sysdev_add,
+       .remove         = __devexit_p(sq_sysdev_remove),
 };
 
 static int __init sq_api_init(void)
 {
-       int ret;
+       unsigned int nr_pages = 0x04000000 >> PAGE_SHIFT;
+       unsigned int size = (nr_pages + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
+       int ret = -ENOMEM;
+
        printk(KERN_NOTICE "sq: Registering store queue API.\n");
 
-       create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
+       sq_cache = kmem_cache_create("store_queue_cache",
+                               sizeof(struct sq_mapping), 0, 0,
+                               NULL, NULL);
+       if (unlikely(!sq_cache))
+               return ret;
 
-       ret = misc_register(&sq_dev);
-       if (ret)
-               remove_proc_entry("sq_mapping", NULL);
+       sq_bitmap = kzalloc(size, GFP_KERNEL);
+       if (unlikely(!sq_bitmap))
+               goto out;
+
+       ret = sysdev_driver_register(&cpu_sysdev_class, &sq_sysdev_driver);
+       if (unlikely(ret != 0))
+               goto out;
+
+       return 0;
+
+out:
+       kfree(sq_bitmap);
+       kmem_cache_destroy(sq_cache);
 
        return ret;
 }
 
 static void __exit sq_api_exit(void)
 {
-       misc_deregister(&sq_dev);
-       remove_proc_entry("sq_mapping", NULL);
+       sysdev_driver_unregister(&cpu_sysdev_class, &sq_sysdev_driver);
+       kfree(sq_bitmap);
+       kmem_cache_destroy(sq_cache);
 }
 
 module_init(sq_api_init);
@@ -445,11 +402,7 @@ module_exit(sq_api_exit);
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
 MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(STORE_QUEUE_MINOR);
 
 EXPORT_SYMBOL(sq_remap);
 EXPORT_SYMBOL(sq_unmap);
-EXPORT_SYMBOL(sq_clear);
-EXPORT_SYMBOL(sq_flush);
 EXPORT_SYMBOL(sq_flush_range);
-
index 1378db375e175c9905f583382ab02bacbec9d54d..a00022722e9e43c8ee4734e539ac97383be6790d 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1999, 2000  Niibe Yutaka
  *  Copyright (C) 2002  M. R. Brown
- *  Copyright (C) 2004  Paul Mundt
+ *  Copyright (C) 2004 - 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
@@ -49,7 +49,7 @@ static int __init sh_console_setup(struct console *co, char *options)
        return 0;
 }
 
-static struct console early_console = {
+static struct console bios_console = {
        .name           = "bios",
        .write          = sh_console_write,
        .setup          = sh_console_setup,
@@ -59,34 +59,43 @@ static struct console early_console = {
 #endif
 
 #ifdef CONFIG_EARLY_SCIF_CONSOLE
+#include <linux/serial_core.h>
+#include "../../../drivers/serial/sh-sci.h"
+
+#ifdef CONFIG_CPU_SH4
 #define SCIF_REG       0xffe80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
+#define SCIF_REG       0xfffe9800
+#else
+#error "Undefined SCIF for this subtype"
+#endif
+
+static struct uart_port scif_port = {
+       .mapbase        = SCIF_REG,
+       .membase        = (char __iomem *)SCIF_REG,
+};
 
 static void scif_sercon_putc(int c)
 {
-       while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
+       while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16))
+               ;
 
-       ctrl_outb(c, SCIF_REG + 12);
-       ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
+       sci_out(&scif_port, SCxTDR, c);
+       sci_in(&scif_port, SCxSR);
+       sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+
+       while ((sci_in(&scif_port, SCxSR) & 0x40) == 0);
+               ;
 
        if (c == '\n')
                scif_sercon_putc('\r');
 }
 
-static void scif_sercon_flush(void)
-{
-       ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-
-       while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
-
-       ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-}
-
-static void scif_sercon_write(struct console *con, const char *s, unsigned count)
+static void scif_sercon_write(struct console *con, const char *s,
+                             unsigned count)
 {
        while (count-- > 0)
                scif_sercon_putc(*s++);
-
-       scif_sercon_flush();
 }
 
 static int __init scif_sercon_setup(struct console *con, char *options)
@@ -96,7 +105,7 @@ static int __init scif_sercon_setup(struct console *con, char *options)
        return 0;
 }
 
-static struct console early_console = {
+static struct console scif_console = {
        .name           = "sercon",
        .write          = scif_sercon_write,
        .setup          = scif_sercon_setup,
@@ -104,7 +113,7 @@ static struct console early_console = {
        .index          = -1,
 };
 
-void scif_sercon_init(int baud)
+static void scif_sercon_init(int baud)
 {
        ctrl_outw(0, SCIF_REG + 8);
        ctrl_outw(0, SCIF_REG);
@@ -122,16 +131,61 @@ void scif_sercon_init(int baud)
 }
 #endif
 
-void __init enable_early_printk(void)
+/*
+ * Setup a default console, if more than one is compiled in, rely on the
+ * earlyprintk= parsing to give priority.
+ */
+static struct console *early_console =
+#ifdef CONFIG_SH_STANDARD_BIOS
+       &bios_console
+#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
+       &scif_console
+#else
+       NULL
+#endif
+       ;
+
+static int __initdata keep_early;
+
+int __init setup_early_printk(char *opt)
 {
-#ifdef CONFIG_EARLY_SCIF_CONSOLE
-       scif_sercon_init(115200);
+       char *space;
+       char buf[256];
+
+       strlcpy(buf, opt, sizeof(buf));
+       space = strchr(buf, ' ');
+       if (space)
+               *space = 0;
+
+       if (strstr(buf, "keep"))
+               keep_early = 1;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+       if (!strncmp(buf, "bios", 4))
+               early_console = &bios_console;
+#endif
+#if defined(CONFIG_EARLY_SCIF_CONSOLE)
+       if (!strncmp(buf, "serial", 6)) {
+               early_console = &scif_console;
+
+#ifdef CONFIG_CPU_SH4
+               scif_sercon_init(115200);
+#endif
+       }
 #endif
-       register_console(&early_console);
+
+       if (likely(early_console))
+               register_console(early_console);
+
+       return 1;
 }
+__setup("earlyprintk=", setup_early_printk);
 
-void disable_early_printk(void)
+void __init disable_early_printk(void)
 {
-       unregister_console(&early_console);
+       if (!keep_early) {
+               printk("disabling early console\n");
+               unregister_console(early_console);
+       } else
+               printk("keeping early console\n");
 }
-
index 7dfd2ba75f7fb9d96fa1dcdfff8c2ce9475ff7ae..fe8221855b282648f25472cd64286814728f7843 100644 (file)
 #include <asm/cpu/mmu_context.h>
 #include <asm/unistd.h>
 
-#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
-#define sys_nfsservctl         sys_ni_syscall
-#endif
-
-#if !defined(CONFIG_MMU)
-#define sys_madvise            sys_ni_syscall
-#define sys_readahead          sys_ni_syscall
-#define sys_mprotect           sys_ni_syscall
-#define sys_msync              sys_ni_syscall
-#define sys_mlock              sys_ni_syscall
-#define sys_munlock            sys_ni_syscall
-#define sys_mlockall           sys_ni_syscall
-#define sys_munlockall         sys_ni_syscall
-#define sys_mremap             sys_ni_syscall
-#define sys_mincore            sys_ni_syscall
-#define sys_remap_file_pages   sys_ni_syscall
-#endif
-
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
 ! to be jumped is too far, but it causes illegal slot exception.
@@ -326,7 +308,7 @@ ENTRY(exception_error)
        .align  2
 ret_from_exception:
        preempt_stop()
-ret_from_irq:
+ENTRY(ret_from_irq)
        !
        mov     #OFF_SR, r0
        mov.l   @(r0,r15), r0   ! get status register
@@ -389,11 +371,12 @@ work_pending:
        ! r8: current_thread_info
        ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
        bf/s    work_resched
-        tst    #_TIF_SIGPENDING, r0
+        tst    #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
 work_notifysig:
        bt/s    restore_all
         mov    r15, r4
-       mov     #0, r5
+       mov     r12, r5         ! set arg1(save_r0)
+       mov     r0, r6
        mov.l   2f, r1
        mova    restore_all, r0
        jmp     @r1
@@ -431,7 +414,7 @@ work_resched:
 
        .align  2
 1:     .long   schedule
-2:     .long   do_signal
+2:     .long   do_notify_resume
 
        .align  2
 syscall_exit_work:
@@ -552,6 +535,7 @@ syscall_call:
        mov.l   @r9, r8
        jsr     @r8             ! jump to specific syscall handler
         nop
+       mov.l   @(OFF_R0,r15), r12              ! save r0
        mov.l   r0, @(OFF_R0,r15)               ! save the return value
        !
 syscall_exit:
@@ -644,7 +628,7 @@ skip_restore:
        !
 #if defined(CONFIG_KGDB_NMI)
        ! Clear in_nmi
-       mov.l   4f, k0
+       mov.l   6f, k0
        mov     #0, k1
        mov.b   k1, @k0
 #endif
@@ -722,7 +706,7 @@ interrupt:
 !
 !
        .align  2
-handle_exception:
+ENTRY(handle_exception)
        ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
        ! save all registers onto stack.
        !
@@ -732,8 +716,8 @@ handle_exception:
        bt/s    1f              ! It's a kernel to kernel transition.
         mov    r15, k0         ! save original stack to k0
        /* User space to kernel */
-       mov     #0x20, k1
-       shll8   k1              ! k1 := 8192 (== THREAD_SIZE)
+       mov     #(THREAD_SIZE >> 8), k1
+       shll8   k1              ! k1 := THREAD_SIZE
        add     current, k1
        mov     k1, r15         ! change to kernel stack
        !
@@ -838,300 +822,3 @@ ENTRY(exception_none)
        rts
         nop
 
-       .data
-ENTRY(sys_call_table)
-       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
-       .long sys_exit
-       .long sys_fork
-       .long sys_read
-       .long sys_write
-       .long sys_open          /* 5 */
-       .long sys_close
-       .long sys_waitpid
-       .long sys_creat
-       .long sys_link
-       .long sys_unlink                /* 10 */
-       .long sys_execve
-       .long sys_chdir
-       .long sys_time
-       .long sys_mknod
-       .long sys_chmod         /* 15 */
-       .long sys_lchown16
-       .long sys_ni_syscall    /* old break syscall holder */
-       .long sys_stat
-       .long sys_lseek
-       .long sys_getpid                /* 20 */
-       .long sys_mount
-       .long sys_oldumount
-       .long sys_setuid16
-       .long sys_getuid16
-       .long sys_stime         /* 25 */
-       .long sys_ptrace
-       .long sys_alarm
-       .long sys_fstat
-       .long sys_pause
-       .long sys_utime         /* 30 */
-       .long sys_ni_syscall    /* old stty syscall holder */
-       .long sys_ni_syscall    /* old gtty syscall holder */
-       .long sys_access
-       .long sys_nice
-       .long sys_ni_syscall    /* 35 */                /* old ftime syscall holder */
-       .long sys_sync
-       .long sys_kill
-       .long sys_rename
-       .long sys_mkdir
-       .long sys_rmdir         /* 40 */
-       .long sys_dup
-       .long sys_pipe
-       .long sys_times
-       .long sys_ni_syscall    /* old prof syscall holder */
-       .long sys_brk           /* 45 */
-       .long sys_setgid16
-       .long sys_getgid16
-       .long sys_signal
-       .long sys_geteuid16
-       .long sys_getegid16     /* 50 */
-       .long sys_acct
-       .long sys_umount                /* recycled never used phys() */
-       .long sys_ni_syscall    /* old lock syscall holder */
-       .long sys_ioctl
-       .long sys_fcntl         /* 55 */
-       .long sys_ni_syscall    /* old mpx syscall holder */
-       .long sys_setpgid
-       .long sys_ni_syscall    /* old ulimit syscall holder */
-       .long sys_ni_syscall    /* sys_olduname */
-       .long sys_umask         /* 60 */
-       .long sys_chroot
-       .long sys_ustat
-       .long sys_dup2
-       .long sys_getppid
-       .long sys_getpgrp               /* 65 */
-       .long sys_setsid
-       .long sys_sigaction
-       .long sys_sgetmask
-       .long sys_ssetmask
-       .long sys_setreuid16    /* 70 */
-       .long sys_setregid16
-       .long sys_sigsuspend
-       .long sys_sigpending
-       .long sys_sethostname
-       .long sys_setrlimit     /* 75 */
-       .long sys_old_getrlimit
-       .long sys_getrusage
-       .long sys_gettimeofday
-       .long sys_settimeofday
-       .long sys_getgroups16   /* 80 */
-       .long sys_setgroups16
-       .long sys_ni_syscall    /* sys_oldselect */
-       .long sys_symlink
-       .long sys_lstat
-       .long sys_readlink              /* 85 */
-       .long sys_uselib
-       .long sys_swapon
-       .long sys_reboot
-       .long old_readdir
-       .long old_mmap          /* 90 */
-       .long sys_munmap
-       .long sys_truncate
-       .long sys_ftruncate
-       .long sys_fchmod
-       .long sys_fchown16              /* 95 */
-       .long sys_getpriority
-       .long sys_setpriority
-       .long sys_ni_syscall    /* old profil syscall holder */
-       .long sys_statfs
-       .long sys_fstatfs               /* 100 */
-       .long sys_ni_syscall    /* ioperm */
-       .long sys_socketcall
-       .long sys_syslog
-       .long sys_setitimer
-       .long sys_getitimer     /* 105 */
-       .long sys_newstat
-       .long sys_newlstat
-       .long sys_newfstat
-       .long sys_uname
-       .long sys_ni_syscall    /* 110 */ /* iopl */
-       .long sys_vhangup
-       .long sys_ni_syscall    /* idle */
-       .long sys_ni_syscall    /* vm86old */
-       .long sys_wait4
-       .long sys_swapoff               /* 115 */
-       .long sys_sysinfo
-       .long sys_ipc
-       .long sys_fsync
-       .long sys_sigreturn
-       .long sys_clone         /* 120 */
-       .long sys_setdomainname
-       .long sys_newuname
-       .long sys_ni_syscall    /* sys_modify_ldt */
-       .long sys_adjtimex
-       .long sys_mprotect              /* 125 */
-       .long sys_sigprocmask
-       .long sys_ni_syscall    /* old "create_module" */
-       .long sys_init_module
-       .long sys_delete_module
-       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
-       .long sys_quotactl
-       .long sys_getpgid
-       .long sys_fchdir
-       .long sys_bdflush
-       .long sys_sysfs         /* 135 */
-       .long sys_personality
-       .long sys_ni_syscall    /* for afs_syscall */
-       .long sys_setfsuid16
-       .long sys_setfsgid16
-       .long sys_llseek                /* 140 */
-       .long sys_getdents
-       .long sys_select
-       .long sys_flock
-       .long sys_msync
-       .long sys_readv         /* 145 */
-       .long sys_writev
-       .long sys_getsid
-       .long sys_fdatasync
-       .long sys_sysctl
-       .long sys_mlock         /* 150 */
-       .long sys_munlock
-       .long sys_mlockall
-       .long sys_munlockall
-       .long sys_sched_setparam
-       .long sys_sched_getparam   /* 155 */
-       .long sys_sched_setscheduler
-       .long sys_sched_getscheduler
-       .long sys_sched_yield
-       .long sys_sched_get_priority_max
-       .long sys_sched_get_priority_min  /* 160 */
-       .long sys_sched_rr_get_interval
-       .long sys_nanosleep
-       .long sys_mremap
-       .long sys_setresuid16
-       .long sys_getresuid16   /* 165 */
-       .long sys_ni_syscall    /* vm86 */
-       .long sys_ni_syscall    /* old "query_module" */
-       .long sys_poll
-       .long sys_nfsservctl
-       .long sys_setresgid16   /* 170 */
-       .long sys_getresgid16
-       .long sys_prctl
-       .long sys_rt_sigreturn
-       .long sys_rt_sigaction
-       .long sys_rt_sigprocmask        /* 175 */
-       .long sys_rt_sigpending
-       .long sys_rt_sigtimedwait
-       .long sys_rt_sigqueueinfo
-       .long sys_rt_sigsuspend
-       .long sys_pread_wrapper    /* 180 */
-       .long sys_pwrite_wrapper
-       .long sys_chown16
-       .long sys_getcwd
-       .long sys_capget
-       .long sys_capset           /* 185 */
-       .long sys_sigaltstack
-       .long sys_sendfile
-       .long sys_ni_syscall    /* streams1 */
-       .long sys_ni_syscall    /* streams2 */
-       .long sys_vfork            /* 190 */
-       .long sys_getrlimit
-       .long sys_mmap2
-       .long sys_truncate64
-       .long sys_ftruncate64
-       .long sys_stat64                /* 195 */
-       .long sys_lstat64
-       .long sys_fstat64
-       .long sys_lchown
-       .long sys_getuid
-       .long sys_getgid                /* 200 */
-       .long sys_geteuid
-       .long sys_getegid
-       .long sys_setreuid
-       .long sys_setregid
-       .long sys_getgroups     /* 205 */
-       .long sys_setgroups
-       .long sys_fchown
-       .long sys_setresuid
-       .long sys_getresuid
-       .long sys_setresgid     /* 210 */
-       .long sys_getresgid
-       .long sys_chown
-       .long sys_setuid
-       .long sys_setgid
-       .long sys_setfsuid              /* 215 */
-       .long sys_setfsgid
-       .long sys_pivot_root
-       .long sys_mincore
-       .long sys_madvise
-       .long sys_getdents64    /* 220 */
-       .long sys_fcntl64
-       .long sys_ni_syscall    /* reserved for TUX */
-       .long sys_ni_syscall    /* Reserved for Security */
-       .long sys_gettid
-       .long sys_readahead     /* 225 */
-       .long sys_setxattr
-       .long sys_lsetxattr
-       .long sys_fsetxattr
-       .long sys_getxattr
-       .long sys_lgetxattr     /* 230 */
-       .long sys_fgetxattr
-       .long sys_listxattr
-       .long sys_llistxattr
-       .long sys_flistxattr
-       .long sys_removexattr   /* 235 */
-       .long sys_lremovexattr
-       .long sys_fremovexattr
-       .long sys_tkill
-       .long sys_sendfile64
-       .long sys_futex         /* 240 */
-       .long sys_sched_setaffinity
-       .long sys_sched_getaffinity
-       .long sys_ni_syscall
-       .long sys_ni_syscall
-       .long sys_io_setup      /* 245 */
-       .long sys_io_destroy
-       .long sys_io_getevents
-       .long sys_io_submit
-       .long sys_io_cancel
-       .long sys_fadvise64     /* 250 */
-       .long sys_ni_syscall
-       .long sys_exit_group
-       .long sys_lookup_dcookie
-       .long sys_epoll_create
-       .long sys_epoll_ctl     /* 255 */
-       .long sys_epoll_wait
-       .long sys_remap_file_pages
-       .long sys_set_tid_address
-       .long sys_timer_create
-       .long sys_timer_settime         /* 260 */
-       .long sys_timer_gettime
-       .long sys_timer_getoverrun
-       .long sys_timer_delete
-       .long sys_clock_settime
-       .long sys_clock_gettime         /* 265 */
-       .long sys_clock_getres
-       .long sys_clock_nanosleep
-       .long sys_statfs64
-       .long sys_fstatfs64     
-       .long sys_tgkill                /* 270 */
-       .long sys_utimes
-       .long sys_fadvise64_64_wrapper
-       .long sys_ni_syscall    /* Reserved for vserver */
-       .long sys_ni_syscall    /* Reserved for mbind */
-       .long sys_ni_syscall    /* 275 - get_mempolicy */
-       .long sys_ni_syscall    /* set_mempolicy */
-       .long sys_mq_open
-       .long sys_mq_unlink
-       .long sys_mq_timedsend
-       .long sys_mq_timedreceive       /* 280 */
-       .long sys_mq_notify
-       .long sys_mq_getsetattr
-       .long sys_ni_syscall    /* Reserved for kexec */
-       .long sys_waitid
-       .long sys_add_key               /* 285 */
-       .long sys_request_key
-       .long sys_keyctl
-       .long sys_ioprio_set
-       .long sys_ioprio_get
-       .long sys_inotify_init          /* 290 */
-       .long sys_inotify_add_watch
-       .long sys_inotify_rm_watch
-
-/* End of entry.S */
index 9b9e6ef626cea4497f472c176b11355248ed55d5..f5f53d14f2456aaf61a9a0d34468efde924864b8 100644 (file)
  * Head.S contains the SH exception handlers and startup code.
  */
 #include <linux/linkage.h>
+#include <asm/thread_info.h>
+
+#ifdef CONFIG_CPU_SH4A
+#define SYNCO()                synco
+
+#define PREFI(label, reg)      \
+       mov.l   label, reg;     \
+       prefi   @reg
+#else
+#define SYNCO()
+#define PREFI(label, reg)
+#endif
 
        .section        .empty_zero_page, "aw"
 ENTRY(empty_zero_page)
@@ -42,18 +54,25 @@ ENTRY(_stext)
        !                       Initialize global interrupt mask
        mov     #0, r0
        ldc     r0, r6_bank
+
+       /*
+        * Prefetch if possible to reduce cache miss penalty.
+        *
+        * We do this early on for SH-4A as a micro-optimization,
+        * as later on we will have speculative execution enabled
+        * and this will become less of an issue.
+        */
+       PREFI(5f, r0)
+       PREFI(6f, r0)
+
        !
        mov.l   2f, r0
        mov     r0, r15         ! Set initial r15 (stack pointer)
-       mov     #0x20, r1       !
-       shll8   r1              ! r1 = 8192
+       mov     #(THREAD_SIZE >> 8), r1
+       shll8   r1              ! r1 = THREAD_SIZE
        sub     r1, r0          !
        ldc     r0, r7_bank     ! ... and initial thread_info
-       !
-       !                       Additional CPU initialization
-       mov.l   6f, r0
-       jsr     @r0
-        nop
+
        !                       Clear BSS area
        mov.l   3f, r1
        add     #4, r1
@@ -62,6 +81,14 @@ ENTRY(_stext)
 9:     cmp/hs  r2, r1
        bf/s    9b              ! while (r1 < r2)
         mov.l  r0,@-r2
+
+       !                       Additional CPU initialization
+       mov.l   6f, r0
+       jsr     @r0
+        nop
+
+       SYNCO()                 ! Wait for pending instructions..
+
        !                       Start kernel
        mov.l   5f, r0
        jmp     @r0
@@ -69,7 +96,7 @@ ENTRY(_stext)
 
        .balign 4
 1:     .long   0x400080F0              ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
-2:     .long   stack
+2:     .long   init_thread_union+THREAD_SIZE
 3:     .long   __bss_start
 4:     .long   _end
 5:     .long   start_kernel
index 71c9fde2fd9072517af4062168d720c2c3153b57..501fe03e3715770c484684f7b1fbecfb954d2010 100644 (file)
@@ -61,6 +61,73 @@ void memset_io(volatile void __iomem *dst, int c, unsigned long count)
 }
 EXPORT_SYMBOL(memset_io);
 
+void __raw_readsl(unsigned long addr, void *datap, int len)
+{
+       u32 *data;
+
+       for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--)
+               *data++ = ctrl_inl(addr);
+
+       if (likely(len >= (0x20 >> 2))) {
+               int tmp2, tmp3, tmp4, tmp5, tmp6;
+
+               __asm__ __volatile__(
+                       "1:                     \n\t"
+                       "mov.l  @%7, r0         \n\t"
+                       "mov.l  @%7, %2         \n\t"
+#ifdef CONFIG_CPU_SH4
+                       "movca.l r0, @%0        \n\t"
+#else
+                       "mov.l  r0, @%0         \n\t"
+#endif
+                       "mov.l  @%7, %3         \n\t"
+                       "mov.l  @%7, %4         \n\t"
+                       "mov.l  @%7, %5         \n\t"
+                       "mov.l  @%7, %6         \n\t"
+                       "mov.l  @%7, r7         \n\t"
+                       "mov.l  @%7, r0         \n\t"
+                       "mov.l  %2, @(0x04,%0)  \n\t"
+                       "mov    #0x20>>2, %2    \n\t"
+                       "mov.l  %3, @(0x08,%0)  \n\t"
+                       "sub    %2, %1          \n\t"
+                       "mov.l  %4, @(0x0c,%0)  \n\t"
+                       "cmp/hi %1, %2          ! T if 32 > len \n\t"
+                       "mov.l  %5, @(0x10,%0)  \n\t"
+                       "mov.l  %6, @(0x14,%0)  \n\t"
+                       "mov.l  r7, @(0x18,%0)  \n\t"
+                       "mov.l  r0, @(0x1c,%0)  \n\t"
+                       "bf.s   1b              \n\t"
+                       " add   #0x20, %0       \n\t"
+                       : "=&r" (data), "=&r" (len),
+                         "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4),
+                         "=&r" (tmp5), "=&r" (tmp6)
+                       : "r"(addr), "0" (data), "1" (len)
+                       : "r0", "r7", "t", "memory");
+       }
+
+       for (; len != 0; len--)
+               *data++ = ctrl_inl(addr);
+}
+EXPORT_SYMBOL(__raw_readsl);
+
+void __raw_writesl(unsigned long addr, const void *data, int len)
+{
+       if (likely(len != 0)) {
+               int tmp1;
+
+               __asm__ __volatile__ (
+                       "1:                             \n\t"
+                       "mov.l  @%0+, %1        \n\t"
+                       "dt             %3              \n\t"
+                       "bf.s           1b              \n\t"
+                       " mov.l %1, @%4         \n\t"
+                       : "=&r" (data), "=&r" (tmp1)
+                       : "0" (data), "r" (len), "r"(addr)
+                       : "t", "memory");
+       }
+}
+EXPORT_SYMBOL(__raw_writesl);
+
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
        return sh_mv.mv_ioport_map(port, nr);
index c2e07f7f3496a45efa79b87be2cc953b2ebd49e0..c7ebd6aec9514cdb4f16583a94a6570e01262440 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $
- *
+/*
  * linux/arch/sh/kernel/irq.c
  *
  *     Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
@@ -7,13 +6,15 @@
  *
  * SuperH version:  Copyright (C) 1999  Niibe Yutaka
  */
-
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/thread_info.h>
 #include <asm/cpu/mmu_context.h>
 
 /*
@@ -60,15 +61,46 @@ unlock:
 }
 #endif
 
+#ifdef CONFIG_4KSTACKS
+/*
+ * per-CPU IRQ handling contexts (thread information and stack)
+ */
+union irq_ctx {
+       struct thread_info      tinfo;
+       u32                     stack[THREAD_SIZE/sizeof(u32)];
+};
+
+static union irq_ctx *hardirq_ctx[NR_CPUS];
+static union irq_ctx *softirq_ctx[NR_CPUS];
+#endif
 
 asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
                      unsigned long r6, unsigned long r7,
                      struct pt_regs regs)
 {
        int irq = r4;
+#ifdef CONFIG_4KSTACKS
+       union irq_ctx *curctx, *irqctx;
+#endif
 
        irq_enter();
 
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+       /* Debugging check for stack overflow: is there less than 1KB free? */
+       {
+               long sp;
+
+               __asm__ __volatile__ ("and r15, %0" :
+                                       "=r" (sp) : "0" (THREAD_SIZE - 1));
+
+               if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+                       printk("do_IRQ: stack overflow: %ld\n",
+                              sp - sizeof(struct thread_info));
+                       dump_stack();
+               }
+       }
+#endif
+
 #ifdef CONFIG_CPU_HAS_INTEVT
        __asm__ __volatile__ (
 #ifdef CONFIG_CPU_HAS_SR_RB
@@ -87,7 +119,135 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
 #endif
 
        irq = irq_demux(irq);
-       __do_IRQ(irq, &regs);
+
+#ifdef CONFIG_4KSTACKS
+       curctx = (union irq_ctx *)current_thread_info();
+       irqctx = hardirq_ctx[smp_processor_id()];
+
+       /*
+        * this is where we switch to the IRQ stack. However, if we are
+        * already using the IRQ stack (because we interrupted a hardirq
+        * handler) we can't do that and just have to keep using the
+        * current stack (which is the irq stack already after all)
+        */
+       if (curctx != irqctx) {
+               u32 *isp;
+
+               isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
+               irqctx->tinfo.task = curctx->tinfo.task;
+               irqctx->tinfo.previous_sp = current_stack_pointer;
+
+               __asm__ __volatile__ (
+                       "mov    %0, r4          \n"
+                       "mov    %1, r5          \n"
+                       "mov    r15, r9         \n"
+                       "jsr    @%2             \n"
+                       /* swith to the irq stack */
+                       " mov   %3, r15         \n"
+                       /* restore the stack (ring zero) */
+                       "mov    r9, r15         \n"
+                       : /* no outputs */
+                       : "r" (irq), "r" (&regs), "r" (__do_IRQ), "r" (isp)
+                       /* XXX: A somewhat excessive clobber list? -PFM */
+                       : "memory", "r0", "r1", "r2", "r3", "r4",
+                         "r5", "r6", "r7", "r8", "t", "pr"
+               );
+       } else
+#endif
+               __do_IRQ(irq, &regs);
+
        irq_exit();
+
        return 1;
 }
+
+#ifdef CONFIG_4KSTACKS
+/*
+ * These should really be __section__(".bss.page_aligned") as well, but
+ * gcc's 3.0 and earlier don't handle that correctly.
+ */
+static char softirq_stack[NR_CPUS * THREAD_SIZE]
+               __attribute__((__aligned__(THREAD_SIZE)));
+
+static char hardirq_stack[NR_CPUS * THREAD_SIZE]
+               __attribute__((__aligned__(THREAD_SIZE)));
+
+/*
+ * allocate per-cpu stacks for hardirq and for softirq processing
+ */
+void irq_ctx_init(int cpu)
+{
+       union irq_ctx *irqctx;
+
+       if (hardirq_ctx[cpu])
+               return;
+
+       irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE];
+       irqctx->tinfo.task              = NULL;
+       irqctx->tinfo.exec_domain       = NULL;
+       irqctx->tinfo.cpu               = cpu;
+       irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
+       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+
+       hardirq_ctx[cpu] = irqctx;
+
+       irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE];
+       irqctx->tinfo.task              = NULL;
+       irqctx->tinfo.exec_domain       = NULL;
+       irqctx->tinfo.cpu               = cpu;
+       irqctx->tinfo.preempt_count     = SOFTIRQ_OFFSET;
+       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+
+       softirq_ctx[cpu] = irqctx;
+
+       printk("CPU %u irqstacks, hard=%p soft=%p\n",
+               cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
+}
+
+void irq_ctx_exit(int cpu)
+{
+       hardirq_ctx[cpu] = NULL;
+}
+
+extern asmlinkage void __do_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+       unsigned long flags;
+       struct thread_info *curctx;
+       union irq_ctx *irqctx;
+       u32 *isp;
+
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+
+       if (local_softirq_pending()) {
+               curctx = current_thread_info();
+               irqctx = softirq_ctx[smp_processor_id()];
+               irqctx->tinfo.task = curctx->task;
+               irqctx->tinfo.previous_sp = current_stack_pointer;
+
+               /* build the stack frame on the softirq stack */
+               isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
+
+               __asm__ __volatile__ (
+                       "mov    r15, r9         \n"
+                       "jsr    @%0             \n"
+                       /* switch to the softirq stack */
+                       " mov   %1, r15         \n"
+                       /* restore the thread stack */
+                       "mov    r9, r15         \n"
+                       : /* no outputs */
+                       : "r" (__do_softirq), "r" (isp)
+                       /* XXX: A somewhat excessive clobber list? -PFM */
+                       : "memory", "r0", "r1", "r2", "r3", "r4",
+                         "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
+               );
+       }
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(do_softirq);
+#endif
index 42638b92b51c0828141e0937cf62a9a54a1d0307..9c6315f0335dfdc45bac2f8aa47a3fc9fa0adb11 100644 (file)
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+#ifdef CONFIG_SH_KGDB_CONSOLE
+#include <linux/console.h>
+#endif
+
 #include <asm/system.h>
 #include <asm/current.h>
 #include <asm/signal.h>
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/kgdb.h>
-
-#ifdef CONFIG_SH_KGDB_CONSOLE
-#include <linux/console.h>
-#endif
+#include <asm/io.h>
 
 /* Function pointers for linkage */
 kgdb_debug_hook_t *kgdb_debug_hook;
@@ -240,7 +241,6 @@ static jmp_buf rem_com_env;
 /* Misc static */
 static int stepped_address;
 static short stepped_opcode;
-static const char hexchars[] = "0123456789abcdef";
 static char in_buffer[BUFMAX];
 static char out_buffer[OUTBUFMAX];
 
@@ -253,29 +253,6 @@ typedef unsigned char threadref[8];
 #define BUF_THREAD_ID_SIZE 16
 #endif
 
-/* Return addr as a real volatile address */
-static inline unsigned int ctrl_inl(const unsigned long addr)
-{
-       return *(volatile unsigned long *) addr;
-}
-
-/* Correctly set *addr using volatile */
-static inline void ctrl_outl(const unsigned int b, unsigned long addr)
-{
-       *(volatile unsigned long *) addr = b;
-}
-
-/* Get high hex bits */
-static char highhex(const int x)
-{
-       return hexchars[(x >> 4) & 0xf];
-}
-
-/* Get low hex bits */
-static char lowhex(const int x)
-{
-       return hexchars[x & 0xf];
-}
 
 /* Convert ch to hex */
 static int hex(const char ch)
index 6bcd8d92399fcb094fa725831413e93b4a65f66f..08587cdb64d62577e481a19df5885f6b3dc1962b 100644 (file)
@@ -29,12 +29,6 @@ extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
 extern void *gdb_vbr_vector;
 
-/*
- * Provide a dummy crash_notes definition while crash dump arrives to ppc.
- * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- */
-void *crash_notes = NULL;
-
 void machine_shutdown(void)
 {
 }
diff --git a/arch/sh/kernel/pm.c b/arch/sh/kernel/pm.c
new file mode 100644 (file)
index 0000000..10ab62c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Generic Power Management Routine
+ *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/suspend.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+#include <asm/watchdog.h>
+#include <asm/pm.h>
+
+#define INTR_OFFSET    0x600
+
+#define STBCR          0xffffff82
+#define STBCR2         0xffffff88
+
+#define STBCR_STBY     0x80
+#define STBCR_MSTP2    0x04
+
+#define MCR            0xffffff68
+#define RTCNT          0xffffff70
+
+#define MCR_RMODE      2
+#define MCR_RFSH       4
+
+void pm_enter(void)
+{
+       u8 stbcr, csr;
+       u16 frqcr, mcr;
+       u32 vbr_new, vbr_old;
+
+       set_bl_bit();
+
+       /* set wdt */
+       csr = sh_wdt_read_csr();
+       csr &= ~WTCSR_TME;
+       csr |= WTCSR_CKS_4096;
+       sh_wdt_write_csr(csr);
+       csr = sh_wdt_read_csr();
+       sh_wdt_write_cnt(0);
+
+       /* disable PLL1 */
+       frqcr = ctrl_inw(FRQCR);
+       frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
+       ctrl_outw(frqcr, FRQCR);
+
+       /* enable standby */
+       stbcr = ctrl_inb(STBCR);
+       ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
+
+       /* set self-refresh */
+       mcr = ctrl_inw(MCR);
+       ctrl_outw(mcr & ~MCR_RFSH, MCR);
+
+       /* set interrupt handler */
+       asm volatile("stc vbr, %0" : "=r" (vbr_old));
+       vbr_new = get_zeroed_page(GFP_ATOMIC);
+       udelay(50);
+       memcpy((void*)(vbr_new + INTR_OFFSET),
+              &wakeup_start, &wakeup_end - &wakeup_start);
+       asm volatile("ldc %0, vbr" : : "r" (vbr_new));
+
+       ctrl_outw(0, RTCNT);
+       ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR);
+
+       cpu_sleep();
+
+       asm volatile("ldc %0, vbr" : : "r" (vbr_old));
+
+       free_page(vbr_new);
+
+       /* enable PLL1 */
+       frqcr = ctrl_inw(FRQCR);
+       frqcr |= FRQCR_PSTBY;
+       ctrl_outw(frqcr, FRQCR);
+       udelay(50);
+       frqcr |= FRQCR_PLLEN;
+       ctrl_outw(frqcr, FRQCR);
+
+       ctrl_outb(stbcr, STBCR);
+
+       clear_bl_bit();
+}
index f2031314cb2b393c81b7599c36b393f6e323a3b4..0b1d5dd7a93b4237c70f3681d5745cac2296e3bd 100644 (file)
@@ -81,16 +81,6 @@ void cpu_idle(void)
 
 void machine_restart(char * __unused)
 {
-
-#ifdef CONFIG_KEXEC
-       struct kimage *image;
-       image = xchg(&kexec_image, 0);
-       if (image) {
-               machine_shutdown();
-               machine_kexec(image);
-       }
-#endif
-
        /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
        asm volatile("ldc %0, sr\n\t"
                     "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
@@ -263,6 +253,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                unsigned long unused,
                struct task_struct *p, struct pt_regs *regs)
 {
+       struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs;
 #if defined(CONFIG_SH_FPU)
        struct task_struct *tsk = current;
@@ -277,8 +268,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 
        if (user_mode(regs)) {
                childregs->regs[15] = usp;
+               ti->addr_limit = USER_DS;
        } else {
                childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+               ti->addr_limit = KERNEL_DS;
        }
         if (clone_flags & CLONE_SETTLS) {
                childregs->gbr = childregs->regs[0];
@@ -299,13 +292,15 @@ ubc_set_tracing(int asid, unsigned long pc)
 {
        ctrl_outl(pc, UBC_BARA);
 
+#ifdef CONFIG_MMU
        /* We don't have any ASID settings for the SH-2! */
        if (cpu_data->type != CPU_SH7604)
                ctrl_outb(asid, UBC_BASRA);
+#endif
 
        ctrl_outl(0, UBC_BAMRA);
 
-       if (cpu_data->type == CPU_SH7729) {
+       if (cpu_data->type == CPU_SH7729 || cpu_data->type == CPU_SH7710) {
                ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
                ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
        } else {
@@ -344,6 +339,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
        }
 #endif
 
+#ifdef CONFIG_MMU
        /*
         * Restore the kernel mode register
         *      k7 (r7_bank1)
@@ -351,19 +347,21 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
        asm volatile("ldc       %0, r7_bank"
                     : /* no output */
                     : "r" (task_thread_info(next)));
+#endif
 
-#ifdef CONFIG_MMU
        /* If no tasks are using the UBC, we're done */
        if (ubc_usercnt == 0)
                /* If no tasks are using the UBC, we're done */;
        else if (next->thread.ubc_pc && next->mm) {
-               ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK,
-                               next->thread.ubc_pc);
+               int asid = 0;
+#ifdef CONFIG_MMU
+               asid |= next->mm->context.id & MMU_CONTEXT_ASID_MASK;
+#endif
+               ubc_set_tracing(asid, next->thread.ubc_pc);
        } else {
                ctrl_outw(0, UBC_BBRA);
                ctrl_outw(0, UBC_BBRB);
        }
-#endif
 
        return prev;
 }
index f7eebbde329184808d7a4dfe955fb6756128f582..04ca13a041c160127077dddab6cfd507368fb319 100644 (file)
@@ -224,7 +224,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
        case PTRACE_SETDSPREGS: {
                unsigned long dp;
-               int i;
 
                ret = -EIO;
                dp = ((unsigned long) child) + THREAD_SIZE -
index a3c24dcbf01ddb947adac9bbd0e23da516a29a30..184119eeae56add25f6f450e1a436f702637b45b 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/semaphore.h>
 #include <asm/semaphore-helper.h>
 
-spinlock_t semaphore_wake_lock;
+DEFINE_SPINLOCK(semaphore_wake_lock);
 
 /*
  * Semaphores are implemented using a two-way counter:
index e75189cb1db7ab29424da9cd40a27e462ddc6faf..5f587332234a3e977cf1203477831dddfb446f50 100644 (file)
@@ -43,27 +43,14 @@ extern void * __rd_start, * __rd_end;
  * The bigger value means no problem.
  */
 struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+#ifdef CONFIG_VT
 struct screen_info screen_info;
+#endif
 
 #if defined(CONFIG_SH_UNKNOWN)
 struct sh_machine_vector sh_mv;
 #endif
 
-/* We need this to satisfy some external references. */
-struct screen_info screen_info = {
-        0, 25,                  /* orig-x, orig-y */
-        0,                      /* unused */
-        0,                      /* orig-video-page */
-        0,                      /* orig-video-mode */
-        80,                     /* orig-video-cols */
-        0,0,0,                  /* ega_ax, ega_bx, ega_cx */
-        25,                     /* orig-video-lines */
-        0,                      /* orig-video-isVGA */
-        16                      /* orig-video-points */
-};
-
-extern void platform_setup(void);
-extern char *get_system_type(void);
 extern int root_mountflags;
 
 #define MV_NAME_SIZE 32
@@ -90,29 +77,8 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name);
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
 
-struct resource standard_io_resources[] = {
-       { "dma1", 0x00, 0x1f },
-       { "pic1", 0x20, 0x3f },
-       { "timer", 0x40, 0x5f },
-       { "keyboard", 0x60, 0x6f },
-       { "dma page reg", 0x80, 0x8f },
-       { "pic2", 0xa0, 0xbf },
-       { "dma2", 0xc0, 0xdf },
-       { "fpu", 0xf0, 0xff }
-};
-
-#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
-
-/* System RAM - interrupted by the 640kB-1M hole */
-#define code_resource (ram_resources[3])
-#define data_resource (ram_resources[4])
-static struct resource ram_resources[] = {
-       { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
-       { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
-       { "Video RAM area", 0x0a0000, 0x0bffff },
-       { "Kernel code", 0x100000, 0 },
-       { "Kernel data", 0, 0 }
-};
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
 
 unsigned long memory_start, memory_end;
 
@@ -145,6 +111,24 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
                                memory_end = memory_start + mem_size;
                        }
                }
+
+#ifdef CONFIG_EARLY_PRINTK
+               if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
+                       char *ep_end;
+
+                       if (to != command_line)
+                               to--;
+
+                       from += 12;
+                       ep_end = strchr(from, ' ');
+
+                       setup_early_printk(from);
+                       printk("early console enabled\n");
+
+                       from = ep_end;
+               }
+#endif
+
                if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
                        char* mv_end;
                        char* mv_comma;
@@ -237,6 +221,9 @@ static int __init sh_mv_setup(char **cmdline_p)
        __set_io_port_base(mv_io_base);
 #endif
 
+       if (!sh_mv.mv_nr_irqs)
+               sh_mv.mv_nr_irqs = NR_IRQS;
+
        return 0;
 }
 
@@ -245,11 +232,6 @@ void __init setup_arch(char **cmdline_p)
        unsigned long bootmap_size;
        unsigned long start_pfn, max_pfn, max_low_pfn;
 
-#ifdef CONFIG_EARLY_PRINTK
-       extern void enable_early_printk(void);
-
-       enable_early_printk();
-#endif
 #ifdef CONFIG_CMDLINE_BOOL
         strcpy(COMMAND_LINE, CONFIG_CMDLINE);
 #endif
@@ -368,14 +350,14 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        /* Perform the machine specific initialisation */
-       platform_setup();
+       if (likely(sh_mv.mv_setup))
+               sh_mv.mv_setup(cmdline_p);
 
        paging_init();
 }
 
 struct sh_machine_vector* __init get_mv_byname(const char* name)
 {
-       extern int strcasecmp(const char *, const char *);
        extern long __machvec_start, __machvec_end;
        struct sh_machine_vector *all_vecs =
                (struct sh_machine_vector *)&__machvec_start;
@@ -410,25 +392,18 @@ static int __init topology_init(void)
 subsys_initcall(topology_init);
 
 static const char *cpu_name[] = {
-       [CPU_SH7604]    = "SH7604",
-       [CPU_SH7705]    = "SH7705",
-       [CPU_SH7708]    = "SH7708",
-       [CPU_SH7729]    = "SH7729",
-       [CPU_SH7300]    = "SH7300",
-       [CPU_SH7750]    = "SH7750",
-       [CPU_SH7750S]   = "SH7750S",
-       [CPU_SH7750R]   = "SH7750R",
-       [CPU_SH7751]    = "SH7751",
-       [CPU_SH7751R]   = "SH7751R",
-       [CPU_SH7760]    = "SH7760",
-       [CPU_SH73180]   = "SH73180",
-       [CPU_ST40RA]    = "ST40RA",
-       [CPU_ST40GX1]   = "ST40GX1",
-       [CPU_SH4_202]   = "SH4-202",
-       [CPU_SH4_501]   = "SH4-501",
-       [CPU_SH7770]    = "SH7770",
-       [CPU_SH7780]    = "SH7780",
-       [CPU_SH7781]    = "SH7781",
+       [CPU_SH7604]    = "SH7604",     [CPU_SH7300]    = "SH7300",
+       [CPU_SH7705]    = "SH7705",     [CPU_SH7706]    = "SH7706",
+       [CPU_SH7707]    = "SH7707",     [CPU_SH7708]    = "SH7708",
+       [CPU_SH7709]    = "SH7709",     [CPU_SH7710]    = "SH7710",
+       [CPU_SH7729]    = "SH7729",     [CPU_SH7750]    = "SH7750",
+       [CPU_SH7750S]   = "SH7750S",    [CPU_SH7750R]   = "SH7750R",
+       [CPU_SH7751]    = "SH7751",     [CPU_SH7751R]   = "SH7751R",
+       [CPU_SH7760]    = "SH7760",     [CPU_SH73180]   = "SH73180",
+       [CPU_ST40RA]    = "ST40RA",     [CPU_ST40GX1]   = "ST40GX1",
+       [CPU_SH4_202]   = "SH4-202",    [CPU_SH4_501]   = "SH4-501",
+       [CPU_SH7770]    = "SH7770",     [CPU_SH7780]    = "SH7780",
+       [CPU_SH7781]    = "SH7781",     [CPU_SH7343]    = "SH7343",
        [CPU_SH_NONE]   = "Unknown"
 };
 
@@ -438,8 +413,10 @@ const char *get_cpu_subtype(void)
 }
 
 #ifdef CONFIG_PROC_FS
+/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
-       "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", "ptea", NULL
+       "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+       "ptea", "llsc", "l2", NULL
 };
 
 static void show_cpuflags(struct seq_file *m)
@@ -460,7 +437,8 @@ static void show_cpuflags(struct seq_file *m)
        seq_printf(m, "\n");
 }
 
-static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_info info)
+static void show_cacheinfo(struct seq_file *m, const char *type,
+                          struct cache_info info)
 {
        unsigned int cache_size;
 
@@ -493,7 +471,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
         * unified cache on the SH-2 and SH-3, as well as the harvard
         * style cache on the SH-4.
         */
-       if (test_bit(SH_CACHE_COMBINED, &(boot_cpu_data.icache.flags))) {
+       if (boot_cpu_data.icache.flags & SH_CACHE_COMBINED) {
                seq_printf(m, "unified\n");
                show_cacheinfo(m, "cache", boot_cpu_data.icache);
        } else {
@@ -502,6 +480,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
        }
 
+       /* Optional secondary cache */
+       if (boot_cpu_data.flags & CPU_HAS_L2_CACHE)
+               show_cacheinfo(m, "scache", boot_cpu_data.scache);
+
        seq_printf(m, "bogomips\t: %lu.%02lu\n",
                     boot_cpu_data.loops_per_jiffy/(500000/HZ),
                     (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
@@ -617,4 +599,3 @@ static int __init kgdb_parse_options(char *options)
 }
 __setup("kgdb=", kgdb_parse_options);
 #endif /* CONFIG_SH_KGDB */
-
index 245ed8f945e8e705b72b1db956f9a5e40ada2e36..d3cbfa2ad4a785b13d9e6b130ee5c435b9cbf948 100644 (file)
@@ -27,21 +27,11 @@ EXPORT_SYMBOL(sh_mv);
 
 /* platform dependent support */
 EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(disable_irq_nosync);
 EXPORT_SYMBOL(irq_desc);
 EXPORT_SYMBOL(no_irq_type);
 
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
 
 /* PCI exports */
 #ifdef CONFIG_PCI
@@ -52,13 +42,8 @@ EXPORT_SYMBOL(pci_free_consistent);
 /* mem exports */
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memcpy_fromio);
-EXPORT_SYMBOL(memcpy_toio);
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memset_io);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__copy_user);
 EXPORT_SYMBOL(boot_cpu_data);
 
@@ -94,7 +79,9 @@ EXPORT_SYMBOL(strcpy);
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
 DECLARE_EXPORT(__movstrSI12_i4);
+#endif
 
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 /* needed by some modules */
 EXPORT_SYMBOL(flush_cache_all);
 EXPORT_SYMBOL(flush_cache_range);
@@ -102,11 +89,9 @@ EXPORT_SYMBOL(flush_dcache_page);
 EXPORT_SYMBOL(__flush_purge_region);
 #endif
 
-#if defined(CONFIG_SH7705_CACHE_32KB)
-EXPORT_SYMBOL(flush_cache_all);
-EXPORT_SYMBOL(flush_cache_range);
-EXPORT_SYMBOL(flush_dcache_page);
-EXPORT_SYMBOL(__flush_purge_region);
+#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \
+       defined(CONFIG_SH7705_CACHE_32KB))
+EXPORT_SYMBOL(clear_user_page);
 #endif
 
 EXPORT_SYMBOL(flush_tlb_page);
@@ -116,7 +101,12 @@ EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(synchronize_irq);
 #endif
 
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(pm_suspend);
+#endif
+
 EXPORT_SYMBOL(csum_partial);
+#ifdef CONFIG_IPV6
 EXPORT_SYMBOL(csum_ipv6_magic);
-EXPORT_SYMBOL(consistent_sync);
+#endif
 EXPORT_SYMBOL(clear_page);
index b475c4d2405f3e81795dfb39dfdd8aa2c350e94d..5213f5bc6ce0832c395f5b69f4eeacf407a41479 100644 (file)
@@ -8,7 +8,6 @@
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *
  */
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -21,6 +20,7 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
+#include <linux/elf.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 
-#define DEBUG_SIG 0
-
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -43,51 +39,17 @@ sys_sigsuspend(old_sigset_t mask,
               unsigned long r5, unsigned long r6, unsigned long r7,
               struct pt_regs regs)
 {
-       sigset_t saveset;
-
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, mask);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs.regs[0] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&regs, &saveset))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
-                 unsigned long r6, unsigned long r7,
-                 struct pt_regs regs)
-{
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs.regs[0] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&regs, &saveset))
-                       return -EINTR;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
 asmlinkage int 
@@ -348,7 +310,12 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        return (void __user *)((sp - frame_size) & -8ul);
 }
 
-static void setup_frame(int sig, struct k_sigaction *ka,
+/* These symbols are defined with the addresses in the vsyscall page.
+   See vsyscall-trapa.S.  */
+extern void __user __kernel_sigreturn;
+extern void __user __kernel_rt_sigreturn;
+
+static int setup_frame(int sig, struct k_sigaction *ka,
                        sigset_t *set, struct pt_regs *regs)
 {
        struct sigframe __user *frame;
@@ -368,15 +335,18 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 
        err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
 
-       if (_NSIG_WORDS > 1) {
+       if (_NSIG_WORDS > 1)
                err |= __copy_to_user(frame->extramask, &set->sig[1],
                                      sizeof(frame->extramask));
-       }
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
                regs->pr = (unsigned long) ka->sa.sa_restorer;
+#ifdef CONFIG_VSYSCALL
+       } else if (likely(current->mm->context.vdso)) {
+               regs->pr = VDSO_SYM(&__kernel_sigreturn);
+#endif
        } else {
                /* Generate return code (system call to sigreturn) */
                err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -402,21 +372,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 
        set_fs(USER_DS);
 
-#if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
-               current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
+       pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+                current->comm, current->pid, frame, regs->pc, regs->pr);
 
        flush_cache_sigtramp(regs->pr);
+
        if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
                flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
-       return;
+
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs *regs)
 {
        struct rt_sigframe __user *frame;
@@ -452,6 +423,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
                regs->pr = (unsigned long) ka->sa.sa_restorer;
+#ifdef CONFIG_VSYSCALL
+       } else if (likely(current->mm->context.vdso)) {
+               regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
+#endif
        } else {
                /* Generate return code (system call to rt_sigreturn) */
                err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -477,28 +452,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        set_fs(USER_DS);
 
-#if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
-               current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
+       pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+                current->comm, current->pid, frame, regs->pc, regs->pr);
 
        flush_cache_sigtramp(regs->pr);
+
        if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
                flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
-       return;
+
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
              sigset_t *oldset, struct pt_regs *regs)
 {
+       int ret;
+
        /* Are we from a system call? */
        if (regs->tra >= 0) {
                /* If so, check system call restarting.. */
@@ -539,19 +517,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
-               setup_frame(sig, ka, oldset, regs);
+               ret = setup_frame(sig, ka, oldset, regs);
 
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       if (ret == 0) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
+
+       return ret;
 }
 
 /*
@@ -563,11 +545,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -576,19 +559,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
        if (try_to_freeze())
                goto no_signal;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &ka, &info, oldset, regs);
-               return 1;
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
        }
 
  no_signal:
@@ -597,10 +588,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                /* Restart the system call - no handlers present */
                if (regs->regs[0] == -ERESTARTNOHAND ||
                    regs->regs[0] == -ERESTARTSYS ||
-                   regs->regs[0] == -ERESTARTNOINTR ||
-                   regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+                   regs->regs[0] == -ERESTARTNOINTR) {
+                       regs->regs[0] = save_r0;
+                       regs->pc -= 2;
+               } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
                        regs->pc -= 2;
+                       regs->regs[3] = __NR_restart_syscall;
                }
        }
-       return 0;
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
+                                __u32 thread_info_flags)
+{
+       /* deal with pending signal delivery */
+       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+               do_signal(regs, save_r0);
 }
index 917b2f32f260888b2a84b272303edce8d0b5c1b6..b68ff705f0673c56c1a6845d97569689df136932 100644 (file)
@@ -21,7 +21,8 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
-
+#include <linux/module.h>
+#include <asm/cacheflush.h>
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 
@@ -44,11 +45,16 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
        return error;
 }
 
-#if defined(HAVE_ARCH_UNMAPPED_AREA)
+unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
+
+EXPORT_SYMBOL(shm_align_mask);
+
 /*
- * To avoid cache alias, we map the shard page with same color.
+ * To avoid cache aliases, we map the shared page with same color.
  */
-#define COLOUR_ALIGN(addr)     (((addr)+SHMLBA-1)&~(SHMLBA-1))
+#define COLOUR_ALIGN(addr, pgoff)                              \
+       ((((addr) + shm_align_mask) & ~shm_align_mask) +        \
+        (((pgoff) << PAGE_SHIFT) & shm_align_mask))
 
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -56,43 +62,52 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long start_addr;
+       int do_colour_align;
 
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
+               if ((flags & MAP_SHARED) && (addr & shm_align_mask))
                        return -EINVAL;
                return addr;
        }
 
-       if (len > TASK_SIZE)
+       if (unlikely(len > TASK_SIZE))
                return -ENOMEM;
 
+       do_colour_align = 0;
+       if (filp || (flags & MAP_SHARED))
+               do_colour_align = 1;
+
        if (addr) {
-               if (flags & MAP_PRIVATE)
-                       addr = PAGE_ALIGN(addr);
+               if (do_colour_align)
+                       addr = COLOUR_ALIGN(addr, pgoff);
                else
-                       addr = COLOUR_ALIGN(addr);
+                       addr = PAGE_ALIGN(addr);
+
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       if (len <= mm->cached_hole_size) {
+
+       if (len > mm->cached_hole_size) {
+               start_addr = addr = mm->free_area_cache;
+       } else {
                mm->cached_hole_size = 0;
-               mm->free_area_cache = TASK_UNMAPPED_BASE;
+               start_addr = addr = TASK_UNMAPPED_BASE;
        }
-       if (flags & MAP_PRIVATE)
-               addr = PAGE_ALIGN(mm->free_area_cache);
-       else
-               addr = COLOUR_ALIGN(mm->free_area_cache);
-       start_addr = addr;
 
 full_search:
+       if (do_colour_align)
+               addr = COLOUR_ALIGN(addr, pgoff);
+       else
+               addr = PAGE_ALIGN(mm->free_area_cache);
+
        for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
                /* At this point:  (!vma || addr < vma->vm_end). */
-               if (TASK_SIZE - len < addr) {
+               if (unlikely(TASK_SIZE - len < addr)) {
                        /*
                         * Start a new search - just in case we missed
                         * some holes.
@@ -104,7 +119,7 @@ full_search:
                        }
                        return -ENOMEM;
                }
-               if (!vma || addr + len <= vma->vm_start) {
+               if (likely(!vma || addr + len <= vma->vm_start)) {
                        /*
                         * Remember the place where we stopped the search:
                         */
@@ -115,11 +130,10 @@ full_search:
                        mm->cached_hole_size = vma->vm_start - addr;
 
                addr = vma->vm_end;
-               if (!(flags & MAP_PRIVATE))
-                       addr = COLOUR_ALIGN(addr);
+               if (do_colour_align)
+                       addr = COLOUR_ALIGN(addr, pgoff);
        }
 }
-#endif
 
 static inline long
 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
new file mode 100644 (file)
index 0000000..768334e
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * arch/sh/kernel/syscalls.S
+ *
+ * System call table for SuperH
+ *
+ *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ *  Copyright (C) 2003  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/sys.h>
+#include <linux/linkage.h>
+
+#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl         sys_ni_syscall
+#endif
+
+#if !defined(CONFIG_MMU)
+#define sys_madvise            sys_ni_syscall
+#define sys_readahead          sys_ni_syscall
+#define sys_mprotect           sys_ni_syscall
+#define sys_msync              sys_ni_syscall
+#define sys_mlock              sys_ni_syscall
+#define sys_munlock            sys_ni_syscall
+#define sys_mlockall           sys_ni_syscall
+#define sys_munlockall         sys_ni_syscall
+#define sys_mremap             sys_ni_syscall
+#define sys_mincore            sys_ni_syscall
+#define sys_remap_file_pages   sys_ni_syscall
+#endif
+
+       .data
+ENTRY(sys_call_table)
+       .long sys_restart_syscall       /* 0  -  old "setup()" system call*/
+       .long sys_exit
+       .long sys_fork
+       .long sys_read
+       .long sys_write
+       .long sys_open          /* 5 */
+       .long sys_close
+       .long sys_waitpid
+       .long sys_creat
+       .long sys_link
+       .long sys_unlink                /* 10 */
+       .long sys_execve
+       .long sys_chdir
+       .long sys_time
+       .long sys_mknod
+       .long sys_chmod         /* 15 */
+       .long sys_lchown16
+       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid                /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid16
+       .long sys_getuid16
+       .long sys_stime         /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime         /* 30 */
+       .long sys_ni_syscall    /* old stty syscall holder */
+       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_access
+       .long sys_nice
+       .long sys_ni_syscall    /* 35 */                /* old ftime syscall holder */
+       .long sys_sync
+       .long sys_kill
+       .long sys_rename
+       .long sys_mkdir
+       .long sys_rmdir         /* 40 */
+       .long sys_dup
+       .long sys_pipe
+       .long sys_times
+       .long sys_ni_syscall    /* old prof syscall holder */
+       .long sys_brk           /* 45 */
+       .long sys_setgid16
+       .long sys_getgid16
+       .long sys_signal
+       .long sys_geteuid16
+       .long sys_getegid16     /* 50 */
+       .long sys_acct
+       .long sys_umount                /* recycled never used phys() */
+       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_ioctl
+       .long sys_fcntl         /* 55 */
+       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_setpgid
+       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_ni_syscall    /* sys_olduname */
+       .long sys_umask         /* 60 */
+       .long sys_chroot
+       .long sys_ustat
+       .long sys_dup2
+       .long sys_getppid
+       .long sys_getpgrp               /* 65 */
+       .long sys_setsid
+       .long sys_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid16    /* 70 */
+       .long sys_setregid16
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit     /* 75 */
+       .long sys_old_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups16   /* 80 */
+       .long sys_setgroups16
+       .long sys_ni_syscall    /* sys_oldselect */
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink              /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long old_mmap          /* 90 */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown16              /* 95 */
+       .long sys_getpriority
+       .long sys_setpriority
+       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_statfs
+       .long sys_fstatfs               /* 100 */
+       .long sys_ni_syscall    /* ioperm */
+       .long sys_socketcall
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer     /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_ni_syscall    /* 110 */ /* iopl */
+       .long sys_vhangup
+       .long sys_ni_syscall    /* idle */
+       .long sys_ni_syscall    /* vm86old */
+       .long sys_wait4
+       .long sys_swapoff               /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone         /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_ni_syscall    /* sys_modify_ldt */
+       .long sys_adjtimex
+       .long sys_mprotect              /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall    /* old "create_module" */
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs         /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall    /* for afs_syscall */
+       .long sys_setfsuid16
+       .long sys_setfsgid16
+       .long sys_llseek                /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv         /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock         /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
+       .long sys_sched_setparam
+       .long sys_sched_getparam   /* 155 */
+       .long sys_sched_setscheduler
+       .long sys_sched_getscheduler
+       .long sys_sched_yield
+       .long sys_sched_get_priority_max
+       .long sys_sched_get_priority_min  /* 160 */
+       .long sys_sched_rr_get_interval
+       .long sys_nanosleep
+       .long sys_mremap
+       .long sys_setresuid16
+       .long sys_getresuid16   /* 165 */
+       .long sys_ni_syscall    /* vm86 */
+       .long sys_ni_syscall    /* old "query_module" */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid16   /* 170 */
+       .long sys_getresgid16
+       .long sys_prctl
+       .long sys_rt_sigreturn
+       .long sys_rt_sigaction
+       .long sys_rt_sigprocmask        /* 175 */
+       .long sys_rt_sigpending
+       .long sys_rt_sigtimedwait
+       .long sys_rt_sigqueueinfo
+       .long sys_rt_sigsuspend
+       .long sys_pread_wrapper    /* 180 */
+       .long sys_pwrite_wrapper
+       .long sys_chown16
+       .long sys_getcwd
+       .long sys_capget
+       .long sys_capset           /* 185 */
+       .long sys_sigaltstack
+       .long sys_sendfile
+       .long sys_ni_syscall    /* streams1 */
+       .long sys_ni_syscall    /* streams2 */
+       .long sys_vfork            /* 190 */
+       .long sys_getrlimit
+       .long sys_mmap2
+       .long sys_truncate64
+       .long sys_ftruncate64
+       .long sys_stat64                /* 195 */
+       .long sys_lstat64
+       .long sys_fstat64
+       .long sys_lchown
+       .long sys_getuid
+       .long sys_getgid                /* 200 */
+       .long sys_geteuid
+       .long sys_getegid
+       .long sys_setreuid
+       .long sys_setregid
+       .long sys_getgroups     /* 205 */
+       .long sys_setgroups
+       .long sys_fchown
+       .long sys_setresuid
+       .long sys_getresuid
+       .long sys_setresgid     /* 210 */
+       .long sys_getresgid
+       .long sys_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid              /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       .long sys_getdents64    /* 220 */
+       .long sys_fcntl64
+       .long sys_ni_syscall    /* reserved for TUX */
+       .long sys_ni_syscall    /* Reserved for Security */
+       .long sys_gettid
+       .long sys_readahead     /* 225 */
+       .long sys_setxattr
+       .long sys_lsetxattr
+       .long sys_fsetxattr
+       .long sys_getxattr
+       .long sys_lgetxattr     /* 230 */
+       .long sys_fgetxattr
+       .long sys_listxattr
+       .long sys_llistxattr
+       .long sys_flistxattr
+       .long sys_removexattr   /* 235 */
+       .long sys_lremovexattr
+       .long sys_fremovexattr
+       .long sys_tkill
+       .long sys_sendfile64
+       .long sys_futex         /* 240 */
+       .long sys_sched_setaffinity
+       .long sys_sched_getaffinity
+       .long sys_ni_syscall
+       .long sys_ni_syscall
+       .long sys_io_setup      /* 245 */
+       .long sys_io_destroy
+       .long sys_io_getevents
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64     /* 250 */
+       .long sys_ni_syscall
+       .long sys_exit_group
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl     /* 255 */
+       .long sys_epoll_wait
+       .long sys_remap_file_pages
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
+       .long sys_statfs64
+       .long sys_fstatfs64
+       .long sys_tgkill                /* 270 */
+       .long sys_utimes
+       .long sys_fadvise64_64_wrapper
+       .long sys_ni_syscall    /* Reserved for vserver */
+       .long sys_ni_syscall    /* Reserved for mbind */
+       .long sys_ni_syscall    /* 275 - get_mempolicy */
+       .long sys_ni_syscall    /* set_mempolicy */
+       .long sys_mq_open
+       .long sys_mq_unlink
+       .long sys_mq_timedsend
+       .long sys_mq_timedreceive       /* 280 */
+       .long sys_mq_notify
+       .long sys_mq_getsetattr
+       .long sys_kexec_load
+       .long sys_waitid
+       .long sys_ni_syscall            /* 285 */
+       .long sys_add_key
+       .long sys_request_key
+       .long sys_keyctl
+       .long sys_ioprio_set
+       .long sys_ioprio_get            /* 290 */
+       .long sys_inotify_init
+       .long sys_inotify_add_watch
+       .long sys_inotify_rm_watch
+       .long sys_migrate_pages
+       .long sys_openat                /* 295 */
+       .long sys_mkdirat
+       .long sys_mknodat
+       .long sys_fchownat
+       .long sys_futimesat
+       .long sys_fstatat64             /* 300 */
+       .long sys_unlinkat
+       .long sys_renameat
+       .long sys_linkat
+       .long sys_symlinkat
+       .long sys_readlinkat            /* 305 */
+       .long sys_fchmodat
+       .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
index a1589f85499dc58323f5785d7848178f18c3b3ea..450c68f1df052f5ccba2eaef9d0149a1bc2390bf 100644 (file)
@@ -3,13 +3,12 @@
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002, 2003, 2004, 2005  Paul Mundt
+ *  Copyright (C) 2002 - 2006  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
  */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <asm/timer.h>
 #include <asm/kgdb.h>
 
-extern unsigned long wall_jiffies;
 struct sys_timer *sys_timer;
 
 /* Move this somewhere more sensible.. */
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
-/* XXX: Can we initialize this in a routine somewhere?  Dreamcast doesn't want
- * these routines anywhere... */
-#ifdef CONFIG_SH_RTC
-void (*rtc_get_time)(struct timespec *) = sh_rtc_gettimeofday;
-int (*rtc_set_time)(const time_t) = sh_rtc_settimeofday;
-#else
-void (*rtc_get_time)(struct timespec *);
-int (*rtc_set_time)(const time_t);
-#endif
+/* Dummy RTC ops */
+static void null_rtc_get_time(struct timespec *tv)
+{
+       tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+       tv->tv_nsec = 0;
+}
+
+static int null_rtc_set_time(const time_t secs)
+{
+       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;
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -48,16 +51,10 @@ void do_gettimeofday(struct timeval *tv)
 {
        unsigned long seq;
        unsigned long usec, sec;
-       unsigned long lost;
 
        do {
                seq = read_seqbegin(&xtime_lock);
                usec = get_timer_offset();
-
-               lost = jiffies - wall_jiffies;
-               if (lost)
-                       usec += lost * (1000000 / HZ);
-
                sec = xtime.tv_sec;
                usec += xtime.tv_nsec / 1000;
        } while (read_seqretry(&xtime_lock, seq));
@@ -70,7 +67,6 @@ void do_gettimeofday(struct timeval *tv)
        tv->tv_sec = sec;
        tv->tv_usec = usec;
 }
-
 EXPORT_SYMBOL(do_gettimeofday);
 
 int do_settimeofday(struct timespec *tv)
@@ -88,8 +84,7 @@ int do_settimeofday(struct timespec *tv)
         * wall time.  Discover what correction gettimeofday() would have
         * made, and then undo it!
         */
-       nsec -= 1000 * (get_timer_offset() +
-                               (jiffies - wall_jiffies) * (1000000 / HZ));
+       nsec -= 1000 * get_timer_offset();
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -103,7 +98,6 @@ int do_settimeofday(struct timespec *tv)
 
        return 0;
 }
-
 EXPORT_SYMBOL(do_settimeofday);
 
 /* last time the RTC clock got updated */
@@ -115,7 +109,7 @@ static long last_rtc_update;
  */
 void handle_timer_tick(struct pt_regs *regs)
 {
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -135,7 +129,7 @@ void handle_timer_tick(struct pt_regs *regs)
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-               if (rtc_set_time(xtime.tv_sec) == 0)
+               if (rtc_sh_set_time(xtime.tv_sec) == 0)
                        last_rtc_update = xtime.tv_sec;
                else
                        /* do it again in 60s */
@@ -143,8 +137,33 @@ void handle_timer_tick(struct pt_regs *regs)
        }
 }
 
+#ifdef CONFIG_PM
+int timer_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
+
+       sys_timer->ops->stop();
+
+       return 0;
+}
+
+int timer_resume(struct sys_device *dev)
+{
+       struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
+
+       sys_timer->ops->start();
+
+       return 0;
+}
+#else
+#define timer_suspend NULL
+#define timer_resume NULL
+#endif
+
 static struct sysdev_class timer_sysclass = {
        set_kset_name("timer"),
+       .suspend = timer_suspend,
+       .resume  = timer_resume,
 };
 
 static int __init timer_init_sysfs(void)
@@ -156,7 +175,6 @@ static int __init timer_init_sysfs(void)
        sys_timer->dev.cls = &timer_sysclass;
        return sysdev_register(&sys_timer->dev);
 }
-
 device_initcall(timer_init_sysfs);
 
 void (*board_time_init)(void);
@@ -168,15 +186,9 @@ void __init time_init(void)
 
        clk_init();
 
-       if (rtc_get_time) {
-               rtc_get_time(&xtime);
-       } else {
-               xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0);
-               xtime.tv_nsec = 0;
-       }
-
-        set_normalized_timespec(&wall_to_monotonic,
-                                -xtime.tv_sec, -xtime.tv_nsec);
+       rtc_sh_get_time(&xtime);
+       set_normalized_timespec(&wall_to_monotonic,
+                               -xtime.tv_sec, -xtime.tv_nsec);
 
        /*
         * Find the timer to use as the system timer, it will be
index d4212add53b264094c0261d12011bc610bd6d978..205816fcf0da50d7fecdeecd5975c2fbaf6c0a9e 100644 (file)
@@ -132,17 +132,17 @@ static unsigned long tmu_timer_get_frequency(void)
        ctrl_outl(0xffffffff, TMU0_TCOR);
        ctrl_outl(0xffffffff, TMU0_TCNT);
 
-       rtc_get_time(&ts2);
+       rtc_sh_get_time(&ts2);
 
        do {
-               rtc_get_time(&ts1);
+               rtc_sh_get_time(&ts1);
        } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
 
        /* actually start the timer */
        ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
 
        do {
-               rtc_get_time(&ts2);
+               rtc_sh_get_time(&ts2);
        } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
 
        freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
@@ -188,6 +188,18 @@ static struct clk tmu0_clk = {
        .ops            = &tmu_clk_ops,
 };
 
+static int tmu_timer_start(void)
+{
+       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+       return 0;
+}
+
+static int tmu_timer_stop(void)
+{
+       ctrl_outb(0, TMU_TSTR);
+       return 0;
+}
+
 static int tmu_timer_init(void)
 {
        unsigned long interval;
@@ -197,7 +209,7 @@ static int tmu_timer_init(void)
        tmu0_clk.parent = clk_get("module_clk");
 
        /* Start TMU0 */
-       ctrl_outb(0, TMU_TSTR);
+       tmu_timer_stop();
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
        ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 #endif
@@ -211,13 +223,15 @@ static int tmu_timer_init(void)
        ctrl_outl(interval, TMU0_TCOR);
        ctrl_outl(interval, TMU0_TCNT);
 
-       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+       tmu_timer_start();
 
        return 0;
 }
 
 struct sys_timer_ops tmu_timer_ops = {
        .init           = tmu_timer_init,
+       .start          = tmu_timer_start,
+       .stop           = tmu_timer_stop,
        .get_frequency  = tmu_timer_get_frequency,
        .get_offset     = tmu_timer_get_offset,
 };
index d9db1180f770faa264b561a3f20c14e32d1b671b..c2c597e0948242c780d4d369dff64c69dee14c59 100644 (file)
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
-#define CHK_REMOTE_DEBUG(regs)                                               \
-{                                                                            \
-  if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
-  {                                                                          \
-    (*kgdb_debug_hook)(regs);                                                \
-  }                                                                          \
+#define CHK_REMOTE_DEBUG(regs)                         \
+{                                              \
+       if (kgdb_debug_hook && !user_mode(regs))\
+               (*kgdb_debug_hook)(regs);       \
 }
 #else
 #define CHK_REMOTE_DEBUG(regs)
 #endif
 
-#define DO_ERROR(trapnr, signr, str, name, tsk)                                \
-asmlinkage void do_##name(unsigned long r4, unsigned long r5,          \
-                         unsigned long r6, unsigned long r7,           \
-                         struct pt_regs regs)                          \
-{                                                                      \
-       unsigned long error_code;                                       \
-                                                                       \
-       /* Check if it's a DSP instruction */                           \
-       if (is_dsp_inst(&regs)) {                                       \
-               /* Enable DSP mode, and restart instruction. */         \
-               regs.sr |= SR_DSP;                                      \
-               return;                                                 \
-       }                                                               \
-                                                                       \
-       asm volatile("stc       r2_bank, %0": "=r" (error_code));       \
-       local_irq_enable();                                             \
-       tsk->thread.error_code = error_code;                            \
-       tsk->thread.trap_no = trapnr;                                   \
-        CHK_REMOTE_DEBUG(&regs);                                       \
-       force_sig(signr, tsk);                                          \
-       die_if_no_fixup(str,&regs,error_code);                          \
-}
-
 #ifdef CONFIG_CPU_SH2
 #define TRAP_RESERVED_INST     4
 #define TRAP_ILLEGAL_SLOT_INST 6
@@ -86,7 +61,7 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5,         \
 #define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
-spinlock_t die_lock;
+DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -575,8 +550,117 @@ int is_dsp_inst(struct pt_regs *regs)
 #define is_dsp_inst(regs)      (0)
 #endif /* CONFIG_SH_DSP */
 
-DO_ERROR(TRAP_RESERVED_INST, SIGILL, "reserved instruction", reserved_inst, current)
-DO_ERROR(TRAP_ILLEGAL_SLOT_INST, SIGILL, "illegal slot instruction", illegal_slot_inst, current)
+extern int do_fpu_inst(unsigned short, struct pt_regs*);
+
+asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs regs)
+{
+       unsigned long error_code;
+       struct task_struct *tsk = current;
+
+#ifdef CONFIG_SH_FPU_EMU
+       unsigned short inst;
+       int err;
+
+       get_user(inst, (unsigned short*)regs.pc);
+
+       err = do_fpu_inst(inst, &regs);
+       if (!err) {
+               regs.pc += 2;
+               return;
+       }
+       /* not a FPU inst. */
+#endif
+
+#ifdef CONFIG_SH_DSP
+       /* Check if it's a DSP instruction */
+       if (is_dsp_inst(&regs)) {
+               /* Enable DSP mode, and restart instruction. */
+               regs.sr |= SR_DSP;
+               return;
+       }
+#endif
+
+       asm volatile("stc       r2_bank, %0": "=r" (error_code));
+       local_irq_enable();
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = TRAP_RESERVED_INST;
+       CHK_REMOTE_DEBUG(&regs);
+       force_sig(SIGILL, tsk);
+       die_if_no_fixup("reserved instruction", &regs, error_code);
+}
+
+#ifdef CONFIG_SH_FPU_EMU
+static int emulate_branch(unsigned short inst, struct pt_regs* regs)
+{
+       /*
+        * bfs: 8fxx: PC+=d*2+4;
+        * bts: 8dxx: PC+=d*2+4;
+        * bra: axxx: PC+=D*2+4;
+        * bsr: bxxx: PC+=D*2+4  after PR=PC+4;
+        * braf:0x23: PC+=Rn*2+4;
+        * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4;
+        * jmp: 4x2b: PC=Rn;
+        * jsr: 4x0b: PC=Rn      after PR=PC+4;
+        * rts: 000b: PC=PR;
+        */
+       if ((inst & 0xfd00) == 0x8d00) {
+               regs->pc += SH_PC_8BIT_OFFSET(inst);
+               return 0;
+       }
+
+       if ((inst & 0xe000) == 0xa000) {
+               regs->pc += SH_PC_12BIT_OFFSET(inst);
+               return 0;
+       }
+
+       if ((inst & 0xf0df) == 0x0003) {
+               regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4;
+               return 0;
+       }
+
+       if ((inst & 0xf0df) == 0x400b) {
+               regs->pc = regs->regs[(inst & 0x0f00) >> 8];
+               return 0;
+       }
+
+       if ((inst & 0xffff) == 0x000b) {
+               regs->pc = regs->pr;
+               return 0;
+       }
+
+       return 1;
+}
+#endif
+
+asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs regs)
+{
+       unsigned long error_code;
+       struct task_struct *tsk = current;
+#ifdef CONFIG_SH_FPU_EMU
+       unsigned short inst;
+
+       get_user(inst, (unsigned short *)regs.pc + 1);
+       if (!do_fpu_inst(inst, &regs)) {
+               get_user(inst, (unsigned short *)regs.pc);
+               if (!emulate_branch(inst, &regs))
+                       return;
+               /* fault in branch.*/
+       }
+       /* not a FPU inst. */
+#endif
+
+       asm volatile("stc       r2_bank, %0": "=r" (error_code));
+       local_irq_enable();
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = TRAP_RESERVED_INST;
+       CHK_REMOTE_DEBUG(&regs);
+       force_sig(SIGILL, tsk);
+       die_if_no_fixup("illegal slot instruction", &regs, error_code);
+}
 
 asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
                                   unsigned long r6, unsigned long r7,
@@ -634,14 +718,16 @@ void __init trap_init(void)
        exception_handling_table[TRAP_ILLEGAL_SLOT_INST]
                = (void *)do_illegal_slot_inst;
 
-#ifdef CONFIG_CPU_SH4
-       if (!(cpu_data->flags & CPU_HAS_FPU)) {
-               /* For SH-4 lacking an FPU, treat floating point instructions
-                  as reserved. */
-               /* entry 64 corresponds to EXPEVT=0x800 */
-               exception_handling_table[64] = (void *)do_reserved_inst;
-               exception_handling_table[65] = (void *)do_illegal_slot_inst;
-       }
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
+    defined(CONFIG_SH_FPU_EMU)
+       /*
+        * For SH-4 lacking an FPU, treat floating point instructions as
+        * reserved. They'll be handled in the math-emu case, or faulted on
+        * otherwise.
+        */
+       /* entry 64 corresponds to EXPEVT=0x800 */
+       exception_handling_table[64] = (void *)do_reserved_inst;
+       exception_handling_table[65] = (void *)do_illegal_slot_inst;
 #endif
                
        /* Setup VBR for boot cpu */
@@ -655,20 +741,12 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
        unsigned long module_end = VMALLOC_END;
        int i = 1;
 
-       if (tsk && !sp) {
+       if (!tsk)
+               tsk = current;
+       if (tsk == current)
+               sp = (unsigned long *)current_stack_pointer;
+       else
                sp = (unsigned long *)tsk->thread.sp;
-       }
-
-       if (!sp) {
-               __asm__ __volatile__ (
-                       "mov r15, %0\n\t"
-                       "stc r7_bank, %1\n\t"
-                       : "=r" (module_start),
-                         "=r" (module_end)
-               );
-               
-               sp = (unsigned long *)module_start;
-       }
 
        stack = sp;
 
index 95fdd9135fcfa54f2f1cb8034ace006a78009036..5eb9309181865a15343d39934af2bf282ef57c94 100644 (file)
@@ -2,6 +2,7 @@
  * ld script to make SuperH Linux kernel
  * Written by Niibe Yutaka
  */
+#include <asm/thread_info.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
@@ -13,7 +14,7 @@ OUTPUT_ARCH(sh)
 ENTRY(_start)
 SECTIONS
 {
-  . = 0x80000000 + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+  . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
   _text = .;                   /* Text and read-only data */
   text = .;                    /* Text and read-only data */
   .empty_zero_page : {
@@ -40,16 +41,16 @@ SECTIONS
        *(.data)
 
         /* Align the initial ramdisk image (INITRD) on page boundaries. */
-        . = ALIGN(4096);
+        . = ALIGN(PAGE_SIZE);
         __rd_start = .;
         *(.initrd)
-        . = ALIGN(4096);
+        . = ALIGN(PAGE_SIZE);
         __rd_end = .;
 
        CONSTRUCTORS
        }
 
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE);
   .data.page_aligned : { *(.data.idt) }
 
   . = ALIGN(32);
@@ -60,12 +61,10 @@ SECTIONS
 
   _edata = .;                  /* End of data section */
 
-  . = ALIGN(8192);             /* init_task */
+  . = ALIGN(THREAD_SIZE);              /* init_task */
   .data.init_task : { *(.data.init_task) }
-  /* stack */
-  .stack : { stack = .;  _stack = .; }
 
-  . = ALIGN(4096);             /* Init code and data */
+  . = ALIGN(PAGE_SIZE);                /* Init code and data */
   __init_begin = .;
   _sinittext = .;
   .init.text : { *(.init.text) }
@@ -96,7 +95,7 @@ SECTIONS
   __machvec_start = .;
   .init.machvec : { *(.init.machvec) }
   __machvec_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
   . = ALIGN(4);
diff --git a/arch/sh/kernel/vsyscall/Makefile b/arch/sh/kernel/vsyscall/Makefile
new file mode 100644 (file)
index 0000000..4bbce1c
--- /dev/null
@@ -0,0 +1,36 @@
+obj-y += vsyscall.o vsyscall-syscall.o
+
+$(obj)/vsyscall-syscall.o: \
+       $(foreach F,trapa,$(obj)/vsyscall-$F.so)
+
+# Teach kbuild about targets
+targets += $(foreach F,trapa,vsyscall-$F.o vsyscall-$F.so)
+targets += vsyscall-note.o vsyscall.lds
+
+# The DSO images are built using a special linker script
+quiet_cmd_syscall = SYSCALL $@
+      cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
+                          -Wl,-T,$(filter-out FORCE,$^) -o $@
+
+export CPPFLAGS_vsyscall.lds += -P -C -Ush
+
+vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
+               $(call ld-option, -Wl$(comma)--hash-style=sysv)
+
+SYSCFLAGS_vsyscall-trapa.so    = $(vsyscall-flags)
+
+$(obj)/vsyscall-trapa.so: \
+$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+       $(call if_changed,syscall)
+
+# We also create a special relocatable object that should mirror the symbol
+# table and layout of the linked DSO.  With ld -R we can then refer to
+# these symbols in the kernel code rather than hand-coded addresses.
+extra-y += vsyscall-syms.o
+$(obj)/built-in.o: $(obj)/vsyscall-syms.o
+$(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
+
+SYSCFLAGS_vsyscall-syms.o = -r
+$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
+                       $(obj)/vsyscall-trapa.o $(obj)/vsyscall-note.o FORCE
+       $(call if_changed,syscall)
diff --git a/arch/sh/kernel/vsyscall/vsyscall-note.S b/arch/sh/kernel/vsyscall/vsyscall-note.S
new file mode 100644 (file)
index 0000000..d4b5be4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+
+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type)                        \
+       .section name, flags;                                                 \
+       .balign 4;                                                            \
+       .long 1f - 0f;          /* name length */                             \
+       .long 3f - 2f;          /* data length */                             \
+       .long type;             /* note type */                               \
+0:     .asciz vendor;          /* vendor name */                             \
+1:     .balign 4;                                                            \
+2:
+
+#define ASM_ELF_NOTE_END                                                     \
+3:     .balign 4;              /* pad out section */                         \
+       .previous
+
+       ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
+       .long LINUX_VERSION_CODE
+       ASM_ELF_NOTE_END
diff --git a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
new file mode 100644 (file)
index 0000000..555a64f
--- /dev/null
@@ -0,0 +1,39 @@
+#include <asm/unistd.h>
+
+       .text
+       .balign 32
+       .globl __kernel_sigreturn
+       .type __kernel_sigreturn,@function
+__kernel_sigreturn:
+.LSTART_sigreturn:
+       mov.w   1f, r3
+       trapa   #0x10
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+
+1:     .short  __NR_sigreturn
+.LEND_sigreturn:
+       .size __kernel_sigreturn,.-.LSTART_sigreturn
+
+       .balign 32
+       .globl __kernel_rt_sigreturn
+       .type __kernel_rt_sigreturn,@function
+__kernel_rt_sigreturn:
+.LSTART_rt_sigreturn:
+       mov.w   1f, r3
+       trapa   #0x10
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+
+1:     .short  __NR_rt_sigreturn
+.LEND_rt_sigreturn:
+       .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
+
+       .section .eh_frame,"a",@progbits
+       .previous
diff --git a/arch/sh/kernel/vsyscall/vsyscall-syscall.S b/arch/sh/kernel/vsyscall/vsyscall-syscall.S
new file mode 100644 (file)
index 0000000..c2ac7f0
--- /dev/null
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+       .globl vsyscall_trapa_start, vsyscall_trapa_end
+vsyscall_trapa_start:
+       .incbin "arch/sh/kernel/vsyscall/vsyscall-trapa.so"
+vsyscall_trapa_end:
+
+__FINIT
diff --git a/arch/sh/kernel/vsyscall/vsyscall-trapa.S b/arch/sh/kernel/vsyscall/vsyscall-trapa.S
new file mode 100644 (file)
index 0000000..3b6eb34
--- /dev/null
@@ -0,0 +1,42 @@
+       .text
+       .globl __kernel_vsyscall
+       .type __kernel_vsyscall,@function
+__kernel_vsyscall:
+.LSTART_vsyscall:
+       /* XXX: We'll have to do something here once we opt to use the vDSO
+        * page for something other than the signal trampoline.. as well as
+        * fill out .eh_frame -- PFM. */
+.LEND_vsyscall:
+       .size __kernel_vsyscall,.-.LSTART_vsyscall
+       .previous
+
+       .section .eh_frame,"a",@progbits
+.LCIE:
+       .ualong .LCIE_end - .LCIE_start
+.LCIE_start:
+       .ualong 0               /* CIE ID */
+       .byte   0x1             /* Version number */
+       .string "zRS"           /* NUL-terminated augmentation string */
+       .uleb128 0x1            /* Code alignment factor */
+       .sleb128 -4             /* Data alignment factor */
+       .byte   0x11            /* Return address register column */
+                               /* Augmentation length and data (none) */
+       .byte   0xc             /* DW_CFA_def_cfa */
+       .uleb128 0xf            /* r15 */
+       .uleb128 0x0            /* offset 0 */
+
+       .align 2
+.LCIE_end:
+
+       .ualong .LFDE_end-.LFDE_start   /* Length FDE */
+.LFDE_start:
+       .ualong .LCIE                   /* CIE pointer */
+       .ualong .LSTART_vsyscall-.      /* start address */
+       .ualong .LEND_vsyscall-.LSTART_vsyscall
+       .uleb128 0
+       .align 2
+.LFDE_end:
+       .previous
+
+/* Get the common code for the sigreturn entry points */
+#include "vsyscall-sigreturn.S"
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
new file mode 100644 (file)
index 0000000..075d6cc
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * arch/sh/kernel/vsyscall.c
+ *
+ *  Copyright (C) 2006 Paul Mundt
+ *
+ * vDSO randomization
+ * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
+ *
+ * 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/mm.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/elf.h>
+
+/*
+ * Should the kernel map a VDSO page into processes and pass its
+ * address down to glibc upon exec()?
+ */
+unsigned int __read_mostly vdso_enabled = 1;
+EXPORT_SYMBOL_GPL(vdso_enabled);
+
+static int __init vdso_setup(char *s)
+{
+       vdso_enabled = simple_strtoul(s, NULL, 0);
+       return 1;
+}
+__setup("vdso=", vdso_setup);
+
+/*
+ * These symbols are defined by vsyscall.o to mark the bounds
+ * of the ELF DSO images included therein.
+ */
+extern const char vsyscall_trapa_start, vsyscall_trapa_end;
+static void *syscall_page;
+
+int __init vsyscall_init(void)
+{
+       syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+
+       /*
+        * XXX: Map this page to a fixmap entry if we get around
+        * to adding the page to ELF core dumps
+        */
+
+       memcpy(syscall_page,
+              &vsyscall_trapa_start,
+              &vsyscall_trapa_end - &vsyscall_trapa_start);
+
+       return 0;
+}
+
+static struct page *syscall_vma_nopage(struct vm_area_struct *vma,
+                                      unsigned long address, int *type)
+{
+       unsigned long offset = address - vma->vm_start;
+       struct page *page;
+
+       if (address < vma->vm_start || address > vma->vm_end)
+               return NOPAGE_SIGBUS;
+
+       page = virt_to_page(syscall_page + offset);
+
+       get_page(page);
+
+       return page;
+}
+
+/* Prevent VMA merging */
+static void syscall_vma_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct syscall_vm_ops = {
+       .nopage = syscall_vma_nopage,
+       .close  = syscall_vma_close,
+};
+
+/* Setup a VMA at program startup for the vsyscall page */
+int arch_setup_additional_pages(struct linux_binprm *bprm,
+                               int executable_stack)
+{
+       struct vm_area_struct *vma;
+       struct mm_struct *mm = current->mm;
+       unsigned long addr;
+       int ret;
+
+       down_write(&mm->mmap_sem);
+       addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+       if (IS_ERR_VALUE(addr)) {
+               ret = addr;
+               goto up_fail;
+       }
+
+       vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+       if (!vma) {
+               ret = -ENOMEM;
+               goto up_fail;
+       }
+
+       vma->vm_start = addr;
+       vma->vm_end = addr + PAGE_SIZE;
+       /* MAYWRITE to allow gdb to COW and set breakpoints */
+       vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+       vma->vm_flags |= mm->def_flags;
+       vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+       vma->vm_ops = &syscall_vm_ops;
+       vma->vm_mm = mm;
+
+       ret = insert_vm_struct(mm, vma);
+       if (unlikely(ret)) {
+               kmem_cache_free(vm_area_cachep, vma);
+               goto up_fail;
+       }
+
+       current->mm->context.vdso = (void *)addr;
+
+       mm->total_vm++;
+up_fail:
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+               return "[vdso]";
+
+       return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *task)
+{
+       return NULL;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long address)
+{
+       return 0;
+}
+
+int in_gate_area_no_task(unsigned long address)
+{
+       return 0;
+}
diff --git a/arch/sh/kernel/vsyscall/vsyscall.lds.S b/arch/sh/kernel/vsyscall/vsyscall.lds.S
new file mode 100644 (file)
index 0000000..b13c3d4
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Linker script for vsyscall DSO.  The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page).  This script controls its layout.
+ */
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
+#else
+OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
+#endif
+OUTPUT_ARCH(sh)
+
+/* The ELF entry point can be used to set the AT_SYSINFO value.  */
+ENTRY(__kernel_vsyscall);
+
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+
+  .hash           : { *(.hash) }               :text
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+
+  /* This linker script is used both with -r and with -shared.
+     For the layouts to match, we need to skip more than enough
+     space for the dynamic symbol table et al.  If this amount
+     is insufficient, ld -shared will barf.  Just increase it here.  */
+  . = 0x400;
+
+  .text           : { *(.text) }               :text =0x90909090
+  .note                  : { *(.note.*) }              :text :note
+  .eh_frame_hdr   : { *(.eh_frame_hdr) }       :text :eh_frame_hdr
+  .eh_frame       : { KEEP (*(.eh_frame)) }    :text
+  .dynamic        : { *(.dynamic) }            :text :dynamic
+  .useless        : {
+       *(.got.plt) *(.got)
+       *(.data .data.* .gnu.linkonce.d.*)
+       *(.dynbss)
+       *(.bss .bss.* .gnu.linkonce.b.*)
+  }                                            :text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  note PT_NOTE FLAGS(4); /* PF_R */
+  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+  LINUX_2.6 {
+    global:
+       __kernel_vsyscall;
+       __kernel_sigreturn;
+       __kernel_rt_sigreturn;
+
+    local: *;
+  };
+}
index 7c50dfe68c07707cab8b8e8793a98a423741b68e..cbdd0d40e545f0fa0d5cea817a472f46175f5a47 100644 (file)
@@ -202,8 +202,9 @@ ENTRY(csum_partial_copy_generic)
        cmp/pz  r6              ! Jump if we had at least two bytes.
        bt/s    1f
         clrt
+       add     #2,r6           ! r6 was < 2.   Deal with it.
        bra     4f
-        add    #2,r6           ! r6 was < 2.   Deal with it.
+        mov    r6,r2
 
 3:     ! Handle different src and dest alignments.
        ! This is not common, so simple byte by byte copy will do.
index db6b736537adf9ff7e46f7aa7d69bd8260a83a19..560bc17eebdd6748d1e49e40730a476b3cbe1c3a 100644 (file)
@@ -727,8 +727,8 @@ ENTRY(memcpy)
        mov.l   @(0x04,r5), r11 !  18 LS (latency=2)
        xtrct   r9, r8          !  48 EX
 
-       mov.w   @(0x02,r5), r12 !  18 LS (latency=2)
-       xtrct   r10, r9         !  48 EX
+       mov.l   @(0x00,r5), r12 !  18 LS (latency=2)
+       xtrct   r10, r9         !  48 EX
 
        movca.l r0,@r1          !  40 LS (latency=3-7)
        add     #-0x1c, r1      !  50 EX
index 95670090680e5d5c6e6396c1a730a1ade66edd97..af91fe2b72a66e571ed3c7f08fca44b68f4a4565 100644 (file)
@@ -29,6 +29,7 @@ ENTRY(memset)
        bf/s    1b
         mov.b  r5,@-r4
 2:                             ! make VVVV
+       extu.b  r5,r5
        swap.b  r5,r0           !   V0
        or      r0,r5           !   VV
        swap.w  r5,r0           ! VV00
diff --git a/arch/sh/math-emu/Makefile b/arch/sh/math-emu/Makefile
new file mode 100644 (file)
index 0000000..638b342
--- /dev/null
@@ -0,0 +1 @@
+obj-y  := math.o
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
new file mode 100644 (file)
index 0000000..26b6046
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * arch/sh/math-emu/math.c
+ *
+ * Copyright (C) 2006 Takashi YOSHII <takasi-y@ops.dti.ne.jp>
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#include "sfp-util.h"
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+#include <math-emu/double.h>
+
+#define        FPUL            (fregs->fpul)
+#define FPSCR          (fregs->fpscr)
+#define FPSCR_RM       (FPSCR&3)
+#define FPSCR_DN       ((FPSCR>>18)&1)
+#define FPSCR_PR       ((FPSCR>>19)&1)
+#define FPSCR_SZ       ((FPSCR>>20)&1)
+#define FPSCR_FR       ((FPSCR>>21)&1)
+#define FPSCR_MASK     0x003fffffUL
+
+#define BANK(n)        (n^(FPSCR_FR?16:0))
+#define FR     ((unsigned long*)(fregs->fp_regs))
+#define FR0    (FR[BANK(0)])
+#define FRn    (FR[BANK(n)])
+#define FRm    (FR[BANK(m)])
+#define DR     ((unsigned long long*)(fregs->fp_regs))
+#define DRn    (DR[BANK(n)/2])
+#define DRm    (DR[BANK(m)/2])
+
+#define XREG(n)        (n^16)
+#define XFn    (FR[BANK(XREG(n))])
+#define XFm    (FR[BANK(XREG(m))])
+#define XDn    (DR[BANK(XREG(n))/2])
+#define XDm    (DR[BANK(XREG(m))/2])
+
+#define R0     (regs->regs[0])
+#define Rn     (regs->regs[n])
+#define Rm     (regs->regs[m])
+
+#define WRITE(d,a)     ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
+#define READ(d,a)      ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
+
+#define PACK_S(r,f)    FP_PACK_SP(&r,f)
+#define UNPACK_S(f,r)  FP_UNPACK_SP(f,&r)
+#define PACK_D(r,f) \
+       {u32 t[2]; FP_PACK_DP(t,f); ((u32*)&r)[0]=t[1]; ((u32*)&r)[1]=t[0];}
+#define UNPACK_D(f,r) \
+       {u32 t[2]; t[0]=((u32*)&r)[1]; t[1]=((u32*)&r)[0]; FP_UNPACK_DP(f,t);}
+
+// 2 args instructions.
+#define BOTH_PRmn(op,x) \
+       FP_DECL_EX; if(FPSCR_PR) op(D,x,DRm,DRn); else op(S,x,FRm,FRn);
+
+#define CMP_X(SZ,R,M,N) do{ \
+       FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
+       UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+       FP_CMP_##SZ(R, Fn, Fm, 2); }while(0)
+#define EQ_X(SZ,R,M,N) do{ \
+       FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
+       UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+       FP_CMP_EQ_##SZ(R, Fn, Fm); }while(0)
+#define CMP(OP) ({ int r; BOTH_PRmn(OP##_X,r); r; })
+
+static int
+fcmp_gt(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       if (CMP(CMP) > 0)
+               regs->sr |= 1;
+       else
+               regs->sr &= ~1;
+
+       return 0;
+}
+
+static int
+fcmp_eq(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       if (CMP(CMP /*EQ*/) == 0)
+               regs->sr |= 1;
+       else
+               regs->sr &= ~1;
+       return 0;
+}
+
+#define ARITH_X(SZ,OP,M,N) do{ \
+       FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); FP_DECL_##SZ(Fr); \
+       UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+       FP_##OP##_##SZ(Fr, Fn, Fm); \
+       PACK_##SZ(N, Fr); }while(0)
+
+static int
+fadd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, ADD);
+       return 0;
+}
+
+static int
+fsub(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, SUB);
+       return 0;
+}
+
+static int
+fmul(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, MUL);
+       return 0;
+}
+
+static int
+fdiv(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, DIV);
+       return 0;
+}
+
+static int
+fmac(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       FP_DECL_EX;
+       FP_DECL_S(Fr);
+       FP_DECL_S(Ft);
+       FP_DECL_S(F0);
+       FP_DECL_S(Fm);
+       FP_DECL_S(Fn);
+       UNPACK_S(F0, FR0);
+       UNPACK_S(Fm, FRm);
+       UNPACK_S(Fn, FRn);
+       FP_MUL_S(Ft, Fm, F0);
+       FP_ADD_S(Fr, Fn, Ft);
+       PACK_S(FRn, Fr);
+       return 0;
+}
+
+// to process fmov's extention (odd n for DR access XD).
+#define FMOV_EXT(x) if(x&1) x+=16-1
+
+static int
+fmov_idx_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(n);
+               READ(FRn, Rm + R0 + 4);
+               n++;
+               READ(FRn, Rm + R0);
+       } else {
+               READ(FRn, Rm + R0);
+       }
+
+       return 0;
+}
+
+static int
+fmov_mem_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(n);
+               READ(FRn, Rm + 4);
+               n++;
+               READ(FRn, Rm);
+       } else {
+               READ(FRn, Rm);
+       }
+
+       return 0;
+}
+
+static int
+fmov_inc_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(n);
+               READ(FRn, Rm + 4);
+               n++;
+               READ(FRn, Rm);
+               Rm += 8;
+       } else {
+               READ(FRn, Rm);
+               Rm += 4;
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_idx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               WRITE(FRm, Rn + R0 + 4);
+               m++;
+               WRITE(FRm, Rn + R0);
+       } else {
+               WRITE(FRm, Rn + R0);
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_mem(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               WRITE(FRm, Rn + 4);
+               m++;
+               WRITE(FRm, Rn);
+       } else {
+               WRITE(FRm, Rn);
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_dec(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               Rn -= 8;
+               WRITE(FRm, Rn + 4);
+               m++;
+               WRITE(FRm, Rn);
+       } else {
+               Rn -= 4;
+               WRITE(FRm, Rn);
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               FMOV_EXT(n);
+               DRn = DRm;
+       } else {
+               FRn = FRm;
+       }
+
+       return 0;
+}
+
+static int
+fnop_mn(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       return -EINVAL;
+}
+
+// 1 arg instructions.
+#define NOTYETn(i) static int i(struct sh_fpu_soft_struct *fregs, int n) \
+       { printk( #i " not yet done.\n"); return 0; }
+
+NOTYETn(ftrv)
+NOTYETn(fsqrt)
+NOTYETn(fipr)
+NOTYETn(fsca)
+NOTYETn(fsrra)
+
+#define EMU_FLOAT_X(SZ,N) do { \
+       FP_DECL_##SZ(Fn); \
+       FP_FROM_INT_##SZ(Fn, FPUL, 32, int); \
+       PACK_##SZ(N, Fn); }while(0)
+static int ffloat(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+
+       if (FPSCR_PR)
+               EMU_FLOAT_X(D, DRn);
+       else
+               EMU_FLOAT_X(S, FRn);
+
+       return 0;
+}
+
+#define EMU_FTRC_X(SZ,N) do { \
+       FP_DECL_##SZ(Fn); \
+       UNPACK_##SZ(Fn, N); \
+       FP_TO_INT_##SZ(FPUL, Fn, 32, 1); }while(0)
+static int ftrc(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+
+       if (FPSCR_PR)
+               EMU_FTRC_X(D, DRn);
+       else
+               EMU_FTRC_X(S, FRn);
+
+       return 0;
+}
+
+static int fcnvsd(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+       FP_DECL_S(Fn);
+       FP_DECL_D(Fr);
+       UNPACK_S(Fn, FPUL);
+       FP_CONV(D, S, 2, 1, Fr, Fn);
+       PACK_D(DRn, Fr);
+       return 0;
+}
+
+static int fcnvds(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+       FP_DECL_D(Fn);
+       FP_DECL_S(Fr);
+       UNPACK_D(Fn, DRn);
+       FP_CONV(S, D, 1, 2, Fr, Fn);
+       PACK_S(FPUL, Fr);
+       return 0;
+}
+
+static int fxchg(struct sh_fpu_soft_struct *fregs, int flag)
+{
+       FPSCR ^= flag;
+       return 0;
+}
+
+static int fsts(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn = FPUL;
+       return 0;
+}
+
+static int flds(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FPUL = FRn;
+       return 0;
+}
+
+static int fneg(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn ^= (1 << (_FP_W_TYPE_SIZE - 1));
+       return 0;
+}
+
+static int fabs(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn &= ~(1 << (_FP_W_TYPE_SIZE - 1));
+       return 0;
+}
+
+static int fld0(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn = 0;
+       return 0;
+}
+
+static int fld1(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn = (_FP_EXPBIAS_S << (_FP_FRACBITS_S - 1));
+       return 0;
+}
+
+static int fnop_n(struct sh_fpu_soft_struct *fregs, int n)
+{
+       return -EINVAL;
+}
+
+/// Instruction decoders.
+
+static int id_fxfd(struct sh_fpu_soft_struct *, int);
+static int id_fnxd(struct sh_fpu_soft_struct *, struct pt_regs *, int, int);
+
+static int (*fnxd[])(struct sh_fpu_soft_struct *, int) = {
+       fsts, flds, ffloat, ftrc, fneg, fabs, fsqrt, fsrra,
+       fld0, fld1, fcnvsd, fcnvds, fnop_n, fnop_n, fipr, id_fxfd
+};
+
+static int (*fnmx[])(struct sh_fpu_soft_struct *, struct pt_regs *, int, int) = {
+       fadd, fsub, fmul, fdiv, fcmp_eq, fcmp_gt, fmov_idx_reg, fmov_reg_idx,
+       fmov_mem_reg, fmov_inc_reg, fmov_reg_mem, fmov_reg_dec,
+       fmov_reg_reg, id_fnxd, fmac, fnop_mn};
+
+static int id_fxfd(struct sh_fpu_soft_struct *fregs, int x)
+{
+       const int flag[] = { FPSCR_SZ, FPSCR_PR, FPSCR_FR, 0 };
+       switch (x & 3) {
+       case 3:
+               fxchg(fregs, flag[x >> 2]);
+               break;
+       case 1:
+               ftrv(fregs, x - 1);
+               break;
+       default:
+               fsca(fregs, x);
+       }
+       return 0;
+}
+
+static int
+id_fnxd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int x, int n)
+{
+       return (fnxd[x])(fregs, n);
+}
+
+static int
+id_fnmx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
+{
+       int n = (code >> 8) & 0xf, m = (code >> 4) & 0xf, x = code & 0xf;
+       return (fnmx[x])(fregs, regs, m, n);
+}
+
+static int
+id_sys(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
+{
+       int n = ((code >> 8) & 0xf);
+       unsigned long *reg = (code & 0x0010) ? &FPUL : &FPSCR;
+
+       switch (code & 0xf0ff) {
+       case 0x005a:
+       case 0x006a:
+               Rn = *reg;
+               break;
+       case 0x405a:
+       case 0x406a:
+               *reg = Rn;
+               break;
+       case 0x4052:
+       case 0x4062:
+               Rn -= 4;
+               WRITE(*reg, Rn);
+               break;
+       case 0x4056:
+       case 0x4066:
+               READ(*reg, Rn);
+               Rn += 4;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_regs *regs)
+{
+       if ((code & 0xf000) == 0xf000)
+               return id_fnmx(fregs, regs, code);
+       else
+               return id_sys(fregs, regs, code);
+}
+
+/**
+ *     denormal_to_double - Given denormalized float number,
+ *                          store double float
+ *
+ *     @fpu: Pointer to sh_fpu_hard structure
+ *     @n: Index to FP register
+ */
+static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n)
+{
+       unsigned long du, dl;
+       unsigned long x = fpu->fpul;
+       int exp = 1023 - 126;
+
+       if (x != 0 && (x & 0x7f800000) == 0) {
+               du = (x & 0x80000000);
+               while ((x & 0x00800000) == 0) {
+                       x <<= 1;
+                       exp--;
+               }
+               x &= 0x007fffff;
+               du |= (exp << 20) | (x >> 3);
+               dl = x << 29;
+
+               fpu->fp_regs[n] = du;
+               fpu->fp_regs[n+1] = dl;
+       }
+}
+
+/**
+ *     ieee_fpe_handler - Handle denormalized number exception
+ *
+ *     @regs: Pointer to register structure
+ *
+ *     Returns 1 when it's handled (should not cause exception).
+ */
+static int ieee_fpe_handler(struct pt_regs *regs)
+{
+       unsigned short insn = *(unsigned short *)regs->pc;
+       unsigned short finsn;
+       unsigned long nextpc;
+       int nib[4] = {
+               (insn >> 12) & 0xf,
+               (insn >> 8) & 0xf,
+               (insn >> 4) & 0xf,
+               insn & 0xf};
+
+       if (nib[0] == 0xb ||
+           (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+               regs->pr = regs->pc + 4;
+
+       if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+               nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+               if (regs->sr & 1)
+                       nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+               else
+                       nextpc = regs->pc + 4;
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+               if (regs->sr & 1)
+                       nextpc = regs->pc + 4;
+               else
+                       nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x4 && nib[3] == 0xb &&
+                (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+               nextpc = regs->regs[nib[1]];
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+                (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+               nextpc = regs->pc + 4 + regs->regs[nib[1]];
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (insn == 0x000b) { /* rts */
+               nextpc = regs->pr;
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else {
+               nextpc = regs->pc + 2;
+               finsn = insn;
+       }
+
+       if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+               struct task_struct *tsk = current;
+
+               if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+                       /* FPU error */
+                       denormal_to_double (&tsk->thread.fpu.hard,
+                                           (finsn >> 8) & 0xf);
+                       tsk->thread.fpu.hard.fpscr &=
+                               ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+                       set_tsk_thread_flag(tsk, TIF_USEDFPU);
+               } else {
+                       tsk->thread.trap_no = 11;
+                       tsk->thread.error_code = 0;
+                       force_sig(SIGFPE, tsk);
+               }
+
+               regs->pc = nextpc;
+               return 1;
+       }
+
+       return 0;
+}
+
+asmlinkage void do_fpu_error(unsigned long r4, unsigned long r5,
+                            unsigned long r6, unsigned long r7,
+                            struct pt_regs regs)
+{
+       struct task_struct *tsk = current;
+
+       if (ieee_fpe_handler (&regs))
+               return;
+
+       regs.pc += 2;
+       tsk->thread.trap_no = 11;
+       tsk->thread.error_code = 0;
+       force_sig(SIGFPE, tsk);
+}
+
+/**
+ * fpu_init - Initialize FPU registers
+ * @fpu: Pointer to software emulated FPU registers.
+ */
+static void fpu_init(struct sh_fpu_soft_struct *fpu)
+{
+       int i;
+
+       fpu->fpscr = FPSCR_INIT;
+       fpu->fpul = 0;
+
+       for (i = 0; i < 16; i++) {
+               fpu->fp_regs[i] = 0;
+               fpu->xfp_regs[i]= 0;
+       }
+}
+
+/**
+ * do_fpu_inst - Handle reserved instructions for FPU emulation
+ * @inst: instruction code.
+ * @regs: registers on stack.
+ */
+int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
+{
+       struct task_struct *tsk = current;
+       struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft);
+
+       if (!test_tsk_thread_flag(tsk, TIF_USEDFPU)) {
+               /* initialize once. */
+               fpu_init(fpu);
+               set_tsk_thread_flag(tsk, TIF_USEDFPU);
+       }
+
+       return fpu_emulate(inst, fpu, regs);
+}
diff --git a/arch/sh/math-emu/sfp-util.h b/arch/sh/math-emu/sfp-util.h
new file mode 100644 (file)
index 0000000..8ae1bd3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * These are copied from glibc/stdlib/longlong.h
+ */
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {                                                                  \
+    UWtype __x;                                                         \
+    __x = (al) + (bl);                                                  \
+    (sh) = (ah) + (bh) + (__x < (al));                                  \
+    (sl) = __x;                                                         \
+  } while (0)
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {                                                                  \
+    UWtype __x;                                                         \
+    __x = (al) - (bl);                                                  \
+    (sh) = (ah) - (bh) - (__x > (al));                                  \
+    (sl) = __x;                                                         \
+  } while (0)
+
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("dmulu.l %2,%3\n\tsts    macl,%1\n\tsts  mach,%0"   \
+       : "=r" ((u32)(w1)), "=r" ((u32)(w0))    \
+       :  "r" ((u32)(u)),   "r" ((u32)(v))     \
+       : "macl", "mach")
+
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do {                                                                 \
+    UWtype __d1, __d0, __q1, __q0;                                     \
+    UWtype __r1, __r0, __m;                                            \
+    __d1 = __ll_highpart (d);                                          \
+    __d0 = __ll_lowpart (d);                                           \
+                                                                       \
+    __r1 = (n1) % __d1;                                                        \
+    __q1 = (n1) / __d1;                                                        \
+    __m = (UWtype) __q1 * __d0;                                                \
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);                         \
+    if (__r1 < __m)                                                    \
+      {                                                                        \
+       __q1--, __r1 += (d);                                            \
+       if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+         if (__r1 < __m)                                               \
+           __q1--, __r1 += (d);                                        \
+      }                                                                        \
+    __r1 -= __m;                                                       \
+                                                                       \
+    __r0 = __r1 % __d1;                                                        \
+    __q0 = __r1 / __d1;                                                        \
+    __m = (UWtype) __q0 * __d0;                                                \
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);                          \
+    if (__r0 < __m)                                                    \
+      {                                                                        \
+       __q0--, __r0 += (d);                                            \
+       if (__r0 >= (d))                                                \
+         if (__r0 < __m)                                               \
+           __q0--, __r0 += (d);                                        \
+      }                                                                        \
+    __r0 -= __m;                                                       \
+                                                                       \
+    (q) = (UWtype) __q1 * __ll_B | __q0;                               \
+    (r) = __r0;                                                                \
+  } while (0)
+
+#define abort()        return 0
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+
index fb586b1cf8bb6b236d9b458110ef5a2740af3fb8..9dd606464d234347d4e0f94bec69b34f129e2a42 100644 (file)
@@ -20,7 +20,10 @@ config CPU_SH4
 config CPU_SH4A
        bool
        select CPU_SH4
-       select CPU_HAS_INTC2_IRQ
+
+config CPU_SH4AL_DSP
+       bool
+       select CPU_SH4A
 
 config CPU_SUBTYPE_ST40
        bool
@@ -48,6 +51,12 @@ config CPU_SUBTYPE_SH7705
        select CPU_SH3
        select CPU_HAS_PINT_IRQ
 
+config CPU_SUBTYPE_SH7706
+       bool "Support SH7706 processor"
+       select CPU_SH3
+       help
+         Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU.
+
 config CPU_SUBTYPE_SH7707
        bool "Support SH7707 processor"
        select CPU_SH3
@@ -69,6 +78,12 @@ config CPU_SUBTYPE_SH7709
        help
          Select SH7709 if you have a  80 Mhz SH-3 HD6417709 CPU.
 
+config CPU_SUBTYPE_SH7710
+       bool "Support SH7710 processor"
+       select CPU_SH3
+       help
+         Select SH7710 if you have a SH3-DSP SH7710 CPU.
+
 comment "SH-4 Processor Support"
 
 config CPU_SUBTYPE_SH7750
@@ -133,10 +148,6 @@ config CPU_SUBTYPE_ST40GX1
 
 comment "SH-4A Processor Support"
 
-config CPU_SUBTYPE_SH73180
-       bool "Support SH73180 processor"
-       select CPU_SH4A
-
 config CPU_SUBTYPE_SH7770
        bool "Support SH7770 processor"
        select CPU_SH4A
@@ -144,6 +155,17 @@ config CPU_SUBTYPE_SH7770
 config CPU_SUBTYPE_SH7780
        bool "Support SH7780 processor"
        select CPU_SH4A
+       select CPU_HAS_INTC2_IRQ
+
+comment "SH4AL-DSP Processor Support"
+
+config CPU_SUBTYPE_SH73180
+       bool "Support SH73180 processor"
+       select CPU_SH4AL_DSP
+
+config CPU_SUBTYPE_SH7343
+       bool "Support SH7343 processor"
+       select CPU_SH4AL_DSP
 
 endmenu
 
@@ -161,15 +183,59 @@ config MMU
          turning this off will boot the kernel on these machines with the
          MMU implicitly switched off.
 
+config PAGE_OFFSET
+       hex
+       default "0x80000000" if MMU
+       default "0x00000000"
+
+config MEMORY_START
+       hex "Physical memory start address"
+       default "0x08000000"
+       ---help---
+         Computers built with Hitachi SuperH processors always
+         map the ROM starting at address zero.  But the processor
+         does not specify the range that RAM takes.
+
+         The physical memory (RAM) start address will be automatically
+         set to 08000000. Other platforms, such as the Solution Engine
+         boards typically map RAM at 0C000000.
+
+         Tweak this only when porting to a new machine which does not
+         already have a defconfig. Changing it from the known correct
+         value on any of the known systems will only lead to disaster.
+
+config MEMORY_SIZE
+       hex "Physical memory size"
+       default "0x00400000"
+       help
+         This sets the default memory size assumed by your SH kernel. It can
+         be overridden as normal by the 'mem=' argument on the kernel command
+         line. If unsure, consult your board specifications or just leave it
+         as 0x00400000 which was the default value before this became
+         configurable.
+
 config 32BIT
        bool "Support 32-bit physical addressing through PMB"
-       depends on CPU_SH4A
+       depends on CPU_SH4A && MMU
        default y
        help
          If you say Y here, physical addressing will be extended to
          32-bits through the SH-4A PMB. If this is not set, legacy
          29-bit physical addressing will be used.
 
+config VSYSCALL
+       bool "Support vsyscall page"
+       depends on MMU
+       default y
+       help
+         This will enable support for the kernel mapping a vDSO page
+         in process space, and subsequently handing down the entry point
+         to the libc through the ELF auxiliary vector.
+
+         From the kernel side this is used for the signal trampoline.
+         For systems with an MMU that can afford to give up a page,
+         (the default value) say Y.
+
 choice
        prompt "HugeTLB page size"
        depends on HUGETLB_PAGE && CPU_SH4 && MMU
index 9489a1424644e7368a4ee9d956703987c14ca72d..3ffd7f68c0a206befbcc7ca3f1a940a73027dfb2 100644 (file)
@@ -6,20 +6,26 @@ obj-y                 := init.o extable.o consistent.o
 
 obj-$(CONFIG_CPU_SH2)  += cache-sh2.o
 obj-$(CONFIG_CPU_SH3)  += cache-sh3.o
-obj-$(CONFIG_CPU_SH4)  += cache-sh4.o pg-sh4.o
+obj-$(CONFIG_CPU_SH4)  += cache-sh4.o
 
 obj-$(CONFIG_DMA_PAGE_OPS)     += pg-dma.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
 
 mmu-y                  := fault-nommu.o tlb-nommu.o pg-nommu.o
-mmu-$(CONFIG_MMU)      := fault.o clear_page.o copy_page.o
+mmu-$(CONFIG_MMU)      := fault.o clear_page.o copy_page.o tlb-flush.o \
+                          ioremap.o
 
 obj-y                  += $(mmu-y)
 
+ifdef CONFIG_DEBUG_FS
+obj-$(CONFIG_CPU_SH4)          += cache-debugfs.o
+endif
+
 ifdef CONFIG_MMU
-obj-$(CONFIG_CPU_SH3)  += tlb-sh3.o
-obj-$(CONFIG_CPU_SH4)  += tlb-sh4.o ioremap.o
+obj-$(CONFIG_CPU_SH3)          += tlb-sh3.o
+obj-$(CONFIG_CPU_SH4)          += tlb-sh4.o pg-sh4.o
 obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
 endif
 
-obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
+obj-$(CONFIG_SH7705_CACHE_32KB)        += cache-sh7705.o
+obj-$(CONFIG_32BIT)            += pmb.o
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
new file mode 100644 (file)
index 0000000..a22d914
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * debugfs ops for the L1 cache
+ *
+ *  Copyright (C) 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/init.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+enum cache_type {
+       CACHE_TYPE_ICACHE,
+       CACHE_TYPE_DCACHE,
+       CACHE_TYPE_UNIFIED,
+};
+
+static int cache_seq_show(struct seq_file *file, void *iter)
+{
+       unsigned int cache_type = (unsigned int)file->private;
+       struct cache_info *cache;
+       unsigned int waysize, way, cache_size;
+       unsigned long ccr, base;
+       static unsigned long addrstart = 0;
+
+       /*
+        * Go uncached immediately so we don't skew the results any
+        * more than we already are..
+        */
+       jump_to_P2();
+
+       ccr = ctrl_inl(CCR);
+       if ((ccr & CCR_CACHE_ENABLE) == 0) {
+               back_to_P1();
+
+               seq_printf(file, "disabled\n");
+               return 0;
+       }
+
+       if (cache_type == CACHE_TYPE_DCACHE) {
+               base = CACHE_OC_ADDRESS_ARRAY;
+               cache = &cpu_data->dcache;
+       } else {
+               base = CACHE_IC_ADDRESS_ARRAY;
+               cache = &cpu_data->icache;
+       }
+
+       /*
+        * Due to the amount of data written out (depending on the cache size),
+        * we may be iterated over multiple times. In this case, keep track of
+        * the entry position in addrstart, and rewind it when we've hit the
+        * end of the cache.
+        *
+        * Likewise, the same code is used for multiple caches, so care must
+        * be taken for bouncing addrstart back and forth so the appropriate
+        * cache is hit.
+        */
+       cache_size = cache->ways * cache->sets * cache->linesz;
+       if (((addrstart & 0xff000000) != base) ||
+            (addrstart & 0x00ffffff) > cache_size)
+               addrstart = base;
+
+       waysize = cache->sets;
+
+       /*
+        * If the OC is already in RAM mode, we only have
+        * half of the entries to consider..
+        */
+       if ((ccr & CCR_CACHE_ORA) && cache_type == CACHE_TYPE_DCACHE)
+               waysize >>= 1;
+
+       waysize <<= cache->entry_shift;
+
+       for (way = 0; way < cache->ways; way++) {
+               unsigned long addr;
+               unsigned int line;
+
+               seq_printf(file, "-----------------------------------------\n");
+               seq_printf(file, "Way %d\n", way);
+               seq_printf(file, "-----------------------------------------\n");
+
+               for (addr = addrstart, line = 0;
+                    addr < addrstart + waysize;
+                    addr += cache->linesz, line++) {
+                       unsigned long data = ctrl_inl(addr);
+
+                       /* Check the V bit, ignore invalid cachelines */
+                       if ((data & 1) == 0)
+                               continue;
+
+                       /* U: Dirty, cache tag is 10 bits up */
+                       seq_printf(file, "%3d: %c 0x%lx\n",
+                                  line, data & 2 ? 'U' : ' ',
+                                  data & 0x1ffffc00);
+               }
+
+               addrstart += cache->way_incr;
+       }
+
+       back_to_P1();
+
+       return 0;
+}
+
+static int cache_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cache_seq_show, inode->u.generic_ip);
+}
+
+static struct file_operations cache_debugfs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cache_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init cache_debugfs_init(void)
+{
+       struct dentry *dcache_dentry, *icache_dentry;
+
+       dcache_dentry = debugfs_create_file("dcache", S_IRUSR, NULL,
+                                           (unsigned int *)CACHE_TYPE_DCACHE,
+                                           &cache_debugfs_fops);
+       if (IS_ERR(dcache_dentry))
+               return PTR_ERR(dcache_dentry);
+
+       icache_dentry = debugfs_create_file("icache", S_IRUSR, NULL,
+                                           (unsigned int *)CACHE_TYPE_ICACHE,
+                                           &cache_debugfs_fops);
+       if (IS_ERR(icache_dentry)) {
+               debugfs_remove(dcache_dentry);
+               return PTR_ERR(icache_dentry);
+       }
+
+       return 0;
+}
+module_init(cache_debugfs_init);
+
+MODULE_LICENSE("GPL v2");
index 524cea5b47f9ca7c93685a1d7bfa2746d49efc07..e48cc22724d9e8d7d215544b4904f977c2551418 100644 (file)
  * arch/sh/mm/cache-sh4.c
  *
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2001, 2002, 2003, 2004  Paul Mundt
+ * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * 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/init.h>
-#include <linux/mman.h>
 #include <linux/mm.h>
-#include <linux/threads.h>
 #include <asm/addrspace.h>
-#include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-extern void __flush_cache_4096_all(unsigned long start);
-static void __flush_cache_4096_all_ex(unsigned long start);
-extern void __flush_dcache_all(void);
-static void __flush_dcache_all_ex(void);
+/*
+ * The maximum number of pages we support up to when doing ranged dcache
+ * flushing. Anything exceeding this will simply flush the dcache in its
+ * entirety.
+ */
+#define MAX_DCACHE_PAGES       64      /* XXX: Tune for ways */
+
+static void __flush_dcache_segment_1way(unsigned long start,
+                                       unsigned long extent);
+static void __flush_dcache_segment_2way(unsigned long start,
+                                       unsigned long extent);
+static void __flush_dcache_segment_4way(unsigned long start,
+                                       unsigned long extent);
+
+static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+                              unsigned long exec_offset);
+
+/*
+ * This is initialised here to ensure that it is not placed in the BSS.  If
+ * that were to happen, note that cache_init gets called before the BSS is
+ * cleared, so this would get nulled out which would be hopeless.
+ */
+static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
+       (void (*)(unsigned long, unsigned long))0xdeadbeef;
+
+static void compute_alias(struct cache_info *c)
+{
+       c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
+       c->n_aliases = (c->alias_mask >> PAGE_SHIFT) + 1;
+}
+
+static void __init emit_cache_params(void)
+{
+       printk("PVR=%08x CVR=%08x PRR=%08x\n",
+               ctrl_inl(CCN_PVR),
+               ctrl_inl(CCN_CVR),
+               ctrl_inl(CCN_PRR));
+       printk("I-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+               cpu_data->icache.ways,
+               cpu_data->icache.sets,
+               cpu_data->icache.way_incr);
+       printk("I-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+               cpu_data->icache.entry_mask,
+               cpu_data->icache.alias_mask,
+               cpu_data->icache.n_aliases);
+       printk("D-cache : n_ways=%d n_sets=%d way_incr=%d\n",
+               cpu_data->dcache.ways,
+               cpu_data->dcache.sets,
+               cpu_data->dcache.way_incr);
+       printk("D-cache : entry_mask=0x%08x alias_mask=0x%08x n_aliases=%d\n",
+               cpu_data->dcache.entry_mask,
+               cpu_data->dcache.alias_mask,
+               cpu_data->dcache.n_aliases);
+
+       if (!__flush_dcache_segment_fn)
+               panic("unknown number of cache ways\n");
+}
 
 /*
  * SH-4 has virtually indexed and physically tagged cache.
  */
 
-struct semaphore p3map_sem[4];
+/* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */
+#define MAX_P3_SEMAPHORES 16
+
+struct semaphore p3map_sem[MAX_P3_SEMAPHORES];
 
 void __init p3_cache_init(void)
 {
-       if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE))
+       int i;
+
+       compute_alias(&cpu_data->icache);
+       compute_alias(&cpu_data->dcache);
+
+       switch (cpu_data->dcache.ways) {
+       case 1:
+               __flush_dcache_segment_fn = __flush_dcache_segment_1way;
+               break;
+       case 2:
+               __flush_dcache_segment_fn = __flush_dcache_segment_2way;
+               break;
+       case 4:
+               __flush_dcache_segment_fn = __flush_dcache_segment_4way;
+               break;
+       default:
+               __flush_dcache_segment_fn = NULL;
+               break;
+       }
+
+       emit_cache_params();
+
+       if (remap_area_pages(P3SEG, 0, PAGE_SIZE * 4, _PAGE_CACHABLE))
                panic("%s failed.", __FUNCTION__);
 
-       sema_init (&p3map_sem[0], 1);
-       sema_init (&p3map_sem[1], 1);
-       sema_init (&p3map_sem[2], 1);
-       sema_init (&p3map_sem[3], 1);
+       for (i = 0; i < cpu_data->dcache.n_aliases; i++)
+               sema_init(&p3map_sem[i], 1);
 }
 
 /*
@@ -89,7 +160,6 @@ void __flush_purge_region(void *start, int size)
        }
 }
 
-
 /*
  * No write back please
  */
@@ -108,40 +178,6 @@ void __flush_invalidate_region(void *start, int size)
        }
 }
 
-static void __flush_dcache_all_ex(void)
-{
-       unsigned long addr, end_addr, entry_offset;
-
-       end_addr = CACHE_OC_ADDRESS_ARRAY + (cpu_data->dcache.sets << cpu_data->dcache.entry_shift) * cpu_data->dcache.ways;
-       entry_offset = 1 << cpu_data->dcache.entry_shift;
-       for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; addr += entry_offset) {
-               ctrl_outl(0, addr);
-       }
-}
-
-static void __flush_cache_4096_all_ex(unsigned long start)
-{
-       unsigned long addr, entry_offset;
-       int i;
-
-       entry_offset = 1 << cpu_data->dcache.entry_shift;
-       for (i = 0; i < cpu_data->dcache.ways; i++, start += cpu_data->dcache.way_incr) {
-               for (addr = CACHE_OC_ADDRESS_ARRAY + start;
-                    addr < CACHE_OC_ADDRESS_ARRAY + 4096 + start;
-                    addr += entry_offset) {
-                       ctrl_outl(0, addr);
-               }
-       }
-}
-
-void flush_cache_4096_all(unsigned long start)
-{
-       if (cpu_data->dcache.ways == 1)
-               __flush_cache_4096_all(start);
-       else
-               __flush_cache_4096_all_ex(start);
-}
-
 /*
  * Write back the range of D-cache, and purge the I-cache.
  *
@@ -153,14 +189,14 @@ void flush_icache_range(unsigned long start, unsigned long end)
 }
 
 /*
- * Write back the D-cache and purge the I-cache for signal trampoline. 
+ * Write back the D-cache and purge the I-cache for signal trampoline.
  * .. which happens to be the same behavior as flush_icache_range().
  * So, we simply flush out a line.
  */
 void flush_cache_sigtramp(unsigned long addr)
 {
        unsigned long v, index;
-       unsigned long flags; 
+       unsigned long flags;
        int i;
 
        v = addr & ~(L1_CACHE_BYTES-1);
@@ -172,30 +208,33 @@ void flush_cache_sigtramp(unsigned long addr)
 
        local_irq_save(flags);
        jump_to_P2();
-       for(i = 0; i < cpu_data->icache.ways; i++, index += cpu_data->icache.way_incr)
+
+       for (i = 0; i < cpu_data->icache.ways;
+            i++, index += cpu_data->icache.way_incr)
                ctrl_outl(0, index);    /* Clear out Valid-bit */
+
        back_to_P1();
+       wmb();
        local_irq_restore(flags);
 }
 
 static inline void flush_cache_4096(unsigned long start,
                                    unsigned long phys)
 {
-       unsigned long flags; 
-       extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset);
+       unsigned long flags, exec_offset = 0;
 
        /*
-        * SH7751, SH7751R, and ST40 have no restriction to handle cache.
-        * (While SH7750 must do that at P2 area.)
+        * All types of SH-4 require PC to be in P2 to operate on the I-cache.
+        * Some types of SH-4 require PC to be in P2 to operate on the D-cache.
         */
-       if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG)
-          || start < CACHE_OC_ADDRESS_ARRAY) {
-               local_irq_save(flags);
-               __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0x20000000);
-               local_irq_restore(flags);
-       } else {
-               __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0);
-       }
+       if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
+           (start < CACHE_OC_ADDRESS_ARRAY))
+               exec_offset = 0x20000000;
+
+       local_irq_save(flags);
+       __flush_cache_4096(start | SH_CACHE_ASSOC,
+                          P1SEGADDR(phys), exec_offset);
+       local_irq_restore(flags);
 }
 
 /*
@@ -206,15 +245,19 @@ void flush_dcache_page(struct page *page)
 {
        if (test_bit(PG_mapped, &page->flags)) {
                unsigned long phys = PHYSADDR(page_address(page));
+               unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
+               int i, n;
 
                /* Loop all the D-cache */
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY,          phys);
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+               n = cpu_data->dcache.n_aliases;
+               for (i = 0; i < n; i++, addr += PAGE_SIZE)
+                       flush_cache_4096(addr, phys);
        }
+
+       wmb();
 }
 
+/* TODO: Selective icache invalidation through IC address array.. */
 static inline void flush_icache_all(void)
 {
        unsigned long flags, ccr;
@@ -227,34 +270,142 @@ static inline void flush_icache_all(void)
        ccr |= CCR_CACHE_ICI;
        ctrl_outl(ccr, CCR);
 
+       /*
+        * back_to_P1() will take care of the barrier for us, don't add
+        * another one!
+        */
+
        back_to_P1();
        local_irq_restore(flags);
 }
 
+void flush_dcache_all(void)
+{
+       (*__flush_dcache_segment_fn)(0UL, cpu_data->dcache.way_size);
+       wmb();
+}
+
 void flush_cache_all(void)
 {
-       if (cpu_data->dcache.ways == 1)
-               __flush_dcache_all();
-       else
-               __flush_dcache_all_ex();
+       flush_dcache_all();
        flush_icache_all();
 }
 
+static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
+                            unsigned long end)
+{
+       unsigned long d = 0, p = start & PAGE_MASK;
+       unsigned long alias_mask = cpu_data->dcache.alias_mask;
+       unsigned long n_aliases = cpu_data->dcache.n_aliases;
+       unsigned long select_bit;
+       unsigned long all_aliases_mask;
+       unsigned long addr_offset;
+       pgd_t *dir;
+       pmd_t *pmd;
+       pud_t *pud;
+       pte_t *pte;
+       int i;
+
+       dir = pgd_offset(mm, p);
+       pud = pud_offset(dir, p);
+       pmd = pmd_offset(pud, p);
+       end = PAGE_ALIGN(end);
+
+       all_aliases_mask = (1 << n_aliases) - 1;
+
+       do {
+               if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
+                       p &= PMD_MASK;
+                       p += PMD_SIZE;
+                       pmd++;
+
+                       continue;
+               }
+
+               pte = pte_offset_kernel(pmd, p);
+
+               do {
+                       unsigned long phys;
+                       pte_t entry = *pte;
+
+                       if (!(pte_val(entry) & _PAGE_PRESENT)) {
+                               pte++;
+                               p += PAGE_SIZE;
+                               continue;
+                       }
+
+                       phys = pte_val(entry) & PTE_PHYS_MASK;
+
+                       if ((p ^ phys) & alias_mask) {
+                               d |= 1 << ((p & alias_mask) >> PAGE_SHIFT);
+                               d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT);
+
+                               if (d == all_aliases_mask)
+                                       goto loop_exit;
+                       }
+
+                       pte++;
+                       p += PAGE_SIZE;
+               } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
+               pmd++;
+       } while (p < end);
+
+loop_exit:
+       addr_offset = 0;
+       select_bit = 1;
+
+       for (i = 0; i < n_aliases; i++) {
+               if (d & select_bit) {
+                       (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE);
+                       wmb();
+               }
+
+               select_bit <<= 1;
+               addr_offset += PAGE_SIZE;
+       }
+}
+
+/*
+ * Note : (RPC) since the caches are physically tagged, the only point
+ * of flush_cache_mm for SH-4 is to get rid of aliases from the
+ * D-cache.  The assumption elsewhere, e.g. flush_cache_range, is that
+ * lines can stay resident so long as the virtual address they were
+ * accessed with (hence cache set) is in accord with the physical
+ * address (i.e. tag).  It's no different here.  So I reckon we don't
+ * need to flush the I-cache, since aliases don't matter for that.  We
+ * should try that.
+ *
+ * Caller takes mm->mmap_sem.
+ */
 void flush_cache_mm(struct mm_struct *mm)
 {
-       /* Is there any good way? */
-       /* XXX: possibly call flush_cache_range for each vm area */
-       /* 
-        * FIXME: Really, the optimal solution here would be able to flush out
-        * individual lines created by the specified context, but this isn't
-        * feasible for a number of architectures (such as MIPS, and some
-        * SPARC) .. is this possible for SuperH?
-        *
-        * In the meantime, we'll just flush all of the caches.. this
-        * seems to be the simplest way to avoid at least a few wasted
-        * cache flushes. -Lethal
+       /*
+        * If cache is only 4k-per-way, there are never any 'aliases'.  Since
+        * the cache is physically tagged, the data can just be left in there.
         */
-       flush_cache_all();
+       if (cpu_data->dcache.n_aliases == 0)
+               return;
+
+       /*
+        * Don't bother groveling around the dcache for the VMA ranges
+        * if there are too many PTEs to make it worthwhile.
+        */
+       if (mm->nr_ptes >= MAX_DCACHE_PAGES)
+               flush_dcache_all();
+       else {
+               struct vm_area_struct *vma;
+
+               /*
+                * In this case there are reasonably sized ranges to flush,
+                * iterate through the VMA list and take care of any aliases.
+                */
+               for (vma = mm->mmap; vma; vma = vma->vm_next)
+                       __flush_cache_mm(mm, vma->vm_start, vma->vm_end);
+       }
+
+       /* Only touch the icache if one of the VMAs has VM_EXEC set. */
+       if (mm->exec_vm)
+               flush_icache_all();
 }
 
 /*
@@ -263,27 +414,40 @@ void flush_cache_mm(struct mm_struct *mm)
  * ADDR: Virtual Address (U0 address)
  * PFN: Physical page number
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
+                     unsigned long pfn)
 {
        unsigned long phys = pfn << PAGE_SHIFT;
+       unsigned int alias_mask;
+
+       alias_mask = cpu_data->dcache.alias_mask;
 
        /* We only need to flush D-cache when we have alias */
-       if ((address^phys) & CACHE_ALIAS) {
+       if ((address^phys) & alias_mask) {
                /* Loop 4K of the D-cache */
                flush_cache_4096(
-                       CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS),
+                       CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
                        phys);
                /* Loop another 4K of the D-cache */
                flush_cache_4096(
-                       CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS),
+                       CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
                        phys);
        }
 
-       if (vma->vm_flags & VM_EXEC)
-               /* Loop 4K (half) of the I-cache */
+       alias_mask = cpu_data->icache.alias_mask;
+       if (vma->vm_flags & VM_EXEC) {
+               /*
+                * Evict entries from the portion of the cache from which code
+                * may have been executed at this address (virtual).  There's
+                * no need to evict from the portion corresponding to the
+                * physical address as for the D-cache, because we know the
+                * kernel has never executed the code through its identity
+                * translation.
+                */
                flush_cache_4096(
-                       CACHE_IC_ADDRESS_ARRAY | (address & 0x1000),
+                       CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
                        phys);
+       }
 }
 
 /*
@@ -298,52 +462,31 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigne
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
                       unsigned long end)
 {
-       unsigned long p = start & PAGE_MASK;
-       pgd_t *dir;
-       pmd_t *pmd;
-       pte_t *pte;
-       pte_t entry;
-       unsigned long phys;
-       unsigned long d = 0;
-
-       dir = pgd_offset(vma->vm_mm, p);
-       pmd = pmd_offset(dir, p);
+       /*
+        * If cache is only 4k-per-way, there are never any 'aliases'.  Since
+        * the cache is physically tagged, the data can just be left in there.
+        */
+       if (cpu_data->dcache.n_aliases == 0)
+               return;
 
-       do {
-               if (pmd_none(*pmd) || pmd_bad(*pmd)) {
-                       p &= ~((1 << PMD_SHIFT) -1);
-                       p += (1 << PMD_SHIFT);
-                       pmd++;
-                       continue;
-               }
-               pte = pte_offset_kernel(pmd, p);
-               do {
-                       entry = *pte;
-                       if ((pte_val(entry) & _PAGE_PRESENT)) {
-                               phys = pte_val(entry)&PTE_PHYS_MASK;
-                               if ((p^phys) & CACHE_ALIAS) {
-                                       d |= 1 << ((p & CACHE_ALIAS)>>12); 
-                                       d |= 1 << ((phys & CACHE_ALIAS)>>12);
-                                       if (d == 0x0f)
-                                               goto loop_exit;
-                               }
-                       }
-                       pte++;
-                       p += PAGE_SIZE;
-               } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
-               pmd++;
-       } while (p < end);
- loop_exit:
-       if (d & 1)
-               flush_cache_4096_all(0);
-       if (d & 2)
-               flush_cache_4096_all(0x1000);
-       if (d & 4)
-               flush_cache_4096_all(0x2000);
-       if (d & 8)
-               flush_cache_4096_all(0x3000);
-       if (vma->vm_flags & VM_EXEC)
+       /*
+        * Don't bother with the lookup and alias check if we have a
+        * wide range to cover, just blow away the dcache in its
+        * entirety instead. -- PFM.
+        */
+       if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES)
+               flush_dcache_all();
+       else
+               __flush_cache_mm(vma->vm_mm, start, end);
+
+       if (vma->vm_flags & VM_EXEC) {
+               /*
+                * TODO: Is this required???  Need to look at how I-cache
+                * coherency is assured when new programs are loaded to see if
+                * this matters.
+                */
                flush_icache_all();
+       }
 }
 
 /*
@@ -357,5 +500,273 @@ void flush_icache_user_range(struct vm_area_struct *vma,
                             struct page *page, unsigned long addr, int len)
 {
        flush_cache_page(vma, addr, page_to_pfn(page));
+       mb();
+}
+
+/**
+ * __flush_cache_4096
+ *
+ * @addr:  address in memory mapped cache array
+ * @phys:  P1 address to flush (has to match tags if addr has 'A' bit
+ *         set i.e. associative write)
+ * @exec_offset: set to 0x20000000 if flush has to be executed from P2
+ *               region else 0x0
+ *
+ * The offset into the cache array implied by 'addr' selects the
+ * 'colour' of the virtual address range that will be flushed.  The
+ * operation (purge/write-back) is selected by the lower 2 bits of
+ * 'phys'.
+ */
+static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+                              unsigned long exec_offset)
+{
+       int way_count;
+       unsigned long base_addr = addr;
+       struct cache_info *dcache;
+       unsigned long way_incr;
+       unsigned long a, ea, p;
+       unsigned long temp_pc;
+
+       dcache = &cpu_data->dcache;
+       /* Write this way for better assembly. */
+       way_count = dcache->ways;
+       way_incr = dcache->way_incr;
+
+       /*
+        * Apply exec_offset (i.e. branch to P2 if required.).
+        *
+        * FIXME:
+        *
+        *      If I write "=r" for the (temp_pc), it puts this in r6 hence
+        *      trashing exec_offset before it's been added on - why?  Hence
+        *      "=&r" as a 'workaround'
+        */
+       asm volatile("mov.l 1f, %0\n\t"
+                    "add   %1, %0\n\t"
+                    "jmp   @%0\n\t"
+                    "nop\n\t"
+                    ".balign 4\n\t"
+                    "1:  .long 2f\n\t"
+                    "2:\n" : "=&r" (temp_pc) : "r" (exec_offset));
+
+       /*
+        * We know there will be >=1 iteration, so write as do-while to avoid
+        * pointless nead-of-loop check for 0 iterations.
+        */
+       do {
+               ea = base_addr + PAGE_SIZE;
+               a = base_addr;
+               p = phys;
+
+               do {
+                       *(volatile unsigned long *)a = p;
+                       /*
+                        * Next line: intentionally not p+32, saves an add, p
+                        * will do since only the cache tag bits need to
+                        * match.
+                        */
+                       *(volatile unsigned long *)(a+32) = p;
+                       a += 64;
+                       p += 64;
+               } while (a < ea);
+
+               base_addr += way_incr;
+       } while (--way_count != 0);
 }
 
+/*
+ * Break the 1, 2 and 4 way variants of this out into separate functions to
+ * avoid nearly all the overhead of having the conditional stuff in the function
+ * bodies (+ the 1 and 2 way cases avoid saving any registers too).
+ */
+static void __flush_dcache_segment_1way(unsigned long start,
+                                       unsigned long extent_per_way)
+{
+       unsigned long orig_sr, sr_with_bl;
+       unsigned long base_addr;
+       unsigned long way_incr, linesz, way_size;
+       struct cache_info *dcache;
+       register unsigned long a0, a0e;
+
+       asm volatile("stc sr, %0" : "=r" (orig_sr));
+       sr_with_bl = orig_sr | (1<<28);
+       base_addr = ((unsigned long)&empty_zero_page[0]);
+
+       /*
+        * The previous code aligned base_addr to 16k, i.e. the way_size of all
+        * existing SH-4 D-caches.  Whilst I don't see a need to have this
+        * aligned to any better than the cache line size (which it will be
+        * anyway by construction), let's align it to at least the way_size of
+        * any existing or conceivable SH-4 D-cache.  -- RPC
+        */
+       base_addr = ((base_addr >> 16) << 16);
+       base_addr |= start;
+
+       dcache = &cpu_data->dcache;
+       linesz = dcache->linesz;
+       way_incr = dcache->way_incr;
+       way_size = dcache->way_size;
+
+       a0 = base_addr;
+       a0e = base_addr + extent_per_way;
+       do {
+               asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               a0 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               a0 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               a0 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               asm volatile("ldc %0, sr" : : "r" (orig_sr));
+               a0 += linesz;
+       } while (a0 < a0e);
+}
+
+static void __flush_dcache_segment_2way(unsigned long start,
+                                       unsigned long extent_per_way)
+{
+       unsigned long orig_sr, sr_with_bl;
+       unsigned long base_addr;
+       unsigned long way_incr, linesz, way_size;
+       struct cache_info *dcache;
+       register unsigned long a0, a1, a0e;
+
+       asm volatile("stc sr, %0" : "=r" (orig_sr));
+       sr_with_bl = orig_sr | (1<<28);
+       base_addr = ((unsigned long)&empty_zero_page[0]);
+
+       /* See comment under 1-way above */
+       base_addr = ((base_addr >> 16) << 16);
+       base_addr |= start;
+
+       dcache = &cpu_data->dcache;
+       linesz = dcache->linesz;
+       way_incr = dcache->way_incr;
+       way_size = dcache->way_size;
+
+       a0 = base_addr;
+       a1 = a0 + way_incr;
+       a0e = base_addr + extent_per_way;
+       do {
+               asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               a0 += linesz;
+               a1 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               a0 += linesz;
+               a1 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               a0 += linesz;
+               a1 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               asm volatile("ldc %0, sr" : : "r" (orig_sr));
+               a0 += linesz;
+               a1 += linesz;
+       } while (a0 < a0e);
+}
+
+static void __flush_dcache_segment_4way(unsigned long start,
+                                       unsigned long extent_per_way)
+{
+       unsigned long orig_sr, sr_with_bl;
+       unsigned long base_addr;
+       unsigned long way_incr, linesz, way_size;
+       struct cache_info *dcache;
+       register unsigned long a0, a1, a2, a3, a0e;
+
+       asm volatile("stc sr, %0" : "=r" (orig_sr));
+       sr_with_bl = orig_sr | (1<<28);
+       base_addr = ((unsigned long)&empty_zero_page[0]);
+
+       /* See comment under 1-way above */
+       base_addr = ((base_addr >> 16) << 16);
+       base_addr |= start;
+
+       dcache = &cpu_data->dcache;
+       linesz = dcache->linesz;
+       way_incr = dcache->way_incr;
+       way_size = dcache->way_size;
+
+       a0 = base_addr;
+       a1 = a0 + way_incr;
+       a2 = a1 + way_incr;
+       a3 = a2 + way_incr;
+       a0e = base_addr + extent_per_way;
+       do {
+               asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               asm volatile("ldc %0, sr" : : "r" (orig_sr));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+       } while (a0 < a0e);
+}
index bf94eedb0a8e53e06fc0d0b88147aac636b80ad6..045abdf078f5bdc71a99c67f64da9c6cf76e6f4b 100644 (file)
@@ -9,7 +9,6 @@
  * for more details.
  *
  */
-
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-/* The 32KB cache on the SH7705 suffers from the same synonym problem
- * as SH4 CPUs */
-
-#define __pte_offset(address) \
-               ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
-               __pte_offset(address))
-
+/*
+ * The 32KB cache on the SH7705 suffers from the same synonym problem
+ * as SH4 CPUs
+ */
 static inline void cache_wback_all(void)
 {
        unsigned long ways, waysize, addrstart;
@@ -73,7 +68,6 @@ void flush_icache_range(unsigned long start, unsigned long end)
        __flush_wback_region((void *)start, end - start);
 }
 
-
 /*
  * Writeback&Invalidate the D-cache of the page
  */
@@ -128,7 +122,6 @@ static void __flush_dcache_page(unsigned long phys)
        local_irq_restore(flags);
 }
 
-
 /*
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
@@ -186,7 +179,8 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
  *
  * ADDRESS: Virtual Address (U0 address)
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
+                     unsigned long pfn)
 {
        __flush_dcache_page(pfn << PAGE_SHIFT);
 }
@@ -203,4 +197,3 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
        __flush_purge_region(page_address(page), PAGE_SIZE);
 }
-
index 08acead7b2a1b51070b1f2bf93259bfbd4b55523..7b96425ae270ec932b324465001f0d42eb15ff25 100644 (file)
@@ -193,102 +193,5 @@ ENTRY(__clear_user_page)
         nop
 .L4096:        .word   4096
 
-ENTRY(__flush_cache_4096)
-       mov.l   1f,r3
-       add     r6,r3
-       mov     r4,r0
-       mov     #64,r2
-       shll    r2
-       mov     #64,r6
-       jmp     @r3
-        mov    #96,r7
-       .align  2
-1:     .long   2f
-2:
-       .rept   32
-       mov.l   r5,@r0
-       mov.l   r5,@(32,r0)
-       mov.l   r5,@(r0,r6)
-       mov.l   r5,@(r0,r7)
-       add     r2,r5
-       add     r2,r0
-       .endr
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       rts
-        nop
-
-ENTRY(__flush_dcache_all)
-       mov.l   2f,r0
-       mov.l   3f,r4
-       and     r0,r4           ! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
-       stc     sr,r1           ! save SR
-       mov.l   4f,r2
-       or      r1,r2
-       mov     #32,r3
-       shll2   r3
-1:
-       ldc     r2,sr           ! set BL bit
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       ldc     r1,sr           ! restore SR
-       dt      r3
-       bf/s    1b
-        add    #32,r4
-
-       rts
-        nop
-       .align  2
-2:     .long   0xffffc000
-3:     .long   empty_zero_page
-4:     .long   0x10000000      ! BL bit
-
-/* __flush_cache_4096_all(unsigned long addr) */
-ENTRY(__flush_cache_4096_all)
-       mov.l   2f,r0
-       mov.l   3f,r2
-       and     r0,r2
-       or      r2,r4           ! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
-       stc     sr,r1           ! save SR
-       mov.l   4f,r2
-       or      r1,r2
-       mov     #32,r3
-1:
-       ldc     r2,sr           ! set BL bit
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       ldc     r1,sr           ! restore SR
-       dt      r3
-       bf/s    1b
-        add    #32,r4
-
-       rts
-        nop
-       .align  2
-2:     .long   0xffffc000
-3:     .long   empty_zero_page
-4:     .long   0x10000000      ! BL bit
 #endif
+
index ee73e30263af947b683e2833bb88e52806151f21..c81e6b67ad300e9e8b23c5adfc1658184d1ea59e 100644 (file)
@@ -9,6 +9,8 @@
  */
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/addrspace.h>
 #include <asm/io.h>
 
 void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
index 775f86cd3fe8f5930e85ef2b0b1337876f97d7eb..68663b8f99aec28619ea7cb92d16978c5a08be25 100644 (file)
@@ -1,33 +1,22 @@
-/* $Id: fault.c,v 1.14 2004/01/13 05:52:11 kkojima Exp $
+/*
+ * Page fault handler for SH with an MMU.
  *
- *  linux/arch/sh/mm/fault.c
  *  Copyright (C) 1999  Niibe Yutaka
  *  Copyright (C) 2003  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/fault.c:
  *   Copyright (C) 1995  Linus Torvalds
+ *
+ * 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/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/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
 #include <asm/kgdb.h>
 
 extern void die(const char *,struct pt_regs *,long);
@@ -80,7 +69,7 @@ good_area:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        } else {
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                        goto bad_area;
        }
 
@@ -160,7 +149,7 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
@@ -187,18 +176,30 @@ do_sigbus:
                goto no_context;
 }
 
+#ifdef CONFIG_SH_STORE_QUEUES
 /*
- * Called with interrupt disabled.
+ * This is a special case for the SH-4 store queues, as pages for this
+ * space still need to be faulted in before it's possible to flush the
+ * store queue cache for writeout to the remapped region.
  */
-asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
-                              unsigned long address)
+#define P3_ADDR_MAX            (P4SEG_STORE_QUE + 0x04000000)
+#else
+#define P3_ADDR_MAX            P4SEG
+#endif
+
+/*
+ * Called with interrupts disabled.
+ */
+asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
+                                        unsigned long writeaccess,
+                                        unsigned long address)
 {
-       unsigned long addrmax = P4SEG;
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
        pte_t entry;
-       struct mm_struct *mm;
+       struct mm_struct *mm = current->mm;
        spinlock_t *ptl;
        int ret = 1;
 
@@ -207,31 +208,37 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
                kgdb_bus_err_hook();
 #endif
 
-#ifdef CONFIG_SH_STORE_QUEUES
-       addrmax = P4SEG_STORE_QUE + 0x04000000;
-#endif
-
-       if (address >= P3SEG && address < addrmax) {
+       /*
+        * We don't take page faults for P1, P2, and parts of P4, these
+        * are always mapped, whether it be due to legacy behaviour in
+        * 29-bit mode, or due to PMB configuration in 32-bit mode.
+        */
+       if (address >= P3SEG && address < P3_ADDR_MAX) {
                pgd = pgd_offset_k(address);
                mm = NULL;
-       } else if (address >= TASK_SIZE)
-               return 1;
-       else if (!(mm = current->mm))
-               return 1;
-       else
+       } else {
+               if (unlikely(address >= TASK_SIZE || !mm))
+                       return 1;
+
                pgd = pgd_offset(mm, address);
+       }
 
-       pmd = pmd_offset(pgd, address);
+       pud = pud_offset(pgd, address);
+       if (pud_none_or_clear_bad(pud))
+               return 1;
+       pmd = pmd_offset(pud, address);
        if (pmd_none_or_clear_bad(pmd))
                return 1;
+
        if (mm)
                pte = pte_offset_map_lock(mm, pmd, address, &ptl);
        else
                pte = pte_offset_kernel(pmd, address);
 
        entry = *pte;
-       if (pte_none(entry) || pte_not_present(entry)
-           || (writeaccess && !pte_write(entry)))
+       if (unlikely(pte_none(entry) || pte_not_present(entry)))
+               goto unlock;
+       if (unlikely(writeaccess && !pte_write(entry)))
                goto unlock;
 
        if (writeaccess)
@@ -243,13 +250,7 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
         * ITLB is not affected by "ldtlb" instruction.
         * So, we need to flush the entry by ourselves.
         */
-
-       {
-               unsigned long flags;
-               local_irq_save(flags);
-               __flush_tlb_page(get_asid(), address&PAGE_MASK);
-               local_irq_restore(flags);
-       }
+       __flush_tlb_page(get_asid(), address & PAGE_MASK);
 #endif
 
        set_pte(pte, entry);
@@ -260,121 +261,3 @@ unlock:
                pte_unmap_unlock(pte, ptl);
        return ret;
 }
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-       if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
-               unsigned long flags;
-               unsigned long asid;
-               unsigned long saved_asid = MMU_NO_ASID;
-
-               asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
-               page &= PAGE_MASK;
-
-               local_irq_save(flags);
-               if (vma->vm_mm != current->mm) {
-                       saved_asid = get_asid();
-                       set_asid(asid);
-               }
-               __flush_tlb_page(asid, page);
-               if (saved_asid != MMU_NO_ASID)
-                       set_asid(saved_asid);
-               local_irq_restore(flags);
-       }
-}
-
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-                    unsigned long end)
-{
-       struct mm_struct *mm = vma->vm_mm;
-
-       if (mm->context != NO_CONTEXT) {
-               unsigned long flags;
-               int size;
-
-               local_irq_save(flags);
-               size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-               if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
-                       mm->context = NO_CONTEXT;
-                       if (mm == current->mm)
-                               activate_context(mm);
-               } else {
-                       unsigned long asid = mm->context&MMU_CONTEXT_ASID_MASK;
-                       unsigned long saved_asid = MMU_NO_ASID;
-
-                       start &= PAGE_MASK;
-                       end += (PAGE_SIZE - 1);
-                       end &= PAGE_MASK;
-                       if (mm != current->mm) {
-                               saved_asid = get_asid();
-                               set_asid(asid);
-                       }
-                       while (start < end) {
-                               __flush_tlb_page(asid, start);
-                               start += PAGE_SIZE;
-                       }
-                       if (saved_asid != MMU_NO_ASID)
-                               set_asid(saved_asid);
-               }
-               local_irq_restore(flags);
-       }
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-{
-       unsigned long flags;
-       int size;
-
-       local_irq_save(flags);
-       size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-       if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
-               flush_tlb_all();
-       } else {
-               unsigned long asid = init_mm.context&MMU_CONTEXT_ASID_MASK;
-               unsigned long saved_asid = get_asid();
-
-               start &= PAGE_MASK;
-               end += (PAGE_SIZE - 1);
-               end &= PAGE_MASK;
-               set_asid(asid);
-               while (start < end) {
-                       __flush_tlb_page(asid, start);
-                       start += PAGE_SIZE;
-               }
-               set_asid(saved_asid);
-       }
-       local_irq_restore(flags);
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-       /* Invalidate all TLB of this process. */
-       /* Instead of invalidating each TLB, we get new MMU context. */
-       if (mm->context != NO_CONTEXT) {
-               unsigned long flags;
-
-               local_irq_save(flags);
-               mm->context = NO_CONTEXT;
-               if (mm == current->mm)
-                       activate_context(mm);
-               local_irq_restore(flags);
-       }
-}
-
-void flush_tlb_all(void)
-{
-       unsigned long flags, status;
-
-       /*
-        * Flush all the TLB.
-        *
-        * Write to the MMU control register's bit:
-        *      TF-bit for SH-3, TI-bit for SH-4.
-        *      It's same position, bit #2.
-        */
-       local_irq_save(flags);
-       status = ctrl_inl(MMUCR);
-       status |= 0x04;         
-       ctrl_outl(status, MMUCR);
-       local_irq_restore(flags);
-}
index 2a85bc15a41238ce2d84e5bf891b63b589bd67ae..329059d6b54a79b2bdfb2eacdb2c4477f5936386 100644 (file)
 pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte = NULL;
 
        pgd = pgd_offset(mm, addr);
        if (pgd) {
-               pmd = pmd_alloc(mm, pgd, addr);
-               if (pmd)
-                       pte = pte_alloc_map(mm, pmd, addr);
+               pud = pud_alloc(mm, pgd, addr);
+               if (pud) {
+                       pmd = pmd_alloc(mm, pud, addr);
+                       if (pmd)
+                               pte = pte_alloc_map(mm, pmd, addr);
+               }
        }
+
        return pte;
 }
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte = NULL;
 
        pgd = pgd_offset(mm, addr);
        if (pgd) {
-               pmd = pmd_offset(pgd, addr);
-               if (pmd)
-                       pte = pte_offset_map(pmd, addr);
-       }
-       return pte;
-}
-
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-                    pte_t *ptep, pte_t entry)
-{
-       int i;
-
-       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-               set_pte_at(mm, addr, ptep, entry);
-               ptep++;
-               addr += PAGE_SIZE;
-               pte_val(entry) += PAGE_SIZE;
+               pud = pud_offset(pgd, addr);
+               if (pud) {
+                       pmd = pmd_offset(pud, addr);
+                       if (pmd)
+                               pte = pte_offset_map(pmd, addr);
+               }
        }
-}
-
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
-                             pte_t *ptep)
-{
-       pte_t entry;
-       int i;
-
-       entry = *ptep;
 
-       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-               pte_clear(mm, addr, ptep);
-               addr += PAGE_SIZE;
-               ptep++;
-       }
-
-       return entry;
+       return pte;
 }
 
 struct page *follow_huge_addr(struct mm_struct *mm,
index 8ea27ca4b700c1c080cfa3de90d9617f7a0b34a8..7154d1ce97859098b2c7647eee495c9fc13ef5d7 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
 #include <linux/pagemap.h>
-
+#include <linux/proc_fs.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -80,6 +80,7 @@ void show_mem(void)
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
 
@@ -89,7 +90,17 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
                return;
        }
 
-       pmd = pmd_offset(pgd, addr);
+       pud = pud_offset(pgd, addr);
+       if (pud_none(*pud)) {
+               pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
+               set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+               if (pmd != pmd_offset(pud, 0)) {
+                       pud_ERROR(*pud);
+                       return;
+               }
+       }
+
+       pmd = pmd_offset(pud, addr);
        if (pmd_none(*pmd)) {
                pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
                set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
@@ -212,6 +223,8 @@ void __init paging_init(void)
        free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 }
 
+static struct kcore_list kcore_mem, kcore_vmalloc;
+
 void __init mem_init(void)
 {
        extern unsigned long empty_zero_page[1024];
@@ -237,8 +250,13 @@ void __init mem_init(void)
         * Setup wrappers for copy/clear_page(), these will get overridden
         * later in the boot process if a better method is available.
         */
+#ifdef CONFIG_MMU
        copy_page = copy_page_slow;
        clear_page = clear_page_slow;
+#else
+       copy_page = copy_page_nommu;
+       clear_page = clear_page_nommu;
+#endif
 
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem_node(NODE_DATA(0));
@@ -254,7 +272,12 @@ void __init mem_init(void)
        datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
-       printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+       kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+       kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+                  VMALLOC_END - VMALLOC_START);
+
+       printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+              "%dk reserved, %dk data, %dk init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                max_mapnr << (PAGE_SHIFT-10),
                codesize >> 10,
@@ -263,6 +286,9 @@ void __init mem_init(void)
                initsize >> 10);
 
        p3_cache_init();
+
+       /* Initialize the vDSO */
+       vsyscall_init();
 }
 
 void free_initmem(void)
index 96fa4a999e2af1147b58c23ae4e04f8142a34b68..a9fe80cfc2338feaf2bbf2797b9988ac3982633a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -134,6 +135,20 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
        if (phys_addr >= 0xA0000 && last_addr < 0x100000)
                return (void __iomem *)phys_to_virt(phys_addr);
 
+       /*
+        * If we're on an SH7751 or SH7780 PCI controller, PCI memory is
+        * mapped at the end of the address space (typically 0xfd000000)
+        * in a non-translatable area, so mapping through page tables for
+        * this area is not only pointless, but also fundamentally
+        * broken. Just return the physical address instead.
+        *
+        * For boards that map a small PCI memory aperture somewhere in
+        * P1/P2 space, ioremap() will already do the right thing,
+        * and we'll never get this far.
+        */
+       if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
+               return (void __iomem *)phys_addr;
+
        /*
         * Don't allow anybody to remap normal RAM that we're using..
         */
@@ -192,7 +207,7 @@ void __iounmap(void __iomem *addr)
        unsigned long vaddr = (unsigned long __force)addr;
        struct vm_struct *p;
 
-       if (PXSEG(vaddr) < P3SEG)
+       if (PXSEG(vaddr) < P3SEG || is_pci_memaddr(vaddr))
                return;
 
 #ifdef CONFIG_32BIT
index 8f9165a4e333a32181c6cc4b678d2e4eacc42d7e..d15221beaa161ab555cb6b481268651d56570a4f 100644 (file)
 #include <linux/string.h>
 #include <asm/page.h>
 
-static void copy_page_nommu(void *to, void *from)
+void copy_page_nommu(void *to, void *from)
 {
        memcpy(to, from, PAGE_SIZE);
 }
 
-static void clear_page_nommu(void *to)
+void clear_page_nommu(void *to)
 {
        memset(to, 0, PAGE_SIZE);
 }
 
-static int __init pg_nommu_init(void)
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
 {
-       copy_page = copy_page_nommu;
-       clear_page = clear_page_nommu;
-
+       memcpy(to, from, n);
        return 0;
 }
 
-subsys_initcall(pg_nommu_init);
-
+__kernel_size_t __clear_user(void *to, __kernel_size_t n)
+{
+       memset(to, 0, n);
+       return 0;
+}
index c776b60fc25018ebfb0cf75e9976c603b65fdecd..07371ed7a31328e49fcf34377abc3b7b247cffb5 100644 (file)
@@ -2,7 +2,7 @@
  * arch/sh/mm/pg-sh4.c
  *
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2002  Paul Mundt
+ * Copyright (C) 2002 - 2005  Paul Mundt
  *
  * Released under the terms of the GNU GPL v2.0.
  */
@@ -23,6 +23,8 @@
 
 extern struct semaphore p3map_sem[];
 
+#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
+
 /*
  * clear_user_page
  * @to: P1 address
@@ -35,14 +37,15 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                clear_page(to);
        else {
-               pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
+               pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
                                           _PAGE_RW | _PAGE_CACHABLE |
-                                          _PAGE_DIRTY | _PAGE_ACCESSED | 
+                                          _PAGE_DIRTY | _PAGE_ACCESSED |
                                           _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
                unsigned long phys_addr = PHYSADDR(to);
                unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
-               pgd_t *dir = pgd_offset_k(p3_addr);
-               pmd_t *pmd = pmd_offset(dir, p3_addr);
+               pgd_t *pgd = pgd_offset_k(p3_addr);
+               pud_t *pud = pud_offset(pgd, p3_addr);
+               pmd_t *pmd = pmd_offset(pud, p3_addr);
                pte_t *pte = pte_offset_kernel(pmd, p3_addr);
                pte_t entry;
                unsigned long flags;
@@ -67,21 +70,22 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
  * @address: U0 address to be mapped
  * @page: page (virt_to_page(to))
  */
-void copy_user_page(void *to, void *from, unsigned long address, 
+void copy_user_page(void *to, void *from, unsigned long address,
                    struct page *page)
 {
        __set_bit(PG_mapped, &page->flags);
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                copy_page(to, from);
        else {
-               pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
+               pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
                                           _PAGE_RW | _PAGE_CACHABLE |
-                                          _PAGE_DIRTY | _PAGE_ACCESSED | 
+                                          _PAGE_DIRTY | _PAGE_ACCESSED |
                                           _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
                unsigned long phys_addr = PHYSADDR(to);
                unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
-               pgd_t *dir = pgd_offset_k(p3_addr);
-               pmd_t *pmd = pmd_offset(dir, p3_addr);
+               pgd_t *pgd = pgd_offset_k(p3_addr);
+               pud_t *pud = pud_offset(pgd, p3_addr);
+               pmd_t *pmd = pmd_offset(pud, p3_addr);
                pte_t *pte = pte_offset_kernel(pmd, p3_addr);
                pte_t entry;
                unsigned long flags;
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
new file mode 100644 (file)
index 0000000..92e7453
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * arch/sh/mm/pmb.c
+ *
+ * Privileged Space Mapping Buffer (PMB) Support.
+ *
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * P1/P2 Section mapping definitions from map32.h, which was:
+ *
+ *     Copyright 2003 (c) Lineo Solutions,Inc.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+
+#define NR_PMB_ENTRIES 16
+
+static kmem_cache_t *pmb_cache;
+static unsigned long pmb_map;
+
+static struct pmb_entry pmb_init_map[] = {
+       /* vpn         ppn         flags (ub/sz/c/wt) */
+
+       /* P1 Section Mappings */
+       { 0x80000000, 0x00000000, PMB_SZ_64M  | PMB_C, },
+       { 0x84000000, 0x04000000, PMB_SZ_64M  | PMB_C, },
+       { 0x88000000, 0x08000000, PMB_SZ_128M | PMB_C, },
+       { 0x90000000, 0x10000000, PMB_SZ_64M  | PMB_C, },
+       { 0x94000000, 0x14000000, PMB_SZ_64M  | PMB_C, },
+       { 0x98000000, 0x18000000, PMB_SZ_64M  | PMB_C, },
+
+       /* P2 Section Mappings */
+       { 0xa0000000, 0x00000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xa4000000, 0x04000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xa8000000, 0x08000000, PMB_UB | PMB_SZ_128M | PMB_WT, },
+       { 0xb0000000, 0x10000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xb4000000, 0x14000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xb8000000, 0x18000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+};
+
+static inline unsigned long mk_pmb_entry(unsigned int entry)
+{
+       return (entry & PMB_E_MASK) << PMB_E_SHIFT;
+}
+
+static inline unsigned long mk_pmb_addr(unsigned int entry)
+{
+       return mk_pmb_entry(entry) | PMB_ADDR;
+}
+
+static inline unsigned long mk_pmb_data(unsigned int entry)
+{
+       return mk_pmb_entry(entry) | PMB_DATA;
+}
+
+struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
+                           unsigned long flags)
+{
+       struct pmb_entry *pmbe;
+
+       pmbe = kmem_cache_alloc(pmb_cache, GFP_KERNEL);
+       if (!pmbe)
+               return ERR_PTR(-ENOMEM);
+
+       pmbe->vpn       = vpn;
+       pmbe->ppn       = ppn;
+       pmbe->flags     = flags;
+
+       return pmbe;
+}
+
+void pmb_free(struct pmb_entry *pmbe)
+{
+       kmem_cache_free(pmb_cache, pmbe);
+}
+
+/*
+ * Must be in P2 for __set_pmb_entry()
+ */
+int __set_pmb_entry(unsigned long vpn, unsigned long ppn,
+                   unsigned long flags, int *entry)
+{
+       unsigned int pos = *entry;
+
+       if (unlikely(pos == PMB_NO_ENTRY))
+               pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
+
+repeat:
+       if (unlikely(pos > NR_PMB_ENTRIES))
+               return -ENOSPC;
+
+       if (test_and_set_bit(pos, &pmb_map)) {
+               pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
+               goto repeat;
+       }
+
+       ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos));
+
+#ifdef CONFIG_SH_WRITETHROUGH
+       /*
+        * When we are in 32-bit address extended mode, CCR.CB becomes
+        * invalid, so care must be taken to manually adjust cacheable
+        * translations.
+        */
+       if (likely(flags & PMB_C))
+               flags |= PMB_WT;
+#endif
+
+       ctrl_outl(ppn | flags | PMB_V, mk_pmb_data(pos));
+
+       *entry = pos;
+
+       return 0;
+}
+
+int set_pmb_entry(struct pmb_entry *pmbe)
+{
+       int ret;
+
+       jump_to_P2();
+       ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry);
+       back_to_P1();
+
+       return ret;
+}
+
+void clear_pmb_entry(struct pmb_entry *pmbe)
+{
+       unsigned int entry = pmbe->entry;
+       unsigned long addr;
+
+       /*
+        * Don't allow clearing of wired init entries, P1 or P2 access
+        * without a corresponding mapping in the PMB will lead to reset
+        * by the TLB.
+        */
+       if (unlikely(entry < ARRAY_SIZE(pmb_init_map) ||
+                    entry >= NR_PMB_ENTRIES))
+               return;
+
+       jump_to_P2();
+
+       /* Clear V-bit */
+       addr = mk_pmb_addr(entry);
+       ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
+
+       addr = mk_pmb_data(entry);
+       ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
+
+       back_to_P1();
+
+       clear_bit(entry, &pmb_map);
+}
+
+static DEFINE_SPINLOCK(pmb_list_lock);
+static struct pmb_entry *pmb_list;
+
+static inline void pmb_list_add(struct pmb_entry *pmbe)
+{
+       struct pmb_entry **p, *tmp;
+
+       p = &pmb_list;
+       while ((tmp = *p) != NULL)
+               p = &tmp->next;
+
+       pmbe->next = tmp;
+       *p = pmbe;
+}
+
+static inline void pmb_list_del(struct pmb_entry *pmbe)
+{
+       struct pmb_entry **p, *tmp;
+
+       for (p = &pmb_list; (tmp = *p); p = &tmp->next)
+               if (tmp == pmbe) {
+                       *p = tmp->next;
+                       return;
+               }
+}
+
+static struct {
+       unsigned long size;
+       int flag;
+} pmb_sizes[] = {
+       { .size = 0x20000000, .flag = PMB_SZ_512M, },
+       { .size = 0x08000000, .flag = PMB_SZ_128M, },
+       { .size = 0x04000000, .flag = PMB_SZ_64M,  },
+       { .size = 0x01000000, .flag = PMB_SZ_16M,  },
+};
+
+long pmb_remap(unsigned long vaddr, unsigned long phys,
+              unsigned long size, unsigned long flags)
+{
+       struct pmb_entry *pmbp;
+       unsigned long wanted;
+       int pmb_flags, i;
+
+       /* Convert typical pgprot value to the PMB equivalent */
+       if (flags & _PAGE_CACHABLE) {
+               if (flags & _PAGE_WT)
+                       pmb_flags = PMB_WT;
+               else
+                       pmb_flags = PMB_C;
+       } else
+               pmb_flags = PMB_WT | PMB_UB;
+
+       pmbp = NULL;
+       wanted = size;
+
+again:
+       for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
+               struct pmb_entry *pmbe;
+               int ret;
+
+               if (size < pmb_sizes[i].size)
+                       continue;
+
+               pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag);
+               if (IS_ERR(pmbe))
+                       return PTR_ERR(pmbe);
+
+               ret = set_pmb_entry(pmbe);
+               if (ret != 0) {
+                       pmb_free(pmbe);
+                       return -EBUSY;
+               }
+
+               phys    += pmb_sizes[i].size;
+               vaddr   += pmb_sizes[i].size;
+               size    -= pmb_sizes[i].size;
+
+               /*
+                * Link adjacent entries that span multiple PMB entries
+                * for easier tear-down.
+                */
+               if (likely(pmbp))
+                       pmbp->link = pmbe;
+
+               pmbp = pmbe;
+       }
+
+       if (size >= 0x1000000)
+               goto again;
+
+       return wanted - size;
+}
+
+void pmb_unmap(unsigned long addr)
+{
+       struct pmb_entry **p, *pmbe;
+
+       for (p = &pmb_list; (pmbe = *p); p = &pmbe->next)
+               if (pmbe->vpn == addr)
+                       break;
+
+       if (unlikely(!pmbe))
+               return;
+
+       WARN_ON(!test_bit(pmbe->entry, &pmb_map));
+
+       do {
+               struct pmb_entry *pmblink = pmbe;
+
+               clear_pmb_entry(pmbe);
+               pmbe = pmblink->link;
+
+               pmb_free(pmblink);
+       } while (pmbe);
+}
+
+static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+{
+       struct pmb_entry *pmbe = pmb;
+
+       memset(pmb, 0, sizeof(struct pmb_entry));
+
+       spin_lock_irq(&pmb_list_lock);
+
+       pmbe->entry = PMB_NO_ENTRY;
+       pmb_list_add(pmbe);
+
+       spin_unlock_irq(&pmb_list_lock);
+}
+
+static void pmb_cache_dtor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+{
+       spin_lock_irq(&pmb_list_lock);
+       pmb_list_del(pmb);
+       spin_unlock_irq(&pmb_list_lock);
+}
+
+static int __init pmb_init(void)
+{
+       unsigned int nr_entries = ARRAY_SIZE(pmb_init_map);
+       unsigned int entry;
+
+       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);
+
+       jump_to_P2();
+
+       /*
+        * Ordering is important, P2 must be mapped in the PMB before we
+        * can set PMB.SE, and P1 must be mapped before we jump back to
+        * P1 space.
+        */
+       for (entry = 0; entry < nr_entries; entry++) {
+               struct pmb_entry *pmbe = pmb_init_map + entry;
+
+               __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &entry);
+       }
+
+       ctrl_outl(0, PMB_IRMCR);
+
+       /* PMB.SE and UB[7] */
+       ctrl_outl((1 << 31) | (1 << 7), PMB_PASCR);
+
+       back_to_P1();
+
+       return 0;
+}
+arch_initcall(pmb_init);
+
+static int pmb_seq_show(struct seq_file *file, void *iter)
+{
+       int i;
+
+       seq_printf(file, "V: Valid, C: Cacheable, WT: Write-Through\n"
+                        "CB: Copy-Back, B: Buffered, UB: Unbuffered\n");
+       seq_printf(file, "ety   vpn  ppn  size   flags\n");
+
+       for (i = 0; i < NR_PMB_ENTRIES; i++) {
+               unsigned long addr, data;
+               unsigned int size;
+               char *sz_str = NULL;
+
+               addr = ctrl_inl(mk_pmb_addr(i));
+               data = ctrl_inl(mk_pmb_data(i));
+
+               size = data & PMB_SZ_MASK;
+               sz_str = (size == PMB_SZ_16M)  ? " 16MB":
+                        (size == PMB_SZ_64M)  ? " 64MB":
+                        (size == PMB_SZ_128M) ? "128MB":
+                                                "512MB";
+
+               /* 02: V 0x88 0x08 128MB C CB  B */
+               seq_printf(file, "%02d: %c 0x%02lx 0x%02lx %s %c %s %s\n",
+                          i, ((addr & PMB_V) && (data & PMB_V)) ? 'V' : ' ',
+                          (addr >> 24) & 0xff, (data >> 24) & 0xff,
+                          sz_str, (data & PMB_C) ? 'C' : ' ',
+                          (data & PMB_WT) ? "WT" : "CB",
+                          (data & PMB_UB) ? "UB" : " B");
+       }
+
+       return 0;
+}
+
+static int pmb_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pmb_seq_show, NULL);
+}
+
+static struct file_operations pmb_debugfs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pmb_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init pmb_debugfs_init(void)
+{
+       struct dentry *dentry;
+
+       dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
+                                    NULL, NULL, &pmb_debugfs_fops);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+
+       return 0;
+}
+postcore_initcall(pmb_debugfs_init);
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c
new file mode 100644 (file)
index 0000000..73ec7f6
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * TLB flushing operations for SH with an MMU.
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *  Copyright (C) 2003  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/mm.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+       if (vma->vm_mm && vma->vm_mm->context.id != NO_CONTEXT) {
+               unsigned long flags;
+               unsigned long asid;
+               unsigned long saved_asid = MMU_NO_ASID;
+
+               asid = vma->vm_mm->context.id & MMU_CONTEXT_ASID_MASK;
+               page &= PAGE_MASK;
+
+               local_irq_save(flags);
+               if (vma->vm_mm != current->mm) {
+                       saved_asid = get_asid();
+                       set_asid(asid);
+               }
+               __flush_tlb_page(asid, page);
+               if (saved_asid != MMU_NO_ASID)
+                       set_asid(saved_asid);
+               local_irq_restore(flags);
+       }
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+                    unsigned long end)
+{
+       struct mm_struct *mm = vma->vm_mm;
+
+       if (mm->context.id != NO_CONTEXT) {
+               unsigned long flags;
+               int size;
+
+               local_irq_save(flags);
+               size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+               if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+                       mm->context.id = NO_CONTEXT;
+                       if (mm == current->mm)
+                               activate_context(mm);
+               } else {
+                       unsigned long asid;
+                       unsigned long saved_asid = MMU_NO_ASID;
+
+                       asid = mm->context.id & MMU_CONTEXT_ASID_MASK;
+                       start &= PAGE_MASK;
+                       end += (PAGE_SIZE - 1);
+                       end &= PAGE_MASK;
+                       if (mm != current->mm) {
+                               saved_asid = get_asid();
+                               set_asid(asid);
+                       }
+                       while (start < end) {
+                               __flush_tlb_page(asid, start);
+                               start += PAGE_SIZE;
+                       }
+                       if (saved_asid != MMU_NO_ASID)
+                               set_asid(saved_asid);
+               }
+               local_irq_restore(flags);
+       }
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       unsigned long flags;
+       int size;
+
+       local_irq_save(flags);
+       size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+       if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
+               flush_tlb_all();
+       } else {
+               unsigned long asid;
+               unsigned long saved_asid = get_asid();
+
+               asid = init_mm.context.id & MMU_CONTEXT_ASID_MASK;
+               start &= PAGE_MASK;
+               end += (PAGE_SIZE - 1);
+               end &= PAGE_MASK;
+               set_asid(asid);
+               while (start < end) {
+                       __flush_tlb_page(asid, start);
+                       start += PAGE_SIZE;
+               }
+               set_asid(saved_asid);
+       }
+       local_irq_restore(flags);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       /* Invalidate all TLB of this process. */
+       /* Instead of invalidating each TLB, we get new MMU context. */
+       if (mm->context.id != NO_CONTEXT) {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               mm->context.id = NO_CONTEXT;
+               if (mm == current->mm)
+                       activate_context(mm);
+               local_irq_restore(flags);
+       }
+}
+
+void flush_tlb_all(void)
+{
+       unsigned long flags, status;
+
+       /*
+        * Flush all the TLB.
+        *
+        * Write to the MMU control register's bit:
+        *      TF-bit for SH-3, TI-bit for SH-4.
+        *      It's same position, bit #2.
+        */
+       local_irq_save(flags);
+       status = ctrl_inl(MMUCR);
+       status |= 0x04;
+       ctrl_outl(status, MMUCR);
+       ctrl_barrier();
+       local_irq_restore(flags);
+}
index 115b1b6be40b45c30c71b1413b4b6be8c1ef7cc7..812b2d567de2f6e57a7519864923a1bbd69bbfb9 100644 (file)
@@ -36,7 +36,6 @@ void update_mmu_cache(struct vm_area_struct * vma,
        unsigned long vpn;
        struct page *page;
        unsigned long pfn;
-       unsigned long ptea;
 
        /* Ptrace may call this routine. */
        if (vma && current->active_mm != vma->vm_mm)
@@ -59,10 +58,11 @@ void update_mmu_cache(struct vm_area_struct * vma,
        ctrl_outl(vpn, MMU_PTEH);
 
        pteval = pte_val(pte);
+
        /* Set PTEA register */
-       /* TODO: make this look less hacky */
-       ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
-       ctrl_outl(ptea, MMU_PTEA);
+       if (cpu_data->flags & CPU_HAS_PTEA)
+               /* TODO: make this look less hacky */
+               ctrl_outl(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA);
 
        /* Set PTEL register */
        pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
index 686738d4aa3c295fe511878ec82cb99f69b400c8..1f25d9bb7538a511d3d9ff8d9d4dc88658d84b97 100644 (file)
@@ -7,7 +7,11 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                timer_int.o )
 
 profdrvr-y                             := op_model_null.o
+
+# SH7750-style performance counters exist across 7750/7750S and 7091.
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750S) := op_model_sh7750.o
 profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750)  := op_model_sh7750.o
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7091)  := op_model_sh7750.o
 
 oprofile-y                             := $(DRIVER_OBJS) $(profdrvr-y)
 
index 182fe90925771cccbda3d51fa9d4160dd95a86f3..ac57638977ee639f332b541a9b2624a233a81d6d 100644 (file)
@@ -8,16 +8,15 @@
 SE                     SH_SOLUTION_ENGINE
 7751SE                 SH_7751_SOLUTION_ENGINE         
 7300SE                 SH_7300_SOLUTION_ENGINE
+7343SE                 SH_7343_SOLUTION_ENGINE
 73180SE                        SH_73180_SOLUTION_ENGINE
 7751SYSTEMH            SH_7751_SYSTEMH
 HP6XX                  SH_HP6XX
 HD64461                        HD64461
 HD64465                        HD64465
-SH2000                 SH_SH2000
 SATURN                 SH_SATURN
 DREAMCAST              SH_DREAMCAST
 BIGSUR                 SH_BIGSUR
-ADX                    SH_ADX
 MPC1211                        SH_MPC1211
 SNAPGEAR               SH_SECUREEDGE5410
 HS7751RVOIP            SH_HS7751RVOIP
@@ -25,4 +24,9 @@ RTS7751R2D            SH_RTS7751R2D
 EDOSK7705              SH_EDOSK7705
 SH4202_MICRODEV                SH_SH4202_MICRODEV
 SH03                   SH_SH03
-
+LANDISK                        SH_LANDISK
+R7780RP                        SH_R7780RP
+R7780MP                        SH_R7780MP
+TITAN                  SH_TITAN
+SHMIN                  SH_SHMIN
+7710VOIPGW             SH_7710VOIPGW
index b8162e59030e447c6fcc1d12cdb0c59e15ce34e6..9c4a38a8698c608e353a04831fc1761fcd99e526 100644 (file)
 
 #define TICK_SIZE (tick_nsec / 1000)
 
-extern unsigned long wall_jiffies;
-
 static unsigned long tmu_base, rtc_base;
 unsigned long cprc_base;
 
@@ -194,13 +192,6 @@ void do_gettimeofday(struct timeval *tv)
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = usecs_since_tick();
-               {
-                       unsigned long lost = jiffies - wall_jiffies;
-
-                       if (lost)
-                               usec += lost * (1000000 / HZ);
-               }
-
                sec = xtime.tv_sec;
                usec += xtime.tv_nsec / 1000;
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -229,8 +220,7 @@ int do_settimeofday(struct timespec *tv)
         * wall time.  Discover what correction gettimeofday() would have
         * made, and then undo it!
         */
-       nsec -= 1000 * (usecs_since_tick() +
-                               (jiffies - wall_jiffies) * (1000000 / HZ));
+       nsec -= 1000 * usecs_since_tick();
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -298,7 +288,7 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
        asm ("getcon cr62, %0" : "=r" (current_ctc));
        ctc_last_interrupt = (unsigned long) current_ctc;
 
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
index f08d0eaf6497d34c716d8f0c5ee4baf2aa4eb27c..8e2f6c28b7390fc712a8d07f8e8e567fbd7b6853 100644 (file)
@@ -277,7 +277,7 @@ bad_area:
                        show_regs(regs);
 #endif
                }
-               if (tsk->pid == 1) {
+               if (is_init(tsk)) {
                        panic("INIT had user mode bad_area\n");
                }
                tsk->thread.address = address;
@@ -319,14 +319,14 @@ no_context:
  * us unable to handle the page fault gracefully.
  */
 out_of_memory:
-       if (current->pid == 1) {
+       if (is_init(current)) {
                panic("INIT out of memory\n");
                yield();
                goto survive;
        }
        printk("fault:Out of memory\n");
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index bfd31aac2df3b2c7992f082fd08b9f5ba78da4c2..edb6cc665f561652a7c3ef487166ad034c31f0df 100644 (file)
@@ -712,7 +712,7 @@ static irqreturn_t pcic_timer_handler (int irq, void *h, struct pt_regs *regs)
 {
        write_seqlock(&xtime_lock);     /* Dummy, to show that we remember */
        pcic_clear_clock_irq();
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -765,8 +765,6 @@ static __inline__ unsigned long do_gettimeoffset(void)
        return count;
 }
 
-extern unsigned long wall_jiffies;
-
 static void pci_do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
@@ -775,26 +773,17 @@ static void pci_do_gettimeofday(struct timeval *tv)
        unsigned long max_ntp_tick = tick_usec - tickadj;
 
        do {
-               unsigned long lost;
-
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = do_gettimeoffset();
-               lost = jiffies - wall_jiffies;
 
                /*
                 * If time_adjust is negative then NTP is slowing the clock
                 * so make sure not to go into next possible interval.
                 * Better to lose some accuracy than have time go backwards..
                 */
-               if (unlikely(time_adjust < 0)) {
+               if (unlikely(time_adjust < 0))
                        usec = min(usec, max_ntp_tick);
 
-                       if (lost)
-                               usec += lost * max_ntp_tick;
-               }
-               else if (unlikely(lost))
-                       usec += lost * tick_usec;
-
                sec = xtime.tv_sec;
                usec += (xtime.tv_nsec / 1000);
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -819,8 +808,7 @@ static int pci_do_settimeofday(struct timespec *tv)
         * wall time.  Discover what correction gettimeofday() would have
         * made, and then undo it!
         */
-       tv->tv_nsec -= 1000 * (do_gettimeoffset() + 
-                               (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ));
+       tv->tv_nsec -= 1000 * do_gettimeoffset();
        while (tv->tv_nsec < 0) {
                tv->tv_nsec += NSEC_PER_SEC;
                tv->tv_sec--;
index 845081b0126760ac14e8b7c2735ad089bee991f2..e10dc831944d45c27f129038b1103306c15b567d 100644 (file)
@@ -43,8 +43,6 @@
 #include <asm/pcic.h>
 #include <asm/of_device.h>
 
-extern unsigned long wall_jiffies;
-
 DEFINE_SPINLOCK(rtc_lock);
 enum sparc_clock_type sp_clock_typ;
 DEFINE_SPINLOCK(mostek_lock);
@@ -128,7 +126,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 #endif
        clear_clock_irq();
 
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -449,7 +447,7 @@ unsigned long long sched_clock(void)
 
 /* Ok, my cute asm atomicity trick doesn't work anymore.
  * There are just too many variables that need to be protected
- * now (both members of xtime, wall_jiffies, et al.)
+ * now (both members of xtime, et al.)
  */
 void do_gettimeofday(struct timeval *tv)
 {
@@ -459,26 +457,17 @@ void do_gettimeofday(struct timeval *tv)
        unsigned long max_ntp_tick = tick_usec - tickadj;
 
        do {
-               unsigned long lost;
-
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
                usec = do_gettimeoffset();
-               lost = jiffies - wall_jiffies;
 
                /*
                 * If time_adjust is negative then NTP is slowing the clock
                 * so make sure not to go into next possible interval.
                 * Better to lose some accuracy than have time go backwards..
                 */
-               if (unlikely(time_adjust < 0)) {
+               if (unlikely(time_adjust < 0))
                        usec = min(usec, max_ntp_tick);
 
-                       if (lost)
-                               usec += lost * max_ntp_tick;
-               }
-               else if (unlikely(lost))
-                       usec += lost * tick_usec;
-
                sec = xtime.tv_sec;
                usec += (xtime.tv_nsec / 1000);
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
@@ -521,8 +510,7 @@ static int sbus_do_settimeofday(struct timespec *tv)
         * wall time.  Discover what correction gettimeofday() would have
         * made, and then undo it!
         */
-       nsec -= 1000 * (do_gettimeoffset() +
-                       (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ));
+       nsec -= 1000 * do_gettimeoffset();
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
index 577505b692ae0643b046223187d071de9106f618..ef095b6c43b157dc7ad076b641893b59e25775de 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/ptrace.h>
 #include <asm/asmmacro.h>
 #include <asm/page.h>
+#include <asm/thread_info.h>
 
 /* Work around cpp -rob */
 #define ALLOC #alloc
@@ -366,6 +367,9 @@ fixupretl:
        blu     1f
         cmp    %o1, %g1
        bgeu    1f
+        ld     [%g6 + TI_PREEMPT], %g1
+       cmp     %g1, 0
+       bne     1f
         nop
        save    %sp, -64, %sp
        mov     %i0, %o0
index 51cf6027b7014634ee8838d02288845933e6c5cb..0fbdaa5daa8cfbdd6f761481a93d3b1f7b95ff06 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18
-# Sat Sep 23 18:32:19 2006
+# Tue Sep 26 23:09:35 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -141,6 +141,7 @@ CONFIG_SUN_AUXIO=y
 CONFIG_SUN_IO=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 CONFIG_SUN_OPENPROMFS=m
 CONFIG_SPARC32_COMPAT=y
@@ -194,21 +195,9 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
-CONFIG_TCP_CONG_ADVANCED=y
-
-#
-# TCP congestion control
-#
-CONFIG_TCP_CONG_BIC=y
-CONFIG_TCP_CONG_CUBIC=m
-CONFIG_TCP_CONG_WESTWOOD=m
-CONFIG_TCP_CONG_HTCP=m
-CONFIG_TCP_CONG_HSTCP=m
-CONFIG_TCP_CONG_HYBLA=m
-CONFIG_TCP_CONG_VEGAS=m
-CONFIG_TCP_CONG_SCALABLE=m
-CONFIG_TCP_CONG_LP=m
-CONFIG_TCP_CONG_VENO=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -247,6 +236,7 @@ CONFIG_IP_DCCP_TFRC_LIB=m
 # DCCP Kernel Hacking
 #
 # CONFIG_IP_DCCP_DEBUG is not set
+# CONFIG_NET_DCCPPROBE is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -401,6 +391,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -422,12 +413,13 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -440,16 +432,18 @@ CONFIG_ISCSI_TCP=m
 # 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_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN 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
@@ -461,6 +455,11 @@ CONFIG_ISCSI_TCP=m
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SUNESP is not set
 
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
 #
 # Multi-device support (RAID and LVM)
 #
@@ -575,6 +574,7 @@ CONFIG_E1000_NAPI=y
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1006,6 +1006,7 @@ CONFIG_SND_ALI5451=m
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
 
 #
 # USB devices
@@ -1353,6 +1354,7 @@ CONFIG_KPROBES=y
 # Kernel hacking
 #
 CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
index c88ae23ce81230709d491888bdfb6542d7c24705..69444f266e2d5b88526b7019f3a0529de80edd9d 100644 (file)
@@ -1016,7 +1016,7 @@ struct __sysctl_args32 {
 
 asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
-#ifndef CONFIG_SYSCTL
+#ifndef CONFIG_SYSCTL_SYSCALL
        return -ENOSYS;
 #else
        struct __sysctl_args32 tmp;
index b0b4feeec09826f84a70e29d9ad8b77d6347ab7c..00f6fc4aaaffc4182c0dec5af21f127d7e353493 100644 (file)
@@ -53,8 +53,6 @@ void __iomem *mstk48t02_regs = NULL;
 unsigned long ds1287_regs = 0UL;
 #endif
 
-extern unsigned long wall_jiffies;
-
 static void __iomem *mstk48t08_regs;
 static void __iomem *mstk48t59_regs;
 
@@ -465,7 +463,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                profile_tick(CPU_PROFILING, regs);
                update_process_times(user_mode(regs));
 #endif
-               do_timer(regs);
+               do_timer(1);
 
                /* Guarantee that the following sequences execute
                 * uninterrupted.
@@ -496,7 +494,7 @@ void timer_tick_interrupt(struct pt_regs *regs)
 {
        write_seqlock(&xtime_lock);
 
-       do_timer(regs);
+       do_timer(1);
 
        timer_check_rtc();
 
index dcba4e6ab5702d675365c5ec56a77866ddad4dde..09cb7fccc03a758ca2e0f8351734e8a550830c02 100644 (file)
@@ -920,8 +920,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
        if (sparc_ramdisk_image || sparc_ramdisk_image64) {
                unsigned long ramdisk_image = sparc_ramdisk_image ?
                        sparc_ramdisk_image : sparc_ramdisk_image64;
-               if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
-                       ramdisk_image -= KERNBASE;
+               ramdisk_image -= KERNBASE;
                initrd_start = ramdisk_image + phys_base;
                initrd_end = initrd_start + sparc_ramdisk_size;
                if (initrd_end > end_of_phys_memory) {
index 642541769a179970c077dba52e23c2d1d90984a3..9c581328e76a191e3b4aa4903840276db2c3aab2 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/limits.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/tty.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/timex.h>
@@ -422,7 +423,9 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
                           Solaris setpgrp and setsid? */
                        ret = sys_setpgid(0, 0);
                        if (ret) return ret;
+                       mutex_lock(&tty_mutex);
                        current->signal->tty = NULL;
+                       mutex_unlock(&tty_mutex);
                        return process_group(current);
                }
        case 2: /* getsid */
index 9558a7cf34d599f8eda369838ffda69bba6ec646..11154b6773ec230302341d8889e79601677b47c1 100644 (file)
@@ -4,10 +4,13 @@
 core-y += arch/um/sys-x86_64/
 START := 0x60000000
 
+_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel
+
 #We #undef __x86_64__ for kernelspace, not for userspace where
 #it's needed for headers to work!
-CFLAGS += -U__$(SUBARCH)__ -fno-builtin -m64
-USER_CFLAGS += -fno-builtin -m64
+CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_)
+USER_CFLAGS += $(_extra_flags_)
+
 CHECKFLAGS  += -m64
 AFLAGS += -m64
 LDFLAGS += -m elf_x86_64
index e82764f75e7f149c5144f3d4d984c9cac990c06b..3576b3cc505e65432a3068dbce33f6aecc1f666b 100644 (file)
@@ -110,7 +110,7 @@ static void not_configged_free(void *data)
               "UML\n");
 }
 
-static struct chan_ops not_configged_ops = {
+static const struct chan_ops not_configged_ops = {
        .init           = not_configged_init,
        .open           = not_configged_open,
        .close          = not_configged_close,
@@ -373,7 +373,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
 }
 
 int console_open_chan(struct line *line, struct console *co,
-                     struct chan_opts *opts)
+                     const struct chan_opts *opts)
 {
        int err;
 
@@ -494,10 +494,10 @@ int chan_config_string(struct list_head *chans, char *str, int size,
 
 struct chan_type {
        char *key;
-       struct chan_ops *ops;
+       const struct chan_ops *ops;
 };
 
-static struct chan_type chan_table[] = {
+static const struct chan_type chan_table[] = {
        { "fd", &fd_ops },
 
 #ifdef CONFIG_NULL_CHAN
@@ -534,10 +534,10 @@ static struct chan_type chan_table[] = {
 };
 
 static struct chan *parse_chan(struct line *line, char *str, int device,
-                              struct chan_opts *opts)
+                              const struct chan_opts *opts)
 {
-       struct chan_type *entry;
-       struct chan_ops *ops;
+       const struct chan_type *entry;
+       const struct chan_ops *ops;
        struct chan *chan;
        void *data;
        int i;
@@ -582,7 +582,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
 }
 
 int parse_chan_pair(char *str, struct line *line, int device,
-                   struct chan_opts *opts)
+                   const struct chan_opts *opts)
 {
        struct list_head *chans = &line->chan_list;
        struct chan *new, *chan;
index 7326c42f7ef9c9572c1f32488c3ffc2df117afc6..3bc3cf6b94aaf41b2e7e64eeff26ddaa74d36626 100644 (file)
@@ -18,7 +18,7 @@ struct daemon_data {
        void *dev;
 };
 
-extern struct net_user_info daemon_user_info;
+extern const struct net_user_info daemon_user_info;
 
 extern int daemon_user_write(int fd, void *buf, int len, 
                             struct daemon_data *pri);
index 53d09ed78b425391c3e118f998fcd0f89a146691..824386974f88902469f2d95713ae9e4bf6a2928f 100644 (file)
@@ -57,7 +57,7 @@ static int daemon_write(int fd, struct sk_buff **skb,
                                 (struct daemon_data *) &lp->user));
 }
 
-static struct net_kern_info daemon_kern_info = {
+static const struct net_kern_info daemon_kern_info = {
        .init                   = daemon_init,
        .protocol               = eth_protocol,
        .read                   = daemon_read,
index c944265955e203f9a11892f2283e3900aebcef11..77954ea77043796217b22f83e3ef0d9d3b8c7c14 100644 (file)
@@ -182,7 +182,7 @@ static int daemon_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info daemon_user_info = {
+const struct net_user_info daemon_user_info = {
        .init           = daemon_user_init,
        .open           = daemon_open,
        .close          = NULL,
index c41f75e4acb5a64d733af6534837026421f52037..108b7dafbd0e99a6d0cf9a9d82ca26ed6d1ac5f1 100644 (file)
@@ -20,7 +20,7 @@ struct fd_chan {
        char str[sizeof("1234567890\0")];
 };
 
-static void *fd_init(char *str, int device, struct chan_opts *opts)
+static void *fd_init(char *str, int device, const struct chan_opts *opts)
 {
        struct fd_chan *data;
        char *end;
@@ -77,7 +77,7 @@ static void fd_close(int fd, void *d)
        }
 }
 
-struct chan_ops fd_ops = {
+const struct chan_ops fd_ops = {
        .type           = "fd",
        .init           = fd_init,
        .open           = fd_open,
index 37232f908cd74e1c86e88874f68f41bb342fabcf..d247ef45c374c3cb620f6e741035c310f428d4d6 100644 (file)
@@ -280,7 +280,7 @@ static int hostmixer_release(struct inode *inode, struct file *file)
 
 /* kernel module operations */
 
-static struct file_operations hostaudio_fops = {
+static const struct file_operations hostaudio_fops = {
         .owner          = THIS_MODULE,
         .llseek         = no_llseek,
         .read           = hostaudio_read,
@@ -292,7 +292,7 @@ static struct file_operations hostaudio_fops = {
         .release        = hostaudio_release,
 };
 
-static struct file_operations hostmixer_fops = {
+static const struct file_operations hostmixer_fops = {
         .owner          = THIS_MODULE,
         .llseek         = no_llseek,
         .ioctl          = hostmixer_ioctl_mixdev,
index ebebaabb78ad75150ff818cd092f7c918b3fe7dd..563ce7690a1eb66ccf38376da5c68c591666a7ea 100644 (file)
@@ -251,7 +251,7 @@ void line_set_termios(struct tty_struct *tty, struct termios * old)
        /* nothing */
 }
 
-static struct {
+static const struct {
        int  cmd;
        char *level;
        char *name;
@@ -405,7 +405,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
 
 int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
 {
-       struct line_driver *driver = line->driver;
+       const struct line_driver *driver = line->driver;
        int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
 
        if (input)
@@ -558,7 +558,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
 }
 
 int line_config(struct line *lines, unsigned int num, char *str,
-               struct chan_opts *opts)
+               const struct chan_opts *opts)
 {
        struct line *line;
        char *new;
index a2c6db243458972a7eb8dab4c244d29cb0f685b9..bc56af9d3e534a6d4fb874597d2a719564ad5f26 100644 (file)
@@ -13,7 +13,7 @@ struct mcast_data {
        void *dev;
 };
 
-extern struct net_user_info mcast_user_info;
+extern const struct net_user_info mcast_user_info;
 
 extern int mcast_user_write(int fd, void *buf, int len, 
                            struct mcast_data *pri);
index 3a7af18cf9442f1c890ea674d9a8f33784a825a4..c090fbd464e7c9c7713d0eb6456aa859d69eb831 100644 (file)
@@ -61,7 +61,7 @@ static int mcast_write(int fd, struct sk_buff **skb,
                                 (struct mcast_data *) &lp->user);
 }
 
-static struct net_kern_info mcast_kern_info = {
+static const struct net_kern_info mcast_kern_info = {
        .init                   = mcast_init,
        .protocol               = eth_protocol,
        .read                   = mcast_read,
index afe85bfa66e0872eabc55cd1e0b25dace52900bc..4d2bd39a85bc16ff7dc685b908dad366fa82cac0 100644 (file)
@@ -152,7 +152,7 @@ static int mcast_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info mcast_user_info = {
+const struct net_user_info mcast_user_info = {
        .init           = mcast_user_init,
        .open           = mcast_open,
        .close          = mcast_close,
index 79610b5ce67ed5978aa5b74ee109411616c76e60..773a134e7fdb806fd6b63c80ceb3576ede57a370 100644 (file)
@@ -598,6 +598,11 @@ out:
        mconsole_reply(req, err_msg, err, 0);
 }
 
+struct mconsole_output {
+       struct list_head list;
+       struct mc_request *req;
+};
+
 static DEFINE_SPINLOCK(console_lock);
 static LIST_HEAD(clients);
 static char console_buf[MCONSOLE_MAX_DATA];
@@ -622,10 +627,10 @@ static void console_write(struct console *console, const char *string,
                        return;
 
                list_for_each(ele, &clients){
-                       struct mconsole_entry *entry;
+                       struct mconsole_output *entry;
 
-                       entry = list_entry(ele, struct mconsole_entry, list);
-                       mconsole_reply_len(&entry->request, console_buf,
+                       entry = list_entry(ele, struct mconsole_output, list);
+                       mconsole_reply_len(entry->req, console_buf,
                                           console_index, 0, 1);
                }
 
@@ -649,10 +654,10 @@ late_initcall(mc_add_console);
 static void with_console(struct mc_request *req, void (*proc)(void *),
                         void *arg)
 {
-       struct mconsole_entry entry;
+       struct mconsole_output entry;
        unsigned long flags;
 
-       entry.request = *req;
+       entry.req = req;
        list_add(&entry.list, &clients);
        spin_lock_irqsave(&console_lock, flags);
 
index 5b2f5fe9e426d3d45043bae9a49badb804a9426e..17068eb746c0bda5204a8ffd49ee0ab5de16c46a 100644 (file)
@@ -131,6 +131,10 @@ int mconsole_get_request(int fd, struct mc_request *req)
 int mconsole_reply_len(struct mc_request *req, const char *str, int total,
                       int err, int more)
 {
+       /* XXX This is a stack consumption problem.  It'd be nice to
+        * make it global and serialize access to it, but there are a
+        * ton of callers to this function.
+        */
        struct mconsole_reply reply;
        int len, n;
 
index 022f67bb687364f2934b388fca57f703f53c2bfe..9a3b5daf6250784c1359f8997e115eac3ab8f29b 100644 (file)
@@ -85,7 +85,7 @@ mmapper_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static struct file_operations mmapper_fops = {
+static const struct file_operations mmapper_fops = {
        .owner          = THIS_MODULE,
        .read           = mmapper_read,
        .write          = mmapper_write,
@@ -95,7 +95,7 @@ static struct file_operations mmapper_fops = {
        .release        = mmapper_release,
 };
 
-static struct miscdevice mmapper_dev = {
+static const struct miscdevice mmapper_dev = {
        .minor          = MISC_DYNAMIC_MINOR,
        .name           = "mmapper",
        .fops           = &mmapper_fops
index 4a7966b219317440b991de2961130add5d94299d..300a54a6523eb925de5e5308b5170c622f7b3811 100644 (file)
@@ -114,18 +114,11 @@ static int uml_net_open(struct net_device *dev)
        struct uml_net_private *lp = dev->priv;
        int err;
 
-       spin_lock(&lp->lock);
-
        if(lp->fd >= 0){
                err = -ENXIO;
                goto out;
        }
 
-       if(!lp->have_mac){
-               dev_ip_addr(dev, &lp->mac[2]);
-               set_ether_mac(dev, lp->mac);
-       }
-
        lp->fd = (*lp->open)(&lp->user);
        if(lp->fd < 0){
                err = lp->fd;
@@ -149,8 +142,6 @@ static int uml_net_open(struct net_device *dev)
         */
        while((err = uml_net_rx(dev)) > 0) ;
 
-       spin_unlock(&lp->lock);
-
        spin_lock(&opened_lock);
        list_add(&lp->list, &opened);
        spin_unlock(&opened_lock);
@@ -160,7 +151,6 @@ out_close:
        if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
        lp->fd = -1;
 out:
-       spin_unlock(&lp->lock);
        return err;
 }
 
@@ -169,15 +159,12 @@ static int uml_net_close(struct net_device *dev)
        struct uml_net_private *lp = dev->priv;
        
        netif_stop_queue(dev);
-       spin_lock(&lp->lock);
 
        free_irq(dev->irq, dev);
        if(lp->close != NULL)
                (*lp->close)(lp->fd, &lp->user);
        lp->fd = -1;
 
-       spin_unlock(&lp->lock);
-
        spin_lock(&opened_lock);
        list_del(&lp->list);
        spin_unlock(&opened_lock);
@@ -246,9 +233,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
        struct uml_net_private *lp = dev->priv;
        struct sockaddr *hwaddr = addr;
 
-       spin_lock(&lp->lock);
+       spin_lock_irq(&lp->lock);
        set_ether_mac(dev, hwaddr->sa_data);
-       spin_unlock(&lp->lock);
+       spin_unlock_irq(&lp->lock);
 
        return(0);
 }
@@ -258,7 +245,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
        struct uml_net_private *lp = dev->priv;
        int err = 0;
 
-       spin_lock(&lp->lock);
+       spin_lock_irq(&lp->lock);
 
        new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
        if(new_mtu < 0){
@@ -269,7 +256,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
        dev->mtu = new_mtu;
 
  out:
-       spin_unlock(&lp->lock);
+       spin_unlock_irq(&lp->lock);
        return err;
 }
 
@@ -295,6 +282,37 @@ void uml_net_user_timer_expire(unsigned long _conn)
 #endif
 }
 
+static void setup_etheraddr(char *str, unsigned char *addr)
+{
+       char *end;
+       int i;
+
+       if(str == NULL)
+               goto random;
+
+       for(i=0;i<6;i++){
+               addr[i] = simple_strtoul(str, &end, 16);
+               if((end == str) ||
+                  ((*end != ':') && (*end != ',') && (*end != '\0'))){
+                       printk(KERN_ERR
+                              "setup_etheraddr: failed to parse '%s' "
+                              "as an ethernet address\n", str);
+                       goto random;
+               }
+               str = end + 1;
+       }
+       if(addr[0] & 1){
+               printk(KERN_ERR
+                      "Attempt to assign a broadcast ethernet address to a "
+                      "device disallowed\n");
+               goto random;
+       }
+       return;
+
+random:
+       random_ether_addr(addr);
+}
+
 static DEFINE_SPINLOCK(devices_lock);
 static LIST_HEAD(devices);
 
@@ -330,15 +348,13 @@ static int eth_configure(int n, void *init, char *mac,
        list_add(&device->list, &devices);
        spin_unlock(&devices_lock);
 
-       if (setup_etheraddr(mac, device->mac))
-               device->have_mac = 1;
+       setup_etheraddr(mac, device->mac);
 
        printk(KERN_INFO "Netdevice %d ", n);
-       if (device->have_mac)
-               printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
-                      device->mac[0], device->mac[1],
-                      device->mac[2], device->mac[3],
-                      device->mac[4], device->mac[5]);
+       printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
+              device->mac[0], device->mac[1],
+              device->mac[2], device->mac[3],
+              device->mac[4], device->mac[5]);
        printk(": ");
        dev = alloc_etherdev(size);
        if (dev == NULL) {
@@ -404,7 +420,6 @@ static int eth_configure(int n, void *init, char *mac,
                  .dev                  = dev,
                  .fd                   = -1,
                  .mac                  = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
-                 .have_mac             = device->have_mac,
                  .protocol             = transport->kern->protocol,
                  .open                 = transport->user->open,
                  .close                = transport->user->close,
@@ -419,14 +434,12 @@ static int eth_configure(int n, void *init, char *mac,
        init_timer(&lp->tl);
        spin_lock_init(&lp->lock);
        lp->tl.function = uml_net_user_timer_expire;
-       if (lp->have_mac)
-               memcpy(lp->mac, device->mac, sizeof(lp->mac));
+       memcpy(lp->mac, device->mac, sizeof(lp->mac));
 
        if (transport->user->init) 
                (*transport->user->init)(&lp->user, dev);
 
-       if (device->have_mac)
-               set_ether_mac(dev, device->mac);
+       set_ether_mac(dev, device->mac);
 
        return 0;
 }
@@ -569,12 +582,13 @@ static int eth_setup(char *str)
        int n, err;
 
        err = eth_parse(str, &n, &str);
-       if(err) return(1);
+       if(err)
+               return 1;
 
-       new = alloc_bootmem(sizeof(new));
+       new = alloc_bootmem(sizeof(*new));
        if (new == NULL){
                printk("eth_init : alloc_bootmem failed\n");
-               return(1);
+               return 1;
        }
 
        INIT_LIST_HEAD(&new->list);
@@ -582,7 +596,7 @@ static int eth_setup(char *str)
        new->init = str;
 
        list_add_tail(&new->list, &eth_cmd_line);
-       return(1);
+       return 1;
 }
 
 __setup("eth", eth_setup);
@@ -754,47 +768,6 @@ static void close_devices(void)
 
 __uml_exitcall(close_devices);
 
-int setup_etheraddr(char *str, unsigned char *addr)
-{
-       char *end;
-       int i;
-
-       if(str == NULL)
-               return(0);
-       for(i=0;i<6;i++){
-               addr[i] = simple_strtoul(str, &end, 16);
-               if((end == str) ||
-                  ((*end != ':') && (*end != ',') && (*end != '\0'))){
-                       printk(KERN_ERR 
-                              "setup_etheraddr: failed to parse '%s' "
-                              "as an ethernet address\n", str);
-                       return(0);
-               }
-               str = end + 1;
-       }
-       if(addr[0] & 1){
-               printk(KERN_ERR 
-                      "Attempt to assign a broadcast ethernet address to a "
-                      "device disallowed\n");
-               return(0);
-       }
-       return(1);
-}
-
-void dev_ip_addr(void *d, unsigned char *bin_buf)
-{
-       struct net_device *dev = d;
-       struct in_device *ip = dev->ip_ptr;
-       struct in_ifaddr *in;
-
-       if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
-               printk(KERN_WARNING "dev_ip_addr - device not assigned an "
-                      "IP address\n");
-               return;
-       }
-       memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
-}
-
 struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
 {
        if((skb != NULL) && (skb_tailroom(skb) < extra)){
@@ -832,7 +805,7 @@ int dev_netmask(void *d, void *m)
        struct net_device *dev = d;
        struct in_device *ip = dev->ip_ptr;
        struct in_ifaddr *in;
-       __u32 *mask_out = m;
+       __be32 *mask_out = m;
 
        if(ip == NULL) 
                return(1);
index 107c5e43fa00fec37d6fcf8c3b01851274a9b87e..f3a3f8a29c7af877d327692f2f30f89a7ef6f081 100644 (file)
@@ -12,6 +12,7 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
+#include <sys/time.h>
 #include "user.h"
 #include "user_util.h"
 #include "kern_util.h"
index 14cc5f78398ad4363968278ba30e2dbe981e30e4..9016c68beee8d3287761b1da07001c5915bde7c6 100644 (file)
@@ -8,9 +8,10 @@
 #include "chan_user.h"
 #include "os.h"
 
+/* This address is used only as a unique identifer */
 static int null_chan;
 
-static void *null_init(char *str, int device, struct chan_opts *opts)
+static void *null_init(char *str, int device, const struct chan_opts *opts)
 {
        return(&null_chan);
 }
@@ -31,7 +32,7 @@ static void null_free(void *data)
 {
 }
 
-struct chan_ops null_ops = {
+const struct chan_ops null_ops = {
        .type           = "null",
        .init           = null_init,
        .open           = null_open,
index 4c767c7adb964d5546383a4b20e57302334efc2a..6e1ef8558283254faf6c28f462cf71b90cb6626f 100644 (file)
@@ -46,7 +46,7 @@ static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
        return(-EPERM);
 }
 
-static struct net_kern_info pcap_kern_info = {
+static const struct net_kern_info pcap_kern_info = {
        .init                   = pcap_init,
        .protocol               = eth_protocol,
        .read                   = pcap_read,
index edfcb29273e1abf19f601d523a4b125cdc35289f..2ef641ded960a96670456b5d2f1b56914a689c42 100644 (file)
@@ -120,7 +120,7 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
        return(hdata.len);
 }
 
-struct net_user_info pcap_user_info = {
+const struct net_user_info pcap_user_info = {
        .init           = pcap_user_init,
        .open           = pcap_open,
        .close          = NULL,
index c43e8bb3250264940af52ea528fe6a378fe41f67..f2e8fc42ecc2df4a2ec7bfe247ab7ec12fe1659c 100644 (file)
@@ -27,7 +27,7 @@ struct port_chan {
        char dev[sizeof("32768\0")];
 };
 
-static void *port_init(char *str, int device, struct chan_opts *opts)
+static void *port_init(char *str, int device, const struct chan_opts *opts)
 {
        struct port_chan *data;
        void *kern_data;
@@ -100,7 +100,7 @@ static void port_close(int fd, void *d)
        os_close_file(fd);
 }
 
-struct chan_ops port_ops = {
+const struct chan_ops port_ops = {
        .type           = "port",
        .init           = port_init,
        .open           = port_open,
index 1c555c38de4d0184adb129755058b71a1449553f..abec620e838030d43e7a01626cb82c5c041ed63f 100644 (file)
@@ -22,7 +22,7 @@ struct pty_chan {
        char dev_name[sizeof("/dev/pts/0123456\0")];
 };
 
-static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
 {
        struct pty_chan *data;
 
@@ -118,7 +118,7 @@ static int pty_open(int input, int output, int primary, void *d,
        return(fd);
 }
 
-struct chan_ops pty_ops = {
+const struct chan_ops pty_ops = {
        .type           = "pty",
        .init           = pty_chan_init,
        .open           = pty_open,
@@ -131,7 +131,7 @@ struct chan_ops pty_ops = {
        .winch          = 0,
 };
 
-struct chan_ops pts_ops = {
+const struct chan_ops pts_ops = {
        .type           = "pts",
        .init           = pty_chan_init,
        .open           = pts_open,
index ba471f5864a6d7d6815f3847a36aa78b4ed1a5e3..73b2bdd6d2d3b867165e116b7a1b430f34096c9b 100644 (file)
 
 #define RNG_MISCDEV_MINOR              183 /* official */
 
+/* Changed at init time, in the non-modular case, and at module load
+ * time, in the module case.  Presumably, the module subsystem
+ * protects against a module being loaded twice at the same time.
+ */
 static int random_fd = -1;
 
 static int rng_dev_open (struct inode *inode, struct file *filp)
@@ -68,7 +72,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
        return ret;
 }
 
-static struct file_operations rng_chrdev_ops = {
+static const struct file_operations rng_chrdev_ops = {
        .owner          = THIS_MODULE,
        .open           = rng_dev_open,
        .read           = rng_dev_read,
index bb0dab41c2e43a464f5e7dbfe15c28aca84a197c..c64f8c61d2743bc7a75cfea4712a40a3063eb128 100644 (file)
@@ -12,7 +12,7 @@ struct slip_data {
        struct slip_proto slip;
 };
 
-extern struct net_user_info slip_user_info;
+extern const struct net_user_info slip_user_info;
 
 extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
 extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
index 163ee0d5f75e4e165c312a47b02d2af8975f4be9..ccea2d7885e58d2937df864a30e61db69d3f7b77 100644 (file)
@@ -61,7 +61,7 @@ static int slip_write(int fd, struct sk_buff **skb,
                               (struct slip_data *) &lp->user));
 }
 
-struct net_kern_info slip_kern_info = {
+const struct net_kern_info slip_kern_info = {
        .init                   = slip_init,
        .protocol               = slip_protocol,
        .read                   = slip_read,
index 89fbec185cc16ec10d2d8df49410cf8bb32080a1..8460285c69a5cea3e0b842d0b5cd792d84c38aef 100644 (file)
@@ -241,7 +241,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
        close_addr(addr, netmask, pri->name);
 }
 
-struct net_user_info slip_user_info = {
+const struct net_user_info slip_user_info = {
        .init           = slip_user_init,
        .open           = slip_open,
        .close          = slip_close,
index 6cf88ab580c99a7828fbf545fa8b427ec8b862b5..89ccf83b757718b7c4617df8d1e223138a5a2f39 100644 (file)
@@ -24,7 +24,7 @@ struct slirp_data {
        struct slip_proto slip;
 };
 
-extern struct net_user_info slirp_user_info;
+extern const struct net_user_info slirp_user_info;
 
 extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
 extern int slirp_user_write(int fd, void *buf, int len,
index 95e50c943e14f52c7770be2788d5f598cab64adf..ae322e1c8a8753e3794c18cafa20d5d3af6d9b2d 100644 (file)
@@ -64,7 +64,7 @@ static int slirp_write(int fd, struct sk_buff **skb,
                               (struct slirp_data *) &lp->user));
 }
 
-struct net_kern_info slirp_kern_info = {
+const struct net_kern_info slirp_kern_info = {
        .init                   = slirp_init,
        .protocol               = slirp_protocol,
        .read                   = slirp_read,
index 33c5f6e625e83eecc26a97b774dffa6fe1bbb750..ce5e85d1de3d8029ca968033d2d66117de66abcf 100644 (file)
@@ -126,7 +126,7 @@ static int slirp_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info slirp_user_info = {
+const struct net_user_info slirp_user_info = {
        .init           = slirp_user_init,
        .open           = slirp_open,
        .close          = slirp_close,
index 6dafd6fbfdaed13be0f48424f1e811fd24955b89..6f13e7c71a82f3ecb00ccf44e24c0cfc8fafc9fd 100644 (file)
@@ -23,7 +23,7 @@
 #include "irq_user.h"
 #include "mconsole_kern.h"
 
-static int ssl_version = 1;
+static const int ssl_version = 1;
 
 /* Referenced only by tty_driver below - presumably it's locked correctly
  * by the tty driver.
@@ -123,7 +123,7 @@ void ssl_hangup(struct tty_struct *tty)
 }
 #endif
 
-static struct tty_operations ssl_ops = {
+static const struct tty_operations ssl_ops = {
        .open                   = ssl_open,
        .close                  = line_close,
        .write                  = line_write,
index 6d2cf32a9e8f880eeaf7439e874ef4640f3ec7dc..911539293871d271ed306c36fd1b113f6acc9203 100644 (file)
@@ -9,6 +9,8 @@
 /*
  * Don't register by default -- as this registeres very early in the
  * boot process it becomes the default console.
+ *
+ * Initialized at init time.
  */
 static int use_stderr_console = 0;
 
index 856f568c2687fd485a111d2f68843bb3918ac7dc..e4bfcfe8550ba91cc7515c3d3bd46bd7e39ba325 100644 (file)
@@ -108,9 +108,10 @@ static int con_open(struct tty_struct *tty, struct file *filp)
        return line_open(vts, tty);
 }
 
+/* Set in an initcall, checked in an exitcall */
 static int con_init_done = 0;
 
-static struct tty_operations console_ops = {
+static const struct tty_operations console_ops = {
        .open                   = con_open,
        .close                  = line_close,
        .write                  = line_write,
index 9f70edf5d8ef027c645de108ef9cd901f0f8cd27..11de3ac1eb5c787512b4c1a71f6ac1a16cd6725b 100644 (file)
@@ -18,7 +18,7 @@ struct tty_chan {
        struct termios tt;
 };
 
-static void *tty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
 {
        struct tty_chan *data;
 
@@ -62,7 +62,7 @@ static int tty_open(int input, int output, int primary, void *d,
        return fd;
 }
 
-struct chan_ops tty_ops = {
+const struct chan_ops tty_ops = {
        .type           = "tty",
        .init           = tty_chan_init,
        .open           = tty_open,
index 34085315aa57e045232a20abeea45ec1111dda79..fda4a3940698c26a8be776ce5141e5fa3e03189f 100644 (file)
@@ -668,18 +668,15 @@ static int ubd_add(int n)
        if(dev->file == NULL)
                goto out;
 
-       if (ubd_open_dev(dev))
-               goto out;
-
        err = ubd_file_size(dev, &dev->size);
        if(err < 0)
-               goto out_close;
+               goto out;
 
        dev->size = ROUND_BLOCK(dev->size);
 
        err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
        if(err)
-               goto out_close;
+               goto out;
 
        if(fake_major != MAJOR_NR)
                ubd_new_disk(fake_major, dev->size, n,
@@ -691,8 +688,6 @@ static int ubd_add(int n)
                make_ide_entries(ubd_gendisk[n]->disk_name);
 
        err = 0;
-out_close:
-       ubd_close(dev);
 out:
        return err;
 }
@@ -986,8 +981,6 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
        __u64 offset;
        int len;
 
-       if(req->rq_status == RQ_INACTIVE) return(1);
-
        /* This should be impossible now */
        if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
                printk("Write attempted on readonly ubd device %s\n",
index aaa63666104333f487d01521bb6792250cb40a14..386f8b952982e4317f5254e4016a2e7ba18597d1 100644 (file)
@@ -31,7 +31,7 @@ struct xterm_chan {
 };
 
 /* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, struct chan_opts *opts)
+void *xterm_init(char *str, int device, const struct chan_opts *opts)
 {
        struct xterm_chan *data;
 
@@ -194,7 +194,7 @@ static void xterm_free(void *d)
        free(d);
 }
 
-struct chan_ops xterm_ops = {
+const struct chan_ops xterm_ops = {
        .type           = "xterm",
        .init           = xterm_init,
        .open           = xterm_open,
index 1bb5e9d94270493959ef0ffa7053a8cc6d6ce300..572d286ed2c666e21faa970fd2a88f5658056c9a 100644 (file)
@@ -23,21 +23,21 @@ struct chan {
        unsigned int opened:1;
        unsigned int enabled:1;
        int fd;
-       struct chan_ops *ops;
+       const struct chan_ops *ops;
        void *data;
 };
 
 extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
                           struct tty_struct *tty, int irq);
 extern int parse_chan_pair(char *str, struct line *line, int device,
-                          struct chan_opts *opts);
+                          const struct chan_opts *opts);
 extern int open_chan(struct list_head *chans);
 extern int write_chan(struct list_head *chans, const char *buf, int len,
                             int write_irq);
 extern int console_write_chan(struct list_head *chans, const char *buf, 
                              int len);
 extern int console_open_chan(struct line *line, struct console *co,
-                            struct chan_opts *opts);
+                            const struct chan_opts *opts);
 extern void deactivate_chan(struct list_head *chans, int irq);
 extern void reactivate_chan(struct list_head *chans, int irq);
 extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
index 659bb3cac32f51f3e7f8017bd137270e068cabf6..a795547a1dbdb5217563457761bd0f13c2a557e4 100644 (file)
@@ -20,7 +20,7 @@ enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
 
 struct chan_ops {
        char *type;
-       void *(*init)(char *, int, struct chan_opts *);
+       void *(*init)(char *, int, const struct chan_opts *);
        int (*open)(int, int, int, void *, char **);
        void (*close)(int, void *);
        int (*read)(int, char *, void *);
@@ -31,8 +31,8 @@ struct chan_ops {
        int winch;
 };
 
-extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops,
-       xterm_ops;
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+       tty_ops, xterm_ops;
 
 extern void generic_close(int fd, void *unused);
 extern int generic_read(int fd, char *c_out, void *unused);
index 89e1dc835a5bf0281a7fd38b156d7b4ffe72789d..59cfa9e0cad034739c3add89720269c01f0177c2 100644 (file)
@@ -21,7 +21,7 @@ struct kern_handlers {
        kern_hndl timer_handler;
 };
 
-extern struct kern_handlers handlinfo_kern;
+extern const struct kern_handlers handlinfo_kern;
 
 extern int ncpus;
 extern char *linux_prog;
index 27bf2f6fbc05a60d398cb9b2b8ef0a51605711b2..642c9a0320f9a111af988a8dead98a08ef107efb 100644 (file)
@@ -52,7 +52,7 @@ struct line {
 
        int sigio;
        struct work_struct task;
-       struct line_driver *driver;
+       const struct line_driver *driver;
        int have_irq;
 };
 
@@ -99,7 +99,7 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
 extern void close_lines(struct line *lines, int nlines);
 
 extern int line_config(struct line *lines, unsigned int sizeof_lines,
-                      char *str, struct chan_opts *opts);
+                      char *str, const struct chan_opts *opts);
 extern int line_id(char **str, int *start_out, int *end_out);
 extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
 extern int line_get_config(char *dev, struct line *lines,
index f7de6df60dd717f1ba2a16fc563ecee853a5fe7a..280459fb0b2619ded00ce874565a5d6c93ef6c49 100644 (file)
@@ -18,7 +18,6 @@ struct uml_net {
        struct platform_device pdev;
        int index;
        unsigned char mac[ETH_ALEN];
-       int have_mac;
 };
 
 struct uml_net_private {
@@ -29,7 +28,6 @@ struct uml_net_private {
        struct net_device_stats stats;
        int fd;
        unsigned char mac[ETH_ALEN];
-       int have_mac;
        unsigned short (*protocol)(struct sk_buff *);
        int (*open)(void *);
        void (*close)(int, void *);
@@ -54,15 +52,14 @@ struct transport {
        struct list_head list;
        char *name;
        int (*setup)(char *, char **, void *);
-       struct net_user_info *user;
-       struct net_kern_info *kern;
+       const struct net_user_info *user;
+       const struct net_kern_info *kern;
        int private_size;
        int setup_size;
 };
 
 extern struct net_device *ether_init(int);
 extern unsigned short ether_protocol(struct sk_buff *);
-extern int setup_etheraddr(char *str, unsigned char *addr);
 extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
 extern int tap_setup_common(char *str, char *type, char **dev_name, 
                            char **mac_out, char **gate_addr);
@@ -70,14 +67,3 @@ extern void register_transport(struct transport *new);
 extern unsigned short eth_protocol(struct sk_buff *skb);
 
 #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 47ef7cb49a8e3f19619d7417ca856c7762907f3c..19f207cd70fe4b3bf6ed33dee917a58622055d9a 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -25,9 +25,8 @@ struct net_user_info {
 };
 
 extern void ether_user_init(void *data, void *dev);
-extern void dev_ip_addr(void *d, unsigned char *bin_buf);
-extern void iter_addresses(void *d, void (*cb)(unsigned char *, 
-                                              unsigned char *, void *), 
+extern void iter_addresses(void *d, void (*cb)(unsigned char *,
+                                              unsigned char *, void *),
                           void *arg);
 
 extern void *get_output_buffer(int *len_out);
@@ -52,14 +51,3 @@ extern char *split_if_spec(char *str, ...);
 extern int dev_netmask(void *d, void *m);
 
 #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 24fb6d8680e11d0f4c44037b7766fce5d7bd7707..120ca21a513a03853a38abf2004a35a1d0b4b173 100644 (file)
@@ -14,6 +14,7 @@
 #include "skas/mm_id.h"
 #include "irq_user.h"
 #include "sysdep/tls.h"
+#include "sysdep/archsetjmp.h"
 
 #define OS_TYPE_FILE 1
 #define OS_TYPE_DIR 2
@@ -198,7 +199,9 @@ extern long os_ptrace_ldt(long pid, long addr, long data);
 extern int os_getpid(void);
 extern int os_getpgrp(void);
 
+#ifdef UML_CONFIG_MODE_TT
 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
+#endif
 extern void init_new_thread_signals(void);
 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 
@@ -216,7 +219,6 @@ extern void os_flush_stdout(void);
  */
 extern void forward_ipi(int fd, int pid);
 extern void kill_child_dead(int pid);
-extern void stop(void);
 extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
 extern int protect_memory(unsigned long addr, unsigned long len,
                          int r, int w, int x, int must_succeed);
@@ -307,12 +309,9 @@ extern int copy_context_skas0(unsigned long stack, int pid);
 extern void userspace(union uml_pt_regs *regs);
 extern void map_stub_pages(int fd, unsigned long code,
                           unsigned long data, unsigned long stack);
-extern void new_thread(void *stack, void **switch_buf_ptr,
-                        void **fork_buf_ptr, void (*handler)(int));
-extern void thread_wait(void *sw, void *fb);
-extern void switch_threads(void *me, void *next);
-extern int start_idle_thread(void *stack, void *switch_buf_ptr,
-                            void **fork_buf_ptr);
+extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
+extern void switch_threads(jmp_buf *me, jmp_buf *you);
+extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
 extern void initial_thread_cb_skas(void (*proc)(void *),
                                 void *arg);
 extern void halt_skas(void);
index 853b26f148c5bde6043a40dd74c288c7a8e6a4f7..e88926b16072e21d0b1c4af2f854397c24a8bfd0 100644 (file)
@@ -14,8 +14,7 @@ extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
 extern int skas_needs_stub;
 
 extern int user_thread(unsigned long stack, int flags);
-extern void new_thread_proc(void *stack, void (*handler)(int sig));
-extern void new_thread_handler(int sig);
+extern void new_thread_handler(void);
 extern void handle_syscall(union uml_pt_regs *regs);
 extern int new_mm(unsigned long stack);
 extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
index ea1ba3d42aee7b87fdf8734a4251534311ff97cd..11bafab669e942b517e403b13cb966eb2c9242b0 100644 (file)
@@ -16,4 +16,7 @@ struct __jmp_buf {
 
 typedef struct __jmp_buf jmp_buf[1];
 
+#define JB_IP __eip
+#define JB_SP __esp
+
 #endif                         /* _SETJMP_H */
index 454fc60aff6d5a0ba12f403bf2b896f67e999aaa..9a5e1a6ec80042095b5f3562d2c2107e85431508 100644 (file)
@@ -18,4 +18,7 @@ struct __jmp_buf {
 
 typedef struct __jmp_buf jmp_buf[1];
 
+#define JB_IP __rip
+#define JB_SP __rsp
+
 #endif                         /* _SETJMP_H */
index 8d353f0feec1bd66286908008f4674a5635cb569..617bb9efc93424ef59fb413cf0394f7266ad12d1 100644 (file)
 #define HOST_FS 25
 #define HOST_GS 26
 
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
 #define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
 #define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
 #define REGS_DS(r) ((r)[HOST_DS])
@@ -89,9 +104,12 @@ union uml_pt_regs {
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
        struct skas_regs {
-               /* XXX */
-               unsigned long regs[27];
-               unsigned long fp[65];
+               /* x86_64 ptrace uses sizeof(user_regs_struct) as its register
+                * file size, while i386 uses FRAME_SIZE.  Therefore, we need
+                * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE.
+                */
+               unsigned long regs[UM_FRAME_SIZE];
+               unsigned long fp[HOST_FP_SIZE];
                 struct faultinfo faultinfo;
                long syscall;
                int is_user;
@@ -120,11 +138,16 @@ extern int mode_tt;
 #define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
 #define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
 #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_FS_BASE(r) \
+       __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs))
 #define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
+#define UPT_GS_BASE(r) \
+       __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs))
 #define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
 #define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
 #define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
 #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
 #define UPT_ORIG_RAX(r) \
        __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
 
@@ -183,6 +206,13 @@ struct syscall_args {
                 case RBP: val = UPT_RBP(regs); break; \
                 case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
                 case CS: val = UPT_CS(regs); break; \
+                case SS: val = UPT_SS(regs); break; \
+               case FS_BASE: val = UPT_FS_BASE(regs); break; \
+                case GS_BASE: val = UPT_GS_BASE(regs); break; \
+                case DS: val = UPT_DS(regs); break; \
+                case ES: val = UPT_ES(regs); break; \
+                case FS : val = UPT_FS (regs); break; \
+               case GS: val = UPT_GS(regs); break;         \
                 case EFLAGS: val = UPT_EFLAGS(regs); break; \
                 default :  \
                         panic("Bad register in UPT_REG : %d\n", reg);  \
@@ -214,6 +244,13 @@ struct syscall_args {
                 case RBP: UPT_RBP(regs) = __upt_val; break; \
                 case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
                 case CS: UPT_CS(regs) = __upt_val; break; \
+                case SS: UPT_SS(regs) = __upt_val; break; \
+                case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
+                case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
+                case DS: UPT_DS(regs) = __upt_val; break; \
+                case ES: UPT_ES(regs) = __upt_val; break; \
+                case FS: UPT_FS(regs) = __upt_val; break; \
+                case GS: UPT_GS(regs) = __upt_val; break; \
                 case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
                 default :  \
                         panic("Bad register in UPT_SET : %d\n", reg);  \
index a160d9fcc59621b2bc04593df8059f9133a89576..8aee45b074344d979d799330022be9900503764e 100644 (file)
 #define SC_GS(sc) SC_OFFSET(sc, SC_GS)
 #define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
 #define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
+#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
 #if 0
 #define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
 #define SC_DS(sc) SC_OFFSET(sc, SC_DS)
 #define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
 #endif
 
 #endif
index a2d93065b2d0aa10e2b2b363b74366d60276696c..6fa63a2a89e3855df6d351229cdca896c6c3a8f7 100644 (file)
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
 clean-files :=
 
 obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
-       physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \
+       physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
        signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
        um_arch.o umid.o
 
index d21ebad666b4246f45c99d2667dbcc82702b6f6c..8b7f2cdedf945148ffd96306ac04024dc9a0a7ee 100644 (file)
@@ -16,9 +16,13 @@ int uml_exitcode = 0;
 static int read_proc_exitcode(char *page, char **start, off_t off,
                              int count, int *eof, void *data)
 {
-       int len;
+       int len, val;
 
-       len = sprintf(page, "%d\n", uml_exitcode);
+       /* Save uml_exitcode in a local so that we don't need to guarantee
+        * that sprintf accesses it atomically.
+        */
+       val = uml_exitcode;
+       len = sprintf(page, "%d\n", val);
        len -= off;
        if(len <= off+count) *eof = 1;
        *start = page + off;
index 2c86e7fdb014356da4029dd767914f8a355fb622..13aa115cd1b4b521d3bdc1259454626f6b3a4a33 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "linux/module.h"
 
-extern void __bb_init_func(void *);
+extern void __bb_init_func(void *)  __attribute__((weak));
 EXPORT_SYMBOL(__bb_init_func);
 
 /* This is defined (and referred to in profiling stub code) only by some GCC
@@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init);
 
 extern void __gcov_merge_add(void *) __attribute__((weak));
 EXPORT_SYMBOL(__gcov_merge_add);
-
-/*
- * 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 c97045d6d89f5ecf61df62886b54d67bdc42411d..f030e44262ba88a1e7b6b22034f86537ed83c529 100644 (file)
@@ -21,7 +21,6 @@
 #include "mem_user.h"
 #include "os.h"
 
-EXPORT_SYMBOL(stop);
 EXPORT_SYMBOL(uml_physmem);
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
@@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault);
 EXPORT_SYMBOL(find_iomem);
 
 #ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(stop);
 EXPORT_SYMBOL(strncpy_from_user_tt);
 EXPORT_SYMBOL(copy_from_user_tt);
 EXPORT_SYMBOL(copy_to_user_tt);
 #endif
 
 #ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(strnlen_user_skas);
 EXPORT_SYMBOL(strncpy_from_user_skas);
 EXPORT_SYMBOL(copy_to_user_skas);
 EXPORT_SYMBOL(copy_from_user_skas);
index 93121c6d26e55594fe8bb505ebdd17ef20de145c..c95855ba6ab576f7063f3bdf825efb8182a13b9a 100644 (file)
@@ -226,7 +226,8 @@ void paging_init(void)
        for(i = 0; i < ARRAY_SIZE(zones_size); i++)
                zones_size[i] = 0;
 
-       zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
+       zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
+               (uml_physmem >> PAGE_SHIFT);
 #ifdef CONFIG_HIGHMEM
        zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
 #endif
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
new file mode 100644 (file)
index 0000000..fe6c64a
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/sched.h"
+#include "linux/interrupt.h"
+#include "linux/string.h"
+#include "linux/mm.h"
+#include "linux/slab.h"
+#include "linux/utsname.h"
+#include "linux/fs.h"
+#include "linux/utime.h"
+#include "linux/smp_lock.h"
+#include "linux/module.h"
+#include "linux/init.h"
+#include "linux/capability.h"
+#include "linux/vmalloc.h"
+#include "linux/spinlock.h"
+#include "linux/proc_fs.h"
+#include "linux/ptrace.h"
+#include "linux/random.h"
+#include "linux/personality.h"
+#include "asm/unistd.h"
+#include "asm/mman.h"
+#include "asm/segment.h"
+#include "asm/stat.h"
+#include "asm/pgtable.h"
+#include "asm/processor.h"
+#include "asm/tlbflush.h"
+#include "asm/uaccess.h"
+#include "asm/user.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "kern.h"
+#include "signal_kern.h"
+#include "init.h"
+#include "irq_user.h"
+#include "mem_user.h"
+#include "tlb.h"
+#include "frame_kern.h"
+#include "sigcontext.h"
+#include "os.h"
+#include "mode.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
+
+/* This is a per-cpu array.  A processor only modifies its entry and it only
+ * cares about its entry, so it's OK if another processor is modifying its
+ * entry.
+ */
+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
+
+int external_pid(void *t)
+{
+       struct task_struct *task = t ? t : current;
+
+       return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
+}
+
+int pid_to_processor_id(int pid)
+{
+       int i;
+
+       for(i = 0; i < ncpus; i++){
+               if(cpu_tasks[i].pid == pid) return(i);
+       }
+       return(-1);
+}
+
+void free_stack(unsigned long stack, int order)
+{
+       free_pages(stack, order);
+}
+
+unsigned long alloc_stack(int order, int atomic)
+{
+       unsigned long page;
+       gfp_t flags = GFP_KERNEL;
+
+       if (atomic)
+               flags = GFP_ATOMIC;
+       page = __get_free_pages(flags, order);
+       if(page == 0)
+               return(0);
+       stack_protections(page);
+       return(page);
+}
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+       int pid;
+
+       current->thread.request.u.thread.proc = fn;
+       current->thread.request.u.thread.arg = arg;
+       pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
+                     &current->thread.regs, 0, NULL, NULL);
+       if(pid < 0)
+               panic("do_fork failed in kernel_thread, errno = %d", pid);
+       return(pid);
+}
+
+void set_current(void *t)
+{
+       struct task_struct *task = t;
+
+       cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
+               { external_pid(task), task });
+}
+
+void *_switch_to(void *prev, void *next, void *last)
+{
+       struct task_struct *from = prev;
+       struct task_struct *to= next;
+
+       to->thread.prev_sched = from;
+       set_current(to);
+
+       do {
+               current->thread.saved_task = NULL ;
+               CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
+               if(current->thread.saved_task)
+                       show_regs(&(current->thread.regs));
+               next= current->thread.saved_task;
+               prev= current;
+       } while(current->thread.saved_task);
+
+       return(current->thread.prev_sched);
+
+}
+
+void interrupt_end(void)
+{
+       if(need_resched()) schedule();
+       if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
+}
+
+void release_thread(struct task_struct *task)
+{
+       CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
+}
+
+void exit_thread(void)
+{
+       unprotect_stack((unsigned long) current_thread);
+}
+
+void *get_current(void)
+{
+       return(current);
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+               unsigned long stack_top, struct task_struct * p,
+               struct pt_regs *regs)
+{
+       int ret;
+
+       p->thread = (struct thread_struct) INIT_THREAD;
+       ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
+                               clone_flags, sp, stack_top, p, regs);
+
+       if (ret || !current->thread.forking)
+               goto out;
+
+       clear_flushed_tls(p);
+
+       /*
+        * Set a new TLS for the child thread?
+        */
+       if (clone_flags & CLONE_SETTLS)
+               ret = arch_copy_tls(p);
+
+out:
+       return ret;
+}
+
+void initial_thread_cb(void (*proc)(void *), void *arg)
+{
+       int save_kmalloc_ok = kmalloc_ok;
+
+       kmalloc_ok = 0;
+       CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
+                        arg);
+       kmalloc_ok = save_kmalloc_ok;
+}
+
+unsigned long stack_sp(unsigned long page)
+{
+       return(page + PAGE_SIZE - sizeof(void *));
+}
+
+int current_pid(void)
+{
+       return(current->pid);
+}
+
+void default_idle(void)
+{
+       CHOOSE_MODE(uml_idle_timer(), (void) 0);
+
+       while(1){
+               /* endless idle loop with no priority at all */
+
+               /*
+                * although we are an idle CPU, we do not want to
+                * get into the scheduler unnecessarily.
+                */
+               if(need_resched())
+                       schedule();
+
+               idle_sleep(10);
+       }
+}
+
+void cpu_idle(void)
+{
+       CHOOSE_MODE(init_idle_tt(), init_idle_skas());
+}
+
+int page_size(void)
+{
+       return(PAGE_SIZE);
+}
+
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+                     pte_t *pte_out)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t ptent;
+
+       if(task->mm == NULL)
+               return(ERR_PTR(-EINVAL));
+       pgd = pgd_offset(task->mm, addr);
+       if(!pgd_present(*pgd))
+               return(ERR_PTR(-EINVAL));
+
+       pud = pud_offset(pgd, addr);
+       if(!pud_present(*pud))
+               return(ERR_PTR(-EINVAL));
+
+       pmd = pmd_offset(pud, addr);
+       if(!pmd_present(*pmd))
+               return(ERR_PTR(-EINVAL));
+
+       pte = pte_offset_kernel(pmd, addr);
+       ptent = *pte;
+       if(!pte_present(ptent))
+               return(ERR_PTR(-EINVAL));
+
+       if(pte_out != NULL)
+               *pte_out = ptent;
+       return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
+}
+
+char *current_cmd(void)
+{
+#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
+       return("(Unknown)");
+#else
+       void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
+       return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
+#endif
+}
+
+void force_sigbus(void)
+{
+       printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
+              current->pid);
+       lock_kernel();
+       sigaddset(&current->pending.signal, SIGBUS);
+       recalc_sigpending();
+       current->flags |= PF_SIGNALED;
+       do_exit(SIGBUS | 0x80);
+}
+
+void dump_thread(struct pt_regs *regs, struct user *u)
+{
+}
+
+void enable_hlt(void)
+{
+       panic("enable_hlt");
+}
+
+EXPORT_SYMBOL(enable_hlt);
+
+void disable_hlt(void)
+{
+       panic("disable_hlt");
+}
+
+EXPORT_SYMBOL(disable_hlt);
+
+void *um_kmalloc(int size)
+{
+       return kmalloc(size, GFP_KERNEL);
+}
+
+void *um_kmalloc_atomic(int size)
+{
+       return kmalloc(size, GFP_ATOMIC);
+}
+
+void *um_vmalloc(int size)
+{
+       return vmalloc(size);
+}
+
+void *um_vmalloc_atomic(int size)
+{
+       return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
+}
+
+int __cant_sleep(void) {
+       return in_atomic() || irqs_disabled() || in_interrupt();
+       /* Is in_interrupt() really needed? */
+}
+
+unsigned long get_fault_addr(void)
+{
+       return((unsigned long) current->thread.fault_addr);
+}
+
+EXPORT_SYMBOL(get_fault_addr);
+
+void not_implemented(void)
+{
+       printk(KERN_DEBUG "Something isn't implemented in here\n");
+}
+
+EXPORT_SYMBOL(not_implemented);
+
+int user_context(unsigned long sp)
+{
+       unsigned long stack;
+
+       stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
+       return(stack != (unsigned long) current_thread);
+}
+
+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
+
+void do_uml_exitcalls(void)
+{
+       exitcall_t *call;
+
+       call = &__uml_exitcall_end;
+       while (--call >= &__uml_exitcall_begin)
+               (*call)();
+}
+
+char *uml_strdup(char *string)
+{
+       return kstrdup(string, GFP_KERNEL);
+}
+
+int copy_to_user_proc(void __user *to, void *from, int size)
+{
+       return(copy_to_user(to, from, size));
+}
+
+int copy_from_user_proc(void *to, void __user *from, int size)
+{
+       return(copy_from_user(to, from, size));
+}
+
+int clear_user_proc(void __user *buf, int size)
+{
+       return(clear_user(buf, size));
+}
+
+int strlen_user_proc(char __user *str)
+{
+       return(strlen_user(str));
+}
+
+int smp_sigio_handler(void)
+{
+#ifdef CONFIG_SMP
+       int cpu = current_thread->cpu;
+       IPI_handler(cpu);
+       if(cpu != 0)
+               return(1);
+#endif
+       return(0);
+}
+
+int cpu(void)
+{
+       return(current_thread->cpu);
+}
+
+static atomic_t using_sysemu = ATOMIC_INIT(0);
+int sysemu_supported;
+
+void set_using_sysemu(int value)
+{
+       if (value > sysemu_supported)
+               return;
+       atomic_set(&using_sysemu, value);
+}
+
+int get_using_sysemu(void)
+{
+       return atomic_read(&using_sysemu);
+}
+
+static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
+{
+       if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+               *eof = 1;
+
+       return strlen(buf);
+}
+
+static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
+{
+       char tmp[2];
+
+       if (copy_from_user(tmp, buf, 1))
+               return -EFAULT;
+
+       if (tmp[0] >= '0' && tmp[0] <= '2')
+               set_using_sysemu(tmp[0] - '0');
+       return count; /*We use the first char, but pretend to write everything*/
+}
+
+int __init make_proc_sysemu(void)
+{
+       struct proc_dir_entry *ent;
+       if (!sysemu_supported)
+               return 0;
+
+       ent = create_proc_entry("sysemu", 0600, &proc_root);
+
+       if (ent == NULL)
+       {
+               printk(KERN_WARNING "Failed to register /proc/sysemu\n");
+               return(0);
+       }
+
+       ent->read_proc  = proc_read_sysemu;
+       ent->write_proc = proc_write_sysemu;
+
+       return 0;
+}
+
+late_initcall(make_proc_sysemu);
+
+int singlestepping(void * t)
+{
+       struct task_struct *task = t ? t : current;
+
+       if ( ! (task->ptrace & PT_DTRACE) )
+               return(0);
+
+       if (task->thread.singlestep_syscall)
+               return(1);
+
+       return 2;
+}
+
+/*
+ * Only x86 and x86_64 have an arch_align_stack().
+ * All other arches have "#define arch_align_stack(x) (x)"
+ * in their asm/system.h
+ * As this is included in UML from asm-um/system-generic.h,
+ * we can use it to behave as the subarch does.
+ */
+#ifndef arch_align_stack
+unsigned long arch_align_stack(unsigned long sp)
+{
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+               sp -= get_random_int() % 8192;
+       return sp & ~0xf;
+}
+#endif
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
deleted file mode 100644 (file)
index 537895d..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/config.h"
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/interrupt.h"
-#include "linux/string.h"
-#include "linux/mm.h"
-#include "linux/slab.h"
-#include "linux/utsname.h"
-#include "linux/fs.h"
-#include "linux/utime.h"
-#include "linux/smp_lock.h"
-#include "linux/module.h"
-#include "linux/init.h"
-#include "linux/capability.h"
-#include "linux/vmalloc.h"
-#include "linux/spinlock.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/personality.h"
-#include "asm/unistd.h"
-#include "asm/mman.h"
-#include "asm/segment.h"
-#include "asm/stat.h"
-#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "asm/user.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "signal_kern.h"
-#include "init.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "frame_kern.h"
-#include "sigcontext.h"
-#include "os.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
-
-/* This is a per-cpu array.  A processor only modifies its entry and it only
- * cares about its entry, so it's OK if another processor is modifying its
- * entry.
- */
-struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-
-int external_pid(void *t)
-{
-       struct task_struct *task = t ? t : current;
-
-       return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
-}
-
-int pid_to_processor_id(int pid)
-{
-       int i;
-
-       for(i = 0; i < ncpus; i++){
-               if(cpu_tasks[i].pid == pid) return(i);
-       }
-       return(-1);
-}
-
-void free_stack(unsigned long stack, int order)
-{
-       free_pages(stack, order);
-}
-
-unsigned long alloc_stack(int order, int atomic)
-{
-       unsigned long page;
-       gfp_t flags = GFP_KERNEL;
-
-       if (atomic)
-               flags = GFP_ATOMIC;
-       page = __get_free_pages(flags, order);
-       if(page == 0)
-               return(0);
-       stack_protections(page);
-       return(page);
-}
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       int pid;
-
-       current->thread.request.u.thread.proc = fn;
-       current->thread.request.u.thread.arg = arg;
-       pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
-                     &current->thread.regs, 0, NULL, NULL);
-       if(pid < 0)
-               panic("do_fork failed in kernel_thread, errno = %d", pid);
-       return(pid);
-}
-
-void set_current(void *t)
-{
-       struct task_struct *task = t;
-
-       cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
-               { external_pid(task), task });
-}
-
-void *_switch_to(void *prev, void *next, void *last)
-{
-        struct task_struct *from = prev;
-        struct task_struct *to= next;
-
-        to->thread.prev_sched = from;
-        set_current(to);
-
-       do {
-               current->thread.saved_task = NULL ;
-               CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
-               if(current->thread.saved_task)
-                       show_regs(&(current->thread.regs));
-               next= current->thread.saved_task;
-               prev= current;
-       } while(current->thread.saved_task);
-
-        return(current->thread.prev_sched);
-
-}
-
-void interrupt_end(void)
-{
-       if(need_resched()) schedule();
-       if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
-}
-
-void release_thread(struct task_struct *task)
-{
-       CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
-}
-void exit_thread(void)
-{
-       unprotect_stack((unsigned long) current_thread);
-}
-void *get_current(void)
-{
-       return(current);
-}
-
-int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
-               unsigned long stack_top, struct task_struct * p, 
-               struct pt_regs *regs)
-{
-       int ret;
-
-       p->thread = (struct thread_struct) INIT_THREAD;
-       ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
-                               clone_flags, sp, stack_top, p, regs);
-
-       if (ret || !current->thread.forking)
-               goto out;
-
-       clear_flushed_tls(p);
-
-       /*
-        * Set a new TLS for the child thread?
-        */
-       if (clone_flags & CLONE_SETTLS)
-               ret = arch_copy_tls(p);
-
-out:
-       return ret;
-}
-
-void initial_thread_cb(void (*proc)(void *), void *arg)
-{
-       int save_kmalloc_ok = kmalloc_ok;
-
-       kmalloc_ok = 0;
-       CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, 
-                        arg);
-       kmalloc_ok = save_kmalloc_ok;
-}
-unsigned long stack_sp(unsigned long page)
-{
-       return(page + PAGE_SIZE - sizeof(void *));
-}
-
-int current_pid(void)
-{
-       return(current->pid);
-}
-
-void default_idle(void)
-{
-       CHOOSE_MODE(uml_idle_timer(), (void) 0);
-
-       while(1){
-               /* endless idle loop with no priority at all */
-
-               /*
-                * although we are an idle CPU, we do not want to
-                * get into the scheduler unnecessarily.
-                */
-               if(need_resched())
-                       schedule();
-               
-               idle_sleep(10);
-       }
-}
-
-void cpu_idle(void)
-{
-       CHOOSE_MODE(init_idle_tt(), init_idle_skas());
-}
-
-int page_size(void)
-{
-       return(PAGE_SIZE);
-}
-
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 
-                     pte_t *pte_out)
-{
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       pte_t ptent;
-
-       if(task->mm == NULL) 
-               return(ERR_PTR(-EINVAL));
-       pgd = pgd_offset(task->mm, addr);
-       if(!pgd_present(*pgd))
-               return(ERR_PTR(-EINVAL));
-
-       pud = pud_offset(pgd, addr);
-       if(!pud_present(*pud))
-               return(ERR_PTR(-EINVAL));
-
-       pmd = pmd_offset(pud, addr);
-       if(!pmd_present(*pmd)) 
-               return(ERR_PTR(-EINVAL));
-
-       pte = pte_offset_kernel(pmd, addr);
-       ptent = *pte;
-       if(!pte_present(ptent))
-               return(ERR_PTR(-EINVAL));
-
-       if(pte_out != NULL)
-               *pte_out = ptent;
-       return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
-       return("(Unknown)");
-#else
-       void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
-       return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
-void force_sigbus(void)
-{
-       printk(KERN_ERR "Killing pid %d because of a lack of memory\n", 
-              current->pid);
-       lock_kernel();
-       sigaddset(&current->pending.signal, SIGBUS);
-       recalc_sigpending();
-       current->flags |= PF_SIGNALED;
-       do_exit(SIGBUS | 0x80);
-}
-
-void dump_thread(struct pt_regs *regs, struct user *u)
-{
-}
-
-void enable_hlt(void)
-{
-       panic("enable_hlt");
-}
-
-EXPORT_SYMBOL(enable_hlt);
-
-void disable_hlt(void)
-{
-       panic("disable_hlt");
-}
-
-EXPORT_SYMBOL(disable_hlt);
-
-void *um_kmalloc(int size)
-{
-       return kmalloc(size, GFP_KERNEL);
-}
-
-void *um_kmalloc_atomic(int size)
-{
-       return kmalloc(size, GFP_ATOMIC);
-}
-
-void *um_vmalloc(int size)
-{
-       return vmalloc(size);
-}
-
-void *um_vmalloc_atomic(int size)
-{
-       return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
-}
-
-int __cant_sleep(void) {
-       return in_atomic() || irqs_disabled() || in_interrupt();
-       /* Is in_interrupt() really needed? */
-}
-
-unsigned long get_fault_addr(void)
-{
-       return((unsigned long) current->thread.fault_addr);
-}
-
-EXPORT_SYMBOL(get_fault_addr);
-
-void not_implemented(void)
-{
-       printk(KERN_DEBUG "Something isn't implemented in here\n");
-}
-
-EXPORT_SYMBOL(not_implemented);
-
-int user_context(unsigned long sp)
-{
-       unsigned long stack;
-
-       stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-       return(stack != (unsigned long) current_thread);
-}
-
-extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
-
-void do_uml_exitcalls(void)
-{
-       exitcall_t *call;
-
-       call = &__uml_exitcall_end;
-       while (--call >= &__uml_exitcall_begin)
-               (*call)();
-}
-
-char *uml_strdup(char *string)
-{
-       return kstrdup(string, GFP_KERNEL);
-}
-
-int copy_to_user_proc(void __user *to, void *from, int size)
-{
-       return(copy_to_user(to, from, size));
-}
-
-int copy_from_user_proc(void *to, void __user *from, int size)
-{
-       return(copy_from_user(to, from, size));
-}
-
-int clear_user_proc(void __user *buf, int size)
-{
-       return(clear_user(buf, size));
-}
-
-int strlen_user_proc(char __user *str)
-{
-       return(strlen_user(str));
-}
-
-int smp_sigio_handler(void)
-{
-#ifdef CONFIG_SMP
-       int cpu = current_thread->cpu;
-       IPI_handler(cpu);
-       if(cpu != 0)
-               return(1);
-#endif
-       return(0);
-}
-
-int cpu(void)
-{
-       return(current_thread->cpu);
-}
-
-static atomic_t using_sysemu = ATOMIC_INIT(0);
-int sysemu_supported;
-
-void set_using_sysemu(int value)
-{
-       if (value > sysemu_supported)
-               return;
-       atomic_set(&using_sysemu, value);
-}
-
-int get_using_sysemu(void)
-{
-       return atomic_read(&using_sysemu);
-}
-
-static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
-{
-       if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
-               *eof = 1;
-
-       return strlen(buf);
-}
-
-static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
-{
-       char tmp[2];
-
-       if (copy_from_user(tmp, buf, 1))
-               return -EFAULT;
-
-       if (tmp[0] >= '0' && tmp[0] <= '2')
-               set_using_sysemu(tmp[0] - '0');
-       return count; /*We use the first char, but pretend to write everything*/
-}
-
-int __init make_proc_sysemu(void)
-{
-       struct proc_dir_entry *ent;
-       if (!sysemu_supported)
-               return 0;
-
-       ent = create_proc_entry("sysemu", 0600, &proc_root);
-
-       if (ent == NULL)
-       {
-               printk(KERN_WARNING "Failed to register /proc/sysemu\n");
-               return(0);
-       }
-
-       ent->read_proc  = proc_read_sysemu;
-       ent->write_proc = proc_write_sysemu;
-
-       return 0;
-}
-
-late_initcall(make_proc_sysemu);
-
-int singlestepping(void * t)
-{
-       struct task_struct *task = t ? t : current;
-
-       if ( ! (task->ptrace & PT_DTRACE) )
-               return(0);
-
-       if (task->thread.singlestep_syscall)
-               return(1);
-
-       return 2;
-}
-
-/*
- * Only x86 and x86_64 have an arch_align_stack().
- * All other arches have "#define arch_align_stack(x) (x)"
- * in their asm/system.h
- * As this is included in UML from asm-um/system-generic.h,
- * we can use it to behave as the subarch does.
- */
-#ifndef arch_align_stack
-unsigned long arch_align_stack(unsigned long sp)
-{
-       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-               sp -= get_random_int() % 8192;
-       return sp & ~0xf;
-}
-#endif
index ea3a8e409a6e69c05d18634acc724f7fc5bbcf94..3e3fa7e7e3cfaf6ac5d72d88cc8108faefcdfd6d 100644 (file)
@@ -3,8 +3,7 @@
 # Licensed under the GPL
 #
 
-obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
-       syscall.o tlb.o uaccess.o
+obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
 
 # clone.o is in the stub, so it can't be built with profiling
 # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
new file mode 100644 (file)
index 0000000..54b7959
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "asm/current.h"
+#include "asm/page.h"
+#include "asm/signal.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/mmu_context.h"
+#include "tlb.h"
+#include "skas.h"
+#include "um_mmu.h"
+#include "os.h"
+
+void flush_thread_skas(void)
+{
+       force_flush_all();
+       switch_mm_skas(&current->mm->context.skas.id);
+}
+
+void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+                      unsigned long esp)
+{
+       set_fs(USER_DS);
+       PT_REGS_IP(regs) = eip;
+       PT_REGS_SP(regs) = esp;
+}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
deleted file mode 100644 (file)
index 77ed7bb..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-#include "tlb.h"
-#include "skas.h"
-#include "um_mmu.h"
-#include "os.h"
-
-void flush_thread_skas(void)
-{
-       force_flush_all();
-        switch_mm_skas(&current->mm->context.skas.id);
-}
-
-void start_thread_skas(struct pt_regs *regs, unsigned long eip, 
-                      unsigned long esp)
-{
-       set_fs(USER_DS);
-        PT_REGS_IP(regs) = eip;
-       PT_REGS_SP(regs) = esp;
-}
-
-/*
- * 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 79c22707a6375c84cbda0f89df31abf0eda28836..4cd2ff546ef6f9d322b2f882ca182bf5315cf7c9 100644 (file)
@@ -61,8 +61,10 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
 #endif
 
        *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
-       *pte = pte_mkexec(*pte);
-       *pte = pte_wrprotect(*pte);
+       /* This is wrong for the code page, but it doesn't matter since the
+        * stub is mapped by hand with the correct permissions.
+        */
+       *pte = pte_mkwrite(*pte);
        return(0);
 
  out_pmd:
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
new file mode 100644 (file)
index 0000000..ae4fa71
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/slab.h"
+#include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
+#include "kern_util.h"
+#include "skas.h"
+#include "os.h"
+#include "user_util.h"
+#include "tlb.h"
+#include "kern.h"
+#include "mode.h"
+#include "registers.h"
+
+void switch_to_skas(void *prev, void *next)
+{
+       struct task_struct *from, *to;
+
+       from = prev;
+       to = next;
+
+       /* XXX need to check runqueues[cpu].idle */
+       if(current->pid == 0)
+               switch_timers(0);
+
+       switch_threads(&from->thread.mode.skas.switch_buf,
+                      &to->thread.mode.skas.switch_buf);
+
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
+       if(current->pid == 0)
+               switch_timers(1);
+}
+
+extern void schedule_tail(struct task_struct *prev);
+
+/* This is called magically, by its address being stuffed in a jmp_buf
+ * and being longjmp-d to.
+ */
+void new_thread_handler(void)
+{
+       int (*fn)(void *), n;
+       void *arg;
+
+       if(current->thread.prev_sched != NULL)
+               schedule_tail(current->thread.prev_sched);
+       current->thread.prev_sched = NULL;
+
+       fn = current->thread.request.u.thread.proc;
+       arg = current->thread.request.u.thread.arg;
+
+       /* The return value is 1 if the kernel thread execs a process,
+        * 0 if it just exits
+        */
+       n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
+       if(n == 1){
+               /* Handle any immediate reschedules or signals */
+               interrupt_end();
+               userspace(&current->thread.regs.regs);
+       }
+       else do_exit(0);
+}
+
+void release_thread_skas(struct task_struct *task)
+{
+}
+
+/* Called magically, see new_thread_handler above */
+void fork_handler(void)
+{
+       force_flush_all();
+       if(current->thread.prev_sched == NULL)
+               panic("blech");
+
+       schedule_tail(current->thread.prev_sched);
+
+       /* XXX: if interrupt_end() calls schedule, this call to
+        * arch_switch_to_skas isn't needed. We could want to apply this to
+        * improve performance. -bb */
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
+       current->thread.prev_sched = NULL;
+
+/* Handle any immediate reschedules or signals */
+       interrupt_end();
+
+       userspace(&current->thread.regs.regs);
+}
+
+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
+                    unsigned long stack_top, struct task_struct * p,
+                    struct pt_regs *regs)
+{
+       void (*handler)(void);
+
+       if(current->thread.forking){
+               memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
+                      sizeof(p->thread.regs.regs.skas));
+               REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
+               if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
+
+               handler = fork_handler;
+
+               arch_copy_thread(&current->thread.arch, &p->thread.arch);
+       }
+       else {
+               init_thread_registers(&p->thread.regs.regs);
+               p->thread.request.u.thread = current->thread.request.u.thread;
+               handler = new_thread_handler;
+       }
+
+       new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
+                  handler);
+       return(0);
+}
+
+int new_mm(unsigned long stack)
+{
+       int fd;
+
+       fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
+       if(fd < 0)
+               return(fd);
+
+       if(skas_needs_stub)
+               map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+
+       return(fd);
+}
+
+void init_idle_skas(void)
+{
+       cpu_tasks[current_thread->cpu].pid = os_getpid();
+       default_idle();
+}
+
+extern void start_kernel(void);
+
+static int start_kernel_proc(void *unused)
+{
+       int pid;
+
+       block_signals();
+       pid = os_getpid();
+
+       cpu_tasks[0].pid = pid;
+       cpu_tasks[0].task = current;
+#ifdef CONFIG_SMP
+       cpu_online_map = cpumask_of_cpu(0);
+#endif
+       start_kernel();
+       return(0);
+}
+
+extern int userspace_pid[];
+
+int start_uml_skas(void)
+{
+       if(proc_mm)
+               userspace_pid[0] = start_userspace(0);
+
+       init_new_thread_signals();
+
+       init_task.thread.request.u.thread.proc = start_kernel_proc;
+       init_task.thread.request.u.thread.arg = NULL;
+       return(start_idle_thread(task_stack_page(&init_task),
+                                &init_task.thread.mode.skas.switch_buf));
+}
+
+int external_pid_skas(struct task_struct *task)
+{
+#warning 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
+       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
+               os_kill_ptraced_process(userspace_pid[0], 1);
+       else {
+               struct task_struct *p;
+               int pid, me;
+
+               me = os_getpid();
+               for_each_process(p){
+                       if(p->mm == NULL)
+                               continue;
+
+                       pid = p->mm->context.skas.id.u.pid;
+                       os_kill_ptraced_process(pid, 1);
+               }
+       }
+}
+
+unsigned long current_stub_stack(void)
+{
+       if(current->mm == NULL)
+               return(0);
+
+       return(current->mm->context.skas.id.stack);
+}
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
deleted file mode 100644 (file)
index 55caeec..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/ptrace.h"
-#include "linux/proc_fs.h"
-#include "linux/file.h"
-#include "linux/errno.h"
-#include "linux/init.h"
-#include "asm/uaccess.h"
-#include "asm/atomic.h"
-#include "kern_util.h"
-#include "skas.h"
-#include "os.h"
-#include "user_util.h"
-#include "tlb.h"
-#include "kern.h"
-#include "mode.h"
-#include "registers.h"
-
-void switch_to_skas(void *prev, void *next)
-{
-       struct task_struct *from, *to;
-
-       from = prev;
-       to = next;
-
-       /* XXX need to check runqueues[cpu].idle */
-       if(current->pid == 0)
-               switch_timers(0);
-
-       switch_threads(&from->thread.mode.skas.switch_buf,
-                      to->thread.mode.skas.switch_buf);
-
-       arch_switch_to_skas(current->thread.prev_sched, current);
-
-       if(current->pid == 0)
-               switch_timers(1);
-}
-
-extern void schedule_tail(struct task_struct *prev);
-
-void new_thread_handler(int sig)
-{
-       int (*fn)(void *), n;
-       void *arg;
-
-       fn = current->thread.request.u.thread.proc;
-       arg = current->thread.request.u.thread.arg;
-       os_usr1_signal(1);
-       thread_wait(&current->thread.mode.skas.switch_buf,
-                   current->thread.mode.skas.fork_buf);
-
-       if(current->thread.prev_sched != NULL)
-               schedule_tail(current->thread.prev_sched);
-       current->thread.prev_sched = NULL;
-
-       /* The return value is 1 if the kernel thread execs a process,
-        * 0 if it just exits
-        */
-       n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
-       if(n == 1){
-               /* Handle any immediate reschedules or signals */
-               interrupt_end();
-               userspace(&current->thread.regs.regs);
-       }
-       else do_exit(0);
-}
-
-void new_thread_proc(void *stack, void (*handler)(int sig))
-{
-       init_new_thread_stack(stack, handler);
-       os_usr1_process(os_getpid());
-}
-
-void release_thread_skas(struct task_struct *task)
-{
-}
-
-void fork_handler(int sig)
-{
-       os_usr1_signal(1);
-       thread_wait(&current->thread.mode.skas.switch_buf,
-                   current->thread.mode.skas.fork_buf);
-       
-       force_flush_all();
-       if(current->thread.prev_sched == NULL)
-               panic("blech");
-
-       schedule_tail(current->thread.prev_sched);
-
-       /* XXX: if interrupt_end() calls schedule, this call to
-        * arch_switch_to_skas isn't needed. We could want to apply this to
-        * improve performance. -bb */
-       arch_switch_to_skas(current->thread.prev_sched, current);
-
-       current->thread.prev_sched = NULL;
-
-/* Handle any immediate reschedules or signals */
-       interrupt_end();
-
-       userspace(&current->thread.regs.regs);
-}
-
-int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
-                    unsigned long stack_top, struct task_struct * p,
-                    struct pt_regs *regs)
-{
-       void (*handler)(int);
-
-       if(current->thread.forking){
-               memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
-                      sizeof(p->thread.regs.regs.skas));
-               REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
-               if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
-
-               handler = fork_handler;
-
-               arch_copy_thread(&current->thread.arch, &p->thread.arch);
-       }
-       else {
-               init_thread_registers(&p->thread.regs.regs);
-                p->thread.request.u.thread = current->thread.request.u.thread;
-               handler = new_thread_handler;
-       }
-
-       new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
-                  &p->thread.mode.skas.fork_buf, handler);
-       return(0);
-}
-
-int new_mm(unsigned long stack)
-{
-       int fd;
-
-       fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
-       if(fd < 0)
-               return(fd);
-
-       if(skas_needs_stub)
-               map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
-
-       return(fd);
-}
-
-void init_idle_skas(void)
-{
-       cpu_tasks[current_thread->cpu].pid = os_getpid();
-       default_idle();
-}
-
-extern void start_kernel(void);
-
-static int start_kernel_proc(void *unused)
-{
-       int pid;
-
-       block_signals();
-       pid = os_getpid();
-
-       cpu_tasks[0].pid = pid;
-       cpu_tasks[0].task = current;
-#ifdef CONFIG_SMP
-       cpu_online_map = cpumask_of_cpu(0);
-#endif
-       start_kernel();
-       return(0);
-}
-
-extern int userspace_pid[];
-
-int start_uml_skas(void)
-{
-       if(proc_mm)
-               userspace_pid[0] = start_userspace(0);
-
-       init_new_thread_signals();
-
-       init_task.thread.request.u.thread.proc = start_kernel_proc;
-       init_task.thread.request.u.thread.arg = NULL;
-       return(start_idle_thread(task_stack_page(&init_task),
-                                &init_task.thread.mode.skas.switch_buf,
-                                &init_task.thread.mode.skas.fork_buf));
-}
-
-int external_pid_skas(struct task_struct *task)
-{
-#warning 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
-       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
-               os_kill_ptraced_process(userspace_pid[0], 1);
-       else {
-               struct task_struct *p;
-               int pid, me;
-
-               me = os_getpid();
-               for_each_process(p){
-                       if(p->mm == NULL)
-                               continue;
-
-                       pid = p->mm->context.skas.id.u.pid;
-                       os_kill_ptraced_process(pid, 1);
-               }
-       }
-}
-
-unsigned long current_stub_stack(void)
-{
-       if(current->mm == NULL)
-               return(0);
-
-       return(current->mm->context.skas.id.stack);
-}
index 2454bbd9555d5287f2859e9baa921a39e007c23d..a92965f8f9cdd57d600e229e136dee8fafa64d5a 100644 (file)
@@ -93,9 +93,9 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 
        write_seqlock_irqsave(&xtime_lock, flags);
 
-       do_timer(regs);
+       do_timer(1);
 
-       nsecs = get_time() + local_offset;
+       nsecs = get_time();
        xtime.tv_sec = nsecs / NSEC_PER_SEC;
        xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
 
index e5eeaf2b6af118c33401528a0e03ff206af15ed9..c7b195c7e51fa3ddc3d46da245f2f0f5ce7fa6fe 100644 (file)
@@ -120,7 +120,7 @@ out_nosemaphore:
  * us unable to handle the page fault gracefully.
  */
 out_of_memory:
-       if (current->pid == 1) {
+       if (is_init(current)) {
                up_read(&mm->mmap_sem);
                yield();
                down_read(&mm->mmap_sem);
@@ -140,14 +140,6 @@ void segv_handler(int sig, union uml_pt_regs *regs)
        segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
 }
 
-struct kern_handlers handlinfo_kern = {
-       .relay_signal = relay_signal,
-       .winch = winch,
-       .bus_handler = relay_signal,
-       .page_fault = segv_handler,
-       .sigio_handler = sigio_handler,
-       .timer_handler = timer_handler
-};
 /*
  * We give a *copy* of the faultinfo in the regs to segv.
  * This must be done, since nesting SEGVs could overwrite
@@ -253,6 +245,15 @@ void winch(int sig, union uml_pt_regs *regs)
        do_IRQ(WINCH_IRQ, regs);
 }
 
+const struct kern_handlers handlinfo_kern = {
+       .relay_signal = relay_signal,
+       .winch = winch,
+       .bus_handler = bus_handler,
+       .page_fault = segv_handler,
+       .sigio_handler = sigio_handler,
+       .timer_handler = timer_handler
+};
+
 void trap_init(void)
 {
 }
index 7896cf98232df1a06c6593957e24597b8dbb7e04..55005710dcbbc8254fc3bbea46f3f3b6ad065ad1 100644 (file)
@@ -106,7 +106,7 @@ static void c_stop(struct seq_file *m, void *v)
 {
 }
 
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
        .start  = c_start,
        .next   = c_next,
        .stop   = c_stop,
index f4bfc4c7ccac25504c359f805013c35adb3ce78b..b4183929b32cb28e3d6e5f4efaa445676293e86a 100644 (file)
@@ -4,15 +4,19 @@
 #
 
 obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
-       signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
+       signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
        user_syms.o util.o drivers/ sys-$(SUBARCH)/
 
 obj-$(CONFIG_MODE_SKAS) += skas/
+
+obj-$(CONFIG_MODE_TT) += tt.o
+user-objs-$(CONFIG_MODE_TT) += tt.o
+
 obj-$(CONFIG_TTY_LOG) += tty_log.o
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
-       process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
+       process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
        uaccess.o umid.o util.o
 
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
index b84f6c4740f74efc9389c2e042a0de3198649707..57ecdaf2f67e872f029da7a8b501f970e4950d1b 100644 (file)
@@ -13,7 +13,7 @@ struct ethertap_data {
        void *dev;
 };
 
-extern struct net_user_info ethertap_user_info;
+extern const struct net_user_info ethertap_user_info;
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 768606bec233222de64a8698b535a62e4a472157..16385e2ada854ebd1c965364a6d065f709294c3f 100644 (file)
@@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
        return(net_send(fd, (*skb)->data, (*skb)->len));
 }
 
-struct net_kern_info ethertap_kern_info = {
+const struct net_kern_info ethertap_kern_info = {
        .init                   = etap_init,
        .protocol               = eth_protocol,
        .read                   = etap_read,
index 8f49507e64ef5ac0091fe22189bea6413e427469..f559bdf746e6099bfb7593215ded118626a899df 100644 (file)
@@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
        etap_close_addr(addr, netmask, &pri->control_fd);
 }
 
-struct net_user_info ethertap_user_info = {
+const struct net_user_info ethertap_user_info = {
        .init           = etap_user_init,
        .open           = etap_open,
        .close          = etap_close,
index 25d4a2868814bdd83ebd083448d1006a3e1962af..d3e8d3af62454af21338709d5dda4c80996ee62f 100644 (file)
@@ -16,7 +16,7 @@ struct tuntap_data {
        void *dev;
 };
 
-extern struct net_user_info tuntap_user_info;
+extern const struct net_user_info tuntap_user_info;
 
 #endif
 
index 190009a6f89cd2a713f8b6a44fc1b1b12bff6c0e..0edbac63c52708009ac792442fee6eb75dc2fbb5 100644 (file)
@@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb,
        return(net_write(fd, (*skb)->data, (*skb)->len));
 }
 
-struct net_kern_info tuntap_kern_info = {
+const struct net_kern_info tuntap_kern_info = {
        .init                   = tuntap_init,
        .protocol               = eth_protocol,
        .read                   = tuntap_read,
index 87c3aa0252db5530190d0ac0837dfe8ec55d3aa6..e846b23f7558582e8bf51f09a18d91b698c25f65 100644 (file)
@@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info tuntap_user_info = {
+const struct net_user_info tuntap_user_info = {
        .init           = tuntap_user_init,
        .open           = tuntap_open,
        .close          = tuntap_close,
index b170b4704dc40aa25137f6ab29ece4b36eb03078..4203681e508d0a680635347c53a2168fdd3a68be 100644 (file)
@@ -132,6 +132,9 @@ err:
        else if(found < 0)
                printf("read returned errno %d\n", -found);
 
+out:
+       close(fd);
+
        return;
 
 found:
@@ -141,11 +144,12 @@ found:
 
        if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
                printf("not tmpfs\n");
-               return;
+               goto out;
        }
 
        printf("OK\n");
        default_tmpdir = "/dev/shm";
+       goto out;
 }
 
 /*
index 42e3d1ed802cadf01a6f06345daf8ecc327f05d5..cb9ab54146cc6126ac5a6344a520f4e0e8a8f25c 100644 (file)
@@ -444,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
        }
 }
 
-void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
-               void (*handler)(int))
+void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
 {
-       unsigned long flags;
-       jmp_buf switch_buf, fork_buf;
-
-       *switch_buf_ptr = &switch_buf;
-       *fork_buf_ptr = &fork_buf;
-
-       /* Somewhat subtle - siglongjmp restores the signal mask before doing
-        * the longjmp.  This means that when jumping from one stack to another
-        * when the target stack has interrupts enabled, an interrupt may occur
-        * on the source stack.  This is bad when starting up a process because
-        * it's not supposed to get timer ticks until it has been scheduled.
-        * So, we disable interrupts around the sigsetjmp to ensure that
-        * they can't happen until we get back here where they are safe.
-        */
-       flags = get_signals();
-       block_signals();
-       if(UML_SETJMP(&fork_buf) == 0)
-               new_thread_proc(stack, handler);
-
-       remove_sigstack();
-
-       set_signals(flags);
+       (*buf)[0].JB_IP = (unsigned long) handler;
+       (*buf)[0].JB_SP = (unsigned long) stack +
+               (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
 }
 
 #define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
-
-void thread_wait(void *sw, void *fb)
-{
-       jmp_buf buf, **switch_buf = sw, *fork_buf;
-
-       *switch_buf = &buf;
-       fork_buf = fb;
-       if(UML_SETJMP(&buf) == 0)
-               UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);
-}
+#define INIT_JMP_CALLBACK 1
+#define INIT_JMP_HALT 2
+#define INIT_JMP_REBOOT 3
 
-void switch_threads(void *me, void *next)
+void switch_threads(jmp_buf *me, jmp_buf *you)
 {
-       jmp_buf my_buf, **me_ptr = me, *next_buf = next;
-
-       *me_ptr = &my_buf;
-       if(UML_SETJMP(&my_buf) == 0)
-               UML_LONGJMP(next_buf, 1);
+       if(UML_SETJMP(me) == 0)
+               UML_LONGJMP(you, 1);
 }
 
 static jmp_buf initial_jmpbuf;
@@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg);
 static void *cb_arg;
 static jmp_buf *cb_back;
 
-int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+int start_idle_thread(void *stack, jmp_buf *switch_buf)
 {
-       jmp_buf **switch_buf = switch_buf_ptr;
        int n;
 
        set_handler(SIGWINCH, (__sighandler_t) sig_handler,
                    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
                    SIGVTALRM, -1);
 
-       *fork_buf_ptr = &initial_jmpbuf;
        n = UML_SETJMP(&initial_jmpbuf);
        switch(n){
        case INIT_JMP_NEW_THREAD:
-               new_thread_proc((void *) stack, new_thread_handler);
-               break;
-       case INIT_JMP_REMOVE_SIGSTACK:
-               remove_sigstack();
+               (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+               (*switch_buf)[0].JB_SP = (unsigned long) stack +
+                       (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
+                       sizeof(void *);
                break;
        case INIT_JMP_CALLBACK:
                (*cb_proc)(cb_arg);
@@ -534,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
        default:
                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
        }
-       UML_LONGJMP(*switch_buf, 1);
+       UML_LONGJMP(switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
index 491614c435cd5f8de9a2d54a445156f94448a5d6..815f8a43926fab1f51c5bde3f7ecef16cd53d700 100644 (file)
@@ -30,7 +30,7 @@ static DEFINE_SPINLOCK(memcons_lock);
 
 static size_t write (const char *buf, size_t len)
 {
-       int flags;
+       unsigned long flags;
        char *point;
 
        spin_lock_irqsave (memcons_lock, flags);
index f654088b27600098d89cab8afe0714f5a10aa645..996bd4f33ecb11a84de31911cb44fa531d53a429 100644 (file)
@@ -42,7 +42,7 @@ do {                                                                  \
                        len = LED_NUM_DIGITS - pos;                     \
                                                                        \
                if (len > 0) {                                          \
-                       int _flags;                                     \
+                       unsigned long _flags;                           \
                        const char *_end = buf + len;                   \
                        img_decl = &leds_image[pos];                    \
                                                                        \
index f36b778f14320e96e6dca7f748b2ed7cf98ae76c..35213fa9f7d829544c36e1223a6805df9cc4f004 100644 (file)
@@ -365,7 +365,7 @@ static DEFINE_SPINLOCK(mb_sram_lock);
 static void *alloc_mb_sram (size_t size)
 {
        struct mb_sram_free_area *prev, *fa;
-       int flags;
+       unsigned long flags;
        void *mem = 0;
 
        spin_lock_irqsave (mb_sram_lock, flags);
@@ -406,7 +406,7 @@ static void *alloc_mb_sram (size_t size)
 static void free_mb_sram (void *mem, size_t size)
 {
        struct mb_sram_free_area *prev, *fa, *new_fa;
-       int flags;
+       unsigned long flags;
        void *end = mem + size;
 
        spin_lock_irqsave (mb_sram_lock, flags);
@@ -517,7 +517,7 @@ static DEFINE_SPINLOCK(dma_mappings_lock);
 
 static struct dma_mapping *new_dma_mapping (size_t size)
 {
-       int flags;
+       unsigned long flags;
        struct dma_mapping *mapping;
        void *mb_sram_block = alloc_mb_sram (size);
 
@@ -575,7 +575,7 @@ static struct dma_mapping *new_dma_mapping (size_t size)
 
 static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
 {
-       int flags;
+       unsigned long flags;
        struct dma_mapping *mapping;
 
        spin_lock_irqsave (dma_mappings_lock, flags);
@@ -592,7 +592,7 @@ static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
 
 static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
 {
-       int flags;
+       unsigned long flags;
        struct dma_mapping *mapping, *prev;
 
        spin_lock_irqsave (dma_mappings_lock, flags);
@@ -622,7 +622,7 @@ static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
 static inline void
 free_dma_mapping (struct dma_mapping *mapping)
 {
-       int flags;
+       unsigned long flags;
 
        free_mb_sram (mapping->mb_sram_addr, mapping->size);
 
index a0b46695f186f03921a7a09b66cde5af0bf5bfa8..f4d1a4d3cdc231696e55802039541e5b024b3c76 100644 (file)
@@ -51,7 +51,7 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
        if (mach_tick)
          mach_tick ();
 
-       do_timer (regs);
+       do_timer (1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
index efe249e7d6b37c8cc8ffbcdf946cdfc1765a66ef..b87a19f0d584910f2c0438308d007c5515968b3f 100644 (file)
@@ -85,6 +85,9 @@ config ARCH_MAY_HAVE_PC_FDC
        bool
        default y
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 config DMI
        bool
        default y
@@ -168,6 +171,7 @@ config X86_GOOD_APIC
 
 config MICROCODE
        tristate "/dev/cpu/microcode - Intel CPU microcode support"
+       select FW_LOADER
        ---help---
          If you say Y here the 'File systems' section, you will be
          able to update the microcode on Intel processors. You will
@@ -183,6 +187,11 @@ config MICROCODE
          If you use modprobe or kmod you may also want to add the line
          'alias char-major-10-184 microcode' to your /etc/modules.conf file.
 
+config MICROCODE_OLD_INTERFACE
+       bool
+       depends on MICROCODE
+       default y
+
 config X86_MSR
        tristate "/dev/cpu/*/msr - Model-specific register support"
        help
@@ -358,6 +367,10 @@ config ARCH_FLATMEM_ENABLE
 
 source "mm/Kconfig"
 
+config MEMORY_HOTPLUG_RESERVE
+       def_bool y
+       depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
+
 config HAVE_ARCH_EARLY_PFN_TO_NID
        def_bool y
        depends on NUMA
index 647610ecb5802b39e5e3e09b9e649381acb6a36d..4844b543bed0b8c4d697f64910ec7c550c922a11 100644 (file)
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-git5
-# Tue Sep 26 09:30:47 2006
+# Linux kernel version: 2.6.18-git7
+# Wed Sep 27 21:53:10 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
 CONFIG_X86=y
+CONFIG_ZONE_DMA32=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_SEMAPHORE_SLEEPERS=y
@@ -179,6 +180,7 @@ CONFIG_GENERIC_PENDING_IRQ=y
 CONFIG_PM=y
 # CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
 CONFIG_SOFTWARE_SUSPEND=y
 CONFIG_PM_STD_PARTITION=""
 CONFIG_SUSPEND_SMP=y
@@ -251,6 +253,7 @@ CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_MSI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -1458,6 +1461,7 @@ CONFIG_KPROBES=y
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_KERNEL=y
index b0e82c7947dc8ee3662a829ae1e0eec152c0421c..f280d3665f4bed8fa07513078f39113369814354 100644 (file)
@@ -648,7 +648,7 @@ sys32_pause(void)
 }
 
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 struct sysctl_ia32 {
        unsigned int    name;
        int             nlen;
index c0af3828df4579da916aef68445ea5a8d255580a..b3f0908668ece23c11fc4d42675f011aab808821 100644 (file)
@@ -162,59 +162,14 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
        return -1UL;            
 } 
 
-/* 
- * Free bootmem based on the e820 table for a node.
- */
-void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end)
-{
-       int i;
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i]; 
-               unsigned long last, addr;
-
-               if (ei->type != E820_RAM || 
-                   ei->addr+ei->size <= start || 
-                   ei->addr >= end)
-                       continue;
-
-               addr = round_up(ei->addr, PAGE_SIZE);
-               if (addr < start) 
-                       addr = start;
-
-               last = round_down(ei->addr + ei->size, PAGE_SIZE); 
-               if (last >= end)
-                       last = end; 
-
-               if (last > addr && last-addr >= PAGE_SIZE)
-                       free_bootmem_node(pgdat, addr, last-addr);
-       }
-}
-
 /*
  * Find the highest page frame number we have available
  */
 unsigned long __init e820_end_of_ram(void)
 {
-       int i;
        unsigned long end_pfn = 0;
+       end_pfn = find_max_pfn_with_active_regions();
        
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i]; 
-               unsigned long start, end;
-
-               start = round_up(ei->addr, PAGE_SIZE); 
-               end = round_down(ei->addr + ei->size, PAGE_SIZE); 
-               if (start >= end)
-                       continue;
-               if (ei->type == E820_RAM) { 
-               if (end > end_pfn<<PAGE_SHIFT)
-                       end_pfn = end>>PAGE_SHIFT;
-               } else { 
-                       if (end > end_pfn_map<<PAGE_SHIFT) 
-                               end_pfn_map = end>>PAGE_SHIFT;
-               } 
-       }
-
        if (end_pfn > end_pfn_map) 
                end_pfn_map = end_pfn;
        if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
@@ -224,43 +179,10 @@ unsigned long __init e820_end_of_ram(void)
        if (end_pfn > end_pfn_map) 
                end_pfn = end_pfn_map; 
 
+       printk("end_pfn_map = %lu\n", end_pfn_map);
        return end_pfn; 
 }
 
-/* 
- * Compute how much memory is missing in a range.
- * Unlike the other functions in this file the arguments are in page numbers.
- */
-unsigned long __init
-e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
-{
-       unsigned long ram = 0;
-       unsigned long start = start_pfn << PAGE_SHIFT;
-       unsigned long end = end_pfn << PAGE_SHIFT;
-       int i;
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i];
-               unsigned long last, addr;
-
-               if (ei->type != E820_RAM ||
-                   ei->addr+ei->size <= start ||
-                   ei->addr >= end)
-                       continue;
-
-               addr = round_up(ei->addr, PAGE_SIZE);
-               if (addr < start)
-                       addr = start;
-
-               last = round_down(ei->addr + ei->size, PAGE_SIZE);
-               if (last >= end)
-                       last = end;
-
-               if (last > addr)
-                       ram += last - addr;
-       }
-       return ((end - start) - ram) >> PAGE_SHIFT;
-}
-
 /*
  * Mark e820 reserved areas as busy for the resource manager.
  */
@@ -342,6 +264,49 @@ void __init e820_mark_nosave_regions(void)
        }
 }
 
+/* Walk the e820 map and register active regions within a node */
+void __init
+e820_register_active_regions(int nid, unsigned long start_pfn,
+                                                       unsigned long end_pfn)
+{
+       int i;
+       unsigned long ei_startpfn, ei_endpfn;
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
+               ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE)
+                                                               >> PAGE_SHIFT;
+
+               /* Skip map entries smaller than a page */
+               if (ei_startpfn > ei_endpfn)
+                       continue;
+
+               /* Check if end_pfn_map should be updated */
+               if (ei->type != E820_RAM && ei_endpfn > end_pfn_map)
+                       end_pfn_map = ei_endpfn;
+
+               /* Skip if map is outside the node */
+               if (ei->type != E820_RAM ||
+                               ei_endpfn <= start_pfn ||
+                               ei_startpfn >= end_pfn)
+                       continue;
+
+               /* Check for overlaps */
+               if (ei_startpfn < start_pfn)
+                       ei_startpfn = start_pfn;
+               if (ei_endpfn > end_pfn)
+                       ei_endpfn = end_pfn;
+
+               /* Obey end_user_pfn to save on memmap */
+               if (ei_startpfn >= end_user_pfn)
+                       continue;
+               if (ei_endpfn > end_user_pfn)
+                       ei_endpfn = end_user_pfn;
+
+               add_active_range(nid, ei_startpfn, ei_endpfn);
+       }
+}
+
 /* 
  * Add a memory region to the kernel e820 map.
  */ 
index 20e88f4b564b6d8c31604c8c5c50f71da6a7ac0e..b8d53dfa9931730a39409e2bb7c8048d6c6070cd 100644 (file)
@@ -152,6 +152,21 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
        }
 }
 
+static int bad_ioapic(unsigned long address)
+{
+       if (nr_ioapics >= MAX_IO_APICS) {
+               printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+                       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
+               panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+       }
+       if (!address) {
+               printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+                       " found in table, skipping!\n");
+               return 1;
+       }
+       return 0;
+}
+
 static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
 {
        if (!(m->mpc_flags & MPC_APIC_USABLE))
@@ -159,16 +174,10 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
 
        printk("I/O APIC #%d at 0x%X.\n",
                m->mpc_apicid, m->mpc_apicaddr);
-       if (nr_ioapics >= MAX_IO_APICS) {
-               printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
-                       MAX_IO_APICS, nr_ioapics);
-               panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
-       }
-       if (!m->mpc_apicaddr) {
-               printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
-                       " found in MP table, skipping!\n");
+
+       if (bad_ioapic(m->mpc_apicaddr))
                return;
-       }
+
        mp_ioapics[nr_ioapics] = *m;
        nr_ioapics++;
 }
@@ -647,16 +656,8 @@ void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
 {
        int idx = 0;
 
-       if (nr_ioapics >= MAX_IO_APICS) {
-               printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
-                       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
-               panic("Recompile kernel with bigger MAX_IO_APICS!\n");
-       }
-       if (!address) {
-               printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
-                       " found in MADT table, skipping!\n");
+       if (bad_ioapic(address))
                return;
-       }
 
        idx = nr_ioapics++;
 
index 4d6fb047952e8abec336175d3bc5abe12dc76e76..7af9cb3e2d99a8e71e54d89c170245580b2d470e 100644 (file)
 #include <asm/mce.h>
 #include <asm/intel_arch_perfmon.h>
 
+int unknown_nmi_panic;
+int nmi_watchdog_enabled;
+int panic_on_unrecovered_nmi;
+
 /* perfctr_nmi_owner tracks the ownership of the perfctr registers:
  * evtsel_nmi_owner tracks the ownership of the event selection
  * - different performance counters/ event selection may be reserved for
index 4dcb671bd19fa760f81dc7d22f05a3eecf7c36a4..f8d857453f8afaf5fc839060cf1ad07dc69d13dc 100644 (file)
@@ -170,8 +170,20 @@ void dma_free_coherent(struct device *dev, size_t size,
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
+static int forbid_dac __read_mostly;
+
 int dma_supported(struct device *dev, u64 mask)
 {
+#ifdef CONFIG_PCI
+       if (mask > 0xffffffff && forbid_dac > 0) {
+
+
+
+               printk(KERN_INFO "PCI: Disallowing DAC for device %s\n", dev->bus_id);
+               return 0;
+       }
+#endif
+
        if (dma_ops->dma_supported)
                return dma_ops->dma_supported(dev, mask);
 
@@ -231,57 +243,64 @@ EXPORT_SYMBOL(dma_set_mask);
    allowed  overwrite iommu off workarounds for specific chipsets.
    soft         Use software bounce buffering (default for Intel machines)
    noaperture Don't touch the aperture for AGP.
+   allowdac Allow DMA >4GB
+   nodac    Forbid DMA >4GB
+   panic    Force panic when IOMMU overflows
 */
 __init int iommu_setup(char *p)
 {
-    iommu_merge = 1;
+       iommu_merge = 1;
 
        if (!p)
                return -EINVAL;
 
-    while (*p) {
-           if (!strncmp(p,"off",3))
-                   no_iommu = 1;
-           /* gart_parse_options has more force support */
-           if (!strncmp(p,"force",5))
-                   force_iommu = 1;
-           if (!strncmp(p,"noforce",7)) {
-                   iommu_merge = 0;
-                   force_iommu = 0;
-           }
-
-           if (!strncmp(p, "biomerge",8)) {
-                   iommu_bio_merge = 4096;
-                   iommu_merge = 1;
-                   force_iommu = 1;
-           }
-           if (!strncmp(p, "panic",5))
-                   panic_on_overflow = 1;
-           if (!strncmp(p, "nopanic",7))
-                   panic_on_overflow = 0;
-           if (!strncmp(p, "merge",5)) {
-                   iommu_merge = 1;
-                   force_iommu = 1;
-           }
-           if (!strncmp(p, "nomerge",7))
-                   iommu_merge = 0;
-           if (!strncmp(p, "forcesac",8))
-                   iommu_sac_force = 1;
+       while (*p) {
+               if (!strncmp(p,"off",3))
+                       no_iommu = 1;
+               /* gart_parse_options has more force support */
+               if (!strncmp(p,"force",5))
+                       force_iommu = 1;
+               if (!strncmp(p,"noforce",7)) {
+                       iommu_merge = 0;
+                       force_iommu = 0;
+               }
+
+               if (!strncmp(p, "biomerge",8)) {
+                       iommu_bio_merge = 4096;
+                       iommu_merge = 1;
+                       force_iommu = 1;
+               }
+               if (!strncmp(p, "panic",5))
+                       panic_on_overflow = 1;
+               if (!strncmp(p, "nopanic",7))
+                       panic_on_overflow = 0;
+               if (!strncmp(p, "merge",5)) {
+                       iommu_merge = 1;
+                       force_iommu = 1;
+               }
+               if (!strncmp(p, "nomerge",7))
+                       iommu_merge = 0;
+               if (!strncmp(p, "forcesac",8))
+                       iommu_sac_force = 1;
+               if (!strncmp(p, "allowdac", 8))
+                       forbid_dac = 0;
+               if (!strncmp(p, "nodac", 5))
+                       forbid_dac = -1;
 
 #ifdef CONFIG_SWIOTLB
-           if (!strncmp(p, "soft",4))
-                   swiotlb = 1;
+               if (!strncmp(p, "soft",4))
+                       swiotlb = 1;
 #endif
 
 #ifdef CONFIG_IOMMU
-           gart_parse_options(p);
+               gart_parse_options(p);
 #endif
 
-           p += strcspn(p, ",");
-           if (*p == ',')
-                   ++p;
-    }
-    return 0;
+               p += strcspn(p, ",");
+               if (*p == ',')
+                       ++p;
+       }
+       return 0;
 }
 early_param("iommu", iommu_setup);
 
index 6a55f87ba97f917ed2814bc3c11c3f21a3ad096b..697f0aa794b960a663b15ee09e161f86890119ab 100644 (file)
@@ -3,7 +3,8 @@
 #include <linux/pci.h>
 #include <linux/cache.h>
 #include <linux/module.h>
-#include <asm/dma-mapping.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/proto.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
index f98e48cae6da08f4386765f0094bbe9c98545a08..fc944b5e8f4a6050612a0c9220c713e2f47d3a51 100644 (file)
@@ -123,9 +123,6 @@ struct resource standard_io_resources[] = {
                .flags = IORESOURCE_BUSY | IORESOURCE_IO }
 };
 
-#define STANDARD_IO_RESOURCES \
-       (sizeof standard_io_resources / sizeof standard_io_resources[0])
-
 #define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
 
 struct resource data_resource = {
@@ -172,9 +169,6 @@ static struct resource adapter_rom_resources[] = {
                .flags = IORESOURCE_ROM }
 };
 
-#define ADAPTER_ROM_RESOURCES \
-       (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
-
 static struct resource video_rom_resource = {
        .name = "Video ROM",
        .start = 0xc0000,
@@ -245,7 +239,8 @@ static void __init probe_roms(void)
        }
 
        /* check for adapter roms on 2k boundaries */
-       for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
+       for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper;
+            start += 2048) {
                rom = isa_bus_to_virt(start);
                if (!romsignature(rom))
                        continue;
@@ -292,7 +287,8 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
        if (bootmap == -1L)
                panic("Cannot find bootmem map of size %ld\n",bootmap_size);
        bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
-       e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+       e820_register_active_regions(0, start_pfn, end_pfn);
+       free_bootmem_with_active_regions(0, end_pfn);
        reserve_bootmem(bootmap, bootmap_size);
 } 
 #endif
@@ -384,6 +380,7 @@ void __init setup_arch(char **cmdline_p)
 
        finish_e820_parsing();
 
+       e820_register_active_regions(0, 0, -1UL);
        /*
         * partially used pages are not usable - thus
         * we are rounding upwards:
@@ -414,6 +411,9 @@ void __init setup_arch(char **cmdline_p)
        max_pfn = end_pfn;
        high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
 
+       /* Remove active ranges so rediscovery with NUMA-awareness happens */
+       remove_all_active_ranges();
+
 #ifdef CONFIG_ACPI_NUMA
        /*
         * Parse SRAT to discover nodes.
@@ -532,7 +532,7 @@ void __init setup_arch(char **cmdline_p)
        {
        unsigned i;
        /* request I/O space for devices used on all i[345]86 PCs */
-       for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+       for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
                request_resource(&ioport_resource, &standard_io_resources[i]);
        }
 
index 1c255ee76e7c81870768f54adc9a5fe149dc0239..557e92af7beabdf84b58d265ecda54bb5dbf4f58 100644 (file)
@@ -77,7 +77,6 @@ unsigned long long monotonic_base;
 struct vxtime_data __vxtime __section_vxtime;  /* for vsyscalls */
 
 volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
-unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
 struct timespec __xtime __section_xtime;
 struct timezone __sys_tz __section_sys_tz;
 
@@ -119,7 +118,7 @@ unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
 
 void do_gettimeofday(struct timeval *tv)
 {
-       unsigned long seq, t;
+       unsigned long seq;
        unsigned int sec, usec;
 
        do {
@@ -136,10 +135,7 @@ void do_gettimeofday(struct timeval *tv)
                   be found. Note when you fix it here you need to do the same
                   in arch/x86_64/kernel/vsyscall.c and export all needed
                   variables in vmlinux.lds. -AK */ 
-
-               t = (jiffies - wall_jiffies) * USEC_PER_TICK +
-                       do_gettimeoffset();
-               usec += t;
+               usec += do_gettimeoffset();
 
        } while (read_seqretry(&xtime_lock, seq));
 
@@ -165,8 +161,7 @@ int do_settimeofday(struct timespec *tv)
 
        write_seqlock_irq(&xtime_lock);
 
-       nsec -= do_gettimeoffset() * NSEC_PER_USEC +
-               (jiffies - wall_jiffies) * NSEC_PER_TICK;
+       nsec -= do_gettimeoffset() * NSEC_PER_USEC;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -415,16 +410,16 @@ void main_timer_handler(struct pt_regs *regs)
                                (((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
        }
 
-       if (lost > 0) {
+       if (lost > 0)
                handle_lost_ticks(lost, regs);
-               jiffies += lost;
-       }
+       else
+               lost = 0;
 
 /*
  * Do the timer stuff.
  */
 
-       do_timer(regs);
+       do_timer(lost + 1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
@@ -1071,7 +1066,6 @@ static int timer_resume(struct sys_device *dev)
                vxtime.last_tsc = get_cycles_sync();
        write_sequnlock_irqrestore(&xtime_lock,flags);
        jiffies += sleep_length;
-       wall_jiffies += sleep_length;
        monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
        touch_softlockup_watchdog();
        return 0;
index d0564f1bcb0b9aa62a42919bcbeb24f8c2725397..b9df2ab6529fc8286b00f41d2081d393bbb2b444 100644 (file)
@@ -67,13 +67,6 @@ SECTIONS
 
   _edata = .;                  /* End of data section */
 
-  __bss_start = .;             /* BSS */
-  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
-       *(.bss.page_aligned)    
-       *(.bss)
-       }
-  __bss_stop = .;
-
   . = ALIGN(PAGE_SIZE);
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
@@ -108,9 +101,6 @@ SECTIONS
   .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
   vgetcpu_mode = VVIRT(.vgetcpu_mode);
 
-  .wall_jiffies : AT(VLOAD(.wall_jiffies)) { *(.wall_jiffies) }
-  wall_jiffies = VVIRT(.wall_jiffies);
-
   .sys_tz : AT(VLOAD(.sys_tz)) { *(.sys_tz) }
   sys_tz = VVIRT(.sys_tz);
 
@@ -229,6 +219,13 @@ SECTIONS
   . = ALIGN(4096);
   __nosave_end = .;
 
+  __bss_start = .;             /* BSS */
+  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+       *(.bss.page_aligned)
+       *(.bss)
+       }
+  __bss_stop = .;
+
   _end = . ;
 
   /* Sections to be discarded */
index ac48c3857ddb2164b34f857e6fe659b5b154b9b3..a98b460af6a1f600ebc2153490ecd4706700d08e 100644 (file)
@@ -66,8 +66,7 @@ static __always_inline void do_vgettimeofday(struct timeval * tv)
                sequence = read_seqbegin(&__xtime_lock);
                
                sec = __xtime.tv_sec;
-               usec = (__xtime.tv_nsec / 1000) +
-                       (__jiffies - __wall_jiffies) * (1000000 / HZ);
+               usec = __xtime.tv_nsec / 1000;
 
                if (__vxtime.mode != VXTIME_HPET) {
                        t = get_cycles_sync();
@@ -155,8 +154,8 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
           We do this here because otherwise user space would do it on
           its own in a likely inferior way (no access to jiffies).
           If you don't like it pass NULL. */
-       if (tcache && tcache->t0 == (j = __jiffies)) {
-               p = tcache->t1;
+       if (tcache && tcache->blob[0] == (j = __jiffies)) {
+               p = tcache->blob[1];
        } else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
                /* Load per CPU data from RDTSCP */
                rdtscp(dummy, dummy, p);
@@ -165,8 +164,8 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
                asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
        }
        if (tcache) {
-               tcache->t0 = j;
-               tcache->t1 = p;
+               tcache->blob[0] = j;
+               tcache->blob[1] = p;
        }
        if (cpu)
                *cpu = p & 0xfff;
index 1a17b0733ab5d38ad81ccdf4263e2d58571d9e24..3751b4788e288748112c05df0121a1186aac5fab 100644 (file)
@@ -244,7 +244,7 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
 
 int unhandled_signal(struct task_struct *tsk, int sig)
 {
-       if (tsk->pid == 1)
+       if (is_init(tsk))
                return 1;
        if (tsk->ptrace & PT_PTRACED)
                return 0;
@@ -464,7 +464,7 @@ good_area:
                case PF_PROT:           /* read, present */
                        goto bad_area;
                case 0:                 /* read, not present */
-                       if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                       if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                                goto bad_area;
        }
 
@@ -580,7 +580,7 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) { 
+       if (is_init(current)) {
                yield();
                goto again;
        }
index 1e4669fa5734fd8a36dfcc59070afb2cad2a4458..19c72520a86876a616becaf31ab3d72f73e8bb3f 100644 (file)
@@ -403,69 +403,15 @@ void __cpuinit zap_low_mappings(int cpu)
        __flush_tlb_all();
 }
 
-/* Compute zone sizes for the DMA and DMA32 zones in a node. */
-__init void
-size_zones(unsigned long *z, unsigned long *h,
-          unsigned long start_pfn, unsigned long end_pfn)
-{
-       int i;
-       unsigned long w;
-
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               z[i] = 0;
-
-       if (start_pfn < MAX_DMA_PFN)
-               z[ZONE_DMA] = MAX_DMA_PFN - start_pfn;
-       if (start_pfn < MAX_DMA32_PFN) {
-               unsigned long dma32_pfn = MAX_DMA32_PFN;
-               if (dma32_pfn > end_pfn)
-                       dma32_pfn = end_pfn;
-               z[ZONE_DMA32] = dma32_pfn - start_pfn;
-       }
-       z[ZONE_NORMAL] = end_pfn - start_pfn;
-
-       /* Remove lower zones from higher ones. */
-       w = 0;
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               if (z[i])
-                       z[i] -= w;
-               w += z[i];
-       }
-
-       /* Compute holes */
-       w = start_pfn;
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               unsigned long s = w;
-               w += z[i];
-               h[i] = e820_hole_size(s, w);
-       }
-
-       /* Add the space pace needed for mem_map to the holes too. */
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE;
-
-       /* The 16MB DMA zone has the kernel and other misc mappings.
-          Account them too */
-       if (h[ZONE_DMA]) {
-               h[ZONE_DMA] += dma_reserve;
-               if (h[ZONE_DMA] >= z[ZONE_DMA]) {
-                       printk(KERN_WARNING
-                               "Kernel too large and filling up ZONE_DMA?\n");
-                       h[ZONE_DMA] = z[ZONE_DMA];
-               }
-       }
-}
-
 #ifndef CONFIG_NUMA
 void __init paging_init(void)
 {
-       unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
-
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {MAX_DMA_PFN,
+                                                       MAX_DMA32_PFN,
+                                                       end_pfn};
        memory_present(0, 0, end_pfn);
        sparse_init();
-       size_zones(zones, holes, 0, end_pfn);
-       free_area_init_node(0, NODE_DATA(0), zones,
-                           __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
+       free_area_init_nodes(max_zone_pfns);
 }
 #endif
 
@@ -516,19 +462,6 @@ void online_page(struct page *page)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-/*
- * XXX: memory_add_physaddr_to_nid() is to find node id from physical address
- *     via probe interface of sysfs. If acpi notifies hot-add event, then it
- *     can tell node id by searching dsdt. But, probe interface doesn't have
- *     node id. So, return 0 as node id at this time.
- */
-#ifdef CONFIG_NUMA
-int memory_add_physaddr_to_nid(u64 start)
-{
-       return 0;
-}
-#endif
-
 /*
  * Memory is added always to NORMAL zone. This means you will never get
  * additional DMA/DMA32 memory.
@@ -541,12 +474,12 @@ int arch_add_memory(int nid, u64 start, u64 size)
        unsigned long nr_pages = size >> PAGE_SHIFT;
        int ret;
 
+       init_memory_mapping(start, (start + size -1));
+
        ret = __add_pages(zone, start_pfn, nr_pages);
        if (ret)
                goto error;
 
-       init_memory_mapping(start, (start + size -1));
-
        return ret;
 error:
        printk("%s: Problem encountered in __add_pages!\n", __func__);
@@ -560,7 +493,24 @@ int remove_memory(u64 start, u64 size)
 }
 EXPORT_SYMBOL_GPL(remove_memory);
 
-#else /* CONFIG_MEMORY_HOTPLUG */
+#ifndef CONFIG_ACPI_NUMA
+int memory_add_physaddr_to_nid(u64 start)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
+
+#ifndef CONFIG_ACPI_NUMA
+int memory_add_physaddr_to_nid(u64 start)
+{
+       return 0;
+}
+#endif
+
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
 /*
  * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
  * just online the pages.
@@ -586,7 +536,7 @@ int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
        }
        return err;
 }
-#endif /* CONFIG_MEMORY_HOTPLUG */
+#endif
 
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
                         kcore_vsyscall;
@@ -608,7 +558,8 @@ void __init mem_init(void)
 #else
        totalram_pages = free_all_bootmem();
 #endif
-       reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
+       reservedpages = end_pfn - totalram_pages -
+                                       absent_pages_in_range(0, end_pfn);
 
        after_bootmem = 1;
 
@@ -708,8 +659,10 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
 #else                  
        reserve_bootmem(phys, len);    
 #endif
-       if (phys+len <= MAX_DMA_PFN*PAGE_SIZE)
+       if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
                dma_reserve += len / PAGE_SIZE;
+               set_dma_reserve(dma_reserve);
+       }
 }
 
 int kern_addr_valid(unsigned long addr) 
index 45d7d823c3b85c91dab6740e30278fd0caa628ae..c6e5e8d401a490ab4fe25cf0a850f8cbc84d76a2 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
-#include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 #include <asm/proto.h>
 
 #define ISA_START_ADDRESS      0xa0000
 #define ISA_END_ADDRESS                0x100000
 
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-       unsigned long pfn;
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       if (address >= end)
-               BUG();
-       pfn = phys_addr >> PAGE_SHIFT;
-       do {
-               if (!pte_none(*pte)) {
-                       printk("remap_area_pte: page already exists\n");
-                       BUG();
-               }
-               set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW | 
-                                       _PAGE_GLOBAL | _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
-               address += PAGE_SIZE;
-               pfn++;
-               pte++;
-       } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PUD_MASK;
-       end = address + size;
-       if (end > PUD_SIZE)
-               end = PUD_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pte_t * pte = pte_alloc_kernel(pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static inline int remap_area_pud(pud_t * pud, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       phys_addr -= address;
-       if (address >= end)
-               BUG();
-       do {
-               pmd_t * pmd = pmd_alloc(&init_mm, pud, address);
-               if (!pmd)
-                       return -ENOMEM;
-               remap_area_pmd(pmd, address, end - address, address + phys_addr, flags);
-               address = (address + PUD_SIZE) & PUD_MASK;
-               pud++;
-       } while (address && (address < end));
-       return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                                unsigned long size, unsigned long flags)
-{
-       int error;
-       pgd_t *pgd;
-       unsigned long end = address + size;
-
-       phys_addr -= address;
-       pgd = pgd_offset_k(address);
-       flush_cache_all();
-       if (address >= end)
-               BUG();
-       do {
-               pud_t *pud;
-               pud = pud_alloc(&init_mm, pgd, address);
-               error = -ENOMEM;
-               if (!pud)
-                       break;
-               if (remap_area_pud(pud, address, end - address,
-                                        phys_addr + address, flags))
-                       break;
-               error = 0;
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               pgd++;
-       } while (address && (address < end));
-       flush_tlb_all();
-       return error;
-}
-
 /*
  * Fix up the linear direct mapping of the kernel to avoid cache attribute
  * conflicts.
@@ -165,6 +64,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        void * addr;
        struct vm_struct * area;
        unsigned long offset, last_addr;
+       pgprot_t pgprot;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
@@ -194,6 +94,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
        }
 #endif
 
+       pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_GLOBAL
+                         | _PAGE_DIRTY | _PAGE_ACCESSED | flags);
        /*
         * Mappings have to be page-aligned
         */
@@ -209,7 +111,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
                return NULL;
        area->phys_addr = phys_addr;
        addr = area->addr;
-       if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+       if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+                              phys_addr, pgprot)) {
                remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
                return NULL;
        }
index 5cf594f9230d49e724bf1504177c6403f6b7a01d..b5b8dba28b4efa43000510ad924a83cc97a95fd4 100644 (file)
@@ -149,6 +149,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
                
                nodes[nodeid].start = base; 
                nodes[nodeid].end = limit;
+               e820_register_active_regions(nodeid,
+                               nodes[nodeid].start >> PAGE_SHIFT,
+                               nodes[nodeid].end >> PAGE_SHIFT);
 
                prevbase = base;
 
index 322bf45fc36ac8c55f7bdb070904082d2fba8b65..829a008bd39b75a95eec6dfb66a46d4497459a48 100644 (file)
@@ -161,7 +161,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
                                         bootmap_start >> PAGE_SHIFT, 
                                         start_pfn, end_pfn); 
 
-       e820_bootmem_free(NODE_DATA(nodeid), start, end);
+       free_bootmem_with_active_regions(nodeid, end);
 
        reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); 
        reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
@@ -175,13 +175,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
 void __init setup_node_zones(int nodeid)
 { 
        unsigned long start_pfn, end_pfn, memmapsize, limit;
-       unsigned long zones[MAX_NR_ZONES];
-       unsigned long holes[MAX_NR_ZONES];
 
        start_pfn = node_start_pfn(nodeid);
        end_pfn = node_end_pfn(nodeid);
 
-       Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
+       Dprintk(KERN_INFO "Setting up memmap for node %d %lx-%lx\n",
                nodeid, start_pfn, end_pfn);
 
        /* Try to allocate mem_map at end to not fill up precious <4GB
@@ -195,10 +193,6 @@ void __init setup_node_zones(int nodeid)
                                round_down(limit - memmapsize, PAGE_SIZE), 
                                limit);
 #endif
-
-       size_zones(zones, holes, start_pfn, end_pfn);
-       free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
-                           start_pfn, holes);
 } 
 
 void __init numa_init_array(void)
@@ -259,8 +253,11 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
                printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
                return -1;
        }
-       for_each_online_node(i)
+       for_each_online_node(i) {
+               e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
+                                               nodes[i].end >> PAGE_SHIFT);
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+       }
        numa_init_array();
        return 0;
 }
@@ -299,6 +296,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
        for (i = 0; i < NR_CPUS; i++)
                numa_set_node(i, 0);
        node_to_cpumask[0] = cpumask_of_cpu(0);
+       e820_register_active_regions(0, start_pfn, end_pfn);
        setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
 }
 
@@ -340,12 +338,17 @@ static void __init arch_sparse_init(void)
 void __init paging_init(void)
 { 
        int i;
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = { MAX_DMA_PFN,
+               MAX_DMA32_PFN,
+               end_pfn};
 
        arch_sparse_init();
 
        for_each_online_node(i) {
                setup_node_zones(i); 
        }
+
+       free_area_init_nodes(max_zone_pfns);
 } 
 
 static __init int numa_setup(char *opt)
index ca10701e7a905a36f88b604a5b2c3ed280112d6b..3cc0544e25f5a8569af1a727c3f819b252fe3635 100644 (file)
 
 int acpi_numa __initdata;
 
-#if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
-       defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \
-               && !defined(CONFIG_MEMORY_HOTPLUG)
-#define RESERVE_HOTADD 1
-#endif
-
 static struct acpi_table_slit *acpi_slit;
 
 static nodemask_t nodes_parsed __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
-static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
+static struct bootnode nodes_add[MAX_NUMNODES];
 static int found_add_area __initdata;
 int hotadd_percent __initdata = 0;
-#ifndef RESERVE_HOTADD
-#define hotadd_percent 0       /* Ignore all settings */
-#endif
 
 /* Too small nodes confuse the VM badly. Usually they result
    from BIOS bugs. */
@@ -93,6 +84,7 @@ static __init void bad_srat(void)
                apicid_to_node[i] = NUMA_NO_NODE;
        for (i = 0; i < MAX_NUMNODES; i++)
                nodes_add[i].start = nodes[i].end = 0;
+       remove_all_active_ranges();
 }
 
 static __init inline int srat_disabled(void)
@@ -159,7 +151,7 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
               pxm, pa->apic_id, node);
 }
 
-#ifdef RESERVE_HOTADD
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
 /*
  * Protect against too large hotadd areas that would fill up memory.
  */
@@ -175,7 +167,7 @@ static int hotadd_enough_memory(struct bootnode *nd)
 
        if (mem < 0)
                return 0;
-       allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
+       allowed = (end_pfn - absent_pages_in_range(0, end_pfn)) * PAGE_SIZE;
        allowed = (allowed / 100) * hotadd_percent;
        if (allocated + mem > allowed) {
                unsigned long range;
@@ -202,15 +194,37 @@ static int hotadd_enough_memory(struct bootnode *nd)
        return 1;
 }
 
+static int update_end_of_memory(unsigned long end)
+{
+       found_add_area = 1;
+       if ((end >> PAGE_SHIFT) > end_pfn)
+               end_pfn = end >> PAGE_SHIFT;
+       return 1;
+}
+
+static inline int save_add_info(void)
+{
+       return hotadd_percent > 0;
+}
+#else
+int update_end_of_memory(unsigned long end) {return 0;}
+static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
+#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int save_add_info(void) {return 1;}
+#else
+static inline int save_add_info(void) {return 0;}
+#endif
+#endif
 /*
- * It is fine to add this area to the nodes data it will be used later
+ * Update nodes_add and decide if to include add are in the zone.
+ * Both SPARSE and RESERVE need nodes_add infomation.
  * This code supports one contigious hot add area per node.
  */
 static int reserve_hotadd(int node, unsigned long start, unsigned long end)
 {
        unsigned long s_pfn = start >> PAGE_SHIFT;
        unsigned long e_pfn = end >> PAGE_SHIFT;
-       int changed = 0;
+       int ret = 0, changed = 0;
        struct bootnode *nd = &nodes_add[node];
 
        /* I had some trouble with strange memory hotadd regions breaking
@@ -225,8 +239,10 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end)
        }
 
        /* This check might be a bit too strict, but I'm keeping it for now. */
-       if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) {
-               printk(KERN_ERR "SRAT: Hotplug area has existing memory\n");
+       if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) {
+               printk(KERN_ERR
+                       "SRAT: Hotplug area %lu -> %lu has existing memory\n",
+                       s_pfn, e_pfn);
                return -1;
        }
 
@@ -237,7 +253,6 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end)
 
        /* Looks good */
 
-       found_add_area = 1;
        if (nd->start == nd->end) {
                nd->start = start;
                nd->end = end;
@@ -255,14 +270,12 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end)
                        printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
        }
 
-       if ((nd->end >> PAGE_SHIFT) > end_pfn)
-               end_pfn = nd->end >> PAGE_SHIFT;
+       ret = update_end_of_memory(nd->end);
 
        if (changed)
                printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end);
-       return 0;
+       return ret;
 }
-#endif
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
 void __init
@@ -281,7 +294,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
        }
        if (ma->flags.enabled == 0)
                return;
-       if (ma->flags.hot_pluggable && hotadd_percent == 0)
+       if (ma->flags.hot_pluggable && !save_add_info())
                return;
        start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32);
        end = start + (ma->length_lo | ((u64)ma->length_hi << 32));
@@ -319,16 +332,18 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
 
        printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
               nd->start, nd->end);
+       e820_register_active_regions(node, nd->start >> PAGE_SHIFT,
+                                               nd->end >> PAGE_SHIFT);
+       push_node_boundaries(node, nd->start >> PAGE_SHIFT,
+                                               nd->end >> PAGE_SHIFT);
 
-#ifdef RESERVE_HOTADD
-       if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
+       if (ma->flags.hot_pluggable && !reserve_hotadd(node, start, end) < 0) {
                /* Ignore hotadd region. Undo damage */
                printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
                *nd = oldnode;
                if ((nd->start | nd->end) == 0)
                        node_clear(node, nodes_parsed);
        }
-#endif
 }
 
 /* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -343,13 +358,12 @@ static int nodes_cover_memory(void)
                unsigned long s = nodes[i].start >> PAGE_SHIFT;
                unsigned long e = nodes[i].end >> PAGE_SHIFT;
                pxmram += e - s;
-               pxmram -= e820_hole_size(s, e);
-               pxmram -= nodes_add[i].end - nodes_add[i].start;
+               pxmram -= absent_pages_in_range(s, e);
                if ((long)pxmram < 0)
                        pxmram = 0;
        }
 
-       e820ram = end_pfn - e820_hole_size(0, end_pfn);
+       e820ram = end_pfn - absent_pages_in_range(0, end_pfn);
        /* We seem to lose 3 pages somewhere. Allow a bit of slack. */
        if ((long)(e820ram - pxmram) >= 1*1024*1024) {
                printk(KERN_ERR
@@ -452,3 +466,16 @@ int __node_distance(int a, int b)
 }
 
 EXPORT_SYMBOL(__node_distance);
+
+int memory_add_physaddr_to_nid(u64 start)
+{
+       int i, ret = 0;
+
+       for_each_node(i)
+               if (nodes_add[i].start <= start && nodes_add[i].end > start)
+                       ret = i;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+
index 412ab32de391788de830fe5786adffe2ac3ca854..37347e36998723aaaf7803a3185cf9543cd9f805 100644 (file)
@@ -26,8 +26,6 @@
 #include <asm/platform.h>
 
 
-extern volatile unsigned long wall_jiffies;
-
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
@@ -110,7 +108,6 @@ int do_settimeofday(struct timespec *tv)
         */
        ccount = get_ccount();
        nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC;
-       nsec -= (jiffies - wall_jiffies) * CCOUNT_PER_JIFFY * CCOUNT_NSEC;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -129,7 +126,7 @@ EXPORT_SYMBOL(do_settimeofday);
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
-       unsigned long sec, usec, delta, lost, seq;
+       unsigned long sec, usec, delta, seq;
 
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
@@ -137,12 +134,9 @@ void do_gettimeofday(struct timeval *tv)
                delta = get_ccount() - last_ccount_stamp;
                sec = xtime.tv_sec;
                usec = (xtime.tv_nsec / NSEC_PER_USEC);
-
-               lost = jiffies - wall_jiffies;
-
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-       usec += lost * (1000000UL/HZ) + (delta * CCOUNT_NSEC) / NSEC_PER_USEC;
+       usec += (delta * CCOUNT_NSEC) / NSEC_PER_USEC;
        for (; usec >= 1000000; sec++, usec -= 1000000)
                ;
 
@@ -175,12 +169,11 @@ again:
 
                last_ccount_stamp = next;
                next += CCOUNT_PER_JIFFY;
-               do_timer (regs); /* Linux handler in kernel/timer.c */
+               do_timer (1); /* Linux handler in kernel/timer.c */
 
                if (ntp_synced() &&
                    xtime.tv_sec - last_rtc_update >= 659 &&
-                   abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
-                   jiffies - wall_jiffies == 1) {
+                   abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ) {
 
                        if (platform_set_rtc_time(xtime.tv_sec+1) == 0)
                                last_rtc_update = xtime.tv_sec+1;
index a945a33e85a129d0e268b1e20cf9a54710ec93c6..dd0dbec2e57e4f39b51ab7a73359a0117e638b48 100644 (file)
@@ -144,7 +144,7 @@ bad_area:
         */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
index d96164e602fea496c7b33b35d4e685261eef7647..15d64414bd6018e2394d3485ec6070730614eb5a 100644 (file)
@@ -201,7 +201,7 @@ static void dev_ip_addr(void *d, char *buf, char *bin_buf)
        struct net_device *dev = d;
        struct in_device *ip = dev->ip_ptr;
        struct in_ifaddr *in;
-       u32 addr;
+       __be32 addr;
 
        if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
                printk(KERN_WARNING "Device not assigned an IP address!\n");
index b6f5f0a79655a3de0125af945682f91bf92bc726..83766a6bdee264f3c3a8da74bfa95ada55097062 100644 (file)
@@ -1,6 +1,24 @@
 #
 # Block layer core configuration
 #
+config BLOCK
+       bool "Enable the block layer" if EMBEDDED
+       default y
+       help
+        This permits the block layer to be removed from the kernel if it's not
+        needed (on some embedded devices for example).  If this option is
+        disabled, then blockdev files will become unusable and some
+        filesystems (such as ext3) will become unavailable.
+
+        This option will also disable SCSI character devices and USB storage
+        since they make use of various block layer definitions and
+        facilities.
+
+        Say Y here unless you know you really don't want to mount disks and
+        suchlike.
+
+if BLOCK
+
 #XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64
 #for instance.
 config LBD
@@ -33,4 +51,6 @@ config LSF
 
          If unsure, say Y.
 
+endif
+
 source block/Kconfig.iosched
index 48d090e266fc5745be94af97ff8deb32c2726995..903f0d3b68520a94a5a76222b31c6860ba57de20 100644 (file)
@@ -1,3 +1,4 @@
+if BLOCK
 
 menu "IO Schedulers"
 
@@ -67,3 +68,5 @@ config DEFAULT_IOSCHED
        default "noop" if DEFAULT_NOOP
 
 endmenu
+
+endif
index c05de0e0037fe6f14f9e6f508bece1271568bb36..4b84d0d5947bc22cf8a94f91fb7c556b29ff571c 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the kernel block layer
 #
 
-obj- := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
+obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_IOSCHED_NOOP)     += noop-iosched.o
 obj-$(CONFIG_IOSCHED_AS)       += as-iosched.o
index 5da56d48fbd36473ba92fb346a91d06dbea148a1..50b95e4c1425b8ae3950451c146c020da4b0b146 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Anticipatory & deadline i/o scheduler.
  *
- *  Copyright (C) 2002 Jens Axboe <axboe@suse.de>
+ *  Copyright (C) 2002 Jens Axboe <axboe@kernel.dk>
  *                     Nick Piggin <nickpiggin@yahoo.com.au>
  *
  */
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/compiler.h>
-#include <linux/hash.h>
 #include <linux/rbtree.h>
 #include <linux/interrupt.h>
 
@@ -93,9 +92,8 @@ struct as_data {
        struct rb_root sort_list[2];
        struct list_head fifo_list[2];
 
-       struct as_rq *next_arq[2];      /* next in sort order */
+       struct request *next_rq[2];     /* next in sort order */
        sector_t last_sector[2];        /* last REQ_SYNC & REQ_ASYNC sectors */
-       struct hlist_head *hash;        /* request hash */
 
        unsigned long exit_prob;        /* probability a task will exit while
                                           being waited on */
@@ -115,7 +113,6 @@ struct as_data {
        int write_batch_count;          /* max # of reqs in a write batch */
        int current_write_count;        /* how many requests left this batch */
        int write_batch_idled;          /* has the write batch gone idle? */
-       mempool_t *arq_pool;
 
        enum anticipation_status antic_status;
        unsigned long antic_start;      /* jiffies: when it started */
@@ -133,8 +130,6 @@ struct as_data {
        unsigned long antic_expire;
 };
 
-#define list_entry_fifo(ptr)   list_entry((ptr), struct as_rq, fifo)
-
 /*
  * per-request data.
  */
@@ -150,40 +145,14 @@ enum arq_state {
        AS_RQ_POSTSCHED,        /* when they shouldn't be */
 };
 
-struct as_rq {
-       /*
-        * rbtree index, key is the starting offset
-        */
-       struct rb_node rb_node;
-       sector_t rb_key;
-
-       struct request *request;
-
-       struct io_context *io_context;  /* The submitting task */
-
-       /*
-        * request hash, key is the ending offset (for back merge lookup)
-        */
-       struct hlist_node hash;
-
-       /*
-        * expire fifo
-        */
-       struct list_head fifo;
-       unsigned long expires;
+#define RQ_IOC(rq)     ((struct io_context *) (rq)->elevator_private)
+#define RQ_STATE(rq)   ((enum arq_state)(rq)->elevator_private2)
+#define RQ_SET_STATE(rq, state)        ((rq)->elevator_private2 = (void *) state)
 
-       unsigned int is_sync;
-       enum arq_state state;
-};
-
-#define RQ_DATA(rq)    ((struct as_rq *) (rq)->elevator_private)
-
-static kmem_cache_t *arq_pool;
-
-static atomic_t ioc_count = ATOMIC_INIT(0);
+static DEFINE_PER_CPU(unsigned long, ioc_count);
 static struct completion *ioc_gone;
 
-static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
+static void as_move_to_dispatch(struct as_data *ad, struct request *rq);
 static void as_antic_stop(struct as_data *ad);
 
 /*
@@ -194,7 +163,8 @@ static void as_antic_stop(struct as_data *ad);
 static void free_as_io_context(struct as_io_context *aic)
 {
        kfree(aic);
-       if (atomic_dec_and_test(&ioc_count) && ioc_gone)
+       elv_ioc_count_dec(ioc_count);
+       if (ioc_gone && !elv_ioc_count_read(ioc_count))
                complete(ioc_gone);
 }
 
@@ -230,7 +200,7 @@ static struct as_io_context *alloc_as_io_context(void)
                ret->seek_total = 0;
                ret->seek_samples = 0;
                ret->seek_mean = 0;
-               atomic_inc(&ioc_count);
+               elv_ioc_count_inc(ioc_count);
        }
 
        return ret;
@@ -240,9 +210,9 @@ static struct as_io_context *alloc_as_io_context(void)
  * If the current task has no AS IO context then create one and initialise it.
  * Then take a ref on the task's io context and return it.
  */
-static struct io_context *as_get_io_context(void)
+static struct io_context *as_get_io_context(int node)
 {
-       struct io_context *ioc = get_io_context(GFP_ATOMIC);
+       struct io_context *ioc = get_io_context(GFP_ATOMIC, node);
        if (ioc && !ioc->aic) {
                ioc->aic = alloc_as_io_context();
                if (!ioc->aic) {
@@ -253,194 +223,43 @@ static struct io_context *as_get_io_context(void)
        return ioc;
 }
 
-static void as_put_io_context(struct as_rq *arq)
+static void as_put_io_context(struct request *rq)
 {
        struct as_io_context *aic;
 
-       if (unlikely(!arq->io_context))
+       if (unlikely(!RQ_IOC(rq)))
                return;
 
-       aic = arq->io_context->aic;
+       aic = RQ_IOC(rq)->aic;
 
-       if (arq->is_sync == REQ_SYNC && aic) {
+       if (rq_is_sync(rq) && aic) {
                spin_lock(&aic->lock);
                set_bit(AS_TASK_IORUNNING, &aic->state);
                aic->last_end_request = jiffies;
                spin_unlock(&aic->lock);
        }
 
-       put_io_context(arq->io_context);
-}
-
-/*
- * the back merge hash support functions
- */
-static const int as_hash_shift = 6;
-#define AS_HASH_BLOCK(sec)     ((sec) >> 3)
-#define AS_HASH_FN(sec)                (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift))
-#define AS_HASH_ENTRIES                (1 << as_hash_shift)
-#define rq_hash_key(rq)                ((rq)->sector + (rq)->nr_sectors)
-
-static inline void __as_del_arq_hash(struct as_rq *arq)
-{
-       hlist_del_init(&arq->hash);
-}
-
-static inline void as_del_arq_hash(struct as_rq *arq)
-{
-       if (!hlist_unhashed(&arq->hash))
-               __as_del_arq_hash(arq);
-}
-
-static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
-{
-       struct request *rq = arq->request;
-
-       BUG_ON(!hlist_unhashed(&arq->hash));
-
-       hlist_add_head(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]);
-}
-
-/*
- * move hot entry to front of chain
- */
-static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq)
-{
-       struct request *rq = arq->request;
-       struct hlist_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))];
-
-       if (hlist_unhashed(&arq->hash)) {
-               WARN_ON(1);
-               return;
-       }
-
-       if (&arq->hash != head->first) {
-               hlist_del(&arq->hash);
-               hlist_add_head(&arq->hash, head);
-       }
-}
-
-static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
-{
-       struct hlist_head *hash_list = &ad->hash[AS_HASH_FN(offset)];
-       struct hlist_node *entry, *next;
-       struct as_rq *arq;
-
-       hlist_for_each_entry_safe(arq, entry, next, hash_list, hash) {
-               struct request *__rq = arq->request;
-
-               BUG_ON(hlist_unhashed(&arq->hash));
-
-               if (!rq_mergeable(__rq)) {
-                       as_del_arq_hash(arq);
-                       continue;
-               }
-
-               if (rq_hash_key(__rq) == offset)
-                       return __rq;
-       }
-
-       return NULL;
+       put_io_context(RQ_IOC(rq));
 }
 
 /*
  * rb tree support functions
  */
-#define rb_entry_arq(node)     rb_entry((node), struct as_rq, rb_node)
-#define ARQ_RB_ROOT(ad, arq)   (&(ad)->sort_list[(arq)->is_sync])
-#define rq_rb_key(rq)          (rq)->sector
-
-/*
- * as_find_first_arq finds the first (lowest sector numbered) request
- * for the specified data_dir. Used to sweep back to the start of the disk
- * (1-way elevator) after we process the last (highest sector) request.
- */
-static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir)
-{
-       struct rb_node *n = ad->sort_list[data_dir].rb_node;
-
-       if (n == NULL)
-               return NULL;
-
-       for (;;) {
-               if (n->rb_left == NULL)
-                       return rb_entry_arq(n);
-
-               n = n->rb_left;
-       }
-}
-
-/*
- * Add the request to the rb tree if it is unique.  If there is an alias (an
- * existing request against the same sector), which can happen when using
- * direct IO, then return the alias.
- */
-static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
-{
-       struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node;
-       struct rb_node *parent = NULL;
-       struct as_rq *__arq;
-       struct request *rq = arq->request;
-
-       arq->rb_key = rq_rb_key(rq);
-
-       while (*p) {
-               parent = *p;
-               __arq = rb_entry_arq(parent);
-
-               if (arq->rb_key < __arq->rb_key)
-                       p = &(*p)->rb_left;
-               else if (arq->rb_key > __arq->rb_key)
-                       p = &(*p)->rb_right;
-               else
-                       return __arq;
-       }
-
-       rb_link_node(&arq->rb_node, parent, p);
-       rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
-
-       return NULL;
-}
+#define RQ_RB_ROOT(ad, rq)     (&(ad)->sort_list[rq_is_sync((rq))])
 
-static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+static void as_add_rq_rb(struct as_data *ad, struct request *rq)
 {
-       struct as_rq *alias;
+       struct request *alias;
 
-       while ((unlikely(alias = __as_add_arq_rb(ad, arq)))) {
+       while ((unlikely(alias = elv_rb_add(RQ_RB_ROOT(ad, rq), rq)))) {
                as_move_to_dispatch(ad, alias);
                as_antic_stop(ad);
        }
 }
 
-static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq)
-{
-       if (!RB_EMPTY_NODE(&arq->rb_node)) {
-               WARN_ON(1);
-               return;
-       }
-
-       rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
-       RB_CLEAR_NODE(&arq->rb_node);
-}
-
-static struct request *
-as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir)
+static inline void as_del_rq_rb(struct as_data *ad, struct request *rq)
 {
-       struct rb_node *n = ad->sort_list[data_dir].rb_node;
-       struct as_rq *arq;
-
-       while (n) {
-               arq = rb_entry_arq(n);
-
-               if (sector < arq->rb_key)
-                       n = n->rb_left;
-               else if (sector > arq->rb_key)
-                       n = n->rb_right;
-               else
-                       return arq->request;
-       }
-
-       return NULL;
+       elv_rb_del(RQ_RB_ROOT(ad, rq), rq);
 }
 
 /*
@@ -458,26 +277,26 @@ as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir)
  * as_choose_req selects the preferred one of two requests of the same data_dir
  * ignoring time - eg. timeouts, which is the job of as_dispatch_request
  */
-static struct as_rq *
-as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2)
+static struct request *
+as_choose_req(struct as_data *ad, struct request *rq1, struct request *rq2)
 {
        int data_dir;
        sector_t last, s1, s2, d1, d2;
        int r1_wrap=0, r2_wrap=0;       /* requests are behind the disk head */
        const sector_t maxback = MAXBACK;
 
-       if (arq1 == NULL || arq1 == arq2)
-               return arq2;
-       if (arq2 == NULL)
-               return arq1;
+       if (rq1 == NULL || rq1 == rq2)
+               return rq2;
+       if (rq2 == NULL)
+               return rq1;
 
-       data_dir = arq1->is_sync;
+       data_dir = rq_is_sync(rq1);
 
        last = ad->last_sector[data_dir];
-       s1 = arq1->request->sector;
-       s2 = arq2->request->sector;
+       s1 = rq1->sector;
+       s2 = rq2->sector;
 
-       BUG_ON(data_dir != arq2->is_sync);
+       BUG_ON(data_dir != rq_is_sync(rq2));
 
        /*
         * Strict one way elevator _except_ in the case where we allow
@@ -504,61 +323,58 @@ as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2)
 
        /* Found required data */
        if (!r1_wrap && r2_wrap)
-               return arq1;
+               return rq1;
        else if (!r2_wrap && r1_wrap)
-               return arq2;
+               return rq2;
        else if (r1_wrap && r2_wrap) {
                /* both behind the head */
                if (s1 <= s2)
-                       return arq1;
+                       return rq1;
                else
-                       return arq2;
+                       return rq2;
        }
 
        /* Both requests in front of the head */
        if (d1 < d2)
-               return arq1;
+               return rq1;
        else if (d2 < d1)
-               return arq2;
+               return rq2;
        else {
                if (s1 >= s2)
-                       return arq1;
+                       return rq1;
                else
-                       return arq2;
+                       return rq2;
        }
 }
 
 /*
- * as_find_next_arq finds the next request after @prev in elevator order.
+ * as_find_next_rq finds the next request after @prev in elevator order.
  * this with as_choose_req form the basis for how the scheduler chooses
  * what request to process next. Anticipation works on top of this.
  */
-static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last)
+static struct request *
+as_find_next_rq(struct as_data *ad, struct request *last)
 {
-       const int data_dir = last->is_sync;
-       struct as_rq *ret;
        struct rb_node *rbnext = rb_next(&last->rb_node);
        struct rb_node *rbprev = rb_prev(&last->rb_node);
-       struct as_rq *arq_next, *arq_prev;
+       struct request *next = NULL, *prev = NULL;
 
-       BUG_ON(!RB_EMPTY_NODE(&last->rb_node));
+       BUG_ON(RB_EMPTY_NODE(&last->rb_node));
 
        if (rbprev)
-               arq_prev = rb_entry_arq(rbprev);
-       else
-               arq_prev = NULL;
+               prev = rb_entry_rq(rbprev);
 
        if (rbnext)
-               arq_next = rb_entry_arq(rbnext);
+               next = rb_entry_rq(rbnext);
        else {
-               arq_next = as_find_first_arq(ad, data_dir);
-               if (arq_next == last)
-                       arq_next = NULL;
-       }
+               const int data_dir = rq_is_sync(last);
 
-       ret = as_choose_req(ad, arq_next, arq_prev);
+               rbnext = rb_first(&ad->sort_list[data_dir]);
+               if (rbnext && rbnext != &last->rb_node)
+                       next = rb_entry_rq(rbnext);
+       }
 
-       return ret;
+       return as_choose_req(ad, next, prev);
 }
 
 /*
@@ -712,8 +528,7 @@ static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic,
 static void as_update_iohist(struct as_data *ad, struct as_io_context *aic,
                                struct request *rq)
 {
-       struct as_rq *arq = RQ_DATA(rq);
-       int data_dir = arq->is_sync;
+       int data_dir = rq_is_sync(rq);
        unsigned long thinktime = 0;
        sector_t seek_dist;
 
@@ -752,11 +567,11 @@ static void as_update_iohist(struct as_data *ad, struct as_io_context *aic,
  * previous one issued.
  */
 static int as_close_req(struct as_data *ad, struct as_io_context *aic,
-                               struct as_rq *arq)
+                       struct request *rq)
 {
        unsigned long delay;    /* milliseconds */
        sector_t last = ad->last_sector[ad->batch_data_dir];
-       sector_t next = arq->request->sector;
+       sector_t next = rq->sector;
        sector_t delta; /* acceptable close offset (in sectors) */
        sector_t s;
 
@@ -813,7 +628,7 @@ static int as_close_req(struct as_data *ad, struct as_io_context *aic,
  *
  * If this task has queued some other IO, do not enter enticipation.
  */
-static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
+static int as_can_break_anticipation(struct as_data *ad, struct request *rq)
 {
        struct io_context *ioc;
        struct as_io_context *aic;
@@ -821,7 +636,7 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
        ioc = ad->io_context;
        BUG_ON(!ioc);
 
-       if (arq && ioc == arq->io_context) {
+       if (rq && ioc == RQ_IOC(rq)) {
                /* request from same process */
                return 1;
        }
@@ -848,7 +663,7 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
                return 1;
        }
 
-       if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, aic, arq)) {
+       if (rq && rq_is_sync(rq) && as_close_req(ad, aic, rq)) {
                /*
                 * Found a close request that is not one of ours.
                 *
@@ -864,7 +679,7 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
                        ad->exit_no_coop = (7*ad->exit_no_coop)/8;
                }
 
-               as_update_iohist(ad, aic, arq->request);
+               as_update_iohist(ad, aic, rq);
                return 1;
        }
 
@@ -891,10 +706,10 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
 }
 
 /*
- * as_can_anticipate indicates whether we should either run arq
+ * as_can_anticipate indicates whether we should either run rq
  * or keep anticipating a better request.
  */
-static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
+static int as_can_anticipate(struct as_data *ad, struct request *rq)
 {
        if (!ad->io_context)
                /*
@@ -908,7 +723,7 @@ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
                 */
                return 0;
 
-       if (as_can_break_anticipation(ad, arq))
+       if (as_can_break_anticipation(ad, rq))
                /*
                 * This request is a good candidate. Don't keep anticipating,
                 * run it.
@@ -926,16 +741,16 @@ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
 }
 
 /*
- * as_update_arq must be called whenever a request (arq) is added to
+ * as_update_rq must be called whenever a request (rq) is added to
  * the sort_list. This function keeps caches up to date, and checks if the
  * request might be one we are "anticipating"
  */
-static void as_update_arq(struct as_data *ad, struct as_rq *arq)
+static void as_update_rq(struct as_data *ad, struct request *rq)
 {
-       const int data_dir = arq->is_sync;
+       const int data_dir = rq_is_sync(rq);
 
-       /* keep the next_arq cache up to date */
-       ad->next_arq[data_dir] = as_choose_req(ad, arq, ad->next_arq[data_dir]);
+       /* keep the next_rq cache up to date */
+       ad->next_rq[data_dir] = as_choose_req(ad, rq, ad->next_rq[data_dir]);
 
        /*
         * have we been anticipating this request?
@@ -944,7 +759,7 @@ static void as_update_arq(struct as_data *ad, struct as_rq *arq)
         */
        if (ad->antic_status == ANTIC_WAIT_REQ
                        || ad->antic_status == ANTIC_WAIT_NEXT) {
-               if (as_can_break_anticipation(ad, arq))
+               if (as_can_break_anticipation(ad, rq))
                        as_antic_stop(ad);
        }
 }
@@ -984,12 +799,11 @@ static void update_write_batch(struct as_data *ad)
 static void as_completed_request(request_queue_t *q, struct request *rq)
 {
        struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq = RQ_DATA(rq);
 
        WARN_ON(!list_empty(&rq->queuelist));
 
-       if (arq->state != AS_RQ_REMOVED) {
-               printk("arq->state %d\n", arq->state);
+       if (RQ_STATE(rq) != AS_RQ_REMOVED) {
+               printk("rq->state %d\n", RQ_STATE(rq));
                WARN_ON(1);
                goto out;
        }
@@ -1009,14 +823,14 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
         * actually serviced. This should help devices with big TCQ windows
         * and writeback caches
         */
-       if (ad->new_batch && ad->batch_data_dir == arq->is_sync) {
+       if (ad->new_batch && ad->batch_data_dir == rq_is_sync(rq)) {
                update_write_batch(ad);
                ad->current_batch_expires = jiffies +
                                ad->batch_expire[REQ_SYNC];
                ad->new_batch = 0;
        }
 
-       if (ad->io_context == arq->io_context && ad->io_context) {
+       if (ad->io_context == RQ_IOC(rq) && ad->io_context) {
                ad->antic_start = jiffies;
                ad->ioc_finished = 1;
                if (ad->antic_status == ANTIC_WAIT_REQ) {
@@ -1028,9 +842,9 @@ static void as_completed_request(request_queue_t *q, struct request *rq)
                }
        }
 
-       as_put_io_context(arq);
+       as_put_io_context(rq);
 out:
-       arq->state = AS_RQ_POSTSCHED;
+       RQ_SET_STATE(rq, AS_RQ_POSTSCHED);
 }
 
 /*
@@ -1041,27 +855,27 @@ out:
  */
 static void as_remove_queued_request(request_queue_t *q, struct request *rq)
 {
-       struct as_rq *arq = RQ_DATA(rq);
-       const int data_dir = arq->is_sync;
+       const int data_dir = rq_is_sync(rq);
        struct as_data *ad = q->elevator->elevator_data;
+       struct io_context *ioc;
 
-       WARN_ON(arq->state != AS_RQ_QUEUED);
+       WARN_ON(RQ_STATE(rq) != AS_RQ_QUEUED);
 
-       if (arq->io_context && arq->io_context->aic) {
-               BUG_ON(!atomic_read(&arq->io_context->aic->nr_queued));
-               atomic_dec(&arq->io_context->aic->nr_queued);
+       ioc = RQ_IOC(rq);
+       if (ioc && ioc->aic) {
+               BUG_ON(!atomic_read(&ioc->aic->nr_queued));
+               atomic_dec(&ioc->aic->nr_queued);
        }
 
        /*
-        * Update the "next_arq" cache if we are about to remove its
+        * Update the "next_rq" cache if we are about to remove its
         * entry
         */
-       if (ad->next_arq[data_dir] == arq)
-               ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
+       if (ad->next_rq[data_dir] == rq)
+               ad->next_rq[data_dir] = as_find_next_rq(ad, rq);
 
-       list_del_init(&arq->fifo);
-       as_del_arq_hash(arq);
-       as_del_arq_rb(ad, arq);
+       rq_fifo_clear(rq);
+       as_del_rq_rb(ad, rq);
 }
 
 /*
@@ -1074,7 +888,7 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq)
  */
 static int as_fifo_expired(struct as_data *ad, int adir)
 {
-       struct as_rq *arq;
+       struct request *rq;
        long delta_jif;
 
        delta_jif = jiffies - ad->last_check_fifo[adir];
@@ -1088,9 +902,9 @@ static int as_fifo_expired(struct as_data *ad, int adir)
        if (list_empty(&ad->fifo_list[adir]))
                return 0;
 
-       arq = list_entry_fifo(ad->fifo_list[adir].next);
+       rq = rq_entry_fifo(ad->fifo_list[adir].next);
 
-       return time_after(jiffies, arq->expires);
+       return time_after(jiffies, rq_fifo_time(rq));
 }
 
 /*
@@ -1113,25 +927,25 @@ static inline int as_batch_expired(struct as_data *ad)
 /*
  * move an entry to dispatch queue
  */
-static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
+static void as_move_to_dispatch(struct as_data *ad, struct request *rq)
 {
-       struct request *rq = arq->request;
-       const int data_dir = arq->is_sync;
+       const int data_dir = rq_is_sync(rq);
 
-       BUG_ON(!RB_EMPTY_NODE(&arq->rb_node));
+       BUG_ON(RB_EMPTY_NODE(&rq->rb_node));
 
        as_antic_stop(ad);
        ad->antic_status = ANTIC_OFF;
 
        /*
         * This has to be set in order to be correctly updated by
-        * as_find_next_arq
+        * as_find_next_rq
         */
        ad->last_sector[data_dir] = rq->sector + rq->nr_sectors;
 
        if (data_dir == REQ_SYNC) {
+               struct io_context *ioc = RQ_IOC(rq);
                /* In case we have to anticipate after this */
-               copy_io_context(&ad->io_context, &arq->io_context);
+               copy_io_context(&ad->io_context, &ioc);
        } else {
                if (ad->io_context) {
                        put_io_context(ad->io_context);
@@ -1143,19 +957,19 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
        }
        ad->ioc_finished = 0;
 
-       ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
+       ad->next_rq[data_dir] = as_find_next_rq(ad, rq);
 
        /*
         * take it off the sort and fifo list, add to dispatch queue
         */
        as_remove_queued_request(ad->q, rq);
-       WARN_ON(arq->state != AS_RQ_QUEUED);
+       WARN_ON(RQ_STATE(rq) != AS_RQ_QUEUED);
 
        elv_dispatch_sort(ad->q, rq);
 
-       arq->state = AS_RQ_DISPATCHED;
-       if (arq->io_context && arq->io_context->aic)
-               atomic_inc(&arq->io_context->aic->nr_dispatched);
+       RQ_SET_STATE(rq, AS_RQ_DISPATCHED);
+       if (RQ_IOC(rq) && RQ_IOC(rq)->aic)
+               atomic_inc(&RQ_IOC(rq)->aic->nr_dispatched);
        ad->nr_dispatched++;
 }
 
@@ -1167,9 +981,9 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
 static int as_dispatch_request(request_queue_t *q, int force)
 {
        struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq;
        const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
        const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
+       struct request *rq;
 
        if (unlikely(force)) {
                /*
@@ -1185,14 +999,14 @@ static int as_dispatch_request(request_queue_t *q, int force)
                ad->changed_batch = 0;
                ad->new_batch = 0;
 
-               while (ad->next_arq[REQ_SYNC]) {
-                       as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+               while (ad->next_rq[REQ_SYNC]) {
+                       as_move_to_dispatch(ad, ad->next_rq[REQ_SYNC]);
                        dispatched++;
                }
                ad->last_check_fifo[REQ_SYNC] = jiffies;
 
-               while (ad->next_arq[REQ_ASYNC]) {
-                       as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+               while (ad->next_rq[REQ_ASYNC]) {
+                       as_move_to_dispatch(ad, ad->next_rq[REQ_ASYNC]);
                        dispatched++;
                }
                ad->last_check_fifo[REQ_ASYNC] = jiffies;
@@ -1216,19 +1030,19 @@ static int as_dispatch_request(request_queue_t *q, int force)
                /*
                 * batch is still running or no reads or no writes
                 */
-               arq = ad->next_arq[ad->batch_data_dir];
+               rq = ad->next_rq[ad->batch_data_dir];
 
                if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) {
                        if (as_fifo_expired(ad, REQ_SYNC))
                                goto fifo_expired;
 
-                       if (as_can_anticipate(ad, arq)) {
+                       if (as_can_anticipate(ad, rq)) {
                                as_antic_waitreq(ad);
                                return 0;
                        }
                }
 
-               if (arq) {
+               if (rq) {
                        /* we have a "next request" */
                        if (reads && !writes)
                                ad->current_batch_expires =
@@ -1256,7 +1070,7 @@ static int as_dispatch_request(request_queue_t *q, int force)
                        ad->changed_batch = 1;
                }
                ad->batch_data_dir = REQ_SYNC;
-               arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
+               rq = rq_entry_fifo(ad->fifo_list[REQ_SYNC].next);
                ad->last_check_fifo[ad->batch_data_dir] = jiffies;
                goto dispatch_request;
        }
@@ -1282,7 +1096,7 @@ dispatch_writes:
                ad->batch_data_dir = REQ_ASYNC;
                ad->current_write_count = ad->write_batch_count;
                ad->write_batch_idled = 0;
-               arq = ad->next_arq[ad->batch_data_dir];
+               rq = ad->next_rq[ad->batch_data_dir];
                goto dispatch_request;
        }
 
@@ -1296,8 +1110,7 @@ dispatch_request:
 
        if (as_fifo_expired(ad, ad->batch_data_dir)) {
 fifo_expired:
-               arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
-               BUG_ON(arq == NULL);
+               rq = rq_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
        }
 
        if (ad->changed_batch) {
@@ -1316,70 +1129,58 @@ fifo_expired:
        }
 
        /*
-        * arq is the selected appropriate request.
+        * rq is the selected appropriate request.
         */
-       as_move_to_dispatch(ad, arq);
+       as_move_to_dispatch(ad, rq);
 
        return 1;
 }
 
 /*
- * add arq to rbtree and fifo
+ * add rq to rbtree and fifo
  */
 static void as_add_request(request_queue_t *q, struct request *rq)
 {
        struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq = RQ_DATA(rq);
        int data_dir;
 
-       arq->state = AS_RQ_NEW;
+       RQ_SET_STATE(rq, AS_RQ_NEW);
 
-       if (rq_data_dir(arq->request) == READ
-                       || (arq->request->flags & REQ_RW_SYNC))
-               arq->is_sync = 1;
-       else
-               arq->is_sync = 0;
-       data_dir = arq->is_sync;
+       data_dir = rq_is_sync(rq);
 
-       arq->io_context = as_get_io_context();
+       rq->elevator_private = as_get_io_context(q->node);
 
-       if (arq->io_context) {
-               as_update_iohist(ad, arq->io_context->aic, arq->request);
-               atomic_inc(&arq->io_context->aic->nr_queued);
+       if (RQ_IOC(rq)) {
+               as_update_iohist(ad, RQ_IOC(rq)->aic, rq);
+               atomic_inc(&RQ_IOC(rq)->aic->nr_queued);
        }
 
-       as_add_arq_rb(ad, arq);
-       if (rq_mergeable(arq->request))
-               as_add_arq_hash(ad, arq);
+       as_add_rq_rb(ad, rq);
 
        /*
         * set expire time (only used for reads) and add to fifo list
         */
-       arq->expires = jiffies + ad->fifo_expire[data_dir];
-       list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
+       rq_set_fifo_time(rq, jiffies + ad->fifo_expire[data_dir]);
+       list_add_tail(&rq->queuelist, &ad->fifo_list[data_dir]);
 
-       as_update_arq(ad, arq); /* keep state machine up to date */
-       arq->state = AS_RQ_QUEUED;
+       as_update_rq(ad, rq); /* keep state machine up to date */
+       RQ_SET_STATE(rq, AS_RQ_QUEUED);
 }
 
 static void as_activate_request(request_queue_t *q, struct request *rq)
 {
-       struct as_rq *arq = RQ_DATA(rq);
-
-       WARN_ON(arq->state != AS_RQ_DISPATCHED);
-       arq->state = AS_RQ_REMOVED;
-       if (arq->io_context && arq->io_context->aic)
-               atomic_dec(&arq->io_context->aic->nr_dispatched);
+       WARN_ON(RQ_STATE(rq) != AS_RQ_DISPATCHED);
+       RQ_SET_STATE(rq, AS_RQ_REMOVED);
+       if (RQ_IOC(rq) && RQ_IOC(rq)->aic)
+               atomic_dec(&RQ_IOC(rq)->aic->nr_dispatched);
 }
 
 static void as_deactivate_request(request_queue_t *q, struct request *rq)
 {
-       struct as_rq *arq = RQ_DATA(rq);
-
-       WARN_ON(arq->state != AS_RQ_REMOVED);
-       arq->state = AS_RQ_DISPATCHED;
-       if (arq->io_context && arq->io_context->aic)
-               atomic_inc(&arq->io_context->aic->nr_dispatched);
+       WARN_ON(RQ_STATE(rq) != AS_RQ_REMOVED);
+       RQ_SET_STATE(rq, AS_RQ_DISPATCHED);
+       if (RQ_IOC(rq) && RQ_IOC(rq)->aic)
+               atomic_inc(&RQ_IOC(rq)->aic->nr_dispatched);
 }
 
 /*
@@ -1396,93 +1197,35 @@ static int as_queue_empty(request_queue_t *q)
                && list_empty(&ad->fifo_list[REQ_SYNC]);
 }
 
-static struct request *as_former_request(request_queue_t *q,
-                                       struct request *rq)
-{
-       struct as_rq *arq = RQ_DATA(rq);
-       struct rb_node *rbprev = rb_prev(&arq->rb_node);
-       struct request *ret = NULL;
-
-       if (rbprev)
-               ret = rb_entry_arq(rbprev)->request;
-
-       return ret;
-}
-
-static struct request *as_latter_request(request_queue_t *q,
-                                       struct request *rq)
-{
-       struct as_rq *arq = RQ_DATA(rq);
-       struct rb_node *rbnext = rb_next(&arq->rb_node);
-       struct request *ret = NULL;
-
-       if (rbnext)
-               ret = rb_entry_arq(rbnext)->request;
-
-       return ret;
-}
-
 static int
 as_merge(request_queue_t *q, struct request **req, struct bio *bio)
 {
        struct as_data *ad = q->elevator->elevator_data;
        sector_t rb_key = bio->bi_sector + bio_sectors(bio);
        struct request *__rq;
-       int ret;
-
-       /*
-        * see if the merge hash can satisfy a back merge
-        */
-       __rq = as_find_arq_hash(ad, bio->bi_sector);
-       if (__rq) {
-               BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
-
-               if (elv_rq_merge_ok(__rq, bio)) {
-                       ret = ELEVATOR_BACK_MERGE;
-                       goto out;
-               }
-       }
 
        /*
         * check for front merge
         */
-       __rq = as_find_arq_rb(ad, rb_key, bio_data_dir(bio));
-       if (__rq) {
-               BUG_ON(rb_key != rq_rb_key(__rq));
-
-               if (elv_rq_merge_ok(__rq, bio)) {
-                       ret = ELEVATOR_FRONT_MERGE;
-                       goto out;
-               }
+       __rq = elv_rb_find(&ad->sort_list[bio_data_dir(bio)], rb_key);
+       if (__rq && elv_rq_merge_ok(__rq, bio)) {
+               *req = __rq;
+               return ELEVATOR_FRONT_MERGE;
        }
 
        return ELEVATOR_NO_MERGE;
-out:
-       if (ret) {
-               if (rq_mergeable(__rq))
-                       as_hot_arq_hash(ad, RQ_DATA(__rq));
-       }
-       *req = __rq;
-       return ret;
 }
 
-static void as_merged_request(request_queue_t *q, struct request *req)
+static void as_merged_request(request_queue_t *q, struct request *req, int type)
 {
        struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq = RQ_DATA(req);
-
-       /*
-        * hash always needs to be repositioned, key is end sector
-        */
-       as_del_arq_hash(arq);
-       as_add_arq_hash(ad, arq);
 
        /*
         * if the merge was a front merge, we need to reposition request
         */
-       if (rq_rb_key(req) != arq->rb_key) {
-               as_del_arq_rb(ad, arq);
-               as_add_arq_rb(ad, arq);
+       if (type == ELEVATOR_FRONT_MERGE) {
+               as_del_rq_rb(ad, req);
+               as_add_rq_rb(ad, req);
                /*
                 * Note! At this stage of this and the next function, our next
                 * request may not be optimal - eg the request may have "grown"
@@ -1494,38 +1237,22 @@ static void as_merged_request(request_queue_t *q, struct request *req)
 static void as_merged_requests(request_queue_t *q, struct request *req,
                                struct request *next)
 {
-       struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq = RQ_DATA(req);
-       struct as_rq *anext = RQ_DATA(next);
-
-       BUG_ON(!arq);
-       BUG_ON(!anext);
-
        /*
-        * reposition arq (this is the merged request) in hash, and in rbtree
-        * in case of a front merge
+        * if next expires before rq, assign its expire time to arq
+        * and move into next position (next will be deleted) in fifo
         */
-       as_del_arq_hash(arq);
-       as_add_arq_hash(ad, arq);
-
-       if (rq_rb_key(req) != arq->rb_key) {
-               as_del_arq_rb(ad, arq);
-               as_add_arq_rb(ad, arq);
-       }
+       if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
+               if (time_before(rq_fifo_time(next), rq_fifo_time(req))) {
+                       struct io_context *rioc = RQ_IOC(req);
+                       struct io_context *nioc = RQ_IOC(next);
 
-       /*
-        * if anext expires before arq, assign its expire time to arq
-        * and move into anext position (anext will be deleted) in fifo
-        */
-       if (!list_empty(&arq->fifo) && !list_empty(&anext->fifo)) {
-               if (time_before(anext->expires, arq->expires)) {
-                       list_move(&arq->fifo, &anext->fifo);
-                       arq->expires = anext->expires;
+                       list_move(&req->queuelist, &next->queuelist);
+                       rq_set_fifo_time(req, rq_fifo_time(next));
                        /*
                         * Don't copy here but swap, because when anext is
                         * removed below, it must contain the unused context
                         */
-                       swap_io_context(&arq->io_context, &anext->io_context);
+                       swap_io_context(&rioc, &nioc);
                }
        }
 
@@ -1533,9 +1260,9 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
         * kill knowledge of next, this one is a goner
         */
        as_remove_queued_request(q, next);
-       as_put_io_context(anext);
+       as_put_io_context(next);
 
-       anext->state = AS_RQ_MERGED;
+       RQ_SET_STATE(next, AS_RQ_MERGED);
 }
 
 /*
@@ -1553,61 +1280,18 @@ static void as_work_handler(void *data)
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
-       if (!as_queue_empty(q))
-               q->request_fn(q);
+       blk_start_queueing(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
-static void as_put_request(request_queue_t *q, struct request *rq)
-{
-       struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq = RQ_DATA(rq);
-
-       if (!arq) {
-               WARN_ON(1);
-               return;
-       }
-
-       if (unlikely(arq->state != AS_RQ_POSTSCHED &&
-                    arq->state != AS_RQ_PRESCHED &&
-                    arq->state != AS_RQ_MERGED)) {
-               printk("arq->state %d\n", arq->state);
-               WARN_ON(1);
-       }
-
-       mempool_free(arq, ad->arq_pool);
-       rq->elevator_private = NULL;
-}
-
-static int as_set_request(request_queue_t *q, struct request *rq,
-                         struct bio *bio, gfp_t gfp_mask)
-{
-       struct as_data *ad = q->elevator->elevator_data;
-       struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
-
-       if (arq) {
-               memset(arq, 0, sizeof(*arq));
-               RB_CLEAR_NODE(&arq->rb_node);
-               arq->request = rq;
-               arq->state = AS_RQ_PRESCHED;
-               arq->io_context = NULL;
-               INIT_HLIST_NODE(&arq->hash);
-               INIT_LIST_HEAD(&arq->fifo);
-               rq->elevator_private = arq;
-               return 0;
-       }
-
-       return 1;
-}
-
-static int as_may_queue(request_queue_t *q, int rw, struct bio *bio)
+static int as_may_queue(request_queue_t *q, int rw)
 {
        int ret = ELV_MQUEUE_MAY;
        struct as_data *ad = q->elevator->elevator_data;
        struct io_context *ioc;
        if (ad->antic_status == ANTIC_WAIT_REQ ||
                        ad->antic_status == ANTIC_WAIT_NEXT) {
-               ioc = as_get_io_context();
+               ioc = as_get_io_context(q->node);
                if (ad->io_context == ioc)
                        ret = ELV_MQUEUE_MUST;
                put_io_context(ioc);
@@ -1626,23 +1310,16 @@ static void as_exit_queue(elevator_t *e)
        BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC]));
        BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC]));
 
-       mempool_destroy(ad->arq_pool);
        put_io_context(ad->io_context);
-       kfree(ad->hash);
        kfree(ad);
 }
 
 /*
- * initialize elevator private data (as_data), and alloc a arq for
- * each request on the free lists
+ * initialize elevator private data (as_data).
  */
 static void *as_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct as_data *ad;
-       int i;
-
-       if (!arq_pool)
-               return NULL;
 
        ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
        if (!ad)
@@ -1651,30 +1328,12 @@ static void *as_init_queue(request_queue_t *q, elevator_t *e)
 
        ad->q = q; /* Identify what queue the data belongs to */
 
-       ad->hash = kmalloc_node(sizeof(struct hlist_head)*AS_HASH_ENTRIES,
-                               GFP_KERNEL, q->node);
-       if (!ad->hash) {
-               kfree(ad);
-               return NULL;
-       }
-
-       ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
-                               mempool_free_slab, arq_pool, q->node);
-       if (!ad->arq_pool) {
-               kfree(ad->hash);
-               kfree(ad);
-               return NULL;
-       }
-
        /* anticipatory scheduling helpers */
        ad->antic_timer.function = as_antic_timeout;
        ad->antic_timer.data = (unsigned long)q;
        init_timer(&ad->antic_timer);
        INIT_WORK(&ad->antic_work, as_work_handler, q);
 
-       for (i = 0; i < AS_HASH_ENTRIES; i++)
-               INIT_HLIST_HEAD(&ad->hash[i]);
-
        INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
        INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
        ad->sort_list[REQ_SYNC] = RB_ROOT;
@@ -1787,10 +1446,8 @@ static struct elevator_type iosched_as = {
                .elevator_deactivate_req_fn =   as_deactivate_request,
                .elevator_queue_empty_fn =      as_queue_empty,
                .elevator_completed_req_fn =    as_completed_request,
-               .elevator_former_req_fn =       as_former_request,
-               .elevator_latter_req_fn =       as_latter_request,
-               .elevator_set_req_fn =          as_set_request,
-               .elevator_put_req_fn =          as_put_request,
+               .elevator_former_req_fn =       elv_rb_former_request,
+               .elevator_latter_req_fn =       elv_rb_latter_request,
                .elevator_may_queue_fn =        as_may_queue,
                .elevator_init_fn =             as_init_queue,
                .elevator_exit_fn =             as_exit_queue,
@@ -1806,11 +1463,6 @@ static int __init as_init(void)
 {
        int ret;
 
-       arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq),
-                                    0, 0, NULL, NULL);
-       if (!arq_pool)
-               return -ENOMEM;
-
        ret = elv_register(&iosched_as);
        if (!ret) {
                /*
@@ -1822,21 +1474,19 @@ static int __init as_init(void)
                return 0;
        }
 
-       kmem_cache_destroy(arq_pool);
        return ret;
 }
 
 static void __exit as_exit(void)
 {
-       DECLARE_COMPLETION(all_gone);
+       DECLARE_COMPLETION_ONSTACK(all_gone);
        elv_unregister(&iosched_as);
        ioc_gone = &all_gone;
        /* ioc_gone's update must be visible before reading ioc_count */
        smp_wmb();
-       if (atomic_read(&ioc_count))
+       if (elv_ioc_count_read(ioc_count))
                wait_for_completion(ioc_gone);
        synchronize_rcu();
-       kmem_cache_destroy(arq_pool);
 }
 
 module_init(as_init);
index 265f7a830619ef1e5de60bfe1179fa9d3a002229..135593c8e45bdee40f97c3e690d47c34e769370a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
  *
  * 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
@@ -69,7 +69,7 @@ static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK
 /*
  * Bio action bits of interest
  */
-static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD) };
+static u32 bio_act[9] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD), 0, 0, 0, BLK_TC_ACT(BLK_TC_META) };
 
 /*
  * More could be added as needed, taking care to increment the decrementer
@@ -81,6 +81,8 @@ static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_AC
        (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1))
 #define trace_ahead_bit(rw)    \
        (((rw) & (1 << BIO_RW_AHEAD)) << (2 - BIO_RW_AHEAD))
+#define trace_meta_bit(rw)     \
+       (((rw) & (1 << BIO_RW_META)) >> (BIO_RW_META - 3))
 
 /*
  * The worker for the various blk_add_trace*() types. Fills out a
@@ -103,6 +105,7 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
        what |= bio_act[trace_barrier_bit(rw)];
        what |= bio_act[trace_sync_bit(rw)];
        what |= bio_act[trace_ahead_bit(rw)];
+       what |= bio_act[trace_meta_bit(rw)];
 
        pid = tsk->pid;
        if (unlikely(act_log_check(bt, what, sector, pid)))
@@ -217,7 +220,7 @@ static int blk_trace_remove(request_queue_t *q)
 
 static int blk_dropped_open(struct inode *inode, struct file *filp)
 {
-       filp->private_data = inode->u.generic_ip;
+       filp->private_data = inode->i_private;
 
        return 0;
 }
@@ -450,8 +453,10 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
  **/
 void blk_trace_shutdown(request_queue_t *q)
 {
-       blk_trace_startstop(q, 0);
-       blk_trace_remove(q);
+       if (q->blk_trace) {
+               blk_trace_startstop(q, 0);
+               blk_trace_remove(q);
+       }
 }
 
 /*
@@ -471,6 +476,9 @@ static void blk_check_time(unsigned long long *t)
        *t -= (a + b) / 2;
 }
 
+/*
+ * calibrate our inter-CPU timings
+ */
 static void blk_trace_check_cpu_time(void *data)
 {
        unsigned long long *t;
@@ -488,20 +496,6 @@ static void blk_trace_check_cpu_time(void *data)
        put_cpu();
 }
 
-/*
- * Call blk_trace_check_cpu_time() on each CPU to calibrate our inter-CPU
- * timings
- */
-static void blk_trace_calibrate_offsets(void)
-{
-       unsigned long flags;
-
-       smp_call_function(blk_trace_check_cpu_time, NULL, 1, 1);
-       local_irq_save(flags);
-       blk_trace_check_cpu_time(NULL);
-       local_irq_restore(flags);
-}
-
 static void blk_trace_set_ht_offsets(void)
 {
 #if defined(CONFIG_SCHED_SMT)
@@ -530,7 +524,7 @@ static void blk_trace_set_ht_offsets(void)
 static __init int blk_trace_init(void)
 {
        mutex_init(&blk_tree_mutex);
-       blk_trace_calibrate_offsets();
+       on_each_cpu(blk_trace_check_cpu_time, NULL, 1, 1);
        blk_trace_set_ht_offsets();
 
        return 0;
index 3a3aee08ec5f4850f0a1877b3bdf86d9b03d9625..d3d76136f53adea6293244f7cd9a9aa07f24b4d0 100644 (file)
@@ -4,7 +4,7 @@
  *  Based on ideas from a previously unfinished io
  *  scheduler (round robin per-process disk scheduling) and Andrea Arcangeli.
  *
- *  Copyright (C) 2003 Jens Axboe <axboe@suse.de>
+ *  Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
  */
 #include <linux/module.h>
 #include <linux/blkdev.h>
@@ -17,7 +17,6 @@
  * tunables
  */
 static const int cfq_quantum = 4;              /* max queue in one round of service */
-static const int cfq_queued = 8;               /* minimum rq allocate limit per-queue*/
 static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
 static const int cfq_back_max = 16 * 1024;     /* maximum backwards seek, in KiB */
 static const int cfq_back_penalty = 2;         /* penalty of a backwards seek */
@@ -32,8 +31,6 @@ static int cfq_slice_idle = HZ / 125;
 
 #define CFQ_KEY_ASYNC          (0)
 
-static DEFINE_SPINLOCK(cfq_exit_lock);
-
 /*
  * for the hash of cfqq inside the cfqd
  */
@@ -41,37 +38,19 @@ static DEFINE_SPINLOCK(cfq_exit_lock);
 #define CFQ_QHASH_ENTRIES      (1 << CFQ_QHASH_SHIFT)
 #define list_entry_qhash(entry)        hlist_entry((entry), struct cfq_queue, cfq_hash)
 
-/*
- * for the hash of crq inside the cfqq
- */
-#define CFQ_MHASH_SHIFT                6
-#define CFQ_MHASH_BLOCK(sec)   ((sec) >> 3)
-#define CFQ_MHASH_ENTRIES      (1 << CFQ_MHASH_SHIFT)
-#define CFQ_MHASH_FN(sec)      hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT)
-#define rq_hash_key(rq)                ((rq)->sector + (rq)->nr_sectors)
-#define list_entry_hash(ptr)   hlist_entry((ptr), struct cfq_rq, hash)
-
 #define list_entry_cfqq(ptr)   list_entry((ptr), struct cfq_queue, cfq_list)
-#define list_entry_fifo(ptr)   list_entry((ptr), struct request, queuelist)
 
-#define RQ_DATA(rq)            (rq)->elevator_private
+#define RQ_CIC(rq)             ((struct cfq_io_context*)(rq)->elevator_private)
+#define RQ_CFQQ(rq)            ((rq)->elevator_private2)
 
-/*
- * rb-tree defines
- */
-#define rb_entry_crq(node)     rb_entry((node), struct cfq_rq, rb_node)
-#define rq_rb_key(rq)          (rq)->sector
-
-static kmem_cache_t *crq_pool;
 static kmem_cache_t *cfq_pool;
 static kmem_cache_t *cfq_ioc_pool;
 
-static atomic_t ioc_count = ATOMIC_INIT(0);
+static DEFINE_PER_CPU(unsigned long, ioc_count);
 static struct completion *ioc_gone;
 
 #define CFQ_PRIO_LISTS         IOPRIO_BE_NR
 #define cfq_class_idle(cfqq)   ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
-#define cfq_class_be(cfqq)     ((cfqq)->ioprio_class == IOPRIO_CLASS_BE)
 #define cfq_class_rt(cfqq)     ((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
 
 #define ASYNC                  (0)
@@ -102,29 +81,14 @@ struct cfq_data {
        struct list_head idle_rr;
        unsigned int busy_queues;
 
-       /*
-        * non-ordered list of empty cfqq's
-        */
-       struct list_head empty_list;
-
        /*
         * cfqq lookup hash
         */
        struct hlist_head *cfq_hash;
 
-       /*
-        * global crq hash for all queues
-        */
-       struct hlist_head *crq_hash;
-
-       mempool_t *crq_pool;
-
        int rq_in_driver;
        int hw_tag;
 
-       /*
-        * schedule slice state info
-        */
        /*
         * idle window management
         */
@@ -141,13 +105,10 @@ struct cfq_data {
        sector_t last_sector;
        unsigned long last_end_request;
 
-       unsigned int rq_starved;
-
        /*
         * tunables, see top of file
         */
        unsigned int cfq_quantum;
-       unsigned int cfq_queued;
        unsigned int cfq_fifo_expire[2];
        unsigned int cfq_back_penalty;
        unsigned int cfq_back_max;
@@ -170,23 +131,24 @@ struct cfq_queue {
        struct hlist_node cfq_hash;
        /* hash key */
        unsigned int key;
-       /* on either rr or empty list of cfqd */
+       /* member of the rr/busy/cur/idle cfqd list */
        struct list_head cfq_list;
        /* sorted list of pending requests */
        struct rb_root sort_list;
        /* if fifo isn't expired, next request to serve */
-       struct cfq_rq *next_crq;
+       struct request *next_rq;
        /* requests queued in sort_list */
        int queued[2];
        /* currently allocated requests */
        int allocated[2];
+       /* pending metadata requests */
+       int meta_pending;
        /* fifo list of requests in sort_list */
        struct list_head fifo;
 
        unsigned long slice_start;
        unsigned long slice_end;
        unsigned long slice_left;
-       unsigned long service_last;
 
        /* number of requests that are on the dispatch list */
        int on_dispatch[2];
@@ -199,18 +161,6 @@ struct cfq_queue {
        unsigned int flags;
 };
 
-struct cfq_rq {
-       struct rb_node rb_node;
-       sector_t rb_key;
-       struct request *request;
-       struct hlist_node hash;
-
-       struct cfq_queue *cfq_queue;
-       struct cfq_io_context *io_context;
-
-       unsigned int crq_flags;
-};
-
 enum cfqq_state_flags {
        CFQ_CFQQ_FLAG_on_rr = 0,
        CFQ_CFQQ_FLAG_wait_request,
@@ -220,6 +170,7 @@ enum cfqq_state_flags {
        CFQ_CFQQ_FLAG_fifo_expire,
        CFQ_CFQQ_FLAG_idle_window,
        CFQ_CFQQ_FLAG_prio_changed,
+       CFQ_CFQQ_FLAG_queue_new,
 };
 
 #define CFQ_CFQQ_FNS(name)                                             \
@@ -244,69 +195,13 @@ CFQ_CFQQ_FNS(must_dispatch);
 CFQ_CFQQ_FNS(fifo_expire);
 CFQ_CFQQ_FNS(idle_window);
 CFQ_CFQQ_FNS(prio_changed);
+CFQ_CFQQ_FNS(queue_new);
 #undef CFQ_CFQQ_FNS
 
-enum cfq_rq_state_flags {
-       CFQ_CRQ_FLAG_is_sync = 0,
-};
-
-#define CFQ_CRQ_FNS(name)                                              \
-static inline void cfq_mark_crq_##name(struct cfq_rq *crq)             \
-{                                                                      \
-       crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name);                   \
-}                                                                      \
-static inline void cfq_clear_crq_##name(struct cfq_rq *crq)            \
-{                                                                      \
-       crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name);                  \
-}                                                                      \
-static inline int cfq_crq_##name(const struct cfq_rq *crq)             \
-{                                                                      \
-       return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0;      \
-}
-
-CFQ_CRQ_FNS(is_sync);
-#undef CFQ_CRQ_FNS
-
 static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
-static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
+static void cfq_dispatch_insert(request_queue_t *, struct request *);
 static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
 
-/*
- * lots of deadline iosched dupes, can be abstracted later...
- */
-static inline void cfq_del_crq_hash(struct cfq_rq *crq)
-{
-       hlist_del_init(&crq->hash);
-}
-
-static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
-{
-       const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
-
-       hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]);
-}
-
-static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
-{
-       struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)];
-       struct hlist_node *entry, *next;
-
-       hlist_for_each_safe(entry, next, hash_list) {
-               struct cfq_rq *crq = list_entry_hash(entry);
-               struct request *__rq = crq->request;
-
-               if (!rq_mergeable(__rq)) {
-                       cfq_del_crq_hash(crq);
-                       continue;
-               }
-
-               if (rq_hash_key(__rq) == offset)
-                       return __rq;
-       }
-
-       return NULL;
-}
-
 /*
  * scheduler run of queue, if there are requests pending and no one in the
  * driver that will restart queueing
@@ -333,12 +228,12 @@ static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
 }
 
 /*
- * Lifted from AS - choose which of crq1 and crq2 that is best served now.
+ * Lifted from AS - choose which of rq1 and rq2 that is best served now.
  * We choose the request that is closest to the head right now. Distance
  * behind the head is penalized and only allowed to a certain extent.
  */
-static struct cfq_rq *
-cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
+static struct request *
+cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2)
 {
        sector_t last, s1, s2, d1 = 0, d2 = 0;
        unsigned long back_max;
@@ -346,18 +241,22 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
 #define CFQ_RQ2_WRAP   0x02 /* request 2 wraps */
        unsigned wrap = 0; /* bit mask: requests behind the disk head? */
 
-       if (crq1 == NULL || crq1 == crq2)
-               return crq2;
-       if (crq2 == NULL)
-               return crq1;
+       if (rq1 == NULL || rq1 == rq2)
+               return rq2;
+       if (rq2 == NULL)
+               return rq1;
 
-       if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
-               return crq1;
-       else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
-               return crq2;
+       if (rq_is_sync(rq1) && !rq_is_sync(rq2))
+               return rq1;
+       else if (rq_is_sync(rq2) && !rq_is_sync(rq1))
+               return rq2;
+       if (rq_is_meta(rq1) && !rq_is_meta(rq2))
+               return rq1;
+       else if (rq_is_meta(rq2) && !rq_is_meta(rq1))
+               return rq2;
 
-       s1 = crq1->request->sector;
-       s2 = crq2->request->sector;
+       s1 = rq1->sector;
+       s2 = rq2->sector;
 
        last = cfqd->last_sector;
 
@@ -392,23 +291,23 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
         * check two variables for all permutations: --> faster!
         */
        switch (wrap) {
-       case 0: /* common case for CFQ: crq1 and crq2 not wrapped */
+       case 0: /* common case for CFQ: rq1 and rq2 not wrapped */
                if (d1 < d2)
-                       return crq1;
+                       return rq1;
                else if (d2 < d1)
-                       return crq2;
+                       return rq2;
                else {
                        if (s1 >= s2)
-                               return crq1;
+                               return rq1;
                        else
-                               return crq2;
+                               return rq2;
                }
 
        case CFQ_RQ2_WRAP:
-               return crq1;
+               return rq1;
        case CFQ_RQ1_WRAP:
-               return crq2;
-       case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */
+               return rq2;
+       case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both rqs wrapped */
        default:
                /*
                 * Since both rqs are wrapped,
@@ -417,50 +316,43 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
                 * since back seek takes more time than forward.
                 */
                if (s1 <= s2)
-                       return crq1;
+                       return rq1;
                else
-                       return crq2;
+                       return rq2;
        }
 }
 
 /*
  * would be nice to take fifo expire time into account as well
  */
-static struct cfq_rq *
-cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                 struct cfq_rq *last)
+static struct request *
+cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+                 struct request *last)
 {
-       struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
-       struct rb_node *rbnext, *rbprev;
-
-       if (!(rbnext = rb_next(&last->rb_node))) {
-               rbnext = rb_first(&cfqq->sort_list);
-               if (rbnext == &last->rb_node)
-                       rbnext = NULL;
-       }
+       struct rb_node *rbnext = rb_next(&last->rb_node);
+       struct rb_node *rbprev = rb_prev(&last->rb_node);
+       struct request *next = NULL, *prev = NULL;
 
-       rbprev = rb_prev(&last->rb_node);
+       BUG_ON(RB_EMPTY_NODE(&last->rb_node));
 
        if (rbprev)
-               crq_prev = rb_entry_crq(rbprev);
-       if (rbnext)
-               crq_next = rb_entry_crq(rbnext);
-
-       return cfq_choose_req(cfqd, crq_next, crq_prev);
-}
+               prev = rb_entry_rq(rbprev);
 
-static void cfq_update_next_crq(struct cfq_rq *crq)
-{
-       struct cfq_queue *cfqq = crq->cfq_queue;
+       if (rbnext)
+               next = rb_entry_rq(rbnext);
+       else {
+               rbnext = rb_first(&cfqq->sort_list);
+               if (rbnext && rbnext != &last->rb_node)
+                       next = rb_entry_rq(rbnext);
+       }
 
-       if (cfqq->next_crq == crq)
-               cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq);
+       return cfq_choose_req(cfqd, next, prev);
 }
 
 static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
 {
        struct cfq_data *cfqd = cfqq->cfqd;
-       struct list_head *list, *entry;
+       struct list_head *list;
 
        BUG_ON(!cfq_cfqq_on_rr(cfqq));
 
@@ -485,31 +377,26 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
        }
 
        /*
-        * if queue was preempted, just add to front to be fair. busy_rr
-        * isn't sorted, but insert at the back for fairness.
+        * If this queue was preempted or is new (never been serviced), let
+        * it be added first for fairness but beind other new queues.
+        * Otherwise, just add to the back  of the list.
         */
-       if (preempted || list == &cfqd->busy_rr) {
-               if (preempted)
-                       list = list->prev;
+       if (preempted || cfq_cfqq_queue_new(cfqq)) {
+               struct list_head *n = list;
+               struct cfq_queue *__cfqq;
 
-               list_add_tail(&cfqq->cfq_list, list);
-               return;
-       }
+               while (n->next != list) {
+                       __cfqq = list_entry_cfqq(n->next);
+                       if (!cfq_cfqq_queue_new(__cfqq))
+                               break;
 
-       /*
-        * sort by when queue was last serviced
-        */
-       entry = list;
-       while ((entry = entry->prev) != list) {
-               struct cfq_queue *__cfqq = list_entry_cfqq(entry);
+                       n = n->next;
+               }
 
-               if (!__cfqq->service_last)
-                       break;
-               if (time_before(__cfqq->service_last, cfqq->service_last))
-                       break;
+               list = n;
        }
 
-       list_add(&cfqq->cfq_list, entry);
+       list_add_tail(&cfqq->cfq_list, list);
 }
 
 /*
@@ -531,7 +418,7 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
        BUG_ON(!cfq_cfqq_on_rr(cfqq));
        cfq_clear_cfqq_on_rr(cfqq);
-       list_move(&cfqq->cfq_list, &cfqd->empty_list);
+       list_del_init(&cfqq->cfq_list);
 
        BUG_ON(!cfqd->busy_queues);
        cfqd->busy_queues--;
@@ -540,81 +427,43 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 /*
  * rb tree support functions
  */
-static inline void cfq_del_crq_rb(struct cfq_rq *crq)
+static inline void cfq_del_rq_rb(struct request *rq)
 {
-       struct cfq_queue *cfqq = crq->cfq_queue;
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
        struct cfq_data *cfqd = cfqq->cfqd;
-       const int sync = cfq_crq_is_sync(crq);
+       const int sync = rq_is_sync(rq);
 
        BUG_ON(!cfqq->queued[sync]);
        cfqq->queued[sync]--;
 
-       cfq_update_next_crq(crq);
-
-       rb_erase(&crq->rb_node, &cfqq->sort_list);
+       elv_rb_del(&cfqq->sort_list, rq);
 
        if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list))
                cfq_del_cfqq_rr(cfqd, cfqq);
 }
 
-static struct cfq_rq *
-__cfq_add_crq_rb(struct cfq_rq *crq)
+static void cfq_add_rq_rb(struct request *rq)
 {
-       struct rb_node **p = &crq->cfq_queue->sort_list.rb_node;
-       struct rb_node *parent = NULL;
-       struct cfq_rq *__crq;
-
-       while (*p) {
-               parent = *p;
-               __crq = rb_entry_crq(parent);
-
-               if (crq->rb_key < __crq->rb_key)
-                       p = &(*p)->rb_left;
-               else if (crq->rb_key > __crq->rb_key)
-                       p = &(*p)->rb_right;
-               else
-                       return __crq;
-       }
-
-       rb_link_node(&crq->rb_node, parent, p);
-       return NULL;
-}
-
-static void cfq_add_crq_rb(struct cfq_rq *crq)
-{
-       struct cfq_queue *cfqq = crq->cfq_queue;
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
        struct cfq_data *cfqd = cfqq->cfqd;
-       struct request *rq = crq->request;
-       struct cfq_rq *__alias;
+       struct request *__alias;
 
-       crq->rb_key = rq_rb_key(rq);
-       cfqq->queued[cfq_crq_is_sync(crq)]++;
+       cfqq->queued[rq_is_sync(rq)]++;
 
        /*
         * looks a little odd, but the first insert might return an alias.
         * if that happens, put the alias on the dispatch list
         */
-       while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
+       while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
                cfq_dispatch_insert(cfqd->queue, __alias);
-
-       rb_insert_color(&crq->rb_node, &cfqq->sort_list);
-
-       if (!cfq_cfqq_on_rr(cfqq))
-               cfq_add_cfqq_rr(cfqd, cfqq);
-
-       /*
-        * check if this request is a better next-serve candidate
-        */
-       cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
 }
 
 static inline void
-cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
+cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq)
 {
-       rb_erase(&crq->rb_node, &cfqq->sort_list);
-       cfqq->queued[cfq_crq_is_sync(crq)]--;
-
-       cfq_add_crq_rb(crq);
+       elv_rb_del(&cfqq->sort_list, rq);
+       cfqq->queued[rq_is_sync(rq)]--;
+       cfq_add_rq_rb(rq);
 }
 
 static struct request *
@@ -623,27 +472,14 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
        struct task_struct *tsk = current;
        pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
        struct cfq_queue *cfqq;
-       struct rb_node *n;
-       sector_t sector;
 
        cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
-       if (!cfqq)
-               goto out;
-
-       sector = bio->bi_sector + bio_sectors(bio);
-       n = cfqq->sort_list.rb_node;
-       while (n) {
-               struct cfq_rq *crq = rb_entry_crq(n);
+       if (cfqq) {
+               sector_t sector = bio->bi_sector + bio_sectors(bio);
 
-               if (sector < crq->rb_key)
-                       n = n->rb_left;
-               else if (sector > crq->rb_key)
-                       n = n->rb_right;
-               else
-                       return crq->request;
+               return elv_rb_find(&cfqq->sort_list, sector);
        }
 
-out:
        return NULL;
 }
 
@@ -673,11 +509,18 @@ static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
 
 static void cfq_remove_request(struct request *rq)
 {
-       struct cfq_rq *crq = RQ_DATA(rq);
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
+
+       if (cfqq->next_rq == rq)
+               cfqq->next_rq = cfq_find_next_rq(cfqq->cfqd, cfqq, rq);
 
        list_del_init(&rq->queuelist);
-       cfq_del_crq_rb(crq);
-       cfq_del_crq_hash(crq);
+       cfq_del_rq_rb(rq);
+
+       if (rq_is_meta(rq)) {
+               WARN_ON(!cfqq->meta_pending);
+               cfqq->meta_pending--;
+       }
 }
 
 static int
@@ -685,39 +528,23 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct request *__rq;
-       int ret;
-
-       __rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
-       if (__rq && elv_rq_merge_ok(__rq, bio)) {
-               ret = ELEVATOR_BACK_MERGE;
-               goto out;
-       }
 
        __rq = cfq_find_rq_fmerge(cfqd, bio);
        if (__rq && elv_rq_merge_ok(__rq, bio)) {
-               ret = ELEVATOR_FRONT_MERGE;
-               goto out;
+               *req = __rq;
+               return ELEVATOR_FRONT_MERGE;
        }
 
        return ELEVATOR_NO_MERGE;
-out:
-       *req = __rq;
-       return ret;
 }
 
-static void cfq_merged_request(request_queue_t *q, struct request *req)
+static void cfq_merged_request(request_queue_t *q, struct request *req,
+                              int type)
 {
-       struct cfq_data *cfqd = q->elevator->elevator_data;
-       struct cfq_rq *crq = RQ_DATA(req);
-
-       cfq_del_crq_hash(crq);
-       cfq_add_crq_hash(cfqd, crq);
-
-       if (rq_rb_key(req) != crq->rb_key) {
-               struct cfq_queue *cfqq = crq->cfq_queue;
+       if (type == ELEVATOR_FRONT_MERGE) {
+               struct cfq_queue *cfqq = RQ_CFQQ(req);
 
-               cfq_update_next_crq(crq);
-               cfq_reposition_crq_rb(cfqq, crq);
+               cfq_reposition_rq_rb(cfqq, req);
        }
 }
 
@@ -725,8 +552,6 @@ static void
 cfq_merged_requests(request_queue_t *q, struct request *rq,
                    struct request *next)
 {
-       cfq_merged_request(q, rq);
-
        /*
         * reposition in fifo if next is older than rq
         */
@@ -768,13 +593,12 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        if (cfq_cfqq_wait_request(cfqq))
                del_timer(&cfqd->idle_slice_timer);
 
-       if (!preempted && !cfq_cfqq_dispatched(cfqq)) {
-               cfqq->service_last = now;
+       if (!preempted && !cfq_cfqq_dispatched(cfqq))
                cfq_schedule_dispatch(cfqd);
-       }
 
        cfq_clear_cfqq_must_dispatch(cfqq);
        cfq_clear_cfqq_wait_request(cfqq);
+       cfq_clear_cfqq_queue_new(cfqq);
 
        /*
         * store what was left of this slice, if the queue idled out
@@ -868,26 +692,25 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
 {
        struct cfq_queue *cfqq = NULL;
 
-       /*
-        * if current list is non-empty, grab first entry. if it is empty,
-        * get next prio level and grab first entry then if any are spliced
-        */
-       if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1)
+       if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) {
+               /*
+                * if current list is non-empty, grab first entry. if it is
+                * empty, get next prio level and grab first entry then if any
+                * are spliced
+                */
                cfqq = list_entry_cfqq(cfqd->cur_rr.next);
-
-       /*
-        * If no new queues are available, check if the busy list has some
-        * before falling back to idle io.
-        */
-       if (!cfqq && !list_empty(&cfqd->busy_rr))
+       } else if (!list_empty(&cfqd->busy_rr)) {
+               /*
+                * If no new queues are available, check if the busy list has
+                * some before falling back to idle io.
+                */
                cfqq = list_entry_cfqq(cfqd->busy_rr.next);
-
-       /*
-        * if we have idle queues and no rt or be queues had pending
-        * requests, either allow immediate service if the grace period
-        * has passed or arm the idle grace timer
-        */
-       if (!cfqq && !list_empty(&cfqd->idle_rr)) {
+       } else if (!list_empty(&cfqd->idle_rr)) {
+               /*
+                * if we have idle queues and no rt or be queues had pending
+                * requests, either allow immediate service if the grace period
+                * has passed or arm the idle grace timer
+                */
                unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
 
                if (time_after_eq(jiffies, end))
@@ -942,16 +765,14 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
        return 1;
 }
 
-static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
+static void cfq_dispatch_insert(request_queue_t *q, struct request *rq)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
-       struct cfq_queue *cfqq = crq->cfq_queue;
-       struct request *rq;
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
 
-       cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
-       cfq_remove_request(crq->request);
-       cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
-       elv_dispatch_sort(q, crq->request);
+       cfq_remove_request(rq);
+       cfqq->on_dispatch[rq_is_sync(rq)]++;
+       elv_dispatch_sort(q, rq);
 
        rq = list_entry(q->queue_head.prev, struct request, queuelist);
        cfqd->last_sector = rq->sector + rq->nr_sectors;
@@ -960,24 +781,23 @@ static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
 /*
  * return expired entry, or NULL to just start from scratch in rbtree
  */
-static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq)
+static inline struct request *cfq_check_fifo(struct cfq_queue *cfqq)
 {
        struct cfq_data *cfqd = cfqq->cfqd;
        struct request *rq;
-       struct cfq_rq *crq;
+       int fifo;
 
        if (cfq_cfqq_fifo_expire(cfqq))
                return NULL;
+       if (list_empty(&cfqq->fifo))
+               return NULL;
 
-       if (!list_empty(&cfqq->fifo)) {
-               int fifo = cfq_cfqq_class_sync(cfqq);
+       fifo = cfq_cfqq_class_sync(cfqq);
+       rq = rq_entry_fifo(cfqq->fifo.next);
 
-               crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next));
-               rq = crq->request;
-               if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
-                       cfq_mark_cfqq_fifo_expire(cfqq);
-                       return crq;
-               }
+       if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
+               cfq_mark_cfqq_fifo_expire(cfqq);
+               return rq;
        }
 
        return NULL;
@@ -1063,25 +883,25 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
 
        do {
-               struct cfq_rq *crq;
+               struct request *rq;
 
                /*
                 * follow expired path, else get first next available
                 */
-               if ((crq = cfq_check_fifo(cfqq)) == NULL)
-                       crq = cfqq->next_crq;
+               if ((rq = cfq_check_fifo(cfqq)) == NULL)
+                       rq = cfqq->next_rq;
 
                /*
                 * finally, insert request into driver dispatch list
                 */
-               cfq_dispatch_insert(cfqd->queue, crq);
+               cfq_dispatch_insert(cfqd->queue, rq);
 
                cfqd->dispatch_slice++;
                dispatched++;
 
                if (!cfqd->active_cic) {
-                       atomic_inc(&crq->io_context->ioc->refcount);
-                       cfqd->active_cic = crq->io_context;
+                       atomic_inc(&RQ_CIC(rq)->ioc->refcount);
+                       cfqd->active_cic = RQ_CIC(rq);
                }
 
                if (RB_EMPTY_ROOT(&cfqq->sort_list))
@@ -1112,13 +932,12 @@ static int
 cfq_forced_dispatch_cfqqs(struct list_head *list)
 {
        struct cfq_queue *cfqq, *next;
-       struct cfq_rq *crq;
        int dispatched;
 
        dispatched = 0;
        list_for_each_entry_safe(cfqq, next, list, cfq_list) {
-               while ((crq = cfqq->next_crq)) {
-                       cfq_dispatch_insert(cfqq->cfqd->queue, crq);
+               while (cfqq->next_rq) {
+                       cfq_dispatch_insert(cfqq->cfqd->queue, cfqq->next_rq);
                        dispatched++;
                }
                BUG_ON(!list_empty(&cfqq->fifo));
@@ -1194,8 +1013,8 @@ cfq_dispatch_requests(request_queue_t *q, int force)
 }
 
 /*
- * task holds one reference to the queue, dropped when task exits. each crq
- * in-flight on this queue also holds a reference, dropped when crq is freed.
+ * task holds one reference to the queue, dropped when task exits. each rq
+ * in-flight on this queue also holds a reference, dropped when rq is freed.
  *
  * queue lock must be held here.
  */
@@ -1223,7 +1042,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
        kmem_cache_free(cfq_pool, cfqq);
 }
 
-static inline struct cfq_queue *
+static struct cfq_queue *
 __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
                    const int hashval)
 {
@@ -1260,62 +1079,63 @@ static void cfq_free_io_context(struct io_context *ioc)
                freed++;
        }
 
-       if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone)
+       elv_ioc_count_mod(ioc_count, -freed);
+
+       if (ioc_gone && !elv_ioc_count_read(ioc_count))
                complete(ioc_gone);
 }
 
-static void cfq_trim(struct io_context *ioc)
+static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-       ioc->set_ioprio = NULL;
-       cfq_free_io_context(ioc);
+       if (unlikely(cfqq == cfqd->active_queue))
+               __cfq_slice_expired(cfqd, cfqq, 0);
+
+       cfq_put_queue(cfqq);
 }
 
-/*
- * Called with interrupts disabled
- */
-static void cfq_exit_single_io_context(struct cfq_io_context *cic)
+static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
+                                        struct cfq_io_context *cic)
 {
-       struct cfq_data *cfqd = cic->key;
-       request_queue_t *q;
-
-       if (!cfqd)
-               return;
-
-       q = cfqd->queue;
-
-       WARN_ON(!irqs_disabled());
-
-       spin_lock(q->queue_lock);
+       list_del_init(&cic->queue_list);
+       smp_wmb();
+       cic->key = NULL;
 
        if (cic->cfqq[ASYNC]) {
-               if (unlikely(cic->cfqq[ASYNC] == cfqd->active_queue))
-                       __cfq_slice_expired(cfqd, cic->cfqq[ASYNC], 0);
-               cfq_put_queue(cic->cfqq[ASYNC]);
+               cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]);
                cic->cfqq[ASYNC] = NULL;
        }
 
        if (cic->cfqq[SYNC]) {
-               if (unlikely(cic->cfqq[SYNC] == cfqd->active_queue))
-                       __cfq_slice_expired(cfqd, cic->cfqq[SYNC], 0);
-               cfq_put_queue(cic->cfqq[SYNC]);
+               cfq_exit_cfqq(cfqd, cic->cfqq[SYNC]);
                cic->cfqq[SYNC] = NULL;
        }
+}
 
-       cic->key = NULL;
-       list_del_init(&cic->queue_list);
-       spin_unlock(q->queue_lock);
+
+/*
+ * Called with interrupts disabled
+ */
+static void cfq_exit_single_io_context(struct cfq_io_context *cic)
+{
+       struct cfq_data *cfqd = cic->key;
+
+       if (cfqd) {
+               request_queue_t *q = cfqd->queue;
+
+               spin_lock_irq(q->queue_lock);
+               __cfq_exit_single_io_context(cfqd, cic);
+               spin_unlock_irq(q->queue_lock);
+       }
 }
 
 static void cfq_exit_io_context(struct io_context *ioc)
 {
        struct cfq_io_context *__cic;
-       unsigned long flags;
        struct rb_node *n;
 
        /*
         * put the reference this task is holding to the various queues
         */
-       spin_lock_irqsave(&cfq_exit_lock, flags);
 
        n = rb_first(&ioc->cic_root);
        while (n != NULL) {
@@ -1324,22 +1144,21 @@ static void cfq_exit_io_context(struct io_context *ioc)
                cfq_exit_single_io_context(__cic);
                n = rb_next(n);
        }
-
-       spin_unlock_irqrestore(&cfq_exit_lock, flags);
 }
 
 static struct cfq_io_context *
 cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 {
-       struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
+       struct cfq_io_context *cic;
 
+       cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask, cfqd->queue->node);
        if (cic) {
                memset(cic, 0, sizeof(*cic));
                cic->last_end_request = jiffies;
                INIT_LIST_HEAD(&cic->queue_list);
                cic->dtor = cfq_free_io_context;
                cic->exit = cfq_exit_io_context;
-               atomic_inc(&ioc_count);
+               elv_ioc_count_inc(ioc_count);
        }
 
        return cic;
@@ -1420,15 +1239,12 @@ static inline void changed_ioprio(struct cfq_io_context *cic)
        spin_unlock(cfqd->queue->queue_lock);
 }
 
-/*
- * callback from sys_ioprio_set, irqs are disabled
- */
-static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
+static void cfq_ioc_set_ioprio(struct io_context *ioc)
 {
        struct cfq_io_context *cic;
        struct rb_node *n;
 
-       spin_lock(&cfq_exit_lock);
+       ioc->ioprio_changed = 0;
 
        n = rb_first(&ioc->cic_root);
        while (n != NULL) {
@@ -1437,10 +1253,6 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
                changed_ioprio(cic);
                n = rb_next(n);
        }
-
-       spin_unlock(&cfq_exit_lock);
-
-       return 0;
 }
 
 static struct cfq_queue *
@@ -1460,12 +1272,18 @@ retry:
                        cfqq = new_cfqq;
                        new_cfqq = NULL;
                } else if (gfp_mask & __GFP_WAIT) {
+                       /*
+                        * Inform the allocator of the fact that we will
+                        * just repeat this allocation if it fails, to allow
+                        * the allocator to do whatever it needs to attempt to
+                        * free memory.
+                        */
                        spin_unlock_irq(cfqd->queue->queue_lock);
-                       new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
+                       new_cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask|__GFP_NOFAIL, cfqd->queue->node);
                        spin_lock_irq(cfqd->queue->queue_lock);
                        goto retry;
                } else {
-                       cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
+                       cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask, cfqd->queue->node);
                        if (!cfqq)
                                goto out;
                }
@@ -1480,13 +1298,13 @@ retry:
                hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
                atomic_set(&cfqq->ref, 0);
                cfqq->cfqd = cfqd;
-               cfqq->service_last = 0;
                /*
                 * set ->slice_left to allow preemption for a new process
                 */
                cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
                cfq_mark_cfqq_idle_window(cfqq);
                cfq_mark_cfqq_prio_changed(cfqq);
+               cfq_mark_cfqq_queue_new(cfqq);
                cfq_init_prio_data(cfqq);
        }
 
@@ -1502,12 +1320,10 @@ out:
 static void
 cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
 {
-       spin_lock(&cfq_exit_lock);
+       WARN_ON(!list_empty(&cic->queue_list));
        rb_erase(&cic->rb_node, &ioc->cic_root);
-       list_del_init(&cic->queue_list);
-       spin_unlock(&cfq_exit_lock);
        kmem_cache_free(cfq_ioc_pool, cic);
-       atomic_dec(&ioc_count);
+       elv_ioc_count_dec(ioc_count);
 }
 
 static struct cfq_io_context *
@@ -1551,7 +1367,6 @@ cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
        cic->ioc = ioc;
        cic->key = cfqd;
 
-       ioc->set_ioprio = cfq_ioc_set_ioprio;
 restart:
        parent = NULL;
        p = &ioc->cic_root.rb_node;
@@ -1573,11 +1388,12 @@ restart:
                        BUG();
        }
 
-       spin_lock(&cfq_exit_lock);
        rb_link_node(&cic->rb_node, parent, p);
        rb_insert_color(&cic->rb_node, &ioc->cic_root);
+
+       spin_lock_irq(cfqd->queue->queue_lock);
        list_add(&cic->queue_list, &cfqd->cic_list);
-       spin_unlock(&cfq_exit_lock);
+       spin_unlock_irq(cfqd->queue->queue_lock);
 }
 
 /*
@@ -1593,7 +1409,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
-       ioc = get_io_context(gfp_mask);
+       ioc = get_io_context(gfp_mask, cfqd->queue->node);
        if (!ioc)
                return NULL;
 
@@ -1607,6 +1423,10 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 
        cfq_cic_link(cfqd, ioc, cic);
 out:
+       smp_read_barrier_depends();
+       if (unlikely(ioc->ioprio_changed))
+               cfq_ioc_set_ioprio(ioc);
+
        return cic;
 err:
        put_io_context(ioc);
@@ -1640,15 +1460,15 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
 
 static void
 cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
-                      struct cfq_rq *crq)
+                      struct request *rq)
 {
        sector_t sdist;
        u64 total;
 
-       if (cic->last_request_pos < crq->request->sector)
-               sdist = crq->request->sector - cic->last_request_pos;
+       if (cic->last_request_pos < rq->sector)
+               sdist = rq->sector - cic->last_request_pos;
        else
-               sdist = cic->last_request_pos - crq->request->sector;
+               sdist = cic->last_request_pos - rq->sector;
 
        /*
         * Don't allow the seek distance to get too large from the
@@ -1699,7 +1519,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  */
 static int
 cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
-                  struct cfq_rq *crq)
+                  struct request *rq)
 {
        struct cfq_queue *cfqq = cfqd->active_queue;
 
@@ -1718,7 +1538,17 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
         */
        if (new_cfqq->slice_left < cfqd->cfq_slice_idle)
                return 0;
-       if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq))
+       /*
+        * if the new request is sync, but the currently running queue is
+        * not, let the sync request have priority.
+        */
+       if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq))
+               return 1;
+       /*
+        * So both queues are sync. Let the new request get disk time if
+        * it's a metadata request and the current queue is doing regular IO.
+        */
+       if (rq_is_meta(rq) && !cfqq->meta_pending)
                return 1;
 
        return 0;
@@ -1730,47 +1560,45 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
  */
 static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-       struct cfq_queue *__cfqq, *next;
-
-       list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list)
-               cfq_resort_rr_list(__cfqq, 1);
+       cfq_slice_expired(cfqd, 1);
 
        if (!cfqq->slice_left)
                cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2;
 
-       cfqq->slice_end = cfqq->slice_left + jiffies;
-       cfq_slice_expired(cfqd, 1);
-       __cfq_set_active_queue(cfqd, cfqq);
-}
-
-/*
- * should really be a ll_rw_blk.c helper
- */
-static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq)
-{
-       request_queue_t *q = cfqd->queue;
+       /*
+        * Put the new queue at the front of the of the current list,
+        * so we know that it will be selected next.
+        */
+       BUG_ON(!cfq_cfqq_on_rr(cfqq));
+       list_move(&cfqq->cfq_list, &cfqd->cur_rr);
 
-       if (!blk_queue_plugged(q))
-               q->request_fn(q);
-       else
-               __generic_unplug_device(q);
+       cfqq->slice_end = cfqq->slice_left + jiffies;
 }
 
 /*
- * Called when a new fs request (crq) is added (to cfqq). Check if there's
+ * Called when a new fs request (rq) is added (to cfqq). Check if there's
  * something we should do about it
  */
 static void
-cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                struct cfq_rq *crq)
+cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+               struct request *rq)
 {
-       struct cfq_io_context *cic = crq->io_context;
+       struct cfq_io_context *cic = RQ_CIC(rq);
+
+       if (rq_is_meta(rq))
+               cfqq->meta_pending++;
+
+       /*
+        * check if this request is a better next-serve candidate)) {
+        */
+       cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq);
+       BUG_ON(!cfqq->next_rq);
 
        /*
         * we never wait for an async request and we don't allow preemption
         * of an async request. so just return early
         */
-       if (!cfq_crq_is_sync(crq)) {
+       if (!rq_is_sync(rq)) {
                /*
                 * sync process issued an async request, if it's waiting
                 * then expire it and kick rq handling.
@@ -1778,17 +1606,17 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                if (cic == cfqd->active_cic &&
                    del_timer(&cfqd->idle_slice_timer)) {
                        cfq_slice_expired(cfqd, 0);
-                       cfq_start_queueing(cfqd, cfqq);
+                       blk_start_queueing(cfqd->queue);
                }
                return;
        }
 
        cfq_update_io_thinktime(cfqd, cic);
-       cfq_update_io_seektime(cfqd, cic, crq);
+       cfq_update_io_seektime(cfqd, cic, rq);
        cfq_update_idle_window(cfqd, cfqq, cic);
 
        cic->last_queue = jiffies;
-       cic->last_request_pos = crq->request->sector + crq->request->nr_sectors;
+       cic->last_request_pos = rq->sector + rq->nr_sectors;
 
        if (cfqq == cfqd->active_queue) {
                /*
@@ -1799,9 +1627,9 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                if (cfq_cfqq_wait_request(cfqq)) {
                        cfq_mark_cfqq_must_dispatch(cfqq);
                        del_timer(&cfqd->idle_slice_timer);
-                       cfq_start_queueing(cfqd, cfqq);
+                       blk_start_queueing(cfqd->queue);
                }
-       } else if (cfq_should_preempt(cfqd, cfqq, crq)) {
+       } else if (cfq_should_preempt(cfqd, cfqq, rq)) {
                /*
                 * not the active queue - expire current slice if it is
                 * idle and has expired it's mean thinktime or this new queue
@@ -1809,34 +1637,32 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                 */
                cfq_preempt_queue(cfqd, cfqq);
                cfq_mark_cfqq_must_dispatch(cfqq);
-               cfq_start_queueing(cfqd, cfqq);
+               blk_start_queueing(cfqd->queue);
        }
 }
 
 static void cfq_insert_request(request_queue_t *q, struct request *rq)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
-       struct cfq_rq *crq = RQ_DATA(rq);
-       struct cfq_queue *cfqq = crq->cfq_queue;
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
 
        cfq_init_prio_data(cfqq);
 
-       cfq_add_crq_rb(crq);
+       cfq_add_rq_rb(rq);
 
-       list_add_tail(&rq->queuelist, &cfqq->fifo);
+       if (!cfq_cfqq_on_rr(cfqq))
+               cfq_add_cfqq_rr(cfqd, cfqq);
 
-       if (rq_mergeable(rq))
-               cfq_add_crq_hash(cfqd, crq);
+       list_add_tail(&rq->queuelist, &cfqq->fifo);
 
-       cfq_crq_enqueued(cfqd, cfqq, crq);
+       cfq_rq_enqueued(cfqd, cfqq, rq);
 }
 
 static void cfq_completed_request(request_queue_t *q, struct request *rq)
 {
-       struct cfq_rq *crq = RQ_DATA(rq);
-       struct cfq_queue *cfqq = crq->cfq_queue;
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
        struct cfq_data *cfqd = cfqq->cfqd;
-       const int sync = cfq_crq_is_sync(crq);
+       const int sync = rq_is_sync(rq);
        unsigned long now;
 
        now = jiffies;
@@ -1849,15 +1675,11 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
        if (!cfq_class_idle(cfqq))
                cfqd->last_end_request = now;
 
-       if (!cfq_cfqq_dispatched(cfqq)) {
-               if (cfq_cfqq_on_rr(cfqq)) {
-                       cfqq->service_last = now;
-                       cfq_resort_rr_list(cfqq, 0);
-               }
-       }
+       if (!cfq_cfqq_dispatched(cfqq) && cfq_cfqq_on_rr(cfqq))
+               cfq_resort_rr_list(cfqq, 0);
 
        if (sync)
-               crq->io_context->last_end_request = now;
+               RQ_CIC(rq)->last_end_request = now;
 
        /*
         * If this is the active queue, check if it needs to be expired,
@@ -1873,30 +1695,6 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
        }
 }
 
-static struct request *
-cfq_former_request(request_queue_t *q, struct request *rq)
-{
-       struct cfq_rq *crq = RQ_DATA(rq);
-       struct rb_node *rbprev = rb_prev(&crq->rb_node);
-
-       if (rbprev)
-               return rb_entry_crq(rbprev)->request;
-
-       return NULL;
-}
-
-static struct request *
-cfq_latter_request(request_queue_t *q, struct request *rq)
-{
-       struct cfq_rq *crq = RQ_DATA(rq);
-       struct rb_node *rbnext = rb_next(&crq->rb_node);
-
-       if (rbnext)
-               return rb_entry_crq(rbnext)->request;
-
-       return NULL;
-}
-
 /*
  * we temporarily boost lower priority queues if they are holding fs exclusive
  * resources. they are boosted to normal prio (CLASS_BE/4)
@@ -1933,9 +1731,7 @@ static void cfq_prio_boost(struct cfq_queue *cfqq)
                cfq_resort_rr_list(cfqq, 0);
 }
 
-static inline int
-__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-               struct task_struct *task, int rw)
+static inline int __cfq_may_queue(struct cfq_queue *cfqq)
 {
        if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
            !cfq_cfqq_must_alloc_slice(cfqq)) {
@@ -1946,7 +1742,7 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        return ELV_MQUEUE_MAY;
 }
 
-static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio)
+static int cfq_may_queue(request_queue_t *q, int rw)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct task_struct *tsk = current;
@@ -1963,48 +1759,30 @@ static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio)
                cfq_init_prio_data(cfqq);
                cfq_prio_boost(cfqq);
 
-               return __cfq_may_queue(cfqd, cfqq, tsk, rw);
+               return __cfq_may_queue(cfqq);
        }
 
        return ELV_MQUEUE_MAY;
 }
 
-static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq)
-{
-       struct cfq_data *cfqd = q->elevator->elevator_data;
-
-       if (unlikely(cfqd->rq_starved)) {
-               struct request_list *rl = &q->rq;
-
-               smp_mb();
-               if (waitqueue_active(&rl->wait[READ]))
-                       wake_up(&rl->wait[READ]);
-               if (waitqueue_active(&rl->wait[WRITE]))
-                       wake_up(&rl->wait[WRITE]);
-       }
-}
-
 /*
  * queue lock held here
  */
 static void cfq_put_request(request_queue_t *q, struct request *rq)
 {
-       struct cfq_data *cfqd = q->elevator->elevator_data;
-       struct cfq_rq *crq = RQ_DATA(rq);
+       struct cfq_queue *cfqq = RQ_CFQQ(rq);
 
-       if (crq) {
-               struct cfq_queue *cfqq = crq->cfq_queue;
+       if (cfqq) {
                const int rw = rq_data_dir(rq);
 
                BUG_ON(!cfqq->allocated[rw]);
                cfqq->allocated[rw]--;
 
-               put_io_context(crq->io_context->ioc);
+               put_io_context(RQ_CIC(rq)->ioc);
 
-               mempool_free(crq, cfqd->crq_pool);
                rq->elevator_private = NULL;
+               rq->elevator_private2 = NULL;
 
-               cfq_check_waiters(q, cfqq);
                cfq_put_queue(cfqq);
        }
 }
@@ -2013,8 +1791,7 @@ static void cfq_put_request(request_queue_t *q, struct request *rq)
  * Allocate cfq data structures associated with this request.
  */
 static int
-cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-               gfp_t gfp_mask)
+cfq_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask)
 {
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct task_struct *tsk = current;
@@ -2022,7 +1799,6 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
        const int rw = rq_data_dir(rq);
        pid_t key = cfq_queue_pid(tsk, rw);
        struct cfq_queue *cfqq;
-       struct cfq_rq *crq;
        unsigned long flags;
        int is_sync = key != CFQ_KEY_ASYNC;
 
@@ -2046,42 +1822,18 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
 
        cfqq->allocated[rw]++;
        cfq_clear_cfqq_must_alloc(cfqq);
-       cfqd->rq_starved = 0;
        atomic_inc(&cfqq->ref);
-       spin_unlock_irqrestore(q->queue_lock, flags);
 
-       crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
-       if (crq) {
-               RB_CLEAR_NODE(&crq->rb_node);
-               crq->rb_key = 0;
-               crq->request = rq;
-               INIT_HLIST_NODE(&crq->hash);
-               crq->cfq_queue = cfqq;
-               crq->io_context = cic;
-
-               if (is_sync)
-                       cfq_mark_crq_is_sync(crq);
-               else
-                       cfq_clear_crq_is_sync(crq);
+       spin_unlock_irqrestore(q->queue_lock, flags);
 
-               rq->elevator_private = crq;
-               return 0;
-       }
+       rq->elevator_private = cic;
+       rq->elevator_private2 = cfqq;
+       return 0;
 
-       spin_lock_irqsave(q->queue_lock, flags);
-       cfqq->allocated[rw]--;
-       if (!(cfqq->allocated[0] + cfqq->allocated[1]))
-               cfq_mark_cfqq_must_alloc(cfqq);
-       cfq_put_queue(cfqq);
 queue_fail:
        if (cic)
                put_io_context(cic->ioc);
-       /*
-        * mark us rq allocation starved. we need to kickstart the process
-        * ourselves if there are no pending requests that can do it for us.
-        * that would be an extremely rare OOM situation
-        */
-       cfqd->rq_starved = 1;
+
        cfq_schedule_dispatch(cfqd);
        spin_unlock_irqrestore(q->queue_lock, flags);
        return 1;
@@ -2090,27 +1842,10 @@ queue_fail:
 static void cfq_kick_queue(void *data)
 {
        request_queue_t *q = data;
-       struct cfq_data *cfqd = q->elevator->elevator_data;
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
-
-       if (cfqd->rq_starved) {
-               struct request_list *rl = &q->rq;
-
-               /*
-                * we aren't guaranteed to get a request after this, but we
-                * have to be opportunistic
-                */
-               smp_mb();
-               if (waitqueue_active(&rl->wait[READ]))
-                       wake_up(&rl->wait[READ]);
-               if (waitqueue_active(&rl->wait[WRITE]))
-                       wake_up(&rl->wait[WRITE]);
-       }
-
-       blk_remove_plug(q);
-       q->request_fn(q);
+       blk_start_queueing(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -2193,7 +1928,6 @@ static void cfq_exit_queue(elevator_t *e)
 
        cfq_shutdown_timer_wq(cfqd);
 
-       spin_lock(&cfq_exit_lock);
        spin_lock_irq(q->queue_lock);
 
        if (cfqd->active_queue)
@@ -2203,25 +1937,14 @@ static void cfq_exit_queue(elevator_t *e)
                struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
                                                        struct cfq_io_context,
                                                        queue_list);
-               if (cic->cfqq[ASYNC]) {
-                       cfq_put_queue(cic->cfqq[ASYNC]);
-                       cic->cfqq[ASYNC] = NULL;
-               }
-               if (cic->cfqq[SYNC]) {
-                       cfq_put_queue(cic->cfqq[SYNC]);
-                       cic->cfqq[SYNC] = NULL;
-               }
-               cic->key = NULL;
-               list_del_init(&cic->queue_list);
+
+               __cfq_exit_single_io_context(cfqd, cic);
        }
 
        spin_unlock_irq(q->queue_lock);
-       spin_unlock(&cfq_exit_lock);
 
        cfq_shutdown_timer_wq(cfqd);
 
-       mempool_destroy(cfqd->crq_pool);
-       kfree(cfqd->crq_hash);
        kfree(cfqd->cfq_hash);
        kfree(cfqd);
 }
@@ -2231,7 +1954,7 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
        struct cfq_data *cfqd;
        int i;
 
-       cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
+       cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node);
        if (!cfqd)
                return NULL;
 
@@ -2243,23 +1966,12 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
        INIT_LIST_HEAD(&cfqd->busy_rr);
        INIT_LIST_HEAD(&cfqd->cur_rr);
        INIT_LIST_HEAD(&cfqd->idle_rr);
-       INIT_LIST_HEAD(&cfqd->empty_list);
        INIT_LIST_HEAD(&cfqd->cic_list);
 
-       cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
-       if (!cfqd->crq_hash)
-               goto out_crqhash;
-
-       cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL);
+       cfqd->cfq_hash = kmalloc_node(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL, q->node);
        if (!cfqd->cfq_hash)
-               goto out_cfqhash;
-
-       cfqd->crq_pool = mempool_create_slab_pool(BLKDEV_MIN_RQ, crq_pool);
-       if (!cfqd->crq_pool)
-               goto out_crqpool;
+               goto out_free;
 
-       for (i = 0; i < CFQ_MHASH_ENTRIES; i++)
-               INIT_HLIST_HEAD(&cfqd->crq_hash[i]);
        for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
                INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
 
@@ -2275,7 +1987,6 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
 
        INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
 
-       cfqd->cfq_queued = cfq_queued;
        cfqd->cfq_quantum = cfq_quantum;
        cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
        cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
@@ -2287,19 +1998,13 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
        cfqd->cfq_slice_idle = cfq_slice_idle;
 
        return cfqd;
-out_crqpool:
-       kfree(cfqd->cfq_hash);
-out_cfqhash:
-       kfree(cfqd->crq_hash);
-out_crqhash:
+out_free:
        kfree(cfqd);
        return NULL;
 }
 
 static void cfq_slab_kill(void)
 {
-       if (crq_pool)
-               kmem_cache_destroy(crq_pool);
        if (cfq_pool)
                kmem_cache_destroy(cfq_pool);
        if (cfq_ioc_pool)
@@ -2308,11 +2013,6 @@ static void cfq_slab_kill(void)
 
 static int __init cfq_slab_setup(void)
 {
-       crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0,
-                                       NULL, NULL);
-       if (!crq_pool)
-               goto fail;
-
        cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0,
                                        NULL, NULL);
        if (!cfq_pool)
@@ -2358,7 +2058,6 @@ static ssize_t __FUNC(elevator_t *e, char *page)                  \
        return cfq_var_show(__data, (page));                            \
 }
 SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0);
-SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0);
 SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1);
 SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
 SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0);
@@ -2386,7 +2085,6 @@ static ssize_t __FUNC(elevator_t *e, const char *page, size_t count)      \
        return ret;                                                     \
 }
 STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0);
 STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
@@ -2402,7 +2100,6 @@ STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX,
 
 static struct elv_fs_entry cfq_attrs[] = {
        CFQ_ATTR(quantum),
-       CFQ_ATTR(queued),
        CFQ_ATTR(fifo_expire_sync),
        CFQ_ATTR(fifo_expire_async),
        CFQ_ATTR(back_seek_max),
@@ -2425,14 +2122,14 @@ static struct elevator_type iosched_cfq = {
                .elevator_deactivate_req_fn =   cfq_deactivate_request,
                .elevator_queue_empty_fn =      cfq_queue_empty,
                .elevator_completed_req_fn =    cfq_completed_request,
-               .elevator_former_req_fn =       cfq_former_request,
-               .elevator_latter_req_fn =       cfq_latter_request,
+               .elevator_former_req_fn =       elv_rb_former_request,
+               .elevator_latter_req_fn =       elv_rb_latter_request,
                .elevator_set_req_fn =          cfq_set_request,
                .elevator_put_req_fn =          cfq_put_request,
                .elevator_may_queue_fn =        cfq_may_queue,
                .elevator_init_fn =             cfq_init_queue,
                .elevator_exit_fn =             cfq_exit_queue,
-               .trim =                         cfq_trim,
+               .trim =                         cfq_free_io_context,
        },
        .elevator_attrs =       cfq_attrs,
        .elevator_name =        "cfq",
@@ -2463,12 +2160,12 @@ static int __init cfq_init(void)
 
 static void __exit cfq_exit(void)
 {
-       DECLARE_COMPLETION(all_gone);
+       DECLARE_COMPLETION_ONSTACK(all_gone);
        elv_unregister(&iosched_cfq);
        ioc_gone = &all_gone;
        /* ioc_gone's update must be visible before reading ioc_count */
        smp_wmb();
-       if (atomic_read(&ioc_count))
+       if (elv_ioc_count_read(ioc_count))
                wait_for_completion(ioc_gone);
        synchronize_rcu();
        cfq_slab_kill();
index c7ca9f0b64989cdda8a16a56593fd52f2a251470..b7c5b34cb7b43b4688b3f4bbda5951726bbb008a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Deadline i/o scheduler.
  *
- *  Copyright (C) 2002 Jens Axboe <axboe@suse.de>
+ *  Copyright (C) 2002 Jens Axboe <axboe@kernel.dk>
  */
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/compiler.h>
-#include <linux/hash.h>
 #include <linux/rbtree.h>
 
 /*
@@ -24,13 +23,6 @@ static const int writes_starved = 2;    /* max times reads can starve a write */
 static const int fifo_batch = 16;       /* # of sequential requests treated as one
                                     by the above parameters. For throughput. */
 
-static const int deadline_hash_shift = 5;
-#define DL_HASH_BLOCK(sec)     ((sec) >> 3)
-#define DL_HASH_FN(sec)                (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift))
-#define DL_HASH_ENTRIES                (1 << deadline_hash_shift)
-#define rq_hash_key(rq)                ((rq)->sector + (rq)->nr_sectors)
-#define ON_HASH(drq)           (!hlist_unhashed(&(drq)->hash))
-
 struct deadline_data {
        /*
         * run time data
@@ -45,8 +37,7 @@ struct deadline_data {
        /*
         * next in sort order. read, write or both are NULL
         */
-       struct deadline_rq *next_drq[2];
-       struct hlist_head *hash;        /* request hash */
+       struct request *next_rq[2];
        unsigned int batching;          /* number of sequential requests made */
        sector_t last_sector;           /* head position */
        unsigned int starved;           /* times reads have starved writes */
@@ -58,240 +49,69 @@ struct deadline_data {
        int fifo_batch;
        int writes_starved;
        int front_merges;
-
-       mempool_t *drq_pool;
 };
 
-/*
- * pre-request data.
- */
-struct deadline_rq {
-       /*
-        * rbtree index, key is the starting offset
-        */
-       struct rb_node rb_node;
-       sector_t rb_key;
-
-       struct request *request;
-
-       /*
-        * request hash, key is the ending offset (for back merge lookup)
-        */
-       struct hlist_node hash;
-
-       /*
-        * expire fifo
-        */
-       struct list_head fifo;
-       unsigned long expires;
-};
-
-static void deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq);
-
-static kmem_cache_t *drq_pool;
-
-#define RQ_DATA(rq)    ((struct deadline_rq *) (rq)->elevator_private)
+static void deadline_move_request(struct deadline_data *, struct request *);
 
-/*
- * the back merge hash support functions
- */
-static inline void __deadline_del_drq_hash(struct deadline_rq *drq)
-{
-       hlist_del_init(&drq->hash);
-}
-
-static inline void deadline_del_drq_hash(struct deadline_rq *drq)
-{
-       if (ON_HASH(drq))
-               __deadline_del_drq_hash(drq);
-}
-
-static inline void
-deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
-{
-       struct request *rq = drq->request;
-
-       BUG_ON(ON_HASH(drq));
-
-       hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]);
-}
-
-/*
- * move hot entry to front of chain
- */
-static inline void
-deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
-{
-       struct request *rq = drq->request;
-       struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))];
-
-       if (ON_HASH(drq) && &drq->hash != head->first) {
-               hlist_del(&drq->hash);
-               hlist_add_head(&drq->hash, head);
-       }
-}
-
-static struct request *
-deadline_find_drq_hash(struct deadline_data *dd, sector_t offset)
-{
-       struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)];
-       struct hlist_node *entry, *next;
-       struct deadline_rq *drq;
-
-       hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) {
-               struct request *__rq = drq->request;
-
-               BUG_ON(!ON_HASH(drq));
-
-               if (!rq_mergeable(__rq)) {
-                       __deadline_del_drq_hash(drq);
-                       continue;
-               }
-
-               if (rq_hash_key(__rq) == offset)
-                       return __rq;
-       }
-
-       return NULL;
-}
-
-/*
- * rb tree support functions
- */
-#define rb_entry_drq(node)     rb_entry((node), struct deadline_rq, rb_node)
-#define DRQ_RB_ROOT(dd, drq)   (&(dd)->sort_list[rq_data_dir((drq)->request)])
-#define rq_rb_key(rq)          (rq)->sector
-
-static struct deadline_rq *
-__deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
-{
-       struct rb_node **p = &DRQ_RB_ROOT(dd, drq)->rb_node;
-       struct rb_node *parent = NULL;
-       struct deadline_rq *__drq;
-
-       while (*p) {
-               parent = *p;
-               __drq = rb_entry_drq(parent);
-
-               if (drq->rb_key < __drq->rb_key)
-                       p = &(*p)->rb_left;
-               else if (drq->rb_key > __drq->rb_key)
-                       p = &(*p)->rb_right;
-               else
-                       return __drq;
-       }
-
-       rb_link_node(&drq->rb_node, parent, p);
-       return NULL;
-}
+#define RQ_RB_ROOT(dd, rq)     (&(dd)->sort_list[rq_data_dir((rq))])
 
 static void
-deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
+deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
 {
-       struct deadline_rq *__alias;
-
-       drq->rb_key = rq_rb_key(drq->request);
+       struct rb_root *root = RQ_RB_ROOT(dd, rq);
+       struct request *__alias;
 
 retry:
-       __alias = __deadline_add_drq_rb(dd, drq);
-       if (!__alias) {
-               rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
-               return;
+       __alias = elv_rb_add(root, rq);
+       if (unlikely(__alias)) {
+               deadline_move_request(dd, __alias);
+               goto retry;
        }
-
-       deadline_move_request(dd, __alias);
-       goto retry;
 }
 
 static inline void
-deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
+deadline_del_rq_rb(struct deadline_data *dd, struct request *rq)
 {
-       const int data_dir = rq_data_dir(drq->request);
+       const int data_dir = rq_data_dir(rq);
 
-       if (dd->next_drq[data_dir] == drq) {
-               struct rb_node *rbnext = rb_next(&drq->rb_node);
+       if (dd->next_rq[data_dir] == rq) {
+               struct rb_node *rbnext = rb_next(&rq->rb_node);
 
-               dd->next_drq[data_dir] = NULL;
+               dd->next_rq[data_dir] = NULL;
                if (rbnext)
-                       dd->next_drq[data_dir] = rb_entry_drq(rbnext);
-       }
-
-       BUG_ON(!RB_EMPTY_NODE(&drq->rb_node));
-       rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
-       RB_CLEAR_NODE(&drq->rb_node);
-}
-
-static struct request *
-deadline_find_drq_rb(struct deadline_data *dd, sector_t sector, int data_dir)
-{
-       struct rb_node *n = dd->sort_list[data_dir].rb_node;
-       struct deadline_rq *drq;
-
-       while (n) {
-               drq = rb_entry_drq(n);
-
-               if (sector < drq->rb_key)
-                       n = n->rb_left;
-               else if (sector > drq->rb_key)
-                       n = n->rb_right;
-               else
-                       return drq->request;
+                       dd->next_rq[data_dir] = rb_entry_rq(rbnext);
        }
 
-       return NULL;
+       elv_rb_del(RQ_RB_ROOT(dd, rq), rq);
 }
 
 /*
- * deadline_find_first_drq finds the first (lowest sector numbered) request
- * for the specified data_dir. Used to sweep back to the start of the disk
- * (1-way elevator) after we process the last (highest sector) request.
- */
-static struct deadline_rq *
-deadline_find_first_drq(struct deadline_data *dd, int data_dir)
-{
-       struct rb_node *n = dd->sort_list[data_dir].rb_node;
-
-       for (;;) {
-               if (n->rb_left == NULL)
-                       return rb_entry_drq(n);
-               
-               n = n->rb_left;
-       }
-}
-
-/*
- * add drq to rbtree and fifo
+ * add rq to rbtree and fifo
  */
 static void
 deadline_add_request(struct request_queue *q, struct request *rq)
 {
        struct deadline_data *dd = q->elevator->elevator_data;
-       struct deadline_rq *drq = RQ_DATA(rq);
+       const int data_dir = rq_data_dir(rq);
 
-       const int data_dir = rq_data_dir(drq->request);
+       deadline_add_rq_rb(dd, rq);
 
-       deadline_add_drq_rb(dd, drq);
        /*
         * set expire time (only used for reads) and add to fifo list
         */
-       drq->expires = jiffies + dd->fifo_expire[data_dir];
-       list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
-
-       if (rq_mergeable(rq))
-               deadline_add_drq_hash(dd, drq);
+       rq_set_fifo_time(rq, jiffies + dd->fifo_expire[data_dir]);
+       list_add_tail(&rq->queuelist, &dd->fifo_list[data_dir]);
 }
 
 /*
- * remove rq from rbtree, fifo, and hash
+ * remove rq from rbtree and fifo.
  */
 static void deadline_remove_request(request_queue_t *q, struct request *rq)
 {
-       struct deadline_rq *drq = RQ_DATA(rq);
        struct deadline_data *dd = q->elevator->elevator_data;
 
-       list_del_init(&drq->fifo);
-       deadline_del_drq_rb(dd, drq);
-       deadline_del_drq_hash(drq);
+       rq_fifo_clear(rq);
+       deadline_del_rq_rb(dd, rq);
 }
 
 static int
@@ -301,28 +121,15 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
        struct request *__rq;
        int ret;
 
-       /*
-        * see if the merge hash can satisfy a back merge
-        */
-       __rq = deadline_find_drq_hash(dd, bio->bi_sector);
-       if (__rq) {
-               BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
-
-               if (elv_rq_merge_ok(__rq, bio)) {
-                       ret = ELEVATOR_BACK_MERGE;
-                       goto out;
-               }
-       }
-
        /*
         * check for front merge
         */
        if (dd->front_merges) {
-               sector_t rb_key = bio->bi_sector + bio_sectors(bio);
+               sector_t sector = bio->bi_sector + bio_sectors(bio);
 
-               __rq = deadline_find_drq_rb(dd, rb_key, bio_data_dir(bio));
+               __rq = elv_rb_find(&dd->sort_list[bio_data_dir(bio)], sector);
                if (__rq) {
-                       BUG_ON(rb_key != rq_rb_key(__rq));
+                       BUG_ON(sector != __rq->sector);
 
                        if (elv_rq_merge_ok(__rq, bio)) {
                                ret = ELEVATOR_FRONT_MERGE;
@@ -333,29 +140,21 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
 
        return ELEVATOR_NO_MERGE;
 out:
-       if (ret)
-               deadline_hot_drq_hash(dd, RQ_DATA(__rq));
        *req = __rq;
        return ret;
 }
 
-static void deadline_merged_request(request_queue_t *q, struct request *req)
+static void deadline_merged_request(request_queue_t *q, struct request *req,
+                                   int type)
 {
        struct deadline_data *dd = q->elevator->elevator_data;
-       struct deadline_rq *drq = RQ_DATA(req);
-
-       /*
-        * hash always needs to be repositioned, key is end sector
-        */
-       deadline_del_drq_hash(drq);
-       deadline_add_drq_hash(dd, drq);
 
        /*
         * if the merge was a front merge, we need to reposition request
         */
-       if (rq_rb_key(req) != drq->rb_key) {
-               deadline_del_drq_rb(dd, drq);
-               deadline_add_drq_rb(dd, drq);
+       if (type == ELEVATOR_FRONT_MERGE) {
+               elv_rb_del(RQ_RB_ROOT(dd, req), req);
+               deadline_add_rq_rb(dd, req);
        }
 }
 
@@ -363,33 +162,14 @@ static void
 deadline_merged_requests(request_queue_t *q, struct request *req,
                         struct request *next)
 {
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct deadline_rq *drq = RQ_DATA(req);
-       struct deadline_rq *dnext = RQ_DATA(next);
-
-       BUG_ON(!drq);
-       BUG_ON(!dnext);
-
        /*
-        * reposition drq (this is the merged request) in hash, and in rbtree
-        * in case of a front merge
+        * if next expires before rq, assign its expire time to rq
+        * and move into next position (next will be deleted) in fifo
         */
-       deadline_del_drq_hash(drq);
-       deadline_add_drq_hash(dd, drq);
-
-       if (rq_rb_key(req) != drq->rb_key) {
-               deadline_del_drq_rb(dd, drq);
-               deadline_add_drq_rb(dd, drq);
-       }
-
-       /*
-        * if dnext expires before drq, assign its expire time to drq
-        * and move into dnext position (dnext will be deleted) in fifo
-        */
-       if (!list_empty(&drq->fifo) && !list_empty(&dnext->fifo)) {
-               if (time_before(dnext->expires, drq->expires)) {
-                       list_move(&drq->fifo, &dnext->fifo);
-                       drq->expires = dnext->expires;
+       if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
+               if (time_before(rq_fifo_time(next), rq_fifo_time(req))) {
+                       list_move(&req->queuelist, &next->queuelist);
+                       rq_set_fifo_time(req, rq_fifo_time(next));
                }
        }
 
@@ -403,52 +183,50 @@ deadline_merged_requests(request_queue_t *q, struct request *req,
  * move request from sort list to dispatch queue.
  */
 static inline void
-deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
+deadline_move_to_dispatch(struct deadline_data *dd, struct request *rq)
 {
-       request_queue_t *q = drq->request->q;
+       request_queue_t *q = rq->q;
 
-       deadline_remove_request(q, drq->request);
-       elv_dispatch_add_tail(q, drq->request);
+       deadline_remove_request(q, rq);
+       elv_dispatch_add_tail(q, rq);
 }
 
 /*
  * move an entry to dispatch queue
  */
 static void
-deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq)
+deadline_move_request(struct deadline_data *dd, struct request *rq)
 {
-       const int data_dir = rq_data_dir(drq->request);
-       struct rb_node *rbnext = rb_next(&drq->rb_node);
+       const int data_dir = rq_data_dir(rq);
+       struct rb_node *rbnext = rb_next(&rq->rb_node);
 
-       dd->next_drq[READ] = NULL;
-       dd->next_drq[WRITE] = NULL;
+       dd->next_rq[READ] = NULL;
+       dd->next_rq[WRITE] = NULL;
 
        if (rbnext)
-               dd->next_drq[data_dir] = rb_entry_drq(rbnext);
+               dd->next_rq[data_dir] = rb_entry_rq(rbnext);
        
-       dd->last_sector = drq->request->sector + drq->request->nr_sectors;
+       dd->last_sector = rq->sector + rq->nr_sectors;
 
        /*
         * take it off the sort and fifo list, move
         * to dispatch queue
         */
-       deadline_move_to_dispatch(dd, drq);
+       deadline_move_to_dispatch(dd, rq);
 }
 
-#define list_entry_fifo(ptr)   list_entry((ptr), struct deadline_rq, fifo)
-
 /*
  * deadline_check_fifo returns 0 if there are no expired reads on the fifo,
  * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
  */
 static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)
 {
-       struct deadline_rq *drq = list_entry_fifo(dd->fifo_list[ddir].next);
+       struct request *rq = rq_entry_fifo(dd->fifo_list[ddir].next);
 
        /*
-        * drq is expired!
+        * rq is expired!
         */
-       if (time_after(jiffies, drq->expires))
+       if (time_after(jiffies, rq_fifo_time(rq)))
                return 1;
 
        return 0;
@@ -463,21 +241,21 @@ static int deadline_dispatch_requests(request_queue_t *q, int force)
        struct deadline_data *dd = q->elevator->elevator_data;
        const int reads = !list_empty(&dd->fifo_list[READ]);
        const int writes = !list_empty(&dd->fifo_list[WRITE]);
-       struct deadline_rq *drq;
+       struct request *rq;
        int data_dir;
 
        /*
         * batches are currently reads XOR writes
         */
-       if (dd->next_drq[WRITE])
-               drq = dd->next_drq[WRITE];
+       if (dd->next_rq[WRITE])
+               rq = dd->next_rq[WRITE];
        else
-               drq = dd->next_drq[READ];
+               rq = dd->next_rq[READ];
 
-       if (drq) {
+       if (rq) {
                /* we have a "next request" */
                
-               if (dd->last_sector != drq->request->sector)
+               if (dd->last_sector != rq->sector)
                        /* end the batch on a non sequential request */
                        dd->batching += dd->fifo_batch;
                
@@ -526,30 +304,33 @@ dispatch_find_request:
        if (deadline_check_fifo(dd, data_dir)) {
                /* An expired request exists - satisfy it */
                dd->batching = 0;
-               drq = list_entry_fifo(dd->fifo_list[data_dir].next);
+               rq = rq_entry_fifo(dd->fifo_list[data_dir].next);
                
-       } else if (dd->next_drq[data_dir]) {
+       } else if (dd->next_rq[data_dir]) {
                /*
                 * The last req was the same dir and we have a next request in
                 * sort order. No expired requests so continue on from here.
                 */
-               drq = dd->next_drq[data_dir];
+               rq = dd->next_rq[data_dir];
        } else {
+               struct rb_node *node;
                /*
                 * The last req was the other direction or we have run out of
                 * higher-sectored requests. Go back to the lowest sectored
                 * request (1 way elevator) and start a new batch.
                 */
                dd->batching = 0;
-               drq = deadline_find_first_drq(dd, data_dir);
+               node = rb_first(&dd->sort_list[data_dir]);
+               if (node)
+                       rq = rb_entry_rq(node);
        }
 
 dispatch_request:
        /*
-        * drq is the selected appropriate request.
+        * rq is the selected appropriate request.
         */
        dd->batching++;
-       deadline_move_request(dd, drq);
+       deadline_move_request(dd, rq);
 
        return 1;
 }
@@ -562,30 +343,6 @@ static int deadline_queue_empty(request_queue_t *q)
                && list_empty(&dd->fifo_list[READ]);
 }
 
-static struct request *
-deadline_former_request(request_queue_t *q, struct request *rq)
-{
-       struct deadline_rq *drq = RQ_DATA(rq);
-       struct rb_node *rbprev = rb_prev(&drq->rb_node);
-
-       if (rbprev)
-               return rb_entry_drq(rbprev)->request;
-
-       return NULL;
-}
-
-static struct request *
-deadline_latter_request(request_queue_t *q, struct request *rq)
-{
-       struct deadline_rq *drq = RQ_DATA(rq);
-       struct rb_node *rbnext = rb_next(&drq->rb_node);
-
-       if (rbnext)
-               return rb_entry_drq(rbnext)->request;
-
-       return NULL;
-}
-
 static void deadline_exit_queue(elevator_t *e)
 {
        struct deadline_data *dd = e->elevator_data;
@@ -593,46 +350,21 @@ static void deadline_exit_queue(elevator_t *e)
        BUG_ON(!list_empty(&dd->fifo_list[READ]));
        BUG_ON(!list_empty(&dd->fifo_list[WRITE]));
 
-       mempool_destroy(dd->drq_pool);
-       kfree(dd->hash);
        kfree(dd);
 }
 
 /*
- * initialize elevator private data (deadline_data), and alloc a drq for
- * each request on the free lists
+ * initialize elevator private data (deadline_data).
  */
 static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct deadline_data *dd;
-       int i;
-
-       if (!drq_pool)
-               return NULL;
 
        dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
        if (!dd)
                return NULL;
        memset(dd, 0, sizeof(*dd));
 
-       dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES,
-                               GFP_KERNEL, q->node);
-       if (!dd->hash) {
-               kfree(dd);
-               return NULL;
-       }
-
-       dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
-                                       mempool_free_slab, drq_pool, q->node);
-       if (!dd->drq_pool) {
-               kfree(dd->hash);
-               kfree(dd);
-               return NULL;
-       }
-
-       for (i = 0; i < DL_HASH_ENTRIES; i++)
-               INIT_HLIST_HEAD(&dd->hash[i]);
-
        INIT_LIST_HEAD(&dd->fifo_list[READ]);
        INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
        dd->sort_list[READ] = RB_ROOT;
@@ -645,39 +377,6 @@ static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
        return dd;
 }
 
-static void deadline_put_request(request_queue_t *q, struct request *rq)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct deadline_rq *drq = RQ_DATA(rq);
-
-       mempool_free(drq, dd->drq_pool);
-       rq->elevator_private = NULL;
-}
-
-static int
-deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-                    gfp_t gfp_mask)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct deadline_rq *drq;
-
-       drq = mempool_alloc(dd->drq_pool, gfp_mask);
-       if (drq) {
-               memset(drq, 0, sizeof(*drq));
-               RB_CLEAR_NODE(&drq->rb_node);
-               drq->request = rq;
-
-               INIT_HLIST_NODE(&drq->hash);
-
-               INIT_LIST_HEAD(&drq->fifo);
-
-               rq->elevator_private = drq;
-               return 0;
-       }
-
-       return 1;
-}
-
 /*
  * sysfs parts below
  */
@@ -757,10 +456,8 @@ static struct elevator_type iosched_deadline = {
                .elevator_dispatch_fn =         deadline_dispatch_requests,
                .elevator_add_req_fn =          deadline_add_request,
                .elevator_queue_empty_fn =      deadline_queue_empty,
-               .elevator_former_req_fn =       deadline_former_request,
-               .elevator_latter_req_fn =       deadline_latter_request,
-               .elevator_set_req_fn =          deadline_set_request,
-               .elevator_put_req_fn =          deadline_put_request,
+               .elevator_former_req_fn =       elv_rb_former_request,
+               .elevator_latter_req_fn =       elv_rb_latter_request,
                .elevator_init_fn =             deadline_init_queue,
                .elevator_exit_fn =             deadline_exit_queue,
        },
@@ -772,24 +469,11 @@ static struct elevator_type iosched_deadline = {
 
 static int __init deadline_init(void)
 {
-       int ret;
-
-       drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq),
-                                    0, 0, NULL, NULL);
-
-       if (!drq_pool)
-               return -ENOMEM;
-
-       ret = elv_register(&iosched_deadline);
-       if (ret)
-               kmem_cache_destroy(drq_pool);
-
-       return ret;
+       return elv_register(&iosched_deadline);
 }
 
 static void __exit deadline_exit(void)
 {
-       kmem_cache_destroy(drq_pool);
        elv_unregister(&iosched_deadline);
 }
 
index 9b72dc7c8a5c98dcde87dc0d7e42d9a56f447776..487dd3da8853971d9bcb77cf6ecf51eb39faedf3 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
  *
- * 30042000 Jens Axboe <axboe@suse.de> :
+ * 30042000 Jens Axboe <axboe@kernel.dk> :
  *
  * Split the elevator a bit so that it is possible to choose a different
  * one or even write a new "plug in". There are three pieces:
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
+#include <linux/hash.h>
 
 #include <asm/uaccess.h>
 
 static DEFINE_SPINLOCK(elv_list_lock);
 static LIST_HEAD(elv_list);
 
+/*
+ * Merge hash stuff.
+ */
+static const int elv_hash_shift = 6;
+#define ELV_HASH_BLOCK(sec)    ((sec) >> 3)
+#define ELV_HASH_FN(sec)       (hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift))
+#define ELV_HASH_ENTRIES       (1 << elv_hash_shift)
+#define rq_hash_key(rq)                ((rq)->sector + (rq)->nr_sectors)
+#define ELV_ON_HASH(rq)                (!hlist_unhashed(&(rq)->hash))
+
 /*
  * can we safely merge with this request?
  */
@@ -56,8 +67,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
        /*
         * same device and no special stuff set, merge is ok
         */
-       if (rq->rq_disk == bio->bi_bdev->bd_disk &&
-           !rq->waiting && !rq->special)
+       if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special)
                return 1;
 
        return 0;
@@ -151,27 +161,44 @@ __setup("elevator=", elevator_setup);
 
 static struct kobj_type elv_ktype;
 
-static elevator_t *elevator_alloc(struct elevator_type *e)
-{
-       elevator_t *eq = kmalloc(sizeof(elevator_t), GFP_KERNEL);
-       if (eq) {
-               memset(eq, 0, sizeof(*eq));
-               eq->ops = &e->ops;
-               eq->elevator_type = e;
-               kobject_init(&eq->kobj);
-               snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
-               eq->kobj.ktype = &elv_ktype;
-               mutex_init(&eq->sysfs_lock);
-       } else {
-               elevator_put(e);
-       }
+static elevator_t *elevator_alloc(request_queue_t *q, struct elevator_type *e)
+{
+       elevator_t *eq;
+       int i;
+
+       eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL, q->node);
+       if (unlikely(!eq))
+               goto err;
+
+       memset(eq, 0, sizeof(*eq));
+       eq->ops = &e->ops;
+       eq->elevator_type = e;
+       kobject_init(&eq->kobj);
+       snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
+       eq->kobj.ktype = &elv_ktype;
+       mutex_init(&eq->sysfs_lock);
+
+       eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES,
+                                       GFP_KERNEL, q->node);
+       if (!eq->hash)
+               goto err;
+
+       for (i = 0; i < ELV_HASH_ENTRIES; i++)
+               INIT_HLIST_HEAD(&eq->hash[i]);
+
        return eq;
+err:
+       kfree(eq);
+       elevator_put(e);
+       return NULL;
 }
 
 static void elevator_release(struct kobject *kobj)
 {
        elevator_t *e = container_of(kobj, elevator_t, kobj);
+
        elevator_put(e->elevator_type);
+       kfree(e->hash);
        kfree(e);
 }
 
@@ -198,7 +225,7 @@ int elevator_init(request_queue_t *q, char *name)
                e = elevator_get("noop");
        }
 
-       eq = elevator_alloc(e);
+       eq = elevator_alloc(q, e);
        if (!eq)
                return -ENOMEM;
 
@@ -212,6 +239,8 @@ int elevator_init(request_queue_t *q, char *name)
        return ret;
 }
 
+EXPORT_SYMBOL(elevator_init);
+
 void elevator_exit(elevator_t *e)
 {
        mutex_lock(&e->sysfs_lock);
@@ -223,10 +252,118 @@ void elevator_exit(elevator_t *e)
        kobject_put(&e->kobj);
 }
 
+EXPORT_SYMBOL(elevator_exit);
+
+static inline void __elv_rqhash_del(struct request *rq)
+{
+       hlist_del_init(&rq->hash);
+}
+
+static void elv_rqhash_del(request_queue_t *q, struct request *rq)
+{
+       if (ELV_ON_HASH(rq))
+               __elv_rqhash_del(rq);
+}
+
+static void elv_rqhash_add(request_queue_t *q, struct request *rq)
+{
+       elevator_t *e = q->elevator;
+
+       BUG_ON(ELV_ON_HASH(rq));
+       hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]);
+}
+
+static void elv_rqhash_reposition(request_queue_t *q, struct request *rq)
+{
+       __elv_rqhash_del(rq);
+       elv_rqhash_add(q, rq);
+}
+
+static struct request *elv_rqhash_find(request_queue_t *q, sector_t offset)
+{
+       elevator_t *e = q->elevator;
+       struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)];
+       struct hlist_node *entry, *next;
+       struct request *rq;
+
+       hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) {
+               BUG_ON(!ELV_ON_HASH(rq));
+
+               if (unlikely(!rq_mergeable(rq))) {
+                       __elv_rqhash_del(rq);
+                       continue;
+               }
+
+               if (rq_hash_key(rq) == offset)
+                       return rq;
+       }
+
+       return NULL;
+}
+
+/*
+ * RB-tree support functions for inserting/lookup/removal of requests
+ * in a sorted RB tree.
+ */
+struct request *elv_rb_add(struct rb_root *root, struct request *rq)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct request *__rq;
+
+       while (*p) {
+               parent = *p;
+               __rq = rb_entry(parent, struct request, rb_node);
+
+               if (rq->sector < __rq->sector)
+                       p = &(*p)->rb_left;
+               else if (rq->sector > __rq->sector)
+                       p = &(*p)->rb_right;
+               else
+                       return __rq;
+       }
+
+       rb_link_node(&rq->rb_node, parent, p);
+       rb_insert_color(&rq->rb_node, root);
+       return NULL;
+}
+
+EXPORT_SYMBOL(elv_rb_add);
+
+void elv_rb_del(struct rb_root *root, struct request *rq)
+{
+       BUG_ON(RB_EMPTY_NODE(&rq->rb_node));
+       rb_erase(&rq->rb_node, root);
+       RB_CLEAR_NODE(&rq->rb_node);
+}
+
+EXPORT_SYMBOL(elv_rb_del);
+
+struct request *elv_rb_find(struct rb_root *root, sector_t sector)
+{
+       struct rb_node *n = root->rb_node;
+       struct request *rq;
+
+       while (n) {
+               rq = rb_entry(n, struct request, rb_node);
+
+               if (sector < rq->sector)
+                       n = n->rb_left;
+               else if (sector > rq->sector)
+                       n = n->rb_right;
+               else
+                       return rq;
+       }
+
+       return NULL;
+}
+
+EXPORT_SYMBOL(elv_rb_find);
+
 /*
  * Insert rq into dispatch queue of q.  Queue lock must be held on
- * entry.  If sort != 0, rq is sort-inserted; otherwise, rq will be
- * appended to the dispatch queue.  To be used by specific elevators.
+ * entry.  rq is sort insted into the dispatch queue. To be used by
+ * specific elevators.
  */
 void elv_dispatch_sort(request_queue_t *q, struct request *rq)
 {
@@ -235,6 +372,9 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
 
        if (q->last_merge == rq)
                q->last_merge = NULL;
+
+       elv_rqhash_del(q, rq);
+
        q->nr_sorted--;
 
        boundary = q->end_sector;
@@ -242,7 +382,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
        list_for_each_prev(entry, &q->queue_head) {
                struct request *pos = list_entry_rq(entry);
 
-               if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
+               if (pos->cmd_flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
                        break;
                if (rq->sector >= boundary) {
                        if (pos->sector < boundary)
@@ -258,11 +398,38 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
        list_add(&rq->queuelist, entry);
 }
 
+EXPORT_SYMBOL(elv_dispatch_sort);
+
+/*
+ * Insert rq into dispatch queue of q.  Queue lock must be held on
+ * entry.  rq is added to the back of the dispatch queue. To be used by
+ * specific elevators.
+ */
+void elv_dispatch_add_tail(struct request_queue *q, struct request *rq)
+{
+       if (q->last_merge == rq)
+               q->last_merge = NULL;
+
+       elv_rqhash_del(q, rq);
+
+       q->nr_sorted--;
+
+       q->end_sector = rq_end_sector(rq);
+       q->boundary_rq = rq;
+       list_add_tail(&rq->queuelist, &q->queue_head);
+}
+
+EXPORT_SYMBOL(elv_dispatch_add_tail);
+
 int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
 {
        elevator_t *e = q->elevator;
+       struct request *__rq;
        int ret;
 
+       /*
+        * First try one-hit cache.
+        */
        if (q->last_merge) {
                ret = elv_try_merge(q->last_merge, bio);
                if (ret != ELEVATOR_NO_MERGE) {
@@ -271,18 +438,30 @@ int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
                }
        }
 
+       /*
+        * See if our hash lookup can find a potential backmerge.
+        */
+       __rq = elv_rqhash_find(q, bio->bi_sector);
+       if (__rq && elv_rq_merge_ok(__rq, bio)) {
+               *req = __rq;
+               return ELEVATOR_BACK_MERGE;
+       }
+
        if (e->ops->elevator_merge_fn)
                return e->ops->elevator_merge_fn(q, req, bio);
 
        return ELEVATOR_NO_MERGE;
 }
 
-void elv_merged_request(request_queue_t *q, struct request *rq)
+void elv_merged_request(request_queue_t *q, struct request *rq, int type)
 {
        elevator_t *e = q->elevator;
 
        if (e->ops->elevator_merged_fn)
-               e->ops->elevator_merged_fn(q, rq);
+               e->ops->elevator_merged_fn(q, rq, type);
+
+       if (type == ELEVATOR_BACK_MERGE)
+               elv_rqhash_reposition(q, rq);
 
        q->last_merge = rq;
 }
@@ -294,8 +473,11 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
 
        if (e->ops->elevator_merge_req_fn)
                e->ops->elevator_merge_req_fn(q, rq, next);
-       q->nr_sorted--;
 
+       elv_rqhash_reposition(q, rq);
+       elv_rqhash_del(q, next);
+
+       q->nr_sorted--;
        q->last_merge = rq;
 }
 
@@ -313,7 +495,7 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
                        e->ops->elevator_deactivate_req_fn(q, rq);
        }
 
-       rq->flags &= ~REQ_STARTED;
+       rq->cmd_flags &= ~REQ_STARTED;
 
        elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
 }
@@ -344,13 +526,13 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
 
        switch (where) {
        case ELEVATOR_INSERT_FRONT:
-               rq->flags |= REQ_SOFTBARRIER;
+               rq->cmd_flags |= REQ_SOFTBARRIER;
 
                list_add(&rq->queuelist, &q->queue_head);
                break;
 
        case ELEVATOR_INSERT_BACK:
-               rq->flags |= REQ_SOFTBARRIER;
+               rq->cmd_flags |= REQ_SOFTBARRIER;
                elv_drain_elevator(q);
                list_add_tail(&rq->queuelist, &q->queue_head);
                /*
@@ -369,10 +551,14 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
 
        case ELEVATOR_INSERT_SORT:
                BUG_ON(!blk_fs_request(rq));
-               rq->flags |= REQ_SORTED;
+               rq->cmd_flags |= REQ_SORTED;
                q->nr_sorted++;
-               if (q->last_merge == NULL && rq_mergeable(rq))
-                       q->last_merge = rq;
+               if (rq_mergeable(rq)) {
+                       elv_rqhash_add(q, rq);
+                       if (!q->last_merge)
+                               q->last_merge = rq;
+               }
+
                /*
                 * Some ioscheds (cfq) run q->request_fn directly, so
                 * rq cannot be accessed after calling
@@ -387,7 +573,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
                 * insertion; otherwise, requests should be requeued
                 * in ordseq order.
                 */
-               rq->flags |= REQ_SOFTBARRIER;
+               rq->cmd_flags |= REQ_SOFTBARRIER;
 
                if (q->ordseq == 0) {
                        list_add(&rq->queuelist, &q->queue_head);
@@ -429,9 +615,9 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
                       int plug)
 {
        if (q->ordcolor)
-               rq->flags |= REQ_ORDERED_COLOR;
+               rq->cmd_flags |= REQ_ORDERED_COLOR;
 
-       if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
+       if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
                /*
                 * toggle ordered color
                 */
@@ -452,7 +638,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
                        q->end_sector = rq_end_sector(rq);
                        q->boundary_rq = rq;
                }
-       } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
+       } else if (!(rq->cmd_flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
                where = ELEVATOR_INSERT_BACK;
 
        if (plug)
@@ -461,6 +647,8 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
        elv_insert(q, rq, where);
 }
 
+EXPORT_SYMBOL(__elv_add_request);
+
 void elv_add_request(request_queue_t *q, struct request *rq, int where,
                     int plug)
 {
@@ -471,6 +659,8 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
+EXPORT_SYMBOL(elv_add_request);
+
 static inline struct request *__elv_next_request(request_queue_t *q)
 {
        struct request *rq;
@@ -493,7 +683,7 @@ struct request *elv_next_request(request_queue_t *q)
        int ret;
 
        while ((rq = __elv_next_request(q)) != NULL) {
-               if (!(rq->flags & REQ_STARTED)) {
+               if (!(rq->cmd_flags & REQ_STARTED)) {
                        elevator_t *e = q->elevator;
 
                        /*
@@ -510,7 +700,7 @@ struct request *elv_next_request(request_queue_t *q)
                         * it, a request that has been delayed should
                         * not be passed by new incoming requests
                         */
-                       rq->flags |= REQ_STARTED;
+                       rq->cmd_flags |= REQ_STARTED;
                        blk_add_trace_rq(q, rq, BLK_TA_ISSUE);
                }
 
@@ -519,7 +709,7 @@ struct request *elv_next_request(request_queue_t *q)
                        q->boundary_rq = NULL;
                }
 
-               if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
+               if ((rq->cmd_flags & REQ_DONTPREP) || !q->prep_rq_fn)
                        break;
 
                ret = q->prep_rq_fn(q, rq);
@@ -541,7 +731,7 @@ struct request *elv_next_request(request_queue_t *q)
                                nr_bytes = rq->data_len;
 
                        blkdev_dequeue_request(rq);
-                       rq->flags |= REQ_QUIET;
+                       rq->cmd_flags |= REQ_QUIET;
                        end_that_request_chunk(rq, 0, nr_bytes);
                        end_that_request_last(rq, 0);
                } else {
@@ -554,9 +744,12 @@ struct request *elv_next_request(request_queue_t *q)
        return rq;
 }
 
+EXPORT_SYMBOL(elv_next_request);
+
 void elv_dequeue_request(request_queue_t *q, struct request *rq)
 {
        BUG_ON(list_empty(&rq->queuelist));
+       BUG_ON(ELV_ON_HASH(rq));
 
        list_del_init(&rq->queuelist);
 
@@ -569,6 +762,8 @@ void elv_dequeue_request(request_queue_t *q, struct request *rq)
                q->in_flight++;
 }
 
+EXPORT_SYMBOL(elv_dequeue_request);
+
 int elv_queue_empty(request_queue_t *q)
 {
        elevator_t *e = q->elevator;
@@ -582,6 +777,8 @@ int elv_queue_empty(request_queue_t *q)
        return 1;
 }
 
+EXPORT_SYMBOL(elv_queue_empty);
+
 struct request *elv_latter_request(request_queue_t *q, struct request *rq)
 {
        elevator_t *e = q->elevator;
@@ -600,13 +797,12 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
        return NULL;
 }
 
-int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-                   gfp_t gfp_mask)
+int elv_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask)
 {
        elevator_t *e = q->elevator;
 
        if (e->ops->elevator_set_req_fn)
-               return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask);
+               return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
 
        rq->elevator_private = NULL;
        return 0;
@@ -620,12 +816,12 @@ void elv_put_request(request_queue_t *q, struct request *rq)
                e->ops->elevator_put_req_fn(q, rq);
 }
 
-int elv_may_queue(request_queue_t *q, int rw, struct bio *bio)
+int elv_may_queue(request_queue_t *q, int rw)
 {
        elevator_t *e = q->elevator;
 
        if (e->ops->elevator_may_queue_fn)
-               return e->ops->elevator_may_queue_fn(q, rw, bio);
+               return e->ops->elevator_may_queue_fn(q, rw);
 
        return ELV_MQUEUE_MAY;
 }
@@ -792,7 +988,7 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
        /*
         * Allocate new elevator
         */
-       e = elevator_alloc(new_e);
+       e = elevator_alloc(q, new_e);
        if (!e)
                return 0;
 
@@ -908,11 +1104,26 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
        return len;
 }
 
-EXPORT_SYMBOL(elv_dispatch_sort);
-EXPORT_SYMBOL(elv_add_request);
-EXPORT_SYMBOL(__elv_add_request);
-EXPORT_SYMBOL(elv_next_request);
-EXPORT_SYMBOL(elv_dequeue_request);
-EXPORT_SYMBOL(elv_queue_empty);
-EXPORT_SYMBOL(elevator_exit);
-EXPORT_SYMBOL(elevator_init);
+struct request *elv_rb_former_request(request_queue_t *q, struct request *rq)
+{
+       struct rb_node *rbprev = rb_prev(&rq->rb_node);
+
+       if (rbprev)
+               return rb_entry_rq(rbprev);
+
+       return NULL;
+}
+
+EXPORT_SYMBOL(elv_rb_former_request);
+
+struct request *elv_rb_latter_request(request_queue_t *q, struct request *rq)
+{
+       struct rb_node *rbnext = rb_next(&rq->rb_node);
+
+       if (rbnext)
+               return rb_entry_rq(rbnext);
+
+       return NULL;
+}
+
+EXPORT_SYMBOL(elv_rb_latter_request);
index 25d1f42568cc19714a2f8a5469ecd2842e9ea7e5..653919d50cd4d06aea68d8e027d15a473e5b4f5a 100644 (file)
@@ -295,10 +295,15 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
 
 static int __init genhd_device_init(void)
 {
+       int err;
+
        bdev_map = kobj_map_init(base_probe, &block_subsys_lock);
        blk_dev_init();
-       subsystem_register(&block_subsys);
-       return 0;
+       err = subsystem_register(&block_subsys);
+       if (err < 0)
+               printk(KERN_WARNING "%s: subsystem_register error: %d\n",
+                       __FUNCTION__, err);
+       return err;
 }
 
 subsys_initcall(genhd_device_init);
index 9c3a06bcb7ba97b02d12de6638944ac79e33baa2..83425fb3c8dba6e2b62122aaa6a02a25d2436ab4 100644 (file)
@@ -39,6 +39,7 @@ static void blk_unplug_timeout(unsigned long data);
 static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
 static void init_request_from_bio(struct request *req, struct bio *bio);
 static int __make_request(request_queue_t *q, struct bio *bio);
+static struct io_context *current_io_context(gfp_t gfp_flags, int node);
 
 /*
  * For the allocated request tables
@@ -277,19 +278,19 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
 
 EXPORT_SYMBOL(blk_queue_make_request);
 
-static inline void rq_init(request_queue_t *q, struct request *rq)
+static void rq_init(request_queue_t *q, struct request *rq)
 {
        INIT_LIST_HEAD(&rq->queuelist);
        INIT_LIST_HEAD(&rq->donelist);
 
        rq->errors = 0;
-       rq->rq_status = RQ_ACTIVE;
        rq->bio = rq->biotail = NULL;
+       INIT_HLIST_NODE(&rq->hash);
+       RB_CLEAR_NODE(&rq->rb_node);
        rq->ioprio = 0;
        rq->buffer = NULL;
        rq->ref_count = 1;
        rq->q = q;
-       rq->waiting = NULL;
        rq->special = NULL;
        rq->data_len = 0;
        rq->data = NULL;
@@ -382,8 +383,8 @@ unsigned blk_ordered_req_seq(struct request *rq)
        if (rq == &q->post_flush_rq)
                return QUEUE_ORDSEQ_POSTFLUSH;
 
-       if ((rq->flags & REQ_ORDERED_COLOR) ==
-           (q->orig_bar_rq->flags & REQ_ORDERED_COLOR))
+       if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
+           (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
                return QUEUE_ORDSEQ_DRAIN;
        else
                return QUEUE_ORDSEQ_DONE;
@@ -446,11 +447,11 @@ static void queue_flush(request_queue_t *q, unsigned which)
                end_io = post_flush_end_io;
        }
 
+       rq->cmd_flags = REQ_HARDBARRIER;
        rq_init(q, rq);
-       rq->flags = REQ_HARDBARRIER;
        rq->elevator_private = NULL;
+       rq->elevator_private2 = NULL;
        rq->rq_disk = q->bar_rq.rq_disk;
-       rq->rl = NULL;
        rq->end_io = end_io;
        q->prepare_flush_fn(q, rq);
 
@@ -471,11 +472,13 @@ static inline struct request *start_ordered(request_queue_t *q,
        blkdev_dequeue_request(rq);
        q->orig_bar_rq = rq;
        rq = &q->bar_rq;
+       rq->cmd_flags = 0;
        rq_init(q, rq);
-       rq->flags = bio_data_dir(q->orig_bar_rq->bio);
-       rq->flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0;
+       if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
+               rq->cmd_flags |= REQ_RW;
+       rq->cmd_flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0;
        rq->elevator_private = NULL;
-       rq->rl = NULL;
+       rq->elevator_private2 = NULL;
        init_request_from_bio(rq, q->orig_bar_rq->bio);
        rq->end_io = bar_end_io;
 
@@ -587,8 +590,8 @@ static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
        return 0;
 }
 
-static inline int ordered_bio_endio(struct request *rq, struct bio *bio,
-                                   unsigned int nbytes, int error)
+static int ordered_bio_endio(struct request *rq, struct bio *bio,
+                            unsigned int nbytes, int error)
 {
        request_queue_t *q = rq->q;
        bio_end_io_t *endio;
@@ -1124,7 +1127,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
        }
 
        list_del_init(&rq->queuelist);
-       rq->flags &= ~REQ_QUEUED;
+       rq->cmd_flags &= ~REQ_QUEUED;
        rq->tag = -1;
 
        if (unlikely(bqt->tag_index[tag] == NULL))
@@ -1160,7 +1163,7 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq)
        struct blk_queue_tag *bqt = q->queue_tags;
        int tag;
 
-       if (unlikely((rq->flags & REQ_QUEUED))) {
+       if (unlikely((rq->cmd_flags & REQ_QUEUED))) {
                printk(KERN_ERR 
                       "%s: request %p for device [%s] already tagged %d",
                       __FUNCTION__, rq,
@@ -1168,13 +1171,18 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq)
                BUG();
        }
 
-       tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
-       if (tag >= bqt->max_depth)
-               return 1;
+       /*
+        * Protect against shared tag maps, as we may not have exclusive
+        * access to the tag map.
+        */
+       do {
+               tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
+               if (tag >= bqt->max_depth)
+                       return 1;
 
-       __set_bit(tag, bqt->tag_map);
+       } while (test_and_set_bit(tag, bqt->tag_map));
 
-       rq->flags |= REQ_QUEUED;
+       rq->cmd_flags |= REQ_QUEUED;
        rq->tag = tag;
        bqt->tag_index[tag] = rq;
        blkdev_dequeue_request(rq);
@@ -1210,65 +1218,31 @@ void blk_queue_invalidate_tags(request_queue_t *q)
                        printk(KERN_ERR
                               "%s: bad tag found on list\n", __FUNCTION__);
                        list_del_init(&rq->queuelist);
-                       rq->flags &= ~REQ_QUEUED;
+                       rq->cmd_flags &= ~REQ_QUEUED;
                } else
                        blk_queue_end_tag(q, rq);
 
-               rq->flags &= ~REQ_STARTED;
+               rq->cmd_flags &= ~REQ_STARTED;
                __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0);
        }
 }
 
 EXPORT_SYMBOL(blk_queue_invalidate_tags);
 
-static const char * const rq_flags[] = {
-       "REQ_RW",
-       "REQ_FAILFAST",
-       "REQ_SORTED",
-       "REQ_SOFTBARRIER",
-       "REQ_HARDBARRIER",
-       "REQ_FUA",
-       "REQ_CMD",
-       "REQ_NOMERGE",
-       "REQ_STARTED",
-       "REQ_DONTPREP",
-       "REQ_QUEUED",
-       "REQ_ELVPRIV",
-       "REQ_PC",
-       "REQ_BLOCK_PC",
-       "REQ_SENSE",
-       "REQ_FAILED",
-       "REQ_QUIET",
-       "REQ_SPECIAL",
-       "REQ_DRIVE_CMD",
-       "REQ_DRIVE_TASK",
-       "REQ_DRIVE_TASKFILE",
-       "REQ_PREEMPT",
-       "REQ_PM_SUSPEND",
-       "REQ_PM_RESUME",
-       "REQ_PM_SHUTDOWN",
-       "REQ_ORDERED_COLOR",
-};
-
 void blk_dump_rq_flags(struct request *rq, char *msg)
 {
        int bit;
 
-       printk("%s: dev %s: flags = ", msg,
-               rq->rq_disk ? rq->rq_disk->disk_name : "?");
-       bit = 0;
-       do {
-               if (rq->flags & (1 << bit))
-                       printk("%s ", rq_flags[bit]);
-               bit++;
-       } while (bit < __REQ_NR_BITS);
+       printk("%s: dev %s: type=%x, flags=%x\n", msg,
+               rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->cmd_type,
+               rq->cmd_flags);
 
        printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
                                                       rq->nr_sectors,
                                                       rq->current_nr_sectors);
        printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len);
 
-       if (rq->flags & (REQ_BLOCK_PC | REQ_PC)) {
+       if (blk_pc_request(rq)) {
                printk("cdb: ");
                for (bit = 0; bit < sizeof(rq->cmd); bit++)
                        printk("%02x ", rq->cmd[bit]);
@@ -1441,7 +1415,7 @@ static inline int ll_new_mergeable(request_queue_t *q,
        int nr_phys_segs = bio_phys_segments(q, bio);
 
        if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
-               req->flags |= REQ_NOMERGE;
+               req->cmd_flags |= REQ_NOMERGE;
                if (req == q->last_merge)
                        q->last_merge = NULL;
                return 0;
@@ -1464,7 +1438,7 @@ static inline int ll_new_hw_segment(request_queue_t *q,
 
        if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments
            || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
-               req->flags |= REQ_NOMERGE;
+               req->cmd_flags |= REQ_NOMERGE;
                if (req == q->last_merge)
                        q->last_merge = NULL;
                return 0;
@@ -1491,7 +1465,7 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
                max_sectors = q->max_sectors;
 
        if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
-               req->flags |= REQ_NOMERGE;
+               req->cmd_flags |= REQ_NOMERGE;
                if (req == q->last_merge)
                        q->last_merge = NULL;
                return 0;
@@ -1530,7 +1504,7 @@ static int ll_front_merge_fn(request_queue_t *q, struct request *req,
 
 
        if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
-               req->flags |= REQ_NOMERGE;
+               req->cmd_flags |= REQ_NOMERGE;
                if (req == q->last_merge)
                        q->last_merge = NULL;
                return 0;
@@ -1847,8 +1821,7 @@ static void blk_release_queue(struct kobject *kobj)
        if (q->queue_tags)
                __blk_queue_free_tags(q);
 
-       if (q->blk_trace)
-               blk_trace_shutdown(q);
+       blk_trace_shutdown(q);
 
        kmem_cache_free(requestq_cachep, q);
 }
@@ -2030,14 +2003,13 @@ EXPORT_SYMBOL(blk_get_queue);
 
 static inline void blk_free_request(request_queue_t *q, struct request *rq)
 {
-       if (rq->flags & REQ_ELVPRIV)
+       if (rq->cmd_flags & REQ_ELVPRIV)
                elv_put_request(q, rq);
        mempool_free(rq, q->rq.rq_pool);
 }
 
-static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
-                 int priv, gfp_t gfp_mask)
+static struct request *
+blk_alloc_request(request_queue_t *q, int rw, int priv, gfp_t gfp_mask)
 {
        struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -2045,17 +2017,17 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
                return NULL;
 
        /*
-        * first three bits are identical in rq->flags and bio->bi_rw,
+        * first three bits are identical in rq->cmd_flags and bio->bi_rw,
         * see bio.h and blkdev.h
         */
-       rq->flags = rw;
+       rq->cmd_flags = rw | REQ_ALLOCED;
 
        if (priv) {
-               if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) {
+               if (unlikely(elv_set_request(q, rq, gfp_mask))) {
                        mempool_free(rq, q->rq.rq_pool);
                        return NULL;
                }
-               rq->flags |= REQ_ELVPRIV;
+               rq->cmd_flags |= REQ_ELVPRIV;
        }
 
        return rq;
@@ -2142,13 +2114,13 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
        struct io_context *ioc = NULL;
        int may_queue, priv;
 
-       may_queue = elv_may_queue(q, rw, bio);
+       may_queue = elv_may_queue(q, rw);
        if (may_queue == ELV_MQUEUE_NO)
                goto rq_starved;
 
        if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) {
                if (rl->count[rw]+1 >= q->nr_requests) {
-                       ioc = current_io_context(GFP_ATOMIC);
+                       ioc = current_io_context(GFP_ATOMIC, q->node);
                        /*
                         * The queue will fill after this allocation, so set
                         * it as full, and mark this process as "batching".
@@ -2190,7 +2162,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
 
        spin_unlock_irq(q->queue_lock);
 
-       rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
+       rq = blk_alloc_request(q, rw, priv, gfp_mask);
        if (unlikely(!rq)) {
                /*
                 * Allocation failed presumably due to memory. Undo anything
@@ -2226,7 +2198,6 @@ rq_starved:
                ioc->nr_batch_requests--;
        
        rq_init(q, rq);
-       rq->rl = rl;
 
        blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ);
 out:
@@ -2269,7 +2240,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
                         * up to a big batch of them for a small period time.
                         * See ioc_batching, ioc_set_batching
                         */
-                       ioc = current_io_context(GFP_NOIO);
+                       ioc = current_io_context(GFP_NOIO, q->node);
                        ioc_set_batching(q, ioc);
 
                        spin_lock_irq(q->queue_lock);
@@ -2300,6 +2271,25 @@ struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(blk_get_request);
 
+/**
+ * blk_start_queueing - initiate dispatch of requests to device
+ * @q:         request queue to kick into gear
+ *
+ * This is basically a helper to remove the need to know whether a queue
+ * is plugged or not if someone just wants to initiate dispatch of requests
+ * for this queue.
+ *
+ * The queue lock must be held with interrupts disabled.
+ */
+void blk_start_queueing(request_queue_t *q)
+{
+       if (!blk_queue_plugged(q))
+               q->request_fn(q);
+       else
+               __generic_unplug_device(q);
+}
+EXPORT_SYMBOL(blk_start_queueing);
+
 /**
  * blk_requeue_request - put a request back on queue
  * @q:         request queue where request should be inserted
@@ -2352,7 +2342,8 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
         * must not attempt merges on this) and that it acts as a soft
         * barrier
         */
-       rq->flags |= REQ_SPECIAL | REQ_SOFTBARRIER;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd_flags |= REQ_SOFTBARRIER;
 
        rq->special = data;
 
@@ -2366,11 +2357,7 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
 
        drive_stat_acct(rq, rq->nr_sectors, 1);
        __elv_add_request(q, rq, where, 0);
-
-       if (blk_queue_plugged(q))
-               __generic_unplug_device(q);
-       else
-               q->request_fn(q);
+       blk_start_queueing(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -2559,7 +2546,7 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
 
        rq->rq_disk = bd_disk;
-       rq->flags |= REQ_NOMERGE;
+       rq->cmd_flags |= REQ_NOMERGE;
        rq->end_io = done;
        WARN_ON(irqs_disabled());
        spin_lock_irq(q->queue_lock);
@@ -2599,10 +2586,9 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
                rq->sense_len = 0;
        }
 
-       rq->waiting = &wait;
+       rq->end_io_data = &wait;
        blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
        wait_for_completion(&wait);
-       rq->waiting = NULL;
 
        if (rq->errors)
                err = -EIO;
@@ -2711,8 +2697,6 @@ EXPORT_SYMBOL_GPL(disk_round_stats);
  */
 void __blk_put_request(request_queue_t *q, struct request *req)
 {
-       struct request_list *rl = req->rl;
-
        if (unlikely(!q))
                return;
        if (unlikely(--req->ref_count))
@@ -2720,18 +2704,16 @@ void __blk_put_request(request_queue_t *q, struct request *req)
 
        elv_completed_request(q, req);
 
-       req->rq_status = RQ_INACTIVE;
-       req->rl = NULL;
-
        /*
         * Request may not have originated from ll_rw_blk. if not,
         * it didn't come out of our reserved rq pools
         */
-       if (rl) {
+       if (req->cmd_flags & REQ_ALLOCED) {
                int rw = rq_data_dir(req);
-               int priv = req->flags & REQ_ELVPRIV;
+               int priv = req->cmd_flags & REQ_ELVPRIV;
 
                BUG_ON(!list_empty(&req->queuelist));
+               BUG_ON(!hlist_unhashed(&req->hash));
 
                blk_free_request(q, req);
                freed_request(q, rw, priv);
@@ -2765,9 +2747,9 @@ EXPORT_SYMBOL(blk_put_request);
  */
 void blk_end_sync_rq(struct request *rq, int error)
 {
-       struct completion *waiting = rq->waiting;
+       struct completion *waiting = rq->end_io_data;
 
-       rq->waiting = NULL;
+       rq->end_io_data = NULL;
        __blk_put_request(rq->q, rq);
 
        /*
@@ -2830,7 +2812,7 @@ static int attempt_merge(request_queue_t *q, struct request *req,
 
        if (rq_data_dir(req) != rq_data_dir(next)
            || req->rq_disk != next->rq_disk
-           || next->waiting || next->special)
+           || next->special)
                return 0;
 
        /*
@@ -2891,22 +2873,24 @@ static inline int attempt_front_merge(request_queue_t *q, struct request *rq)
 
 static void init_request_from_bio(struct request *req, struct bio *bio)
 {
-       req->flags |= REQ_CMD;
+       req->cmd_type = REQ_TYPE_FS;
 
        /*
         * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
         */
        if (bio_rw_ahead(bio) || bio_failfast(bio))
-               req->flags |= REQ_FAILFAST;
+               req->cmd_flags |= REQ_FAILFAST;
 
        /*
         * REQ_BARRIER implies no merging, but lets make it explicit
         */
        if (unlikely(bio_barrier(bio)))
-               req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
+               req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
 
        if (bio_sync(bio))
-               req->flags |= REQ_RW_SYNC;
+               req->cmd_flags |= REQ_RW_SYNC;
+       if (bio_rw_meta(bio))
+               req->cmd_flags |= REQ_RW_META;
 
        req->errors = 0;
        req->hard_sector = req->sector = bio->bi_sector;
@@ -2915,7 +2899,6 @@ static void init_request_from_bio(struct request *req, struct bio *bio)
        req->nr_phys_segments = bio_phys_segments(req->q, bio);
        req->nr_hw_segments = bio_hw_segments(req->q, bio);
        req->buffer = bio_data(bio);    /* see ->buffer comment above */
-       req->waiting = NULL;
        req->bio = req->biotail = bio;
        req->ioprio = bio_prio(bio);
        req->rq_disk = bio->bi_bdev->bd_disk;
@@ -2925,17 +2908,11 @@ static void init_request_from_bio(struct request *req, struct bio *bio)
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
        struct request *req;
-       int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
-       unsigned short prio;
-       sector_t sector;
+       int el_ret, nr_sectors, barrier, err;
+       const unsigned short prio = bio_prio(bio);
+       const int sync = bio_sync(bio);
 
-       sector = bio->bi_sector;
        nr_sectors = bio_sectors(bio);
-       cur_nr_sectors = bio_cur_sectors(bio);
-       prio = bio_prio(bio);
-
-       rw = bio_data_dir(bio);
-       sync = bio_sync(bio);
 
        /*
         * low level driver can indicate that it wants pages above a
@@ -2944,8 +2921,6 @@ static int __make_request(request_queue_t *q, struct bio *bio)
         */
        blk_queue_bounce(q, &bio);
 
-       spin_lock_prefetch(q->queue_lock);
-
        barrier = bio_barrier(bio);
        if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) {
                err = -EOPNOTSUPP;
@@ -2973,7 +2948,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
                        req->ioprio = ioprio_best(req->ioprio, prio);
                        drive_stat_acct(req, nr_sectors, 0);
                        if (!attempt_back_merge(q, req))
-                               elv_merged_request(q, req);
+                               elv_merged_request(q, req, el_ret);
                        goto out;
 
                case ELEVATOR_FRONT_MERGE:
@@ -2993,14 +2968,14 @@ static int __make_request(request_queue_t *q, struct bio *bio)
                         * not touch req->buffer either...
                         */
                        req->buffer = bio_data(bio);
-                       req->current_nr_sectors = cur_nr_sectors;
-                       req->hard_cur_sectors = cur_nr_sectors;
-                       req->sector = req->hard_sector = sector;
+                       req->current_nr_sectors = bio_cur_sectors(bio);
+                       req->hard_cur_sectors = req->current_nr_sectors;
+                       req->sector = req->hard_sector = bio->bi_sector;
                        req->nr_sectors = req->hard_nr_sectors += nr_sectors;
                        req->ioprio = ioprio_best(req->ioprio, prio);
                        drive_stat_acct(req, nr_sectors, 0);
                        if (!attempt_front_merge(q, req))
-                               elv_merged_request(q, req);
+                               elv_merged_request(q, req, el_ret);
                        goto out;
 
                /* ELV_NO_MERGE: elevator says don't/can't merge. */
@@ -3013,7 +2988,7 @@ get_rq:
         * Grab a free request. This is might sleep but can not fail.
         * Returns with the queue unlocked.
         */
-       req = get_request_wait(q, rw, bio);
+       req = get_request_wait(q, bio_data_dir(bio), bio);
 
        /*
         * After dropping the lock and possibly sleeping here, our request
@@ -3307,7 +3282,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
                req->errors = 0;
 
        if (!uptodate) {
-               if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
+               if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
                        printk("end_request: I/O error, dev %s, sector %llu\n",
                                req->rq_disk ? req->rq_disk->disk_name : "?",
                                (unsigned long long)req->sector);
@@ -3570,8 +3545,8 @@ EXPORT_SYMBOL(end_request);
 
 void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio)
 {
-       /* first two bits are identical in rq->flags and bio->bi_rw */
-       rq->flags |= (bio->bi_rw & 3);
+       /* first two bits are identical in rq->cmd_flags and bio->bi_rw */
+       rq->cmd_flags |= (bio->bi_rw & 3);
 
        rq->nr_phys_segments = bio_phys_segments(q, bio);
        rq->nr_hw_segments = bio_hw_segments(q, bio);
@@ -3659,25 +3634,22 @@ EXPORT_SYMBOL(put_io_context);
 /* Called by the exitting task */
 void exit_io_context(void)
 {
-       unsigned long flags;
        struct io_context *ioc;
        struct cfq_io_context *cic;
 
-       local_irq_save(flags);
        task_lock(current);
        ioc = current->io_context;
        current->io_context = NULL;
-       ioc->task = NULL;
        task_unlock(current);
-       local_irq_restore(flags);
 
+       ioc->task = NULL;
        if (ioc->aic && ioc->aic->exit)
                ioc->aic->exit(ioc->aic);
        if (ioc->cic_root.rb_node != NULL) {
                cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
                cic->exit(ioc);
        }
+
        put_io_context(ioc);
 }
 
@@ -3689,7 +3661,7 @@ void exit_io_context(void)
  * but since the current task itself holds a reference, the context can be
  * used in general code, so long as it stays within `current` context.
  */
-struct io_context *current_io_context(gfp_t gfp_flags)
+static struct io_context *current_io_context(gfp_t gfp_flags, int node)
 {
        struct task_struct *tsk = current;
        struct io_context *ret;
@@ -3698,11 +3670,11 @@ struct io_context *current_io_context(gfp_t gfp_flags)
        if (likely(ret))
                return ret;
 
-       ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
+       ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
        if (ret) {
                atomic_set(&ret->refcount, 1);
                ret->task = current;
-               ret->set_ioprio = NULL;
+               ret->ioprio_changed = 0;
                ret->last_waited = jiffies; /* doesn't matter... */
                ret->nr_batch_requests = 0; /* because this is 0 */
                ret->aic = NULL;
@@ -3722,10 +3694,10 @@ EXPORT_SYMBOL(current_io_context);
  *
  * This is always called in the context of the task which submitted the I/O.
  */
-struct io_context *get_io_context(gfp_t gfp_flags)
+struct io_context *get_io_context(gfp_t gfp_flags, int node)
 {
        struct io_context *ret;
-       ret = current_io_context(gfp_flags);
+       ret = current_io_context(gfp_flags, node);
        if (likely(ret))
                atomic_inc(&ret->refcount);
        return ret;
@@ -3838,9 +3810,6 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count)
        ssize_t ret = queue_var_store(&ra_kb, page, count);
 
        spin_lock_irq(q->queue_lock);
-       if (ra_kb > (q->max_sectors >> 1))
-               ra_kb = (q->max_sectors >> 1);
-
        q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
        spin_unlock_irq(q->queue_lock);
 
index 56a7c620574f86c0338a431354344d149314ce0f..79af431794213867e5ac1c457103d62b0d74cb43 100644 (file)
@@ -69,7 +69,7 @@ static void *noop_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct noop_data *nd;
 
-       nd = kmalloc(sizeof(*nd), GFP_KERNEL);
+       nd = kmalloc_node(sizeof(*nd), GFP_KERNEL, q->node);
        if (!nd)
                return NULL;
        INIT_LIST_HEAD(&nd->queue);
index b33eda26e2053e84f85473a13cd657cf920e3fe0..2dc326421a24af9c745e9f4eb34f7a80f1a41d0a 100644 (file)
@@ -294,7 +294,7 @@ static int sg_io(struct file *file, request_queue_t *q,
        rq->sense = sense;
        rq->sense_len = 0;
 
-       rq->flags |= REQ_BLOCK_PC;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
        bio = rq->bio;
 
        /*
@@ -470,7 +470,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
        memset(sense, 0, sizeof(sense));
        rq->sense = sense;
        rq->sense_len = 0;
-       rq->flags |= REQ_BLOCK_PC;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
 
        blk_execute_rq(q, disk, rq, 0);
 
@@ -502,7 +502,7 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c
        int err;
 
        rq = blk_get_request(q, WRITE, __GFP_WAIT);
-       rq->flags |= REQ_BLOCK_PC;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->data = NULL;
        rq->data_len = 0;
        rq->timeout = BLK_DEFAULT_TIMEOUT;
index c26c08b368297897f6a07bb86bfb02db3212b3ce..bdb9c8b78ed8afe1a5fd794ce204bef0b60e8d01 100644 (file)
@@ -308,7 +308,6 @@ static struct i2c_algo_bit_data ioc_data = {
        .getsda         = ioc_getsda,
        .getscl         = ioc_getscl,
        .udelay         = 80,
-       .mdelay         = 80,
        .timeout        = 100
 };
 
index 1dda370f402b69d4d69dd433c6dcfab2e58cd5d5..98099de59b45bcfec5ee8636650c5eb29ee5fbd0 100644 (file)
@@ -238,6 +238,10 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
                        num_enabled++;
                        continue;
                }
+
+               if (node < 0)
+                       node = memory_add_physaddr_to_nid(info->start_addr);
+
                result = add_memory(node, info->start_addr, info->length);
                if (result)
                        continue;
index 6809c283ec5865ed7183570dbe5814fa7e9bf5a4..6342e612c203726514be32d5ab4e97ecf579f552 100644 (file)
@@ -293,7 +293,7 @@ static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
 }
 
-static struct i2c_algorithm acpi_ec_smbus_algorithm = {
+static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
        .smbus_xfer = acpi_ec_smb_access,
        .functionality = acpi_ec_smb_func,
 };
index 507f051d1cefd437634454809aa69c748f256a0d..20beea778ea2d929a7efceec03a3fe60f6f9ec12 100644 (file)
@@ -1079,7 +1079,7 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
 
 acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
 {
-       (void)kmem_cache_destroy(cache);
+       kmem_cache_destroy(cache);
        return (AE_OK);
 }
 
index 71066066d626b82f8b0bc656e253bb925761ee8c..0a395fca843b46686b748ffe1583515cc863e9af 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
 #include <linux/sched.h>       /* need_resched() */
+#include <linux/latency.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -453,7 +454,8 @@ static void acpi_processor_idle(void)
         */
        if (cx->promotion.state &&
            ((cx->promotion.state - pr->power.states) <= max_cstate)) {
-               if (sleep_ticks > cx->promotion.threshold.ticks) {
+               if (sleep_ticks > cx->promotion.threshold.ticks &&
+                 cx->promotion.state->latency <= system_latency_constraint()) {
                        cx->promotion.count++;
                        cx->demotion.count = 0;
                        if (cx->promotion.count >=
@@ -494,8 +496,10 @@ static void acpi_processor_idle(void)
       end:
        /*
         * Demote if current state exceeds max_cstate
+        * or if the latency of the current state is unacceptable
         */
-       if ((pr->power.state - pr->power.states) > max_cstate) {
+       if ((pr->power.state - pr->power.states) > max_cstate ||
+               pr->power.state->latency > system_latency_constraint()) {
                if (cx->demotion.state)
                        next_state = cx->demotion.state;
        }
@@ -1009,9 +1013,11 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
 
        seq_printf(seq, "active state:            C%zd\n"
                   "max_cstate:              C%d\n"
-                  "bus master activity:     %08x\n",
+                  "bus master activity:     %08x\n"
+                  "maximum allowed latency: %d usec\n",
                   pr->power.state ? pr->power.state - pr->power.states : 0,
-                  max_cstate, (unsigned)pr->power.bm_activity);
+                  max_cstate, (unsigned)pr->power.bm_activity,
+                  system_latency_constraint());
 
        seq_puts(seq, "states:\n");
 
@@ -1077,6 +1083,28 @@ static const struct file_operations acpi_processor_power_fops = {
        .release = single_release,
 };
 
+static void smp_callback(void *v)
+{
+       /* we already woke the CPU up, nothing more to do */
+}
+
+/*
+ * This function gets called when a part of the kernel has a new latency
+ * requirement.  This means we need to get all processors out of their C-state,
+ * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
+ * wakes them all right up.
+ */
+static int acpi_processor_latency_notify(struct notifier_block *b,
+               unsigned long l, void *v)
+{
+       smp_call_function(smp_callback, NULL, 0, 1);
+       return NOTIFY_OK;
+}
+
+static struct notifier_block acpi_processor_latency_notifier = {
+       .notifier_call = acpi_processor_latency_notify,
+};
+
 int acpi_processor_power_init(struct acpi_processor *pr,
                              struct acpi_device *device)
 {
@@ -1093,6 +1121,7 @@ int acpi_processor_power_init(struct acpi_processor *pr,
                               "ACPI: processor limited to max C-state %d\n",
                               max_cstate);
                first_run++;
+               register_latency_notifier(&acpi_processor_latency_notifier);
        }
 
        if (!pr)
@@ -1164,6 +1193,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
                 * copies of pm_idle before proceeding.
                 */
                cpu_idle_wait();
+               unregister_latency_notifier(&acpi_processor_latency_notifier);
        }
 
        return 0;
index 99837d932f367f29ad0f520095defd63336ce179..3f4aa0c99ee4dccaf096330732887bc5be153f79 100644 (file)
@@ -311,7 +311,7 @@ config PATA_JMICRON
 
 config PATA_LEGACY
        tristate "Legacy ISA PATA support (Experimental)"
-       depends on PCI && EXPERIMENTAL
+       depends on ISA && EXPERIMENTAL
        help
          This option enables support for ISA/VLB bus legacy PATA
          ports and allows them to be accessed via the new ATA layer.
@@ -400,6 +400,7 @@ config PATA_PDC_OLD
 
 config PATA_QDI
        tristate "QDI VLB PATA support"
+       depends on ISA
        help
          Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
 
index 1d1c30a2fcd0234d9bfdf25c76e7febae159c0ee..377425e7139190a855ec551f0f3236ff83431dd4 100644 (file)
@@ -143,7 +143,7 @@ static struct ata_port_operations generic_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .irq_handler    = ata_interrupt,
        .irq_clear      = ata_bmdma_irq_clear,
 
index ffa111eea9daf0f619e43b09bbac691205066114..5719704eb0ee5a6d5699399cf2edb3b12f174f18 100644 (file)
@@ -643,11 +643,9 @@ static int piix_pata_prereset(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-       if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
-               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
-               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
+               return -ENOENT;
+               
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
index 753b0152afd16f15dd655bafacff32d1dc5dd473..b4abd6850367d219e2cb1d59218bf7773b147879 100644 (file)
@@ -5453,6 +5453,11 @@ int ata_device_add(const struct ata_probe_ent *ent)
        int rc;
 
        DPRINTK("ENTER\n");
+       
+       if (ent->irq == 0) {
+               dev_printk(KERN_ERR, dev, "is not available: No interrupt assigned.\n");
+               return 0;
+       }
        /* alloc a container for our list of ATA ports (buses) */
        host = kzalloc(sizeof(struct ata_host) +
                       (ent->n_ports * sizeof(void *)), GFP_KERNEL);
index 3fa80f09f2ae8edf283b36e4553a7c9b119ea1e8..02b2b2787d9b85a33a420fc77b5dc18aac7e29ad 100644 (file)
@@ -1515,7 +1515,11 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
        if (prereset) {
                rc = prereset(ap);
                if (rc) {
-                       ata_port_printk(ap, KERN_ERR,
+                       if (rc == -ENOENT) {
+                               ata_port_printk(ap, KERN_DEBUG, "port disabled. ignoring.\n");
+                               ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
+                       } else
+                               ata_port_printk(ap, KERN_ERR,
                                        "prereset failed (errno=%d)\n", rc);
                        return rc;
                }
index 688bb55e197a786b82d40f63b2695e68afd75fb8..08b3a407473ea47688beb7d91dca4f8d2543bbe0 100644 (file)
@@ -881,7 +881,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
        probe_ent->private_data = port[0]->private_data;
 
        if (port_mask & ATA_PORT_PRIMARY) {
-               probe_ent->irq = 14;
+               probe_ent->irq = ATA_PRIMARY_IRQ;
                probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
                probe_ent->port[0].altstatus_addr =
                probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
@@ -896,9 +896,9 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
 
        if (port_mask & ATA_PORT_SECONDARY) {
                if (probe_ent->irq)
-                       probe_ent->irq2 = 15;
+                       probe_ent->irq2 = ATA_SECONDARY_IRQ;
                else
-                       probe_ent->irq = 15;
+                       probe_ent->irq = ATA_SECONDARY_IRQ;
                probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
                probe_ent->port[1].altstatus_addr =
                probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
index 8448ee6e0eed0666036587998abfa6a6948f63ed..87af3b5861ab0276340822e5eb28f5c15ba76060 100644 (file)
@@ -369,7 +369,7 @@ static struct ata_port_operations ali_early_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -410,7 +410,7 @@ static struct ata_port_operations ali_20_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -448,7 +448,7 @@ static struct ata_port_operations ali_c2_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -485,7 +485,7 @@ static struct ata_port_operations ali_c5_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 3293cf9a7eb53e104c6d433a34b5ce5b7b2c795f..599ee266722ccffe6492650263342ee838eedd16 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.2.3"
+#define DRV_VERSION "0.2.4"
 
 /**
  *     timing_setup            -       shared timing computation and load
@@ -137,11 +137,8 @@ static int amd_pre_reset(struct ata_port *ap)
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        u8 ata66;
 
-       if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
+               return -ENOENT;
 
        pci_read_config_byte(pdev, 0x42, &ata66);
        if (ata66 & bitmask[ap->port_no])
@@ -167,11 +164,9 @@ static int amd_early_pre_reset(struct ata_port *ap)
                { 0x40, 1, 0x01, 0x01 }
        };
 
-       if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        /* No host side cable detection */
        ap->cbl = ATA_CBL_PATA80;
        return ata_std_prereset(ap);
@@ -262,12 +257,8 @@ static int nv_pre_reset(struct ata_port *ap) {
        u8 ata66;
        u16 udma;
 
-       if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
-
+       if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
+               return -ENOENT;
 
        pci_read_config_byte(pdev, 0x52, &ata66);
        if (ata66 & bitmask[ap->port_no])
@@ -368,7 +359,7 @@ static struct ata_port_operations amd33_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -402,7 +393,7 @@ static struct ata_port_operations amd66_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -436,7 +427,7 @@ static struct ata_port_operations amd100_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -470,7 +461,7 @@ static struct ata_port_operations amd133_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -504,7 +495,7 @@ static struct ata_port_operations nv100_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -538,7 +529,7 @@ static struct ata_port_operations nv133_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index d6ef3bf1bac7e07b941b4f2dc75bec015d888312..c4ccb75a4f1d69a2bebba5eb2e9e08640af986d0 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_artop"
-#define DRV_VERSION    "0.4.1"
+#define DRV_VERSION    "0.4.2"
 
 /*
  *     The ARTOP has 33 Mhz and "over clocked" timing tables. Until we
@@ -47,11 +47,9 @@ static int artop6210_pre_reset(struct ata_port *ap)
                { 0x4AU, 1U, 0x04UL, 0x04UL },  /* port 1 */
        };
 
-       if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
@@ -90,11 +88,9 @@ static int artop6260_pre_reset(struct ata_port *ap)
        u8 tmp;
 
        /* 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])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        pci_read_config_byte(pdev, 0x49, &tmp);
        if (tmp & (1 >> ap->port_no))
                ap->cbl = ATA_CBL_PATA40;
@@ -344,7 +340,7 @@ static const struct ata_port_operations artop6210_ops = {
        .bmdma_status           = ata_bmdma_status,
        .qc_prep                = ata_qc_prep,
        .qc_issue               = ata_qc_issue_prot,
-       .eng_timeout            = ata_eng_timeout,
+
        .data_xfer              = ata_pio_data_xfer,
 
        .irq_handler            = ata_interrupt,
@@ -379,8 +375,6 @@ static const struct ata_port_operations artop6260_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index 3f78a1e54a75857b036771f9705f0558ce9ba38a..6c2269b6bd3c0d74cc079548681ccbf15935f067 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_atiixp"
-#define DRV_VERSION "0.4.2"
+#define DRV_VERSION "0.4.3"
 
 enum {
        ATIIXP_IDE_PIO_TIMING   = 0x40,
@@ -41,11 +41,9 @@ static int atiixp_pre_reset(struct ata_port *ap)
                { 0x48, 1, 0x08, 0x00 }
        };
 
-       if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        ap->cbl = ATA_CBL_PATA80;
        return ata_std_prereset(ap);
 }
@@ -244,7 +242,7 @@ static struct ata_port_operations atiixp_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index abf1bb7bd32227319f47b1f4b42b74e395d740a6..e92b0ef43ec55a34e7d390d001bdbb413d8b8648 100644 (file)
@@ -301,7 +301,7 @@ static struct ata_port_operations cmd64x_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -335,7 +335,7 @@ static struct ata_port_operations cmd646r1_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -369,7 +369,7 @@ static struct ata_port_operations cmd648_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 792ce4828510d77e633bca9c43e54c931e6db011..a6c6cebd0dae53e38bc9fd24cadba220ee5b921e 100644 (file)
@@ -193,8 +193,6 @@ static struct ata_port_operations cs5520_port_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index f3d8a3bc1e788e5e08e58002f53ae22d576852d5..7bba4d954e9c00ae43f6f8af3b94358fd2661348 100644 (file)
@@ -207,7 +207,7 @@ static struct ata_port_operations cs5530_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = cs5530_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 69d6b425872498865db0a8a8a202ee7b5b3af400..d64fcdceaf01e917283c6c8f07effd20a4ad36bf 100644 (file)
@@ -211,7 +211,7 @@ static struct ata_port_operations cs5535_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index fd55474e0d151890e436125a35830bab75cc2e5b..dfa5ac5390481dcb58e8ef60b19de6cfb4955fdd 100644 (file)
@@ -162,7 +162,7 @@ static struct ata_port_operations cy82c693_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index c30bc181304f4ac2f5b5366d90a22704a5110ecb..95cd1ca181f5b9332cadc9c883f9cffe91ed08ec 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_efar"
-#define DRV_VERSION    "0.4.1"
+#define DRV_VERSION    "0.4.2"
 
 /**
  *     efar_pre_reset  -       check for 40/80 pin
@@ -42,11 +42,9 @@ static int efar_pre_reset(struct ata_port *ap)
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        u8 tmp;
 
-       if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        pci_read_config_byte(pdev, 0x47, &tmp);
        if (tmp & (2 >> ap->port_no))
                ap->cbl = ATA_CBL_PATA40;
@@ -263,8 +261,6 @@ static const struct ata_port_operations efar_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index 94bb1dfc3f19fcf7a41b5d67b40d4471e0ad1f04..cf656ecbe5073359b3c02b5faaeee9313f476740 100644 (file)
@@ -360,7 +360,7 @@ static struct ata_port_operations hpt366_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 532a7928f803074566d9986f58573794c94c61d6..10318c0012ef84a9c957f96229ab933d91c18c71 100644 (file)
@@ -793,7 +793,7 @@ static struct ata_port_operations hpt370_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -832,7 +832,7 @@ static struct ata_port_operations hpt370a_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -872,7 +872,7 @@ static struct ata_port_operations hpt372_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -912,7 +912,7 @@ static struct ata_port_operations hpt374_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 06c8db079b9125b7d4f400f4cbe6b15de4147ff8..5c5d4f6ab901e699c55cf3e327104ea6804b434f 100644 (file)
@@ -372,7 +372,7 @@ static struct ata_port_operations hpt3x2n_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = hpt3x2n_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 152770133ab1e57414babebbffa64dec143f788e..1f084ab1ccc6a65d6081c056ef7565b994e4895e 100644 (file)
@@ -145,7 +145,7 @@ static struct ata_port_operations hpt3x3_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 73948c8b727074c08819ff393a3003b945d8b1e8..640b8b0954f53ab5cd7a439c9c525040f796f4d9 100644 (file)
@@ -52,7 +52,7 @@ static struct ata_port_operations isapnp_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index af39097d808130dc38c72e7efcf40057ca6a90e3..82a46ff4000095d378c3bab18f7e926a60b2947b 100644 (file)
@@ -703,7 +703,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = it821x_smart_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -739,7 +739,7 @@ static struct ata_port_operations it821x_passthru_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = it821x_passthru_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_clear      = ata_bmdma_irq_clear,
index 6832a643a9eb770ae88d12c6f89565d918ad601e..be3a866b111faa3d23a8ea7ca1285d22dd72828d 100644 (file)
@@ -51,7 +51,7 @@ static int jmicron_pre_reset(struct ata_port *ap)
        /* Check if our port is enabled */
        pci_read_config_dword(pdev, 0x40, &control);
        if ((control & port_mask) == 0)
-               return 0;
+               return -ENOENT;
 
        /* There are two basic mappings. One has the two SATA ports merged
           as master/slave and the secondary as PATA, the other has only the
@@ -164,8 +164,7 @@ static const struct ata_port_operations jmicron_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       /* Timeout handling. Special recovery hooks here */
-       .eng_timeout            = ata_eng_timeout,
+       /* IRQ-related hooks */
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index ad37c220bb2cad1b7c8ed7ed2adb574db105ff7d..10231ef731d124a57c27c5f09ea34d9c51230d48 100644 (file)
@@ -161,7 +161,7 @@ static struct ata_port_operations simple_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer_noirq,
 
        .irq_handler    = ata_interrupt,
@@ -186,7 +186,7 @@ static struct ata_port_operations legacy_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer_noirq,
 
        .irq_handler    = ata_interrupt,
@@ -296,7 +296,7 @@ static struct ata_port_operations pdc20230_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = pdc_data_xfer_vlb,
 
        .irq_handler    = ata_interrupt,
@@ -348,7 +348,7 @@ static struct ata_port_operations ht6560a_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,    /* Check vlb/noirq */
 
        .irq_handler    = ata_interrupt,
@@ -411,7 +411,7 @@ static struct ata_port_operations ht6560b_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,    /* FIXME: Check 32bit and noirq */
 
        .irq_handler    = ata_interrupt,
@@ -529,7 +529,7 @@ static struct ata_port_operations opti82c611a_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -659,7 +659,7 @@ static struct ata_port_operations opti82c46x_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = opti82c46x_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 1958c4ed09a8d62acf9808e84dbee694a6802d1d..3c65393c1f01abfa9e7ab93e81c18323e1f6eb63 100644 (file)
@@ -18,7 +18,7 @@
  * The driver conciously keeps this logic internally to avoid pushing quirky
  * PATA history into the clean libata layer.
  *
- * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA
+ * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA
  * hard disk present this driver will not detect it. This is not a bug. In this
  * configuration the secondary port of the MPIIX is disabled and the addresses
  * are decoded by the PCMCIA bridge and therefore are for a generic IDE driver
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_mpiix"
-#define DRV_VERSION "0.7.1"
+#define DRV_VERSION "0.7.2"
 
 enum {
        IDETIM = 0x6C,          /* IDE control register */
@@ -54,11 +54,8 @@ static int mpiix_pre_reset(struct ata_port *ap)
                { 0x6F, 1, 0x80, 0x80 }
        };
 
-       if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->port_no]))
+               return -ENOENT;
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
index 16cb254cb9733ce148191ab0224831e08fb03660..76eb9c90bee1f3759b8194aabebfe23b95b65e09 100644 (file)
@@ -90,8 +90,7 @@ static const struct ata_port_operations netcell_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       /* Timeout handling. Special recovery hooks here */
-       .eng_timeout            = ata_eng_timeout,
+       /* IRQ-related hooks */
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index 93d6646d295414ae72601fa83b5ed4e18ae517bd..2005a95f48f6524be0e54206e7edbc97b0a51c7e 100644 (file)
@@ -45,11 +45,8 @@ static int ns87410_pre_reset(struct ata_port *ap)
                { 0x47, 1, 0x08, 0x08 }
        };
 
-       if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
+               return -ENOENT;
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
@@ -179,7 +176,7 @@ static struct ata_port_operations ns87410_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ns87410_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 04c618a2664b9be5788cf09f3629c0a8613ab159..31a285ca88dceb0e0292a17859b54ed279647424 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_oldpiix"
-#define DRV_VERSION    "0.5.1"
+#define DRV_VERSION    "0.5.2"
 
 /**
  *     oldpiix_pre_reset               -       probe begin
@@ -42,11 +42,8 @@ static int oldpiix_pre_reset(struct ata_port *ap)
                { 0x43U, 1U, 0x80UL, 0x80UL },  /* port 1 */
        };
 
-       if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
+               return -ENOENT;
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
index c3d01325e0e202a3a26a977c0079229770a02062..57fe21f3a97549c1617f71ba7dffb424a7229f24 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_opti"
-#define DRV_VERSION "0.2.4"
+#define DRV_VERSION "0.2.5"
 
 enum {
        READ_REG        = 0,    /* index of Read cycle timing register */
@@ -59,11 +59,9 @@ static int opti_pre_reset(struct ata_port *ap)
                { 0x40, 1, 0x08, 0x00 }
        };
 
-       if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
@@ -229,7 +227,7 @@ static struct ata_port_operations opti_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 177a455f4251a96624515d6884b9c3d81677c036..7296a20cd107310314448b21b4e5e5f445e65a18 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_optidma"
-#define DRV_VERSION "0.2.1"
+#define DRV_VERSION "0.2.2"
 
 enum {
        READ_REG        = 0,    /* index of Read cycle timing register */
@@ -59,11 +59,9 @@ static int optidma_pre_reset(struct ata_port *ap)
                0x40, 1, 0x08, 0x00
        };
 
-       if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits)) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
+               return -ENOENT;
+
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
@@ -388,7 +386,7 @@ static struct ata_port_operations optidma_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -423,7 +421,7 @@ static struct ata_port_operations optiplus_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 62b25cda409b89834eae39b66e9d42ea95675d91..cb501e145a42a4e85a8a12471a3ef0d8abcdf6ee 100644 (file)
@@ -87,7 +87,7 @@ static struct ata_port_operations pcmcia_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer_noirq,
 
        .irq_handler    = ata_interrupt,
index 31ab9c886209e8e870a340a27fc2522764f752c9..bd4ed6734edc504ca094dbcfb5d2ee6609182662 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "pata_pdc2027x"
-#define DRV_VERSION    "0.74-ac3"
+#define DRV_VERSION    "0.74-ac5"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -311,10 +311,8 @@ static inline int pdc2027x_port_enabled(struct ata_port *ap)
 static int pdc2027x_prereset(struct ata_port *ap)
 {
        /* Check whether port enabled */
-       if (!pdc2027x_port_enabled(ap)) {
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pdc2027x_port_enabled(ap))
+               return -ENOENT;
        pdc2027x_cbl_detect(ap);
        return ata_std_prereset(ap);
 }
index 35cfdf0ac3f015be7aa6d980ae40849eaedf50a8..7977f471d5e9a0619674f209600121c86b52ce24 100644 (file)
@@ -184,7 +184,7 @@ static struct ata_port_operations qdi6500_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = qdi_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = qdi_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -212,7 +212,7 @@ static struct ata_port_operations qdi6580_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = qdi_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = qdi_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 277f8411b521943a165b543dbb934a8dd6497d29..c20bcf43ed6d3ea9f4d2b6f129eec98ae23515a5 100644 (file)
@@ -255,8 +255,6 @@ static const struct ata_port_operations radisys_pata_ops = {
        .qc_issue               = radisys_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index 3c6d84fd43129f2fc7c22abfc74c4402c6fc19df..eccc6fd45032b4992091d74ddb2a608640186bea 100644 (file)
@@ -112,7 +112,7 @@ static struct ata_port_operations rz1000_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .freeze         = ata_bmdma_freeze,
index 4166c1a8a9e80999e3dd35c7af861f532fbdd2f9..107e6cd3dc0d1b9ba0179e5577bcc99e76a1d2e8 100644 (file)
@@ -217,7 +217,7 @@ static struct ata_port_operations sc1200_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = sc1200_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index af456113c55d60a92032396fdb5e22cd0e9a5892..a5c8d7e121d148ed992e25be28367d26dc02f92d 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_serverworks"
-#define DRV_VERSION "0.3.6"
+#define DRV_VERSION "0.3.7"
 
 #define SVWKS_CSB5_REVISION_NEW        0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
 #define SVWKS_CSB6_REVISION    0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -128,7 +128,7 @@ static struct sv_cable_table cable_detect[] = {
        { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable },
        { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable },
        { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN,  sun_cable },
-       { PCI_DEVICE_ID_SERVERWORKS_OSB4, PCI_ANY_ID, osb4_cable },
+       { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable },
        { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable },
        { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable },
        { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable },
@@ -352,10 +352,12 @@ static struct ata_port_operations serverworks_osb4_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
+       .irq_clear      = ata_bmdma_irq_clear,
+
        .port_start     = ata_port_start,
        .port_stop      = ata_port_stop,
        .host_stop      = ata_host_stop
@@ -385,10 +387,12 @@ static struct ata_port_operations serverworks_csb_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
+       .irq_clear      = ata_bmdma_irq_clear,
+
        .port_start     = ata_port_start,
        .port_stop      = ata_port_stop,
        .host_stop      = ata_host_stop
index 8f7db9638d0ac7f3eaaadade1d6a1471d78c7ffb..c8b2e26db70dd309e87fdc2babcea4b45da05715 100644 (file)
@@ -251,7 +251,7 @@ static struct ata_port_operations sil680_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 2e555168b431cdd59312db1edc63594bf0183269..17791e2785f9ca7f0def96858f8aa68de75ef234 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_sis"
-#define DRV_VERSION    "0.4.3"
+#define DRV_VERSION    "0.4.4"
 
 struct sis_chipset {
        u16 device;                     /* PCI host ID */
@@ -74,11 +74,9 @@ static int sis_133_pre_reset(struct ata_port *ap)
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        u16 tmp;
 
-       if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
+               return -ENOENT;
+
        /* The top bit of this register is the cable detect bit */
        pci_read_config_word(pdev, 0x50 + 2 * ap->port_no, &tmp);
        if (tmp & 0x8000)
@@ -575,8 +573,6 @@ static const struct ata_port_operations sis_133_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
@@ -610,8 +606,6 @@ static const struct ata_port_operations sis_133_early_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
@@ -646,8 +640,6 @@ static const struct ata_port_operations sis_100_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
@@ -681,8 +673,6 @@ static const struct ata_port_operations sis_66_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
@@ -716,8 +706,6 @@ static const struct ata_port_operations sis_old_ops = {
        .qc_issue               = ata_qc_issue_prot,
        .data_xfer              = ata_pio_data_xfer,
 
-       .eng_timeout            = ata_eng_timeout,
-
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
 
index f8499786917ae6cd53f60cd609dbc805d9e806a1..5b762acc56877a44f3a03b80139e61b9f21a70bc 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_sl82c105"
-#define DRV_VERSION "0.2.2"
+#define DRV_VERSION "0.2.3"
 
 enum {
        /*
@@ -49,11 +49,8 @@ static int sl82c105_pre_reset(struct ata_port *ap)
        };
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-       if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               dev_printk(KERN_INFO, &pdev->dev, "port disabled. ignoring.\n");
-               return 0;
-       }
+       if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
+               return -ENOENT;
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
@@ -264,7 +261,7 @@ static struct ata_port_operations sl82c105_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 36f788728f3f8ab7e4ffb054ffea76fb89f82a55..a954ed93a40ca48a4ba8b4c5d71d23c549d5fc81 100644 (file)
 #define DRV_VERSION "0.2.5"
 
 /**
- *     triflex_probe_init              -       probe begin
+ *     triflex_prereset                -       probe begin
  *     @ap: ATA port
  *
  *     Set up cable type and use generic probe init
  */
 
-static int triflex_probe_init(struct ata_port *ap)
+static int triflex_prereset(struct ata_port *ap)
 {
        static const struct pci_bits triflex_enable_bits[] = {
                { 0x80, 1, 0x01, 0x01 },
@@ -61,11 +61,8 @@ static int triflex_probe_init(struct ata_port *ap)
 
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-       if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no])) {
-               ata_port_disable(ap);
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-               return 0;
-       }
+       if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
+               return -ENOENT;
        ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
@@ -74,7 +71,7 @@ static int triflex_probe_init(struct ata_port *ap)
 
 static void triflex_error_handler(struct ata_port *ap)
 {
-       ata_bmdma_drive_eh(ap, triflex_probe_init, ata_std_softreset, NULL, ata_std_postreset);
+       ata_bmdma_drive_eh(ap, triflex_prereset, ata_std_softreset, NULL, ata_std_postreset);
 }
 
 /**
@@ -221,7 +218,7 @@ static struct ata_port_operations triflex_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
index 1b2ff133b163302992b33ef967478fdc68673110..7b5dd2343b9a637a9bced517f635ebb133c92f8b 100644 (file)
@@ -60,7 +60,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_via"
-#define DRV_VERSION "0.1.13"
+#define DRV_VERSION "0.1.14"
 
 /*
  *     The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
@@ -155,11 +155,8 @@ static int via_pre_reset(struct ata_port *ap)
 
                struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-               if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no])) {
-                       ata_port_disable(ap);
-                       printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
-                       return 0;
-               }
+               if (!pci_test_config_bits(pdev, &via_enable_bits[ap->port_no]))
+                       return -ENOENT;
        }
 
        if ((config->flags & VIA_UDMA) >= VIA_UDMA_66)
@@ -325,7 +322,7 @@ static struct ata_port_operations via_port_ops = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer,
 
        .irq_handler    = ata_interrupt,
@@ -360,7 +357,7 @@ static struct ata_port_operations via_port_ops_noirq = {
 
        .qc_prep        = ata_qc_prep,
        .qc_issue       = ata_qc_issue_prot,
-       .eng_timeout    = ata_eng_timeout,
+
        .data_xfer      = ata_pio_data_xfer_noirq,
 
        .irq_handler    = ata_interrupt,
index fdce6e07ecd2073d5f474e731b3828d5d990afcc..c01496df4a99c709b7a8f13804207fe3c28149ae 100644 (file)
@@ -463,6 +463,7 @@ static const struct ata_port_operations mv_iie_ops = {
 
        .qc_prep                = mv_qc_prep_iie,
        .qc_issue               = mv_qc_issue,
+       .data_xfer              = ata_mmio_data_xfer,
 
        .eng_timeout            = mv_eng_timeout,
 
index b539e5e75b5690116f868c9ea06283c758f6f7a7..7bbb9eeda235efb5dd307eb1d5e89dfa552f550a 100644 (file)
@@ -8,7 +8,7 @@ obj-y                   += power/
 obj-$(CONFIG_ISA)      += isa.o
 obj-$(CONFIG_FW_LOADER)        += firmware_class.o
 obj-$(CONFIG_NUMA)     += node.o
-obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
+obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
 obj-$(CONFIG_SMP)      += topology.o
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
 
index b06b0e2b9c62b536a321d12295988af5801012b3..b32b77ff2dcd7c1814c66318a477b74840b88e2f 100644 (file)
@@ -228,7 +228,7 @@ error:
 
 /**
  * class_destroy - destroys a struct class structure
- * @cs: pointer to the struct class that is to be destroyed
+ * @cls: pointer to the struct class that is to be destroyed
  *
  * Note, the pointer to be destroyed must have been created with a call
  * to class_create().
@@ -658,9 +658,9 @@ int class_device_register(struct class_device *class_dev)
 
 /**
  * class_device_create - creates a class device and registers it with sysfs
- * @cs: pointer to the struct class that this device should be registered to.
+ * @cls: pointer to the struct class that this device should be registered to.
  * @parent: pointer to the parent struct class_device of this new device, if any.
- * @dev: the dev_t for the char device to be added.
+ * @devt: the dev_t for the char device to be added.
  * @device: a pointer to a struct device that is assiociated with this class device.
  * @fmt: string for the class device's name
  *
@@ -766,7 +766,7 @@ void class_device_unregister(struct class_device *class_dev)
 /**
  * class_device_destroy - removes a class device that was created with class_device_create()
  * @cls: the pointer to the struct class that this device was registered * with.
- * @dev: the dev_t of the device that was previously registered.
+ * @devt: the dev_t of the device that was previously registered.
  *
  * This call unregisters and cleans up a class device that was created with a
  * call to class_device_create()
index 5d6c011183f5b7259297276b251f1648580421c7..14615694ae9aa3e707435f2f04a1c6dde4586c5c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/kthread.h>
 
 #include <linux/firmware.h>
 #include "base.h"
@@ -511,7 +512,6 @@ request_firmware_work_func(void *arg)
                WARN_ON(1);
                return 0;
        }
-       daemonize("%s/%s", "firmware", fw_work->name);
        ret = _request_firmware(&fw, fw_work->name, fw_work->device,
                fw_work->uevent);
        if (ret < 0)
@@ -546,9 +546,9 @@ request_firmware_nowait(
        const char *name, struct device *device, void *context,
        void (*cont)(const struct firmware *fw, void *context))
 {
+       struct task_struct *task;
        struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
                                                GFP_ATOMIC);
-       int ret;
 
        if (!fw_work)
                return -ENOMEM;
@@ -566,14 +566,14 @@ request_firmware_nowait(
                .uevent = uevent,
        };
 
-       ret = kernel_thread(request_firmware_work_func, fw_work,
-                           CLONE_FS | CLONE_FILES);
+       task = kthread_run(request_firmware_work_func, fw_work,
+                           "firmware/%s", name);
 
-       if (ret < 0) {
+       if (IS_ERR(task)) {
                fw_work->cont(NULL, fw_work->context);
                module_put(fw_work->module);
                kfree(fw_work);
-               return ret;
+               return PTR_ERR(task);
        }
        return 0;
 }
@@ -602,7 +602,7 @@ firmware_class_exit(void)
        class_unregister(&firmware_class);
 }
 
-module_init(firmware_class_init);
+fs_initcall(firmware_class_init);
 module_exit(firmware_class_exit);
 
 EXPORT_SYMBOL(release_firmware);
index a360215dbce79cc1ff85f4b03651000ae17436b0..b3f639fbf220038a8b04fad8de15178741ab9e16 100644 (file)
@@ -770,7 +770,7 @@ static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_ExecuteCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  DECLARE_COMPLETION(Completion);
+  DECLARE_COMPLETION_ONSTACK(Completion);
   unsigned long flags;
   Command->Completion = &Completion;
 
@@ -3331,7 +3331,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_
                Command->DmaDirection = PCI_DMA_TODEVICE;
                Command->CommandType = DAC960_WriteCommand;
        }
-       Command->Completion = Request->waiting;
+       Command->Completion = Request->end_io_data;
        Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
        Command->BlockNumber = Request->sector;
        Command->BlockCount = Request->nr_sectors;
index a82f37f749a5c2e265dd96c4d2abb88e84a7d329..f9217c34bc2bb2cbf200f2d4a3f3eb486de11cf0 100644 (file)
@@ -71,7 +71,7 @@
   Define a Boolean data type.
 */
 
-typedef enum { false, true } __attribute__ ((packed)) boolean;
+typedef bool boolean;
 
 
 /*
index b5382cedf0c09cad0376df575c32b194d5ba7c0d..422e31d5f8e5c4627c15c88ecc38ff8627276069 100644 (file)
@@ -2,6 +2,8 @@
 # Block device driver configuration
 #
 
+if BLOCK
+
 menu "Block devices"
 
 config BLK_DEV_FD
@@ -468,3 +470,5 @@ config ATA_OVER_ETH
        devices like the Coraid EtherDrive (R) Storage Blade.
 
 endmenu
+
+endif
index 2cd3391ff8783dcb8497600d833f4cedf4a24eb4..99f87efe0f588b2d4327516b7a7dac0304fcc39b 100644 (file)
@@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
 static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
                           int clear_all);
 
-static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
-                               int withirq, unsigned int *total_size,
-                               unsigned int *block_size);
-static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq,
-                                  unsigned int total_size,
-                                  unsigned int block_size,
-                                  InquiryData_struct *inq_buff,
+static void cciss_read_capacity(int ctlr, int logvol, int withirq,
+                       sector_t *total_size, unsigned int *block_size);
+static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
+                       sector_t *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+                       int withirq, sector_t total_size,
+                       unsigned int block_size, InquiryData_struct *inq_buff,
                                   drive_info_struct *drv);
 static void cciss_getgeometry(int cntl_num);
 static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
@@ -879,7 +879,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                        char *buff = NULL;
                        u64bit temp64;
                        unsigned long flags;
-                       DECLARE_COMPLETION(wait);
+                       DECLARE_COMPLETION_ONSTACK(wait);
 
                        if (!arg)
                                return -EINVAL;
@@ -997,7 +997,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                        BYTE sg_used = 0;
                        int status = 0;
                        int i;
-                       DECLARE_COMPLETION(wait);
+                       DECLARE_COMPLETION_ONSTACK(wait);
                        __u32 left;
                        __u32 sz;
                        BYTE __user *data_ptr;
@@ -1229,7 +1229,6 @@ static inline void complete_buffers(struct bio *bio, int status)
                int nr_sectors = bio_sectors(bio);
 
                bio->bi_next = NULL;
-               blk_finished_io(len);
                bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
                bio = xbh;
        }
@@ -1326,10 +1325,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
 {
        ctlr_info_t *h = hba[ctlr];
        struct gendisk *disk;
-       ReadCapdata_struct *size_buff = NULL;
        InquiryData_struct *inq_buff = NULL;
        unsigned int block_size;
-       unsigned int total_size;
+       sector_t total_size;
        unsigned long flags = 0;
        int ret = 0;
 
@@ -1348,15 +1346,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
                return;
 
        /* Get information about the disk and modify the driver structure */
-       size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
-       if (size_buff == NULL)
-               goto mem_msg;
        inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
        if (inq_buff == NULL)
                goto mem_msg;
 
-       cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+       cciss_read_capacity(ctlr, drv_index, 1,
                            &total_size, &block_size);
+
+       /* total size = last LBA + 1 */
+       /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
+       /* so we assume this volume this must be >2TB in size */
+       if (total_size == (__u32) 0) {
+               cciss_read_capacity_16(ctlr, drv_index, 1,
+               &total_size, &block_size);
+               h->cciss_read = CCISS_READ_16;
+               h->cciss_write = CCISS_WRITE_16;
+       } else {
+               h->cciss_read = CCISS_READ_10;
+               h->cciss_write = CCISS_WRITE_10;
+       }
        cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
                               inq_buff, &h->drv[drv_index]);
 
@@ -1392,7 +1400,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
        }
 
       freeret:
-       kfree(size_buff);
        kfree(inq_buff);
        return;
       mem_msg:
@@ -1717,6 +1724,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = cmd;
                        break;
+               case CCISS_READ_CAPACITY_16:
+                       c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
+                       c->Header.LUN.LogDev.Mode = 1;
+                       c->Request.CDBLen = 16;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = cmd;
+                       c->Request.CDB[1] = 0x10;
+                       c->Request.CDB[10] = (size >> 24) & 0xFF;
+                       c->Request.CDB[11] = (size >> 16) & 0xFF;
+                       c->Request.CDB[12] = (size >> 8) & 0xFF;
+                       c->Request.CDB[13] = size & 0xFF;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = cmd;
+                       break;
                case CCISS_CACHE_FLUSH:
                        c->Request.CDBLen = 12;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1750,6 +1773,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
                        memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
                        c->Request.CDB[0] = cmd;        /* reset */
                        c->Request.CDB[1] = 0x04;       /* reset a LUN */
+                       break;
                case 3: /* No-Op message */
                        c->Request.CDBLen = 1;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1792,7 +1816,7 @@ static int sendcmd_withirq(__u8 cmd,
        u64bit buff_dma_handle;
        unsigned long flags;
        int return_status;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
 
        if ((c = cmd_alloc(h, 0)) == NULL)
                return -ENOMEM;
@@ -1893,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd,
 }
 
 static void cciss_geometry_inquiry(int ctlr, int logvol,
-                                  int withirq, unsigned int total_size,
+                                  int withirq, sector_t total_size,
                                   unsigned int block_size,
                                   InquiryData_struct *inq_buff,
                                   drive_info_struct *drv)
 {
        int return_code;
+       unsigned long t;
+       unsigned long rem;
+
        memset(inq_buff, 0, sizeof(InquiryData_struct));
        if (withirq)
                return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
@@ -1917,10 +1944,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                        drv->nr_blocks = total_size;
                        drv->heads = 255;
                        drv->sectors = 32;      // Sectors per track
-                       drv->cylinders = total_size / 255 / 32;
+                       t = drv->heads * drv->sectors;
+                       drv->cylinders = total_size;
+                       rem = do_div(drv->cylinders, t);
                } else {
-                       unsigned int t;
-
                        drv->block_size = block_size;
                        drv->nr_blocks = total_size;
                        drv->heads = inq_buff->data_byte[6];
@@ -1930,42 +1957,84 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                        drv->raid_level = inq_buff->data_byte[8];
                        t = drv->heads * drv->sectors;
                        if (t > 1) {
-                               drv->cylinders = total_size / t;
+                               drv->cylinders = total_size;
+                               rem = do_div(drv->cylinders, t);
                        }
                }
        } else {                /* Get geometry failed */
                printk(KERN_WARNING "cciss: reading geometry failed\n");
        }
-       printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",
+       printk(KERN_INFO "      heads=%d, sectors=%d, cylinders=%d\n\n",
               drv->heads, drv->sectors, drv->cylinders);
 }
 
 static void
-cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
-                   int withirq, unsigned int *total_size,
+cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
                    unsigned int *block_size)
 {
+       ReadCapdata_struct *buf;
        int return_code;
-       memset(buf, 0, sizeof(*buf));
+       buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+       if (buf == NULL) {
+               printk(KERN_WARNING "cciss: out of memory\n");
+               return;
+       }
+       memset(buf, 0, sizeof(ReadCapdata_struct));
        if (withirq)
                return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
-                                             ctlr, buf, sizeof(*buf), 1,
-                                             logvol, 0, TYPE_CMD);
+                               ctlr, buf, sizeof(ReadCapdata_struct),
+                                       1, logvol, 0, TYPE_CMD);
        else
                return_code = sendcmd(CCISS_READ_CAPACITY,
-                                     ctlr, buf, sizeof(*buf), 1, logvol, 0,
-                                     NULL, TYPE_CMD);
+                               ctlr, buf, sizeof(ReadCapdata_struct),
+                                       1, logvol, 0, NULL, TYPE_CMD);
        if (return_code == IO_OK) {
-               *total_size =
-                   be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1;
-               *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
+               *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
+               *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
                *total_size = 0;
                *block_size = BLOCK_SIZE;
        }
-       printk(KERN_INFO "      blocks= %u block_size= %d\n",
+       if (*total_size != (__u32) 0)
+               printk(KERN_INFO "      blocks= %lld block_size= %d\n",
+               *total_size, *block_size);
+       kfree(buf);
+       return;
+}
+
+static void
+cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,                                unsigned int *block_size)
+{
+       ReadCapdata_struct_16 *buf;
+       int return_code;
+       buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
+       if (buf == NULL) {
+               printk(KERN_WARNING "cciss: out of memory\n");
+               return;
+       }
+       memset(buf, 0, sizeof(ReadCapdata_struct_16));
+       if (withirq) {
+               return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
+                       ctlr, buf, sizeof(ReadCapdata_struct_16),
+                               1, logvol, 0, TYPE_CMD);
+       }
+       else {
+               return_code = sendcmd(CCISS_READ_CAPACITY_16,
+                       ctlr, buf, sizeof(ReadCapdata_struct_16),
+                               1, logvol, 0, NULL, TYPE_CMD);
+       }
+       if (return_code == IO_OK) {
+               *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
+               *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+       } else {                /* read capacity command failed */
+               printk(KERN_WARNING "cciss: read capacity failed\n");
+               *total_size = 0;
+               *block_size = BLOCK_SIZE;
+       }
+       printk(KERN_INFO "      blocks= %lld block_size= %d\n",
               *total_size, *block_size);
+       kfree(buf);
        return;
 }
 
@@ -1976,8 +2045,7 @@ static int cciss_revalidate(struct gendisk *disk)
        int logvol;
        int FOUND = 0;
        unsigned int block_size;
-       unsigned int total_size;
-       ReadCapdata_struct *size_buff = NULL;
+       sector_t total_size;
        InquiryData_struct *inq_buff = NULL;
 
        for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
@@ -1990,27 +2058,24 @@ static int cciss_revalidate(struct gendisk *disk)
        if (!FOUND)
                return 1;
 
-       size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
-       if (size_buff == NULL) {
-               printk(KERN_WARNING "cciss: out of memory\n");
-               return 1;
-       }
        inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
        if (inq_buff == NULL) {
                printk(KERN_WARNING "cciss: out of memory\n");
-               kfree(size_buff);
                return 1;
        }
-
-       cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size,
-                           &block_size);
+       if (h->cciss_read == CCISS_READ_10) {
+               cciss_read_capacity(h->ctlr, logvol, 1,
+                                       &total_size, &block_size);
+       } else {
+               cciss_read_capacity_16(h->ctlr, logvol, 1,
+                                       &total_size, &block_size);
+       }
        cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
                               inq_buff, drv);
 
        blk_queue_hardsect_size(drv->queue, drv->block_size);
        set_capacity(disk, drv->nr_blocks);
 
-       kfree(size_buff);
        kfree(inq_buff);
        return 0;
 }
@@ -2419,7 +2484,8 @@ static void do_cciss_request(request_queue_t *q)
 {
        ctlr_info_t *h = q->queuedata;
        CommandList_struct *c;
-       int start_blk, seg;
+       sector_t start_blk;
+       int seg;
        struct request *creq;
        u64bit temp64;
        struct scatterlist tmp_sg[MAXSGENTRIES];
@@ -2463,10 +2529,10 @@ static void do_cciss_request(request_queue_t *q)
        c->Request.Type.Type = TYPE_CMD;        // It is a command.
        c->Request.Type.Attribute = ATTR_SIMPLE;
        c->Request.Type.Direction =
-           (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
+           (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
        c->Request.Timeout = 0; // Don't time out
        c->Request.CDB[0] =
-           (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
+           (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
        start_blk = creq->sector;
 #ifdef CCISS_DEBUG
        printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
@@ -2500,15 +2566,33 @@ static void do_cciss_request(request_queue_t *q)
 #endif                         /* CCISS_DEBUG */
 
        c->Header.SGList = c->Header.SGTotal = seg;
-       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(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;
+       }
 
        spin_lock_irq(q->queue_lock);
 
@@ -2518,9 +2602,9 @@ static void do_cciss_request(request_queue_t *q)
                h->maxQsinceinit = h->Qdepth;
 
        goto queue;
-      full:
+full:
        blk_stop_queue(q);
-      startio:
+startio:
        /* We will already have the driver lock here so not need
         * to lock it.
         */
@@ -2948,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 static void cciss_getgeometry(int cntl_num)
 {
        ReportLunData_struct *ld_buff;
-       ReadCapdata_struct *size_buff;
        InquiryData_struct *inq_buff;
        int return_code;
        int i;
        int listlength = 0;
        __u32 lunid = 0;
        int block_size;
-       int total_size;
+       sector_t total_size;
 
        ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
        if (ld_buff == NULL) {
                printk(KERN_ERR "cciss: out of memory\n");
                return;
        }
-       size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
-       if (size_buff == NULL) {
-               printk(KERN_ERR "cciss: out of memory\n");
-               kfree(ld_buff);
-               return;
-       }
        inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
        if (inq_buff == NULL) {
                printk(KERN_ERR "cciss: out of memory\n");
                kfree(ld_buff);
-               kfree(size_buff);
                return;
        }
        /* Get the firmware version */
@@ -3027,7 +3103,6 @@ static void cciss_getgeometry(int cntl_num)
 #endif                         /* CCISS_DEBUG */
 
        hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
-//      for(i=0; i<  hba[cntl_num]->num_luns; i++)
        for (i = 0; i < CISS_MAX_LUN; i++) {
                if (i < hba[cntl_num]->num_luns) {
                        lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
@@ -3046,8 +3121,26 @@ static void cciss_getgeometry(int cntl_num)
                               ld_buff->LUN[i][2], ld_buff->LUN[i][3],
                               hba[cntl_num]->drv[i].LunID);
 #endif                         /* CCISS_DEBUG */
-                       cciss_read_capacity(cntl_num, i, size_buff, 0,
+
+               /* testing to see if 16-byte CDBs are already being used */
+               if(hba[cntl_num]->cciss_read == CCISS_READ_16) {
+                       cciss_read_capacity_16(cntl_num, i, 0,
                                            &total_size, &block_size);
+                       goto geo_inq;
+               }
+               cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
+
+               /* total_size = last LBA + 1 */
+               if(total_size == (__u32) 0) {
+                       cciss_read_capacity_16(cntl_num, i, 0,
+                       &total_size, &block_size);
+                       hba[cntl_num]->cciss_read = CCISS_READ_16;
+                       hba[cntl_num]->cciss_write = CCISS_WRITE_16;
+               } else {
+                       hba[cntl_num]->cciss_read = CCISS_READ_10;
+                       hba[cntl_num]->cciss_write = CCISS_WRITE_10;
+               }
+geo_inq:
                        cciss_geometry_inquiry(cntl_num, i, 0, total_size,
                                               block_size, inq_buff,
                                               &hba[cntl_num]->drv[i]);
@@ -3057,7 +3150,6 @@ static void cciss_getgeometry(int cntl_num)
                }
        }
        kfree(ld_buff);
-       kfree(size_buff);
        kfree(inq_buff);
 }
 
index 868e0d862b0d274980857ee8593a385006ae2432..562235c1445a123b9a5f36293b6f28bf887c2ff0 100644 (file)
@@ -76,6 +76,9 @@ struct ctlr_info
        unsigned int intr[4];
        unsigned int msix_vector;
        unsigned int msi_vector;
+       BYTE    cciss_read;
+       BYTE    cciss_write;
+       BYTE    cciss_read_capacity;
 
        // information about each logical volume
        drive_info_struct drv[CISS_MAX_LUN];
index 53fea549ba8b23a6714cfd8a33fc55705893986e..4af7c4c0c7afb4610863d36142ed1e9ad19d994f 100644 (file)
@@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct
   BYTE block_size[4];  // Size of blocks in bytes
 } ReadCapdata_struct;
 
-// 12 byte commands not implemented in firmware yet. 
-// #define CCISS_READ  0xa8    // Read(12)
-// #define CCISS_WRITE 0xaa    // Write(12)
- #define CCISS_READ   0x28    // Read(10)
- #define CCISS_WRITE  0x2a    // Write(10)
+#define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */
+
+/* service action to differentiate a 16 byte read capacity from
+   other commands that use the 0x9e SCSI op code */
+
+#define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10
+
+typedef struct _ReadCapdata_struct_16
+{
+       BYTE total_size[8];   /* Total size in blocks */
+       BYTE block_size[4];   /* Size of blocks in bytes */
+       BYTE prot_en:1;       /* protection enable bit */
+       BYTE rto_en:1;        /* reference tag own enable bit */
+       BYTE reserved:6;      /* reserved bits */
+       BYTE reserved2[18];   /* reserved bytes per spec */
+} ReadCapdata_struct_16;
+
+/* Define the supported read/write commands for cciss based controllers */
+
+#define CCISS_READ_10   0x28    /* Read(10)  */
+#define CCISS_WRITE_10  0x2a    /* Write(10) */
+#define CCISS_READ_16   0x88    /* Read(16)  */
+#define CCISS_WRITE_16  0x8a    /* Write(16) */
+
+/* Define the CDB lengths supported by cciss based controllers */
+
+#define CDB_LEN10      10
+#define CDB_LEN16      16
 
 // BMIC commands 
 #define BMIC_READ 0x26
index 05f79d7393f72960a1f8af8006ba025f939e4a43..bb15051ffbe0d316182cbb9ef11d9dba9b8f64c0 100644 (file)
@@ -766,7 +766,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c,
                        int direction)
 {
        unsigned long flags;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
 
        cp->cmd_type = CMD_IOCTL_PEND;          // treat this like an ioctl 
        cp->scsi_cmd = NULL;
index 78082edc14b4f6fdaec8652f12b45e3a921c3223..4abc193314ee6c34f7a6e93f5e5faaaca8c3761f 100644 (file)
@@ -989,7 +989,6 @@ static inline void complete_buffers(struct bio *bio, int ok)
                xbh = bio->bi_next;
                bio->bi_next = NULL;
                
-               blk_finished_io(nr_sectors);
                bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO);
 
                bio = xbh;
index ad1d7065a1b20ef10028c8723bf63fab817ade4a..629c5769d994e3a45aa9063cfd5cf08532f2c494 100644 (file)
@@ -2991,8 +2991,8 @@ static void do_fd_request(request_queue_t * q)
        if (usage_count == 0) {
                printk("warning: usage count=0, current_req=%p exiting\n",
                       current_req);
-               printk("sect=%ld flags=%lx\n", (long)current_req->sector,
-                      current_req->flags);
+               printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
+                      current_req->cmd_type, current_req->cmd_flags);
                return;
        }
        if (test_bit(0, &fdc_busy)) {
index 7b3b94ddddccb4aaf5cab64e6e94923ab2fb6c49..d6bb8da955a213c0c192dd3272ea435393a0a180 100644 (file)
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/loop.h>
+#include <linux/compat.h>
 #include <linux/suspend.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>         /* for invalidate_bdev() */
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -522,15 +524,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
                goto out;
        if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
                goto out;
-       lo->lo_pending++;
        loop_add_bio(lo, old_bio);
+       wake_up(&lo->lo_event);
        spin_unlock_irq(&lo->lo_lock);
-       complete(&lo->lo_bh_done);
        return 0;
 
 out:
-       if (lo->lo_pending == 0)
-               complete(&lo->lo_bh_done);
        spin_unlock_irq(&lo->lo_lock);
        bio_io_error(old_bio, old_bio->bi_size);
        return 0;
@@ -570,14 +569,18 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
  * to avoid blocking in our make_request_fn. it also does loop decrypting
  * on reads for block backed loop, as that is too heavy to do from
  * b_end_io context where irqs may be disabled.
+ *
+ * Loop explanation:  loop_clr_fd() sets lo_state to Lo_rundown before
+ * calling kthread_stop().  Therefore once kthread_should_stop() is
+ * true, make_request will not place any more requests.  Therefore
+ * once kthread_should_stop() is true and lo_bio is NULL, we are
+ * done with the loop.
  */
 static int loop_thread(void *data)
 {
        struct loop_device *lo = data;
        struct bio *bio;
 
-       daemonize("loop%d", lo->lo_number);
-
        /*
         * loop can be used in an encrypted device,
         * hence, it mustn't be stopped at all
@@ -587,47 +590,21 @@ static int loop_thread(void *data)
 
        set_user_nice(current, -20);
 
-       lo->lo_state = Lo_bound;
-       lo->lo_pending = 1;
+       while (!kthread_should_stop() || lo->lo_bio) {
 
-       /*
-        * complete it, we are running
-        */
-       complete(&lo->lo_done);
-
-       for (;;) {
-               int pending;
+               wait_event_interruptible(lo->lo_event,
+                               lo->lo_bio || kthread_should_stop());
 
-               if (wait_for_completion_interruptible(&lo->lo_bh_done))
+               if (!lo->lo_bio)
                        continue;
-
                spin_lock_irq(&lo->lo_lock);
-
-               /*
-                * could be completed because of tear-down, not pending work
-                */
-               if (unlikely(!lo->lo_pending)) {
-                       spin_unlock_irq(&lo->lo_lock);
-                       break;
-               }
-
                bio = loop_get_bio(lo);
-               lo->lo_pending--;
-               pending = lo->lo_pending;
                spin_unlock_irq(&lo->lo_lock);
 
                BUG_ON(!bio);
                loop_handle_bio(lo, bio);
-
-               /*
-                * upped both for pending work and tear-down, lo_pending
-                * will hit zero then
-                */
-               if (unlikely(!pending))
-                       break;
        }
 
-       complete(&lo->lo_done);
        return 0;
 }
 
@@ -662,7 +639,8 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
 
        mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
        lo->lo_backing_file = file;
-       lo->lo_blocksize = mapping->host->i_blksize;
+       lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
+               mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
        lo->old_gfp_mask = mapping_gfp_mask(mapping);
        mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
        complete(&p->wait);
@@ -794,7 +772,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
                if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
                        lo_flags |= LO_FLAGS_READ_ONLY;
 
-               lo_blocksize = inode->i_blksize;
+               lo_blocksize = S_ISBLK(inode->i_mode) ?
+                       inode->i_bdev->bd_block_size : PAGE_SIZE;
+
                error = 0;
        } else {
                goto out_putf;
@@ -837,12 +817,26 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
 
        set_blocksize(bdev, lo_blocksize);
 
-       error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
-       if (error < 0)
-               goto out_putf;
-       wait_for_completion(&lo->lo_done);
+       lo->lo_thread = kthread_create(loop_thread, lo, "loop%d",
+                                               lo->lo_number);
+       if (IS_ERR(lo->lo_thread)) {
+               error = PTR_ERR(lo->lo_thread);
+               goto out_clr;
+       }
+       lo->lo_state = Lo_bound;
+       wake_up_process(lo->lo_thread);
        return 0;
 
+out_clr:
+       lo->lo_thread = NULL;
+       lo->lo_device = NULL;
+       lo->lo_backing_file = NULL;
+       lo->lo_flags = 0;
+       set_capacity(disks[lo->lo_number], 0);
+       invalidate_bdev(bdev, 0);
+       bd_set_size(bdev, 0);
+       mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
+       lo->lo_state = Lo_unbound;
  out_putf:
        fput(file);
  out:
@@ -904,12 +898,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 
        spin_lock_irq(&lo->lo_lock);
        lo->lo_state = Lo_rundown;
-       lo->lo_pending--;
-       if (!lo->lo_pending)
-               complete(&lo->lo_bh_done);
        spin_unlock_irq(&lo->lo_lock);
 
-       wait_for_completion(&lo->lo_done);
+       kthread_stop(lo->lo_thread);
 
        lo->lo_backing_file = NULL;
 
@@ -922,6 +913,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        lo->lo_sizelimit = 0;
        lo->lo_encrypt_key_size = 0;
        lo->lo_flags = 0;
+       lo->lo_thread = NULL;
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
        memset(lo->lo_file_name, 0, LO_NAME_SIZE);
@@ -1174,6 +1166,162 @@ static int lo_ioctl(struct inode * inode, struct file * file,
        return err;
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_loop_info {
+       compat_int_t    lo_number;      /* ioctl r/o */
+       compat_dev_t    lo_device;      /* ioctl r/o */
+       compat_ulong_t  lo_inode;       /* ioctl r/o */
+       compat_dev_t    lo_rdevice;     /* ioctl r/o */
+       compat_int_t    lo_offset;
+       compat_int_t    lo_encrypt_type;
+       compat_int_t    lo_encrypt_key_size;    /* ioctl w/o */
+       compat_int_t    lo_flags;       /* ioctl r/o */
+       char            lo_name[LO_NAME_SIZE];
+       unsigned char   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+       compat_ulong_t  lo_init[2];
+       char            reserved[4];
+};
+
+/*
+ * Transfer 32-bit compatibility structure in userspace to 64-bit loop info
+ * - noinlined to reduce stack space usage in main part of driver
+ */
+static noinline int
+loop_info64_from_compat(const struct compat_loop_info *arg,
+                       struct loop_info64 *info64)
+{
+       struct compat_loop_info info;
+
+       if (copy_from_user(&info, arg, sizeof(info)))
+               return -EFAULT;
+
+       memset(info64, 0, sizeof(*info64));
+       info64->lo_number = info.lo_number;
+       info64->lo_device = info.lo_device;
+       info64->lo_inode = info.lo_inode;
+       info64->lo_rdevice = info.lo_rdevice;
+       info64->lo_offset = info.lo_offset;
+       info64->lo_sizelimit = 0;
+       info64->lo_encrypt_type = info.lo_encrypt_type;
+       info64->lo_encrypt_key_size = info.lo_encrypt_key_size;
+       info64->lo_flags = info.lo_flags;
+       info64->lo_init[0] = info.lo_init[0];
+       info64->lo_init[1] = info.lo_init[1];
+       if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+               memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE);
+       else
+               memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
+       memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE);
+       return 0;
+}
+
+/*
+ * Transfer 64-bit loop info to 32-bit compatibility structure in userspace
+ * - noinlined to reduce stack space usage in main part of driver
+ */
+static noinline int
+loop_info64_to_compat(const struct loop_info64 *info64,
+                     struct compat_loop_info __user *arg)
+{
+       struct compat_loop_info info;
+
+       memset(&info, 0, sizeof(info));
+       info.lo_number = info64->lo_number;
+       info.lo_device = info64->lo_device;
+       info.lo_inode = info64->lo_inode;
+       info.lo_rdevice = info64->lo_rdevice;
+       info.lo_offset = info64->lo_offset;
+       info.lo_encrypt_type = info64->lo_encrypt_type;
+       info.lo_encrypt_key_size = info64->lo_encrypt_key_size;
+       info.lo_flags = info64->lo_flags;
+       info.lo_init[0] = info64->lo_init[0];
+       info.lo_init[1] = info64->lo_init[1];
+       if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+               memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+       else
+               memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
+       memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
+
+       /* error in case values were truncated */
+       if (info.lo_device != info64->lo_device ||
+           info.lo_rdevice != info64->lo_rdevice ||
+           info.lo_inode != info64->lo_inode ||
+           info.lo_offset != info64->lo_offset ||
+           info.lo_init[0] != info64->lo_init[0] ||
+           info.lo_init[1] != info64->lo_init[1])
+               return -EOVERFLOW;
+
+       if (copy_to_user(arg, &info, sizeof(info)))
+               return -EFAULT;
+       return 0;
+}
+
+static int
+loop_set_status_compat(struct loop_device *lo,
+                      const struct compat_loop_info __user *arg)
+{
+       struct loop_info64 info64;
+       int ret;
+
+       ret = loop_info64_from_compat(arg, &info64);
+       if (ret < 0)
+               return ret;
+       return loop_set_status(lo, &info64);
+}
+
+static int
+loop_get_status_compat(struct loop_device *lo,
+                      struct compat_loop_info __user *arg)
+{
+       struct loop_info64 info64;
+       int err = 0;
+
+       if (!arg)
+               err = -EINVAL;
+       if (!err)
+               err = loop_get_status(lo, &info64);
+       if (!err)
+               err = loop_info64_to_compat(&info64, arg);
+       return err;
+}
+
+static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+       int err;
+
+       lock_kernel();
+       switch(cmd) {
+       case LOOP_SET_STATUS:
+               mutex_lock(&lo->lo_ctl_mutex);
+               err = loop_set_status_compat(
+                       lo, (const struct compat_loop_info __user *) arg);
+               mutex_unlock(&lo->lo_ctl_mutex);
+               break;
+       case LOOP_GET_STATUS:
+               mutex_lock(&lo->lo_ctl_mutex);
+               err = loop_get_status_compat(
+                       lo, (struct compat_loop_info __user *) arg);
+               mutex_unlock(&lo->lo_ctl_mutex);
+               break;
+       case LOOP_CLR_FD:
+       case LOOP_GET_STATUS64:
+       case LOOP_SET_STATUS64:
+               arg = (unsigned long) compat_ptr(arg);
+       case LOOP_SET_FD:
+       case LOOP_CHANGE_FD:
+               err = lo_ioctl(inode, file, cmd, arg);
+               break;
+       default:
+               err = -ENOIOCTLCMD;
+               break;
+       }
+       unlock_kernel();
+       return err;
+}
+#endif
+
 static int lo_open(struct inode *inode, struct file *file)
 {
        struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
@@ -1201,6 +1349,9 @@ static struct block_device_operations lo_fops = {
        .open =         lo_open,
        .release =      lo_release,
        .ioctl =        lo_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = lo_compat_ioctl,
+#endif
 };
 
 /*
@@ -1284,9 +1435,9 @@ static int __init loop_init(void)
                if (!lo->lo_queue)
                        goto out_mem4;
                mutex_init(&lo->lo_ctl_mutex);
-               init_completion(&lo->lo_done);
-               init_completion(&lo->lo_bh_done);
                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;
index bdbade9a5cf50a99e3b2e3fa3f860d71f36bfe82..9d1035e8d9d8c713148aa589abbf2c738022c197 100644 (file)
@@ -407,10 +407,10 @@ static void do_nbd_request(request_queue_t * q)
                struct nbd_device *lo;
 
                blkdev_dequeue_request(req);
-               dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
-                               req->rq_disk->disk_name, req, req->flags);
+               dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
+                               req->rq_disk->disk_name, req, req->cmd_type);
 
-               if (!(req->flags & REQ_CMD))
+               if (!blk_fs_request(req))
                        goto error_out;
 
                lo = req->rq_disk->private_data;
@@ -489,7 +489,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case NBD_DISCONNECT:
                printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
-               sreq.flags = REQ_SPECIAL;
+               sreq.cmd_type = REQ_TYPE_SPECIAL;
                nbd_cmd(&sreq) = NBD_CMD_DISC;
                /*
                 * Set these to sane values in case server implementation
index 2403721f9db107509cc4ff8b628795a70290597e..40a11e567970f30675f8b84590591146947d4e95 100644 (file)
@@ -437,7 +437,7 @@ static char *pd_buf;                /* buffer for request in progress */
 
 static enum action do_pd_io_start(void)
 {
-       if (pd_req->flags & REQ_SPECIAL) {
+       if (blk_special_request(pd_req)) {
                phase = pd_special;
                return pd_special();
        }
@@ -713,20 +713,18 @@ static void do_pd_request(request_queue_t * q)
 static int pd_special_command(struct pd_unit *disk,
                      enum action (*func)(struct pd_unit *disk))
 {
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
        struct request rq;
        int err = 0;
 
        memset(&rq, 0, sizeof(rq));
        rq.errors = 0;
-       rq.rq_status = RQ_ACTIVE;
        rq.rq_disk = disk->gd;
        rq.ref_count = 1;
-       rq.waiting = &wait;
+       rq.end_io_data = &wait;
        rq.end_io = blk_end_sync_rq;
        blk_insert_request(disk->gd->queue, &rq, 0, func);
        wait_for_completion(&wait);
-       rq.waiting = NULL;
        if (rq.errors)
                err = -EIO;
        blk_put_request(&rq);
index 451b996bba91e53bc934cc54048951015acc9868..a6b2aa67c9b264869b71720971b4566b171ec71f 100644 (file)
@@ -348,7 +348,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
        char sense[SCSI_SENSE_BUFFERSIZE];
        request_queue_t *q;
        struct request *rq;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
        int err = 0;
 
        q = bdev_get_queue(pd->bdev);
@@ -365,17 +365,17 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
        rq->sense = sense;
        memset(sense, 0, sizeof(sense));
        rq->sense_len = 0;
-       rq->flags |= REQ_BLOCK_PC | REQ_HARDBARRIER;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
+       rq->cmd_flags |= REQ_HARDBARRIER;
        if (cgc->quiet)
-               rq->flags |= REQ_QUIET;
+               rq->cmd_flags |= REQ_QUIET;
        memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
        if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
                memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
        rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
 
        rq->ref_count++;
-       rq->flags |= REQ_NOMERGE;
-       rq->waiting = &wait;
+       rq->end_io_data = &wait;
        rq->end_io = blk_end_sync_rq;
        elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
        generic_unplug_device(q);
index cc42e762396f28fccff473f32b9cc1c73ef862fb..f2305ee792a142b32d700473222ffe530742f31b 100644 (file)
@@ -319,8 +319,8 @@ static void start_request(struct floppy_state *fs)
                printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
                       req->rq_disk->disk_name, req->cmd,
                       (long)req->sector, req->nr_sectors, req->buffer);
-               printk("           rq_status=%d errors=%d current_nr_sectors=%ld\n",
-                      req->rq_status, req->errors, req->current_nr_sectors);
+               printk("           errors=%d current_nr_sectors=%ld\n",
+                      req->errors, req->current_nr_sectors);
 #endif
 
                if (req->sector < 0 || req->sector >= fs->total_secs) {
index 89e3c2f8b77681bacd376ba480732d4e84b97b9d..dfda796eba563df8fbfa53b476f7abc0f48d9372 100644 (file)
@@ -529,8 +529,8 @@ static void start_request(struct floppy_state *fs)
                printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
                       CURRENT->rq_disk->disk_name, CURRENT->cmd,
                       CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
-               printk("           rq_status=%d errors=%d current_nr_sectors=%ld\n",
-                      CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
+               printk("           errors=%d current_nr_sectors=%ld\n",
+                     CURRENT->errors, CURRENT->current_nr_sectors);
 #endif
 
                if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
index d62b49fbf10c319334ca6f26e49f58a46747b6f3..45a8f402b07bd6c214ce69a1a3b348c32127cda8 100644 (file)
@@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
 static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_scsi_cmd *cmd, struct ub_request *urq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_end_rq(struct request *rq, int uptodate);
+static void ub_end_rq(struct request *rq, unsigned int status);
 static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_request *urq, struct ub_scsi_cmd *cmd);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
        struct ub_request *urq;
        int n_elem;
 
-       if (atomic_read(&sc->poison) || lun->changed) {
+       if (atomic_read(&sc->poison)) {
+               blkdev_dequeue_request(rq);
+               ub_end_rq(rq, DID_NO_CONNECT << 16);
+               return 0;
+       }
+
+       if (lun->changed && !blk_pc_request(rq)) {
                blkdev_dequeue_request(rq);
-               ub_end_rq(rq, 0);
+               ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
                return 0;
        }
 
@@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
 
 drop:
        ub_put_cmd(lun, cmd);
-       ub_end_rq(rq, 0);
+       ub_end_rq(rq, DID_ERROR << 16);
        return 0;
 }
 
@@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        struct ub_lun *lun = cmd->lun;
        struct ub_request *urq = cmd->back;
        struct request *rq;
-       int uptodate;
+       unsigned int scsi_status;
 
        rq = urq->rq;
 
        if (cmd->error == 0) {
-               uptodate = 1;
-
                if (blk_pc_request(rq)) {
                        if (cmd->act_len >= rq->data_len)
                                rq->data_len = 0;
                        else
                                rq->data_len -= cmd->act_len;
                }
+               scsi_status = 0;
        } else {
-               uptodate = 0;
-
                if (blk_pc_request(rq)) {
                        /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
                        memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
                        rq->sense_len = UB_SENSE_SIZE;
                        if (sc->top_sense[0] != 0)
-                               rq->errors = SAM_STAT_CHECK_CONDITION;
+                               scsi_status = SAM_STAT_CHECK_CONDITION;
                        else
-                               rq->errors = DID_ERROR << 16;
+                               scsi_status = DID_ERROR << 16;
                } else {
                        if (cmd->error == -EIO) {
                                if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
                                        return;
                        }
+                       scsi_status = SAM_STAT_CHECK_CONDITION;
                }
        }
 
        urq->rq = NULL;
 
        ub_put_cmd(lun, cmd);
-       ub_end_rq(rq, uptodate);
+       ub_end_rq(rq, scsi_status);
        blk_start_queue(lun->disk->queue);
 }
 
-static void ub_end_rq(struct request *rq, int uptodate)
+static void ub_end_rq(struct request *rq, unsigned int scsi_status)
 {
+       int uptodate;
+
+       if (scsi_status == 0) {
+               uptodate = 1;
+       } else {
+               uptodate = 0;
+               rq->errors = scsi_status;
+       }
        end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
        end_that_request_last(rq, uptodate);
 }
index e828e4cbd3e1122a0ca3abb48e7ed2de51a6bf81..ebf3025721d148866aeb0f5be68fbd4e6fdfb7ea 100644 (file)
@@ -313,7 +313,7 @@ static void do_xd_request (request_queue_t * q)
                int res = 0;
                int retry;
 
-               if (!(req->flags & REQ_CMD)) {
+               if (!blk_fs_request(req)) {
                        end_request(req, 0);
                        continue;
                }
index 23f96213f4acad7e9c5f72b51e1e392e22a208c8..efcc28ec9d9a2a1b719fc8e5a5e87d527a71ab20 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  AVM BlueFRITZ! USB driver
  *
- *  Copyright (C) 2003  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2003-2006  Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -59,7 +59,6 @@ static struct usb_device_id bfusb_table[] = {
 
 MODULE_DEVICE_TABLE(usb, bfusb_table);
 
-
 #define BFUSB_MAX_BLOCK_SIZE   256
 
 #define BFUSB_BLOCK_TIMEOUT    3000
@@ -70,7 +69,7 @@ MODULE_DEVICE_TABLE(usb, bfusb_table);
 #define BFUSB_MAX_BULK_TX      2
 #define BFUSB_MAX_BULK_RX      2
 
-struct bfusb {
+struct bfusb_data {
        struct hci_dev          *hdev;
 
        unsigned long           state;
@@ -92,137 +91,136 @@ struct bfusb {
        struct sk_buff_head     completed_q;
 };
 
-struct bfusb_scb {
+struct bfusb_data_scb {
        struct urb *urb;
 };
 
 static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs);
 static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs);
 
-static struct urb *bfusb_get_completed(struct bfusb *bfusb)
+static struct urb *bfusb_get_completed(struct bfusb_data *data)
 {
        struct sk_buff *skb;
        struct urb *urb = NULL;
 
-       BT_DBG("bfusb %p", bfusb);
+       BT_DBG("bfusb %p", data);
 
-       skb = skb_dequeue(&bfusb->completed_q);
+       skb = skb_dequeue(&data->completed_q);
        if (skb) {
-               urb = ((struct bfusb_scb *) skb->cb)->urb;
+               urb = ((struct bfusb_data_scb *) skb->cb)->urb;
                kfree_skb(skb);
        }
 
        return urb;
 }
 
-static void bfusb_unlink_urbs(struct bfusb *bfusb)
+static void bfusb_unlink_urbs(struct bfusb_data *data)
 {
        struct sk_buff *skb;
        struct urb *urb;
 
-       BT_DBG("bfusb %p", bfusb);
+       BT_DBG("bfusb %p", data);
 
-       while ((skb = skb_dequeue(&bfusb->pending_q))) {
-               urb = ((struct bfusb_scb *) skb->cb)->urb;
+       while ((skb = skb_dequeue(&data->pending_q))) {
+               urb = ((struct bfusb_data_scb *) skb->cb)->urb;
                usb_kill_urb(urb);
-               skb_queue_tail(&bfusb->completed_q, skb);
+               skb_queue_tail(&data->completed_q, skb);
        }
 
-       while ((urb = bfusb_get_completed(bfusb)))
+       while ((urb = bfusb_get_completed(data)))
                usb_free_urb(urb);
 }
 
-
-static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb)
+static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
 {
-       struct bfusb_scb *scb = (void *) skb->cb;
-       struct urb *urb = bfusb_get_completed(bfusb);
+       struct bfusb_data_scb *scb = (void *) skb->cb;
+       struct urb *urb = bfusb_get_completed(data);
        int err, pipe;
 
-       BT_DBG("bfusb %p skb %p len %d", bfusb, skb, skb->len);
+       BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
 
        if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
                return -ENOMEM;
 
-       pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
+       pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
-       usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, skb->len,
+       usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len,
                        bfusb_tx_complete, skb);
 
        scb->urb = urb;
 
-       skb_queue_tail(&bfusb->pending_q, skb);
+       skb_queue_tail(&data->pending_q, skb);
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err) {
                BT_ERR("%s bulk tx submit failed urb %p err %d", 
-                                       bfusb->hdev->name, urb, err);
-               skb_unlink(skb, &bfusb->pending_q);
+                                       data->hdev->name, urb, err);
+               skb_unlink(skb, &data->pending_q);
                usb_free_urb(urb);
        } else
-               atomic_inc(&bfusb->pending_tx);
+               atomic_inc(&data->pending_tx);
 
        return err;
 }
 
-static void bfusb_tx_wakeup(struct bfusb *bfusb)
+static void bfusb_tx_wakeup(struct bfusb_data *data)
 {
        struct sk_buff *skb;
 
-       BT_DBG("bfusb %p", bfusb);
+       BT_DBG("bfusb %p", data);
 
-       if (test_and_set_bit(BFUSB_TX_PROCESS, &bfusb->state)) {
-               set_bit(BFUSB_TX_WAKEUP, &bfusb->state);
+       if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) {
+               set_bit(BFUSB_TX_WAKEUP, &data->state);
                return;
        }
 
        do {
-               clear_bit(BFUSB_TX_WAKEUP, &bfusb->state);
+               clear_bit(BFUSB_TX_WAKEUP, &data->state);
 
-               while ((atomic_read(&bfusb->pending_tx) < BFUSB_MAX_BULK_TX) &&
-                               (skb = skb_dequeue(&bfusb->transmit_q))) {
-                       if (bfusb_send_bulk(bfusb, skb) < 0) {
-                               skb_queue_head(&bfusb->transmit_q, skb);
+               while ((atomic_read(&data->pending_tx) < BFUSB_MAX_BULK_TX) &&
+                               (skb = skb_dequeue(&data->transmit_q))) {
+                       if (bfusb_send_bulk(data, skb) < 0) {
+                               skb_queue_head(&data->transmit_q, skb);
                                break;
                        }
                }
 
-       } while (test_bit(BFUSB_TX_WAKEUP, &bfusb->state));
+       } while (test_bit(BFUSB_TX_WAKEUP, &data->state));
 
-       clear_bit(BFUSB_TX_PROCESS, &bfusb->state);
+       clear_bit(BFUSB_TX_PROCESS, &data->state);
 }
 
 static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
 {
        struct sk_buff *skb = (struct sk_buff *) urb->context;
-       struct bfusb *bfusb = (struct bfusb *) skb->dev;
+       struct bfusb_data *data = (struct bfusb_data *) skb->dev;
 
-       BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
+       BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
 
-       atomic_dec(&bfusb->pending_tx);
+       atomic_dec(&data->pending_tx);
 
-       if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
+       if (!test_bit(HCI_RUNNING, &data->hdev->flags))
                return;
 
        if (!urb->status)
-               bfusb->hdev->stat.byte_tx += skb->len;
+               data->hdev->stat.byte_tx += skb->len;
        else
-               bfusb->hdev->stat.err_tx++;
+               data->hdev->stat.err_tx++;
 
-       read_lock(&bfusb->lock);
+       read_lock(&data->lock);
 
-       skb_unlink(skb, &bfusb->pending_q);
-       skb_queue_tail(&bfusb->completed_q, skb);
+       skb_unlink(skb, &data->pending_q);
+       skb_queue_tail(&data->completed_q, skb);
 
-       bfusb_tx_wakeup(bfusb);
+       bfusb_tx_wakeup(data);
 
-       read_unlock(&bfusb->lock);
+       read_unlock(&data->lock);
 }
 
 
-static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
+static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
 {
-       struct bfusb_scb *scb;
+       struct bfusb_data_scb *scb;
        struct sk_buff *skb;
        int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;
 
@@ -231,28 +229,29 @@ static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
        if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
                return -ENOMEM;
 
-       if (!(skb = bt_skb_alloc(size, GFP_ATOMIC))) {
+       skb = bt_skb_alloc(size, GFP_ATOMIC);
+       if (!skb) {
                usb_free_urb(urb);
                return -ENOMEM;
        }
 
-       skb->dev = (void *) bfusb;
+       skb->dev = (void *) data;
 
-       scb = (struct bfusb_scb *) skb->cb;
+       scb = (struct bfusb_data_scb *) skb->cb;
        scb->urb = urb;
 
-       pipe = usb_rcvbulkpipe(bfusb->udev, bfusb->bulk_in_ep);
+       pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep);
 
-       usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, size,
+       usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size,
                        bfusb_rx_complete, skb);
 
-       skb_queue_tail(&bfusb->pending_q, skb);
+       skb_queue_tail(&data->pending_q, skb);
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err) {
                BT_ERR("%s bulk rx submit failed urb %p err %d",
-                                       bfusb->hdev->name, urb, err);
-               skb_unlink(skb, &bfusb->pending_q);
+                                       data->hdev->name, urb, err);
+               skb_unlink(skb, &data->pending_q);
                kfree_skb(skb);
                usb_free_urb(urb);
        }
@@ -260,15 +259,15 @@ static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
        return err;
 }
 
-static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *data, int len)
+static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
 {
-       BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len);
+       BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);
 
        if (hdr & 0x10) {
-               BT_ERR("%s error in block", bfusb->hdev->name);
-               if (bfusb->reassembly)
-                       kfree_skb(bfusb->reassembly);
-               bfusb->reassembly = NULL;
+               BT_ERR("%s error in block", data->hdev->name);
+               if (data->reassembly)
+                       kfree_skb(data->reassembly);
+               data->reassembly = NULL;
                return -EIO;
        }
 
@@ -277,46 +276,46 @@ static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *
                unsigned char pkt_type;
                int pkt_len = 0;
 
-               if (bfusb->reassembly) {
-                       BT_ERR("%s unexpected start block", bfusb->hdev->name);
-                       kfree_skb(bfusb->reassembly);
-                       bfusb->reassembly = NULL;
+               if (data->reassembly) {
+                       BT_ERR("%s unexpected start block", data->hdev->name);
+                       kfree_skb(data->reassembly);
+                       data->reassembly = NULL;
                }
 
                if (len < 1) {
-                       BT_ERR("%s no packet type found", bfusb->hdev->name);
+                       BT_ERR("%s no packet type found", data->hdev->name);
                        return -EPROTO;
                }
 
-               pkt_type = *data++; len--;
+               pkt_type = *buf++; len--;
 
                switch (pkt_type) {
                case HCI_EVENT_PKT:
                        if (len >= HCI_EVENT_HDR_SIZE) {
-                               struct hci_event_hdr *hdr = (struct hci_event_hdr *) data;
+                               struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
                                pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
                        } else {
-                               BT_ERR("%s event block is too short", bfusb->hdev->name);
+                               BT_ERR("%s event block is too short", data->hdev->name);
                                return -EILSEQ;
                        }
                        break;
 
                case HCI_ACLDATA_PKT:
                        if (len >= HCI_ACL_HDR_SIZE) {
-                               struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) data;
+                               struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
                                pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
                        } else {
-                               BT_ERR("%s data block is too short", bfusb->hdev->name);
+                               BT_ERR("%s data block is too short", data->hdev->name);
                                return -EILSEQ;
                        }
                        break;
 
                case HCI_SCODATA_PKT:
                        if (len >= HCI_SCO_HDR_SIZE) {
-                               struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) data;
+                               struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
                                pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
                        } else {
-                               BT_ERR("%s audio block is too short", bfusb->hdev->name);
+                               BT_ERR("%s audio block is too short", data->hdev->name);
                                return -EILSEQ;
                        }
                        break;
@@ -324,27 +323,27 @@ static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *
 
                skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
                if (!skb) {
-                       BT_ERR("%s no memory for the packet", bfusb->hdev->name);
+                       BT_ERR("%s no memory for the packet", data->hdev->name);
                        return -ENOMEM;
                }
 
-               skb->dev = (void *) bfusb->hdev;
+               skb->dev = (void *) data->hdev;
                bt_cb(skb)->pkt_type = pkt_type;
 
-               bfusb->reassembly = skb;
+               data->reassembly = skb;
        } else {
-               if (!bfusb->reassembly) {
-                       BT_ERR("%s unexpected continuation block", bfusb->hdev->name);
+               if (!data->reassembly) {
+                       BT_ERR("%s unexpected continuation block", data->hdev->name);
                        return -EIO;
                }
        }
 
        if (len > 0)
-               memcpy(skb_put(bfusb->reassembly, len), data, len);
+               memcpy(skb_put(data->reassembly, len), buf, len);
 
        if (hdr & 0x08) {
-               hci_recv_frame(bfusb->reassembly);
-               bfusb->reassembly = NULL;
+               hci_recv_frame(data->reassembly);
+               data->reassembly = NULL;
        }
 
        return 0;
@@ -353,22 +352,22 @@ static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *
 static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
 {
        struct sk_buff *skb = (struct sk_buff *) urb->context;
-       struct bfusb *bfusb = (struct bfusb *) skb->dev;
+       struct bfusb_data *data = (struct bfusb_data *) skb->dev;
        unsigned char *buf = urb->transfer_buffer;
        int count = urb->actual_length;
        int err, hdr, len;
 
        BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
 
-       read_lock(&bfusb->lock);
+       read_lock(&data->lock);
 
-       if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
+       if (!test_bit(HCI_RUNNING, &data->hdev->flags))
                goto unlock;
 
        if (urb->status || !count)
                goto resubmit;
 
-       bfusb->hdev->stat.byte_rx += count;
+       data->hdev->stat.byte_rx += count;
 
        skb_put(skb, count);
 
@@ -387,90 +386,89 @@ static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
 
                if (count < len) {
                        BT_ERR("%s block extends over URB buffer ranges",
-                                       bfusb->hdev->name);
+                                       data->hdev->name);
                }
 
                if ((hdr & 0xe1) == 0xc1)
-                       bfusb_recv_block(bfusb, hdr, buf, len);
+                       bfusb_recv_block(data, hdr, buf, len);
 
                count -= len;
                buf   += len;
        }
 
-       skb_unlink(skb, &bfusb->pending_q);
+       skb_unlink(skb, &data->pending_q);
        kfree_skb(skb);
 
-       bfusb_rx_submit(bfusb, urb);
+       bfusb_rx_submit(data, urb);
 
-       read_unlock(&bfusb->lock);
+       read_unlock(&data->lock);
 
        return;
 
 resubmit:
-       urb->dev = bfusb->udev;
+       urb->dev = data->udev;
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err) {
                BT_ERR("%s bulk resubmit failed urb %p err %d",
-                                       bfusb->hdev->name, urb, err);
+                                       data->hdev->name, urb, err);
        }
 
 unlock:
-       read_unlock(&bfusb->lock);
+       read_unlock(&data->lock);
 }
 
-
 static int bfusb_open(struct hci_dev *hdev)
 {
-       struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+       struct bfusb_data *data = hdev->driver_data;
        unsigned long flags;
        int i, err;
 
-       BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+       BT_DBG("hdev %p bfusb %p", hdev, data);
 
        if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
                return 0;
 
-       write_lock_irqsave(&bfusb->lock, flags);
+       write_lock_irqsave(&data->lock, flags);
 
-       err = bfusb_rx_submit(bfusb, NULL);
+       err = bfusb_rx_submit(data, NULL);
        if (!err) {
                for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
-                       bfusb_rx_submit(bfusb, NULL);
+                       bfusb_rx_submit(data, NULL);
        } else {
                clear_bit(HCI_RUNNING, &hdev->flags);
        }
 
-       write_unlock_irqrestore(&bfusb->lock, flags);
+       write_unlock_irqrestore(&data->lock, flags);
 
        return err;
 }
 
 static int bfusb_flush(struct hci_dev *hdev)
 {
-       struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+       struct bfusb_data *data = hdev->driver_data;
 
-       BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+       BT_DBG("hdev %p bfusb %p", hdev, data);
 
-       skb_queue_purge(&bfusb->transmit_q);
+       skb_queue_purge(&data->transmit_q);
 
        return 0;
 }
 
 static int bfusb_close(struct hci_dev *hdev)
 {
-       struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+       struct bfusb_data *data = hdev->driver_data;
        unsigned long flags;
 
-       BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+       BT_DBG("hdev %p bfusb %p", hdev, data);
 
        if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
                return 0;
 
-       write_lock_irqsave(&bfusb->lock, flags);
-       write_unlock_irqrestore(&bfusb->lock, flags);
+       write_lock_irqsave(&data->lock, flags);
+       write_unlock_irqrestore(&data->lock, flags);
 
-       bfusb_unlink_urbs(bfusb);
+       bfusb_unlink_urbs(data);
        bfusb_flush(hdev);
 
        return 0;
@@ -479,7 +477,7 @@ static int bfusb_close(struct hci_dev *hdev)
 static int bfusb_send_frame(struct sk_buff *skb)
 {
        struct hci_dev *hdev = (struct hci_dev *) skb->dev;
-       struct bfusb *bfusb;
+       struct bfusb_data *data;
        struct sk_buff *nskb;
        unsigned char buf[3];
        int sent = 0, size, count;
@@ -494,7 +492,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                return -EBUSY;
 
-       bfusb = (struct bfusb *) hdev->driver_data;
+       data = hdev->driver_data;
 
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
@@ -514,12 +512,13 @@ static int bfusb_send_frame(struct sk_buff *skb)
        count = skb->len;
 
        /* Max HCI frame size seems to be 1511 + 1 */
-       if (!(nskb = bt_skb_alloc(count + 32, GFP_ATOMIC))) {
+       nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
+       if (!nskb) {
                BT_ERR("Can't allocate memory for new packet");
                return -ENOMEM;
        }
 
-       nskb->dev = (void *) bfusb;
+       nskb->dev = (void *) data;
 
        while (count) {
                size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE);
@@ -536,18 +535,18 @@ static int bfusb_send_frame(struct sk_buff *skb)
        }
 
        /* Don't send frame with multiple size of bulk max packet */
-       if ((nskb->len % bfusb->bulk_pkt_size) == 0) {
+       if ((nskb->len % data->bulk_pkt_size) == 0) {
                buf[0] = 0xdd;
                buf[1] = 0x00;
                memcpy(skb_put(nskb, 2), buf, 2);
        }
 
-       read_lock(&bfusb->lock);
+       read_lock(&data->lock);
 
-       skb_queue_tail(&bfusb->transmit_q, nskb);
-       bfusb_tx_wakeup(bfusb);
+       skb_queue_tail(&data->transmit_q, nskb);
+       bfusb_tx_wakeup(data);
 
-       read_unlock(&bfusb->lock);
+       read_unlock(&data->lock);
 
        kfree_skb(skb);
 
@@ -556,11 +555,11 @@ static int bfusb_send_frame(struct sk_buff *skb)
 
 static void bfusb_destruct(struct hci_dev *hdev)
 {
-       struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+       struct bfusb_data *data = hdev->driver_data;
 
-       BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+       BT_DBG("hdev %p bfusb %p", hdev, data);
 
-       kfree(bfusb);
+       kfree(data);
 }
 
 static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
@@ -568,25 +567,24 @@ static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg
        return -ENOIOCTLCMD;
 }
 
-
-static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count)
+static int bfusb_load_firmware(struct bfusb_data *data, unsigned char *firmware, int count)
 {
        unsigned char *buf;
        int err, pipe, len, size, sent = 0;
 
-       BT_DBG("bfusb %p udev %p", bfusb, bfusb->udev);
+       BT_DBG("bfusb %p udev %p", data, data->udev);
 
        BT_INFO("BlueFRITZ! USB loading firmware");
 
-       pipe = usb_sndctrlpipe(bfusb->udev, 0);
+       pipe = usb_sndctrlpipe(data->udev, 0);
 
-       if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+       if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
                                0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
                BT_ERR("Can't change to loading configuration");
                return -EBUSY;
        }
 
-       bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
+       data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
        buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
        if (!buf) {
@@ -594,14 +592,14 @@ static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int
                return -ENOMEM;
        }
 
-       pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
+       pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
 
        while (count) {
                size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3);
 
                memcpy(buf, firmware + sent, size);
 
-               err = usb_bulk_msg(bfusb->udev, pipe, buf, size,
+               err = usb_bulk_msg(data->udev, pipe, buf, size,
                                        &len, BFUSB_BLOCK_TIMEOUT);
 
                if (err || (len != size)) {
@@ -613,21 +611,23 @@ static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int
                count -= size;
        }
 
-       if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0,
-                               &len, BFUSB_BLOCK_TIMEOUT)) < 0) {
+       err = usb_bulk_msg(data->udev, pipe, NULL, 0,
+                                       &len, BFUSB_BLOCK_TIMEOUT);
+       if (err < 0) {
                BT_ERR("Error in null packet request");
                goto error;
        }
 
-       pipe = usb_sndctrlpipe(bfusb->udev, 0);
+       pipe = usb_sndctrlpipe(data->udev, 0);
 
-        if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
-                               0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+       err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
+                               0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+       if (err < 0) {
                BT_ERR("Can't change to running configuration");
                goto error;
        }
 
-       bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
+       data->udev->toggle[0] = data->udev->toggle[1] = 0;
 
        BT_INFO("BlueFRITZ! USB device ready");
 
@@ -637,9 +637,9 @@ static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int
 error:
        kfree(buf);
 
-       pipe = usb_sndctrlpipe(bfusb->udev, 0);
+       pipe = usb_sndctrlpipe(data->udev, 0);
 
-       usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+       usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
                                0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 
        return err;
@@ -652,7 +652,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct usb_host_endpoint *bulk_out_ep;
        struct usb_host_endpoint *bulk_in_ep;
        struct hci_dev *hdev;
-       struct bfusb *bfusb;
+       struct bfusb_data *data;
 
        BT_DBG("intf %p id %p", intf, id);
 
@@ -672,23 +672,24 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
        }
 
        /* Initialize control structure and load firmware */
-       if (!(bfusb = kzalloc(sizeof(struct bfusb), GFP_KERNEL))) {
+       data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
+       if (!data) {
                BT_ERR("Can't allocate memory for control structure");
                goto done;
        }
 
-       bfusb->udev = udev;
-       bfusb->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
-       bfusb->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
-       bfusb->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
+       data->udev = udev;
+       data->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
+       data->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
+       data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
 
-       rwlock_init(&bfusb->lock);
+       rwlock_init(&data->lock);
 
-       bfusb->reassembly = NULL;
+       data->reassembly = NULL;
 
-       skb_queue_head_init(&bfusb->transmit_q);
-       skb_queue_head_init(&bfusb->pending_q);
-       skb_queue_head_init(&bfusb->completed_q);
+       skb_queue_head_init(&data->transmit_q);
+       skb_queue_head_init(&data->pending_q);
+       skb_queue_head_init(&data->completed_q);
 
        if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
                BT_ERR("Firmware request failed");
@@ -697,7 +698,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
 
-       if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) {
+       if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
                BT_ERR("Firmware loading failed");
                goto release;
        }
@@ -711,10 +712,10 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
                goto error;
        }
 
-       bfusb->hdev = hdev;
+       data->hdev = hdev;
 
        hdev->type = HCI_USB;
-       hdev->driver_data = bfusb;
+       hdev->driver_data = data;
        SET_HCIDEV_DEV(hdev, &intf->dev);
 
        hdev->open     = bfusb_open;
@@ -732,7 +733,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
                goto error;
        }
 
-       usb_set_intfdata(intf, bfusb);
+       usb_set_intfdata(intf, data);
 
        return 0;
 
@@ -740,7 +741,7 @@ release:
        release_firmware(firmware);
 
 error:
-       kfree(bfusb);
+       kfree(data);
 
 done:
        return -EIO;
@@ -748,8 +749,8 @@ done:
 
 static void bfusb_disconnect(struct usb_interface *intf)
 {
-       struct bfusb *bfusb = usb_get_intfdata(intf);
-       struct hci_dev *hdev = bfusb->hdev;
+       struct bfusb_data *data = usb_get_intfdata(intf);
+       struct hci_dev *hdev = data->hdev;
 
        BT_DBG("intf %p", intf);
 
@@ -779,7 +780,8 @@ static int __init bfusb_init(void)
 
        BT_INFO("BlueFRITZ! USB driver ver %s", VERSION);
 
-       if ((err = usb_register(&bfusb_driver)) < 0)
+       err = usb_register(&bfusb_driver);
+       if (err < 0)
                BT_ERR("Failed to register BlueFRITZ! USB driver");
 
        return err;
index 93ba25b7ea328303fad462372ddb575e69ea207e..420b645c4c9f0d20db0e5790e44a3c854890f6c8 100644 (file)
@@ -241,15 +241,11 @@ static int hci_uart_send_frame(struct sk_buff *skb)
 
 static void hci_uart_destruct(struct hci_dev *hdev)
 {
-       struct hci_uart *hu;
-
        if (!hdev)
                return;
 
        BT_DBG("%s", hdev->name);
-
-       hu = (struct hci_uart *) hdev->driver_data;
-       kfree(hu);
+       kfree(hdev->driver_data);
 }
 
 /* ------ LDISC part ------ */
@@ -272,7 +268,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
                return -EEXIST;
 
        if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
-               BT_ERR("Can't allocate controll structure");
+               BT_ERR("Can't allocate control structure");
                return -ENFILE;
        }
 
@@ -360,7 +356,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
  *     
  * Return Value:    None
  */
-static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
+static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
 {
        struct hci_uart *hu = (void *)tty->disc_data;
 
@@ -375,7 +371,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char
        hu->hdev->stat.byte_rx += count;
        spin_unlock(&hu->rx_lock);
 
-       if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle)
+       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+                                       tty->driver->unthrottle)
                tty->driver->unthrottle(tty);
 }
 
index e2d4beac74207c711bdafaf11399d0170d73d07b..0801af4ad2b9cab68ca22db8206e98031a090fb6 100644 (file)
@@ -96,6 +96,9 @@ static struct usb_device_id bluetooth_ids[] = {
        /* Ericsson with non-standard id */
        { USB_DEVICE(0x0bdb, 0x1002) },
 
+       /* Canyon CN-BTU1 with HID interfaces */
+       { USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
+
        { }     /* Terminating entry */
 };
 
index aac67a3a6019958a5ad77347aa0dcc11c6609c99..a278d98a915126a2dac78c6d1865fc11d89181cf 100644 (file)
@@ -2,9 +2,9 @@
  *
  *  Bluetooth virtual HCI driver
  *
- *  Copyright (C) 2000-2001 Qualcomm Incorporated
- *  Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
- *  Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-200 Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -72,21 +72,21 @@ static int vhci_open_dev(struct hci_dev *hdev)
 
 static int vhci_close_dev(struct hci_dev *hdev)
 {
-       struct vhci_data *vhci = hdev->driver_data;
+       struct vhci_data *data = hdev->driver_data;
 
        if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
                return 0;
 
-       skb_queue_purge(&vhci->readq);
+       skb_queue_purge(&data->readq);
 
        return 0;
 }
 
 static int vhci_flush(struct hci_dev *hdev)
 {
-       struct vhci_data *vhci = hdev->driver_data;
+       struct vhci_data *data = hdev->driver_data;
 
-       skb_queue_purge(&vhci->readq);
+       skb_queue_purge(&data->readq);
 
        return 0;
 }
@@ -94,7 +94,7 @@ static int vhci_flush(struct hci_dev *hdev)
 static int vhci_send_frame(struct sk_buff *skb)
 {
        struct hci_dev* hdev = (struct hci_dev *) skb->dev;
-       struct vhci_data *vhci;
+       struct vhci_data *data;
 
        if (!hdev) {
                BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -104,15 +104,15 @@ static int vhci_send_frame(struct sk_buff *skb)
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                return -EBUSY;
 
-       vhci = hdev->driver_data;
+       data = hdev->driver_data;
 
        memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
-       skb_queue_tail(&vhci->readq, skb);
+       skb_queue_tail(&data->readq, skb);
 
-       if (vhci->flags & VHCI_FASYNC)
-               kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
+       if (data->flags & VHCI_FASYNC)
+               kill_fasync(&data->fasync, SIGIO, POLL_IN);
 
-       wake_up_interruptible(&vhci->read_wait);
+       wake_up_interruptible(&data->read_wait);
 
        return 0;
 }
@@ -122,7 +122,7 @@ static void vhci_destruct(struct hci_dev *hdev)
        kfree(hdev->driver_data);
 }
 
-static inline ssize_t vhci_get_user(struct vhci_data *vhci,
+static inline ssize_t vhci_get_user(struct vhci_data *data,
                                        const char __user *buf, size_t count)
 {
        struct sk_buff *skb;
@@ -139,7 +139,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *vhci,
                return -EFAULT;
        }
 
-       skb->dev = (void *) vhci->hdev;
+       skb->dev = (void *) data->hdev;
        bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
        skb_pull(skb, 1);
 
@@ -148,7 +148,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *vhci,
        return count;
 }
 
-static inline ssize_t vhci_put_user(struct vhci_data *vhci,
+static inline ssize_t vhci_put_user(struct vhci_data *data,
                        struct sk_buff *skb, char __user *buf, int count)
 {
        char __user *ptr = buf;
@@ -161,42 +161,43 @@ static inline ssize_t vhci_put_user(struct vhci_data *vhci,
 
        total += len;
 
-       vhci->hdev->stat.byte_tx += len;
+       data->hdev->stat.byte_tx += len;
 
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
-               vhci->hdev->stat.cmd_tx++;
+               data->hdev->stat.cmd_tx++;
                break;
 
        case HCI_ACLDATA_PKT:
-               vhci->hdev->stat.acl_tx++;
+               data->hdev->stat.acl_tx++;
                break;
 
        case HCI_SCODATA_PKT:
-               vhci->hdev->stat.cmd_tx++;
+               data->hdev->stat.cmd_tx++;
                break;
        };
 
        return total;
 }
 
-static loff_t vhci_llseek(struct file * file, loff_t offset, int origin)
+static loff_t vhci_llseek(struct file *file, loff_t offset, int origin)
 {
        return -ESPIPE;
 }
 
-static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
+static ssize_t vhci_read(struct file *file,
+                               char __user *buf, size_t count, loff_t *pos)
 {
        DECLARE_WAITQUEUE(wait, current);
-       struct vhci_data *vhci = file->private_data;
+       struct vhci_data *data = file->private_data;
        struct sk_buff *skb;
        ssize_t ret = 0;
 
-       add_wait_queue(&vhci->read_wait, &wait);
+       add_wait_queue(&data->read_wait, &wait);
        while (count) {
                set_current_state(TASK_INTERRUPTIBLE);
 
-               skb = skb_dequeue(&vhci->readq);
+               skb = skb_dequeue(&data->readq);
                if (!skb) {
                        if (file->f_flags & O_NONBLOCK) {
                                ret = -EAGAIN;
@@ -213,7 +214,7 @@ static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, lo
                }
 
                if (access_ok(VERIFY_WRITE, buf, count))
-                       ret = vhci_put_user(vhci, skb, buf, count);
+                       ret = vhci_put_user(data, skb, buf, count);
                else
                        ret = -EFAULT;
 
@@ -221,7 +222,7 @@ static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, lo
                break;
        }
        set_current_state(TASK_RUNNING);
-       remove_wait_queue(&vhci->read_wait, &wait);
+       remove_wait_queue(&data->read_wait, &wait);
 
        return ret;
 }
@@ -229,21 +230,21 @@ static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, lo
 static ssize_t vhci_write(struct file *file,
                        const char __user *buf, size_t count, loff_t *pos)
 {
-       struct vhci_data *vhci = file->private_data;
+       struct vhci_data *data = file->private_data;
 
        if (!access_ok(VERIFY_READ, buf, count))
                return -EFAULT;
 
-       return vhci_get_user(vhci, buf, count);
+       return vhci_get_user(data, buf, count);
 }
 
 static unsigned int vhci_poll(struct file *file, poll_table *wait)
 {
-       struct vhci_data *vhci = file->private_data;
+       struct vhci_data *data = file->private_data;
 
-       poll_wait(file, &vhci->read_wait, wait);
+       poll_wait(file, &data->read_wait, wait);
 
-       if (!skb_queue_empty(&vhci->readq))
+       if (!skb_queue_empty(&data->readq))
                return POLLIN | POLLRDNORM;
 
        return POLLOUT | POLLWRNORM;
@@ -257,26 +258,26 @@ static int vhci_ioctl(struct inode *inode, struct file *file,
 
 static int vhci_open(struct inode *inode, struct file *file)
 {
-       struct vhci_data *vhci;
+       struct vhci_data *data;
        struct hci_dev *hdev;
 
-       vhci = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
-       if (!vhci)
+       data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
+       if (!data)
                return -ENOMEM;
 
-       skb_queue_head_init(&vhci->readq);
-       init_waitqueue_head(&vhci->read_wait);
+       skb_queue_head_init(&data->readq);
+       init_waitqueue_head(&data->read_wait);
 
        hdev = hci_alloc_dev();
        if (!hdev) {
-               kfree(vhci);
+               kfree(data);
                return -ENOMEM;
        }
 
-       vhci->hdev = hdev;
+       data->hdev = hdev;
 
-       hdev->type = HCI_VHCI;
-       hdev->driver_data = vhci;
+       hdev->type = HCI_VIRTUAL;
+       hdev->driver_data = data;
 
        hdev->open     = vhci_open_dev;
        hdev->close    = vhci_close_dev;
@@ -288,20 +289,20 @@ static int vhci_open(struct inode *inode, struct file *file)
 
        if (hci_register_dev(hdev) < 0) {
                BT_ERR("Can't register HCI device");
-               kfree(vhci);
+               kfree(data);
                hci_free_dev(hdev);
                return -EBUSY;
        }
 
-       file->private_data = vhci;
+       file->private_data = data;
 
        return nonseekable_open(inode, file);
 }
 
 static int vhci_release(struct inode *inode, struct file *file)
 {
-       struct vhci_data *vhci = file->private_data;
-       struct hci_dev *hdev = vhci->hdev;
+       struct vhci_data *data = file->private_data;
+       struct hci_dev *hdev = data->hdev;
 
        if (hci_unregister_dev(hdev) < 0) {
                BT_ERR("Can't unregister HCI device %s", hdev->name);
@@ -316,17 +317,17 @@ static int vhci_release(struct inode *inode, struct file *file)
 
 static int vhci_fasync(int fd, struct file *file, int on)
 {
-       struct vhci_data *vhci = file->private_data;
+       struct vhci_data *data = file->private_data;
        int err;
 
-       err = fasync_helper(fd, file, on, &vhci->fasync);
+       err = fasync_helper(fd, file, on, &data->fasync);
        if (err < 0)
                return err;
 
        if (on)
-               vhci->flags |= VHCI_FASYNC;
+               data->flags |= VHCI_FASYNC;
        else
-               vhci->flags &= ~VHCI_FASYNC;
+               data->flags &= ~VHCI_FASYNC;
 
        return 0;
 }
index ff5652d40619e018a83a29b7bed703531e37e85f..4b12e9031fb3cecbf6259c457aa77c8a394a3674 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menu "Old CD-ROM drivers (not SCSI, not IDE)"
-       depends on ISA
+       depends on ISA && BLOCK
 
 config CD_NO_IDESCSI
        bool "Support non-SCSI/IDE/ATAPI CDROM drives"
index d239cf8b20bd1e769a84612959e55eccfe8e1510..b38c84a7a8e3e30e7d8080fafa209562d7e7f673 100644 (file)
@@ -2129,7 +2129,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                rq->cmd[9] = 0xf8;
 
                rq->cmd_len = 12;
-               rq->flags |= REQ_BLOCK_PC;
+               rq->cmd_type = REQ_TYPE_BLOCK_PC;
                rq->timeout = 60 * HZ;
                bio = rq->bio;
 
index 37bdb0163f0d1b47acf2df88392b318de984480a..ccd91c1a84bd10d2e0c2ca42a7cbd161f93146af 100644 (file)
@@ -1338,8 +1338,10 @@ static void do_cdu31a_request(request_queue_t * q)
                }
 
                /* WTF??? */
-               if (!(req->flags & REQ_CMD))
+               if (!blk_fs_request(req)) {
+                       end_request(req, 0);
                        continue;
+               }
                if (rq_data_dir(req) == WRITE) {
                        end_request(req, 0);
                        continue;
index 52ea94b891f59cedb6a8d50794240d43c37598d6..bde1c665d9f4b1cf6e70cfa9ba32ec7bd765d3cc 100644 (file)
@@ -439,6 +439,14 @@ config SGI_MBCS
          If you have an SGI Altix with an attached SABrick
          say Y or M here, otherwise say N.
 
+config MSPEC
+       tristate "Memory special operations driver"
+       depends on IA64
+       help
+         If you have an ia64 and you want to enable memory special
+         operations support (formerly known as fetchop), say Y here,
+         otherwise say N.
+
 source "drivers/serial/Kconfig"
 
 config UNIX98_PTYS
@@ -739,7 +747,7 @@ config NVRAM
 
 config RTC
        tristate "Enhanced Real Time Clock Support"
-       depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM
+       depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH
        ---help---
          If you say Y here and create a character special file /dev/rtc with
          major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -823,14 +831,6 @@ config DS1302
          will get access to the real time clock (or hardware clock) built
          into your computer.
 
-config S3C2410_RTC
-       bool "S3C2410 RTC Driver"
-       depends on ARCH_S3C2410
-       help
-         RTC (Realtime Clock) driver for the clock inbuilt into the
-         Samsung S3C2410. This can provide periodic interrupt rates
-         from 1Hz to 64Hz for user programs, and wakeup from Alarm.
-
 config COBALT_LCD
        bool "Support for Cobalt LCD"
        depends on MIPS_COBALT
@@ -1006,6 +1006,7 @@ config GPIO_VR41XX
 
 config RAW_DRIVER
        tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+       depends on BLOCK
        help
          The raw driver permits block devices to be bound to /dev/raw/rawN. 
          Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 
index 8c6dfc6215201d238ab629847a7fd173bb543536..19114df59bbdf72e973812808f66caaa65ca4df2 100644 (file)
@@ -47,6 +47,7 @@ obj-$(CONFIG_HVC_RTAS)                += hvc_rtas.o
 obj-$(CONFIG_HVC_DRIVER)       += hvc_console.o
 obj-$(CONFIG_RAW_DRIVER)       += raw.o
 obj-$(CONFIG_SGI_SNSC)         += snsc.o snsc_event.o
+obj-$(CONFIG_MSPEC)            += mspec.o
 obj-$(CONFIG_MMTIMER)          += mmtimer.o
 obj-$(CONFIG_VIOCONS)          += viocons.o
 obj-$(CONFIG_VIOTAPE)          += viotape.o
@@ -68,7 +69,6 @@ obj-$(CONFIG_EFI_RTC)         += efirtc.o
 obj-$(CONFIG_SGI_DS1286)       += ds1286.o
 obj-$(CONFIG_SGI_IP27_RTC)     += ip27-rtc.o
 obj-$(CONFIG_DS1302)           += ds1302.o
-obj-$(CONFIG_S3C2410_RTC)      += s3c2410-rtc.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM)  += generic_nvram.o
 else
index 5278c388d3e747dbc40251c70985e25ef5d4eceb..ef833a1c27eb1c60a49eca9566f8d987add2d262 100644 (file)
@@ -60,7 +60,9 @@ config DRM_I830
          Choose this option if you have a system that has Intel 830M, 845G,
          852GM, 855GM or 865G integrated graphics.  If M is selected, the
          module will be called i830.  AGP support is required for this driver
-         to work. This driver will eventually be replaced by the i915 one.
+         to work. This driver is used by the older X releases X.org 6.7 and
+         XFree86 4.3. If unsure, build this and i915 as modules and the X server
+         will load the correct one.
 
 config DRM_I915
        tristate "i915 driver"
@@ -68,8 +70,9 @@ config DRM_I915
          Choose this option if you have a system that has Intel 830M, 845G,
          852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
          module will be called i915.  AGP support is required for this driver
-         to work. This driver will eventually replace the I830 driver, when
-         later release of X start to use the new DDX and DRI.
+         to work. This driver is used by the Intel driver in X.org 6.8 and
+         XFree86 4.4 and above. If unsure, build this and i830 as modules and 
+         the X server will load the correct one.
        
 endchoice
 
index 9d180c42816cb592c4c83b7331d2977116cf263d..3ad0f648c6b22340e79f0f12068f5661808a3c43 100644 (file)
@@ -6,7 +6,7 @@ drm-objs    :=  drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
                drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
                drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
                drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
-               drm_sysfs.o
+               drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
 
 tdfx-objs   := tdfx_drv.o
 r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
@@ -16,9 +16,9 @@ i830-objs   := i830_drv.o i830_dma.o i830_irq.o
 i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
 ffb-objs    := ffb_drv.o ffb_context.o
-sis-objs    := sis_drv.o sis_ds.o sis_mm.o
+sis-objs    := sis_drv.o sis_mm.o
 savage-objs := savage_drv.o savage_bci.o savage_state.o
-via-objs    := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
+via-objs    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
 
 ifeq ($(CONFIG_COMPAT),y)
 drm-objs    += drm_ioc32.o
index d2a56182bc35786a08c681abb273fea450e3abdd..7690a59ace0426b0249127831b3d668bab2bb444 100644 (file)
@@ -79,6 +79,7 @@
 #define __OS_HAS_MTRR (defined(CONFIG_MTRR))
 
 #include "drm_os_linux.h"
+#include "drm_hashtab.h"
 
 /***********************************************************************/
 /** \name DRM template customization defaults */
 #define DRM_DEBUG_CODE 2         /**< Include debugging code if > 1, then
                                     also include looping detection. */
 
-#define DRM_HASH_SIZE        16 /**< Size of key hash table. Must be power of 2. */
+#define DRM_MAGIC_HASH_ORDER  4  /**< Size of key hash table. Must be power of 2. */
 #define DRM_KERNEL_CONTEXT    0         /**< Change drm_resctx if changed */
 #define DRM_RESERVED_CONTEXTS 1         /**< Change drm_resctx if changed */
 #define DRM_LOOPING_LIMIT     5000000
 #define DRM_MEM_CTXBITMAP 18
 #define DRM_MEM_STUB      19
 #define DRM_MEM_SGLISTS   20
-#define DRM_MEM_CTXLIST  21
+#define DRM_MEM_CTXLIST   21
+#define DRM_MEM_MM        22
+#define DRM_MEM_HASHTAB   23
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
-
-/*@}*/
-
-/***********************************************************************/
-/** \name Backward compatibility section */
-/*@{*/
-
-#define DRM_RPR_ARG(vma) vma,
-
-#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
+#define DRM_MAP_HASH_OFFSET 0x10000000
 
 /*@}*/
 
 /*@{*/
 
 #define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
-#define DRM_MIN(a,b) min(a,b)
-#define DRM_MAX(a,b) max(a,b)
 
 #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
 #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
@@ -286,7 +278,8 @@ typedef struct drm_devstate {
 } drm_devstate_t;
 
 typedef struct drm_magic_entry {
-       drm_magic_t magic;
+       drm_hash_item_t hash_item;
+       struct list_head head;
        struct drm_file *priv;
        struct drm_magic_entry *next;
 } drm_magic_entry_t;
@@ -493,6 +486,7 @@ typedef struct drm_sigdata {
  */
 typedef struct drm_map_list {
        struct list_head head;          /**< list head */
+       drm_hash_item_t hash;
        drm_map_t *map;                 /**< mapping */
        unsigned int user_token;
 } drm_map_list_t;
@@ -527,6 +521,22 @@ typedef struct ati_pcigart_info {
        drm_local_map_t mapping;
 } drm_ati_pcigart_info;
 
+/*
+ * Generic memory manager structs
+ */
+typedef struct drm_mm_node {
+       struct list_head fl_entry;
+       struct list_head ml_entry;
+       int free;
+       unsigned long start;
+       unsigned long size;
+       void *private;
+} drm_mm_node_t;
+
+typedef struct drm_mm {
+       drm_mm_node_t root_node;
+} drm_mm_t;
+
 /**
  * DRM driver structure. This structure represent the common code for
  * a family of cards. There will one drm_device for each card present
@@ -646,13 +656,15 @@ typedef struct drm_device {
        /*@{ */
        drm_file_t *file_first;         /**< file list head */
        drm_file_t *file_last;          /**< file list tail */
-       drm_magic_head_t magiclist[DRM_HASH_SIZE];      /**< magic hash table */
+       drm_open_hash_t magiclist;      /**< magic hash table */
+       struct list_head magicfree;
        /*@} */
 
        /** \name Memory management */
        /*@{ */
        drm_map_list_t *maplist;        /**< Linked list of regions */
        int map_count;                  /**< Number of mappable regions */
+       drm_open_hash_t map_hash;       /**< User token hash table for maps */
 
        /** \name Context handle management */
        /*@{ */
@@ -711,10 +723,8 @@ typedef struct drm_device {
        drm_agp_head_t *agp;    /**< AGP data */
 
        struct pci_dev *pdev;           /**< PCI device structure */
-       int pci_domain;                 /**< PCI bus domain number */
-       int pci_bus;                    /**< PCI bus number */
-       int pci_slot;                   /**< PCI slot number */
-       int pci_func;                   /**< PCI function number */
+       int pci_vendor;                 /**< PCI vendor id */
+       int pci_device;                 /**< PCI device id */
 #ifdef __alpha__
        struct pci_controller *hose;
 #endif
@@ -736,6 +746,12 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,
        return ((dev->driver->driver_features & feature) ? 1 : 0);
 }
 
+#ifdef __alpha__
+#define drm_get_pci_domain(dev) dev->hose->bus->number
+#else
+#define drm_get_pci_domain(dev) 0
+#endif
+
 #if __OS_HAS_AGP
 static inline int drm_core_has_AGP(struct drm_device *dev)
 {
@@ -1011,6 +1027,18 @@ extern struct class_device *drm_sysfs_device_add(struct class *cs,
                                                 drm_head_t *head);
 extern void drm_sysfs_device_remove(struct class_device *class_dev);
 
+/*
+ * Basic memory manager support (drm_mm.c)
+ */
+extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+                                      unsigned long size,
+                                      unsigned alignment);
+extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur);
+extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
+                                        unsigned alignment, int best_match);
+extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
+extern void drm_mm_takedown(drm_mm_t *mm);
+
 /* Inline replacements for DRM_IOREMAP macros */
 static __inline__ void drm_core_ioremap(struct drm_map *map,
                                        struct drm_device *dev)
index 2a37586a7ee8d4e7ca856723f27be808e6649005..c7b19d35bcd6fc059c4c41d6925221f0bc78eb0a 100644 (file)
 
 #include "drmP.h"
 
-/**
- * Generate a hash key from a magic.
- *
- * \param magic magic.
- * \return hash key.
- *
- * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
- * a power of 2.
- */
-static int drm_hash_magic(drm_magic_t magic)
-{
-       return magic & (DRM_HASH_SIZE - 1);
-}
-
 /**
  * Find the file with the given magic number.
  *
@@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
 {
        drm_file_t *retval = NULL;
        drm_magic_entry_t *pt;
-       int hash = drm_hash_magic(magic);
+       drm_hash_item_t *hash;
 
        mutex_lock(&dev->struct_mutex);
-       for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
-               if (pt->magic == magic) {
-                       retval = pt->priv;
-                       break;
-               }
+       if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+               pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+               retval = pt->priv;
        }
        mutex_unlock(&dev->struct_mutex);
        return retval;
@@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
 static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
                         drm_magic_t magic)
 {
-       int hash;
        drm_magic_entry_t *entry;
 
        DRM_DEBUG("%d\n", magic);
 
-       hash = drm_hash_magic(magic);
        entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
        if (!entry)
                return -ENOMEM;
        memset(entry, 0, sizeof(*entry));
-       entry->magic = magic;
        entry->priv = priv;
-       entry->next = NULL;
 
+       entry->hash_item.key = (unsigned long)magic;
        mutex_lock(&dev->struct_mutex);
-       if (dev->magiclist[hash].tail) {
-               dev->magiclist[hash].tail->next = entry;
-               dev->magiclist[hash].tail = entry;
-       } else {
-               dev->magiclist[hash].head = entry;
-               dev->magiclist[hash].tail = entry;
-       }
+       drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
+       list_add_tail(&entry->head, &dev->magicfree);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -128,34 +104,24 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
  */
 static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
 {
-       drm_magic_entry_t *prev = NULL;
        drm_magic_entry_t *pt;
-       int hash;
+       drm_hash_item_t *hash;
 
        DRM_DEBUG("%d\n", magic);
-       hash = drm_hash_magic(magic);
 
        mutex_lock(&dev->struct_mutex);
-       for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
-               if (pt->magic == magic) {
-                       if (dev->magiclist[hash].head == pt) {
-                               dev->magiclist[hash].head = pt->next;
-                       }
-                       if (dev->magiclist[hash].tail == pt) {
-                               dev->magiclist[hash].tail = prev;
-                       }
-                       if (prev) {
-                               prev->next = pt->next;
-                       }
-                       mutex_unlock(&dev->struct_mutex);
-                       return 0;
-               }
+       if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
        }
+       pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+       drm_ht_remove_item(&dev->magiclist, hash);
+       list_del(&pt->head);
        mutex_unlock(&dev->struct_mutex);
 
        drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
 
-       return -EINVAL;
+       return 0;
 }
 
 /**
index 006b06d29727069b30ff304f5ad58084804a689d..029baea33b628772bb0f238acb3d59392117fa9c 100644 (file)
@@ -65,43 +65,29 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
        return NULL;
 }
 
-/*
- * Used to allocate 32-bit handles for mappings.
- */
-#define START_RANGE 0x10000000
-#define END_RANGE 0x40000000
-
-#ifdef _LP64
-static __inline__ unsigned int HandleID(unsigned long lhandle,
-                                       drm_device_t *dev)
+static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
+                         unsigned long user_token, int hashed_handle)
 {
-       static unsigned int map32_handle = START_RANGE;
-       unsigned int hash;
-
-       if (lhandle & 0xffffffff00000000) {
-               hash = map32_handle;
-               map32_handle += PAGE_SIZE;
-               if (map32_handle > END_RANGE)
-                       map32_handle = START_RANGE;
-       } else
-               hash = lhandle;
-
-       while (1) {
-               drm_map_list_t *_entry;
-               list_for_each_entry(_entry, &dev->maplist->head, head) {
-                       if (_entry->user_token == hash)
-                               break;
-               }
-               if (&_entry->head == &dev->maplist->head)
-                       return hash;
+       int use_hashed_handle;
+#if (BITS_PER_LONG == 64)
+       use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
+#elif (BITS_PER_LONG == 32)
+       use_hashed_handle = hashed_handle;
+#else
+#error Unsupported long size. Neither 64 nor 32 bits.
+#endif
 
-               hash += PAGE_SIZE;
-               map32_handle += PAGE_SIZE;
+       if (!use_hashed_handle) {
+               int ret;
+               hash->key = user_token;
+               ret = drm_ht_insert_item(&dev->map_hash, hash);
+               if (ret != -EINVAL)
+                       return ret;
        }
+       return drm_ht_just_insert_please(&dev->map_hash, hash,
+                                        user_token, 32 - PAGE_SHIFT - 3,
+                                        PAGE_SHIFT, DRM_MAP_HASH_OFFSET);
 }
-#else
-# define HandleID(x,dev) (unsigned int)(x)
-#endif
 
 /**
  * Ioctl to specify a range of memory that is available for mapping by a non-root process.
@@ -123,6 +109,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
        drm_map_t *map;
        drm_map_list_t *list;
        drm_dma_handle_t *dmah;
+       unsigned long user_token;
+       int ret;
 
        map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
        if (!map)
@@ -257,11 +245,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
 
        mutex_lock(&dev->struct_mutex);
        list_add(&list->head, &dev->maplist->head);
+
        /* Assign a 32-bit handle */
        /* We do it here so that dev->struct_mutex protects the increment */
-       list->user_token = HandleID(map->type == _DRM_SHM
-                                   ? (unsigned long)map->handle
-                                   : map->offset, dev);
+       user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
+               map->offset;
+       ret = drm_map_handle(dev, &list->hash, user_token, 0);
+       if (ret) {
+               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       list->user_token = list->hash.key;
        mutex_unlock(&dev->struct_mutex);
 
        *maplist = list;
@@ -346,6 +343,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
 
                if (r_list->map == map) {
                        list_del(list);
+                       drm_ht_remove_key(&dev->map_hash, r_list->user_token);
                        drm_free(list, sizeof(*list), DRM_MEM_MAPS);
                        break;
                }
@@ -441,8 +439,10 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       if (!map)
+       if (!map) {
+               mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
+       }
 
        /* Register and framebuffer maps are permanent */
        if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
index 3c0b882a8e72843a2074b2b495ffa2f2ebf266ab..b366c5b1bd16713345c56a09e389db70b026e727 100644 (file)
@@ -118,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
 };
 
-#define DRIVER_IOCTL_COUNT     DRM_ARRAY_SIZE( drm_ioctls )
+#define DRIVER_IOCTL_COUNT     ARRAY_SIZE( drm_ioctls )
 
 /**
  * Take down the DRM device.
@@ -155,12 +155,13 @@ int drm_lastclose(drm_device_t * dev)
        del_timer(&dev->timer);
 
        /* Clear pid list */
-       for (i = 0; i < DRM_HASH_SIZE; i++) {
-               for (pt = dev->magiclist[i].head; pt; pt = next) {
-                       next = pt->next;
+       if (dev->magicfree.next) {
+               list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
+                       list_del(&pt->head);
+                       drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
                        drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
                }
-               dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+               drm_ht_remove(&dev->magiclist);
        }
 
        /* Clear AGP information */
@@ -299,6 +300,7 @@ static void drm_cleanup(drm_device_t * dev)
        if (dev->maplist) {
                drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
                dev->maplist = NULL;
+               drm_ht_remove(&dev->map_hash);
        }
 
        drm_ctxbitmap_cleanup(dev);
index b7f7951c458721d8b3517c49dd5b4531bfa6f3be..898f47dafec0b2fc6234e0c7f42ad3a4656e70ef 100644 (file)
@@ -53,6 +53,8 @@ static int drm_setup(drm_device_t * dev)
                        return ret;
        }
 
+       dev->magicfree.next = NULL;
+
        /* prebuild the SAREA */
        i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
        if (i != 0)
@@ -69,13 +71,11 @@ static int drm_setup(drm_device_t * dev)
                        return i;
        }
 
-       for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
+       for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
                atomic_set(&dev->counts[i], 0);
 
-       for (i = 0; i < DRM_HASH_SIZE; i++) {
-               dev->magiclist[i].head = NULL;
-               dev->magiclist[i].tail = NULL;
-       }
+       drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
+       INIT_LIST_HEAD(&dev->magicfree);
 
        dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
        if (dev->ctxlist == NULL)
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
new file mode 100644 (file)
index 0000000..a0b2d68
--- /dev/null
@@ -0,0 +1,190 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple open hash tab implementation.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+#include "drm_hashtab.h"
+#include <linux/hash.h>
+
+int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
+{
+       unsigned int i;
+
+       ht->size = 1 << order;
+       ht->order = order;
+       ht->fill = 0;
+       ht->table = vmalloc(ht->size*sizeof(*ht->table));
+       if (!ht->table) {
+               DRM_ERROR("Out of memory for hash table\n");
+               return -ENOMEM;
+       }
+       for (i=0; i< ht->size; ++i) {
+               INIT_HLIST_HEAD(&ht->table[i]);
+       }
+       return 0;
+}
+
+void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
+{
+       drm_hash_item_t *entry;
+       struct hlist_head *h_list;
+       struct hlist_node *list;
+       unsigned int hashed_key;
+       int count = 0;
+
+       hashed_key = hash_long(key, ht->order);
+       DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
+       h_list = &ht->table[hashed_key];
+       hlist_for_each(list, h_list) {
+               entry = hlist_entry(list, drm_hash_item_t, head);
+               DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
+       }
+}
+
+static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht, 
+                                         unsigned long key)
+{
+       drm_hash_item_t *entry;
+       struct hlist_head *h_list;
+       struct hlist_node *list;
+       unsigned int hashed_key;
+
+       hashed_key = hash_long(key, ht->order);
+       h_list = &ht->table[hashed_key];
+       hlist_for_each(list, h_list) {
+               entry = hlist_entry(list, drm_hash_item_t, head);
+               if (entry->key == key)
+                       return list;
+               if (entry->key > key)
+                       break;
+       }
+       return NULL;
+}
+
+
+int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+{
+       drm_hash_item_t *entry;
+       struct hlist_head *h_list;
+       struct hlist_node *list, *parent;
+       unsigned int hashed_key;
+       unsigned long key = item->key;
+
+       hashed_key = hash_long(key, ht->order);
+       h_list = &ht->table[hashed_key];
+       parent = NULL;
+       hlist_for_each(list, h_list) {
+               entry = hlist_entry(list, drm_hash_item_t, head);
+               if (entry->key == key)
+                       return -EINVAL;
+               if (entry->key > key)
+                       break;
+               parent = list;
+       }
+       if (parent) {
+               hlist_add_after(parent, &item->head);
+       } else {
+               hlist_add_head(&item->head, h_list);
+       }
+       return 0;
+}
+
+/*
+ * Just insert an item and return any "bits" bit key that hasn't been 
+ * used before.
+ */
+int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+                             unsigned long seed, int bits, int shift,
+                             unsigned long add)
+{
+       int ret;
+       unsigned long mask = (1 << bits) - 1;
+       unsigned long first, unshifted_key;
+
+       unshifted_key = hash_long(seed, bits);
+       first = unshifted_key;
+       do {
+               item->key = (unshifted_key << shift) + add;
+               ret = drm_ht_insert_item(ht, item);
+               if (ret)
+                       unshifted_key = (unshifted_key + 1) & mask;
+       } while(ret && (unshifted_key != first));
+
+       if (ret) {
+               DRM_ERROR("Available key bit space exhausted\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key,
+                    drm_hash_item_t **item)
+{
+       struct hlist_node *list;
+
+       list = drm_ht_find_key(ht, key);
+       if (!list)
+               return -EINVAL;
+
+       *item = hlist_entry(list, drm_hash_item_t, head);
+       return 0;
+}
+
+int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
+{
+       struct hlist_node *list;
+
+       list = drm_ht_find_key(ht, key);
+       if (list) {
+               hlist_del_init(list);
+               ht->fill--;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
+{
+       hlist_del_init(&item->head);
+       ht->fill--;
+       return 0;
+}
+
+void drm_ht_remove(drm_open_hash_t *ht)
+{
+       if (ht->table) {
+               vfree(ht->table);
+               ht->table = NULL;
+       }
+}
+
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
new file mode 100644 (file)
index 0000000..40afec0
--- /dev/null
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple open hash tab implementation.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef DRM_HASHTAB_H
+#define DRM_HASHTAB_H
+
+#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
+
+typedef struct drm_hash_item{
+       struct hlist_node head;
+       unsigned long key;
+} drm_hash_item_t;
+
+typedef struct drm_open_hash{
+       unsigned int size;
+       unsigned int order;
+       unsigned int fill;
+       struct hlist_head *table;
+} drm_open_hash_t;
+
+
+extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
+extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
+extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+                                    unsigned long seed, int bits, int shift,
+                                    unsigned long add);
+extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
+
+extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
+extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
+extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
+extern void drm_ht_remove(drm_open_hash_t *ht);
+
+
+#endif
+
index e9e2db18952dc91e2b88c8283efb6d385ff84dd9..d4f874520082844776eff9f912cb70323f25003f 100644 (file)
@@ -1051,7 +1051,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        drm_ioctl_compat_t *fn;
        int ret;
 
-       if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls))
+       if (nr >= ARRAY_SIZE(drm_compat_ioctls))
                return -ENOTTY;
 
        fn = drm_compat_ioctls[nr];
index 555f323b8a32c350578b4f75ea04b5a345472c80..565895547d75b2c254db4eafaab91c344d14780e 100644 (file)
@@ -127,9 +127,10 @@ int drm_setunique(struct inode *inode, struct file *filp,
        domain = bus >> 8;
        bus &= 0xff;
 
-       if ((domain != dev->pci_domain) ||
-           (bus != dev->pci_bus) ||
-           (slot != dev->pci_slot) || (func != dev->pci_func))
+       if ((domain != drm_get_pci_domain(dev)) ||
+           (bus != dev->pdev->bus->number) ||
+           (slot != PCI_SLOT(dev->pdev->devfn)) ||
+           (func != PCI_FUNC(dev->pdev->devfn)))
                return -EINVAL;
 
        return 0;
@@ -140,15 +141,17 @@ static int drm_set_busid(drm_device_t * dev)
        int len;
 
        if (dev->unique != NULL)
-               return EBUSY;
+               return 0;
 
        dev->unique_len = 40;
        dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
        if (dev->unique == NULL)
-               return ENOMEM;
+               return -ENOMEM;
 
        len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
-                dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
+                      drm_get_pci_domain(dev), dev->pdev->bus->number,
+                      PCI_SLOT(dev->pdev->devfn),
+                      PCI_FUNC(dev->pdev->devfn));
 
        if (len > dev->unique_len)
                DRM_ERROR("Unique buffer overflowed\n");
@@ -157,7 +160,7 @@ static int drm_set_busid(drm_device_t * dev)
            drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
                      2, DRM_MEM_DRIVER);
        if (dev->devname == NULL)
-               return ENOMEM;
+               return -ENOMEM;
 
        sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
                dev->unique);
@@ -330,27 +333,32 @@ int drm_setversion(DRM_IOCTL_ARGS)
        drm_set_version_t retv;
        int if_version;
        drm_set_version_t __user *argp = (void __user *)data;
+       int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv));
+       if (copy_from_user(&sv, argp, sizeof(sv)))
+               return -EFAULT;
 
        retv.drm_di_major = DRM_IF_MAJOR;
        retv.drm_di_minor = DRM_IF_MINOR;
        retv.drm_dd_major = dev->driver->major;
        retv.drm_dd_minor = dev->driver->minor;
 
-       DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv));
+       if (copy_to_user(argp, &retv, sizeof(retv)))
+               return -EFAULT;
 
        if (sv.drm_di_major != -1) {
                if (sv.drm_di_major != DRM_IF_MAJOR ||
                    sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
-                       return EINVAL;
+                       return -EINVAL;
                if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor);
-               dev->if_version = DRM_MAX(if_version, dev->if_version);
+               dev->if_version = max(if_version, dev->if_version);
                if (sv.drm_di_minor >= 1) {
                        /*
                         * Version 1.1 includes tying of DRM to specific device
                         */
-                       drm_set_busid(dev);
+                       ret = drm_set_busid(dev);
+                       if (ret)
+                               return ret;
                }
        }
 
@@ -358,7 +366,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
                if (sv.drm_dd_major != dev->driver->major ||
                    sv.drm_dd_minor < 0
                    || sv.drm_dd_minor > dev->driver->minor)
-                       return EINVAL;
+                       return -EINVAL;
 
                if (dev->driver->set_version)
                        dev->driver->set_version(dev, &sv);
index ebdb7182c4fd7e2c973d27a5aaa602861058c960..4553a3a1e496c463b82b6a93e7cda756aec350a0 100644 (file)
@@ -64,9 +64,9 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
        if (copy_from_user(&p, argp, sizeof(p)))
                return -EFAULT;
 
-       if ((p.busnum >> 8) != dev->pci_domain ||
-           (p.busnum & 0xff) != dev->pci_bus ||
-           p.devnum != dev->pci_slot || p.funcnum != dev->pci_func)
+       if ((p.busnum >> 8) != drm_get_pci_domain(dev) ||
+           (p.busnum & 0xff) != dev->pdev->bus->number ||
+           p.devnum != PCI_SLOT(dev->pdev->devfn) || p.funcnum != PCI_FUNC(dev->pdev->devfn))
                return -EINVAL;
 
        p.irq = dev->irq;
@@ -255,7 +255,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        if (!dev->irq)
                return -EINVAL;
 
-       DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait));
+       if (copy_from_user(&vblwait, argp, sizeof(vblwait)))
+               return -EFAULT;
 
        switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
        case _DRM_VBLANK_RELATIVE:
@@ -329,7 +330,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        }
 
       done:
-       DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait));
+       if (copy_to_user(argp, &vblwait, sizeof(vblwait)))
+               return -EFAULT;
 
        return ret;
 }
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
new file mode 100644 (file)
index 0000000..617526b
--- /dev/null
@@ -0,0 +1,201 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Generic simple memory manager implementation. Intended to be used as a base
+ * class implementation for more advanced memory managers.
+ *
+ * Note that the algorithm used is quite simple and there might be substantial
+ * performance gains if a smarter free list is implemented. Currently it is just an
+ * unordered stack of free regions. This could easily be improved if an RB-tree
+ * is used instead. At least if we expect heavy fragmentation.
+ *
+ * Aligned allocations can also see improvement.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+
+drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+                               unsigned long size, unsigned alignment)
+{
+
+       drm_mm_node_t *child;
+
+       if (alignment)
+               size += alignment - 1;
+
+       if (parent->size == size) {
+               list_del_init(&parent->fl_entry);
+               parent->free = 0;
+               return parent;
+       } else {
+               child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM);
+               if (!child)
+                       return NULL;
+
+               INIT_LIST_HEAD(&child->ml_entry);
+               INIT_LIST_HEAD(&child->fl_entry);
+
+               child->free = 0;
+               child->size = size;
+               child->start = parent->start;
+
+               list_add_tail(&child->ml_entry, &parent->ml_entry);
+               parent->size -= size;
+               parent->start += size;
+       }
+       return child;
+}
+
+/*
+ * Put a block. Merge with the previous and / or next block if they are free.
+ * Otherwise add to the free stack.
+ */
+
+void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur)
+{
+
+       drm_mm_node_t *list_root = &mm->root_node;
+       struct list_head *cur_head = &cur->ml_entry;
+       struct list_head *root_head = &list_root->ml_entry;
+       drm_mm_node_t *prev_node = NULL;
+       drm_mm_node_t *next_node;
+
+       int merged = 0;
+
+       if (cur_head->prev != root_head) {
+               prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry);
+               if (prev_node->free) {
+                       prev_node->size += cur->size;
+                       merged = 1;
+               }
+       }
+       if (cur_head->next != root_head) {
+               next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry);
+               if (next_node->free) {
+                       if (merged) {
+                               prev_node->size += next_node->size;
+                               list_del(&next_node->ml_entry);
+                               list_del(&next_node->fl_entry);
+                               drm_free(next_node, sizeof(*next_node),
+                                        DRM_MEM_MM);
+                       } else {
+                               next_node->size += cur->size;
+                               next_node->start = cur->start;
+                               merged = 1;
+                       }
+               }
+       }
+       if (!merged) {
+               cur->free = 1;
+               list_add(&cur->fl_entry, &list_root->fl_entry);
+       } else {
+               list_del(&cur->ml_entry);
+               drm_free(cur, sizeof(*cur), DRM_MEM_MM);
+       }
+}
+
+drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
+                                 unsigned long size,
+                                 unsigned alignment, int best_match)
+{
+       struct list_head *list;
+       const struct list_head *free_stack = &mm->root_node.fl_entry;
+       drm_mm_node_t *entry;
+       drm_mm_node_t *best;
+       unsigned long best_size;
+
+       best = NULL;
+       best_size = ~0UL;
+
+       if (alignment)
+               size += alignment - 1;
+
+       list_for_each(list, free_stack) {
+               entry = list_entry(list, drm_mm_node_t, fl_entry);
+               if (entry->size >= size) {
+                       if (!best_match)
+                               return entry;
+                       if (size < best_size) {
+                               best = entry;
+                               best_size = entry->size;
+                       }
+               }
+       }
+
+       return best;
+}
+
+int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
+{
+       drm_mm_node_t *child;
+
+       INIT_LIST_HEAD(&mm->root_node.ml_entry);
+       INIT_LIST_HEAD(&mm->root_node.fl_entry);
+       child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM);
+       if (!child)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&child->ml_entry);
+       INIT_LIST_HEAD(&child->fl_entry);
+
+       child->start = start;
+       child->size = size;
+       child->free = 1;
+
+       list_add(&child->fl_entry, &mm->root_node.fl_entry);
+       list_add(&child->ml_entry, &mm->root_node.ml_entry);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_mm_init);
+
+void drm_mm_takedown(drm_mm_t * mm)
+{
+       struct list_head *bnode = mm->root_node.fl_entry.next;
+       drm_mm_node_t *entry;
+
+       entry = list_entry(bnode, drm_mm_node_t, fl_entry);
+
+       if (entry->ml_entry.next != &mm->root_node.ml_entry ||
+           entry->fl_entry.next != &mm->root_node.fl_entry) {
+               DRM_ERROR("Memory manager not clean. Delaying takedown\n");
+               return;
+       }
+
+       list_del(&entry->fl_entry);
+       list_del(&entry->ml_entry);
+
+       drm_free(entry, sizeof(*entry), DRM_MEM_MM);
+}
+
+EXPORT_SYMBOL(drm_mm_takedown);
index b1bb3c7b568deaac4be5e259930d7daecc00699c..09398d5fbd3f0644ca528e740f3bbb8f53c65431 100644 (file)
@@ -3,13 +3,13 @@
    Please contact dri-devel@lists.sf.net to add new cards to this list
 */
 #define radeon_PCI_IDS \
-       {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \
-       {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
+       {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \
+       {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
        {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
        {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
        {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
+       {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
        {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
        {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-       {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
+       {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
        {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
-       {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
+       {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
        {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
        {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
-       {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
-       {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
-       {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
+       {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
        {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
        {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
        {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
        {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
        {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
        {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
-       {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
+       {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {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, 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}, \
        {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
        {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
        {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
-       {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \
-       {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+       {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0, 0, 0}
 
 #define r128_PCI_IDS \
        {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
        {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
        {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
 #define i810_PCI_IDS \
        {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
index 362a270af0f10c53387069b2b7124ce788f23e96..62d5fe15f0468971b9017c1b932c3c1fcd5be819 100644 (file)
@@ -510,7 +510,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
                               vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
                               vma->vm_flags & VM_LOCKED ? 'l' : '-',
                               vma->vm_flags & VM_IO ? 'i' : '-',
-                              VM_OFFSET(vma));
+                              vma->vm_pgoff << PAGE_SHIFT);
 
 #if defined(__i386__)
                pgprot = pgprot_val(vma->vm_page_prot);
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
new file mode 100644 (file)
index 0000000..425c823
--- /dev/null
@@ -0,0 +1,352 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple memory manager interface that keeps track on allocate regions on a
+ * per "owner" basis. All regions associated with an "owner" can be released
+ * with a simple call. Typically if the "owner" exists. The owner is any
+ * "unsigned long" identifier. Can typically be a pointer to a file private
+ * struct or a context identifier.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drm_sman.h"
+
+typedef struct drm_owner_item {
+       drm_hash_item_t owner_hash;
+       struct list_head sman_list;
+       struct list_head mem_blocks;
+} drm_owner_item_t;
+
+void drm_sman_takedown(drm_sman_t * sman)
+{
+       drm_ht_remove(&sman->user_hash_tab);
+       drm_ht_remove(&sman->owner_hash_tab);
+       if (sman->mm)
+               drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
+                        DRM_MEM_MM);
+}
+
+EXPORT_SYMBOL(drm_sman_takedown);
+
+int
+drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+             unsigned int user_order, unsigned int owner_order)
+{
+       int ret = 0;
+
+       sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm),
+                                               DRM_MEM_MM);
+       if (!sman->mm) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       sman->num_managers = num_managers;
+       INIT_LIST_HEAD(&sman->owner_items);
+       ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
+       if (ret)
+               goto out1;
+       ret = drm_ht_create(&sman->user_hash_tab, user_order);
+       if (!ret)
+               goto out;
+
+       drm_ht_remove(&sman->owner_hash_tab);
+out1:
+       drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
+out:
+       return ret;
+}
+
+EXPORT_SYMBOL(drm_sman_init);
+
+static void *drm_sman_mm_allocate(void *private, unsigned long size,
+                                 unsigned alignment)
+{
+       drm_mm_t *mm = (drm_mm_t *) private;
+       drm_mm_node_t *tmp;
+
+       tmp = drm_mm_search_free(mm, size, alignment, 1);
+       if (!tmp) {
+               return NULL;
+       }
+       tmp = drm_mm_get_block(tmp, size, alignment);
+       return tmp;
+}
+
+static void drm_sman_mm_free(void *private, void *ref)
+{
+       drm_mm_t *mm = (drm_mm_t *) private;
+       drm_mm_node_t *node = (drm_mm_node_t *) ref;
+
+       drm_mm_put_block(mm, node);
+}
+
+static void drm_sman_mm_destroy(void *private)
+{
+       drm_mm_t *mm = (drm_mm_t *) private;
+       drm_mm_takedown(mm);
+       drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+}
+
+static unsigned long drm_sman_mm_offset(void *private, void *ref)
+{
+       drm_mm_node_t *node = (drm_mm_node_t *) ref;
+       return node->start;
+}
+
+int
+drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+                  unsigned long start, unsigned long size)
+{
+       drm_sman_mm_t *sman_mm;
+       drm_mm_t *mm;
+       int ret;
+
+       BUG_ON(manager >= sman->num_managers);
+
+       sman_mm = &sman->mm[manager];
+       mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM);
+       if (!mm) {
+               return -ENOMEM;
+       }
+       sman_mm->private = mm;
+       ret = drm_mm_init(mm, start, size);
+
+       if (ret) {
+               drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+               return ret;
+       }
+
+       sman_mm->allocate = drm_sman_mm_allocate;
+       sman_mm->free = drm_sman_mm_free;
+       sman_mm->destroy = drm_sman_mm_destroy;
+       sman_mm->offset = drm_sman_mm_offset;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_sman_set_range);
+
+int
+drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
+                    drm_sman_mm_t * allocator)
+{
+       BUG_ON(manager >= sman->num_managers);
+       sman->mm[manager] = *allocator;
+
+       return 0;
+}
+
+static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
+                                                unsigned long owner)
+{
+       int ret;
+       drm_hash_item_t *owner_hash_item;
+       drm_owner_item_t *owner_item;
+
+       ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
+       if (!ret) {
+               return drm_hash_entry(owner_hash_item, drm_owner_item_t,
+                                     owner_hash);
+       }
+
+       owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM);
+       if (!owner_item)
+               goto out;
+
+       INIT_LIST_HEAD(&owner_item->mem_blocks);
+       owner_item->owner_hash.key = owner;
+       if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
+               goto out1;
+
+       list_add_tail(&owner_item->sman_list, &sman->owner_items);
+       return owner_item;
+
+out1:
+       drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+out:
+       return NULL;
+}
+
+drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager,
+                                   unsigned long size, unsigned alignment,
+                                   unsigned long owner)
+{
+       void *tmp;
+       drm_sman_mm_t *sman_mm;
+       drm_owner_item_t *owner_item;
+       drm_memblock_item_t *memblock;
+
+       BUG_ON(manager >= sman->num_managers);
+
+       sman_mm = &sman->mm[manager];
+       tmp = sman_mm->allocate(sman_mm->private, size, alignment);
+
+       if (!tmp) {
+               return NULL;
+       }
+
+       memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM);
+
+       if (!memblock)
+               goto out;
+
+       memblock->mm_info = tmp;
+       memblock->mm = sman_mm;
+       memblock->sman = sman;
+
+       if (drm_ht_just_insert_please
+           (&sman->user_hash_tab, &memblock->user_hash,
+            (unsigned long)memblock, 32, 0, 0))
+               goto out1;
+
+       owner_item = drm_sman_get_owner_item(sman, owner);
+       if (!owner_item)
+               goto out2;
+
+       list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
+
+       return memblock;
+
+out2:
+       drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
+out1:
+       drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
+out:
+       sman_mm->free(sman_mm->private, tmp);
+
+       return NULL;
+}
+
+EXPORT_SYMBOL(drm_sman_alloc);
+
+static void drm_sman_free(drm_memblock_item_t *item)
+{
+       drm_sman_t *sman = item->sman;
+
+       list_del(&item->owner_list);
+       drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
+       item->mm->free(item->mm->private, item->mm_info);
+       drm_free(item, sizeof(*item), DRM_MEM_MM);
+}
+
+int drm_sman_free_key(drm_sman_t *sman, unsigned int key)
+{
+       drm_hash_item_t *hash_item;
+       drm_memblock_item_t *memblock_item;
+
+       if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
+               return -EINVAL;
+
+       memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash);
+       drm_sman_free(memblock_item);
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_sman_free_key);
+
+static void drm_sman_remove_owner(drm_sman_t *sman,
+                                 drm_owner_item_t *owner_item)
+{
+       list_del(&owner_item->sman_list);
+       drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
+       drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+}
+
+int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
+{
+
+       drm_hash_item_t *hash_item;
+       drm_owner_item_t *owner_item;
+
+       if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
+               return -1;
+       }
+
+       owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+       if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
+               drm_sman_remove_owner(sman, owner_item);
+               return -1;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_sman_owner_clean);
+
+static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
+                                     drm_owner_item_t *owner_item)
+{
+       drm_memblock_item_t *entry, *next;
+
+       list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
+                                owner_list) {
+               drm_sman_free(entry);
+       }
+       drm_sman_remove_owner(sman, owner_item);
+}
+
+void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner)
+{
+
+       drm_hash_item_t *hash_item;
+       drm_owner_item_t *owner_item;
+
+       if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
+
+               return;
+       }
+
+       owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+       drm_sman_do_owner_cleanup(sman, owner_item);
+}
+
+EXPORT_SYMBOL(drm_sman_owner_cleanup);
+
+void drm_sman_cleanup(drm_sman_t *sman)
+{
+       drm_owner_item_t *entry, *next;
+       unsigned int i;
+       drm_sman_mm_t *sman_mm;
+
+       list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
+               drm_sman_do_owner_cleanup(sman, entry);
+       }
+       if (sman->mm) {
+               for (i = 0; i < sman->num_managers; ++i) {
+                       sman_mm = &sman->mm[i];
+                       if (sman_mm->private) {
+                               sman_mm->destroy(sman_mm->private);
+                               sman_mm->private = NULL;
+                       }
+               }
+       }
+}
+
+EXPORT_SYMBOL(drm_sman_cleanup);
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
new file mode 100644 (file)
index 0000000..ddc732a
--- /dev/null
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple memory MANager interface that keeps track on allocate regions on a
+ * per "owner" basis. All regions associated with an "owner" can be released
+ * with a simple call. Typically if the "owner" exists. The owner is any
+ * "unsigned long" identifier. Can typically be a pointer to a file private
+ * struct or a context identifier.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef DRM_SMAN_H
+#define DRM_SMAN_H
+
+#include "drmP.h"
+#include "drm_hashtab.h"
+
+/*
+ * A class that is an abstration of a simple memory allocator.
+ * The sman implementation provides a default such allocator
+ * using the drm_mm.c implementation. But the user can replace it.
+ * See the SiS implementation, which may use the SiS FB kernel module
+ * for memory management.
+ */
+
+typedef struct drm_sman_mm {
+       /* private info. If allocated, needs to be destroyed by the destroy
+          function */
+       void *private;
+
+       /* Allocate a memory block with given size and alignment.
+          Return an opaque reference to the memory block */
+
+       void *(*allocate) (void *private, unsigned long size,
+                          unsigned alignment);
+
+       /* Free a memory block. "ref" is the opaque reference that we got from
+          the "alloc" function */
+
+       void (*free) (void *private, void *ref);
+
+       /* Free all resources associated with this allocator */
+
+       void (*destroy) (void *private);
+
+       /* Return a memory offset from the opaque reference returned from the
+          "alloc" function */
+
+       unsigned long (*offset) (void *private, void *ref);
+} drm_sman_mm_t;
+
+typedef struct drm_memblock_item {
+       struct list_head owner_list;
+       drm_hash_item_t user_hash;
+       void *mm_info;
+       drm_sman_mm_t *mm;
+       struct drm_sman *sman;
+} drm_memblock_item_t;
+
+typedef struct drm_sman {
+       drm_sman_mm_t *mm;
+       int num_managers;
+       drm_open_hash_t owner_hash_tab;
+       drm_open_hash_t user_hash_tab;
+       struct list_head owner_items;
+} drm_sman_t;
+
+/*
+ * Take down a memory manager. This function should only be called after a
+ * successful init and after a call to drm_sman_cleanup.
+ */
+
+extern void drm_sman_takedown(drm_sman_t * sman);
+
+/*
+ * Allocate structures for a manager.
+ * num_managers are the number of memory pools to manage. (VRAM, AGP, ....)
+ * user_order is the log2 of the number of buckets in the user hash table.
+ *         set this to approximately log2 of the max number of memory regions
+ *         that will be allocated for _all_ pools together.
+ * owner_order is the log2 of the number of buckets in the owner hash table.
+ *         set this to approximately log2 of
+ *         the number of client file connections that will
+ *         be using the manager.
+ *
+ */
+
+extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+                        unsigned int user_order, unsigned int owner_order);
+
+/*
+ * Initialize a drm_mm.c allocator. Should be called only once for each
+ * manager unless a customized allogator is used.
+ */
+
+extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+                             unsigned long start, unsigned long size);
+
+/*
+ * Initialize a customized allocator for one of the managers.
+ * (See the SiS module). The object pointed to by "allocator" is copied,
+ * so it can be destroyed after this call.
+ */
+
+extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger,
+                               drm_sman_mm_t * allocator);
+
+/*
+ * Allocate a memory block. Aligment is not implemented yet.
+ */
+
+extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman,
+                                          unsigned int manager,
+                                          unsigned long size,
+                                          unsigned alignment,
+                                          unsigned long owner);
+/*
+ * Free a memory block identified by its user hash key.
+ */
+
+extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
+
+/*
+ * returns 1 iff there are no stale memory blocks associated with this owner.
+ * Typically called to determine if we need to idle the hardware and call
+ * drm_sman_owner_cleanup. If there are no stale memory blocks, it removes all
+ * resources associated with owner.
+ */
+
+extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
+
+/*
+ * Frees all stale memory blocks associated with this owner. Note that this
+ * requires that the hardware is finished with all blocks, so the graphics engine
+ * should be idled before this call is made. This function also frees
+ * any resources associated with "owner" and should be called when owner
+ * is not going to be referenced anymore.
+ */
+
+extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner);
+
+/*
+ * Frees all stale memory blocks associated with the memory manager.
+ * See idling above.
+ */
+
+extern void drm_sman_cleanup(drm_sman_t * sman);
+
+#endif
index 9a842a36bb2754cfef213344754e0ff951e4c44c..7b1d4e8659baa41e71560f8c02d5592baa66ea4a 100644 (file)
@@ -65,22 +65,22 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
        mutex_init(&dev->ctxlist_mutex);
 
        dev->pdev = pdev;
+       dev->pci_device = pdev->device;
+       dev->pci_vendor = pdev->vendor;
 
 #ifdef __alpha__
        dev->hose = pdev->sysdata;
-       dev->pci_domain = dev->hose->bus->number;
-#else
-       dev->pci_domain = 0;
 #endif
-       dev->pci_bus = pdev->bus->number;
-       dev->pci_slot = PCI_SLOT(pdev->devfn);
-       dev->pci_func = PCI_FUNC(pdev->devfn);
        dev->irq = pdev->irq;
 
        dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
        if (dev->maplist == NULL)
                return -ENOMEM;
        INIT_LIST_HEAD(&dev->maplist->head);
+       if (drm_ht_create(&dev->map_hash, 12)) {
+               drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+               return -ENOMEM;
+       }
 
        /* the DRM has 6 basic counters */
        dev->counters = 6;
index ffd0800ed601b286863f5a3a80c2538042340af1..b40ae438f5315343248930f32df8f53f10b38845 100644 (file)
@@ -59,7 +59,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
        drm_device_t *dev = priv->head->dev;
        drm_map_t *map = NULL;
        drm_map_list_t *r_list;
-       struct list_head *list;
+       drm_hash_item_t *hash;
 
        /*
         * Find the right map
@@ -70,14 +70,11 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
        if (!dev->agp || !dev->agp->cant_use_aperture)
                goto vm_nopage_error;
 
-       list_for_each(list, &dev->maplist->head) {
-               r_list = list_entry(list, drm_map_list_t, head);
-               map = r_list->map;
-               if (!map)
-                       continue;
-               if (r_list->user_token == VM_OFFSET(vma))
-                       break;
-       }
+       if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash))
+               goto vm_nopage_error;
+
+       r_list = drm_hash_entry(hash, drm_map_list_t, hash);
+       map = r_list->map;
 
        if (map && map->type == _DRM_AGP) {
                unsigned long offset = address - vma->vm_start;
@@ -467,7 +464,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        dev = priv->head->dev;
        dma = dev->dma;
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
-                 vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+                 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
 
        /* Length must match exact page count */
        if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
@@ -521,12 +518,11 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->head->dev;
        drm_map_t *map = NULL;
-       drm_map_list_t *r_list;
        unsigned long offset = 0;
-       struct list_head *list;
+       drm_hash_item_t *hash;
 
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
-                 vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+                 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
 
        if (!priv->authenticated)
                return -EACCES;
@@ -535,7 +531,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
         * the AGP mapped at physical address 0
         * --BenH.
         */
-       if (!VM_OFFSET(vma)
+       if (!(vma->vm_pgoff << PAGE_SHIFT)
 #if __OS_HAS_AGP
            && (!dev->agp
                || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
@@ -543,23 +539,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
            )
                return drm_mmap_dma(filp, vma);
 
-       /* A sequential search of a linked list is
-          fine here because: 1) there will only be
-          about 5-10 entries in the list and, 2) a
-          DRI client only has to do this mapping
-          once, so it doesn't have to be optimized
-          for performance, even if the list was a
-          bit longer. */
-       list_for_each(list, &dev->maplist->head) {
-
-               r_list = list_entry(list, drm_map_list_t, head);
-               map = r_list->map;
-               if (!map)
-                       continue;
-               if (r_list->user_token == VM_OFFSET(vma))
-                       break;
+       if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) {
+               DRM_ERROR("Could not find map\n");
+               return -EINVAL;
        }
 
+       map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
        if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
                return -EPERM;
 
@@ -620,7 +605,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                offset = dev->driver->get_reg_ofs(dev);
 #ifdef __sparc__
                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-               if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+               if (io_remap_pfn_range(vma, vma->vm_start,
                                       (map->offset + offset) >> PAGE_SHIFT,
                                       vma->vm_end - vma->vm_start,
                                       vma->vm_page_prot))
index c658dde3633b4307b4e38d79eafdf079ab56af0d..fa2de70f7401aded1c300fec6ba4799075348562 100644 (file)
@@ -106,7 +106,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        unlock_kernel();
 
        if (io_remap_pfn_range(vma, vma->vm_start,
-                              VM_OFFSET(vma) >> PAGE_SHIFT,
+                              vma->vm_pgoff,
                               vma->vm_end - vma->vm_start, vma->vm_page_prot))
                return -EAGAIN;
        return 0;
@@ -141,10 +141,10 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
                                            MAP_SHARED, buf->bus_address);
        dev_priv->mmap_buffer = NULL;
        filp->f_op = old_fops;
-       if ((unsigned long)buf_priv->virtual > -1024UL) {
+       if (IS_ERR(buf_priv->virtual)) {
                /* Real error */
                DRM_ERROR("mmap error\n");
-               retcode = (signed int)buf_priv->virtual;
+               retcode = PTR_ERR(buf_priv->virtual);
                buf_priv->virtual = NULL;
        }
        up_write(&current->mm->mmap_sem);
@@ -808,7 +808,7 @@ static void i810_dma_dispatch_vertex(drm_device_t * dev,
                    ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
 
                if (used & 4) {
-                       *(u32 *) ((u32) buf_priv->kernel_virtual + used) = 0;
+                       *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0;
                        used += 4;
                }
 
@@ -1166,7 +1166,7 @@ static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
 
        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
                if (used & 4) {
-                       *(u32 *) ((u32) buf_priv->virtual + used) = 0;
+                       *(u32 *) ((char *) buf_priv->virtual + used) = 0;
                        used += 4;
                }
 
index b0f815d8cea8592028cee0540f6b23ffe3dac9c8..4f0e5746ab3382f30ff16e393aabca4f973e025d 100644 (file)
@@ -108,7 +108,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        unlock_kernel();
 
        if (io_remap_pfn_range(vma, vma->vm_start,
-                              VM_OFFSET(vma) >> PAGE_SHIFT,
+                              vma->vm_pgoff,
                               vma->vm_end - vma->vm_start, vma->vm_page_prot))
                return -EAGAIN;
        return 0;
@@ -146,7 +146,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
        if (IS_ERR((void *)virtual)) {  /* ugh */
                /* Real error */
                DRM_ERROR("mmap error\n");
-               retcode = virtual;
+               retcode = PTR_ERR((void *)virtual);
                buf_priv->virtual = NULL;
        } else {
                buf_priv->virtual = (void __user *)virtual;
index a94233bdbc0e4575748e90ed54b461521016dda6..fb7913ff5286b58e6fd8b5a574590f8e1d8f8948 100644 (file)
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
+                      dev->pci_device == 0x2982 || \
+                      dev->pci_device == 0x2992 || \
+                      dev->pci_device == 0x29A2)
+
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
  * the head pointer changes, so that EBUSY only happens if the ring
@@ -255,7 +260,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
                retcode = i915_dma_resume(dev);
                break;
        default:
-               retcode = -EINVAL;
+               retcode = DRM_ERR(EINVAL);
                break;
        }
 
@@ -347,7 +352,7 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
        if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
                return DRM_ERR(EINVAL);
 
-       BEGIN_LP_RING(((dwords+1)&~1));
+       BEGIN_LP_RING((dwords+1)&~1);
 
        for (i = 0; i < dwords;) {
                int cmd, sz;
@@ -386,7 +391,7 @@ static int i915_emit_box(drm_device_t * dev,
        RING_LOCALS;
 
        if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
-               return EFAULT;
+               return DRM_ERR(EFAULT);
        }
 
        if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
@@ -395,24 +400,40 @@ static int i915_emit_box(drm_device_t * dev,
                return DRM_ERR(EINVAL);
        }
 
-       BEGIN_LP_RING(6);
-       OUT_RING(GFX_OP_DRAWRECT_INFO);
-       OUT_RING(DR1);
-       OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
-       OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
-       OUT_RING(DR4);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
+       if (IS_I965G(dev)) {
+               BEGIN_LP_RING(4);
+               OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+               OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+               OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+               OUT_RING(DR4);
+               ADVANCE_LP_RING();
+       } else {
+               BEGIN_LP_RING(6);
+               OUT_RING(GFX_OP_DRAWRECT_INFO);
+               OUT_RING(DR1);
+               OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+               OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+               OUT_RING(DR4);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       }
 
        return 0;
 }
 
+/* XXX: Emitting the counter should really be moved to part of the IRQ
+ * emit. For now, do it in both places:
+ */
+
 static void i915_emit_breadcrumb(drm_device_t *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
 
-       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+
+       if (dev_priv->counter > 0x7FFFFFFFUL)
+               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
 
        BEGIN_LP_RING(4);
        OUT_RING(CMD_STORE_DWORD_IDX);
index 5aa3e0e3bb457693f45174962bcf5039973a1deb..6af83e613f277537af402c7358f3288ef715d8d6 100644 (file)
@@ -98,6 +98,12 @@ typedef struct _drm_i915_sarea {
        int rotated_size;
        int rotated_pitch;
        int virtualX, virtualY;
+
+       unsigned int front_tiled;
+       unsigned int back_tiled;
+       unsigned int depth_tiled;
+       unsigned int rotated_tiled;
+       unsigned int rotated2_tiled;
 } drm_i915_sarea_t;
 
 /* Flags for perf_boxes
index 2d565031c0020c541e07bdeaa97d9b172cd21243..fdc2bf1927143febdac052799b72c68747ff11ae 100644 (file)
@@ -146,9 +146,9 @@ extern void i915_mem_release(drm_device_t * dev,
 #define BEGIN_LP_RING(n) do {                          \
        if (I915_VERBOSE)                               \
                DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",  \
-                         n, __FUNCTION__);             \
-       if (dev_priv->ring.space < n*4)                 \
-               i915_wait_ring(dev, n*4, __FUNCTION__);         \
+                         (n), __FUNCTION__);           \
+       if (dev_priv->ring.space < (n)*4)                       \
+               i915_wait_ring(dev, (n)*4, __FUNCTION__);               \
        outcount = 0;                                   \
        outring = dev_priv->ring.tail;                  \
        ringmask = dev_priv->ring.tail_mask;            \
@@ -157,7 +157,7 @@ extern void i915_mem_release(drm_device_t * dev,
 
 #define OUT_RING(n) do {                                       \
        if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
-       *(volatile unsigned int *)(virt + outring) = n;         \
+       *(volatile unsigned int *)(virt + outring) = (n);       \
         outcount++;                                            \
        outring += 4;                                           \
        outring &= ringmask;                                    \
@@ -254,6 +254,8 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
 #define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
 
+#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
+
 #define MI_BATCH_BUFFER        ((0x30<<23)|1)
 #define MI_BATCH_BUFFER_START  (0x31<<23)
 #define MI_BATCH_BUFFER_END    (0xA<<23)
index cd96cfa430db2615d5276c60990a022b139f0913..0d4a162aa38514a4aea1f27898cb47b05e829264 100644 (file)
@@ -71,21 +71,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 static int i915_emit_irq(drm_device_t * dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 ret;
        RING_LOCALS;
 
        i915_kernel_lost_context(dev);
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       ret = dev_priv->counter;
+       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
 
-       BEGIN_LP_RING(2);
+       if (dev_priv->counter > 0x7FFFFFFFUL)
+               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+
+       BEGIN_LP_RING(6);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(20);
+       OUT_RING(dev_priv->counter);
+       OUT_RING(0);
        OUT_RING(0);
        OUT_RING(GFX_OP_USER_INTERRUPT);
        ADVANCE_LP_RING();
-
-       return ret;
+       
+       return dev_priv->counter;
 }
 
 static int i915_wait_irq(drm_device_t * dev, int irq_nr)
index 5ad43ba7b5aa16fa526a8428d507a212073688ae..5ed965688293a04b6c6a11641be19ce0adf5ba6c 100644 (file)
@@ -864,13 +864,13 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
 
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-       tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT);
-       tmp |= RADEON_RB2D_DC_FLUSH_ALL;
-       RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp);
+       tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
+       tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+       RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
 
        for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT)
-                     & RADEON_RB2D_DC_BUSY)) {
+               if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
+                     & RADEON_RB3D_DC_BUSY)) {
                        return 0;
                }
                DRM_UDELAY(1);
@@ -1130,7 +1130,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
                             | (dev_priv->fb_location >> 16));
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
                RADEON_WRITE(RADEON_MC_AGP_LOCATION,
                             (((dev_priv->gart_vm_start - 1 +
@@ -1158,7 +1158,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
        dev_priv->ring.tail = cur_read_ptr;
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
                             dev_priv->ring_rptr->offset
                             - dev->agp->base + dev_priv->gart_vm_start);
@@ -1258,6 +1258,13 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
                dev_priv->writeback_works = 0;
                DRM_INFO("writeback forced off\n");
        }
+
+       if (!dev_priv->writeback_works) {
+               /* Disable writeback to avoid unnecessary bus master transfer */
+               RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
+                            RADEON_RB_NO_UPDATE);
+               RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
+       }
 }
 
 /* Enable or disable PCI-E GART on the chip */
@@ -1295,7 +1302,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 {
        u32 tmp;
 
-       if (dev_priv->flags & CHIP_IS_PCIE) {
+       if (dev_priv->flags & RADEON_IS_PCIE) {
                radeon_set_pciegart(dev_priv, on);
                return;
        }
@@ -1333,20 +1340,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        DRM_DEBUG("\n");
 
        /* if we require new memory map but we don't have it fail */
-       if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap)
-       {
-               DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n");
+       if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
+               DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
                radeon_do_cleanup_cp(dev);
                return DRM_ERR(EINVAL);
        }
 
-       if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
-       {
+       if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
                DRM_DEBUG("Forcing AGP card to PCI mode\n");
-               dev_priv->flags &= ~CHIP_IS_AGP;
+               dev_priv->flags &= ~RADEON_IS_AGP;
+       } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
+                  && !init->is_pci) {
+               DRM_DEBUG("Restoring AGP flag\n");
+               dev_priv->flags |= RADEON_IS_AGP;
        }
 
-       if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) {
+       if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
                DRM_ERROR("PCI GART memory not allocated!\n");
                radeon_do_cleanup_cp(dev);
                return DRM_ERR(EINVAL);
@@ -1489,7 +1498,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                                    init->sarea_priv_offset);
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                drm_core_ioremap(dev_priv->cp_ring, dev);
                drm_core_ioremap(dev_priv->ring_rptr, dev);
                drm_core_ioremap(dev->agp_buffer_map, dev);
@@ -1548,7 +1557,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                 * align it down.
                 */
 #if __OS_HAS_AGP
-               if (dev_priv->flags & CHIP_IS_AGP) {
+               if (dev_priv->flags & RADEON_IS_AGP) {
                        base = dev->agp->base;
                        /* Check if valid */
                        if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
@@ -1578,7 +1587,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        }
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP)
+       if (dev_priv->flags & RADEON_IS_AGP)
                dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
                                                 - dev->agp->base
                                                 + dev_priv->gart_vm_start);
@@ -1604,7 +1613,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                /* Turn off PCI GART */
                radeon_set_pcigart(dev_priv, 0);
        } else
@@ -1624,7 +1633,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                            dev_priv->gart_info.mapping.handle;
 
                        dev_priv->gart_info.is_pcie =
-                           !!(dev_priv->flags & CHIP_IS_PCIE);
+                           !!(dev_priv->flags & RADEON_IS_PCIE);
                        dev_priv->gart_info.gart_table_location =
                            DRM_ATI_GART_FB;
 
@@ -1636,7 +1645,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                            DRM_ATI_GART_MAIN;
                        dev_priv->gart_info.addr = NULL;
                        dev_priv->gart_info.bus_addr = 0;
-                       if (dev_priv->flags & CHIP_IS_PCIE) {
+                       if (dev_priv->flags & RADEON_IS_PCIE) {
                                DRM_ERROR
                                    ("Cannot use PCI Express without GART in FB memory\n");
                                radeon_do_cleanup_cp(dev);
@@ -1678,7 +1687,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
                drm_irq_uninstall(dev);
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                if (dev_priv->cp_ring != NULL) {
                        drm_core_ioremapfree(dev_priv->cp_ring, dev);
                        dev_priv->cp_ring = NULL;
@@ -1733,7 +1742,7 @@ static int radeon_do_resume_cp(drm_device_t * dev)
        DRM_DEBUG("Starting radeon_do_resume_cp()\n");
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                /* Turn off PCI GART */
                radeon_set_pcigart(dev_priv, 0);
        } else
@@ -2177,13 +2186,15 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        dev->dev_private = (void *)dev_priv;
        dev_priv->flags = flags;
 
-       switch (flags & CHIP_FAMILY_MASK) {
+       switch (flags & RADEON_FAMILY_MASK) {
        case CHIP_R100:
        case CHIP_RV200:
        case CHIP_R200:
        case CHIP_R300:
+       case CHIP_R350:
        case CHIP_R420:
-               dev_priv->flags |= CHIP_HAS_HIERZ;
+       case CHIP_RV410:
+               dev_priv->flags |= RADEON_HAS_HIERZ;
                break;
        default:
                /* all other chips have no hierarchical z buffer */
@@ -2191,13 +2202,14 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        if (drm_device_is_agp(dev))
-               dev_priv->flags |= CHIP_IS_AGP;
-
-       if (drm_device_is_pcie(dev))
-               dev_priv->flags |= CHIP_IS_PCIE;
+               dev_priv->flags |= RADEON_IS_AGP;
+       else if (drm_device_is_pcie(dev))
+               dev_priv->flags |= RADEON_IS_PCIE;
+       else
+               dev_priv->flags |= RADEON_IS_PCI;
 
        DRM_DEBUG("%s card detected\n",
-                 ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));
+                 ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
        return ret;
 }
 
index eb985c2a31e96b3a81ac2ae3ef37357834cb2fb7..2eb652ec674578c97f24cf1ca6c40b0d58a4454e 100644 (file)
@@ -44,7 +44,7 @@ module_param_named(no_wb, radeon_no_wb, int, 0444);
 static int dri_library_name(struct drm_device *dev, char *buf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       int family = dev_priv->flags & CHIP_FAMILY_MASK;
+       int family = dev_priv->flags & RADEON_FAMILY_MASK;
 
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        (family < CHIP_R200) ? "radeon" :
index e5a256f5429c81c504d1ec15086caea2489c67cb..f45cd7f147a5ad97eaffd2aec313ed1d0fb4fe05 100644 (file)
@@ -133,15 +133,16 @@ enum radeon_cp_microcode_version {
  * Chip flags
  */
 enum radeon_chip_flags {
-       CHIP_FAMILY_MASK = 0x0000ffffUL,
-       CHIP_FLAGS_MASK = 0xffff0000UL,
-       CHIP_IS_MOBILITY = 0x00010000UL,
-       CHIP_IS_IGP = 0x00020000UL,
-       CHIP_SINGLE_CRTC = 0x00040000UL,
-       CHIP_IS_AGP = 0x00080000UL,
-       CHIP_HAS_HIERZ = 0x00100000UL,
-       CHIP_IS_PCIE = 0x00200000UL,
-       CHIP_NEW_MEMMAP = 0x00400000UL,
+       RADEON_FAMILY_MASK = 0x0000ffffUL,
+       RADEON_FLAGS_MASK = 0xffff0000UL,
+       RADEON_IS_MOBILITY = 0x00010000UL,
+       RADEON_IS_IGP = 0x00020000UL,
+       RADEON_SINGLE_CRTC = 0x00040000UL,
+       RADEON_IS_AGP = 0x00080000UL,
+       RADEON_HAS_HIERZ = 0x00100000UL,
+       RADEON_IS_PCIE = 0x00200000UL,
+       RADEON_NEW_MEMMAP = 0x00400000UL,
+       RADEON_IS_PCI = 0x00800000UL,
 };
 
 #define GET_RING_HEAD(dev_priv)        (dev_priv->writeback_works ? \
@@ -424,6 +425,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #define RADEON_RB3D_COLOROFFSET                0x1c40
 #define RADEON_RB3D_COLORPITCH         0x1c48
 
+#define        RADEON_SRC_X_Y                  0x1590
+
 #define RADEON_DP_GUI_MASTER_CNTL      0x146c
 #      define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
 #      define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
@@ -441,6 +444,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #      define RADEON_ROP3_S                    0x00cc0000
 #      define RADEON_ROP3_P                    0x00f00000
 #define RADEON_DP_WRITE_MASK           0x16cc
+#define RADEON_SRC_PITCH_OFFSET                0x1428
 #define RADEON_DST_PITCH_OFFSET                0x142c
 #define RADEON_DST_PITCH_OFFSET_C      0x1c80
 #      define RADEON_DST_TILE_LINEAR           (0 << 30)
@@ -545,6 +549,11 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #      define RADEON_RB3D_ZC_FREE              (1 << 2)
 #      define RADEON_RB3D_ZC_FLUSH_ALL         0x5
 #      define RADEON_RB3D_ZC_BUSY              (1 << 31)
+#define RADEON_RB3D_DSTCACHE_CTLSTAT   0x325c
+#      define RADEON_RB3D_DC_FLUSH             (3 << 0)
+#      define RADEON_RB3D_DC_FREE              (3 << 2)
+#      define RADEON_RB3D_DC_FLUSH_ALL         0xf
+#      define RADEON_RB3D_DC_BUSY              (1 << 31)
 #define RADEON_RB3D_ZSTENCILCNTL       0x1c2c
 #      define RADEON_Z_TEST_MASK               (7 << 4)
 #      define RADEON_Z_TEST_ALWAYS             (7 << 4)
@@ -681,6 +690,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #define RADEON_CP_RB_BASE              0x0700
 #define RADEON_CP_RB_CNTL              0x0704
 #      define RADEON_BUF_SWAP_32BIT            (2 << 16)
+#      define RADEON_RB_NO_UPDATE              (1 << 27)
 #define RADEON_CP_RB_RPTR_ADDR         0x070c
 #define RADEON_CP_RB_RPTR              0x0710
 #define RADEON_CP_RB_WPTR              0x0714
@@ -986,13 +996,13 @@ do {                                                                      \
 } while (0)
 
 #define RADEON_FLUSH_CACHE() do {                                      \
-       OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );      \
-       OUT_RING( RADEON_RB2D_DC_FLUSH );                               \
+       OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) );      \
+       OUT_RING( RADEON_RB3D_DC_FLUSH );                               \
 } while (0)
 
 #define RADEON_PURGE_CACHE() do {                                      \
-       OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );      \
-       OUT_RING( RADEON_RB2D_DC_FLUSH_ALL );                           \
+       OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) );      \
+       OUT_RING( RADEON_RB3D_DC_FLUSH_ALL );                           \
 } while (0)
 
 #define RADEON_FLUSH_ZCACHE() do {                                     \
index 39a7f685e3fd7d5f0e3c4e98f58510258303069a..feac5f005d47be1d56d52819ff8074651ec87e7a 100644 (file)
@@ -42,7 +42,11 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
                                                    drm_file_t * filp_priv,
                                                    u32 *offset)
 {
-       u32 off = *offset;
+       u64 off = *offset;
+       u32 fb_start = dev_priv->fb_location;
+       u32 fb_end = fb_start + dev_priv->fb_size - 1;
+       u32 gart_start = dev_priv->gart_vm_start;
+       u32 gart_end = gart_start + dev_priv->gart_size - 1;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
        /* Hrm ... the story of the offset ... So this function converts
@@ -62,10 +66,8 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
        /* First, the best case, the offset already lands in either the
         * framebuffer or the GART mapped space
         */
-       if ((off >= dev_priv->fb_location &&
-            off < (dev_priv->fb_location + dev_priv->fb_size)) ||
-           (off >= dev_priv->gart_vm_start &&
-            off < (dev_priv->gart_vm_start + dev_priv->gart_size)))
+       if ((off >= fb_start && off <= fb_end) ||
+           (off >= gart_start && off <= gart_end))
                return 0;
 
        /* Ok, that didn't happen... now check if we have a zero based
@@ -78,16 +80,13 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
        }
 
        /* Finally, assume we aimed at a GART offset if beyond the fb */
-       if (off > (dev_priv->fb_location + dev_priv->fb_size))
-               off = off - (dev_priv->fb_location + dev_priv->fb_size) +
-                       dev_priv->gart_vm_start;
+       if (off > fb_end)
+               off = off - fb_end - 1 + gart_start;
 
        /* Now recheck and fail if out of bounds */
-       if ((off >= dev_priv->fb_location &&
-            off < (dev_priv->fb_location + dev_priv->fb_size)) ||
-           (off >= dev_priv->gart_vm_start &&
-            off < (dev_priv->gart_vm_start + dev_priv->gart_size))) {
-               DRM_DEBUG("offset fixed up to 0x%x\n", off);
+       if ((off >= fb_start && off <= fb_end) ||
+           (off >= gart_start && off <= gart_end)) {
+               DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
                *offset = off;
                return 0;
        }
@@ -869,7 +868,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                 */
                dev_priv->sarea_priv->ctx_owner = 0;
 
-               if ((dev_priv->flags & CHIP_HAS_HIERZ)
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
                    && (flags & RADEON_USE_HIERZ)) {
                        /* FIXME : reverse engineer that for Rx00 cards */
                        /* FIXME : the mask supposedly contains low-res z values. So can't set
@@ -914,7 +913,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                for (i = 0; i < nbox; i++) {
                        int tileoffset, nrtilesx, nrtilesy, j;
                        /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
-                       if ((dev_priv->flags & CHIP_HAS_HIERZ)
+                       if ((dev_priv->flags & RADEON_HAS_HIERZ)
                            && !(dev_priv->microcode_version == UCODE_R200)) {
                                /* FIXME : figure this out for r200 (when hierz is enabled). Or
                                   maybe r200 actually doesn't need to put the low-res z value into
@@ -998,7 +997,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
                }
 
                /* TODO don't always clear all hi-level z tiles */
-               if ((dev_priv->flags & CHIP_HAS_HIERZ)
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
                    && (dev_priv->microcode_version == UCODE_R200)
                    && (flags & RADEON_USE_HIERZ))
                        /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
@@ -1270,9 +1269,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
 
                DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
 
-               BEGIN_RING(7);
+               BEGIN_RING(9);
 
-               OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+               OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
                OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
                         RADEON_GMC_DST_PITCH_OFFSET_CNTL |
                         RADEON_GMC_BRUSH_NONE |
@@ -1284,6 +1283,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) {
                        OUT_RING(dev_priv->back_pitch_offset);
                        OUT_RING(dev_priv->front_pitch_offset);
@@ -1292,6 +1292,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
                        OUT_RING(dev_priv->back_pitch_offset);
                }
 
+               OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
                OUT_RING((x << 16) | y);
                OUT_RING((x << 16) | y);
                OUT_RING((w << 16) | h);
@@ -2987,16 +2988,21 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
        case RADEON_PARAM_GART_TEX_HANDLE:
                value = dev_priv->gart_textures_offset;
                break;
-       
+       case RADEON_PARAM_SCRATCH_OFFSET:
+               if (!dev_priv->writeback_works)
+                       return DRM_ERR(EINVAL);
+               value = RADEON_SCRATCH_REG_OFFSET;
+               break;
        case RADEON_PARAM_CARD_TYPE:
-               if (dev_priv->flags & CHIP_IS_PCIE)
+               if (dev_priv->flags & RADEON_IS_PCIE)
                        value = RADEON_CARD_PCIE;
-               else if (dev_priv->flags & CHIP_IS_AGP)
+               else if (dev_priv->flags & RADEON_IS_AGP)
                        value = RADEON_CARD_AGP;
                else
                        value = RADEON_CARD_PCI;
                break;
        default:
+               DRM_DEBUG("Invalid parameter %d\n", param.param);
                return DRM_ERR(EINVAL);
        }
 
index 5e9dc86f2956f5ed93683ca618f375b9917e03b2..3d5b3218b6ff02fa5da3e377276be76174692151 100644 (file)
@@ -35,11 +35,44 @@ static struct pci_device_id pciidlist[] = {
        sisdrv_PCI_IDS
 };
 
+static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+       drm_sis_private_t *dev_priv;
+       int ret;
+
+       dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return DRM_ERR(ENOMEM);
+
+       dev->dev_private = (void *)dev_priv;
+       dev_priv->chipset = chipset;
+       ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
+       if (ret) {
+               drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER);
+       }
+
+       return ret;
+}
+
+static int sis_driver_unload(drm_device_t *dev)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+
+       drm_sman_takedown(&dev_priv->sman);
+       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+
+       return 0;
+}
+
 static struct drm_driver driver = {
        .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
-       .context_ctor = sis_init_context,
-       .context_dtor = sis_final_context,
-       .reclaim_buffers = drm_core_reclaim_buffers,
+       .load = sis_driver_load,
+       .unload = sis_driver_unload,
+       .context_dtor = NULL,
+       .dma_quiescent = sis_idle,
+       .reclaim_buffers = NULL,
+       .reclaim_buffers_locked = sis_reclaim_buffers_locked,
+       .lastclose = sis_lastclose,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
        .ioctls = sis_ioctls,
index e218e5269503b80ff65d6127b249ba88baf79bab..2b8d6f6ed7c013adfb3affb0850a0c39e4276473 100644 (file)
 /* General customization:
  */
 
-#define DRIVER_AUTHOR          "SIS"
+#define DRIVER_AUTHOR          "SIS, Tungsten Graphics"
 #define DRIVER_NAME            "sis"
 #define DRIVER_DESC            "SIS 300/630/540"
-#define DRIVER_DATE            "20030826"
+#define DRIVER_DATE            "20060704"
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      0
+#define DRIVER_MINOR           2
+#define DRIVER_PATCHLEVEL      1
 
-#include "sis_ds.h"
+enum sis_family {
+       SIS_OTHER = 0,
+       SIS_CHIP_315 = 1,
+};
+
+#include "drm_sman.h"
+
+#define SIS_BASE (dev_priv->mmio)
+#define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg);
+#define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
 
 typedef struct drm_sis_private {
-       memHeap_t *AGPHeap;
-       memHeap_t *FBHeap;
+       drm_local_map_t *mmio;
+       unsigned int idle_fault;
+       drm_sman_t sman;
+       unsigned int chipset;
+       int vram_initialized;
+       int agp_initialized;
+       unsigned long vram_offset;
+       unsigned long agp_offset;
 } drm_sis_private_t;
 
-extern int sis_init_context(drm_device_t * dev, int context);
-extern int sis_final_context(drm_device_t * dev, int context);
+extern int sis_idle(drm_device_t *dev);
+extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
+extern void sis_lastclose(drm_device_t *dev);
 
 extern drm_ioctl_desc_t sis_ioctls[];
 extern int sis_max_ioctl;
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
deleted file mode 100644 (file)
index 2e485d4..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
- *
- * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Sung-Ching Lin <sclin@sis.com.tw>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "sis_ds.h"
-
-/* Set Data Structure, not check repeated value
- * temporarily used
- */
-
-set_t *setInit(void)
-{
-       int i;
-       set_t *set;
-
-       set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
-       if (set != NULL) {
-               for (i = 0; i < SET_SIZE; i++) {
-                       set->list[i].free_next = i + 1;
-                       set->list[i].alloc_next = -1;
-               }
-               set->list[SET_SIZE - 1].free_next = -1;
-               set->free = 0;
-               set->alloc = -1;
-               set->trace = -1;
-       }
-       return set;
-}
-
-int setAdd(set_t * set, ITEM_TYPE item)
-{
-       int free = set->free;
-
-       if (free != -1) {
-               set->list[free].val = item;
-               set->free = set->list[free].free_next;
-       } else {
-               return 0;
-       }
-
-       set->list[free].alloc_next = set->alloc;
-       set->alloc = free;
-       set->list[free].free_next = -1;
-
-       return 1;
-}
-
-int setDel(set_t * set, ITEM_TYPE item)
-{
-       int alloc = set->alloc;
-       int prev = -1;
-
-       while (alloc != -1) {
-               if (set->list[alloc].val == item) {
-                       if (prev != -1)
-                               set->list[prev].alloc_next =
-                                   set->list[alloc].alloc_next;
-                       else
-                               set->alloc = set->list[alloc].alloc_next;
-                       break;
-               }
-               prev = alloc;
-               alloc = set->list[alloc].alloc_next;
-       }
-
-       if (alloc == -1)
-               return 0;
-
-       set->list[alloc].free_next = set->free;
-       set->free = alloc;
-       set->list[alloc].alloc_next = -1;
-
-       return 1;
-}
-
-/* setFirst -> setAdd -> setNext is wrong */
-
-int setFirst(set_t * set, ITEM_TYPE * item)
-{
-       if (set->alloc == -1)
-               return 0;
-
-       *item = set->list[set->alloc].val;
-       set->trace = set->list[set->alloc].alloc_next;
-
-       return 1;
-}
-
-int setNext(set_t * set, ITEM_TYPE * item)
-{
-       if (set->trace == -1)
-               return 0;
-
-       *item = set->list[set->trace].val;
-       set->trace = set->list[set->trace].alloc_next;
-
-       return 1;
-}
-
-int setDestroy(set_t * set)
-{
-       drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
-
-       return 1;
-}
-
-/*
- * GLX Hardware Device Driver common code
- * Copyright (C) 1999 Wittawat Yamwong
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#define ISFREE(bptr) ((bptr)->free)
-
-memHeap_t *mmInit(int ofs, int size)
-{
-       PMemBlock blocks;
-
-       if (size <= 0)
-               return NULL;
-
-       blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
-       if (blocks != NULL) {
-               blocks->ofs = ofs;
-               blocks->size = size;
-               blocks->free = 1;
-               return (memHeap_t *) blocks;
-       } else
-               return NULL;
-}
-
-/* Checks if a pointer 'b' is part of the heap 'heap' */
-int mmBlockInHeap(memHeap_t * heap, PMemBlock b)
-{
-       TMemBlock *p;
-
-       if (heap == NULL || b == NULL)
-               return 0;
-
-       p = heap;
-       while (p != NULL && p != b) {
-               p = p->next;
-       }
-       if (p == b)
-               return 1;
-       else
-               return 0;
-}
-
-static TMemBlock *SliceBlock(TMemBlock * p,
-                            int startofs, int size,
-                            int reserved, int alignment)
-{
-       TMemBlock *newblock;
-
-       /* break left */
-       if (startofs > p->ofs) {
-               newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
-                                                   DRM_MEM_DRIVER);
-               newblock->ofs = startofs;
-               newblock->size = p->size - (startofs - p->ofs);
-               newblock->free = 1;
-               newblock->next = p->next;
-               p->size -= newblock->size;
-               p->next = newblock;
-               p = newblock;
-       }
-
-       /* break right */
-       if (size < p->size) {
-               newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
-                                                   DRM_MEM_DRIVER);
-               newblock->ofs = startofs + size;
-               newblock->size = p->size - size;
-               newblock->free = 1;
-               newblock->next = p->next;
-               p->size = size;
-               p->next = newblock;
-       }
-
-       /* p = middle block */
-       p->align = alignment;
-       p->free = 0;
-       p->reserved = reserved;
-       return p;
-}
-
-PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
-{
-       int mask, startofs, endofs;
-       TMemBlock *p;
-
-       if (heap == NULL || align2 < 0 || size <= 0)
-               return NULL;
-
-       mask = (1 << align2) - 1;
-       startofs = 0;
-       p = (TMemBlock *) heap;
-       while (p != NULL) {
-               if (ISFREE(p)) {
-                       startofs = (p->ofs + mask) & ~mask;
-                       if (startofs < startSearch) {
-                               startofs = startSearch;
-                       }
-                       endofs = startofs + size;
-                       if (endofs <= (p->ofs + p->size))
-                               break;
-               }
-               p = p->next;
-       }
-       if (p == NULL)
-               return NULL;
-       p = SliceBlock(p, startofs, size, 0, mask + 1);
-       p->heap = heap;
-       return p;
-}
-
-static __inline__ int Join2Blocks(TMemBlock * p)
-{
-       if (p->free && p->next && p->next->free) {
-               TMemBlock *q = p->next;
-               p->size += q->size;
-               p->next = q->next;
-               drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
-               return 1;
-       }
-       return 0;
-}
-
-int mmFreeMem(PMemBlock b)
-{
-       TMemBlock *p, *prev;
-
-       if (b == NULL)
-               return 0;
-       if (b->heap == NULL)
-               return -1;
-
-       p = b->heap;
-       prev = NULL;
-       while (p != NULL && p != b) {
-               prev = p;
-               p = p->next;
-       }
-       if (p == NULL || p->free || p->reserved)
-               return -1;
-
-       p->free = 1;
-       Join2Blocks(p);
-       if (prev)
-               Join2Blocks(prev);
-       return 0;
-}
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
deleted file mode 100644 (file)
index 94f2b47..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- 
- * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
- */
-/*
- * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Sung-Ching Lin <sclin@sis.com.tw>
- *
- */
-
-#ifndef __SIS_DS_H__
-#define __SIS_DS_H__
-
-/* Set Data Structure */
-
-#define SET_SIZE 5000
-
-typedef unsigned long ITEM_TYPE;
-
-typedef struct {
-       ITEM_TYPE val;
-       int alloc_next, free_next;
-} list_item_t;
-
-typedef struct {
-       int alloc;
-       int free;
-       int trace;
-       list_item_t list[SET_SIZE];
-} set_t;
-
-set_t *setInit(void);
-int setAdd(set_t * set, ITEM_TYPE item);
-int setDel(set_t * set, ITEM_TYPE item);
-int setFirst(set_t * set, ITEM_TYPE * item);
-int setNext(set_t * set, ITEM_TYPE * item);
-int setDestroy(set_t * set);
-
-/*
- * GLX Hardware Device Driver common code
- * Copyright (C) 1999 Wittawat Yamwong
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-struct mem_block_t {
-       struct mem_block_t *next;
-       struct mem_block_t *heap;
-       int ofs, size;
-       int align;
-       unsigned int free:1;
-       unsigned int reserved:1;
-};
-typedef struct mem_block_t TMemBlock;
-typedef struct mem_block_t *PMemBlock;
-
-/* a heap is just the first block in a chain */
-typedef struct mem_block_t memHeap_t;
-
-static __inline__ int mmBlockSize(PMemBlock b)
-{
-       return b->size;
-}
-
-static __inline__ int mmOffset(PMemBlock b)
-{
-       return b->ofs;
-}
-
-static __inline__ void mmMarkReserved(PMemBlock b)
-{
-       b->reserved = 1;
-}
-
-/*
- * input: total size in bytes
- * return: a heap pointer if OK, NULL if error
- */
-memHeap_t *mmInit(int ofs, int size);
-
-/*
- * Allocate 'size' bytes with 2^align2 bytes alignment,
- * restrict the search to free memory after 'startSearch'
- * depth and back buffers should be in different 4mb banks
- * to get better page hits if possible
- * input:      size = size of block
- *             align2 = 2^align2 bytes alignment
- *             startSearch = linear offset from start of heap to begin search
- * return: pointer to the allocated block, 0 if error
- */
-PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch);
-
-/*
- * Returns 1 if the block 'b' is part of the heap 'heap'
- */
-int mmBlockInHeap(PMemBlock heap, PMemBlock b);
-
-/*
- * Free block starts at offset
- * input: pointer to a block
- * return: 0 if OK, -1 if error
- */
-int mmFreeMem(PMemBlock b);
-
-/* For debuging purpose. */
-void mmDumpMemInfo(memHeap_t * mmInit);
-
-#endif                         /* __SIS_DS_H__ */
index 5e9936bc307fc21d7a321fae5e1ce2377182aee6..d26f5dbb78538ea4532c7f79965fdd91aefd3fd1 100644 (file)
-/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+/**************************************************************************
  *
- * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
- * All rights reserved.
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
+ * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
  *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
- * Authors:
- *    Sung-Ching Lin <sclin@sis.com.tw>
  *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *    Thomas Hellström <thomas-at-tungstengraphics-dot-com>
  */
 
 #include "drmP.h"
 #include "sis_drm.h"
 #include "sis_drv.h"
-#include "sis_ds.h"
-#if defined(__linux__) && defined(CONFIG_FB_SIS)
+
 #include <video/sisfb.h>
-#endif
 
-#define MAX_CONTEXT 100
 #define VIDEO_TYPE 0
 #define AGP_TYPE 1
 
-typedef struct {
-       int used;
-       int context;
-       set_t *sets[2];         /* 0 for video, 1 for AGP */
-} sis_context_t;
 
-static sis_context_t global_ppriv[MAX_CONTEXT];
+#if defined(CONFIG_FB_SIS)
+/* fb management via fb device */
 
-static int add_alloc_set(int context, int type, unsigned int val)
-{
-       int i, retval = 0;
+#define SIS_MM_ALIGN_SHIFT 0
+#define SIS_MM_ALIGN_MASK 0
 
-       for (i = 0; i < MAX_CONTEXT; i++) {
-               if (global_ppriv[i].used && global_ppriv[i].context == context) {
-                       retval = setAdd(global_ppriv[i].sets[type], val);
-                       break;
-               }
-       }
-       return retval;
-}
-
-static int del_alloc_set(int context, int type, unsigned int val)
+static void *sis_sman_mm_allocate(void *private, unsigned long size,
+                                 unsigned alignment)
 {
-       int i, retval = 0;
+       struct sis_memreq req;
 
-       for (i = 0; i < MAX_CONTEXT; i++) {
-               if (global_ppriv[i].used && global_ppriv[i].context == context) {
-                       retval = setDel(global_ppriv[i].sets[type], val);
-                       break;
-               }
-       }
-       return retval;
+       req.size = size;
+       sis_malloc(&req);
+       if (req.size == 0)
+               return NULL;
+       else
+               return (void *)~req.offset;
 }
 
-/* fb management via fb device */
-#if defined(__linux__) && defined(CONFIG_FB_SIS)
-
-static int sis_fb_init(DRM_IOCTL_ARGS)
+static void sis_sman_mm_free(void *private, void *ref)
 {
-       return 0;
+       sis_free(~((unsigned long)ref));
 }
 
-static int sis_fb_alloc(DRM_IOCTL_ARGS)
+static void sis_sman_mm_destroy(void *private)
 {
-       drm_sis_mem_t fb;
-       struct sis_memreq req;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
-       int retval = 0;
-
-       DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
-
-       req.size = fb.size;
-       sis_malloc(&req);
-       if (req.offset) {
-               /* TODO */
-               fb.offset = req.offset;
-               fb.free = req.offset;
-               if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
-                       DRM_DEBUG("adding to allocation set fails\n");
-                       sis_free(req.offset);
-                       retval = DRM_ERR(EINVAL);
-               }
-       } else {
-               fb.offset = 0;
-               fb.size = 0;
-               fb.free = 0;
-       }
-
-       DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
-
-       DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
-
-       return retval;
+       ;
 }
 
-static int sis_fb_free(DRM_IOCTL_ARGS)
+static unsigned long sis_sman_mm_offset(void *private, void *ref)
 {
-       drm_sis_mem_t fb;
-       int retval = 0;
-
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
-
-       if (!fb.free)
-               return DRM_ERR(EINVAL);
+       return ~((unsigned long)ref);
+}
 
-       if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
-               retval = DRM_ERR(EINVAL);
-       sis_free(fb.free);
+#else /* CONFIG_FB_SIS */
 
-       DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
+#define SIS_MM_ALIGN_SHIFT 4
+#define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
 
-       return retval;
-}
+#endif /* CONFIG_FB_SIS */
 
-#else
-
-/* Called by the X Server to initialize the FB heap.  Allocations will fail
- * unless this is called.  Offset is the beginning of the heap from the
- * framebuffer offset (MaxXFBMem in XFree86).
- *
- * Memory layout according to Thomas Winischofer:
- * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
- *
- *    X driver/sisfb                                  HW-   Command-
- *  framebuffer memory           DRI heap           Cursor   queue
- */
 static int sis_fb_init(DRM_IOCTL_ARGS)
 {
        DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
        drm_sis_fb_t fb;
+       int ret;
 
        DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
 
-       if (dev_priv == NULL) {
-               dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
-                                             DRM_MEM_DRIVER);
-               dev_priv = dev->dev_private;
-               if (dev_priv == NULL)
-                       return ENOMEM;
+       mutex_lock(&dev->struct_mutex);
+#if defined(CONFIG_FB_SIS)
+       {
+               drm_sman_mm_t sman_mm;
+               sman_mm.private = (void *)0xFFFFFFFF;
+               sman_mm.allocate = sis_sman_mm_allocate;
+               sman_mm.free = sis_sman_mm_free;
+               sman_mm.destroy = sis_sman_mm_destroy;
+               sman_mm.offset = sis_sman_mm_offset;
+               ret =
+                   drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
        }
+#else
+       ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
+                                fb.size >> SIS_MM_ALIGN_SHIFT);
+#endif
 
-       if (dev_priv->FBHeap != NULL)
-               return DRM_ERR(EINVAL);
+       if (ret) {
+               DRM_ERROR("VRAM memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
 
-       dev_priv->FBHeap = mmInit(fb.offset, fb.size);
+       dev_priv->vram_initialized = 1;
+       dev_priv->vram_offset = fb.offset;
 
+       mutex_unlock(&dev->struct_mutex);
        DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
 
        return 0;
 }
 
-static int sis_fb_alloc(DRM_IOCTL_ARGS)
+static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
+                        unsigned long data, int pool)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
-       drm_sis_mem_t fb;
-       PMemBlock block;
+       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
+       drm_sis_mem_t mem;
        int retval = 0;
+       drm_memblock_item_t *item;
+
+       DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
 
-       if (dev_priv == NULL || dev_priv->FBHeap == NULL)
+       mutex_lock(&dev->struct_mutex);
+
+       if (0 == ((pool == 0) ? dev_priv->vram_initialized :
+                     dev_priv->agp_initialized)) {
+               DRM_ERROR
+                   ("Attempt to allocate from uninitialized memory manager.\n");
                return DRM_ERR(EINVAL);
+       }
 
-       DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
-
-       block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
-       if (block) {
-               /* TODO */
-               fb.offset = block->ofs;
-               fb.free = (unsigned long)block;
-               if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
-                       DRM_DEBUG("adding to allocation set fails\n");
-                       mmFreeMem((PMemBlock) fb.free);
-                       retval = DRM_ERR(EINVAL);
-               }
+       mem.size = (mem.size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
+       item = drm_sman_alloc(&dev_priv->sman, pool, mem.size, 0,
+                             (unsigned long)priv);
+
+       mutex_unlock(&dev->struct_mutex);
+       if (item) {
+               mem.offset = ((pool == 0) ?
+                             dev_priv->vram_offset : dev_priv->agp_offset) +
+                   (item->mm->
+                    offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
+               mem.free = item->user_hash.key;
+               mem.size = mem.size << SIS_MM_ALIGN_SHIFT;
        } else {
-               fb.offset = 0;
-               fb.size = 0;
-               fb.free = 0;
+               mem.offset = 0;
+               mem.size = 0;
+               mem.free = 0;
+               retval = DRM_ERR(ENOMEM);
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
+       DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem));
 
-       DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
+       DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size,
+                 mem.offset);
 
        return retval;
 }
 
-static int sis_fb_free(DRM_IOCTL_ARGS)
+static int sis_drm_free(DRM_IOCTL_ARGS)
 {
        DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t fb;
+       drm_sis_mem_t mem;
+       int ret;
 
-       if (dev_priv == NULL || dev_priv->FBHeap == NULL)
-               return DRM_ERR(EINVAL);
+       DRM_COPY_FROM_USER_IOCTL(mem, (drm_sis_mem_t __user *) data,
+                                sizeof(mem));
 
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_free_key(&dev_priv->sman, mem.free);
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("free = 0x%lx\n", mem.free);
 
-       if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
-               return DRM_ERR(EINVAL);
-
-       if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
-               return DRM_ERR(EINVAL);
-       mmFreeMem((PMemBlock) fb.free);
-
-       DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
-
-       return 0;
+       return ret;
 }
 
-#endif
-
-/* agp memory management */
+static int sis_fb_alloc(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       return sis_drm_alloc(dev, priv, data, VIDEO_TYPE);
+}
 
 static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
 {
        DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
        drm_sis_agp_t agp;
-
-       if (dev_priv == NULL) {
-               dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
-                                             DRM_MEM_DRIVER);
-               dev_priv = dev->dev_private;
-               if (dev_priv == NULL)
-                       return ENOMEM;
-       }
-
-       if (dev_priv->AGPHeap != NULL)
-               return DRM_ERR(EINVAL);
+       int ret;
+       dev_priv = dev->dev_private;
 
        DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
                                 sizeof(agp));
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
+                                agp.size >> SIS_MM_ALIGN_SHIFT);
+
+       if (ret) {
+               DRM_ERROR("AGP memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
 
-       dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
+       dev_priv->agp_initialized = 1;
+       dev_priv->agp_offset = agp.offset;
+       mutex_unlock(&dev->struct_mutex);
 
        DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
-
        return 0;
 }
 
 static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
 {
        DRM_DEVICE;
-       drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
-       drm_sis_mem_t agp;
-       PMemBlock block;
-       int retval = 0;
 
-       if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
-               return DRM_ERR(EINVAL);
+       return sis_drm_alloc(dev, priv, data, AGP_TYPE);
+}
 
-       DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
-
-       block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
-       if (block) {
-               /* TODO */
-               agp.offset = block->ofs;
-               agp.free = (unsigned long)block;
-               if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
-                       DRM_DEBUG("adding to allocation set fails\n");
-                       mmFreeMem((PMemBlock) agp.free);
-                       retval = -1;
+static drm_local_map_t *sis_reg_init(drm_device_t *dev)
+{
+       drm_map_list_t *entry;
+       drm_local_map_t *map;
+
+       list_for_each_entry(entry, &dev->maplist->head, head) {
+               map = entry->map;
+               if (!map)
+                       continue;
+               if (map->type == _DRM_REGISTERS) {
+                       return map;
                }
-       } else {
-               agp.offset = 0;
-               agp.size = 0;
-               agp.free = 0;
        }
-
-       DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
-
-       DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
-
-       return retval;
+       return NULL;
 }
 
-static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
+int sis_idle(drm_device_t *dev)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t agp;
-
-       if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
-               return DRM_ERR(EINVAL);
+       uint32_t idle_reg;
+       unsigned long end;
+       int i;
 
-       DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
-                                sizeof(agp));
+       if (dev_priv->idle_fault)
+               return 0;
 
-       if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
-               return DRM_ERR(EINVAL);
+       if (dev_priv->mmio == NULL) {
+               dev_priv->mmio = sis_reg_init(dev);
+               if (dev_priv->mmio == NULL) {
+                       DRM_ERROR("Could not find register map.\n");
+                       return 0;
+               }
+       }
+       
+       /*
+        * Implement a device switch here if needed
+        */
+
+       if (dev_priv->chipset != SIS_CHIP_315)
+               return 0;
+
+       /*
+        * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
+        * because its polling frequency is too low.
+        */
+
+       end = jiffies + (DRM_HZ * 3);
+
+       for (i=0; i<4; ++i) {
+               do {
+                       idle_reg = SIS_READ(0x85cc);
+               } while ( !time_after_eq(jiffies, end) &&
+                         ((idle_reg & 0x80000000) != 0x80000000));
+       }
 
-       mmFreeMem((PMemBlock) agp.free);
-       if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
-               return DRM_ERR(EINVAL);
+       if (time_after_eq(jiffies, end)) {
+               DRM_ERROR("Graphics engine idle timeout. "
+                         "Disabling idle check\n");
+               dev_priv->idle_fault = 1;
+       }
 
-       DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
+       /*
+        * The caller never sees an error code. It gets trapped
+        * in libdrm.
+        */
 
        return 0;
 }
 
-int sis_init_context(struct drm_device *dev, int context)
-{
-       int i;
 
-       for (i = 0; i < MAX_CONTEXT; i++) {
-               if (global_ppriv[i].used &&
-                   (global_ppriv[i].context == context))
-                       break;
-       }
+void sis_lastclose(struct drm_device *dev)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
 
-       if (i >= MAX_CONTEXT) {
-               for (i = 0; i < MAX_CONTEXT; i++) {
-                       if (!global_ppriv[i].used) {
-                               global_ppriv[i].context = context;
-                               global_ppriv[i].used = 1;
-                               global_ppriv[i].sets[0] = setInit();
-                               global_ppriv[i].sets[1] = setInit();
-                               DRM_DEBUG("init allocation set, socket=%d, "
-                                         "context = %d\n", i, context);
-                               break;
-                       }
-               }
-               if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
-                   (global_ppriv[i].sets[1] == NULL)) {
-                       return 0;
-               }
-       }
+       if (!dev_priv)
+               return;
 
-       return 1;
+       mutex_lock(&dev->struct_mutex);
+       drm_sman_cleanup(&dev_priv->sman);
+       dev_priv->vram_initialized = 0;
+       dev_priv->agp_initialized = 0;
+       dev_priv->mmio = NULL;
+       mutex_unlock(&dev->struct_mutex);
 }
 
-int sis_final_context(struct drm_device *dev, int context)
+void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
 {
-       int i;
+       drm_sis_private_t *dev_priv = dev->dev_private;
+       drm_file_t *priv = filp->private_data;
 
-       for (i = 0; i < MAX_CONTEXT; i++) {
-               if (global_ppriv[i].used &&
-                   (global_ppriv[i].context == context))
-                       break;
+       mutex_lock(&dev->struct_mutex);
+       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
+               mutex_unlock(&dev->struct_mutex);
+               return;
        }
 
-       if (i < MAX_CONTEXT) {
-               set_t *set;
-               ITEM_TYPE item;
-               int retval;
-
-               DRM_DEBUG("find socket %d, context = %d\n", i, context);
-
-               /* Video Memory */
-               set = global_ppriv[i].sets[0];
-               retval = setFirst(set, &item);
-               while (retval) {
-                       DRM_DEBUG("free video memory 0x%lx\n", item);
-#if defined(__linux__) && defined(CONFIG_FB_SIS)
-                       sis_free(item);
-#else
-                       mmFreeMem((PMemBlock) item);
-#endif
-                       retval = setNext(set, &item);
-               }
-               setDestroy(set);
-
-               /* AGP Memory */
-               set = global_ppriv[i].sets[1];
-               retval = setFirst(set, &item);
-               while (retval) {
-                       DRM_DEBUG("free agp memory 0x%lx\n", item);
-                       mmFreeMem((PMemBlock) item);
-                       retval = setNext(set, &item);
-               }
-               setDestroy(set);
-
-               global_ppriv[i].used = 0;
+       if (dev->driver->dma_quiescent) {
+               dev->driver->dma_quiescent(dev);
        }
 
-       return 1;
+       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
+       mutex_unlock(&dev->struct_mutex);
+       return;
 }
 
 drm_ioctl_desc_t sis_ioctls[] = {
        [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_drm_free, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] =
+           {sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
+       [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_drm_free, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] =
+           {sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}
 };
 
 int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
index 78a81a4a99c5c60fda46b05497351e211d94df1f..60c1695db3000e3611af463374ee0fd388439b07 100644 (file)
@@ -41,9 +41,9 @@
 
 #include <linux/pagemap.h>
 
-#define VIA_PGDN(x)             (((unsigned long)(x)) & PAGE_MASK)
-#define VIA_PGOFF(x)            (((unsigned long)(x)) & ~PAGE_MASK)
-#define VIA_PFN(x)              ((unsigned long)(x) >> PAGE_SHIFT)
+#define VIA_PGDN(x)         (((unsigned long)(x)) & PAGE_MASK)
+#define VIA_PGOFF(x)       (((unsigned long)(x)) & ~PAGE_MASK)
+#define VIA_PFN(x)           ((unsigned long)(x) >> PAGE_SHIFT)
 
 typedef struct _drm_via_descriptor {
        uint32_t mem_addr;
@@ -121,19 +121,19 @@ via_map_blit_for_device(struct pci_dev *pdev,
                
                while (line_len > 0) {
 
-                        remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
+                       remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
                        line_len -= remaining_len;
 
                        if (mode == 1) {
-                                desc_ptr->mem_addr = 
+                               desc_ptr->mem_addr = 
                                        dma_map_page(&pdev->dev, 
                                                     vsg->pages[VIA_PFN(cur_mem) - 
                                                                VIA_PFN(first_addr)],
                                                     VIA_PGOFF(cur_mem), remaining_len, 
                                                     vsg->direction);
-                                desc_ptr->dev_addr = cur_fb;
+                               desc_ptr->dev_addr = cur_fb;
                                
-                                desc_ptr->size = remaining_len;
+                               desc_ptr->size = remaining_len;
                                desc_ptr->next = (uint32_t) next;
                                next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), 
                                                      DMA_TO_DEVICE);
@@ -162,7 +162,7 @@ via_map_blit_for_device(struct pci_dev *pdev,
 
 /*
  * Function that frees up all resources for a blit. It is usable even if the 
- * blit info has only be partially built as long as the status enum is consistent
+ * blit info has only been partially built as long as the status enum is consistent
  * with the actual status of the used resources.
  */
 
@@ -238,8 +238,11 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
                return DRM_ERR(ENOMEM);
        memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
        down_read(&current->mm->mmap_sem);
-       ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr,
-                            vsg->num_pages, vsg->direction, 0, vsg->pages, NULL);
+       ret = get_user_pages(current, current->mm,
+                            (unsigned long)xfer->mem_addr,
+                            vsg->num_pages,
+                            (vsg->direction == DMA_FROM_DEVICE),
+                            0, vsg->pages, NULL);
 
        up_read(&current->mm->mmap_sem);
        if (ret != vsg->num_pages) {
@@ -475,9 +478,15 @@ via_dmablit_timer(unsigned long data)
        if (!timer_pending(&blitq->poll_timer)) {
                blitq->poll_timer.expires = jiffies+1;
                add_timer(&blitq->poll_timer);
-       }
-       via_dmablit_handler(dev, engine, 0);
 
+              /*
+               * Rerun handler to delete timer if engines are off, and
+               * to shorten abort latency. This is a little nasty.
+               */
+
+              via_dmablit_handler(dev, engine, 0);
+
+       }
 }
 
 
@@ -597,15 +606,27 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
         * (Not a big limitation anyway.)
         */
 
-       if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) ||
-           (xfer->mem_stride > 2048*4)) {
+       if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) {
                DRM_ERROR("Too large system memory stride. Stride: %d, "
                          "Length: %d\n", xfer->mem_stride, xfer->line_length);
                return DRM_ERR(EINVAL);
        }
 
-       if (xfer->num_lines > 2048) {
-               DRM_ERROR("Too many PCI DMA bitblt lines.\n");
+       if ((xfer->mem_stride == xfer->line_length) &&
+          (xfer->fb_stride == xfer->line_length)) {
+               xfer->mem_stride *= xfer->num_lines;
+               xfer->line_length = xfer->mem_stride;
+               xfer->fb_stride = xfer->mem_stride;
+               xfer->num_lines = 1;
+       }
+
+       /*
+        * Don't lock an arbitrary large number of pages, since that causes a
+        * DOS security hole.
+        */
+
+       if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
+               DRM_ERROR("Too large PCI DMA bitblt.\n");
                return DRM_ERR(EINVAL);
        }               
 
@@ -628,16 +649,17 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
 
 #ifdef VIA_BUGFREE
        if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
-           ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) {
+           ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
                DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return DRM_ERR(EINVAL);
+               return DRM_ERR(EINVAL);
        }
 #else
        if ((((unsigned long)xfer->mem_addr & 15) ||
-           ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) ||
-           (xfer->fb_stride & 3)) {
+             ((unsigned long)xfer->fb_addr & 3)) ||
+          ((xfer->num_lines > 1) && 
+          ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
                DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return DRM_ERR(EINVAL);
+               return DRM_ERR(EINVAL);
        }       
 #endif
 
@@ -715,7 +737,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
        drm_via_sg_info_t *vsg;
        drm_via_blitq_t *blitq;
-        int ret;
+       int ret;
        int engine;
        unsigned long irqsave;
 
@@ -756,7 +778,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
 
 /*
  * Sync on a previously submitted blit. Note that the X server use signals extensively, and
- * that there is a very big proability that this IOCTL will be interrupted by a signal. In that
+ * that there is a very big probability that this IOCTL will be interrupted by a signal. In that
  * case it returns with -EAGAIN for the signal to be delivered. 
  * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
  */
index 47f0b5b26379522d1881ea95158c74283572c96b..e4ee97d7156ff2b322bcc0ecda06ad1eebbf8b49 100644 (file)
@@ -250,6 +250,12 @@ typedef struct drm_via_blitsync {
        unsigned engine;
 } drm_via_blitsync_t;
 
+/* - * Below,"flags" is currently unused but will be used for possible future
+ * extensions like kernel space bounce buffers for bad alignments and
+ * blit engine busy-wait polling for better latency in the absence of
+ * interrupts.
+ */
+
 typedef struct drm_via_dmablit {
        uint32_t num_lines;
        uint32_t line_length;
@@ -260,7 +266,7 @@ typedef struct drm_via_dmablit {
        unsigned char *mem_addr;
        uint32_t mem_stride;
 
-       int bounce_buffer;
+       uint32_t flags;
        int to_fb;
 
        drm_via_blitsync_t sync;
index b3d364d793d748bf06eeb9833fbada3b38dff0b0..bb9dde8b1911138445caf8cbf665f479dfc1fe42 100644 (file)
@@ -43,7 +43,6 @@ static struct drm_driver driver = {
            DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
        .load = via_driver_load,
        .unload = via_driver_unload,
-       .context_ctor = via_init_context,
        .context_dtor = via_final_context,
        .vblank_wait = via_driver_vblank_wait,
        .irq_preinstall = via_driver_irq_preinstall,
@@ -53,6 +52,8 @@ static struct drm_driver driver = {
        .dma_quiescent = via_driver_dma_quiescent,
        .dri_library_name = dri_library_name,
        .reclaim_buffers = drm_core_reclaim_buffers,
+       .reclaim_buffers_locked = via_reclaim_buffers_locked,
+       .lastclose = via_lastclose,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
        .ioctls = via_ioctls,
index 52bcc7b1ba4560065be1a85eb981b15e5a46aea8..d21b5b75da0fa944153fe1a7134670dd44f6606b 100644 (file)
 #ifndef _VIA_DRV_H_
 #define _VIA_DRV_H_
 
+#include "drm_sman.h"
 #define DRIVER_AUTHOR  "Various"
 
 #define DRIVER_NAME            "via"
 #define DRIVER_DESC            "VIA Unichrome / Pro"
-#define DRIVER_DATE            "20051116"
+#define DRIVER_DATE            "20060529"
 
 #define DRIVER_MAJOR           2
-#define DRIVER_MINOR           7
-#define DRIVER_PATCHLEVEL      4
+#define DRIVER_MINOR           10
+#define DRIVER_PATCHLEVEL      0
 
 #include "via_verifier.h"
 
@@ -85,6 +86,12 @@ typedef struct drm_via_private {
        uint32_t irq_enable_mask;
        uint32_t irq_pending_mask;
        int *irq_map;
+       unsigned int idle_fault;
+       drm_sman_t sman;
+       int vram_initialized;
+       int agp_initialized;
+       unsigned long vram_offset;
+       unsigned long agp_offset;
        drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
 } drm_via_private_t;
 
@@ -135,6 +142,9 @@ extern void via_init_futex(drm_via_private_t * dev_priv);
 extern void via_cleanup_futex(drm_via_private_t * dev_priv);
 extern void via_release_futex(drm_via_private_t * dev_priv, int context);
 
+extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
+extern void via_lastclose(drm_device_t *dev);
+
 extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
 extern void via_init_dmablit(drm_device_t *dev);
 
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
deleted file mode 100644 (file)
index 9429736..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include "drmP.h"
-
-#include "via_ds.h"
-extern unsigned int VIA_DEBUG;
-
-set_t *via_setInit(void)
-{
-       int i;
-       set_t *set;
-       set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
-       for (i = 0; i < SET_SIZE; i++) {
-               set->list[i].free_next = i + 1;
-               set->list[i].alloc_next = -1;
-       }
-       set->list[SET_SIZE - 1].free_next = -1;
-       set->free = 0;
-       set->alloc = -1;
-       set->trace = -1;
-       return set;
-}
-
-int via_setAdd(set_t * set, ITEM_TYPE item)
-{
-       int free = set->free;
-       if (free != -1) {
-               set->list[free].val = item;
-               set->free = set->list[free].free_next;
-       } else {
-               return 0;
-       }
-       set->list[free].alloc_next = set->alloc;
-       set->alloc = free;
-       set->list[free].free_next = -1;
-       return 1;
-}
-
-int via_setDel(set_t * set, ITEM_TYPE item)
-{
-       int alloc = set->alloc;
-       int prev = -1;
-
-       while (alloc != -1) {
-               if (set->list[alloc].val == item) {
-                       if (prev != -1)
-                               set->list[prev].alloc_next =
-                                   set->list[alloc].alloc_next;
-                       else
-                               set->alloc = set->list[alloc].alloc_next;
-                       break;
-               }
-               prev = alloc;
-               alloc = set->list[alloc].alloc_next;
-       }
-
-       if (alloc == -1)
-               return 0;
-
-       set->list[alloc].free_next = set->free;
-       set->free = alloc;
-       set->list[alloc].alloc_next = -1;
-
-       return 1;
-}
-
-/* setFirst -> setAdd -> setNext is wrong */
-
-int via_setFirst(set_t * set, ITEM_TYPE * item)
-{
-       if (set->alloc == -1)
-               return 0;
-
-       *item = set->list[set->alloc].val;
-       set->trace = set->list[set->alloc].alloc_next;
-
-       return 1;
-}
-
-int via_setNext(set_t * set, ITEM_TYPE * item)
-{
-       if (set->trace == -1)
-               return 0;
-
-       *item = set->list[set->trace].val;
-       set->trace = set->list[set->trace].alloc_next;
-
-       return 1;
-}
-
-int via_setDestroy(set_t * set)
-{
-       drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
-
-       return 1;
-}
-
-#define ISFREE(bptr) ((bptr)->free)
-
-#define fprintf(fmt, arg...) do{}while(0)
-
-memHeap_t *via_mmInit(int ofs, int size)
-{
-       PMemBlock blocks;
-
-       if (size <= 0)
-               return NULL;
-
-       blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
-
-       if (blocks) {
-               blocks->ofs = ofs;
-               blocks->size = size;
-               blocks->free = 1;
-               return (memHeap_t *) blocks;
-       } else
-               return NULL;
-}
-
-static TMemBlock *SliceBlock(TMemBlock * p,
-                            int startofs, int size,
-                            int reserved, int alignment)
-{
-       TMemBlock *newblock;
-
-       /* break left */
-       if (startofs > p->ofs) {
-               newblock =
-                   (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
-                                            DRM_MEM_DRIVER);
-               newblock->ofs = startofs;
-               newblock->size = p->size - (startofs - p->ofs);
-               newblock->free = 1;
-               newblock->next = p->next;
-               p->size -= newblock->size;
-               p->next = newblock;
-               p = newblock;
-       }
-
-       /* break right */
-       if (size < p->size) {
-               newblock =
-                   (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
-                                            DRM_MEM_DRIVER);
-               newblock->ofs = startofs + size;
-               newblock->size = p->size - size;
-               newblock->free = 1;
-               newblock->next = p->next;
-               p->size = size;
-               p->next = newblock;
-       }
-
-       /* p = middle block */
-       p->align = alignment;
-       p->free = 0;
-       p->reserved = reserved;
-       return p;
-}
-
-PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
-                        int startSearch)
-{
-       int mask, startofs, endofs;
-       TMemBlock *p;
-
-       if (!heap || align2 < 0 || size <= 0)
-               return NULL;
-
-       mask = (1 << align2) - 1;
-       startofs = 0;
-       p = (TMemBlock *) heap;
-
-       while (p) {
-               if (ISFREE(p)) {
-                       startofs = (p->ofs + mask) & ~mask;
-
-                       if (startofs < startSearch)
-                               startofs = startSearch;
-
-                       endofs = startofs + size;
-
-                       if (endofs <= (p->ofs + p->size))
-                               break;
-               }
-
-               p = p->next;
-       }
-
-       if (!p)
-               return NULL;
-
-       p = SliceBlock(p, startofs, size, 0, mask + 1);
-       p->heap = heap;
-
-       return p;
-}
-
-static __inline__ int Join2Blocks(TMemBlock * p)
-{
-       if (p->free && p->next && p->next->free) {
-               TMemBlock *q = p->next;
-               p->size += q->size;
-               p->next = q->next;
-               drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
-
-               return 1;
-       }
-
-       return 0;
-}
-
-int via_mmFreeMem(PMemBlock b)
-{
-       TMemBlock *p, *prev;
-
-       if (!b)
-               return 0;
-
-       if (!b->heap) {
-               fprintf(stderr, "no heap\n");
-
-               return -1;
-       }
-
-       p = b->heap;
-       prev = NULL;
-
-       while (p && p != b) {
-               prev = p;
-               p = p->next;
-       }
-
-       if (!p || p->free || p->reserved) {
-               if (!p)
-                       fprintf(stderr, "block not found in heap\n");
-               else if (p->free)
-                       fprintf(stderr, "block already free\n");
-               else
-                       fprintf(stderr, "block is reserved\n");
-
-               return -1;
-       }
-
-       p->free = 1;
-       Join2Blocks(p);
-
-       if (prev)
-               Join2Blocks(prev);
-
-       return 0;
-}
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h
deleted file mode 100644 (file)
index d2bb9f3..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef _via_ds_h_
-#define _via_ds_h_
-
-#include "drmP.h"
-
-/* Set Data Structure */
-#define SET_SIZE 5000
-typedef unsigned long ITEM_TYPE;
-
-typedef struct {
-       ITEM_TYPE val;
-       int alloc_next, free_next;
-} list_item_t;
-
-typedef struct {
-       int alloc;
-       int free;
-       int trace;
-       list_item_t list[SET_SIZE];
-} set_t;
-
-set_t *via_setInit(void);
-int via_setAdd(set_t * set, ITEM_TYPE item);
-int via_setDel(set_t * set, ITEM_TYPE item);
-int via_setFirst(set_t * set, ITEM_TYPE * item);
-int via_setNext(set_t * set, ITEM_TYPE * item);
-int via_setDestroy(set_t * set);
-
-#endif
-
-#ifndef MM_INC
-#define MM_INC
-
-struct mem_block_t {
-       struct mem_block_t *next;
-       struct mem_block_t *heap;
-       int ofs, size;
-       int align;
-       unsigned int free:1;
-       unsigned int reserved:1;
-};
-typedef struct mem_block_t TMemBlock;
-typedef struct mem_block_t *PMemBlock;
-
-/* a heap is just the first block in a chain */
-typedef struct mem_block_t memHeap_t;
-
-static __inline__ int mmBlockSize(PMemBlock b)
-{
-       return b->size;
-}
-
-static __inline__ int mmOffset(PMemBlock b)
-{
-       return b->ofs;
-}
-
-static __inline__ void mmMarkReserved(PMemBlock b)
-{
-       b->reserved = 1;
-}
-
-/*
- * input: total size in bytes
- * return: a heap pointer if OK, NULL if error
- */
-memHeap_t *via_mmInit(int ofs, int size);
-
-PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
-                        int startSearch);
-
-/*
- * Free block starts at offset
- * input: pointer to a block
- * return: 0 if OK, -1 if error
- */
-int via_mmFreeMem(PMemBlock b);
-
-#endif
index c6a08e96285bf55c62a96480c7989ea0632a7419..782011e0a58d49efb209593d0896dacd030cdde9 100644 (file)
@@ -98,6 +98,7 @@ int via_map_init(DRM_IOCTL_ARGS)
 int via_driver_load(drm_device_t *dev, unsigned long chipset)
 {
        drm_via_private_t *dev_priv;
+       int ret = 0;
 
        dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
@@ -108,13 +109,19 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset)
        if (chipset == VIA_PRO_GROUP_A)
                dev_priv->pro_group_a = 1;
 
-       return 0;
+       ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
+       if (ret) {
+               drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+       }
+       return ret;
 }
 
 int via_driver_unload(drm_device_t *dev)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
 
+       drm_sman_takedown(&dev_priv->sman);
+
        drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
 
        return 0;
index 33e0cb12e4c30dd448365847421b9266f8ac71c5..2fcf0577a7aa9e5b4b52d37cf7e897b3238e2315 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
+ * All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
 #include "drmP.h"
 #include "via_drm.h"
 #include "via_drv.h"
-#include "via_ds.h"
-#include "via_mm.h"
-
-#define MAX_CONTEXT 100
-
-typedef struct {
-       int used;
-       int context;
-       set_t *sets[2];         /* 0 for frame buffer, 1 for AGP , 2 for System */
-} via_context_t;
-
-static via_context_t global_ppriv[MAX_CONTEXT];
+#include "drm_sman.h"
 
-static int via_agp_alloc(drm_via_mem_t * mem);
-static int via_agp_free(drm_via_mem_t * mem);
-static int via_fb_alloc(drm_via_mem_t * mem);
-static int via_fb_free(drm_via_mem_t * mem);
-
-static int add_alloc_set(int context, int type, unsigned long val)
-{
-       int i, retval = 0;
-
-       for (i = 0; i < MAX_CONTEXT; i++) {
-               if (global_ppriv[i].used && global_ppriv[i].context == context) {
-                       retval = via_setAdd(global_ppriv[i].sets[type], val);
-                       break;
-               }
-       }
-
-       return retval;
-}
-
-static int del_alloc_set(int context, int type, unsigned long val)
-{
-       int i, retval = 0;
-
-       for (i = 0; i < MAX_CONTEXT; i++)
-               if (global_ppriv[i].used && global_ppriv[i].context == context) {
-                       retval = via_setDel(global_ppriv[i].sets[type], val);
-                       break;
-               }
-
-       return retval;
-}
-
-/* agp memory management */
-static memHeap_t *AgpHeap = NULL;
+#define VIA_MM_ALIGN_SHIFT 4
+#define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
 
 int via_agp_init(DRM_IOCTL_ARGS)
 {
+       DRM_DEVICE;
        drm_via_agp_t agp;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       int ret;
 
        DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
                                 sizeof(agp));
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
+                                agp.size >> VIA_MM_ALIGN_SHIFT);
+
+       if (ret) {
+               DRM_ERROR("AGP memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
 
-       AgpHeap = via_mmInit(agp.offset, agp.size);
-
-       DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset,
-                 (unsigned long)agp.size);
+       dev_priv->agp_initialized = 1;
+       dev_priv->agp_offset = agp.offset;
+       mutex_unlock(&dev->struct_mutex);
 
+       DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
        return 0;
 }
 
-/* fb memory management */
-static memHeap_t *FBHeap = NULL;
-
 int via_fb_init(DRM_IOCTL_ARGS)
 {
+       DRM_DEVICE;
        drm_via_fb_t fb;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       int ret;
 
        DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
 
-       FBHeap = via_mmInit(fb.offset, fb.size);
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
+                                fb.size >> VIA_MM_ALIGN_SHIFT);
 
-       DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset,
-                 (unsigned long)fb.size);
+       if (ret) {
+               DRM_ERROR("VRAM memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
 
-       return 0;
-}
+       dev_priv->vram_initialized = 1;
+       dev_priv->vram_offset = fb.offset;
 
-int via_init_context(struct drm_device *dev, int context)
-{
-       int i;
-
-       for (i = 0; i < MAX_CONTEXT; i++)
-               if (global_ppriv[i].used &&
-                   (global_ppriv[i].context == context))
-                       break;
-
-       if (i >= MAX_CONTEXT) {
-               for (i = 0; i < MAX_CONTEXT; i++) {
-                       if (!global_ppriv[i].used) {
-                               global_ppriv[i].context = context;
-                               global_ppriv[i].used = 1;
-                               global_ppriv[i].sets[0] = via_setInit();
-                               global_ppriv[i].sets[1] = via_setInit();
-                               DRM_DEBUG("init allocation set, socket=%d,"
-                                         " context = %d\n", i, context);
-                               break;
-                       }
-               }
-
-               if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
-                   (global_ppriv[i].sets[1] == NULL)) {
-                       return 0;
-               }
-       }
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
+
+       return 0;
 
-       return 1;
 }
 
 int via_final_context(struct drm_device *dev, int context)
 {
-       int i;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 
-       for (i = 0; i < MAX_CONTEXT; i++)
-               if (global_ppriv[i].used &&
-                   (global_ppriv[i].context == context))
-                       break;
-
-       if (i < MAX_CONTEXT) {
-               set_t *set;
-               ITEM_TYPE item;
-               int retval;
-
-               DRM_DEBUG("find socket %d, context = %d\n", i, context);
-
-               /* Video Memory */
-               set = global_ppriv[i].sets[0];
-               retval = via_setFirst(set, &item);
-               while (retval) {
-                       DRM_DEBUG("free video memory 0x%lx\n", item);
-                       via_mmFreeMem((PMemBlock) item);
-                       retval = via_setNext(set, &item);
-               }
-               via_setDestroy(set);
-
-               /* AGP Memory */
-               set = global_ppriv[i].sets[1];
-               retval = via_setFirst(set, &item);
-               while (retval) {
-                       DRM_DEBUG("free agp memory 0x%lx\n", item);
-                       via_mmFreeMem((PMemBlock) item);
-                       retval = via_setNext(set, &item);
-               }
-               via_setDestroy(set);
-               global_ppriv[i].used = 0;
-       }
        via_release_futex(dev_priv, context);
 
-#if defined(__linux__)
        /* Linux specific until context tracking code gets ported to BSD */
        /* Last context, perform cleanup */
        if (dev->ctx_count == 1 && dev->dev_private) {
                DRM_DEBUG("Last Context\n");
                if (dev->irq)
                        drm_irq_uninstall(dev);
-
                via_cleanup_futex(dev_priv);
                via_do_cleanup_map(dev);
        }
-#endif
-
        return 1;
 }
 
+void via_lastclose(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (!dev_priv)
+               return;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_sman_cleanup(&dev_priv->sman);
+       dev_priv->vram_initialized = 0;
+       dev_priv->agp_initialized = 0;
+       mutex_unlock(&dev->struct_mutex);
+}      
+
 int via_mem_alloc(DRM_IOCTL_ARGS)
 {
+       DRM_DEVICE;
+
        drm_via_mem_t mem;
+       int retval = 0;
+       drm_memblock_item_t *item;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       unsigned long tmpSize;
 
        DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
                                 sizeof(mem));
 
-       switch (mem.type) {
-       case VIA_MEM_VIDEO:
-               if (via_fb_alloc(&mem) < 0)
-                       return -EFAULT;
-               DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
-                                      sizeof(mem));
-               return 0;
-       case VIA_MEM_AGP:
-               if (via_agp_alloc(&mem) < 0)
-                       return -EFAULT;
-               DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
-                                      sizeof(mem));
-               return 0;
+       if (mem.type > VIA_MEM_AGP) {
+               DRM_ERROR("Unknown memory type allocation\n");
+               return DRM_ERR(EINVAL);
        }
-
-       return -EFAULT;
-}
-
-static int via_fb_alloc(drm_via_mem_t * mem)
-{
-       drm_via_mm_t fb;
-       PMemBlock block;
-       int retval = 0;
-
-       if (!FBHeap)
-               return -1;
-
-       fb.size = mem->size;
-       fb.context = mem->context;
-
-       block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
-       if (block) {
-               fb.offset = block->ofs;
-               fb.free = (unsigned long)block;
-               if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
-                       DRM_DEBUG("adding to allocation set fails\n");
-                       via_mmFreeMem((PMemBlock) fb.free);
-                       retval = -1;
-               }
-       } else {
-               fb.offset = 0;
-               fb.size = 0;
-               fb.free = 0;
-               retval = -1;
+       mutex_lock(&dev->struct_mutex);
+       if (0 == ((mem.type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
+                     dev_priv->agp_initialized)) {
+               DRM_ERROR
+                   ("Attempt to allocate from uninitialized memory manager.\n");
+               mutex_unlock(&dev->struct_mutex);
+               return DRM_ERR(EINVAL);
        }
 
-       mem->offset = fb.offset;
-       mem->index = fb.free;
-
-       DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size,
-                 (int)fb.offset);
-
-       return retval;
-}
-
-static int via_agp_alloc(drm_via_mem_t * mem)
-{
-       drm_via_mm_t agp;
-       PMemBlock block;
-       int retval = 0;
-
-       if (!AgpHeap)
-               return -1;
-
-       agp.size = mem->size;
-       agp.context = mem->context;
-
-       block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
-       if (block) {
-               agp.offset = block->ofs;
-               agp.free = (unsigned long)block;
-               if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
-                       DRM_DEBUG("adding to allocation set fails\n");
-                       via_mmFreeMem((PMemBlock) agp.free);
-                       retval = -1;
-               }
+       tmpSize = (mem.size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
+       item = drm_sman_alloc(&dev_priv->sman, mem.type, tmpSize, 0,
+                             (unsigned long)priv);
+       mutex_unlock(&dev->struct_mutex);
+       if (item) {
+               mem.offset = ((mem.type == VIA_MEM_VIDEO) ?
+                             dev_priv->vram_offset : dev_priv->agp_offset) +
+                   (item->mm->
+                    offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
+               mem.index = item->user_hash.key;
        } else {
-               agp.offset = 0;
-               agp.size = 0;
-               agp.free = 0;
+               mem.offset = 0;
+               mem.size = 0;
+               mem.index = 0;
+               DRM_DEBUG("Video memory allocation failed\n");
+               retval = DRM_ERR(ENOMEM);
        }
+       DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem));
 
-       mem->offset = agp.offset;
-       mem->index = agp.free;
-
-       DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
-                 (unsigned int)agp.offset);
        return retval;
 }
 
 int via_mem_free(DRM_IOCTL_ARGS)
 {
+       DRM_DEVICE;
+       drm_via_private_t *dev_priv = dev->dev_private;
        drm_via_mem_t mem;
+       int ret;
 
        DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
                                 sizeof(mem));
 
-       switch (mem.type) {
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_free_key(&dev_priv->sman, mem.index);
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("free = 0x%lx\n", mem.index);
 
-       case VIA_MEM_VIDEO:
-               if (via_fb_free(&mem) == 0)
-                       return 0;
-               break;
-       case VIA_MEM_AGP:
-               if (via_agp_free(&mem) == 0)
-                       return 0;
-               break;
-       }
-
-       return -EFAULT;
+       return ret;
 }
 
-static int via_fb_free(drm_via_mem_t * mem)
-{
-       drm_via_mm_t fb;
-       int retval = 0;
-
-       if (!FBHeap) {
-               return -1;
-       }
-
-       fb.free = mem->index;
-       fb.context = mem->context;
-
-       if (!fb.free) {
-               return -1;
-
-       }
-
-       via_mmFreeMem((PMemBlock) fb.free);
-
-       if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
-               retval = -1;
-       }
-
-       DRM_DEBUG("free fb, free = %ld\n", fb.free);
 
-       return retval;
-}
-
-static int via_agp_free(drm_via_mem_t * mem)
+void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
 {
-       drm_via_mm_t agp;
-
-       int retval = 0;
+       drm_via_private_t *dev_priv = dev->dev_private;
+       drm_file_t *priv = filp->private_data;
 
-       agp.free = mem->index;
-       agp.context = mem->context;
-
-       if (!agp.free)
-               return -1;
-
-       via_mmFreeMem((PMemBlock) agp.free);
-
-       if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
-               retval = -1;
+       mutex_lock(&dev->struct_mutex);
+       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
+               mutex_unlock(&dev->struct_mutex);
+               return;
        }
 
-       DRM_DEBUG("free agp, free = %ld\n", agp.free);
+       if (dev->driver->dma_quiescent) {
+               dev->driver->dma_quiescent(dev);
+       }
 
-       return retval;
+       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
+       mutex_unlock(&dev->struct_mutex);
+       return;
 }
index 21c8229f544388cfb2d75f68218abaac215b4c17..6d58b037080234431b49f6cacde669998ab749a7 100644 (file)
@@ -104,7 +104,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
        {
-               unsigned int flags;
+               unsigned long flags;
                unsigned char val;
 
                if (!capable(CAP_SYS_TIME))
@@ -120,7 +120,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
        }
        case RTC_AIE_ON:        /* Allow alarm interrupts.      */
        {
-               unsigned int flags;
+               unsigned long flags;
                unsigned char val;
 
                if (!capable(CAP_SYS_TIME))
@@ -136,7 +136,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
        }
        case RTC_WIE_OFF:       /* Mask watchdog int. enab. bit */
        {
-               unsigned int flags;
+               unsigned long flags;
                unsigned char val;
 
                if (!capable(CAP_SYS_TIME))
@@ -152,7 +152,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
        }
        case RTC_WIE_ON:        /* Allow watchdog interrupts.   */
        {
-               unsigned int flags;
+               unsigned long flags;
                unsigned char val;
 
                if (!capable(CAP_SYS_TIME))
@@ -434,7 +434,7 @@ static inline unsigned char ds1286_is_updating(void)
 static void ds1286_get_time(struct rtc_time *rtc_tm)
 {
        unsigned char save_control;
-       unsigned int flags;
+       unsigned long flags;
        unsigned long uip_watchdog = jiffies;
 
        /*
@@ -494,7 +494,8 @@ static int ds1286_set_time(struct rtc_time *rtc_tm)
 {
        unsigned char mon, day, hrs, min, sec, leap_yr;
        unsigned char save_control;
-       unsigned int yrs, flags;
+       unsigned int yrs;
+       unsigned long flags;
 
 
        yrs = rtc_tm->tm_year + 1900;
@@ -552,7 +553,7 @@ static int ds1286_set_time(struct rtc_time *rtc_tm)
 static void ds1286_get_alm_time(struct rtc_time *alm_tm)
 {
        unsigned char cmd;
-       unsigned int flags;
+       unsigned long flags;
 
        /*
         * Only the values that we read from the RTC are set. That
index 5e59c0b42731990818df9c713adb635f378ec236..4711d9b3a59545f870d769f4818f967923bf21a9 100644 (file)
@@ -746,11 +746,9 @@ void gs_set_termios (struct tty_struct * tty,
                gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
        }
 
-#if 0
        /* This is an optimization that is only allowed for dumb cards */
        /* Smart cards require knowledge of iflags and oflags too: that 
           might change hardware cooking mode.... */
-#endif
        if (old_termios) {
                if(   (tiosp->c_iflag == old_termios->c_iflag)
                   && (tiosp->c_oflag == old_termios->c_oflag)
@@ -774,14 +772,7 @@ void gs_set_termios (struct tty_struct * tty,
                if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
        }
 
-       baudrate = tiosp->c_cflag & CBAUD;
-       if (baudrate & CBAUDEX) {
-               baudrate &= ~CBAUDEX;
-               if ((baudrate < 1) || (baudrate > 4))
-                       tiosp->c_cflag &= ~CBAUDEX;
-               else
-                       baudrate += 15;
-       }
+       baudrate = tty_get_baud_rate(tty);
 
        baudrate = gs_baudrates[baudrate];
        if ((tiosp->c_cflag & CBAUD) == B38400) {
index ccd7e7102234cf09cfda77bdb49db017389d197a..8efbc9c0e5450e53868af1117556c1b89db29270 100644 (file)
 #define INTEL_RNG_ADDR                         0xFFBC015F
 #define INTEL_RNG_ADDR_LEN                     3
 
+/*
+ * LPC bridge PCI config space registers
+ */
+#define FWH_DEC_EN1_REG_OLD                    0xe3
+#define FWH_DEC_EN1_REG_NEW                    0xd9 /* high byte of 16-bit register */
+#define FWH_F8_EN_MASK                         0x80
+
+#define BIOS_CNTL_REG_OLD                      0x4e
+#define BIOS_CNTL_REG_NEW                      0xdc
+#define BIOS_CNTL_WRITE_ENABLE_MASK            0x01
+#define BIOS_CNTL_LOCK_ENABLE_MASK             0x02
+
+/*
+ * Magic address at which Intel Firmware Hubs get accessed
+ */
+#define INTEL_FWH_ADDR                         0xffff0000
+#define INTEL_FWH_ADDR_LEN                     2
+
+/*
+ * Intel Firmware Hub command codes (write to any address inside the device)
+ */
+#define INTEL_FWH_RESET_CMD                    0xff /* aka READ_ARRAY */
+#define INTEL_FWH_READ_ID_CMD                  0x90
+
+/*
+ * Intel Firmware Hub Read ID command result addresses
+ */
+#define INTEL_FWH_MANUFACTURER_CODE_ADDRESS    0x000000
+#define INTEL_FWH_DEVICE_CODE_ADDRESS          0x000001
+
+/*
+ * Intel Firmware Hub Read ID command result values
+ */
+#define INTEL_FWH_MANUFACTURER_CODE            0x89
+#define INTEL_FWH_DEVICE_CODE_8M               0xac
+#define INTEL_FWH_DEVICE_CODE_4M               0xad
+
 /*
  * Data for PCI driver interface
  *
  * want to register another driver on the same PCI id.
  */
 static const struct pci_device_id pci_tbl[] = {
-       { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+/* AA
+       { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
+/* AB
+       { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
+/* ??
+       { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+/* BAM, CAM, DBM, FBM, GxM
+       { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
+       { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
+       { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
+       { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
+       { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
+       { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
+/* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
+       { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
+       { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
+       { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
+       { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
+       { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
+       { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
+       { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
+/* E
+       { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E  */
        { 0, }, /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
@@ -138,22 +213,115 @@ static struct hwrng intel_rng = {
 };
 
 
+#ifdef CONFIG_SMP
+static char __initdata waitflag;
+
+static void __init intel_init_wait(void *unused)
+{
+       while (waitflag)
+               cpu_relax();
+}
+#endif
+
 static int __init mod_init(void)
 {
        int err = -ENODEV;
+       unsigned i;
+       struct pci_dev *dev = NULL;
        void __iomem *mem;
-       u8 hw_status;
+       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;
 
-       if (!pci_dev_present(pci_tbl))
+       for (i = 0; !dev && pci_tbl[i].vendor; ++i)
+               dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL);
+
+       if (!dev)
                goto out; /* Device not found. */
 
+       /* 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);
+
+       mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
+       if (mem == NULL) {
+               pci_dev_put(dev);
+               err = -EBUSY;
+               goto out;
+       }
+
+       /*
+        * 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.
+        */
+#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_LOCK_ENABLE_MASK|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);
+       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;
+               goto out;
+       }
+
        err = -ENOMEM;
        mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
        if (!mem)
                goto out;
        intel_rng.priv = (unsigned long)mem;
 
-       /* Check for Intel 82802 */
+       /* Check for Random Number Generator */
        err = -ENODEV;
        hw_status = hwstatus_get(mem);
        if ((hw_status & INTEL_RNG_PRESENT) == 0)
index 7907ae88c2f4df48cdecccd87d0c20f6e7f2b8e2..331f447e62283291b3d799a04557ecb018a0d197 100644 (file)
@@ -436,6 +436,7 @@ cleanup_module(void)
 #ifdef CONFIG_PCI
                if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
                        pci_disable_device(ip2config.pci_dev[i]);
+                       pci_dev_put(ip2config.pci_dev[i]);
                        ip2config.pci_dev[i] = NULL;
                }
 #endif
@@ -505,6 +506,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
        static int loaded;
        i2eBordStrPtr pB = NULL;
        int rc = -1;
+       static struct pci_dev *pci_dev_i = NULL;
 
        ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
 
@@ -588,8 +590,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
                case PCI:
 #ifdef CONFIG_PCI
                        {
-                               struct pci_dev *pci_dev_i = NULL;
-                               pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
+                               pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
                                                          PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
                                if (pci_dev_i != NULL) {
                                        unsigned int addr;
@@ -600,7 +601,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
                                                break;
                                        }
                                        ip2config.type[i] = PCI;
-                                       ip2config.pci_dev[i] = pci_dev_i;
+                                       ip2config.pci_dev[i] = pci_dev_get(pci_dev_i);
                                        status =
                                        pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
                                        if ( addr & 1 ) {
@@ -641,6 +642,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
                        break;
                }       /* switch */
        }       /* for */
+       if (pci_dev_i)
+               pci_dev_put(pci_dev_i);
+
        for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
                if ( ip2config.addr[i] ) {
                        pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL);
index 68d7c61a864e7ecc4f696e3b36f4ceb92201472f..81fcf0ce21d1c91cf95f478a960a20d2459a6772 100644 (file)
@@ -377,7 +377,8 @@ static int ipmi_ioctl(struct inode  *inode,
                        break;
                }
 
-               rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd);
+               rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
+                                          IPMI_CHAN_ALL);
                break;
        }
 
@@ -390,7 +391,36 @@ static int ipmi_ioctl(struct inode  *inode,
                        break;
                }
 
-               rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd);
+               rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
+                                            IPMI_CHAN_ALL);
+               break;
+       }
+
+       case IPMICTL_REGISTER_FOR_CMD_CHANS:
+       {
+               struct ipmi_cmdspec_chans val;
+
+               if (copy_from_user(&val, arg, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+
+               rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
+                                          val.chans);
+               break;
+       }
+
+       case IPMICTL_UNREGISTER_FOR_CMD_CHANS:
+       {
+               struct ipmi_cmdspec_chans val;
+
+               if (copy_from_user(&val, arg, sizeof(val))) {
+                       rv = -EFAULT;
+                       break;
+               }
+
+               rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
+                                            val.chans);
                break;
        }
 
index 843d34c8627c38d3a72889557f216513bc9fe638..2455e8d478ace521bd7ef8f85c3ffac7e6a5388e 100644 (file)
@@ -96,6 +96,7 @@ struct cmd_rcvr
        ipmi_user_t   user;
        unsigned char netfn;
        unsigned char cmd;
+       unsigned int  chans;
 
        /*
         * This is used to form a linked lised during mass deletion.
@@ -953,24 +954,41 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
 
 static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t    intf,
                                      unsigned char netfn,
-                                     unsigned char cmd)
+                                     unsigned char cmd,
+                                     unsigned char chan)
 {
        struct cmd_rcvr *rcvr;
 
        list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
-               if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd))
+               if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)
+                                       && (rcvr->chans & (1 << chan)))
                        return rcvr;
        }
        return NULL;
 }
 
+static int is_cmd_rcvr_exclusive(ipmi_smi_t    intf,
+                                unsigned char netfn,
+                                unsigned char cmd,
+                                unsigned int  chans)
+{
+       struct cmd_rcvr *rcvr;
+
+       list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
+               if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)
+                                       && (rcvr->chans & chans))
+                       return 0;
+       }
+       return 1;
+}
+
 int ipmi_register_for_cmd(ipmi_user_t   user,
                          unsigned char netfn,
-                         unsigned char cmd)
+                         unsigned char cmd,
+                         unsigned int  chans)
 {
        ipmi_smi_t      intf = user->intf;
        struct cmd_rcvr *rcvr;
-       struct cmd_rcvr *entry;
        int             rv = 0;
 
 
@@ -979,12 +997,12 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
                return -ENOMEM;
        rcvr->cmd = cmd;
        rcvr->netfn = netfn;
+       rcvr->chans = chans;
        rcvr->user = user;
 
        mutex_lock(&intf->cmd_rcvrs_mutex);
        /* Make sure the command/netfn is not already registered. */
-       entry = find_cmd_rcvr(intf, netfn, cmd);
-       if (entry) {
+       if (!is_cmd_rcvr_exclusive(intf, netfn, cmd, chans)) {
                rv = -EBUSY;
                goto out_unlock;
        }
@@ -1001,24 +1019,39 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
 
 int ipmi_unregister_for_cmd(ipmi_user_t   user,
                            unsigned char netfn,
-                           unsigned char cmd)
+                           unsigned char cmd,
+                           unsigned int  chans)
 {
        ipmi_smi_t      intf = user->intf;
        struct cmd_rcvr *rcvr;
+       struct cmd_rcvr *rcvrs = NULL;
+       int i, rv = -ENOENT;
 
        mutex_lock(&intf->cmd_rcvrs_mutex);
-       /* Make sure the command/netfn is not already registered. */
-       rcvr = find_cmd_rcvr(intf, netfn, cmd);
-       if ((rcvr) && (rcvr->user == user)) {
-               list_del_rcu(&rcvr->link);
-               mutex_unlock(&intf->cmd_rcvrs_mutex);
-               synchronize_rcu();
+       for (i = 0; i < IPMI_NUM_CHANNELS; i++) {
+               if (((1 << i) & chans) == 0)
+                       continue;
+               rcvr = find_cmd_rcvr(intf, netfn, cmd, i);
+               if (rcvr == NULL)
+                       continue;
+               if (rcvr->user == user) {
+                       rv = 0;
+                       rcvr->chans &= ~chans;
+                       if (rcvr->chans == 0) {
+                               list_del_rcu(&rcvr->link);
+                               rcvr->next = rcvrs;
+                               rcvrs = rcvr;
+                       }
+               }
+       }
+       mutex_unlock(&intf->cmd_rcvrs_mutex);
+       synchronize_rcu();
+       while (rcvrs) {
+               rcvr = rcvrs;
+               rcvrs = rcvr->next;
                kfree(rcvr);
-               return 0;
-       } else {
-               mutex_unlock(&intf->cmd_rcvrs_mutex);
-               return -ENOENT;
        }
+       return rv;
 }
 
 void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
@@ -2548,6 +2581,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
        int                      rv = 0;
        unsigned char            netfn;
        unsigned char            cmd;
+       unsigned char            chan;
        ipmi_user_t              user = NULL;
        struct ipmi_ipmb_addr    *ipmb_addr;
        struct ipmi_recv_msg     *recv_msg;
@@ -2568,9 +2602,10 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
 
        netfn = msg->rsp[4] >> 2;
        cmd = msg->rsp[8];
+       chan = msg->rsp[3] & 0xf;
 
        rcu_read_lock();
-       rcvr = find_cmd_rcvr(intf, netfn, cmd);
+       rcvr = find_cmd_rcvr(intf, netfn, cmd, chan);
        if (rcvr) {
                user = rcvr->user;
                kref_get(&user->refcount);
@@ -2728,6 +2763,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
        int                      rv = 0;
        unsigned char            netfn;
        unsigned char            cmd;
+       unsigned char            chan;
        ipmi_user_t              user = NULL;
        struct ipmi_lan_addr     *lan_addr;
        struct ipmi_recv_msg     *recv_msg;
@@ -2748,9 +2784,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
 
        netfn = msg->rsp[6] >> 2;
        cmd = msg->rsp[10];
+       chan = msg->rsp[3] & 0xf;
 
        rcu_read_lock();
-       rcvr = find_cmd_rcvr(intf, netfn, cmd);
+       rcvr = find_cmd_rcvr(intf, netfn, cmd, chan);
        if (rcvr) {
                user = rcvr->user;
                kref_get(&user->refcount);
index abca98beac14507471537abfc50403e06d10abdf..908521e36d81ca137abdce89f0c09e2475d1af30 100644 (file)
@@ -916,7 +916,11 @@ static int smi_start_processing(void       *send_info,
        new_smi->last_timeout_jiffies = jiffies;
        mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
 
-       if (new_smi->si_type != SI_BT) {
+       /*
+        * The BT interface is efficient enough to not need a thread,
+        * and there is no need for a thread if we have interrupts.
+        */
+       if ((new_smi->si_type != SI_BT) && (!new_smi->irq)) {
                new_smi->thread = kthread_run(ipmi_thread, new_smi,
                                              "kipmi%d", new_smi->intf_num);
                if (IS_ERR(new_smi->thread)) {
index 913be23e0a2427e16b07ae6e422ba9e8632bf7ea..2e1da632aee18ef3c8d7ea22cc70ea06010169b5 100644 (file)
@@ -1756,9 +1756,12 @@ static int __devinit load_firmware(struct pci_dev *pdev,
        if (retval)
                goto end;
 
+       retval = -EIO;
+
        for (frame = (struct stframe *)fw->data;
                        frame < (struct stframe *)(fw->data + fw->size);
-                       frame++) {
+                       frame = (struct stframe *)((u8 *)(frame + 1) +
+                               frame->count)) {
                if (WaitTillCardIsFree(base))
                        goto errrelfw;
 
@@ -1797,23 +1800,12 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                }
        }
 
-       retval = -EIO;
-
-       if (WaitTillCardIsFree(base))
-               goto errrelfw;
-
-       outw(0xf2, base);
-       outw(0x800, base);
-       outw(0x0, base);
-       outw(0x0, base);
-       InterruptTheCard(base);
-       outw(0x0, base + 0x4); /* for ISI4608 cards */
-
 /* XXX: should we test it by reading it back and comparing with original like
  * in load firmware package? */
-       for (frame = (struct stframe*)fw->data;
-                       frame < (struct stframe*)(fw->data + fw->size);
-                       frame++) {
+       for (frame = (struct stframe *)fw->data;
+                       frame < (struct stframe *)(fw->data + fw->size);
+                       frame = (struct stframe *)((u8 *)(frame + 1) +
+                               frame->count)) {
                if (WaitTillCardIsFree(base))
                        goto errrelfw;
 
@@ -1863,6 +1855,17 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                }
        }
 
+       /* xfer ctrl */
+       if (WaitTillCardIsFree(base))
+               goto errrelfw;
+
+       outw(0xf2, base);
+       outw(0x800, base);
+       outw(0x0, base);
+       outw(0x0, base);
+       InterruptTheCard(base);
+       outw(0x0, base + 0x4); /* for ISI4608 cards */
+
        board->status |= FIRMWARE_LOADED;
        retval = 0;
 
index 8c09997cc3d63b9108c7c4f948a9eb611a580bff..6b4d82a4565fbf9ec533891f8043b6aa3d5ca707 100644 (file)
@@ -612,16 +612,6 @@ MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
 #define        MINOR2BRD(min)          (((min) & 0xc0) >> 6)
 #define        MINOR2PORT(min)         ((min) & 0x3f)
 
-/*
- *     Define a baud rate table that converts termios baud rate selector
- *     into the actual baud rate value. All baud rate calculations are based
- *     on the actual baud rate required.
- */
-static unsigned int    stli_baudrates[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
-};
-
 /*****************************************************************************/
 
 /*
@@ -2747,15 +2737,7 @@ static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tio
 /*
  *     Start of by setting the baud, char size, parity and stop bit info.
  */
-       pp->baudout = tiosp->c_cflag & CBAUD;
-       if (pp->baudout & CBAUDEX) {
-               pp->baudout &= ~CBAUDEX;
-               if ((pp->baudout < 1) || (pp->baudout > 4))
-                       tiosp->c_cflag &= ~CBAUDEX;
-               else
-                       pp->baudout += 15;
-       }
-       pp->baudout = stli_baudrates[pp->baudout];
+       pp->baudout = tty_get_baud_rate(portp->tty);
        if ((tiosp->c_cflag & CBAUD) == B38400) {
                if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
                        pp->baudout = 57600;
index f875fda3b089d54332341671388716c99ebd05eb..1ecea7d448f14618e19112b6c84dd75a25c25d7d 100644 (file)
@@ -906,7 +906,7 @@ static int __init lp_init (void)
        lp_class = class_create(THIS_MODULE, "printer");
        if (IS_ERR(lp_class)) {
                err = PTR_ERR(lp_class);
-               goto out_devfs;
+               goto out_reg;
        }
 
        if (parport_register_driver (&lp_driver)) {
@@ -927,7 +927,7 @@ static int __init lp_init (void)
 
 out_class:
        class_destroy(lp_class);
-out_devfs:
+out_reg:
        unregister_chrdev(LP_MAJOR, "lp");
        return err;
 }
index 0385650f6077892843b966f3c68018c254a46492..636354722658eb4b6cc035f7f0a22196fc91e141 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/mm.h>
+#include <linux/fs.h>
 #include <linux/uio.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -447,15 +448,15 @@ loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
        loff_t newpos;
 
        switch (whence) {
-       case 0:         /* SEEK_SET */
+       case SEEK_SET:
                newpos = off;
                break;
 
-       case 1:         /* SEEK_CUR */
+       case SEEK_CUR:
                newpos = filp->f_pos + off;
                break;
 
-       case 2:         /* SEEK_END */
+       case SEEK_END:
                newpos = MBCS_SRAM_SIZE + off;
                break;
 
index 917b20402664aad5ccf970255f65f15974f06eab..6511012cbdcd86d971a6cdebcf6e1baad66ccded 100644 (file)
@@ -238,6 +238,32 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 }
 #endif
 
+#ifndef CONFIG_MMU
+static unsigned long get_unmapped_area_mem(struct file *file,
+                                          unsigned long addr,
+                                          unsigned long len,
+                                          unsigned long pgoff,
+                                          unsigned long flags)
+{
+       if (!valid_mmap_phys_addr_range(pgoff, len))
+               return (unsigned long) -EINVAL;
+       return pgoff;
+}
+
+/* can't do an in-place private mapping if there's no MMU */
+static inline int private_mapping_ok(struct vm_area_struct *vma)
+{
+       return vma->vm_flags & VM_MAYSHARE;
+}
+#else
+#define get_unmapped_area_mem  NULL
+
+static inline int private_mapping_ok(struct vm_area_struct *vma)
+{
+       return 1;
+}
+#endif
+
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
        size_t size = vma->vm_end - vma->vm_start;
@@ -245,6 +271,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
        if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
                return -EINVAL;
 
+       if (!private_mapping_ok(vma))
+               return -ENOSYS;
+
        vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
                                                 size,
                                                 vma->vm_page_prot);
@@ -522,7 +551,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
        return virtr + wrote;
 }
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
 static ssize_t read_port(struct file * file, char __user * buf,
                         size_t count, loff_t *ppos)
 {
@@ -782,6 +811,7 @@ static const struct file_operations mem_fops = {
        .write          = write_mem,
        .mmap           = mmap_mem,
        .open           = open_mem,
+       .get_unmapped_area = get_unmapped_area_mem,
 };
 
 static const struct file_operations kmem_fops = {
@@ -790,6 +820,7 @@ static const struct file_operations kmem_fops = {
        .write          = write_kmem,
        .mmap           = mmap_kmem,
        .open           = open_kmem,
+       .get_unmapped_area = get_unmapped_area_mem,
 };
 
 static const struct file_operations null_fops = {
@@ -799,7 +830,7 @@ static const struct file_operations null_fops = {
        .splice_write   = splice_write_null,
 };
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
 static const struct file_operations port_fops = {
        .llseek         = memory_lseek,
        .read           = read_port,
@@ -815,6 +846,10 @@ static const struct file_operations zero_fops = {
        .mmap           = mmap_zero,
 };
 
+/*
+ * capabilities for /dev/zero
+ * - permits private mappings, "copies" are taken of the source of zeros
+ */
 static struct backing_dev_info zero_bdi = {
        .capabilities   = BDI_CAP_MAP_COPY,
 };
@@ -862,14 +897,18 @@ static int memory_open(struct inode * inode, struct file * filp)
        switch (iminor(inode)) {
                case 1:
                        filp->f_op = &mem_fops;
+                       filp->f_mapping->backing_dev_info =
+                               &directly_mappable_cdev_bdi;
                        break;
                case 2:
                        filp->f_op = &kmem_fops;
+                       filp->f_mapping->backing_dev_info =
+                               &directly_mappable_cdev_bdi;
                        break;
                case 3:
                        filp->f_op = &null_fops;
                        break;
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
                case 4:
                        filp->f_op = &port_fops;
                        break;
@@ -916,7 +955,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(__mc68000__)
+#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
        {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
 #endif
        {5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
index a369dd6877d8afdf5f57f66def984f207b3ea581..c1a6d3c48da155da8c9e974090ad6e4efe3a4b8c 100644 (file)
@@ -260,7 +260,7 @@ static void MoxaPortEnable(int);
 static void MoxaPortDisable(int);
 static long MoxaPortGetMaxBaud(int);
 static long MoxaPortSetBaud(int, long);
-static int MoxaPortSetTermio(int, struct termios *);
+static int MoxaPortSetTermio(int, struct termios *, speed_t);
 static int MoxaPortGetLineOut(int, int *, int *);
 static void MoxaPortLineCtrl(int, int, int);
 static void MoxaPortFlowCtrl(int, int, int, int, int, int);
@@ -986,7 +986,7 @@ static void set_tty_param(struct tty_struct *tty)
        if (ts->c_iflag & IXANY)
                xany = 1;
        MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
-       MoxaPortSetTermio(ch->port, ts);
+       MoxaPortSetTermio(ch->port, ts, tty_get_baud_rate(tty));
 }
 
 static int block_till_ready(struct tty_struct *tty, struct file *filp,
@@ -1900,9 +1900,10 @@ int MoxaPortsOfCard(int cardno)
  *
  *      Function 12:    Configure the port.
  *      Syntax:
- *      int  MoxaPortSetTermio(int port, struct termios *termio);
+ *      int  MoxaPortSetTermio(int port, struct termios *termio, speed_t baud);
  *           int port           : port number (0 - 127)
  *           struct termios * termio : termio structure pointer
+ *          speed_t baud       : baud rate
  *
  *           return:    -1      : this port is invalid or termio == NULL
  *                      0       : setting O.K.
@@ -2182,11 +2183,10 @@ long MoxaPortSetBaud(int port, long baud)
        return (baud);
 }
 
-int MoxaPortSetTermio(int port, struct termios *termio)
+int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud)
 {
        void __iomem *ofsAddr;
        tcflag_t cflag;
-       long baud;
        tcflag_t mode = 0;
 
        if (moxaChkPort[port] == 0 || termio == 0)
@@ -2222,77 +2222,9 @@ int MoxaPortSetTermio(int port, struct termios *termio)
 
        moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
 
-       cflag &= (CBAUD | CBAUDEX);
-#ifndef B921600
-#define        B921600 (B460800+1)
-#endif
-       switch (cflag) {
-       case B921600:
-               baud = 921600L;
-               break;
-       case B460800:
-               baud = 460800L;
-               break;
-       case B230400:
-               baud = 230400L;
-               break;
-       case B115200:
-               baud = 115200L;
-               break;
-       case B57600:
-               baud = 57600L;
-               break;
-       case B38400:
-               baud = 38400L;
-               break;
-       case B19200:
-               baud = 19200L;
-               break;
-       case B9600:
-               baud = 9600L;
-               break;
-       case B4800:
-               baud = 4800L;
-               break;
-       case B2400:
-               baud = 2400L;
-               break;
-       case B1800:
-               baud = 1800L;
-               break;
-       case B1200:
-               baud = 1200L;
-               break;
-       case B600:
-               baud = 600L;
-               break;
-       case B300:
-               baud = 300L;
-               break;
-       case B200:
-               baud = 200L;
-               break;
-       case B150:
-               baud = 150L;
-               break;
-       case B134:
-               baud = 134L;
-               break;
-       case B110:
-               baud = 110L;
-               break;
-       case B75:
-               baud = 75L;
-               break;
-       case B50:
-               baud = 50L;
-               break;
-       default:
-               baud = 0;
-       }
        if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
            (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
-               if (baud == 921600L)
+               if (baud >= 921600L)
                        return (-1);
        }
        MoxaPortSetBaud(port, baud);
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
new file mode 100644 (file)
index 0000000..5426b1e
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2001-2006 Silicon Graphics, Inc.  All rights
+ * reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+/*
+ * SN Platform Special Memory (mspec) Support
+ *
+ * This driver exports the SN special memory (mspec) facility to user
+ * processes.
+ * There are three types of memory made available thru this driver:
+ * fetchops, uncached and cached.
+ *
+ * Fetchops are atomic memory operations that are implemented in the
+ * memory controller on SGI SN hardware.
+ *
+ * Uncached are used for memory write combining feature of the ia64
+ * cpu.
+ *
+ * Cached are used for areas of memory that are used as cached addresses
+ * on our partition and used as uncached addresses from other partitions.
+ * Due to a design constraint of the SN2 Shub, you can not have processors
+ * on the same FSB perform both a cached and uncached reference to the
+ * same cache line.  These special memory cached regions prevent the
+ * kernel from ever dropping in a TLB entry and therefore prevent the
+ * processor from ever speculating a cache line from this page.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/numa.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#include <asm/tlbflush.h>
+#include <asm/uncached.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/mspec.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/io.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/shubio.h>
+
+
+#define FETCHOP_ID     "SGI Fetchop,"
+#define CACHED_ID      "Cached,"
+#define UNCACHED_ID    "Uncached"
+#define REVISION       "4.0"
+#define MSPEC_BASENAME "mspec"
+
+/*
+ * Page types allocated by the device.
+ */
+enum {
+       MSPEC_FETCHOP = 1,
+       MSPEC_CACHED,
+       MSPEC_UNCACHED
+};
+
+static int is_sn2;
+
+/*
+ * One of these structures is allocated when an mspec region is mmaped. The
+ * structure is pointed to by the vma->vm_private_data field in the vma struct.
+ * This structure is used to record the addresses of the mspec pages.
+ */
+struct vma_data {
+       atomic_t refcnt;        /* Number of vmas sharing the data. */
+       spinlock_t lock;        /* Serialize access to the vma. */
+       int count;              /* Number of pages allocated. */
+       int type;               /* Type of pages allocated. */
+       unsigned long maddr[0]; /* Array of MSPEC addresses. */
+};
+
+/* used on shub2 to clear FOP cache in the HUB */
+static unsigned long scratch_page[MAX_NUMNODES];
+#define SH2_AMO_CACHE_ENTRIES  4
+
+static inline int
+mspec_zero_block(unsigned long addr, int len)
+{
+       int status;
+
+       if (is_sn2) {
+               if (is_shub2()) {
+                       int nid;
+                       void *p;
+                       int i;
+
+                       nid = nasid_to_cnodeid(get_node_number(__pa(addr)));
+                       p = (void *)TO_AMO(scratch_page[nid]);
+
+                       for (i=0; i < SH2_AMO_CACHE_ENTRIES; i++) {
+                               FETCHOP_LOAD_OP(p, FETCHOP_LOAD);
+                               p += FETCHOP_VAR_SIZE;
+                       }
+               }
+
+               status = bte_copy(0, addr & ~__IA64_UNCACHED_OFFSET, len,
+                                 BTE_WACQUIRE | BTE_ZERO_FILL, NULL);
+       } else {
+               memset((char *) addr, 0, len);
+               status = 0;
+       }
+       return status;
+}
+
+/*
+ * mspec_open
+ *
+ * Called when a device mapping is created by a means other than mmap
+ * (via fork, etc.).  Increments the reference count on the underlying
+ * mspec data so it is not freed prematurely.
+ */
+static void
+mspec_open(struct vm_area_struct *vma)
+{
+       struct vma_data *vdata;
+
+       vdata = vma->vm_private_data;
+       atomic_inc(&vdata->refcnt);
+}
+
+/*
+ * mspec_close
+ *
+ * Called when unmapping a device mapping. Frees all mspec pages
+ * belonging to the vma.
+ */
+static void
+mspec_close(struct vm_area_struct *vma)
+{
+       struct vma_data *vdata;
+       int i, pages, result, vdata_size;
+
+       vdata = vma->vm_private_data;
+       if (!atomic_dec_and_test(&vdata->refcnt))
+               return;
+
+       pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
+       for (i = 0; i < pages; i++) {
+               if (vdata->maddr[i] == 0)
+                       continue;
+               /*
+                * Clear the page before sticking it back
+                * into the pool.
+                */
+               result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
+               if (!result)
+                       uncached_free_page(vdata->maddr[i]);
+               else
+                       printk(KERN_WARNING "mspec_close(): "
+                              "failed to zero page %i\n",
+                              result);
+       }
+
+       if (vdata_size <= PAGE_SIZE)
+               kfree(vdata);
+       else
+               vfree(vdata);
+}
+
+
+/*
+ * mspec_nopfn
+ *
+ * Creates a mspec page and maps it to user space.
+ */
+static unsigned long
+mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+{
+       unsigned long paddr, maddr;
+       unsigned long pfn;
+       int index;
+       struct vma_data *vdata = vma->vm_private_data;
+
+       index = (address - vma->vm_start) >> PAGE_SHIFT;
+       maddr = (volatile unsigned long) vdata->maddr[index];
+       if (maddr == 0) {
+               maddr = uncached_alloc_page(numa_node_id());
+               if (maddr == 0)
+                       return NOPFN_OOM;
+
+               spin_lock(&vdata->lock);
+               if (vdata->maddr[index] == 0) {
+                       vdata->count++;
+                       vdata->maddr[index] = maddr;
+               } else {
+                       uncached_free_page(maddr);
+                       maddr = vdata->maddr[index];
+               }
+               spin_unlock(&vdata->lock);
+       }
+
+       if (vdata->type == MSPEC_FETCHOP)
+               paddr = TO_AMO(maddr);
+       else
+               paddr = __pa(TO_CAC(maddr));
+
+       pfn = paddr >> PAGE_SHIFT;
+
+       return pfn;
+}
+
+static struct vm_operations_struct mspec_vm_ops = {
+       .open = mspec_open,
+       .close = mspec_close,
+       .nopfn = mspec_nopfn
+};
+
+/*
+ * mspec_mmap
+ *
+ * Called when mmaping the device.  Initializes the vma with a fault handler
+ * and private data structure necessary to allocate, track, and free the
+ * underlying pages.
+ */
+static int
+mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
+{
+       struct vma_data *vdata;
+       int pages, vdata_size;
+
+       if (vma->vm_pgoff != 0)
+               return -EINVAL;
+
+       if ((vma->vm_flags & VM_SHARED) == 0)
+               return -EINVAL;
+
+       if ((vma->vm_flags & VM_WRITE) == 0)
+               return -EPERM;
+
+       pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
+       if (vdata_size <= PAGE_SIZE)
+               vdata = kmalloc(vdata_size, GFP_KERNEL);
+       else
+               vdata = vmalloc(vdata_size);
+       if (!vdata)
+               return -ENOMEM;
+       memset(vdata, 0, vdata_size);
+
+       vdata->type = type;
+       spin_lock_init(&vdata->lock);
+       vdata->refcnt = ATOMIC_INIT(1);
+       vma->vm_private_data = vdata;
+
+       vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+       if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       vma->vm_ops = &mspec_vm_ops;
+
+       return 0;
+}
+
+static int
+fetchop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       return mspec_mmap(file, vma, MSPEC_FETCHOP);
+}
+
+static int
+cached_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       return mspec_mmap(file, vma, MSPEC_CACHED);
+}
+
+static int
+uncached_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       return mspec_mmap(file, vma, MSPEC_UNCACHED);
+}
+
+static struct file_operations fetchop_fops = {
+       .owner = THIS_MODULE,
+       .mmap = fetchop_mmap
+};
+
+static struct miscdevice fetchop_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "sgi_fetchop",
+       .fops = &fetchop_fops
+};
+
+static struct file_operations cached_fops = {
+       .owner = THIS_MODULE,
+       .mmap = cached_mmap
+};
+
+static struct miscdevice cached_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "mspec_cached",
+       .fops = &cached_fops
+};
+
+static struct file_operations uncached_fops = {
+       .owner = THIS_MODULE,
+       .mmap = uncached_mmap
+};
+
+static struct miscdevice uncached_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "mspec_uncached",
+       .fops = &uncached_fops
+};
+
+/*
+ * mspec_init
+ *
+ * Called at boot time to initialize the mspec facility.
+ */
+static int __init
+mspec_init(void)
+{
+       int ret;
+       int nid;
+
+       /*
+        * The fetchop device only works on SN2 hardware, uncached and cached
+        * memory drivers should both be valid on all ia64 hardware
+        */
+       if (ia64_platform_is("sn2")) {
+               is_sn2 = 1;
+               if (is_shub2()) {
+                       ret = -ENOMEM;
+                       for_each_online_node(nid) {
+                               int actual_nid;
+                               int nasid;
+                               unsigned long phys;
+
+                               scratch_page[nid] = uncached_alloc_page(nid);
+                               if (scratch_page[nid] == 0)
+                                       goto free_scratch_pages;
+                               phys = __pa(scratch_page[nid]);
+                               nasid = get_node_number(phys);
+                               actual_nid = nasid_to_cnodeid(nasid);
+                               if (actual_nid != nid)
+                                       goto free_scratch_pages;
+                       }
+               }
+
+               ret = misc_register(&fetchop_miscdev);
+               if (ret) {
+                       printk(KERN_ERR
+                              "%s: failed to register device %i\n",
+                              FETCHOP_ID, ret);
+                       goto free_scratch_pages;
+               }
+       }
+       ret = misc_register(&cached_miscdev);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device %i\n",
+                      CACHED_ID, ret);
+               if (is_sn2)
+                       misc_deregister(&fetchop_miscdev);
+               goto free_scratch_pages;
+       }
+       ret = misc_register(&uncached_miscdev);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device %i\n",
+                      UNCACHED_ID, ret);
+               misc_deregister(&cached_miscdev);
+               if (is_sn2)
+                       misc_deregister(&fetchop_miscdev);
+               goto free_scratch_pages;
+       }
+
+       printk(KERN_INFO "%s %s initialized devices: %s %s %s\n",
+              MSPEC_BASENAME, REVISION, is_sn2 ? FETCHOP_ID : "",
+              CACHED_ID, UNCACHED_ID);
+
+       return 0;
+
+ free_scratch_pages:
+       for_each_node(nid) {
+               if (scratch_page[nid] != 0)
+                       uncached_free_page(scratch_page[nid]);
+       }
+       return ret;
+}
+
+static void __exit
+mspec_exit(void)
+{
+       int nid;
+
+       misc_deregister(&uncached_miscdev);
+       misc_deregister(&cached_miscdev);
+       if (is_sn2) {
+               misc_deregister(&fetchop_miscdev);
+
+               for_each_node(nid) {
+                       if (scratch_page[nid] != 0)
+                               uncached_free_page(scratch_page[nid]);
+               }
+       }
+}
+
+module_init(mspec_init);
+module_exit(mspec_exit);
+
+MODULE_AUTHOR("Silicon Graphics, Inc. <linux-altix@sgi.com>");
+MODULE_DESCRIPTION("Driver for SGI SN special memory operations");
+MODULE_LICENSE("GPL");
index 39a2e661ff550e1ba50848539940c3a0e1e439b6..8d14823b0514ef3b58a4e775aa33cfa72009a4e8 100644 (file)
@@ -297,7 +297,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                " ipcnum %x, usIntCount %x\n",
                                ipcnum,
                                pDrvData->IPCs[ipcnum].usIntCount);
-                       if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+                       if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
                                PRINTK_ERROR(KERN_ERR_MWAVE
                                                "mwavedd::mwave_ioctl:"
                                                " IOCTL_MW_GET_IPC: Error:"
@@ -355,7 +355,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
                                "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
                                " ipcnum %x\n",
                                ipcnum);
-                       if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+                       if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
                                PRINTK_ERROR(KERN_ERR_MWAVE
                                                "mwavedd::mwave_ioctl:"
                                                " IOCTL_MW_UNREGISTER_IPC:"
index 556abd3e0d0735e93ce55415fdf3c14834f69ba6..27a653772049ff6b78050c8f2ff86f2e327b7967 100644 (file)
@@ -2554,71 +2554,7 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
 #define B921600 (B460800 +1)
 #endif
        if (mxser_set_baud_method[info->port] == 0) {
-               switch (cflag & (CBAUD | CBAUDEX)) {
-               case B921600:
-                       baud = 921600;
-                       break;
-               case B460800:
-                       baud = 460800;
-                       break;
-               case B230400:
-                       baud = 230400;
-                       break;
-               case B115200:
-                       baud = 115200;
-                       break;
-               case B57600:
-                       baud = 57600;
-                       break;
-               case B38400:
-                       baud = 38400;
-                       break;
-               case B19200:
-                       baud = 19200;
-                       break;
-               case B9600:
-                       baud = 9600;
-                       break;
-               case B4800:
-                       baud = 4800;
-                       break;
-               case B2400:
-                       baud = 2400;
-                       break;
-               case B1800:
-                       baud = 1800;
-                       break;
-               case B1200:
-                       baud = 1200;
-                       break;
-               case B600:
-                       baud = 600;
-                       break;
-               case B300:
-                       baud = 300;
-                       break;
-               case B200:
-                       baud = 200;
-                       break;
-               case B150:
-                       baud = 150;
-                       break;
-               case B134:
-                       baud = 134;
-                       break;
-               case B110:
-                       baud = 110;
-                       break;
-               case B75:
-                       baud = 75;
-                       break;
-               case B50:
-                       baud = 50;
-                       break;
-               default:
-                       baud = 0;
-                       break;
-               }
+               baud = tty_get_baud_rate(info->tty);
                mxser_set_baud(info, baud);
        }
 
index 84e5a68635f12203c361cf837aab3f2bd4fdbca0..ecfaf180e5bd8b106ee12e06da33fc0c1a88f702 100644 (file)
@@ -188,16 +188,6 @@ static void pc8736x_gpio_set(unsigned minor, int val)
        pc8736x_gpio_shadow[port] = val;
 }
 
-static void pc8736x_gpio_set_high(unsigned index)
-{
-       pc8736x_gpio_set(index, 1);
-}
-
-static void pc8736x_gpio_set_low(unsigned index)
-{
-       pc8736x_gpio_set(index, 0);
-}
-
 static int pc8736x_gpio_current(unsigned minor)
 {
        int port, bit;
index 4c3a5ca9d8f7a98f882cdbeed12f0949af940a55..b430a12eb8190d9266ccd0de322c243021a1086e 100644 (file)
@@ -655,6 +655,7 @@ void add_interrupt_randomness(int irq)
        add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
 }
 
+#ifdef CONFIG_BLOCK
 void add_disk_randomness(struct gendisk *disk)
 {
        if (!disk || !disk->random)
@@ -667,6 +668,7 @@ void add_disk_randomness(struct gendisk *disk)
 }
 
 EXPORT_SYMBOL(add_disk_randomness);
+#endif
 
 #define EXTRACT_SIZE 10
 
@@ -918,6 +920,7 @@ void rand_initialize_irq(int irq)
        }
 }
 
+#ifdef CONFIG_BLOCK
 void rand_initialize_disk(struct gendisk *disk)
 {
        struct timer_rand_state *state;
@@ -932,6 +935,7 @@ void rand_initialize_disk(struct gendisk *disk)
                disk->random = state;
        }
 }
+#endif
 
 static ssize_t
 random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
index 579868af4a54d91be8f0707c96053e3d9bfb7b5e..89b718e326e5a0873ca0002cc76441a3c5469238 100644 (file)
@@ -238,39 +238,14 @@ out:
        return err;
 }
 
-static ssize_t raw_file_write(struct file *file, const char __user *buf,
-                                  size_t count, loff_t *ppos)
-{
-       struct iovec local_iov = {
-               .iov_base = (char __user *)buf,
-               .iov_len = count
-       };
-
-       return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
-static ssize_t raw_file_aio_write(struct kiocb *iocb, const char __user *buf,
-                                       size_t count, loff_t pos)
-{
-       struct iovec local_iov = {
-               .iov_base = (char __user *)buf,
-               .iov_len = count
-       };
-
-       return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
-
 static const struct file_operations raw_fops = {
-       .read   =       generic_file_read,
+       .read   =       do_sync_read,
        .aio_read =     generic_file_aio_read,
-       .write  =       raw_file_write,
-       .aio_write =    raw_file_aio_write,
+       .write  =       do_sync_write,
+       .aio_write =    generic_file_aio_write_nolock,
        .open   =       raw_open,
        .release=       raw_release,
        .ioctl  =       raw_ioctl,
-       .readv  =       generic_file_readv,
-       .writev =       generic_file_writev,
        .owner  =       THIS_MODULE,
 };
 
@@ -288,31 +263,34 @@ static struct cdev raw_cdev = {
 static int __init raw_init(void)
 {
        dev_t dev = MKDEV(RAW_MAJOR, 0);
+       int ret;
 
-       if (register_chrdev_region(dev, MAX_RAW_MINORS, "raw"))
+       ret = register_chrdev_region(dev, MAX_RAW_MINORS, "raw");
+       if (ret)
                goto error;
 
        cdev_init(&raw_cdev, &raw_fops);
-       if (cdev_add(&raw_cdev, dev, MAX_RAW_MINORS)) {
+       ret = cdev_add(&raw_cdev, dev, MAX_RAW_MINORS);
+       if (ret) {
                kobject_put(&raw_cdev.kobj);
-               unregister_chrdev_region(dev, MAX_RAW_MINORS);
-               goto error;
+               goto error_region;
        }
 
        raw_class = class_create(THIS_MODULE, "raw");
        if (IS_ERR(raw_class)) {
                printk(KERN_ERR "Error creating raw class.\n");
                cdev_del(&raw_cdev);
-               unregister_chrdev_region(dev, MAX_RAW_MINORS);
-               goto error;
+               ret = PTR_ERR(raw_class);
+               goto error_region;
        }
        class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
        return 0;
 
+error_region:
+       unregister_chrdev_region(dev, MAX_RAW_MINORS);
 error:
-       printk(KERN_ERR "error register raw device\n");
-       return 1;
+       return ret;
 }
 
 static void __exit raw_exit(void)
index f1c94f771af5e803426fd2f0a707cd7154e66897..06b9f78a95d98224d91e0d70a34c6544bcb4a465 100644 (file)
@@ -675,26 +675,12 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
        port->COR2 = 0;
        port->MSVR = MSVR_RTS;
        
-       baud = C_BAUD(tty);
-       
-       if (baud & CBAUDEX) {
-               baud &= ~CBAUDEX;
-               if (baud < 1 || baud > 2) 
-                       port->tty->termios->c_cflag &= ~CBAUDEX;
-               else
-                       baud += 15;
-       }
-       if (baud == 15)  {
-               if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-                       baud ++;
-               if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-                       baud += 2;
-       }
+       baud = tty_get_baud_rate(tty);
        
        /* Select port on the board */
        rc_out(bp, CD180_CAR, port_No(port));
        
-       if (!baud_table[baud])  {
+       if (!baud)  {
                /* Drop DTR & exit */
                bp->DTR |= (1u << port_No(port));
                rc_out(bp, RC_DTR, bp->DTR);
@@ -710,7 +696,7 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
         */
        
        /* Set baud rate for port */
-       tmp = (((RC_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
+       tmp = (((RC_OSCFREQ + baud/2) / baud +
                CD180_TPC/2) / CD180_TPC);
 
        rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); 
@@ -718,7 +704,7 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
        rc_out(bp, CD180_RBPRL, tmp & 0xff); 
        rc_out(bp, CD180_TBPRL, tmp & 0xff);
        
-       baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
+       baud = (baud + 5) / 10;   /* Estimated CPS */
        
        /* Two timer ticks seems enough to wakeup something like SLIP driver */
        tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;           
index ab6429b4a84e424a9e390d3946bbd1ff6a8c316f..656f8c0ca52effdc31f343360a91309278ae5760 100644 (file)
@@ -1262,10 +1262,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
         * Once the read clears, read the RTC time (again via ioctl). Easy.
         */
 
-       while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
-               barrier();
+       while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100)
                cpu_relax();
-       }
 
        /*
         * Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
deleted file mode 100644 (file)
index 5458ef1..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-/* drivers/char/s3c2410_rtc.c
- *
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
- *                   http://www.simtec.co.uk/products/SWLINUX/
- *
- * 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.
- *
- * S3C2410 Internal RTC Driver
- *
- *  Changelog:
- *     08-Nov-2004     BJD     Initial creation
- *     12-Nov-2004     BJD     Added periodic IRQ and PM code
- *     22-Nov-2004     BJD     Sign-test on alarm code to check for <0
- *     10-Mar-2005     LCVR    Changed S3C2410_VA_RTC to S3C24XX_VA_RTC
-*/
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-#include <linux/clk.h>
-
-#include <asm/hardware.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/rtc.h>
-
-#include <asm/mach/time.h>
-
-#include <asm/arch/regs-rtc.h>
-
-/* need this for the RTC_AF definitions */
-#include <linux/mc146818rtc.h>
-
-#undef S3C24XX_VA_RTC
-#define S3C24XX_VA_RTC s3c2410_rtc_base
-
-static struct resource *s3c2410_rtc_mem;
-
-static void __iomem *s3c2410_rtc_base;
-static int s3c2410_rtc_alarmno = NO_IRQ;
-static int s3c2410_rtc_tickno  = NO_IRQ;
-static int s3c2410_rtc_freq    = 1;
-
-static DEFINE_SPINLOCK(s3c2410_rtc_pie_lock);
-
-/* IRQ Handlers */
-
-static irqreturn_t s3c2410_rtc_alarmirq(int irq, void *id, struct pt_regs *r)
-{
-       rtc_update(1, RTC_AF | RTC_IRQF);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t s3c2410_rtc_tickirq(int irq, void *id, struct pt_regs *r)
-{
-       rtc_update(1, RTC_PF | RTC_IRQF);
-       return IRQ_HANDLED;
-}
-
-/* Update control registers */
-static void s3c2410_rtc_setaie(int to)
-{
-       unsigned int tmp;
-
-       pr_debug("%s: aie=%d\n", __FUNCTION__, to);
-
-       tmp = readb(S3C2410_RTCALM);
-
-       if (to)
-               tmp |= S3C2410_RTCALM_ALMEN;
-       else
-               tmp &= ~S3C2410_RTCALM_ALMEN;
-
-
-       writeb(tmp, S3C2410_RTCALM);
-}
-
-static void s3c2410_rtc_setpie(int to)
-{
-       unsigned int tmp;
-
-       pr_debug("%s: pie=%d\n", __FUNCTION__, to);
-
-       spin_lock_irq(&s3c2410_rtc_pie_lock);
-       tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
-
-       if (to)
-               tmp |= S3C2410_TICNT_ENABLE;
-
-       writeb(tmp, S3C2410_TICNT);
-       spin_unlock_irq(&s3c2410_rtc_pie_lock);
-}
-
-static void s3c2410_rtc_setfreq(int freq)
-{
-       unsigned int tmp;
-
-       spin_lock_irq(&s3c2410_rtc_pie_lock);
-       tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
-
-       s3c2410_rtc_freq = freq;
-
-       tmp |= (128 / freq)-1;
-
-       writeb(tmp, S3C2410_TICNT);
-       spin_unlock_irq(&s3c2410_rtc_pie_lock);
-}
-
-/* Time read/write */
-
-static int s3c2410_rtc_gettime(struct rtc_time *rtc_tm)
-{
-       unsigned int have_retried = 0;
-
- retry_get_time:
-       rtc_tm->tm_min  = readb(S3C2410_RTCMIN);
-       rtc_tm->tm_hour = readb(S3C2410_RTCHOUR);
-       rtc_tm->tm_mday = readb(S3C2410_RTCDATE);
-       rtc_tm->tm_mon  = readb(S3C2410_RTCMON);
-       rtc_tm->tm_year = readb(S3C2410_RTCYEAR);
-       rtc_tm->tm_sec  = readb(S3C2410_RTCSEC);
-
-       /* the only way to work out wether the system was mid-update
-        * when we read it is to check the second counter, and if it
-        * is zero, then we re-try the entire read
-        */
-
-       if (rtc_tm->tm_sec == 0 && !have_retried) {
-               have_retried = 1;
-               goto retry_get_time;
-       }
-
-       pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
-                rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
-                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
-
-       BCD_TO_BIN(rtc_tm->tm_sec);
-       BCD_TO_BIN(rtc_tm->tm_min);
-       BCD_TO_BIN(rtc_tm->tm_hour);
-       BCD_TO_BIN(rtc_tm->tm_mday);
-       BCD_TO_BIN(rtc_tm->tm_mon);
-       BCD_TO_BIN(rtc_tm->tm_year);
-
-       rtc_tm->tm_year += 100;
-       rtc_tm->tm_mon -= 1;
-
-       return 0;
-}
-
-
-static int s3c2410_rtc_settime(struct rtc_time *tm)
-{
-       /* the rtc gets round the y2k problem by just not supporting it */
-
-       if (tm->tm_year < 100)
-               return -EINVAL;
-
-       writeb(BIN2BCD(tm->tm_sec),  S3C2410_RTCSEC);
-       writeb(BIN2BCD(tm->tm_min),  S3C2410_RTCMIN);
-       writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR);
-       writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE);
-       writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON);
-       writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR);
-
-       return 0;
-}
-
-static int s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm)
-{
-       struct rtc_time *alm_tm = &alrm->time;
-       unsigned int alm_en;
-
-       alm_tm->tm_sec  = readb(S3C2410_ALMSEC);
-       alm_tm->tm_min  = readb(S3C2410_ALMMIN);
-       alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
-       alm_tm->tm_mon  = readb(S3C2410_ALMMON);
-       alm_tm->tm_mday = readb(S3C2410_ALMDATE);
-       alm_tm->tm_year = readb(S3C2410_ALMYEAR);
-
-       alm_en = readb(S3C2410_RTCALM);
-
-       pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
-                alm_en,
-                alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
-                alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
-
-
-       /* decode the alarm enable field */
-
-       if (alm_en & S3C2410_RTCALM_SECEN) {
-               BCD_TO_BIN(alm_tm->tm_sec);
-       } else {
-               alm_tm->tm_sec = 0xff;
-       }
-
-       if (alm_en & S3C2410_RTCALM_MINEN) {
-               BCD_TO_BIN(alm_tm->tm_min);
-       } else {
-               alm_tm->tm_min = 0xff;
-       }
-
-       if (alm_en & S3C2410_RTCALM_HOUREN) {
-               BCD_TO_BIN(alm_tm->tm_hour);
-       } else {
-               alm_tm->tm_hour = 0xff;
-       }
-
-       if (alm_en & S3C2410_RTCALM_DAYEN) {
-               BCD_TO_BIN(alm_tm->tm_mday);
-       } else {
-               alm_tm->tm_mday = 0xff;
-       }
-
-       if (alm_en & S3C2410_RTCALM_MONEN) {
-               BCD_TO_BIN(alm_tm->tm_mon);
-               alm_tm->tm_mon -= 1;
-       } else {
-               alm_tm->tm_mon = 0xff;
-       }
-
-       if (alm_en & S3C2410_RTCALM_YEAREN) {
-               BCD_TO_BIN(alm_tm->tm_year);
-       } else {
-               alm_tm->tm_year = 0xffff;
-       }
-
-       /* todo - set alrm->enabled ? */
-
-       return 0;
-}
-
-static int s3c2410_rtc_setalarm(struct rtc_wkalrm *alrm)
-{
-       struct rtc_time *tm = &alrm->time;
-       unsigned int alrm_en;
-
-       pr_debug("s3c2410_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
-                alrm->enabled,
-                tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
-                tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
-
-       if (alrm->enabled || 1) {
-               alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
-               writeb(0x00, S3C2410_RTCALM);
-
-               if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
-                       alrm_en |= S3C2410_RTCALM_SECEN;
-                       writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
-               }
-
-               if (tm->tm_min < 60 && tm->tm_min >= 0) {
-                       alrm_en |= S3C2410_RTCALM_MINEN;
-                       writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN);
-               }
-
-               if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
-                       alrm_en |= S3C2410_RTCALM_HOUREN;
-                       writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR);
-               }
-
-               pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
-
-               writeb(alrm_en, S3C2410_RTCALM);
-               enable_irq_wake(s3c2410_rtc_alarmno);
-       } else {
-               alrm_en = readb(S3C2410_RTCALM);
-               alrm_en &= ~S3C2410_RTCALM_ALMEN;
-               writeb(alrm_en, S3C2410_RTCALM);
-               disable_irq_wake(s3c2410_rtc_alarmno);
-       }
-
-       return 0;
-}
-
-static int s3c2410_rtc_ioctl(unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case RTC_AIE_OFF:
-       case RTC_AIE_ON:
-               s3c2410_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
-               return 0;
-
-       case RTC_PIE_OFF:
-       case RTC_PIE_ON:
-               s3c2410_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
-               return 0;
-
-       case RTC_IRQP_READ:
-               return put_user(s3c2410_rtc_freq, (unsigned long __user *)arg);
-
-       case RTC_IRQP_SET:
-               if (arg < 1 || arg > 64)
-                       return -EINVAL;
-
-               if (!capable(CAP_SYS_RESOURCE))
-                       return -EACCES;
-
-               /* check for power of 2 */
-
-               if ((arg & (arg-1)) != 0)
-                       return -EINVAL;
-
-               pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
-
-               s3c2410_rtc_setfreq(arg);
-               return 0;
-
-       case RTC_UIE_ON:
-       case RTC_UIE_OFF:
-               return -EINVAL;
-       }
-
-       return -EINVAL;
-}
-
-static int s3c2410_rtc_proc(char *buf)
-{
-       unsigned int rtcalm = readb(S3C2410_RTCALM);
-       unsigned int ticnt = readb (S3C2410_TICNT);
-       char *p = buf;
-
-       p += sprintf(p, "alarm_IRQ\t: %s\n",
-                    (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
-       p += sprintf(p, "periodic_IRQ\t: %s\n",
-                    (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
-       p += sprintf(p, "periodic_freq\t: %d\n", s3c2410_rtc_freq);
-
-       return p - buf;
-}
-
-static int s3c2410_rtc_open(void)
-{
-       int ret;
-
-       ret = request_irq(s3c2410_rtc_alarmno, s3c2410_rtc_alarmirq,
-                         IRQF_DISABLED,  "s3c2410-rtc alarm", NULL);
-
-       if (ret)
-               printk(KERN_ERR "IRQ%d already in use\n", s3c2410_rtc_alarmno);
-
-       ret = request_irq(s3c2410_rtc_tickno, s3c2410_rtc_tickirq,
-                         IRQF_DISABLED,  "s3c2410-rtc tick", NULL);
-
-       if (ret) {
-               printk(KERN_ERR "IRQ%d already in use\n", s3c2410_rtc_tickno);
-               goto tick_err;
-       }
-
-       return ret;
-
- tick_err:
-       free_irq(s3c2410_rtc_alarmno, NULL);
-       return ret;
-}
-
-static void s3c2410_rtc_release(void)
-{
-       /* do not clear AIE here, it may be needed for wake */
-
-       s3c2410_rtc_setpie(0);
-       free_irq(s3c2410_rtc_alarmno, NULL);
-       free_irq(s3c2410_rtc_tickno, NULL);
-}
-
-static struct rtc_ops s3c2410_rtcops = {
-       .owner          = THIS_MODULE,
-       .open           = s3c2410_rtc_open,
-       .release        = s3c2410_rtc_release,
-       .ioctl          = s3c2410_rtc_ioctl,
-       .read_time      = s3c2410_rtc_gettime,
-       .set_time       = s3c2410_rtc_settime,
-       .read_alarm     = s3c2410_rtc_getalarm,
-       .set_alarm      = s3c2410_rtc_setalarm,
-       .proc           = s3c2410_rtc_proc,
-};
-
-static void s3c2410_rtc_enable(struct platform_device *pdev, int en)
-{
-       unsigned int tmp;
-
-       if (s3c2410_rtc_base == NULL)
-               return;
-
-       if (!en) {
-               tmp = readb(S3C2410_RTCCON);
-               writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON);
-
-               tmp = readb(S3C2410_TICNT);
-               writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT);
-       } else {
-               /* re-enable the device, and check it is ok */
-
-               if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
-                       dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
-
-                       tmp = readb(S3C2410_RTCCON);
-                       writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON);
-               }
-
-               if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
-                       dev_info(&pdev->dev, "removing S3C2410_RTCCON_CNTSEL\n");
-
-                       tmp = readb(S3C2410_RTCCON);
-                       writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON);
-               }
-
-               if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
-                       dev_info(&pdev->dev, "removing S3C2410_RTCCON_CLKRST\n");
-
-                       tmp = readb(S3C2410_RTCCON);
-                       writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON);
-               }
-       }
-}
-
-static int s3c2410_rtc_remove(struct platform_device *dev)
-{
-       unregister_rtc(&s3c2410_rtcops);
-
-       s3c2410_rtc_setpie(0);
-       s3c2410_rtc_setaie(0);
-
-       if (s3c2410_rtc_mem != NULL) {
-               pr_debug("s3c2410_rtc: releasing s3c2410_rtc_mem\n");
-               iounmap(s3c2410_rtc_base);
-               release_resource(s3c2410_rtc_mem);
-               kfree(s3c2410_rtc_mem);
-       }
-
-       return 0;
-}
-
-static int s3c2410_rtc_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int ret;
-
-       pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);
-
-       /* find the IRQs */
-
-       s3c2410_rtc_tickno = platform_get_irq(pdev, 1);
-       if (s3c2410_rtc_tickno < 0) {
-               dev_err(&pdev->dev, "no irq for rtc tick\n");
-               return -ENOENT;
-       }
-
-       s3c2410_rtc_alarmno = platform_get_irq(pdev, 0);
-       if (s3c2410_rtc_alarmno < 0) {
-               dev_err(&pdev->dev, "no irq for alarm\n");
-               return -ENOENT;
-       }
-
-       pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
-                s3c2410_rtc_tickno, s3c2410_rtc_alarmno);
-
-       /* get the memory region */
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-
-       s3c2410_rtc_mem = request_mem_region(res->start, res->end-res->start+1,
-                                    pdev->name);
-
-       if (s3c2410_rtc_mem == NULL) {
-               dev_err(&pdev->dev, "failed to reserve memory region\n");
-               ret = -ENOENT;
-               goto exit_err;
-       }
-
-       s3c2410_rtc_base = ioremap(res->start, res->end - res->start + 1);
-       if (s3c2410_rtc_base == NULL) {
-               dev_err(&pdev->dev, "failed ioremap()\n");
-               ret = -EINVAL;
-               goto exit_err;
-       }
-
-       s3c2410_rtc_mem = res;
-       pr_debug("s3c2410_rtc_base=%p\n", s3c2410_rtc_base);
-
-       pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
-
-       /* check to see if everything is setup correctly */
-
-       s3c2410_rtc_enable(pdev, 1);
-
-       pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
-
-       s3c2410_rtc_setfreq(s3c2410_rtc_freq);
-
-       /* register RTC and exit */
-
-       register_rtc(&s3c2410_rtcops);
-       return 0;
-
- exit_err:
-       dev_err(&pdev->dev, "error %d during initialisation\n", ret);
-
-       return ret;
-}
-
-#ifdef CONFIG_PM
-
-/* S3C2410 RTC Power management control */
-
-static struct timespec s3c2410_rtc_delta;
-
-static int ticnt_save;
-
-static int s3c2410_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(S3C2410_TICNT);
-
-       /* calculate time delta for suspend */
-
-       s3c2410_rtc_gettime(&tm);
-       rtc_tm_to_time(&tm, &time.tv_sec);
-       save_time_delta(&s3c2410_rtc_delta, &time);
-       s3c2410_rtc_enable(pdev, 0);
-
-       return 0;
-}
-
-static int s3c2410_rtc_resume(struct platform_device *pdev)
-{
-       struct rtc_time tm;
-       struct timespec time;
-
-       time.tv_nsec = 0;
-
-       s3c2410_rtc_enable(pdev, 1);
-       s3c2410_rtc_gettime(&tm);
-       rtc_tm_to_time(&tm, &time.tv_sec);
-       restore_time_delta(&s3c2410_rtc_delta, &time);
-
-       writeb(ticnt_save, S3C2410_TICNT);
-       return 0;
-}
-#else
-#define s3c2410_rtc_suspend NULL
-#define s3c2410_rtc_resume  NULL
-#endif
-
-static struct platform_driver s3c2410_rtcdrv = {
-       .probe          = s3c2410_rtc_probe,
-       .remove         = s3c2410_rtc_remove,
-       .suspend        = s3c2410_rtc_suspend,
-       .resume         = s3c2410_rtc_resume,
-       .driver         = {
-               .name   = "s3c2410-rtc",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static char __initdata banner[] = "S3C2410 RTC, (c) 2004 Simtec Electronics\n";
-
-static int __init s3c2410_rtc_init(void)
-{
-       printk(banner);
-       return platform_driver_register(&s3c2410_rtcdrv);
-}
-
-static void __exit s3c2410_rtc_exit(void)
-{
-       platform_driver_unregister(&s3c2410_rtcdrv);
-}
-
-module_init(s3c2410_rtc_init);
-module_exit(s3c2410_rtc_exit);
-
-MODULE_DESCRIPTION("S3C24XX RTC Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
index b956c7babd18a8a4933d6a99e74bd86ceb63c62d..99e5272e3c53e1ef1aa32f0733b1bbf0e9f2487e 100644 (file)
@@ -44,7 +44,7 @@ struct nsc_gpio_ops scx200_gpio_ops = {
        .gpio_change    = scx200_gpio_change,
        .gpio_current   = scx200_gpio_current
 };
-EXPORT_SYMBOL(scx200_gpio_ops);
+EXPORT_SYMBOL_GPL(scx200_gpio_ops);
 
 static int scx200_gpio_open(struct inode *inode, struct file *file)
 {
@@ -69,7 +69,7 @@ static const struct file_operations scx200_gpio_fileops = {
        .release = scx200_gpio_release,
 };
 
-struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
+static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
 
 static int __init scx200_gpio_init(void)
 {
index 71093a9fc462ac8f562a8c8e980a7d7deceadd89..74cff839c8572c9bf560640b0ea513938627fd54 100644 (file)
@@ -33,7 +33,7 @@ extern void poke_blanked_console(void);
 
 /* Variables for selection control. */
 /* Use a dynamic buffer, instead of static (Dec 1994) */
-struct vc_data *sel_cons;              /* must not be disallocated */
+struct vc_data *sel_cons;              /* must not be deallocated */
 static volatile int sel_start = -1;    /* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
index a1d303f9a33dd30fa2260b82cacf4fdf1fa78308..f52c7c31badf0544bd7024aa12d8feaffeeb4699 100644 (file)
@@ -182,7 +182,6 @@ static int sx_poll = HZ;
 #define RS_EVENT_WRITE_WAKEUP  0
 
 static struct tty_driver *specialix_driver;
-static unsigned char * tmp_buf;
 
 static unsigned long baud_table[] =  {
        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -1087,24 +1086,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
                port->MSVR =  (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
        spin_unlock_irqrestore(&bp->lock, flags);
        dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
-       baud = C_BAUD(tty);
+       baud = tty_get_baud_rate(tty);
 
-       if (baud & CBAUDEX) {
-               baud &= ~CBAUDEX;
-               if (baud < 1 || baud > 2)
-                       port->tty->termios->c_cflag &= ~CBAUDEX;
-               else
-                       baud += 15;
-       }
-       if (baud == 15) {
+       if (baud == 38400) {
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
                        baud ++;
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
                        baud += 2;
        }
 
-
-       if (!baud_table[baud]) {
+       if (!baud) {
                /* Drop DTR & exit */
                dprintk (SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
                if (!SX_CRTSCTS (tty)) {
@@ -1134,7 +1125,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
                                  "This is an untested option, please be carefull.\n",
                                  port_No (port), tmp);
        else
-               tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
+               tmp = (((SX_OSCFREQ + baud/2) / baud +
                         CD186x_TPC/2) / CD186x_TPC);
 
        if ((tmp < 0x10) && time_before(again, jiffies)) {
@@ -1682,7 +1673,7 @@ static int sx_write(struct tty_struct * tty,
 
        bp = port_Board(port);
 
-       if (!port->xmit_buf || !tmp_buf) {
+       if (!port->xmit_buf) {
                func_exit();
                return 0;
        }
@@ -2406,12 +2397,6 @@ static int sx_init_drivers(void)
                return 1;
        }
 
-       if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
-               printk(KERN_ERR "sx: Couldn't get free page.\n");
-               put_tty_driver(specialix_driver);
-               func_exit();
-               return 1;
-       }
        specialix_driver->owner = THIS_MODULE;
        specialix_driver->name = "ttyW";
        specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
@@ -2425,7 +2410,6 @@ static int sx_init_drivers(void)
 
        if ((error = tty_register_driver(specialix_driver))) {
                put_tty_driver(specialix_driver);
-               free_page((unsigned long)tmp_buf);
                printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
                       error);
                func_exit();
@@ -2451,7 +2435,6 @@ static void sx_release_drivers(void)
 {
        func_enter();
 
-       free_page((unsigned long)tmp_buf);
        tty_unregister_driver(specialix_driver);
        put_tty_driver(specialix_driver);
        func_exit();
index 2f07b085536b8879b67ece97348a1126074e2a6d..78bc85180c82d692c4201cf6a692f735fe8ad561 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $
+ * $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $
  *
  * Device driver for Microgate SyncLink GT serial adapters.
  *
  * module identification
  */
 static char *driver_name     = "SyncLink GT";
-static char *driver_version  = "$Revision: 4.25 $";
+static char *driver_version  = "$Revision: 4.36 $";
 static char *tty_driver_name = "synclink_gt";
 static char *tty_dev_prefix  = "ttySLG";
 MODULE_LICENSE("GPL");
 #define MGSL_MAGIC 0x5401
-#define MAX_DEVICES 12
+#define MAX_DEVICES 32
 
 static struct pci_device_id pci_table[] = {
        {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
@@ -461,7 +461,7 @@ static int  adapter_test(struct slgt_info *info);
 static void reset_adapter(struct slgt_info *info);
 static void reset_port(struct slgt_info *info);
 static void async_mode(struct slgt_info *info);
-static void hdlc_mode(struct slgt_info *info);
+static void sync_mode(struct slgt_info *info);
 
 static void rx_stop(struct slgt_info *info);
 static void rx_start(struct slgt_info *info);
@@ -881,7 +881,9 @@ static int write(struct tty_struct *tty,
        if (!count)
                goto cleanup;
 
-       if (info->params.mode == MGSL_MODE_RAW) {
+       if (info->params.mode == MGSL_MODE_RAW ||
+           info->params.mode == MGSL_MODE_MONOSYNC ||
+           info->params.mode == MGSL_MODE_BISYNC) {
                unsigned int bufs_needed = (count/DMABUFSIZE);
                unsigned int bufs_free = free_tbuf_count(info);
                if (count % DMABUFSIZE)
@@ -1897,6 +1899,8 @@ static void bh_handler(void* context)
                                while(rx_get_frame(info));
                                break;
                        case MGSL_MODE_RAW:
+                       case MGSL_MODE_MONOSYNC:
+                       case MGSL_MODE_BISYNC:
                                while(rx_get_buf(info));
                                break;
                        }
@@ -2362,10 +2366,9 @@ static void program_hw(struct slgt_info *info)
        rx_stop(info);
        tx_stop(info);
 
-       if (info->params.mode == MGSL_MODE_HDLC ||
-           info->params.mode == MGSL_MODE_RAW ||
+       if (info->params.mode != MGSL_MODE_ASYNC ||
            info->netcount)
-               hdlc_mode(info);
+               sync_mode(info);
        else
                async_mode(info);
 
@@ -2564,6 +2567,10 @@ static int rx_enable(struct slgt_info *info, int enable)
        if (enable) {
                if (!info->rx_enabled)
                        rx_start(info);
+               else if (enable == 2) {
+                       /* force hunt mode (write 1 to RCR[3]) */
+                       wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
+               }
        } else {
                if (info->rx_enabled)
                        rx_stop(info);
@@ -3748,7 +3755,7 @@ static void tx_start(struct slgt_info *info)
 {
        if (!info->tx_enabled) {
                wr_reg16(info, TCR,
-                       (unsigned short)(rd_reg16(info, TCR) | BIT1));
+                        (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
                info->tx_enabled = TRUE;
        }
 
@@ -3775,13 +3782,18 @@ static void tx_start(struct slgt_info *info)
                                tdma_reset(info);
                                /* set 1st descriptor address */
                                wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
-                               if (info->params.mode == MGSL_MODE_RAW)
+                               switch(info->params.mode) {
+                               case MGSL_MODE_RAW:
+                               case MGSL_MODE_MONOSYNC:
+                               case MGSL_MODE_BISYNC:
                                        wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
-                               else
+                                       break;
+                               default:
                                        wr_reg32(info, TDCSR, BIT0); /* DMA enable */
+                               }
                        }
 
-                       if (info->params.mode != MGSL_MODE_RAW) {
+                       if (info->params.mode == MGSL_MODE_HDLC) {
                                info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
                                add_timer(&info->tx_timer);
                        }
@@ -3814,7 +3826,6 @@ static void tx_stop(struct slgt_info *info)
        /* reset and disable transmitter */
        val = rd_reg16(info, TCR) & ~BIT1;          /* clear enable bit */
        wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-       wr_reg16(info, TCR, val);                  /* clear reset */
 
        slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
 
@@ -3982,7 +3993,7 @@ static void async_mode(struct slgt_info *info)
                enable_loopback(info);
 }
 
-static void hdlc_mode(struct slgt_info *info)
+static void sync_mode(struct slgt_info *info)
 {
        unsigned short val;
 
@@ -3992,7 +4003,7 @@ static void hdlc_mode(struct slgt_info *info)
 
        /* TCR (tx control)
         *
-        * 15..13  mode, 000=HDLC 001=raw sync
+        * 15..13  mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
         * 12..10  encoding
         * 09      CRC enable
         * 08      CRC32
@@ -4006,8 +4017,11 @@ static void hdlc_mode(struct slgt_info *info)
         */
        val = 0;
 
-       if (info->params.mode == MGSL_MODE_RAW)
-               val |= BIT13;
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+       case MGSL_MODE_BISYNC:   val |= BIT15; break;
+       case MGSL_MODE_RAW:      val |= BIT13; break;
+       }
        if (info->if_mode & MGSL_INTERFACE_RTS_EN)
                val |= BIT7;
 
@@ -4058,7 +4072,7 @@ static void hdlc_mode(struct slgt_info *info)
 
        /* RCR (rx control)
         *
-        * 15..13  mode, 000=HDLC 001=raw sync
+        * 15..13  mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
         * 12..10  encoding
         * 09      CRC enable
         * 08      CRC32
@@ -4069,8 +4083,11 @@ static void hdlc_mode(struct slgt_info *info)
         */
        val = 0;
 
-       if (info->params.mode == MGSL_MODE_RAW)
-               val |= BIT13;
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+       case MGSL_MODE_BISYNC:   val |= BIT15; break;
+       case MGSL_MODE_RAW:      val |= BIT13; break;
+       }
 
        switch(info->params.encoding)
        {
@@ -4309,10 +4326,15 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
        while(!done) {
                /* reset current buffer for reuse */
                info->rbufs[i].status = 0;
-               if (info->params.mode == MGSL_MODE_RAW)
+               switch(info->params.mode) {
+               case MGSL_MODE_RAW:
+               case MGSL_MODE_MONOSYNC:
+               case MGSL_MODE_BISYNC:
                        set_desc_count(info->rbufs[i], info->raw_rx_size);
-               else
+                       break;
+               default:
                        set_desc_count(info->rbufs[i], DMABUFSIZE);
+               }
 
                if (i == last)
                        done = 1;
@@ -4477,13 +4499,24 @@ cleanup:
 static int rx_get_buf(struct slgt_info *info)
 {
        unsigned int i = info->rbuf_current;
+       unsigned int count;
 
        if (!desc_complete(info->rbufs[i]))
                return 0;
-       DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx");
-       DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i])));
-       ldisc_receive_buf(info->tty, info->rbufs[i].buf,
-                         info->flag_buf, desc_count(info->rbufs[i]));
+       count = desc_count(info->rbufs[i]);
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC:
+       case MGSL_MODE_BISYNC:
+               /* ignore residue in byte synchronous modes */
+               if (desc_residue(info->rbufs[i]))
+                       count--;
+               break;
+       }
+       DBGDATA(info, info->rbufs[i].buf, count, "rx");
+       DBGINFO(("rx_get_buf size=%d\n", count));
+       if (count)
+               ldisc_receive_buf(info->tty, info->rbufs[i].buf,
+                                 info->flag_buf, count);
        free_rbufs(info, i, i);
        return 1;
 }
@@ -4549,8 +4582,13 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
                size -= count;
                buf  += count;
 
-               if (!size && info->params.mode != MGSL_MODE_RAW)
-                       set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */
+               /*
+                * set EOF bit for last buffer of HDLC frame or
+                * for every buffer in raw mode
+                */
+               if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
+                   info->params.mode == MGSL_MODE_RAW)
+                       set_desc_eof(*d, 1);
                else
                        set_desc_eof(*d, 0);
 
index ee3ca8f1768e9be995a62a252404ad4712d5d6bc..6b4d4d1e343da3332f413b8d47c65b00e9ff4a0b 100644 (file)
@@ -113,6 +113,7 @@ static struct sysrq_key_op sysrq_crashdump_op = {
 static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
                                struct tty_struct *tty)
 {
+       lockdep_off();
        local_irq_enable();
        emergency_restart();
 }
@@ -208,7 +209,7 @@ static void send_sig_all(int sig)
        struct task_struct *p;
 
        for_each_process(p) {
-               if (p->mm && p->pid != 1)
+               if (p->mm && !is_init(p))
                        /* Not swapper, init nor kernel thread */
                        force_sig(sig, p);
        }
index bb0d9199e994867544bfc82da5d6530cd6dfe787..333741770f1e079f2fbe0df98b69699a4194f924 100644 (file)
@@ -129,6 +129,7 @@ LIST_HEAD(tty_drivers);                     /* linked list of tty drivers */
 /* Semaphore to protect creating and releasing a tty. This is shared with
    vt.c for deeply disgusting hack reasons */
 DEFINE_MUTEX(tty_mutex);
+EXPORT_SYMBOL(tty_mutex);
 
 #ifdef CONFIG_UNIX98_PTYS
 extern struct tty_driver *ptm_driver;  /* Unix98 pty masters; for /dev/ptmx */
@@ -160,17 +161,11 @@ static void release_mem(struct tty_struct *tty, int idx);
  *     been initialized in any way but has been zeroed
  *
  *     Locking: none
- *     FIXME: use kzalloc
  */
 
 static struct tty_struct *alloc_tty_struct(void)
 {
-       struct tty_struct *tty;
-
-       tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
-       if (tty)
-               memset(tty, 0, sizeof(struct tty_struct));
-       return tty;
+       return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
 }
 
 static void tty_buffer_free_all(struct tty_struct *);
@@ -483,10 +478,9 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
                tb->used += space;
                copied += space;
                chars += space;
-       }
-       /* There is a small chance that we need to split the data over
-          several buffers. If this is the case we must loop */
-       while (unlikely(size > copied));
+               /* There is a small chance that we need to split the data over
+                  several buffers. If this is the case we must loop */
+       } while (unlikely(size > copied));
        return copied;
 }
 EXPORT_SYMBOL(tty_insert_flip_string);
@@ -521,10 +515,9 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
                copied += space;
                chars += space;
                flags += space;
-       }
-       /* There is a small chance that we need to split the data over
-          several buffers. If this is the case we must loop */
-       while (unlikely(size > copied));
+               /* There is a small chance that we need to split the data over
+                  several buffers. If this is the case we must loop */
+       } while (unlikely(size > copied));
        return copied;
 }
 EXPORT_SYMBOL(tty_insert_flip_string_flags);
@@ -626,9 +619,9 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
  
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 {
-       down(&tty->termios_sem);
+       mutex_lock(&tty->termios_mutex);
        tty->termios->c_line = num;
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
 }
 
 /*
@@ -1346,9 +1339,9 @@ static void do_tty_hangup(void *data)
         */
        if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
        {
-               down(&tty->termios_sem);
+               mutex_lock(&tty->termios_mutex);
                *tty->termios = tty->driver->init_termios;
-               up(&tty->termios_sem);
+               mutex_unlock(&tty->termios_mutex);
        }
        
        /* Defer ldisc switch */
@@ -2072,8 +2065,9 @@ fail_no_mem:
 
        /* call the tty release_mem routine to clean out this slot */
 release_mem_out:
-       printk(KERN_INFO "init_dev: ldisc open failed, "
-                        "clearing slot %d\n", idx);
+       if (printk_ratelimit())
+               printk(KERN_INFO "init_dev: ldisc open failed, "
+                                "clearing slot %d\n", idx);
        release_mem(tty, idx);
        goto end_init;
 }
@@ -2726,6 +2720,8 @@ static int tty_fasync(int fd, struct file * filp, int on)
  *     Locking:
  *             Called functions take tty_ldisc_lock
  *             current->signal->tty check is safe without locks
+ *
+ *     FIXME: may race normal receive processing
  */
 
 static int tiocsti(struct tty_struct *tty, char __user *p)
@@ -2748,18 +2744,21 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
  *     @tty; tty
  *     @arg: user buffer for result
  *
- *     Copies the kernel idea of the window size into the user buffer. No
- *     locking is done.
+ *     Copies the kernel idea of the window size into the user buffer.
  *
- *     FIXME: Returning random values racing a window size set is wrong
- *     should lock here against that
+ *     Locking: tty->termios_sem is taken to ensure the winsize data
+ *             is consistent.
  */
 
 static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
 {
-       if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
-               return -EFAULT;
-       return 0;
+       int err;
+
+       mutex_lock(&tty->termios_mutex);
+       err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
+       mutex_unlock(&tty->termios_mutex);
+
+       return err ? -EFAULT: 0;
 }
 
 /**
@@ -2772,12 +2771,11 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
  *     actually has driver level meaning and triggers a VC resize.
  *
  *     Locking:
- *             The console_sem is used to ensure we do not try and resize
- *     the console twice at once.
- *     FIXME: Two racing size sets may leave the console and kernel
- *             parameters disagreeing. Is this exploitable ?
- *     FIXME: Random values racing a window size get is wrong
- *     should lock here against that
+ *             Called function use the console_sem is used to ensure we do
+ *     not try and resize the console twice at once.
+ *             The tty->termios_sem is used to ensure we don't double
+ *     resize and get confused. Lock order - tty->termios.sem before
+ *     console sem
  */
 
 static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
@@ -2787,17 +2785,18 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
 
        if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
                return -EFAULT;
+
+       mutex_lock(&tty->termios_mutex);
        if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
-               return 0;
+               goto done;
+
 #ifdef CONFIG_VT
        if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
-               int rc;
-
-               acquire_console_sem();
-               rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
-               release_console_sem();
-               if (rc)
-                       return -ENXIO;
+               if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
+                                       tmp_ws.ws_row)) {
+                       mutex_unlock(&tty->termios_mutex);
+                       return -ENXIO;
+               }
        }
 #endif
        if (tty->pgrp > 0)
@@ -2806,6 +2805,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
                kill_pg(real_tty->pgrp, SIGWINCH, 1);
        tty->winsize = tmp_ws;
        real_tty->winsize = tmp_ws;
+done:
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 
@@ -2880,9 +2881,7 @@ static int fionbio(struct file *file, int __user *p)
  *     Locking:
  *             Takes tasklist lock internally to walk sessions
  *             Takes task_lock() when updating signal->tty
- *
- *     FIXME: tty_mutex is needed to protect signal->tty references.
- *     FIXME: why task_lock on the signal->tty reference ??
+ *             Takes tty_mutex() to protect tty instance
  *
  */
 
@@ -2917,9 +2916,11 @@ static int tiocsctty(struct tty_struct *tty, int arg)
                } else
                        return -EPERM;
        }
+       mutex_lock(&tty_mutex);
        task_lock(current);
        current->signal->tty = tty;
        task_unlock(current);
+       mutex_unlock(&tty_mutex);
        current->signal->tty_old_pgrp = 0;
        tty->session = current->signal->session;
        tty->pgrp = process_group(current);
@@ -2959,8 +2960,6 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
  *     permitted where the tty session is our session.
  *
  *     Locking: None
- *
- *     FIXME: current->signal->tty referencing is unsafe.
  */
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3039,19 +3038,20 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
  *     timed break functionality.
  *
  *     Locking:
- *             None
+ *             atomic_write_lock serializes
  *
- *     FIXME:
- *             What if two overlap
  */
 
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
+       if (mutex_lock_interruptible(&tty->atomic_write_lock))
+               return -EINTR;
        tty->driver->break_ctl(tty, -1);
        if (!signal_pending(current)) {
                msleep_interruptible(duration);
        }
        tty->driver->break_ctl(tty, 0);
+       mutex_unlock(&tty->atomic_write_lock);
        if (signal_pending(current))
                return -EINTR;
        return 0;
@@ -3144,6 +3144,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
                return -EINVAL;
 
+       /* CHECKME: is this safe as one end closes ? */
+
        real_tty = tty;
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
            tty->driver->subtype == PTY_TYPE_MASTER)
@@ -3580,7 +3582,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
        tty_buffer_init(tty);
        INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
        init_MUTEX(&tty->buf.pty_sem);
-       init_MUTEX(&tty->termios_sem);
+       mutex_init(&tty->termios_mutex);
        init_waitqueue_head(&tty->write_wait);
        init_waitqueue_head(&tty->read_wait);
        INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
index 4ad47d321bd426eb9e34364b4ad4c44c200fab43..3b6fa7b0be8ba81c1f9d658cf63740394225172d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -131,7 +132,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
 
        /* FIXME: we need to decide on some locking/ordering semantics
           for the set_termios notification eventually */
-       down(&tty->termios_sem);
+       mutex_lock(&tty->termios_mutex);
 
        *tty->termios = *new_termios;
        unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
@@ -176,7 +177,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
                        (ld->set_termios)(tty, &old_termios);
                tty_ldisc_deref(ld);
        }
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
 }
 
 /**
@@ -284,13 +285,13 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
 {
        struct sgttyb tmp;
 
-       down(&tty->termios_sem);
+       mutex_lock(&tty->termios_mutex);
        tmp.sg_ispeed = 0;
        tmp.sg_ospeed = 0;
        tmp.sg_erase = tty->termios->c_cc[VERASE];
        tmp.sg_kill = tty->termios->c_cc[VKILL];
        tmp.sg_flags = get_sgflags(tty);
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
        
        return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
@@ -345,12 +346,12 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
        if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
                return -EFAULT;
 
-       down(&tty->termios_sem);                
+       mutex_lock(&tty->termios_mutex);
        termios =  *tty->termios;
        termios.c_cc[VERASE] = tmp.sg_erase;
        termios.c_cc[VKILL] = tmp.sg_kill;
        set_sgflags(&termios, tmp.sg_flags);
-       up(&tty->termios_sem);
+       mutex_unlock(&tty->termios_mutex);
        change_termios(tty, &termios);
        return 0;
 }
@@ -422,24 +423,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
  *
  *     Send a high priority character to the tty even if stopped
  *
- *     Locking: none
- *
- *     FIXME: overlapping calls with start/stop tty lose state of tty
+ *     Locking: none for xchar method, write ordering for write method.
  */
 
-static void send_prio_char(struct tty_struct *tty, char ch)
+static int send_prio_char(struct tty_struct *tty, char ch)
 {
        int     was_stopped = tty->stopped;
 
        if (tty->driver->send_xchar) {
                tty->driver->send_xchar(tty, ch);
-               return;
+               return 0;
        }
+
+       if (mutex_lock_interruptible(&tty->atomic_write_lock))
+               return -ERESTARTSYS;
+
        if (was_stopped)
                start_tty(tty);
        tty->driver->write(tty, &ch, 1);
        if (was_stopped)
                stop_tty(tty);
+       mutex_unlock(&tty->atomic_write_lock);
+       return 0;
 }
 
 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
@@ -513,11 +518,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                                break;
                        case TCIOFF:
                                if (STOP_CHAR(tty) != __DISABLED_CHAR)
-                                       send_prio_char(tty, STOP_CHAR(tty));
+                                       return send_prio_char(tty, STOP_CHAR(tty));
                                break;
                        case TCION:
                                if (START_CHAR(tty) != __DISABLED_CHAR)
-                                       send_prio_char(tty, START_CHAR(tty));
+                                       return send_prio_char(tty, START_CHAR(tty));
                                break;
                        default:
                                return -EINVAL;
@@ -592,11 +597,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                case TIOCSSOFTCAR:
                        if (get_user(arg, (unsigned int __user *) arg))
                                return -EFAULT;
-                       down(&tty->termios_sem);
+                       mutex_lock(&tty->termios_mutex);
                        tty->termios->c_cflag =
                                ((tty->termios->c_cflag & ~CLOCAL) |
                                 (arg ? CLOCAL : 0));
-                       up(&tty->termios_sem);
+                       mutex_unlock(&tty->termios_mutex);
                        return 0;
                default:
                        return -ENOIOCTLCMD;
index a9247b5213d58e10708cef11b85892ccc8cb6a68..bd7a98c6ea7afb6b94bb392381157aa9e945c339 100644 (file)
@@ -474,14 +474,15 @@ static const struct file_operations vcs_fops = {
 
 static struct class *vc_class;
 
-void vcs_make_devfs(struct tty_struct *tty)
+void vcs_make_sysfs(struct tty_struct *tty)
 {
        class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
                        NULL, "vcs%u", tty->index + 1);
        class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
                        NULL, "vcsa%u", tty->index + 1);
 }
-void vcs_remove_devfs(struct tty_struct *tty)
+
+void vcs_remove_sysfs(struct tty_struct *tty)
 {
        class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
        class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
index da7e66a2a38b5dcda25270c6b4329069f36a886f..fb75da940b59c971472812795b3094966b5c8b73 100644 (file)
  *
  * Removed console_lock, enabled interrupts across all console operations
  * 13 March 2001, Andrew Morton
+ *
+ * Fixed UTF-8 mode so alternate charset modes always work according
+ * to control sequences interpreted in do_con_trol function
+ * preserving backward VT100 semigraphics compatibility,
+ * malformed UTF sequences represented as sequences of replacement glyphs,
+ * original codes or '?' as a last resort if replacement glyph is undefined
+ * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
  */
 
 #include <linux/module.h>
@@ -128,8 +135,8 @@ const struct consw *conswitchp;
 #define DEFAULT_BELL_PITCH     750
 #define DEFAULT_BELL_DURATION  (HZ/8)
 
-extern void vcs_make_devfs(struct tty_struct *tty);
-extern void vcs_remove_devfs(struct tty_struct *tty);
+extern void vcs_make_sysfs(struct tty_struct *tty);
+extern void vcs_remove_sysfs(struct tty_struct *tty);
 
 extern void console_map_init(void);
 #ifdef CONFIG_PROM_CONSOLE
@@ -730,7 +737,8 @@ int vc_allocate(unsigned int currcons)      /* return 0 on success */
            visual_init(vc, currcons, 1);
            if (!*vc->vc_uni_pagedir_loc)
                con_set_default_unimap(vc);
-           vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+           if (!vc->vc_kmalloced)
+               vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
            if (!vc->vc_screenbuf) {
                kfree(vc);
                vc_cons[currcons].d = NULL;
@@ -878,8 +886,17 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        return err;
 }
 
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+{
+       int rc;
+
+       acquire_console_sem();
+       rc = vc_resize(vc, cols, lines);
+       release_console_sem();
+       return rc;
+}
 
-void vc_disallocate(unsigned int currcons)
+void vc_deallocate(unsigned int currcons)
 {
        WARN_CONSOLE_UNLOCKED();
 
@@ -2005,17 +2022,23 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
                /* Do no translation at all in control states */
                if (vc->vc_state != ESnormal) {
                        tc = c;
-               } else if (vc->vc_utf) {
+               } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
                    /* Combine UTF-8 into Unicode */
-                   /* Incomplete characters silently ignored */
+                   /* Malformed sequences as sequences of replacement glyphs */
+rescan_last_byte:
                    if(c > 0x7f) {
-                       if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
-                               vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
-                               vc->vc_utf_count--;
-                               if (vc->vc_utf_count == 0)
-                                   tc = c = vc->vc_utf_char;
-                               else continue;
+                       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);
@@ -2032,14 +2055,15 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
                                    vc->vc_utf_count = 5;
                                    vc->vc_utf_char = (c & 0x01);
                                } else
-                                   vc->vc_utf_count = 0;
+                                   goto replacement_glyph;
                                continue;
                              }
                    } else {
+                     if (vc->vc_utf_count)
+                             goto replacement_glyph;
                      tc = c;
-                     vc->vc_utf_count = 0;
                    }
-               } else {        /* no utf */
+               } else {        /* no utf or alternate charset mode */
                  tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
                }
 
@@ -2054,31 +2078,33 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
                  * direct-to-font zone in UTF-8 mode.
                  */
                 ok = tc && (c >= 32 ||
-                           (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS
-                                               : CTRL_ACTION) >> c) & 1)))
+                           !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
+                                 vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
                        && (c != 127 || vc->vc_disp_ctrl)
                        && (c != 128+27);
 
                if (vc->vc_state == ESnormal && ok) {
                        /* Now try to find out how to display it */
                        tc = conv_uni_to_pc(vc, tc);
-                       if ( tc == -4 ) {
+                       if (tc & ~charmask) {
+                               if ( tc == -4 ) {
                                 /* If we got -4 (not found) then see if we have
                                    defined a replacement character (U+FFFD) */
-                                tc = conv_uni_to_pc(vc, 0xfffd);
-
-                               /* One reason for the -4 can be that we just
-                                  did a clear_unimap();
-                                  try at least to show something. */
-                               if (tc == -4)
-                                    tc = c;
-                        } else if ( tc == -3 ) {
-                                /* Bad hash table -- hope for the best */
-                                tc = c;
-                        }
-                       if (tc & ~charmask)
-                                continue; /* Conversion failed */
+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;
+                       }
 
+display_glyph:
                        if (vc->vc_need_wrap || vc->vc_decim)
                                FLUSH
                        if (vc->vc_need_wrap) {
@@ -2102,6 +2128,15 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
                                vc->vc_x++;
                                draw_to = (vc->vc_pos += 2);
                        }
+                       if (vc->vc_utf_count) {
+                               if (vc->vc_npar) {
+                                       vc->vc_npar--;
+                                       goto display_glyph;
+                               }
+                               vc->vc_utf_count = 0;
+                               c = orig;
+                               goto rescan_last_byte;
+                       }
                        continue;
                }
                FLUSH
@@ -2498,7 +2533,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
                                tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
                        }
                        release_console_sem();
-                       vcs_make_devfs(tty);
+                       vcs_make_sysfs(tty);
                        return ret;
                }
        }
@@ -2511,7 +2546,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
  * and taking a ref against the tty while we're in the process of forgetting
  * about it and cleaning things up.
  *
- * This is because vcs_remove_devfs() can sleep and will drop the BKL.
+ * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
  */
 static void con_close(struct tty_struct *tty, struct file *filp)
 {
@@ -2524,7 +2559,7 @@ static void con_close(struct tty_struct *tty, struct file *filp)
                        vc->vc_tty = NULL;
                tty->driver_data = NULL;
                release_console_sem();
-               vcs_remove_devfs(tty);
+               vcs_remove_sysfs(tty);
                mutex_unlock(&tty_mutex);
                /*
                 * tty_mutex is released, but we still hold BKL, so there is
@@ -3765,6 +3800,7 @@ EXPORT_SYMBOL(default_blu);
 EXPORT_SYMBOL(update_region);
 EXPORT_SYMBOL(redraw_screen);
 EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(vc_lock_resize);
 EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
 EXPORT_SYMBOL(console_blanked);
index a5628a8b66207a4420c99f91565a6746495b14ee..a53e382cc10747b2e73a9386c67a78f73700582f 100644 (file)
@@ -96,7 +96,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str
                if (!perm)
                        return -EPERM;
                if (!i && v == K_NOSUCHMAP) {
-                       /* disallocate map */
+                       /* deallocate map */
                        key_map = key_maps[s];
                        if (s && key_map) {
                            key_maps[s] = NULL;
@@ -819,20 +819,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (arg > MAX_NR_CONSOLES)
                        return -ENXIO;
                if (arg == 0) {
-                   /* disallocate all unused consoles, but leave 0 */
+                   /* deallocate all unused consoles, but leave 0 */
                        acquire_console_sem();
                        for (i=1; i<MAX_NR_CONSOLES; i++)
                                if (! VT_BUSY(i))
-                                       vc_disallocate(i);
+                                       vc_deallocate(i);
                        release_console_sem();
                } else {
-                       /* disallocate a single console, if possible */
+                       /* deallocate a single console, if possible */
                        arg--;
                        if (VT_BUSY(arg))
                                return -EBUSY;
                        if (arg) {                            /* leave 0 */
                                acquire_console_sem();
-                               vc_disallocate(arg);
+                               vc_deallocate(arg);
                                release_console_sem();
                        }
                }
@@ -847,11 +847,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (get_user(ll, &vtsizes->v_rows) ||
                    get_user(cc, &vtsizes->v_cols))
                        return -EFAULT;
-               for (i = 0; i < MAX_NR_CONSOLES; i++) {
-                       acquire_console_sem();
-                       vc_resize(vc_cons[i].d, cc, ll);
-                       release_console_sem();
-               }
+               for (i = 0; i < MAX_NR_CONSOLES; i++)
+                       vc_lock_resize(vc_cons[i].d, cc, ll);
                return 0;
        }
 
index fff89c2d88fda66ad93bb40e822137b2751477b5..77ab7e020da0a8ee2672a379d79f93aed3235899 100644 (file)
@@ -165,6 +165,13 @@ config EP93XX_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called ep93xx_wdt.
 
+config OMAP_WATCHDOG
+       tristate "OMAP Watchdog"
+       depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+       help
+         Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog.  Say 'Y' here to
+         enable the OMAP1610/OMAP1710 watchdog timer.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
@@ -510,6 +517,14 @@ config SH_WDT
          To compile this driver as a module, choose M here: the
          module will be called shwdt.
 
+config SH_WDT_MMAP
+       bool "Allow mmap of SH WDT"
+       default n
+       depends on SH_WDT
+       help
+         If you say Y here, user applications will be able to mmap the
+         WDT/CPG registers.
+#
 # SPARC64 Architecture
 
 config WATCHDOG_CP1XXX
index 6ab77b61a6434635a8a6e2ba8716d2b000bcf56a..5099f8be8cc51efab2bc38d98dfd2df495833daf 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 
 # ARM Architecture
 obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
+obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
new file mode 100644 (file)
index 0000000..8f90b90
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * linux/drivers/char/watchdog/omap_wdt.c
+ *
+ * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
+ *
+ * Author: MontaVista Software, Inc.
+ *      <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * 2003 (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.
+ *
+ * History:
+ *
+ * 20030527: George G. Davis <gdavis@mvista.com>
+ *     Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
+ *     (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *     Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ * Copyright (c) 2004 Texas Instruments.
+ *     1. Modified to support OMAP1610 32-KHz watchdog timer
+ *     2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *     Use the driver model and standard identifiers; handle bigger timeouts.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#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>
+#include <linux/moduleparam.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+
+#include <asm/arch/prcm.h>
+
+#include "omap_wdt.h"
+
+static unsigned timer_margin;
+module_param(timer_margin, uint, 0);
+MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
+
+static int omap_wdt_users;
+static struct clk *armwdt_ck = NULL;
+static struct clk *mpu_wdt_ick = NULL;
+static struct clk *mpu_wdt_fck = NULL;
+
+static unsigned int wdt_trgr_pattern = 0x1234;
+
+static void omap_wdt_ping(void)
+{
+       /* wait for posted write to complete */
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+               cpu_relax();
+       wdt_trgr_pattern = ~wdt_trgr_pattern;
+       omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
+       /* wait for posted write to complete */
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
+               cpu_relax();
+       /* reloaded WCRR from WLDR */
+}
+
+static void omap_wdt_enable(void)
+{
+       /* Sequence to enable the watchdog */
+       omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+               cpu_relax();
+       omap_writel(0x4444, OMAP_WATCHDOG_SPR);
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
+               cpu_relax();
+}
+
+static void omap_wdt_disable(void)
+{
+       /* sequence required to disable watchdog */
+       omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+               cpu_relax();
+       omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
+               cpu_relax();
+}
+
+static void omap_wdt_adjust_timeout(unsigned new_timeout)
+{
+       if (new_timeout < TIMER_MARGIN_MIN)
+               new_timeout = TIMER_MARGIN_DEFAULT;
+       if (new_timeout > TIMER_MARGIN_MAX)
+               new_timeout = TIMER_MARGIN_MAX;
+       timer_margin = new_timeout;
+}
+
+static void omap_wdt_set_timeout(void)
+{
+       u32 pre_margin = GET_WLDR_VAL(timer_margin);
+
+       /* just count up at 32 KHz */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+               cpu_relax();
+       omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+               cpu_relax();
+}
+
+/*
+ *     Allow only one task to hold it open
+ */
+
+static int omap_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
+               return -EBUSY;
+
+       if (cpu_is_omap16xx())
+               clk_enable(armwdt_ck);  /* Enable the clock */
+
+       if (cpu_is_omap24xx()) {
+               clk_enable(mpu_wdt_ick);    /* Enable the interface clock */
+               clk_enable(mpu_wdt_fck);    /* Enable the functional clock */
+       }
+
+       /* initialize prescaler */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+               cpu_relax();
+       omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+               cpu_relax();
+
+       omap_wdt_set_timeout();
+       omap_wdt_enable();
+       return 0;
+}
+
+static int omap_wdt_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer unless NOWAYOUT is defined.
+        */
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+       omap_wdt_disable();
+
+       if (cpu_is_omap16xx()) {
+               clk_disable(armwdt_ck); /* Disable the clock */
+               clk_put(armwdt_ck);
+               armwdt_ck = NULL;
+       }
+
+       if (cpu_is_omap24xx()) {
+               clk_disable(mpu_wdt_ick);       /* Disable the clock */
+               clk_disable(mpu_wdt_fck);       /* Disable the clock */
+               clk_put(mpu_wdt_ick);
+               clk_put(mpu_wdt_fck);
+               mpu_wdt_ick = NULL;
+               mpu_wdt_fck = NULL;
+       }
+#else
+       printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+#endif
+       omap_wdt_users = 0;
+       return 0;
+}
+
+static ssize_t
+omap_wdt_write(struct file *file, const char __user *data,
+               size_t len, loff_t *ppos)
+{
+       /* Refresh LOAD_TIME. */
+       if (len)
+               omap_wdt_ping();
+       return len;
+}
+
+static int
+omap_wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int new_margin;
+       static struct watchdog_info ident = {
+               .identity = "OMAP Watchdog",
+               .options = WDIOF_SETTIMEOUT,
+               .firmware_version = 0,
+       };
+
+       switch (cmd) {
+       default:
+               return -ENOIOCTLCMD;
+       case WDIOC_GETSUPPORT:
+               return copy_to_user((struct watchdog_info __user *)arg, &ident,
+                               sizeof(ident));
+       case WDIOC_GETSTATUS:
+               return put_user(0, (int __user *)arg);
+       case WDIOC_GETBOOTSTATUS:
+               if (cpu_is_omap16xx())
+                       return put_user(omap_readw(ARM_SYSST),
+                                       (int __user *)arg);
+               if (cpu_is_omap24xx())
+                       return put_user(omap_prcm_get_reset_sources(),
+                                       (int __user *)arg);
+       case WDIOC_KEEPALIVE:
+               omap_wdt_ping();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, (int __user *)arg))
+                       return -EFAULT;
+               omap_wdt_adjust_timeout(new_margin);
+
+               omap_wdt_disable();
+               omap_wdt_set_timeout();
+               omap_wdt_enable();
+
+               omap_wdt_ping();
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               return put_user(timer_margin, (int __user *)arg);
+       }
+}
+
+static struct file_operations omap_wdt_fops = {
+       .owner = THIS_MODULE,
+       .write = omap_wdt_write,
+       .ioctl = omap_wdt_ioctl,
+       .open = omap_wdt_open,
+       .release = omap_wdt_release,
+};
+
+static struct miscdevice omap_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &omap_wdt_fops
+};
+
+static int __init omap_wdt_probe(struct platform_device *pdev)
+{
+       struct resource *res, *mem;
+       int ret;
+
+       /* reserve static register mappings */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       mem = request_mem_region(res->start, res->end - res->start + 1,
+                                pdev->name);
+       if (mem == NULL)
+               return -EBUSY;
+
+       platform_set_drvdata(pdev, mem);
+
+       omap_wdt_users = 0;
+
+       if (cpu_is_omap16xx()) {
+               armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
+               if (IS_ERR(armwdt_ck)) {
+                       ret = PTR_ERR(armwdt_ck);
+                       armwdt_ck = NULL;
+                       goto fail;
+               }
+       }
+
+       if (cpu_is_omap24xx()) {
+               mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
+               if (IS_ERR(mpu_wdt_ick)) {
+                       ret = PTR_ERR(mpu_wdt_ick);
+                       mpu_wdt_ick = NULL;
+                       goto fail;
+               }
+               mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
+               if (IS_ERR(mpu_wdt_fck)) {
+                       ret = PTR_ERR(mpu_wdt_fck);
+                       mpu_wdt_fck = NULL;
+                       goto fail;
+               }
+       }
+
+       omap_wdt_disable();
+       omap_wdt_adjust_timeout(timer_margin);
+
+       omap_wdt_miscdev.dev = &pdev->dev;
+       ret = misc_register(&omap_wdt_miscdev);
+       if (ret)
+               goto fail;
+
+       pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
+
+       /* autogate OCP interface clock */
+       omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
+       return 0;
+
+fail:
+       if (armwdt_ck)
+               clk_put(armwdt_ck);
+       if (mpu_wdt_ick)
+               clk_put(mpu_wdt_ick);
+       if (mpu_wdt_fck)
+               clk_put(mpu_wdt_fck);
+       release_resource(mem);
+       return ret;
+}
+
+static void omap_wdt_shutdown(struct platform_device *pdev)
+{
+       omap_wdt_disable();
+}
+
+static int omap_wdt_remove(struct platform_device *pdev)
+{
+       struct resource *mem = platform_get_drvdata(pdev);
+       misc_deregister(&omap_wdt_miscdev);
+       release_resource(mem);
+       if (armwdt_ck)
+               clk_put(armwdt_ck);
+       if (mpu_wdt_ick)
+               clk_put(mpu_wdt_ick);
+       if (mpu_wdt_fck)
+               clk_put(mpu_wdt_fck);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* REVISIT ... not clear this is the best way to handle system suspend; and
+ * it's very inappropriate for selective device suspend (e.g. suspending this
+ * through sysfs rather than by stopping the watchdog daemon).  Also, this
+ * may not play well enough with NOWAYOUT...
+ */
+
+static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       if (omap_wdt_users)
+               omap_wdt_disable();
+       return 0;
+}
+
+static int omap_wdt_resume(struct platform_device *pdev)
+{
+       if (omap_wdt_users) {
+               omap_wdt_enable();
+               omap_wdt_ping();
+       }
+       return 0;
+}
+
+#else
+#define        omap_wdt_suspend        NULL
+#define        omap_wdt_resume         NULL
+#endif
+
+static struct platform_driver omap_wdt_driver = {
+       .probe          = omap_wdt_probe,
+       .remove         = omap_wdt_remove,
+       .shutdown       = omap_wdt_shutdown,
+       .suspend        = omap_wdt_suspend,
+       .resume         = omap_wdt_resume,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "omap_wdt",
+       },
+};
+
+static int __init omap_wdt_init(void)
+{
+       return platform_driver_register(&omap_wdt_driver);
+}
+
+static void __exit omap_wdt_exit(void)
+{
+       platform_driver_unregister(&omap_wdt_driver);
+}
+
+module_init(omap_wdt_init);
+module_exit(omap_wdt_exit);
+
+MODULE_AUTHOR("George G. Davis");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/char/watchdog/omap_wdt.h
new file mode 100644 (file)
index 0000000..52a532a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  linux/drivers/char/watchdog/omap_wdt.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      OMAP Watchdog timer register definitions
+ *
+ *  Copyright (C) 2004 Texas Instruments.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _OMAP_WATCHDOG_H
+#define _OMAP_WATCHDOG_H
+
+#define OMAP1610_WATCHDOG_BASE         0xfffeb000
+#define OMAP2420_WATCHDOG_BASE         0x48022000      /*WDT Timer 2 */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP_WATCHDOG_BASE             OMAP2420_WATCHDOG_BASE
+#else
+#define OMAP_WATCHDOG_BASE             OMAP1610_WATCHDOG_BASE
+#define RM_RSTST_WKUP                  0
+#endif
+
+#define OMAP_WATCHDOG_REV              (OMAP_WATCHDOG_BASE + 0x00)
+#define OMAP_WATCHDOG_SYS_CONFIG       (OMAP_WATCHDOG_BASE + 0x10)
+#define OMAP_WATCHDOG_STATUS           (OMAP_WATCHDOG_BASE + 0x14)
+#define OMAP_WATCHDOG_CNTRL            (OMAP_WATCHDOG_BASE + 0x24)
+#define OMAP_WATCHDOG_CRR              (OMAP_WATCHDOG_BASE + 0x28)
+#define OMAP_WATCHDOG_LDR              (OMAP_WATCHDOG_BASE + 0x2c)
+#define OMAP_WATCHDOG_TGR              (OMAP_WATCHDOG_BASE + 0x30)
+#define OMAP_WATCHDOG_WPS              (OMAP_WATCHDOG_BASE + 0x34)
+#define OMAP_WATCHDOG_SPR              (OMAP_WATCHDOG_BASE + 0x48)
+
+/* Using the prescaler, the OMAP watchdog could go for many
+ * months before firing.  These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX       (24 * 60 * 60)  /* 1 day */
+#define TIMER_MARGIN_DEFAULT   60      /* 60 secs */
+#define TIMER_MARGIN_MIN       1
+
+#define PTV                    0       /* prescale */
+#define GET_WLDR_VAL(secs)     (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+
+#endif                         /* _OMAP_WATCHDOG_H */
index 1355038f10440e27f4a708eea95694f897edbc0a..e5b8c64f1d65acf4ac67dfb8f77d5376d2ac974e 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/notifier.h>
 #include <linux/ioport.h>
 #include <linux/fs.h>
-
+#include <linux/mm.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/watchdog.h>
@@ -125,7 +125,6 @@ static void sh_wdt_start(void)
 
 /**
  *     sh_wdt_stop - Stop the Watchdog
- *
  *     Stops the watchdog.
  */
 static void sh_wdt_stop(void)
@@ -141,22 +140,20 @@ static void sh_wdt_stop(void)
 
 /**
  *     sh_wdt_keepalive - Keep the Userspace Watchdog Alive
- *
  *     The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
  */
-static void sh_wdt_keepalive(void)
+static inline void sh_wdt_keepalive(void)
 {
        next_heartbeat = jiffies + (heartbeat * HZ);
 }
 
 /**
  *     sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
- *
  *     Set the Userspace Watchdog heartbeat
  */
 static int sh_wdt_set_heartbeat(int t)
 {
-       if ((t < 1) || (t > 3600)) /* arbitrary upper limit */
+       if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */
                return -EINVAL;
 
        heartbeat = t;
@@ -165,7 +162,6 @@ static int sh_wdt_set_heartbeat(int t)
 
 /**
  *     sh_wdt_ping - Ping the Watchdog
- *
  *     @data: Unused
  *
  *     Clears overflow bit, resets timer counter.
@@ -182,14 +178,13 @@ static void sh_wdt_ping(unsigned long data)
                sh_wdt_write_cnt(0);
 
                mod_timer(&timer, next_ping_period(clock_division_ratio));
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
+       } else
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
+                      "the watchdog\n");
 }
 
 /**
  *     sh_wdt_open - Open the Device
- *
  *     @inode: inode of device
  *     @file: file handle of device
  *
@@ -209,7 +204,6 @@ static int sh_wdt_open(struct inode *inode, struct file *file)
 
 /**
  *     sh_wdt_close - Close the Device
- *
  *     @inode: inode of device
  *     @file: file handle of device
  *
@@ -220,7 +214,8 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
        if (shwdt_expect_close == 42) {
                sh_wdt_stop();
        } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               printk(KERN_CRIT PFX "Unexpected close, not "
+                      "stopping watchdog!\n");
                sh_wdt_keepalive();
        }
 
@@ -232,7 +227,6 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
 
 /**
  *     sh_wdt_write - Write to Device
- *
  *     @file: file handle of device
  *     @buf: buffer to write
  *     @count: length of buffer
@@ -264,8 +258,56 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf,
 }
 
 /**
- *     sh_wdt_ioctl - Query Device
+ *     sh_wdt_mmap - map WDT/CPG registers into userspace
+ *     @file: file structure for the device
+ *     @vma: VMA to map the registers into
+ *
+ *     A simple mmap() implementation for the corner cases where the counter
+ *     needs to be mapped in userspace directly. Due to the relatively small
+ *     size of the area, neighbouring registers not necessarily tied to the
+ *     CPG will also be accessible through the register page, so this remains
+ *     configurable for users that really know what they're doing.
  *
+ *     Additionaly, the register page maps in the CPG register base relative
+ *     to the nearest page-aligned boundary, which requires that userspace do
+ *     the appropriate CPU subtype math for calculating the page offset for
+ *     the counter value.
+ */
+static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int ret = -ENOSYS;
+
+#ifdef CONFIG_SH_WDT_MMAP
+       unsigned long addr;
+
+       /* Only support the simple cases where we map in a register page. */
+       if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
+               return -EINVAL;
+
+       /*
+        * Pick WTCNT as the start, it's usually the first register after the
+        * FRQCR, and neither one are generally page-aligned out of the box.
+        */
+       addr = WTCNT & ~(PAGE_SIZE - 1);
+
+       vma->vm_flags |= VM_IO;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
+                              PAGE_SIZE, vma->vm_page_prot)) {
+               printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
+                      __FUNCTION__);
+               return -EAGAIN;
+       }
+
+       ret = 0;
+#endif
+
+       return ret;
+}
+
+/**
+ *     sh_wdt_ioctl - Query Device
  *     @inode: inode of device
  *     @file: file handle of device
  *     @cmd: watchdog command
@@ -326,7 +368,6 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
 
 /**
  *     sh_wdt_notify_sys - Notifier Handler
- *
  *     @this: notifier block
  *     @code: notifier event
  *     @unused: unused
@@ -337,9 +378,8 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
 static int sh_wdt_notify_sys(struct notifier_block *this,
                             unsigned long code, void *unused)
 {
-       if (code == SYS_DOWN || code == SYS_HALT) {
+       if (code == SYS_DOWN || code == SYS_HALT)
                sh_wdt_stop();
-       }
 
        return NOTIFY_DONE;
 }
@@ -351,10 +391,12 @@ static const struct file_operations sh_wdt_fops = {
        .ioctl          = sh_wdt_ioctl,
        .open           = sh_wdt_open,
        .release        = sh_wdt_close,
+       .mmap           = sh_wdt_mmap,
 };
 
 static struct watchdog_info sh_wdt_info = {
-       .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+       .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+                                 WDIOF_MAGICCLOSE,
        .firmware_version       = 1,
        .identity               = "SH WDT",
 };
@@ -371,7 +413,6 @@ static struct miscdevice sh_wdt_miscdev = {
 
 /**
  *     sh_wdt_init - Initialize module
- *
  *     Registers the device and notifier handler. Actual device
  *     initialization is handled by sh_wdt_open().
  */
@@ -381,15 +422,15 @@ static int __init sh_wdt_init(void)
 
        if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) {
                clock_division_ratio = WTCSR_CKS_4096;
-               printk(KERN_INFO PFX "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
-                       clock_division_ratio);
+               printk(KERN_INFO PFX "clock_division_ratio value must "
+                      "be 0x5<=x<=0x7, using %d\n", clock_division_ratio);
        }
 
-       if (sh_wdt_set_heartbeat(heartbeat))
-       {
+       rc = sh_wdt_set_heartbeat(heartbeat);
+       if (unlikely(rc)) {
                heartbeat = WATCHDOG_HEARTBEAT;
-               printk(KERN_INFO PFX "heartbeat value must be 1<=x<=3600, using %d\n",
-                       heartbeat);
+               printk(KERN_INFO PFX "heartbeat value must "
+                      "be 1<=x<=3600, using %d\n", heartbeat);
        }
 
        init_timer(&timer);
@@ -397,15 +438,16 @@ static int __init sh_wdt_init(void)
        timer.data = 0;
 
        rc = register_reboot_notifier(&sh_wdt_notifier);
-       if (rc) {
-               printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", rc);
+       if (unlikely(rc)) {
+               printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
+                      rc);
                return rc;
        }
 
        rc = misc_register(&sh_wdt_miscdev);
-       if (rc) {
-               printk(KERN_ERR PFX "Can't register miscdev on minor=%d (err=%d)\n",
-                       sh_wdt_miscdev.minor, rc);
+       if (unlikely(rc)) {
+               printk(KERN_ERR PFX "Can't register miscdev on "
+                      "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc);
                unregister_reboot_notifier(&sh_wdt_notifier);
                return rc;
        }
@@ -418,7 +460,6 @@ static int __init sh_wdt_init(void)
 
 /**
  *     sh_wdt_exit - Deinitialize module
- *
  *     Unregisters the device and notifier handler. Actual device
  *     deinitialization is handled by sh_wdt_close().
  */
@@ -434,14 +475,13 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 module_param(clock_division_ratio, int, 0);
-MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7.");
+MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
 
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 module_init(sh_wdt_init);
 module_exit(sh_wdt_exit);
-
index d35a9f06ab7b6fe25420c53dd657e849fc00cbed..2caaf71d80c85566bd24d235419f6e09fa097d12 100644 (file)
@@ -994,7 +994,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
        unsigned int cur_freq = 0;
        struct cpufreq_policy *cpu_policy;
 
-       dprintk("resuming cpu %u\n", cpu);
+       dprintk("suspending cpu %u\n", cpu);
 
        if (!cpu_online(cpu))
                return 0;
index 6078e2f588172e73aad9ad45ec2a3cfb9eb7e97d..3a365e159d89d52df59b945d22bb7bd1408022f9 100644 (file)
@@ -128,9 +128,23 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv)
        return 0;
 }
 
+static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp,
+                          char *buffer, int buffer_size)
+{
+       struct eisa_device *edev = to_eisa_device(dev);
+       int i = 0;
+       int length = 0;
+
+       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+                      "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
+       envp[i] = NULL;
+       return 0;
+}
+
 struct bus_type eisa_bus_type = {
        .name  = "eisa",
        .match = eisa_bus_match,
+       .uevent = eisa_bus_uevent,
 };
 
 int eisa_driver_register (struct eisa_driver *edrv)
@@ -160,6 +174,14 @@ static ssize_t eisa_show_state (struct device *dev, struct device_attribute *att
 
 static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL);
 
+static ssize_t eisa_show_modalias (struct device *dev, struct device_attribute *attr, char *buf)
+{
+        struct eisa_device *edev = to_eisa_device (dev);
+        return sprintf (buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig);
+}
+
+static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL);
+
 static int __init eisa_init_device (struct eisa_root_device *root,
                                    struct eisa_device *edev,
                                    int slot)
@@ -209,6 +231,7 @@ static int __init eisa_register_device (struct eisa_device *edev)
 
        device_create_file (&edev->dev, &dev_attr_signature);
        device_create_file (&edev->dev, &dev_attr_enabled);
+       device_create_file (&edev->dev, &dev_attr_modalias);
 
        return 0;
 }
index 1a159e8843ca47dd27778937d350df400448c48f..22d17474755f73ac86660c499e486750132f3c60 100644 (file)
@@ -974,7 +974,6 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
         */
 
        fc->rst_pkt->device->host->eh_action = &sem;
-       fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY;
 
        fc->rst_pkt->done = fcp_scsi_reset_done;
 
index b9e3886d9e1618cc4b85345e81a8a2c23fb876ea..b8b596d5778dbe03295395eccbad2176a25c3bfa 100644 (file)
@@ -123,6 +123,26 @@ static void __init dmi_save_devices(struct dmi_header *dm)
                dev->type = *d++ & 0x7f;
                dev->name = dmi_string(dm, *d);
                dev->device_data = NULL;
+               list_add(&dev->list, &dmi_devices);
+       }
+}
+
+static void __init dmi_save_oem_strings_devices(struct dmi_header *dm)
+{
+       int i, count = *(u8 *)(dm + 1);
+       struct dmi_device *dev;
+
+       for (i = 1; i <= count; i++) {
+               dev = dmi_alloc(sizeof(*dev));
+               if (!dev) {
+                       printk(KERN_ERR
+                          "dmi_save_oem_strings_devices: out of memory.\n");
+                       break;
+               }
+
+               dev->type = DMI_DEV_TYPE_OEM_STRING;
+               dev->name = dmi_string(dm, i);
+               dev->device_data = NULL;
 
                list_add(&dev->list, &dmi_devices);
        }
@@ -181,6 +201,9 @@ static void __init dmi_decode(struct dmi_header *dm)
        case 10:        /* Onboard Devices Information */
                dmi_save_devices(dm);
                break;
+       case 11:        /* OEM Strings */
+               dmi_save_oem_strings_devices(dm);
+               break;
        case 38:        /* IPMI Device Information */
                dmi_save_ipmi_device(dm);
        }
index 0e31a0c496e8ae44ce3ed29322d6169787480e91..9b88b25b6edbdfb098dc189c1e54c0efb60e5b4b 100644 (file)
@@ -53,7 +53,7 @@ config SENSORS_ADM1021
 
 config SENSORS_ADM1025
        tristate "Analog Devices ADM1025 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM1025
@@ -94,6 +94,16 @@ config SENSORS_ADM9240
          This driver can also be built as a module.  If so, the module
          will be called adm9240.
 
+config SENSORS_K8TEMP
+       tristate "AMD K8 processor sensor"
+       depends on HWMON && X86 && PCI && EXPERIMENTAL
+       help
+         If you say yes here you get support for the temperature
+         sensor(s) inside your AMD K8 CPU.
+
+         This driver can also be built as a module.  If so, the module
+         will be called k8temp.
+
 config SENSORS_ASB100
        tristate "Asus ASB100 Bach"
        depends on HWMON && I2C && EXPERIMENTAL
@@ -121,7 +131,7 @@ config SENSORS_ATXP1
 
 config SENSORS_DS1621
        tristate "Dallas Semiconductor DS1621 and DS1625"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1621 and DS1625 sensor chips.
@@ -141,7 +151,7 @@ config SENSORS_F71805F
 
 config SENSORS_FSCHER
        tristate "FSC Hermes"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for Fujitsu Siemens
          Computers Hermes sensor chips.
@@ -151,7 +161,7 @@ config SENSORS_FSCHER
 
 config SENSORS_FSCPOS
        tristate "FSC Poseidon"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for Fujitsu Siemens
          Computers Poseidon sensor chips.
@@ -171,7 +181,7 @@ config SENSORS_GL518SM
 
 config SENSORS_GL520SM
        tristate "Genesys Logic GL520SM"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        select HWMON_VID
        help
          If you say yes here you get support for Genesys Logic GL520SM
@@ -186,15 +196,15 @@ config SENSORS_IT87
        select I2C_ISA
        select HWMON_VID
        help
-         If you say yes here you get support for ITE IT87xx sensor chips
-         and clones: SiS960.
+         If you say yes here you get support for ITE IT8705F, IT8712F,
+         IT8716F and IT8718F sensor chips, and the SiS960 clone.
 
          This driver can also be built as a module.  If so, the module
          will be called it87.
 
 config SENSORS_LM63
        tristate "National Semiconductor LM63"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for the National Semiconductor
          LM63 remote diode digital temperature sensor with integrated fan
@@ -231,7 +241,7 @@ config SENSORS_LM75
 
 config SENSORS_LM77
        tristate "National Semiconductor LM77"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for National Semiconductor LM77
          sensor chips.
@@ -241,7 +251,7 @@ config SENSORS_LM77
 
 config SENSORS_LM78
        tristate "National Semiconductor LM78 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        select I2C_ISA
        select HWMON_VID
        help
@@ -284,7 +294,7 @@ config SENSORS_LM85
 
 config SENSORS_LM87
        tristate "National Semiconductor LM87"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM87
@@ -309,7 +319,7 @@ config SENSORS_LM90
 
 config SENSORS_LM92
        tristate "National Semiconductor LM92 and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for National Semiconductor LM92
          and Maxim MAX6635 sensor chips.
@@ -319,7 +329,7 @@ config SENSORS_LM92
 
 config SENSORS_MAX1619
        tristate "Maxim MAX1619 sensor chip"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        help
          If you say yes here you get support for MAX1619 sensor chip.
 
@@ -354,7 +364,7 @@ config SENSORS_SIS5595
 
 config SENSORS_SMSC47M1
        tristate "SMSC LPC47M10x and compatibles"
-       depends on HWMON && I2C && EXPERIMENTAL
+       depends on HWMON && I2C
        select I2C_ISA
        help
          If you say yes here you get support for the integrated fan
@@ -407,8 +417,19 @@ config SENSORS_VIA686A
          This driver can also be built as a module.  If so, the module
          will be called via686a.
 
+config SENSORS_VT1211
+       tristate "VIA VT1211"
+       depends on HWMON && EXPERIMENTAL
+       select HWMON_VID
+       help
+         If you say yes here then you get support for hardware monitoring
+         features of the VIA VT1211 Super-I/O chip.
+
+         This driver can also be built as a module.  If so, the module
+         will be called vt1211.
+
 config SENSORS_VT8231
-       tristate "VT8231"
+       tristate "VIA VT8231"
        depends on HWMON && I2C && PCI && EXPERIMENTAL
        select HWMON_VID
        select I2C_ISA
index 31415843a91ae6c2e1da679c7a7b4f9f04c3812e..af01cc64f7d265e31b7c9700f9c9eeefd596f43a 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
 obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
 obj-$(CONFIG_SENSORS_IT87)     += it87.o
+obj-$(CONFIG_SENSORS_K8TEMP)   += k8temp.o
 obj-$(CONFIG_SENSORS_LM63)     += lm63.o
 obj-$(CONFIG_SENSORS_LM70)     += lm70.o
 obj-$(CONFIG_SENSORS_LM75)     += lm75.o
@@ -45,6 +46,7 @@ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_VIA686A)  += via686a.o
+obj-$(CONFIG_SENSORS_VT1211)   += vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)   += vt8231.o
 obj-$(CONFIG_SENSORS_W83627EHF)        += w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)        += w83l785ts.o
index 35ad1b0327268dac11cf8a3f465a884aef0f42a2..e5cb0fdab9b15d8529274531a8879a31dd2cb0a0 100644 (file)
@@ -1354,13 +1354,39 @@ LEAVE_UPDATE:
                return NULL;
 }
 
+#ifdef CONFIG_PM
+static int abituguru_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct abituguru_data *data = platform_get_drvdata(pdev);
+       /* make sure all communications with the uguru are done and no new
+          ones are started */
+       mutex_lock(&data->update_lock);
+       return 0;
+}
+
+static int abituguru_resume(struct platform_device *pdev)
+{
+       struct abituguru_data *data = platform_get_drvdata(pdev);
+       /* See if the uGuru is still ready */
+       if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT)
+               data->uguru_ready = 0;
+       mutex_unlock(&data->update_lock);
+       return 0;
+}
+#else
+#define abituguru_suspend      NULL
+#define abituguru_resume       NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver abituguru_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = ABIT_UGURU_NAME,
        },
-       .probe  = abituguru_probe,
-       .remove = __devexit_p(abituguru_remove),
+       .probe          = abituguru_probe,
+       .remove         = __devexit_p(abituguru_remove),
+       .suspend        = abituguru_suspend,
+       .resume         = abituguru_resume,
 };
 
 static int __init abituguru_detect(void)
index 2b6e74dd4a82079c6eb18b44719846c33ae961ed..c466329b2ef4745100f00346c4f989958f42828e 100644 (file)
@@ -190,6 +190,21 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, adm1021_detect);
 }
 
+static struct attribute *adm1021_attributes[] = {
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_min.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group adm1021_group = {
+       .attrs = adm1021_attributes,
+};
+
 static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i;
@@ -287,22 +302,19 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
                adm1021_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1021_group)))
+               goto error2;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto error2;
+               goto error3;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
        return 0;
 
+error3:
+       sysfs_remove_group(&new_client->dev.kobj, &adm1021_group);
 error2:
        i2c_detach_client(new_client);
 error1:
@@ -326,6 +338,7 @@ static int adm1021_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &adm1021_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index a4c859c9fbf82c3f6ef09649e621441c6842044d..8c562885b54b031fe03746322b188a5566366d12 100644 (file)
@@ -315,6 +315,49 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, adm1025_detect);
 }
 
+static struct attribute *adm1025_attributes[] = {
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       &dev_attr_in5_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in2_min.attr,
+       &dev_attr_in3_min.attr,
+       &dev_attr_in5_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in1_max.attr,
+       &dev_attr_in2_max.attr,
+       &dev_attr_in3_max.attr,
+       &dev_attr_in5_max.attr,
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp2_min.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       NULL
+};
+
+static const struct attribute_group adm1025_group = {
+       .attrs = adm1025_attributes,
+};
+
+static struct attribute *adm1025_attributes_opt[] = {
+       &dev_attr_in4_input.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in4_max.attr,
+       NULL
+};
+
+static const struct attribute_group adm1025_group_opt = {
+       .attrs = adm1025_attributes_opt,
+};
+
 /*
  * The following function does more than just detection. If detection
  * succeeds, it also registers the new chip.
@@ -415,46 +458,31 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
        adm1025_init_client(new_client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1025_group)))
                goto exit_detach;
-       }
-
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in5_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in5_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in5_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-       device_create_file(&new_client->dev, &dev_attr_vrm);
 
        /* Pin 11 is either in4 (+12V) or VID4 */
        if (!(config & 0x20)) {
-               device_create_file(&new_client->dev, &dev_attr_in4_input);
-               device_create_file(&new_client->dev, &dev_attr_in4_min);
-               device_create_file(&new_client->dev, &dev_attr_in4_max);
+               if ((err = device_create_file(&new_client->dev,
+                                       &dev_attr_in4_input))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in4_min))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in4_max)))
+                       goto exit_remove;
+       }
+
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove;
        }
 
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &adm1025_group);
+       sysfs_remove_group(&new_client->dev.kobj, &adm1025_group_opt);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -511,6 +539,8 @@ static int adm1025_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &adm1025_group);
+       sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 6d4f8b8d358edde71408f52554555aafcd21e594..b4618b2705f76ae1805ab5dd5f24c2c76833d241 100644 (file)
@@ -323,15 +323,6 @@ static int adm1026_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, adm1026_detect);
 }
 
-static int adm1026_detach_client(struct i2c_client *client)
-{
-       struct adm1026_data *data = i2c_get_clientdata(client);
-       hwmon_device_unregister(data->class_dev);
-       i2c_detach_client(client);
-       kfree(data);
-       return 0;
-}
-
 static int adm1026_read_value(struct i2c_client *client, u8 reg)
 {
        int res;
@@ -1450,6 +1441,135 @@ static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 
+static struct attribute *adm1026_attributes[] = {
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_max.dev_attr.attr,
+       &sensor_dev_attr_in0_min.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_max.dev_attr.attr,
+       &sensor_dev_attr_in1_min.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_max.dev_attr.attr,
+       &sensor_dev_attr_in2_min.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in5_max.dev_attr.attr,
+       &sensor_dev_attr_in5_min.dev_attr.attr,
+       &sensor_dev_attr_in6_input.dev_attr.attr,
+       &sensor_dev_attr_in6_max.dev_attr.attr,
+       &sensor_dev_attr_in6_min.dev_attr.attr,
+       &sensor_dev_attr_in7_input.dev_attr.attr,
+       &sensor_dev_attr_in7_max.dev_attr.attr,
+       &sensor_dev_attr_in7_min.dev_attr.attr,
+       &sensor_dev_attr_in8_input.dev_attr.attr,
+       &sensor_dev_attr_in8_max.dev_attr.attr,
+       &sensor_dev_attr_in8_min.dev_attr.attr,
+       &sensor_dev_attr_in9_input.dev_attr.attr,
+       &sensor_dev_attr_in9_max.dev_attr.attr,
+       &sensor_dev_attr_in9_min.dev_attr.attr,
+       &sensor_dev_attr_in10_input.dev_attr.attr,
+       &sensor_dev_attr_in10_max.dev_attr.attr,
+       &sensor_dev_attr_in10_min.dev_attr.attr,
+       &sensor_dev_attr_in11_input.dev_attr.attr,
+       &sensor_dev_attr_in11_max.dev_attr.attr,
+       &sensor_dev_attr_in11_min.dev_attr.attr,
+       &sensor_dev_attr_in12_input.dev_attr.attr,
+       &sensor_dev_attr_in12_max.dev_attr.attr,
+       &sensor_dev_attr_in12_min.dev_attr.attr,
+       &sensor_dev_attr_in13_input.dev_attr.attr,
+       &sensor_dev_attr_in13_max.dev_attr.attr,
+       &sensor_dev_attr_in13_min.dev_attr.attr,
+       &sensor_dev_attr_in14_input.dev_attr.attr,
+       &sensor_dev_attr_in14_max.dev_attr.attr,
+       &sensor_dev_attr_in14_min.dev_attr.attr,
+       &sensor_dev_attr_in15_input.dev_attr.attr,
+       &sensor_dev_attr_in15_max.dev_attr.attr,
+       &sensor_dev_attr_in15_min.dev_attr.attr,
+       &sensor_dev_attr_in16_input.dev_attr.attr,
+       &sensor_dev_attr_in16_max.dev_attr.attr,
+       &sensor_dev_attr_in16_min.dev_attr.attr,
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_div.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_div.dev_attr.attr,
+       &sensor_dev_attr_fan3_min.dev_attr.attr,
+       &sensor_dev_attr_fan4_input.dev_attr.attr,
+       &sensor_dev_attr_fan4_div.dev_attr.attr,
+       &sensor_dev_attr_fan4_min.dev_attr.attr,
+       &sensor_dev_attr_fan5_input.dev_attr.attr,
+       &sensor_dev_attr_fan5_div.dev_attr.attr,
+       &sensor_dev_attr_fan5_min.dev_attr.attr,
+       &sensor_dev_attr_fan6_input.dev_attr.attr,
+       &sensor_dev_attr_fan6_div.dev_attr.attr,
+       &sensor_dev_attr_fan6_min.dev_attr.attr,
+       &sensor_dev_attr_fan7_input.dev_attr.attr,
+       &sensor_dev_attr_fan7_div.dev_attr.attr,
+       &sensor_dev_attr_fan7_min.dev_attr.attr,
+       &sensor_dev_attr_fan8_input.dev_attr.attr,
+       &sensor_dev_attr_fan8_div.dev_attr.attr,
+       &sensor_dev_attr_fan8_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_offset.dev_attr.attr,
+       &sensor_dev_attr_temp2_offset.dev_attr.attr,
+       &sensor_dev_attr_temp3_offset.dev_attr.attr,
+       &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp3_crit.dev_attr.attr,
+       &dev_attr_temp1_crit_enable.attr,
+       &dev_attr_temp2_crit_enable.attr,
+       &dev_attr_temp3_crit_enable.attr,
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_alarm_mask.attr,
+       &dev_attr_gpio.attr,
+       &dev_attr_gpio_mask.attr,
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm2.attr,
+       &dev_attr_pwm3.attr,
+       &dev_attr_pwm1_enable.attr,
+       &dev_attr_pwm2_enable.attr,
+       &dev_attr_pwm3_enable.attr,
+       &dev_attr_temp1_auto_point1_pwm.attr,
+       &dev_attr_temp2_auto_point1_pwm.attr,
+       &dev_attr_temp3_auto_point1_pwm.attr,
+       &dev_attr_temp1_auto_point2_pwm.attr,
+       &dev_attr_temp2_auto_point2_pwm.attr,
+       &dev_attr_temp3_auto_point2_pwm.attr,
+       &dev_attr_analog_out.attr,
+       NULL
+};
+
+static const struct attribute_group adm1026_group = {
+       .attrs = adm1026_attributes,
+};
+
 static int adm1026_detect(struct i2c_adapter *adapter, int address,
                          int kind)
 {
@@ -1554,145 +1674,20 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
        adm1026_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group)))
+               goto exitdetach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exitdetach;
+               goto exitremove;
        }
 
-       device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr);
-       device_create_file(&new_client->dev, 
-               &sensor_dev_attr_temp1_auto_point1_temp.dev_attr);
-       device_create_file(&new_client->dev, 
-               &sensor_dev_attr_temp2_auto_point1_temp.dev_attr);
-       device_create_file(&new_client->dev, 
-               &sensor_dev_attr_temp3_auto_point1_temp.dev_attr);
-       device_create_file(&new_client->dev,
-               &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr);
-       device_create_file(&new_client->dev,
-               &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr);
-       device_create_file(&new_client->dev,
-               &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr);
-       device_create_file(&new_client->dev, 
-               &sensor_dev_attr_temp1_auto_point2_temp.dev_attr);
-       device_create_file(&new_client->dev, 
-               &sensor_dev_attr_temp2_auto_point2_temp.dev_attr);
-       device_create_file(&new_client->dev, 
-               &sensor_dev_attr_temp3_auto_point2_temp.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
-       device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
-       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-       device_create_file(&new_client->dev, &dev_attr_vrm);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_alarm_mask);
-       device_create_file(&new_client->dev, &dev_attr_gpio);
-       device_create_file(&new_client->dev, &dev_attr_gpio_mask);
-       device_create_file(&new_client->dev, &dev_attr_pwm1);
-       device_create_file(&new_client->dev, &dev_attr_pwm2);
-       device_create_file(&new_client->dev, &dev_attr_pwm3);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-       device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
-       device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
-       device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm);
-       device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm);
-       device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm);
-       device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm);
-       device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm);
-       device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm);
-       device_create_file(&new_client->dev, &dev_attr_analog_out);
        return 0;
 
        /* Error out and cleanup code */
+exitremove:
+       sysfs_remove_group(&new_client->dev.kobj, &adm1026_group);
 exitdetach:
        i2c_detach_client(new_client);
 exitfree:
@@ -1700,6 +1695,17 @@ exitfree:
 exit:
        return err;
 }
+
+static int adm1026_detach_client(struct i2c_client *client)
+{
+       struct adm1026_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &adm1026_group);
+       i2c_detach_client(client);
+       kfree(data);
+       return 0;
+}
+
 static int __init sm_adm1026_init(void)
 {
        return i2c_add_driver(&adm1026_driver);
index 3bf2da621aedb39f548f139c31f17ab8d88bac81..122683fc91d096f271e3a372f17b5c8d51bfd2cb 100644 (file)
@@ -730,6 +730,61 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, adm1031_detect);
 }
 
+static struct attribute *adm1031_attributes[] = {
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_pwm1.attr,
+       &dev_attr_auto_fan1_channel.attr,
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_crit.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_min.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_crit.attr,
+
+       &dev_attr_auto_temp1_off.attr,
+       &dev_attr_auto_temp1_min.attr,
+       &dev_attr_auto_temp1_max.attr,
+
+       &dev_attr_auto_temp2_off.attr,
+       &dev_attr_auto_temp2_min.attr,
+       &dev_attr_auto_temp2_max.attr,
+
+       &dev_attr_auto_fan1_min_pwm.attr,
+
+       &dev_attr_alarms.attr,
+
+       NULL
+};
+
+static const struct attribute_group adm1031_group = {
+       .attrs = adm1031_attributes,
+};
+
+static struct attribute *adm1031_attributes_opt[] = {
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan2_div.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_pwm2.attr,
+       &dev_attr_auto_fan2_channel.attr,
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp3_min.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_temp3_crit.attr,
+       &dev_attr_auto_temp3_off.attr,
+       &dev_attr_auto_temp3_min.attr,
+       &dev_attr_auto_temp3_max.attr,
+       &dev_attr_auto_fan2_min_pwm.attr,
+       NULL
+};
+
+static const struct attribute_group adm1031_group_opt = {
+       .attrs = adm1031_attributes_opt,
+};
+
 /* This function is called by i2c_probe */
 static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -789,57 +844,26 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
        adm1031_init_client(new_client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1031_group)))
                goto exit_detach;
-       }
-
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_pwm1);
-       device_create_file(&new_client->dev, &dev_attr_auto_fan1_channel);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-
-       device_create_file(&new_client->dev, &dev_attr_auto_temp1_off);
-       device_create_file(&new_client->dev, &dev_attr_auto_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_auto_temp1_max);
-
-       device_create_file(&new_client->dev, &dev_attr_auto_temp2_off);
-       device_create_file(&new_client->dev, &dev_attr_auto_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_auto_temp2_max);
-
-       device_create_file(&new_client->dev, &dev_attr_auto_fan1_min_pwm);
-
-       device_create_file(&new_client->dev, &dev_attr_alarms);
 
        if (kind == adm1031) {
-               device_create_file(&new_client->dev, &dev_attr_fan2_input);
-               device_create_file(&new_client->dev, &dev_attr_fan2_div);
-               device_create_file(&new_client->dev, &dev_attr_fan2_min);
-               device_create_file(&new_client->dev, &dev_attr_pwm2);
-               device_create_file(&new_client->dev,
-                                  &dev_attr_auto_fan2_channel);
-               device_create_file(&new_client->dev, &dev_attr_temp3_input);
-               device_create_file(&new_client->dev, &dev_attr_temp3_min);
-               device_create_file(&new_client->dev, &dev_attr_temp3_max);
-               device_create_file(&new_client->dev, &dev_attr_temp3_crit);
-               device_create_file(&new_client->dev, &dev_attr_auto_temp3_off);
-               device_create_file(&new_client->dev, &dev_attr_auto_temp3_min);
-               device_create_file(&new_client->dev, &dev_attr_auto_temp3_max);
-               device_create_file(&new_client->dev, &dev_attr_auto_fan2_min_pwm);
+               if ((err = sysfs_create_group(&new_client->dev.kobj,
+                                               &adm1031_group_opt)))
+                       goto exit_remove;
+       }
+
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove;
        }
 
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &adm1031_group);
+       sysfs_remove_group(&new_client->dev.kobj, &adm1031_group_opt);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -854,6 +878,8 @@ static int adm1031_detach_client(struct i2c_client *client)
        int ret;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &adm1031_group);
+       sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
        if ((ret = i2c_detach_client(client)) != 0) {
                return ret;
        }
index 43f6991b588c6792b3e988f879afbce8c24cd3a1..377961c4a41eb7f737681388418324757a48e0e1 100644 (file)
@@ -465,6 +465,45 @@ static ssize_t chassis_clear(struct device *dev,
 }
 static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
 
+static struct attribute *adm9240_attributes[] = {
+       &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,
+       &dev_attr_temp1_input.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_div.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_aout_output.attr,
+       &dev_attr_chassis_clear.attr,
+       &dev_attr_cpu0_vid.attr,
+       NULL
+};
+
+static const struct attribute_group adm9240_group = {
+       .attrs = adm9240_attributes,
+};
+
 
 /*** sensor chip detect and driver install ***/
 
@@ -548,72 +587,19 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
        adm9240_init_client(new_client);
 
        /* populate sysfs filesystem */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove;
        }
 
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in0_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in0_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in0_max.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in1_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in1_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in1_max.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in2_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in2_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in2_max.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in3_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in3_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in3_max.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in4_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in4_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in4_max.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in5_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in5_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_in5_max.dev_attr);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_temp1_max_hyst.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_fan1_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_fan1_div.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_fan1_min.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_fan2_input.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_fan2_div.dev_attr);
-       device_create_file(&new_client->dev,
-                       &sensor_dev_attr_fan2_min.dev_attr);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_aout_output);
-       device_create_file(&new_client->dev, &dev_attr_chassis_clear);
-       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -635,6 +621,7 @@ static int adm9240_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &adm9240_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index facc1ccb8338fd2515d2f271e89645e321572de1..57b1c7b7ac3f5d54601e799a3b0e5f3aaac50708 100644 (file)
@@ -298,12 +298,6 @@ sysfs_in(4);
 sysfs_in(5);
 sysfs_in(6);
 
-#define device_create_file_in(client, offset) do { \
-       device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-       device_create_file(&client->dev, &dev_attr_in##offset##_min); \
-       device_create_file(&client->dev, &dev_attr_in##offset##_max); \
-} while (0)
-
 /* 3 Fans */
 static ssize_t show_fan(struct device *dev, char *buf, int nr)
 {
@@ -421,12 +415,6 @@ sysfs_fan(1);
 sysfs_fan(2);
 sysfs_fan(3);
 
-#define device_create_file_fan(client, offset) do { \
-       device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-       device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
-       device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-} while (0)
-
 /* 4 Temp. Sensors */
 static int sprintf_temp_from_reg(u16 reg, char *buf, int nr)
 {
@@ -515,12 +503,6 @@ sysfs_temp(3);
 sysfs_temp(4);
 
 /* VID */
-#define device_create_file_temp(client, num) do { \
-       device_create_file(&client->dev, &dev_attr_temp##num##_input); \
-       device_create_file(&client->dev, &dev_attr_temp##num##_max); \
-       device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \
-} while (0)
-
 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct asb100_data *data = asb100_update_device(dev);
@@ -528,8 +510,6 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
 }
 
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 /* VRM */
 static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
@@ -549,8 +529,6 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const
 
 /* Alarms */
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm);
 
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -559,8 +537,6 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-#define device_create_file_alarms(client) \
-device_create_file(&client->dev, &dev_attr_alarms)
 
 /* 1 PWM */
 static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
@@ -607,10 +583,65 @@ static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr
 static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
                show_pwm_enable1, set_pwm_enable1);
-#define device_create_file_pwm1(client) do { \
-       device_create_file(&new_client->dev, &dev_attr_pwm1); \
-       device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \
-} while (0)
+
+static struct attribute *asb100_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,
+
+       &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,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_max_hyst.attr,
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_temp3_max_hyst.attr,
+       &dev_attr_temp4_input.attr,
+       &dev_attr_temp4_max.attr,
+       &dev_attr_temp4_max_hyst.attr,
+
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm1_enable.attr,
+
+       NULL
+};
+
+static const struct attribute_group asb100_group = {
+       .attrs = asb100_attributes,
+};
 
 /* This function is called when:
        asb100_driver is inserted (when this module is loaded), for each
@@ -810,38 +841,19 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
        data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group)))
+               goto ERROR3;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto ERROR3;
+               goto ERROR4;
        }
 
-       device_create_file_in(new_client, 0);
-       device_create_file_in(new_client, 1);
-       device_create_file_in(new_client, 2);
-       device_create_file_in(new_client, 3);
-       device_create_file_in(new_client, 4);
-       device_create_file_in(new_client, 5);
-       device_create_file_in(new_client, 6);
-
-       device_create_file_fan(new_client, 1);
-       device_create_file_fan(new_client, 2);
-       device_create_file_fan(new_client, 3);
-
-       device_create_file_temp(new_client, 1);
-       device_create_file_temp(new_client, 2);
-       device_create_file_temp(new_client, 3);
-       device_create_file_temp(new_client, 4);
-
-       device_create_file_vid(new_client);
-       device_create_file_vrm(new_client);
-
-       device_create_file_alarms(new_client);
-
-       device_create_file_pwm1(new_client);
-
        return 0;
 
+ERROR4:
+       sysfs_remove_group(&new_client->dev.kobj, &asb100_group);
 ERROR3:
        i2c_detach_client(data->lm75[1]);
        i2c_detach_client(data->lm75[0]);
@@ -861,8 +873,10 @@ static int asb100_detach_client(struct i2c_client *client)
        int err;
 
        /* main client */
-       if (data)
+       if (data) {
                hwmon_device_unregister(data->class_dev);
+               sysfs_remove_group(&client->dev.kobj, &asb100_group);
+       }
 
        if ((err = i2c_detach_client(client)))
                return err;
index 728a1e8b91904fe570e6767322d6e0a69dc84e2b..0ccdd0750c44c47968097b5422e6190c7317a2f8 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -116,8 +117,7 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
 {
        struct atxp1_data *data;
        struct i2c_client *client;
-       char vid;
-       char cvid;
+       int vid, cvid;
        unsigned int vcore;
 
        client = to_i2c_client(dev);
@@ -251,6 +251,17 @@ static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *att
 */
 static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
 
+static struct attribute *atxp1_attributes[] = {
+       &dev_attr_gpio1.attr,
+       &dev_attr_gpio2.attr,
+       &dev_attr_cpu0_vid.attr,
+       NULL
+};
+
+static const struct attribute_group atxp1_group = {
+       .attrs = atxp1_attributes,
+};
+
 
 static int atxp1_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -320,21 +331,23 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit_free;
        }
 
+       /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_gpio1);
-       device_create_file(&new_client->dev, &dev_attr_gpio2);
-       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-
        dev_info(&new_client->dev, "Using VRM: %d.%d\n",
                         data->vrm / 10, data->vrm % 10);
 
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -349,6 +362,7 @@ static int atxp1_detach_client(struct i2c_client * client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &atxp1_group);
 
        err = i2c_detach_client(client);
 
index 478eb4bb8570958464f57f582c8ee6d52c4edadb..c849c0c6ee9ce37edb2b86061aa595476946686c 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include "lm75.h"
 
 /* Addresses to scan */
@@ -178,6 +179,18 @@ static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL);
 static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min);
 static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
 
+static struct attribute *ds1621_attributes[] = {
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group ds1621_group = {
+       .attrs = ds1621_attributes,
+};
+
 
 static int ds1621_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -253,21 +266,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
        ds1621_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &ds1621_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       
        return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
+      exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &ds1621_group);
       exit_detach:
        i2c_detach_client(new_client);
       exit_free:
@@ -282,6 +293,7 @@ static int ds1621_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &ds1621_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index fd72440faf76167e08a22d9409255a70c4dba256..de17a72149d98ffb999b156b91a4942ee9cec2aa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
  *             hardware monitoring features
- * Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2005-2006  Jean Delvare <khali@linux-fr.org>
  *
  * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
  * complete hardware monitoring features: voltage, fan and temperature
@@ -31,6 +31,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 static struct platform_device *pdev;
@@ -147,7 +148,7 @@ struct f71805f_data {
        u8 temp_high[3];
        u8 temp_hyst[3];
        u8 temp_mode;
-       u8 alarms[3];
+       unsigned long alarms;
 };
 
 static inline long in_from_reg(u8 reg)
@@ -311,10 +312,9 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
                        data->temp[nr] = f71805f_read8(data,
                                         F71805F_REG_TEMP(nr));
                }
-               for (nr = 0; nr < 3; nr++) {
-                       data->alarms[nr] = f71805f_read8(data,
-                                          F71805F_REG_STATUS(nr));
-               }
+               data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0))
+                       + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8)
+                       + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
 
                data->last_updated = jiffies;
                data->valid = 1;
@@ -557,8 +557,7 @@ static ssize_t show_alarms_in(struct device *dev, struct device_attribute
 {
        struct f71805f_data *data = f71805f_update_device(dev);
 
-       return sprintf(buf, "%d\n", data->alarms[0] |
-                                   ((data->alarms[1] & 0x01) << 8));
+       return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
 }
 
 static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
@@ -566,7 +565,7 @@ static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
 {
        struct f71805f_data *data = f71805f_update_device(dev);
 
-       return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
+       return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07);
 }
 
 static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
@@ -574,7 +573,17 @@ static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
 {
        struct f71805f_data *data = f71805f_update_device(dev);
 
-       return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
+       return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07);
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
+{
+       struct f71805f_data *data = f71805f_update_device(dev);
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       int bitnr = attr->index;
+
+       return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1);
 }
 
 static ssize_t show_name(struct device *dev, struct device_attribute
@@ -585,88 +594,189 @@ static ssize_t show_name(struct device *dev, struct device_attribute
        return sprintf(buf, "%s\n", data->name);
 }
 
-static struct device_attribute f71805f_dev_attr[] = {
-       __ATTR(in0_input, S_IRUGO, show_in0, NULL),
-       __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max),
-       __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min),
-       __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL),
-       __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL),
-       __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL),
-       __ATTR(name, S_IRUGO, show_name, NULL),
+static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
+static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
+static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 1);
+static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 2);
+static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 3);
+static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 4);
+static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 5);
+static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 6);
+static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
+static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 7);
+static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 7);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
+static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
+                         show_in_max, set_in_max, 8);
+static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
+                         show_in_min, set_in_min, 8);
+
+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, set_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, set_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, set_fan_min, 2);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
+                   show_temp_max, set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
+                   show_temp_hyst, set_temp_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
+                   show_temp_max, set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
+                   show_temp_hyst, set_temp_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
+                   show_temp_max, set_temp_max, 2);
+static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
+                   show_temp_hyst, set_temp_hyst, 2);
+static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
+static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
+static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct attribute *f71805f_attributes[] = {
+       &dev_attr_in0_input.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in0_min.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_max.dev_attr.attr,
+       &sensor_dev_attr_in1_min.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_max.dev_attr.attr,
+       &sensor_dev_attr_in2_min.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in5_max.dev_attr.attr,
+       &sensor_dev_attr_in5_min.dev_attr.attr,
+       &sensor_dev_attr_in6_input.dev_attr.attr,
+       &sensor_dev_attr_in6_max.dev_attr.attr,
+       &sensor_dev_attr_in6_min.dev_attr.attr,
+       &sensor_dev_attr_in7_input.dev_attr.attr,
+       &sensor_dev_attr_in7_max.dev_attr.attr,
+       &sensor_dev_attr_in7_min.dev_attr.attr,
+       &sensor_dev_attr_in8_input.dev_attr.attr,
+       &sensor_dev_attr_in8_max.dev_attr.attr,
+       &sensor_dev_attr_in8_min.dev_attr.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,
+       &sensor_dev_attr_temp1_type.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp2_type.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp3_type.dev_attr.attr,
+
+       &sensor_dev_attr_in0_alarm.dev_attr.attr,
+       &sensor_dev_attr_in1_alarm.dev_attr.attr,
+       &sensor_dev_attr_in2_alarm.dev_attr.attr,
+       &sensor_dev_attr_in3_alarm.dev_attr.attr,
+       &sensor_dev_attr_in4_alarm.dev_attr.attr,
+       &sensor_dev_attr_in5_alarm.dev_attr.attr,
+       &sensor_dev_attr_in6_alarm.dev_attr.attr,
+       &sensor_dev_attr_in7_alarm.dev_attr.attr,
+       &sensor_dev_attr_in8_alarm.dev_attr.attr,
+       &dev_attr_alarms_in.attr,
+       &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_alarm.dev_attr.attr,
+       &dev_attr_alarms_temp.attr,
+       &dev_attr_alarms_fan.attr,
+
+       &dev_attr_name.attr,
+       NULL
 };
 
-static struct sensor_device_attribute f71805f_sensor_attr[] = {
-       SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
-       SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 1),
-       SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 1),
-       SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
-       SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 2),
-       SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 2),
-       SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
-       SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 3),
-       SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 3),
-       SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
-       SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 4),
-       SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 4),
-       SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
-       SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 5),
-       SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 5),
-       SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
-       SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 6),
-       SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 6),
-       SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
-       SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 7),
-       SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 7),
-       SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
-       SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR,
-                   show_in_max, set_in_max, 8),
-       SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR,
-                   show_in_min, set_in_min, 8),
-
-       SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
-       SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
-                   show_temp_max, set_temp_max, 0),
-       SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
-                   show_temp_hyst, set_temp_hyst, 0),
-       SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
-       SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
-       SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
-                   show_temp_max, set_temp_max, 1),
-       SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
-                   show_temp_hyst, set_temp_hyst, 1),
-       SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
-       SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
-       SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
-                   show_temp_max, set_temp_max, 2),
-       SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
-                   show_temp_hyst, set_temp_hyst, 2),
-       SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
+static const struct attribute_group f71805f_group = {
+       .attrs = f71805f_attributes,
 };
 
-static struct sensor_device_attribute f71805f_fan_attr[] = {
-       SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
-       SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR,
-                   show_fan_min, set_fan_min, 0),
-       SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
-       SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR,
-                   show_fan_min, set_fan_min, 1),
-       SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
-       SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR,
-                   show_fan_min, set_fan_min, 2),
+static struct attribute *f71805f_attributes_fan[3][4] = {
+       {
+               &sensor_dev_attr_fan1_input.dev_attr.attr,
+               &sensor_dev_attr_fan1_min.dev_attr.attr,
+               &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_fan2_input.dev_attr.attr,
+               &sensor_dev_attr_fan2_min.dev_attr.attr,
+               &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_fan3_input.dev_attr.attr,
+               &sensor_dev_attr_fan3_min.dev_attr.attr,
+               &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+               NULL
+       }
+};
+
+static const struct attribute_group f71805f_group_fan[3] = {
+       { .attrs = f71805f_attributes_fan[0] },
+       { .attrs = f71805f_attributes_fan[1] },
+       { .attrs = f71805f_attributes_fan[2] },
 };
 
 /*
@@ -714,43 +824,35 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, data);
 
-       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_free;
-       }
-
        /* Initialize the F71805F chip */
        f71805f_init_device(data);
 
        /* Register sysfs interface files */
-       for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) {
-               err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]);
-               if (err)
-                       goto exit_class;
-       }
-       for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) {
-               err = device_create_file(&pdev->dev,
-                                        &f71805f_sensor_attr[i].dev_attr);
-               if (err)
-                       goto exit_class;
-       }
-       for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) {
-               if (!(data->fan_enabled & (1 << (i / 2))))
+       if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
+               goto exit_free;
+       for (i = 0; i < 3; i++) {
+               if (!(data->fan_enabled & (1 << i)))
                        continue;
-               err = device_create_file(&pdev->dev,
-                                        &f71805f_fan_attr[i].dev_attr);
-               if (err)
-                       goto exit_class;
+               if ((err = sysfs_create_group(&pdev->dev.kobj,
+                                             &f71805f_group_fan[i])))
+                       goto exit_remove_files;
+       }
+
+       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_remove_files;
        }
 
        return 0;
 
-exit_class:
-       dev_err(&pdev->dev, "Sysfs interface creation failed\n");
-       hwmon_device_unregister(data->class_dev);
+exit_remove_files:
+       sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
+       for (i = 0; i < 3; i++)
+               sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
 exit_free:
+       platform_set_drvdata(pdev, NULL);
        kfree(data);
 exit:
        return err;
@@ -759,9 +861,13 @@ exit:
 static int __devexit f71805f_remove(struct platform_device *pdev)
 {
        struct f71805f_data *data = platform_get_drvdata(pdev);
+       int i;
 
        platform_set_drvdata(pdev, NULL);
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
+       for (i = 0; i < 3; i++)
+               sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
        kfree(data);
 
        return 0;
index 6bc76b407636d8a1a8199669d588d51f96bd9b8e..19717752cfcad64a6efd3d786a79d3b53b861578 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -240,47 +241,45 @@ sysfs_alarms(FSCHER_REG_EVENTS)
 sysfs_control(FSCHER_REG_CONTROL)
 sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET)
   
-#define device_create_file_fan(client, offset) \
-do { \
-       device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
-       device_create_file(&client->dev, &dev_attr_pwm##offset); \
-       device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-       device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-} while (0)
-
-#define device_create_file_temp(client, offset) \
-do { \
-       device_create_file(&client->dev, &dev_attr_temp##offset##_status); \
-       device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
-} while (0)
-
-#define device_create_file_in(client, offset) \
-do { \
-       device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-} while (0)
-
-#define device_create_file_revision(client) \
-do { \
-       device_create_file(&client->dev, &dev_attr_revision); \
-} while (0)
-
-#define device_create_file_alarms(client) \
-do { \
-       device_create_file(&client->dev, &dev_attr_alarms); \
-} while (0)
-
-#define device_create_file_control(client) \
-do { \
-       device_create_file(&client->dev, &dev_attr_control); \
-} while (0)
-
-#define device_create_file_watchdog(client) \
-do { \
-       device_create_file(&client->dev, &dev_attr_watchdog_status); \
-       device_create_file(&client->dev, &dev_attr_watchdog_control); \
-       device_create_file(&client->dev, &dev_attr_watchdog_preset); \
-} while (0)
-  
+static struct attribute *fscher_attributes[] = {
+       &dev_attr_revision.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_control.attr,
+
+       &dev_attr_watchdog_status.attr,
+       &dev_attr_watchdog_control.attr,
+       &dev_attr_watchdog_preset.attr,
+
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+
+       &dev_attr_fan1_status.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan1_input.attr,
+       &dev_attr_pwm1.attr,
+       &dev_attr_fan2_status.attr,
+       &dev_attr_fan2_div.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_pwm2.attr,
+       &dev_attr_fan3_status.attr,
+       &dev_attr_fan3_div.attr,
+       &dev_attr_fan3_input.attr,
+       &dev_attr_pwm3.attr,
+
+       &dev_attr_temp1_status.attr,
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_status.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp3_status.attr,
+       &dev_attr_temp3_input.attr,
+       NULL
+};
+
+static const struct attribute_group fscher_group = {
+       .attrs = fscher_attributes,
+};
+
 /*
  * Real code
  */
@@ -342,31 +341,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
        fscher_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file_revision(new_client);
-       device_create_file_alarms(new_client);
-       device_create_file_control(new_client);
-       device_create_file_watchdog(new_client);
-
-       device_create_file_in(new_client, 0);
-       device_create_file_in(new_client, 1);
-       device_create_file_in(new_client, 2);
-
-       device_create_file_fan(new_client, 1);
-       device_create_file_fan(new_client, 2);
-       device_create_file_fan(new_client, 3);
-
-       device_create_file_temp(new_client, 1);
-       device_create_file_temp(new_client, 2);
-       device_create_file_temp(new_client, 3);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &fscher_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -381,6 +368,7 @@ static int fscher_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &fscher_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 6dc4846b9eebb98ce6d661dfd49b40edfdc28536..ea506a77f9c9d25f701b5cc222c471439f56ca6a 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -432,6 +433,44 @@ static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
 static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
 static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
 
+static struct attribute *fscpos_attributes[] = {
+       &dev_attr_event.attr,
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+
+       &dev_attr_wdog_control.attr,
+       &dev_attr_wdog_preset.attr,
+       &dev_attr_wdog_state.attr,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_status.attr,
+       &dev_attr_temp1_reset.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_status.attr,
+       &dev_attr_temp2_reset.attr,
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp3_status.attr,
+       &dev_attr_temp3_reset.attr,
+
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan1_status.attr,
+       &dev_attr_fan1_ripple.attr,
+       &dev_attr_pwm1.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan2_status.attr,
+       &dev_attr_fan2_ripple.attr,
+       &dev_attr_pwm2.attr,
+       &dev_attr_fan3_input.attr,
+       &dev_attr_fan3_status.attr,
+       &dev_attr_fan3_ripple.attr,
+       NULL
+};
+
+static const struct attribute_group fscpos_group = {
+       .attrs = fscpos_attributes,
+};
+
 static int fscpos_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
@@ -497,42 +536,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
        dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_event);
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_wdog_control);
-       device_create_file(&new_client->dev, &dev_attr_wdog_preset);
-       device_create_file(&new_client->dev, &dev_attr_wdog_state);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_status);
-       device_create_file(&new_client->dev, &dev_attr_temp1_reset);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_status);
-       device_create_file(&new_client->dev, &dev_attr_temp2_reset);
-       device_create_file(&new_client->dev, &dev_attr_temp3_input);
-       device_create_file(&new_client->dev, &dev_attr_temp3_status);
-       device_create_file(&new_client->dev, &dev_attr_temp3_reset);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_status);
-       device_create_file(&new_client->dev, &dev_attr_fan1_ripple);
-       device_create_file(&new_client->dev, &dev_attr_pwm1);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_status);
-       device_create_file(&new_client->dev, &dev_attr_fan2_ripple);
-       device_create_file(&new_client->dev, &dev_attr_pwm2);
-       device_create_file(&new_client->dev, &dev_attr_fan3_input);
-       device_create_file(&new_client->dev, &dev_attr_fan3_status);
-       device_create_file(&new_client->dev, &dev_attr_fan3_ripple);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &fscpos_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -547,6 +563,7 @@ static int fscpos_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &fscpos_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 6606aabdb49d5d7b7d3125a496a5a496ceb0e0b8..c103640455a324614f253c741807d34de7e31af7 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
@@ -340,6 +341,42 @@ static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO,
 static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO,
        show_beep_mask, set_beep_mask);
 
+static struct attribute *gl518_attributes[] = {
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in2_min.attr,
+       &dev_attr_in3_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in1_max.attr,
+       &dev_attr_in2_max.attr,
+       &dev_attr_in3_max.attr,
+
+       &dev_attr_fan1_auto.attr,
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan2_div.attr,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+
+       &dev_attr_alarms.attr,
+       &dev_attr_beep_enable.attr,
+       &dev_attr_beep_mask.attr,
+       NULL
+};
+
+static const struct attribute_group gl518_group = {
+       .attrs = gl518_attributes,
+};
+
 /*
  * Real code
  */
@@ -420,43 +457,19 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
        gl518_init_client((struct i2c_client *) new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &gl518_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_fan1_auto);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_beep_enable);
-       device_create_file(&new_client->dev, &dev_attr_beep_mask);
-
        return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
-
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &gl518_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -490,6 +503,7 @@ static int gl518_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &gl518_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 14e810f3c2c09db43ab6687efbfaa8076c65fc5c..ebe7b9aaa91696f092bda00593400f4a1215ab27 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /* Type of the extra sensor */
 static unsigned short extra_sensor_type;
@@ -190,55 +191,29 @@ static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL);
 #define sysfs_vid(n) \
 sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT)
 
-#define device_create_file_vid(client, n) \
-device_create_file(&client->dev, &dev_attr_cpu##n##_vid)
-
 #define sysfs_in(n) \
 sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \
 sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \
 sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \
 
-#define device_create_file_in(client, n) \
-({device_create_file(&client->dev, &dev_attr_in##n##_input); \
-device_create_file(&client->dev, &dev_attr_in##n##_min); \
-device_create_file(&client->dev, &dev_attr_in##n##_max);})
-
 #define sysfs_fan(n) \
 sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \
 sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \
 sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV)
 
-#define device_create_file_fan(client, n) \
-({device_create_file(&client->dev, &dev_attr_fan##n##_input); \
-device_create_file(&client->dev, &dev_attr_fan##n##_min); \
-device_create_file(&client->dev, &dev_attr_fan##n##_div);})
-
 #define sysfs_fan_off(n) \
 sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \
 
-#define device_create_file_fan_off(client, n) \
-device_create_file(&client->dev, &dev_attr_fan##n##_off)
-
 #define sysfs_temp(n) \
 sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \
 sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \
 sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST)
 
-#define device_create_file_temp(client, n) \
-({device_create_file(&client->dev, &dev_attr_temp##n##_input); \
-device_create_file(&client->dev, &dev_attr_temp##n##_max); \
-device_create_file(&client->dev, &dev_attr_temp##n##_max_hyst);})
-
 #define sysfs_alarms() \
 sysfs_ro(alarms, , GL520_REG_ALARMS) \
 sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \
 sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK)
 
-#define device_create_file_alarms(client) \
-({device_create_file(&client->dev, &dev_attr_alarms); \
-device_create_file(&client->dev, &dev_attr_beep_enable); \
-device_create_file(&client->dev, &dev_attr_beep_mask);})
-
 
 sysfs_vid(0)
 
@@ -511,6 +486,59 @@ static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data,
        return count;
 }
 
+static struct attribute *gl520_attributes[] = {
+       &dev_attr_cpu0_vid.attr,
+
+       &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_fan1_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan1_off.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan2_div.attr,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+
+       &dev_attr_alarms.attr,
+       &dev_attr_beep_enable.attr,
+       &dev_attr_beep_mask.attr,
+       NULL
+};
+
+static const struct attribute_group gl520_group = {
+       .attrs = gl520_attributes,
+};
+
+static struct attribute *gl520_attributes_opt[] = {
+       &dev_attr_in4_input.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in4_max.attr,
+
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_max_hyst.attr,
+       NULL
+};
+
+static const struct attribute_group gl520_group_opt = {
+       .attrs = gl520_attributes_opt,
+};
+
 
 /*
  * Real code
@@ -572,33 +600,39 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
        gl520_init_client(new_client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group)))
                goto exit_detach;
-       }
-
-       device_create_file_vid(new_client, 0);
 
-       device_create_file_in(new_client, 0);
-       device_create_file_in(new_client, 1);
-       device_create_file_in(new_client, 2);
-       device_create_file_in(new_client, 3);
-       if (!data->two_temps)
-               device_create_file_in(new_client, 4);
-
-       device_create_file_fan(new_client, 1);
-       device_create_file_fan(new_client, 2);
-       device_create_file_fan_off(new_client, 1);
+       if (data->two_temps) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_temp2_input))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_temp2_max))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_temp2_max_hyst)))
+                       goto exit_remove_files;
+       } else {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_in4_input))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_in4_min))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_in4_max)))
+                       goto exit_remove_files;
+       }
 
-       device_create_file_temp(new_client, 1);
-       if (data->two_temps)
-               device_create_file_temp(new_client, 2);
 
-       device_create_file_alarms(new_client);
+       data->class_dev = hwmon_device_register(&new_client->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(&new_client->dev.kobj, &gl520_group);
+       sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -652,6 +686,8 @@ static int gl520_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &gl520_group);
+       sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 42b632889dd891e7f91259f45ee9a7ceb2aee07c..26be4ea8a38ac7c2150d250fdabcc3395f5cbb71 100644 (file)
@@ -537,6 +537,7 @@ static int __init hdaps_init(void)
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
                HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
+               HDAPS_DMI_MATCH_LENOVO("ThinkPad T60"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
                HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
                HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
@@ -587,7 +588,9 @@ static int __init hdaps_init(void)
        input_set_abs_params(hdaps_idev, ABS_Y,
                        -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
 
-       input_register_device(hdaps_idev);
+       ret = input_register_device(hdaps_idev);
+       if (ret)
+               goto out_idev;
 
        /* start up our timer for the input device */
        init_timer(&hdaps_timer);
@@ -598,6 +601,8 @@ static int __init hdaps_init(void)
        printk(KERN_INFO "hdaps: driver successfully loaded.\n");
        return 0;
 
+out_idev:
+       input_free_device(hdaps_idev);
 out_group:
        sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
 out_device:
index 06df92b3ee492ccbfe3db607e1bd221e65a48b87..323ef06719c160537942a002b5495a79159c2b28 100644 (file)
@@ -4,10 +4,12 @@
 
     Supports: IT8705F  Super I/O chip w/LPC interface
               IT8712F  Super I/O chip w/LPC interface & SMBus
+              IT8716F  Super I/O chip w/LPC interface
+              IT8718F  Super I/O chip w/LPC interface
               Sis950   A clone of the IT8705F
 
     Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> 
-    Largely inspired by lm78.c of the same package
+    Copyright (C) 2005-2006 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
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/*
-    djg@pdp8.net David Gesswein 7/18/01
-    Modified to fix bug with not all alarms enabled.
-    Added ability to read battery voltage and select temperature sensor
-    type at module load time.
-*/
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -42,6 +37,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
@@ -50,12 +46,13 @@ static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 static unsigned short isa_address;
 
 /* Insmod parameters */
-I2C_CLIENT_INSMOD_2(it87, it8712);
+I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718);
 
 #define        REG     0x2e    /* The register to read/write */
 #define        DEV     0x07    /* Register: Logical device select */
 #define        VAL     0x2f    /* The value to read/write */
 #define PME    0x04    /* The device with the fan registers in it */
+#define GPIO   0x07    /* The device with the IT8718F VID value in it */
 #define        DEVID   0x20    /* Register: Device ID */
 #define        DEVREV  0x22    /* Register: Device Revision */
 
@@ -77,10 +74,10 @@ static int superio_inw(int reg)
 }
 
 static inline void
-superio_select(void)
+superio_select(int ldn)
 {
        outb(DEV, REG);
-       outb(PME, VAL);
+       outb(ldn, VAL);
 }
 
 static inline void
@@ -99,20 +96,27 @@ superio_exit(void)
        outb(0x02, VAL);
 }
 
+/* Logical device 4 registers */
 #define IT8712F_DEVID 0x8712
 #define IT8705F_DEVID 0x8705
+#define IT8716F_DEVID 0x8716
+#define IT8718F_DEVID 0x8718
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
+/* Logical device 7 registers (IT8712F and later) */
+#define IT87_SIO_PINX2_REG     0x2c    /* Pin selection */
+#define IT87_SIO_VID_REG       0xfc    /* VID value */
+
 /* Update battery voltage after every reading if true */
 static int update_vbat;
 
 /* Not all BIOSes properly configure the PWM registers */
 static int fix_pwm_polarity;
 
-/* Chip Type */
-
+/* Values read from Super-I/O config space */
 static u16 chip_type;
+static u8 vid_value;
 
 /* Many IT87 constants specified below */
 
@@ -131,13 +135,21 @@ static u16 chip_type;
 #define IT87_REG_ALARM2        0x02
 #define IT87_REG_ALARM3        0x03
 
+/* The IT8718F has the VID value in a different register, in Super-I/O
+   configuration space. */
 #define IT87_REG_VID           0x0a
+/* Warning: register 0x0b is used for something completely different in
+   new chips/revisions. I suspect only 16-bit tachometer mode will work
+   for these. */
 #define IT87_REG_FAN_DIV       0x0b
+#define IT87_REG_FAN_16BIT     0x0c
 
 /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
 
 #define IT87_REG_FAN(nr)       (0x0d + (nr))
 #define IT87_REG_FAN_MIN(nr)   (0x10 + (nr))
+#define IT87_REG_FANX(nr)      (0x18 + (nr))
+#define IT87_REG_FANX_MIN(nr)  (0x1b + (nr))
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
@@ -169,7 +181,16 @@ static inline u8 FAN_TO_REG(long rpm, int div)
                             254);
 }
 
+static inline u16 FAN16_TO_REG(long rpm)
+{
+       if (rpm == 0)
+               return 0xffff;
+       return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
+}
+
 #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
+/* The divider is fixed to 2 in 16-bit mode */
+#define FAN16_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:1350000/((val)*2))
 
 #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\
                                        ((val)+500)/1000),-128,127))
@@ -181,7 +202,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 static int DIV_TO_REG(int val)
 {
        int answer = 0;
-       while ((val >>= 1) != 0)
+       while (answer < 7 && (val >>= 1))
                answer++;
        return answer;
 }
@@ -203,10 +224,11 @@ struct it87_data {
        unsigned long last_updated;     /* In jiffies */
 
        u8 in[9];               /* Register value */
-       u8 in_max[9];           /* Register value */
-       u8 in_min[9];           /* Register value */
-       u8 fan[3];              /* Register value */
-       u8 fan_min[3];          /* Register value */
+       u8 in_max[8];           /* Register value */
+       u8 in_min[8];           /* Register value */
+       u8 has_fan;             /* Bitfield, fans enabled */
+       u16 fan[3];             /* Register values, possibly combined */
+       u16 fan_min[3];         /* Register values, possibly combined */
        u8 temp[3];             /* Register value */
        u8 temp_high[3];        /* Register value */
        u8 temp_low[3];         /* Register value */
@@ -243,6 +265,7 @@ static struct i2c_driver it87_driver = {
 
 static struct i2c_driver it87_isa_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "it87-isa",
        },
        .attach_adapter = it87_isa_attach_adapter,
@@ -544,15 +567,15 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 
        struct i2c_client *client = to_i2c_client(dev);
        struct it87_data *data = i2c_get_clientdata(client);
-       int val = simple_strtol(buf, NULL, 10);
-       int i, min[3];
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       int min;
        u8 old;
 
        mutex_lock(&data->update_lock);
        old = it87_read_value(client, IT87_REG_FAN_DIV);
 
-       for (i = 0; i < 3; i++)
-               min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i]));
+       /* Save fan min limit */
+       min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
 
        switch (nr) {
        case 0:
@@ -572,10 +595,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
                val |= 0x1 << 6;
        it87_write_value(client, IT87_REG_FAN_DIV, val);
 
-       for (i = 0; i < 3; i++) {
-               data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i]));
-               it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]);
-       }
+       /* Restore fan min limit */
+       data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+       it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
+
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -656,6 +679,59 @@ show_pwm_offset(1);
 show_pwm_offset(2);
 show_pwm_offset(3);
 
+/* A different set of callbacks for 16-bit fans */
+static ssize_t show_fan16(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct it87_data *data = it87_update_device(dev);
+       return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr]));
+}
+
+static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct it87_data *data = it87_update_device(dev);
+       return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr]));
+}
+
+static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct it87_data *data = i2c_get_clientdata(client);
+       int val = simple_strtol(buf, NULL, 10);
+
+       mutex_lock(&data->update_lock);
+       data->fan_min[nr] = FAN16_TO_REG(val);
+       it87_write_value(client, IT87_REG_FAN_MIN(nr),
+                        data->fan_min[nr] & 0xff);
+       it87_write_value(client, IT87_REG_FANX_MIN(nr),
+                        data->fan_min[nr] >> 8);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+/* We want to use the same sysfs file names as 8-bit fans, but we need
+   different variable names, so we have to use SENSOR_ATTR instead of
+   SENSOR_DEVICE_ATTR. */
+#define show_fan16_offset(offset) \
+static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \
+       = SENSOR_ATTR(fan##offset##_input, S_IRUGO,             \
+               show_fan16, NULL, offset - 1);                  \
+static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \
+       = SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,     \
+               show_fan16_min, set_fan16_min, offset - 1)
+
+show_fan16_offset(1);
+show_fan16_offset(2);
+show_fan16_offset(3);
+
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -683,8 +759,6 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf
        return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm)
 
 static ssize_t
 show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -693,8 +767,88 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid)
+
+static struct attribute *it87_attributes[] = {
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in6_input.dev_attr.attr,
+       &sensor_dev_attr_in7_input.dev_attr.attr,
+       &sensor_dev_attr_in8_input.dev_attr.attr,
+       &sensor_dev_attr_in0_min.dev_attr.attr,
+       &sensor_dev_attr_in1_min.dev_attr.attr,
+       &sensor_dev_attr_in2_min.dev_attr.attr,
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in5_min.dev_attr.attr,
+       &sensor_dev_attr_in6_min.dev_attr.attr,
+       &sensor_dev_attr_in7_min.dev_attr.attr,
+       &sensor_dev_attr_in0_max.dev_attr.attr,
+       &sensor_dev_attr_in1_max.dev_attr.attr,
+       &sensor_dev_attr_in2_max.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in5_max.dev_attr.attr,
+       &sensor_dev_attr_in6_max.dev_attr.attr,
+       &sensor_dev_attr_in7_max.dev_attr.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_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp3_min.dev_attr.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,
+
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group it87_group = {
+       .attrs = it87_attributes,
+};
+
+static struct attribute *it87_attributes_opt[] = {
+       &sensor_dev_attr_fan1_input16.dev_attr.attr,
+       &sensor_dev_attr_fan1_min16.dev_attr.attr,
+       &sensor_dev_attr_fan2_input16.dev_attr.attr,
+       &sensor_dev_attr_fan2_min16.dev_attr.attr,
+       &sensor_dev_attr_fan3_input16.dev_attr.attr,
+       &sensor_dev_attr_fan3_min16.dev_attr.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_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_pwm2.dev_attr.attr,
+       &sensor_dev_attr_pwm3.dev_attr.attr,
+
+       &dev_attr_vrm.attr,
+       &dev_attr_cpu0_vid.attr,
+       NULL
+};
+
+static const struct attribute_group it87_group_opt = {
+       .attrs = it87_attributes_opt,
+};
 
 /* This function is called when:
      * it87_driver is inserted (when this module is loaded), for each
@@ -720,10 +874,12 @@ static int __init it87_find(unsigned short *address)
        superio_enter();
        chip_type = superio_inw(DEVID);
        if (chip_type != IT8712F_DEVID
+        && chip_type != IT8716F_DEVID
+        && chip_type != IT8718F_DEVID
         && chip_type != IT8705F_DEVID)
                goto exit;
 
-       superio_select();
+       superio_select(PME);
        if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
                pr_info("it87: Device not activated, skipping\n");
                goto exit;
@@ -739,6 +895,21 @@ static int __init it87_find(unsigned short *address)
        pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
                chip_type, *address, superio_inb(DEVREV) & 0x0f);
 
+       /* Read GPIO config and VID value from LDN 7 (GPIO) */
+       if (chip_type != IT8705F_DEVID) {
+               int reg;
+
+               superio_select(GPIO);
+               if (chip_type == it8718)
+                       vid_value = superio_inb(IT87_SIO_VID_REG);
+
+               reg = superio_inb(IT87_SIO_PINX2_REG);
+               if (reg & (1 << 0))
+                       pr_info("it87: in3 is VCC (+5V)\n");
+               if (reg & (1 << 1))
+                       pr_info("it87: in7 is VCCH (+5V Stand-By)\n");
+       }
+
 exit:
        superio_exit();
        return err;
@@ -799,8 +970,19 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
                i = it87_read_value(new_client, IT87_REG_CHIPID);
                if (i == 0x90) {
                        kind = it87;
-                       if ((is_isa) && (chip_type == IT8712F_DEVID))
-                               kind = it8712;
+                       if (is_isa) {
+                               switch (chip_type) {
+                               case IT8712F_DEVID:
+                                       kind = it8712;
+                                       break;
+                               case IT8716F_DEVID:
+                                       kind = it8716;
+                                       break;
+                               case IT8718F_DEVID:
+                                       kind = it8718;
+                                       break;
+                               }
+                       }
                }
                else {
                        if (kind == 0)
@@ -817,6 +999,10 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
                name = "it87";
        } else if (kind == it8712) {
                name = "it8712";
+       } else if (kind == it8716) {
+               name = "it8716";
+       } else if (kind == it8718) {
+               name = "it8718";
        }
 
        /* Fill in the remaining client fields and put it into the global list */
@@ -841,76 +1027,103 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
        it87_init_client(new_client, data);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &it87_group)))
                goto ERROR3;
+
+       /* Do not create fan files for disabled fans */
+       if (data->type == it8716 || data->type == it8718) {
+               /* 16-bit tachometers */
+               if (data->has_fan & (1 << 0)) {
+                       if ((err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan1_input16.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan1_min16.dev_attr)))
+                               goto ERROR4;
+               }
+               if (data->has_fan & (1 << 1)) {
+                       if ((err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan2_input16.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan2_min16.dev_attr)))
+                               goto ERROR4;
+               }
+               if (data->has_fan & (1 << 2)) {
+                       if ((err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan3_input16.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan3_min16.dev_attr)))
+                               goto ERROR4;
+               }
+       } else {
+               /* 8-bit tachometers with clock divider */
+               if (data->has_fan & (1 << 0)) {
+                       if ((err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan1_input.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan1_min.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan1_div.dev_attr)))
+                               goto ERROR4;
+               }
+               if (data->has_fan & (1 << 1)) {
+                       if ((err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan2_input.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan2_min.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan2_div.dev_attr)))
+                               goto ERROR4;
+               }
+               if (data->has_fan & (1 << 2)) {
+                       if ((err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan3_input.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan3_min.dev_attr))
+                        || (err = device_create_file(&new_client->dev,
+                            &sensor_dev_attr_fan3_div.dev_attr)))
+                               goto ERROR4;
+               }
        }
 
-       device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
-       device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
        if (enable_pwm_interface) {
-               device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr);
-               device_create_file(&new_client->dev, &sensor_dev_attr_pwm2_enable.dev_attr);
-               device_create_file(&new_client->dev, &sensor_dev_attr_pwm3_enable.dev_attr);
-               device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
-               device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
-               device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
+               if ((err = device_create_file(&new_client->dev,
+                    &sensor_dev_attr_pwm1_enable.dev_attr))
+                || (err = device_create_file(&new_client->dev,
+                    &sensor_dev_attr_pwm2_enable.dev_attr))
+                || (err = device_create_file(&new_client->dev,
+                    &sensor_dev_attr_pwm3_enable.dev_attr))
+                || (err = device_create_file(&new_client->dev,
+                    &sensor_dev_attr_pwm1.dev_attr))
+                || (err = device_create_file(&new_client->dev,
+                    &sensor_dev_attr_pwm2.dev_attr))
+                || (err = device_create_file(&new_client->dev,
+                    &sensor_dev_attr_pwm3.dev_attr)))
+                       goto ERROR4;
        }
 
-       if (data->type == it8712) {
+       if (data->type == it8712 || data->type == it8716
+        || data->type == it8718) {
                data->vrm = vid_which_vrm();
-               device_create_file_vrm(new_client);
-               device_create_file_vid(new_client);
+               /* VID reading from Super-I/O config space if available */
+               data->vid = vid_value;
+               if ((err = device_create_file(&new_client->dev,
+                    &dev_attr_vrm))
+                || (err = device_create_file(&new_client->dev,
+                    &dev_attr_cpu0_vid)))
+                       goto ERROR4;
+       }
+
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR4;
        }
 
        return 0;
 
+ERROR4:
+       sysfs_remove_group(&new_client->dev.kobj, &it87_group);
+       sysfs_remove_group(&new_client->dev.kobj, &it87_group_opt);
 ERROR3:
        i2c_detach_client(new_client);
 ERROR2:
@@ -928,6 +1141,8 @@ static int it87_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &it87_group);
+       sysfs_remove_group(&client->dev.kobj, &it87_group_opt);
 
        if ((err = i2c_detach_client(client)))
                return err;
@@ -1044,6 +1259,22 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data)
                data->manual_pwm_ctl[i] = 0xff;
        }
 
+       /* Some chips seem to have default value 0xff for all limit
+        * registers. For low voltage limits it makes no sense and triggers
+        * alarms, so change to 0 instead. For high temperature limits, it
+        * means -1 degree C, which surprisingly doesn't trigger an alarm,
+        * but is still confusing, so change to 127 degrees C. */
+       for (i = 0; i < 8; i++) {
+               tmp = it87_read_value(client, IT87_REG_VIN_MIN(i));
+               if (tmp == 0xff)
+                       it87_write_value(client, IT87_REG_VIN_MIN(i), 0);
+       }
+       for (i = 0; i < 3; i++) {
+               tmp = it87_read_value(client, IT87_REG_TEMP_HIGH(i));
+               if (tmp == 0xff)
+                       it87_write_value(client, IT87_REG_TEMP_HIGH(i), 127);
+       }
+
        /* Check if temperature channnels are reset manually or by some reason */
        tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
        if ((tmp & 0x3f) == 0) {
@@ -1067,6 +1298,18 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data)
                data->fan_main_ctrl |= 0x70;
                it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
        }
+       data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
+
+       /* Set tachometers to 16-bit mode if needed */
+       if (data->type == it8716 || data->type == it8718) {
+               tmp = it87_read_value(client, IT87_REG_FAN_16BIT);
+               if (~tmp & 0x07 & data->has_fan) {
+                       dev_dbg(&client->dev,
+                               "Setting fan1-3 to 16-bit mode\n");
+                       it87_write_value(client, IT87_REG_FAN_16BIT,
+                                        tmp | 0x07);
+               }
+       }
 
        /* Set current fan mode registers and the default settings for the
         * other mode registers */
@@ -1117,18 +1360,26 @@ static struct it87_data *it87_update_device(struct device *dev)
                        data->in_max[i] =
                            it87_read_value(client, IT87_REG_VIN_MAX(i));
                }
+               /* in8 (battery) has no limit registers */
                data->in[8] =
                    it87_read_value(client, IT87_REG_VIN(8));
-               /* Temperature sensor doesn't have limit registers, set
-                  to min and max value */
-               data->in_min[8] = 0;
-               data->in_max[8] = 255;
 
                for (i = 0; i < 3; i++) {
-                       data->fan[i] =
-                           it87_read_value(client, IT87_REG_FAN(i));
+                       /* Skip disabled fans */
+                       if (!(data->has_fan & (1 << i)))
+                               continue;
+
                        data->fan_min[i] =
                            it87_read_value(client, IT87_REG_FAN_MIN(i));
+                       data->fan[i] = it87_read_value(client,
+                                      IT87_REG_FAN(i));
+                       /* Add high byte if in 16-bit mode */
+                       if (data->type == it8716 || data->type == it8718) {
+                               data->fan[i] |= it87_read_value(client,
+                                               IT87_REG_FANX(i)) << 8;
+                               data->fan_min[i] |= it87_read_value(client,
+                                               IT87_REG_FANX_MIN(i)) << 8;
+                       }
                }
                for (i = 0; i < 3; i++) {
                        data->temp[i] =
@@ -1139,10 +1390,14 @@ static struct it87_data *it87_update_device(struct device *dev)
                            it87_read_value(client, IT87_REG_TEMP_LOW(i));
                }
 
-               i = it87_read_value(client, IT87_REG_FAN_DIV);
-               data->fan_div[0] = i & 0x07;
-               data->fan_div[1] = (i >> 3) & 0x07;
-               data->fan_div[2] = (i & 0x40) ? 3 : 1;
+               /* Newer chips don't have clock dividers */
+               if ((data->has_fan & 0x07) && data->type != it8716
+                && data->type != it8718) {
+                       i = it87_read_value(client, IT87_REG_FAN_DIV);
+                       data->fan_div[0] = i & 0x07;
+                       data->fan_div[1] = (i >> 3) & 0x07;
+                       data->fan_div[2] = (i & 0x40) ? 3 : 1;
+               }
 
                data->alarms =
                        it87_read_value(client, IT87_REG_ALARM1) |
@@ -1152,9 +1407,11 @@ static struct it87_data *it87_update_device(struct device *dev)
 
                data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
                /* The 8705 does not have VID capability */
-               if (data->type == it8712) {
+               if (data->type == it8712 || data->type == it8716) {
                        data->vid = it87_read_value(client, IT87_REG_VID);
-                       data->vid &= 0x1f;
+                       /* The older IT8712F revisions had only 5 VID pins,
+                          but we assume it is always safe to read 6 bits. */
+                       data->vid &= 0x3f;
                }
                data->last_updated = jiffies;
                data->valid = 1;
@@ -1192,8 +1449,9 @@ static void __exit sm_it87_exit(void)
 }
 
 
-MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
-MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
+MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>, "
+             "Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F, SiS950 driver");
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
 module_param(fix_pwm_polarity, bool, 0);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
new file mode 100644 (file)
index 0000000..f58b64e
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * k8temp.c - Linux kernel module for hardware monitoring
+ *
+ * Copyright (C) 2006 Rudolf Marek <r.marek@sh.cvut.cz>
+ *
+ * Inspired from the w83785 and amd756 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/pci.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+#define TEMP_FROM_REG(val)     (((((val) >> 16) & 0xff) - 49) * 1000)
+#define REG_TEMP       0xe4
+#define SEL_PLACE      0x40
+#define SEL_CORE       0x04
+
+struct k8temp_data {
+       struct class_device *class_dev;
+       struct mutex update_lock;
+       const char *name;
+       char valid;             /* zero until following fields are valid */
+       unsigned long last_updated;     /* in jiffies */
+
+       /* registers values */
+       u8 sensorsp;            /* sensor presence bits - SEL_CORE & SEL_PLACE */
+       u32 temp[2][2];         /* core, place */
+};
+
+static struct k8temp_data *k8temp_update_device(struct device *dev)
+{
+       struct k8temp_data *data = dev_get_drvdata(dev);
+       struct pci_dev *pdev = to_pci_dev(dev);
+       u8 tmp;
+
+       mutex_lock(&data->update_lock);
+
+       if (!data->valid
+           || time_after(jiffies, data->last_updated + HZ)) {
+               pci_read_config_byte(pdev, REG_TEMP, &tmp);
+               tmp &= ~(SEL_PLACE | SEL_CORE);         /* Select sensor 0, core0 */
+               pci_write_config_byte(pdev, REG_TEMP, tmp);
+               pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]);
+
+               if (data->sensorsp & SEL_PLACE) {
+                       tmp |= SEL_PLACE;       /* Select sensor 1, core0 */
+                       pci_write_config_byte(pdev, REG_TEMP, tmp);
+                       pci_read_config_dword(pdev, REG_TEMP,
+                                             &data->temp[0][1]);
+               }
+
+               if (data->sensorsp & SEL_CORE) {
+                       tmp &= ~SEL_PLACE;      /* Select sensor 0, core1 */
+                       tmp |= SEL_CORE;
+                       pci_write_config_byte(pdev, REG_TEMP, tmp);
+                       pci_read_config_dword(pdev, REG_TEMP,
+                                             &data->temp[1][0]);
+
+                       if (data->sensorsp & SEL_PLACE) {
+                               tmp |= SEL_PLACE;       /* Select sensor 1, core1 */
+                               pci_write_config_byte(pdev, REG_TEMP, tmp);
+                               pci_read_config_dword(pdev, REG_TEMP,
+                                                     &data->temp[1][1]);
+                       }
+               }
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->update_lock);
+       return data;
+}
+
+/*
+ * Sysfs stuff
+ */
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+                        *devattr, char *buf)
+{
+       struct k8temp_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", data->name);
+}
+
+
+static ssize_t show_temp(struct device *dev,
+                        struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr =
+           to_sensor_dev_attr_2(devattr);
+       int core = attr->nr;
+       int place = attr->index;
+       struct k8temp_data *data = k8temp_update_device(dev);
+
+       return sprintf(buf, "%d\n",
+                      TEMP_FROM_REG(data->temp[core][place]));
+}
+
+/* core, place */
+
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct pci_device_id k8temp_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
+       { 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, k8temp_ids);
+
+static int __devinit k8temp_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *id)
+{
+       int err;
+       u8 scfg;
+       u32 temp;
+       struct k8temp_data *data;
+       u32 cpuid = cpuid_eax(1);
+
+       /* this feature should be available since SH-C0 core */
+       if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) {
+               err = -ENODEV;
+               goto exit;
+       }
+
+       if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       pci_read_config_byte(pdev, REG_TEMP, &scfg);
+       scfg &= ~(SEL_PLACE | SEL_CORE);                /* Select sensor 0, core0 */
+       pci_write_config_byte(pdev, REG_TEMP, scfg);
+       pci_read_config_byte(pdev, REG_TEMP, &scfg);
+
+       if (scfg & (SEL_PLACE | SEL_CORE)) {
+               dev_err(&pdev->dev, "Configuration bit(s) stuck at 1!\n");
+               err = -ENODEV;
+               goto exit_free;
+       }
+
+       scfg |= (SEL_PLACE | SEL_CORE);
+       pci_write_config_byte(pdev, REG_TEMP, scfg);
+
+       /* now we know if we can change core and/or sensor */
+       pci_read_config_byte(pdev, REG_TEMP, &data->sensorsp);
+
+       if (data->sensorsp & SEL_PLACE) {
+               scfg &= ~SEL_CORE;      /* Select sensor 1, core0 */
+               pci_write_config_byte(pdev, REG_TEMP, scfg);
+               pci_read_config_dword(pdev, REG_TEMP, &temp);
+               scfg |= SEL_CORE;       /* prepare for next selection */
+               if (!((temp >> 16) & 0xff))     /* if temp is 0 -49C is not likely */
+                       data->sensorsp &= ~SEL_PLACE;
+       }
+
+       if (data->sensorsp & SEL_CORE) {
+               scfg &= ~SEL_PLACE;     /* Select sensor 0, core1 */
+               pci_write_config_byte(pdev, REG_TEMP, scfg);
+               pci_read_config_dword(pdev, REG_TEMP, &temp);
+               if (!((temp >> 16) & 0xff))     /* if temp is 0 -49C is not likely */
+                       data->sensorsp &= ~SEL_CORE;
+       }
+
+       data->name = "k8temp";
+       mutex_init(&data->update_lock);
+       dev_set_drvdata(&pdev->dev, data);
+
+       /* Register sysfs hooks */
+       err = device_create_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       if (err)
+               goto exit_remove;
+
+       /* sensor can be changed and reports something */
+       if (data->sensorsp & SEL_PLACE) {
+               err = device_create_file(&pdev->dev,
+                                  &sensor_dev_attr_temp2_input.dev_attr);
+               if (err)
+                       goto exit_remove;
+       }
+
+       /* core can be changed and reports something */
+       if (data->sensorsp & SEL_CORE) {
+               err = device_create_file(&pdev->dev,
+                                  &sensor_dev_attr_temp3_input.dev_attr);
+               if (err)
+                       goto exit_remove;
+               if (data->sensorsp & SEL_PLACE)
+                       err = device_create_file(&pdev->dev,
+                                          &sensor_dev_attr_temp4_input.
+                                          dev_attr);
+                       if (err)
+                               goto exit_remove;
+       }
+
+       err = device_create_file(&pdev->dev, &dev_attr_name);
+       if (err)
+               goto exit_remove;
+
+       data->class_dev = hwmon_device_register(&pdev->dev);
+
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove;
+       }
+
+       return 0;
+
+exit_remove:
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp2_input.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp3_input.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp4_input.dev_attr);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+exit_free:
+       dev_set_drvdata(&pdev->dev, NULL);
+       kfree(data);
+exit:
+       return err;
+}
+
+static void __devexit k8temp_remove(struct pci_dev *pdev)
+{
+       struct k8temp_data *data = dev_get_drvdata(&pdev->dev);
+
+       hwmon_device_unregister(data->class_dev);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp2_input.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp3_input.dev_attr);
+       device_remove_file(&pdev->dev,
+                          &sensor_dev_attr_temp4_input.dev_attr);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       dev_set_drvdata(&pdev->dev, NULL);
+       kfree(data);
+}
+
+static struct pci_driver k8temp_driver = {
+       .name = "k8temp",
+       .id_table = k8temp_ids,
+       .probe = k8temp_probe,
+       .remove = __devexit_p(k8temp_remove),
+};
+
+static int __init k8temp_init(void)
+{
+       return pci_register_driver(&k8temp_driver);
+}
+
+static void __exit k8temp_exit(void)
+{
+       pci_unregister_driver(&k8temp_driver);
+}
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_DESCRIPTION("AMD K8 core temperature monitor");
+MODULE_LICENSE("GPL");
+
+module_init(k8temp_init)
+module_exit(k8temp_exit)
index 071f0fc6adecef40ba8022cd93eacfa7951540d6..d69f3cf07122462faf33bab61232d86782dd98ce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm63.c - driver for the National Semiconductor LM63 temperature sensor
  *          with integrated fan control
- * Copyright (C) 2004-2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2006  Jean Delvare <khali@linux-fr.org>
  * Based on the lm90 driver.
  *
  * The LM63 is a sensor chip made by National Semiconductor. It measures
@@ -46,6 +46,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -330,6 +331,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
        return sprintf(buf, "%u\n", data->alarms);
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr,
+                         char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm63_data *data = lm63_update_device(dev);
+       int bitnr = attr->index;
+
+       return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
        set_fan, 1);
@@ -350,8 +361,52 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2);
 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
        set_temp2_crit_hyst);
 
+/* Individual alarm files */
+static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+/* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *lm63_attributes[] = {
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm1_enable.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &dev_attr_temp2_crit_hyst.attr,
+
+       &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+       &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group lm63_group = {
+       .attrs = lm63_attributes,
+};
+
+static struct attribute *lm63_attributes_fan1[] = {
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+
+       &sensor_dev_attr_fan1_min_alarm.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group lm63_group_fan1 = {
+       .attrs = lm63_attributes_fan1,
+};
+
 /*
  * Real code
  */
@@ -438,37 +493,26 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
        lm63_init_client(new_client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj,
+                                     &lm63_group)))
                goto exit_detach;
+       if (data->config & 0x04) { /* tachometer enabled */
+               if ((err = sysfs_create_group(&new_client->dev.kobj,
+                                             &lm63_group_fan1)))
+                       goto exit_remove_files;
        }
 
-       if (data->config & 0x04) { /* tachometer enabled */
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_fan1_input.dev_attr);
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_fan1_min.dev_attr);
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove_files;
        }
-       device_create_file(&new_client->dev, &dev_attr_pwm1);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_input.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_min.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_max.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_crit.dev_attr);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
 
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
+       sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -518,6 +562,8 @@ static int lm63_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm63_group);
+       sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
 
        if ((err = i2c_detach_client(client)))
                return err;
index fc25b90ec24a5ec5d0cda40cd335ff0bc7e1aa24..7c65b8bb6d721498c9ac1e0f2dc968bb1b2f4744 100644 (file)
@@ -112,6 +112,18 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, lm75_detect);
 }
 
+static struct attribute *lm75_attributes[] = {
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm75_group = {
+       .attrs = lm75_attributes,
+};
+
 /* This function is called by i2c_probe */
 static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -199,18 +211,19 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
        lm75_init_client(new_client);
        
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm75_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &lm75_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -223,6 +236,7 @@ static int lm75_detach_client(struct i2c_client *client)
 {
        struct lm75_data *data = i2c_get_clientdata(client);
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm75_group);
        i2c_detach_client(client);
        kfree(data);
        return 0;
index 459cc977380a33fc36dbae7bdb968734b1a85cd9..dd969f1e84154e6d754b63cfd8f013d09b3dc87e 100644 (file)
@@ -212,6 +212,23 @@ static int lm77_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, lm77_detect);
 }
 
+static struct attribute *lm77_attributes[] = {
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_crit.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_crit_hyst.attr,
+       &dev_attr_temp1_min_hyst.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_alarms.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm77_group = {
+       .attrs = lm77_attributes,
+};
+
 /* This function is called by i2c_probe */
 static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -317,22 +334,19 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
        lm77_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &lm77_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -345,6 +359,7 @@ static int lm77_detach_client(struct i2c_client *client)
 {
        struct lm77_data *data = i2c_get_clientdata(client);
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm77_group);
        i2c_detach_client(client);
        kfree(data);
        return 0;
index a6ce7abf86025dda21531ac6ecddd611926b705e..ac1b746df6d0ad765b97bcb2fd77cb5bb99dabcb 100644 (file)
@@ -175,6 +175,7 @@ static struct i2c_driver lm78_driver = {
 
 static struct i2c_driver lm78_isa_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "lm78-isa",
        },
        .attach_adapter = lm78_isa_attach_adapter,
@@ -481,6 +482,50 @@ 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,
+       &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,
+       &dev_attr_alarms.attr,
+       &dev_attr_cpu0_vid.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm78_group = {
+       .attrs = lm78_attributes,
+};
+
 /* This function is called by i2c_probe */
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -615,50 +660,19 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group)))
+               goto ERROR3;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto ERROR3;
+               goto ERROR4;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in4_input);
-       device_create_file(&new_client->dev, &dev_attr_in4_min);
-       device_create_file(&new_client->dev, &dev_attr_in4_max);
-       device_create_file(&new_client->dev, &dev_attr_in5_input);
-       device_create_file(&new_client->dev, &dev_attr_in5_min);
-       device_create_file(&new_client->dev, &dev_attr_in5_max);
-       device_create_file(&new_client->dev, &dev_attr_in6_input);
-       device_create_file(&new_client->dev, &dev_attr_in6_min);
-       device_create_file(&new_client->dev, &dev_attr_in6_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_fan3_input);
-       device_create_file(&new_client->dev, &dev_attr_fan3_min);
-       device_create_file(&new_client->dev, &dev_attr_fan3_div);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-
        return 0;
 
+ERROR4:
+       sysfs_remove_group(&new_client->dev.kobj, &lm78_group);
 ERROR3:
        i2c_detach_client(new_client);
 ERROR2:
@@ -676,6 +690,7 @@ static int lm78_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm78_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index b4ccdfc0120305bc6f50e04542c0f953150def95..064516d824add6deca6527a1a7a0255884a19514 100644 (file)
@@ -394,6 +394,48 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, lm80_detect);
 }
 
+static struct attribute *lm80_attributes[] = {
+       &dev_attr_in0_min.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in2_min.attr,
+       &dev_attr_in3_min.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in5_min.attr,
+       &dev_attr_in6_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in1_max.attr,
+       &dev_attr_in2_max.attr,
+       &dev_attr_in3_max.attr,
+       &dev_attr_in4_max.attr,
+       &dev_attr_in5_max.attr,
+       &dev_attr_in6_max.attr,
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       &dev_attr_in4_input.attr,
+       &dev_attr_in5_input.attr,
+       &dev_attr_in6_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan2_div.attr,
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_temp1_crit.attr,
+       &dev_attr_temp1_crit_hyst.attr,
+       &dev_attr_alarms.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm80_group = {
+       .attrs = lm80_attributes,
+};
+
 static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i, cur;
@@ -452,48 +494,19 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
        data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm80_group)))
+               goto error_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto error_detach;
+               goto error_remove;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in4_min);
-       device_create_file(&new_client->dev, &dev_attr_in5_min);
-       device_create_file(&new_client->dev, &dev_attr_in6_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in4_max);
-       device_create_file(&new_client->dev, &dev_attr_in5_max);
-       device_create_file(&new_client->dev, &dev_attr_in6_max);
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in4_input);
-       device_create_file(&new_client->dev, &dev_attr_in5_input);
-       device_create_file(&new_client->dev, &dev_attr_in6_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
        return 0;
 
+error_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &lm80_group);
 error_detach:
        i2c_detach_client(new_client);
 error_free:
@@ -508,7 +521,7 @@ static int lm80_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
-
+       sysfs_remove_group(&client->dev.kobj, &lm80_group);
        if ((err = i2c_detach_client(client)))
                return err;
 
index 2137d7879df668f1f91e46d94a77ed8a2adca043..feb87b41e9865ab10750c9bf247797690ae6d67b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2006  Jean Delvare <khali@linux-fr.org>
  *
  * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
  * a sensor chip made by National Semiconductor. It reports up to four
@@ -40,6 +40,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -191,6 +192,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
        return sprintf(buf, "%d\n", data->alarms);
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm83_data *data = lm83_update_device(dev);
+       int bitnr = attr->index;
+
+       return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
+}
+
 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);
@@ -208,8 +219,64 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8);
 static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
        set_temp, 8);
 static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
+
+/* Individual alarm files */
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(temp4_input_fault, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15);
+/* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *lm83_attributes[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp3_crit.dev_attr.attr,
+
+       &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_input_fault.dev_attr.attr,
+       &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group lm83_group = {
+       .attrs = lm83_attributes,
+};
+
+static struct attribute *lm83_attributes_opt[] = {
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp4_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp4_crit.dev_attr.attr,
+
+       &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp4_input_fault.dev_attr.attr,
+       &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group lm83_group_opt = {
+       .attrs = lm83_attributes_opt,
+};
+
 /*
  * Real code
  */
@@ -318,59 +385,32 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit_free;
 
        /*
-        * Initialize the LM83 chip
-        * (Nothing to do for this one.)
-        */
-
-       /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
-               goto exit_detach;
-       }
-
-       /*
+        * Register sysfs hooks
         * The LM82 can only monitor one external diode which is
         * at the same register as the LM83 temp3 entry - so we
         * declare 1 and 3 common, and then 2 and 4 only for the LM83.
         */
 
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp3_input.dev_attr);
-
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp3_max.dev_attr);
-
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_crit.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp3_crit.dev_attr);
-
-       device_create_file(&new_client->dev, &dev_attr_alarms);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
+               goto exit_detach;
 
        if (kind == lm83) {
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_temp2_input.dev_attr);
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_temp4_input.dev_attr);
-
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_temp2_max.dev_attr);
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_temp4_max.dev_attr);
-
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_temp2_crit.dev_attr);
-               device_create_file(&new_client->dev,
-                                  &sensor_dev_attr_temp4_crit.dev_attr);
+               if ((err = sysfs_create_group(&new_client->dev.kobj,
+                                             &lm83_group_opt)))
+                       goto exit_remove_files;
+       }
+
+       data->class_dev = hwmon_device_register(&new_client->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(&new_client->dev.kobj, &lm83_group);
+       sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -385,6 +425,8 @@ static int lm83_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm83_group);
+       sysfs_remove_group(&client->dev.kobj, &lm83_group_opt);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 342e9663119d45ef9d7c14a9ab240110ca554523..2c3293cf69d10303a3a17bde4fb06471a023cefa 100644 (file)
@@ -1025,6 +1025,89 @@ static int lm85_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, lm85_detect);
 }
 
+static struct attribute *lm85_attributes[] = {
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan3_input.attr,
+       &dev_attr_fan4_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan3_min.attr,
+       &dev_attr_fan4_min.attr,
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm2.attr,
+       &dev_attr_pwm3.attr,
+       &dev_attr_pwm1_enable.attr,
+       &dev_attr_pwm2_enable.attr,
+       &dev_attr_pwm3_enable.attr,
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in2_min.attr,
+       &dev_attr_in3_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in1_max.attr,
+       &dev_attr_in2_max.attr,
+       &dev_attr_in3_max.attr,
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp2_min.attr,
+       &dev_attr_temp3_min.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_vrm.attr,
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_pwm1_auto_channels.attr,
+       &dev_attr_pwm2_auto_channels.attr,
+       &dev_attr_pwm3_auto_channels.attr,
+       &dev_attr_pwm1_auto_pwm_min.attr,
+       &dev_attr_pwm2_auto_pwm_min.attr,
+       &dev_attr_pwm3_auto_pwm_min.attr,
+       &dev_attr_pwm1_auto_pwm_minctl.attr,
+       &dev_attr_pwm2_auto_pwm_minctl.attr,
+       &dev_attr_pwm3_auto_pwm_minctl.attr,
+       &dev_attr_pwm1_auto_pwm_freq.attr,
+       &dev_attr_pwm2_auto_pwm_freq.attr,
+       &dev_attr_pwm3_auto_pwm_freq.attr,
+       &dev_attr_temp1_auto_temp_off.attr,
+       &dev_attr_temp2_auto_temp_off.attr,
+       &dev_attr_temp3_auto_temp_off.attr,
+       &dev_attr_temp1_auto_temp_min.attr,
+       &dev_attr_temp2_auto_temp_min.attr,
+       &dev_attr_temp3_auto_temp_min.attr,
+       &dev_attr_temp1_auto_temp_max.attr,
+       &dev_attr_temp2_auto_temp_max.attr,
+       &dev_attr_temp3_auto_temp_max.attr,
+       &dev_attr_temp1_auto_temp_crit.attr,
+       &dev_attr_temp2_auto_temp_crit.attr,
+       &dev_attr_temp3_auto_temp_crit.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm85_group = {
+       .attrs = lm85_attributes,
+};
+
+static struct attribute *lm85_attributes_opt[] = {
+       &dev_attr_in4_input.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in4_max.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm85_group_opt = {
+       .attrs = lm85_attributes_opt,
+};
+
 static int lm85_detect(struct i2c_adapter *adapter, int address,
                int kind)
 {
@@ -1163,87 +1246,33 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
        lm85_init_client(new_client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm85_group)))
                goto ERROR2;
-       }
-
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan3_input);
-       device_create_file(&new_client->dev, &dev_attr_fan4_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan3_min);
-       device_create_file(&new_client->dev, &dev_attr_fan4_min);
-       device_create_file(&new_client->dev, &dev_attr_pwm1);
-       device_create_file(&new_client->dev, &dev_attr_pwm2);
-       device_create_file(&new_client->dev, &dev_attr_pwm3);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-       device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
-       device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp3_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp3_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp3_max);
-       device_create_file(&new_client->dev, &dev_attr_vrm);
-       device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_auto_channels);
-       device_create_file(&new_client->dev, &dev_attr_pwm2_auto_channels);
-       device_create_file(&new_client->dev, &dev_attr_pwm3_auto_channels);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_min);
-       device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_min);
-       device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_min);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_minctl);
-       device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_minctl);
-       device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_minctl);
-       device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_freq);
-       device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_freq);
-       device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_freq);
-       device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_off);
-       device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_off);
-       device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_off);
-       device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_min);
-       device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_max);
-       device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit);
 
        /* The ADT7463 has an optional VRM 10 mode where pin 21 is used
           as a sixth digital VID input rather than an analog input. */
        data->vid = lm85_read_value(new_client, LM85_REG_VID);
-       if (!(kind == adt7463 && (data->vid & 0x80))) {
-               device_create_file(&new_client->dev, &dev_attr_in4_input);
-               device_create_file(&new_client->dev, &dev_attr_in4_min);
-               device_create_file(&new_client->dev, &dev_attr_in4_max);
+       if (!(kind == adt7463 && (data->vid & 0x80)))
+               if ((err = device_create_file(&new_client->dev,
+                                       &dev_attr_in4_input))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in4_min))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in4_max)))
+                       goto ERROR3;
+
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
        }
 
        return 0;
 
        /* Error out and cleanup code */
+    ERROR3:
+       sysfs_remove_group(&new_client->dev.kobj, &lm85_group);
+       sysfs_remove_group(&new_client->dev.kobj, &lm85_group_opt);
     ERROR2:
        i2c_detach_client(new_client);
     ERROR1:
@@ -1256,6 +1285,8 @@ static int lm85_detach_client(struct i2c_client *client)
 {
        struct lm85_data *data = i2c_get_clientdata(client);
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm85_group);
+       sysfs_remove_group(&client->dev.kobj, &lm85_group_opt);
        i2c_detach_client(client);
        kfree(data);
        return 0;
index e6c1b638c971dc68ef8fe4d21904e66b67fa3783..3ce825489e349c0c106646356397aa87eae69531 100644 (file)
@@ -542,6 +542,78 @@ static int lm87_attach_adapter(struct i2c_adapter *adapter)
        return i2c_probe(adapter, &addr_data, lm87_detect);
 }
 
+static struct attribute *lm87_attributes[] = {
+       &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_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp1_crit.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_min.attr,
+       &dev_attr_temp2_crit.attr,
+
+       &dev_attr_alarms.attr,
+       &dev_attr_aout_output.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm87_group = {
+       .attrs = lm87_attributes,
+};
+
+static struct attribute *lm87_attributes_opt[] = {
+       &dev_attr_in6_input.attr,
+       &dev_attr_in6_min.attr,
+       &dev_attr_in6_max.attr,
+
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan1_div.attr,
+
+       &dev_attr_in7_input.attr,
+       &dev_attr_in7_min.attr,
+       &dev_attr_in7_max.attr,
+
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan2_div.attr,
+
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_temp3_min.attr,
+       &dev_attr_temp3_crit.attr,
+
+       &dev_attr_in0_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in5_input.attr,
+       &dev_attr_in5_min.attr,
+       &dev_attr_in5_max.attr,
+
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm87_group_opt = {
+       .attrs = lm87_attributes_opt,
+};
+
 /*
  * The following function does more than just detection. If detection
  * succeeds, it also registers the new chip.
@@ -609,77 +681,90 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
        data->in_scale[7] = 1875;
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group)))
                goto exit_detach;
-       }
-
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in4_input);
-       device_create_file(&new_client->dev, &dev_attr_in4_min);
-       device_create_file(&new_client->dev, &dev_attr_in4_max);
 
        if (data->channel & CHAN_NO_FAN(0)) {
-               device_create_file(&new_client->dev, &dev_attr_in6_input);
-               device_create_file(&new_client->dev, &dev_attr_in6_min);
-               device_create_file(&new_client->dev, &dev_attr_in6_max);
+               if ((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)))
+                       goto exit_remove;
        } else {
-               device_create_file(&new_client->dev, &dev_attr_fan1_input);
-               device_create_file(&new_client->dev, &dev_attr_fan1_min);
-               device_create_file(&new_client->dev, &dev_attr_fan1_div);
+               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)))
+                       goto exit_remove;
        }
+
        if (data->channel & CHAN_NO_FAN(1)) {
-               device_create_file(&new_client->dev, &dev_attr_in7_input);
-               device_create_file(&new_client->dev, &dev_attr_in7_min);
-               device_create_file(&new_client->dev, &dev_attr_in7_max);
+               if ((err = device_create_file(&new_client->dev,
+                                       &dev_attr_in7_input))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in7_min))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in7_max)))
+                       goto exit_remove;
        } else {
-               device_create_file(&new_client->dev, &dev_attr_fan2_input);
-               device_create_file(&new_client->dev, &dev_attr_fan2_min);
-               device_create_file(&new_client->dev, &dev_attr_fan2_div);
+               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)))
+                       goto exit_remove;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-
        if (data->channel & CHAN_TEMP3) {
-               device_create_file(&new_client->dev, &dev_attr_temp3_input);
-               device_create_file(&new_client->dev, &dev_attr_temp3_max);
-               device_create_file(&new_client->dev, &dev_attr_temp3_min);
-               device_create_file(&new_client->dev, &dev_attr_temp3_crit);
+               if ((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_min))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_temp3_crit)))
+                       goto exit_remove;
        } else {
-               device_create_file(&new_client->dev, &dev_attr_in0_input);
-               device_create_file(&new_client->dev, &dev_attr_in0_min);
-               device_create_file(&new_client->dev, &dev_attr_in0_max);
-               device_create_file(&new_client->dev, &dev_attr_in5_input);
-               device_create_file(&new_client->dev, &dev_attr_in5_min);
-               device_create_file(&new_client->dev, &dev_attr_in5_max);
+               if ((err = device_create_file(&new_client->dev,
+                                       &dev_attr_in0_input))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in0_min))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_in0_max))
+                || (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)))
+                       goto exit_remove;
        }
 
        if (!(data->channel & CHAN_NO_VID)) {
-               device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
-               device_create_file(&new_client->dev, &dev_attr_vrm);
+               if ((err = device_create_file(&new_client->dev,
+                                       &dev_attr_cpu0_vid))
+                || (err = device_create_file(&new_client->dev,
+                                       &dev_attr_vrm)))
+                       goto exit_remove;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       device_create_file(&new_client->dev, &dev_attr_aout_output);
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove;
+       }
 
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &lm87_group);
+       sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -732,6 +817,8 @@ static int lm87_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm87_group);
+       sysfs_remove_group(&client->dev.kobj, &lm87_group_opt);
 
        if ((err = i2c_detach_client(client)))
                return err;
index d9eeaf7585bd3be3d171ba2d8f33a3b9393564e3..6882ce75feee99b5c2ab9f4f94b5f3a78820728a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2006  Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm83 driver. The LM90 is a sensor chip made by National
  * Semiconductor. It reports up to two temperatures (its own plus up to
@@ -79,6 +79,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /*
  * Addresses to scan
@@ -327,6 +328,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
        return sprintf(buf, "%d\n", data->alarms);
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute
+                         *devattr, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct lm90_data *data = lm90_update_device(dev);
+       int bitnr = attr->index;
+
+       return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
+}
+
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
@@ -344,8 +355,45 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
        set_temphyst, 3);
 static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
+
+/* Individual alarm files */
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
+/* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *lm90_attributes[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+
+       &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+       &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group lm90_group = {
+       .attrs = lm90_attributes,
+};
+
 /* pec used for ADM1032 only */
 static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
                        char *buf)
@@ -569,39 +617,25 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
        lm90_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group)))
+               goto exit_detach;
+       if (new_client->flags & I2C_CLIENT_PEC) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_pec)))
+                       goto exit_remove_files;
+       }
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_input.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_min.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_min.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_max.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_crit.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_crit.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_crit_hyst.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp2_crit_hyst.dev_attr);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
-       if (new_client->flags & I2C_CLIENT_PEC)
-               device_create_file(&new_client->dev, &dev_attr_pec);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &lm90_group);
+       device_remove_file(&new_client->dev, &dev_attr_pec);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -634,6 +668,8 @@ static int lm90_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm90_group);
+       device_remove_file(&client->dev, &dev_attr_pec);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 197f77226dc478a4d440700659d46d06da90e74d..30b536333f1469f537bd27799f5c5ada55d88323 100644 (file)
@@ -288,6 +288,23 @@ static int max6635_check(struct i2c_client *client)
        return 1;
 }
 
+static struct attribute *lm92_attributes[] = {
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_crit.attr,
+       &dev_attr_temp1_crit_hyst.attr,
+       &dev_attr_temp1_min.attr,
+       &dev_attr_temp1_min_hyst.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_alarms.attr,
+
+       NULL
+};
+
+static const struct attribute_group lm92_group = {
+       .attrs = lm92_attributes,
+};
+
 /* The following function does more than just detection. If detection
    succeeds, it also registers the new chip. */
 static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -359,23 +376,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
        lm92_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min);
-       device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
        return 0;
 
+exit_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &lm92_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -397,6 +410,7 @@ static int lm92_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &lm92_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index b4135b5971f4d67d25404532c75c9472132f4ff2..2f58f651f03a5c7af92d8322c3ff041a83cc12b1 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
                                        0x29, 0x2a, 0x2b,
@@ -172,6 +173,22 @@ static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst2,
        set_temp_hyst2);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *max1619_attributes[] = {
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_min.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_crit.attr,
+       &dev_attr_temp2_crit_hyst.attr,
+
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group max1619_group = {
+       .attrs = max1619_attributes,
+};
+
 /*
  * Real code
  */
@@ -273,22 +290,19 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
        max1619_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_min);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-       device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &max1619_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -318,6 +332,7 @@ static int max1619_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &max1619_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index ae05e483a77877673ea47825960d955e4c2162c7..3b8b81984ad4cf04ab3c0fdb91079654cbda519e 100644 (file)
@@ -238,6 +238,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
 
 static struct i2c_driver pc87360_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "pc87360",
        },
        .attach_adapter = pc87360_detect,
@@ -327,6 +328,12 @@ static struct sensor_device_attribute fan_min[] = {
        SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
 };
 
+#define FAN_UNIT_ATTRS(X)      \
+       &fan_input[X].dev_attr.attr,    \
+       &fan_status[X].dev_attr.attr,   \
+       &fan_div[X].dev_attr.attr,      \
+       &fan_min[X].dev_attr.attr
+
 static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -359,6 +366,19 @@ static struct sensor_device_attribute pwm[] = {
        SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
 };
 
+static struct attribute * pc8736x_fan_attr_array[] = {
+       FAN_UNIT_ATTRS(0),
+       FAN_UNIT_ATTRS(1),
+       FAN_UNIT_ATTRS(2),
+       &pwm[0].dev_attr.attr,
+       &pwm[1].dev_attr.attr,
+       &pwm[2].dev_attr.attr,
+       NULL
+};
+static const struct attribute_group pc8736x_fan_group = {
+       .attrs = pc8736x_fan_attr_array,
+};
+
 static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -471,6 +491,61 @@ static struct sensor_device_attribute in_max[] = {
        SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
 };
 
+#define VIN_UNIT_ATTRS(X) \
+       &in_input[X].dev_attr.attr,     \
+       &in_status[X].dev_attr.attr,    \
+       &in_min[X].dev_attr.attr,       \
+       &in_max[X].dev_attr.attr
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       return sprintf(buf, "%u\n", data->vrm);
+}
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct pc87360_data *data = i2c_get_clientdata(client);
+       data->vrm = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+
+static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       return sprintf(buf, "%u\n", data->in_alarms);
+}
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+
+static struct attribute *pc8736x_vin_attr_array[] = {
+       VIN_UNIT_ATTRS(0),
+       VIN_UNIT_ATTRS(1),
+       VIN_UNIT_ATTRS(2),
+       VIN_UNIT_ATTRS(3),
+       VIN_UNIT_ATTRS(4),
+       VIN_UNIT_ATTRS(5),
+       VIN_UNIT_ATTRS(6),
+       VIN_UNIT_ATTRS(7),
+       VIN_UNIT_ATTRS(8),
+       VIN_UNIT_ATTRS(9),
+       VIN_UNIT_ATTRS(10),
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       &dev_attr_alarms_in.attr,
+       NULL
+};
+static const struct attribute_group pc8736x_vin_group = {
+       .attrs = pc8736x_vin_attr_array,
+};
+
 static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -589,33 +664,22 @@ static struct sensor_device_attribute therm_crit[] = {
                    show_therm_crit, set_therm_crit, 2+11),
 };
 
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct pc87360_data *data = pc87360_update_device(dev);
-       return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
-}
-static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct pc87360_data *data = pc87360_update_device(dev);
-       return sprintf(buf, "%u\n", data->vrm);
-}
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct pc87360_data *data = i2c_get_clientdata(client);
-       data->vrm = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-
-static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct pc87360_data *data = pc87360_update_device(dev);
-       return sprintf(buf, "%u\n", data->in_alarms);
-}
-static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+#define THERM_UNIT_ATTRS(X) \
+       &therm_input[X].dev_attr.attr,  \
+       &therm_status[X].dev_attr.attr, \
+       &therm_min[X].dev_attr.attr,    \
+       &therm_max[X].dev_attr.attr,    \
+       &therm_crit[X].dev_attr.attr
+
+static struct attribute * pc8736x_therm_attr_array[] = {
+       THERM_UNIT_ATTRS(0),
+       THERM_UNIT_ATTRS(1),
+       THERM_UNIT_ATTRS(2),
+       NULL
+};
+static const struct attribute_group pc8736x_therm_group = {
+       .attrs = pc8736x_therm_attr_array,
+};
 
 static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
@@ -735,6 +799,25 @@ static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *att
 }
 static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
 
+#define TEMP_UNIT_ATTRS(X) \
+       &temp_input[X].dev_attr.attr,   \
+       &temp_status[X].dev_attr.attr,  \
+       &temp_min[X].dev_attr.attr,     \
+       &temp_max[X].dev_attr.attr,     \
+       &temp_crit[X].dev_attr.attr
+
+static struct attribute * pc8736x_temp_attr_array[] = {
+       TEMP_UNIT_ATTRS(0),
+       TEMP_UNIT_ATTRS(1),
+       TEMP_UNIT_ATTRS(2),
+       /* include the few miscellaneous atts here */
+       &dev_attr_alarms_temp.attr,
+       NULL
+};
+static const struct attribute_group pc8736x_temp_group = {
+       .attrs = pc8736x_temp_attr_array,
+};
+
 /*
  * Device detection, registration and update
  */
@@ -935,60 +1018,69 @@ static int pc87360_detect(struct i2c_adapter *adapter)
                pc87360_init_client(client, use_thermistors);
        }
 
-       /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       /* Register all-or-nothing sysfs groups */
+
+       if (data->innr &&
+           (err = sysfs_create_group(&client->dev.kobj,
+                                     &pc8736x_vin_group)))
                goto ERROR3;
-       }
 
-       if (data->innr) {
-               for (i = 0; i < 11; i++) {
-                       device_create_file(dev, &in_input[i].dev_attr);
-                       device_create_file(dev, &in_min[i].dev_attr);
-                       device_create_file(dev, &in_max[i].dev_attr);
-                       device_create_file(dev, &in_status[i].dev_attr);
-               }
-               device_create_file(dev, &dev_attr_cpu0_vid);
-               device_create_file(dev, &dev_attr_vrm);
-               device_create_file(dev, &dev_attr_alarms_in);
-       }
+       if (data->innr == 14 &&
+           (err = sysfs_create_group(&client->dev.kobj,
+                                     &pc8736x_therm_group)))
+               goto ERROR3;
+
+       /* create device attr-files for varying sysfs groups */
 
        if (data->tempnr) {
                for (i = 0; i < data->tempnr; i++) {
-                       device_create_file(dev, &temp_input[i].dev_attr);
-                       device_create_file(dev, &temp_min[i].dev_attr);
-                       device_create_file(dev, &temp_max[i].dev_attr);
-                       device_create_file(dev, &temp_crit[i].dev_attr);
-                       device_create_file(dev, &temp_status[i].dev_attr);
-               }
-               device_create_file(dev, &dev_attr_alarms_temp);
-       }
-
-       if (data->innr == 14) {
-               for (i = 0; i < 3; i++) {
-                       device_create_file(dev, &therm_input[i].dev_attr);
-                       device_create_file(dev, &therm_min[i].dev_attr);
-                       device_create_file(dev, &therm_max[i].dev_attr);
-                       device_create_file(dev, &therm_crit[i].dev_attr);
-                       device_create_file(dev, &therm_status[i].dev_attr);
+                       if ((err = device_create_file(dev,
+                                       &temp_input[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_min[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_max[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_crit[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_status[i].dev_attr)))
+                               goto ERROR3;
                }
+               if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
+                       goto ERROR3;
        }
 
        for (i = 0; i < data->fannr; i++) {
-               if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
-                       device_create_file(dev, &fan_input[i].dev_attr);
-                       device_create_file(dev, &fan_min[i].dev_attr);
-                       device_create_file(dev, &fan_div[i].dev_attr);
-                       device_create_file(dev, &fan_status[i].dev_attr);
-               }
-               if (FAN_CONFIG_CONTROL(data->fan_conf, i))
-                       device_create_file(dev, &pwm[i].dev_attr);
+               if (FAN_CONFIG_MONITOR(data->fan_conf, i)
+                   && ((err = device_create_file(dev,
+                                       &fan_input[i].dev_attr))
+                       || (err = device_create_file(dev,
+                                       &fan_min[i].dev_attr))
+                       || (err = device_create_file(dev,
+                                       &fan_div[i].dev_attr))
+                       || (err = device_create_file(dev,
+                                       &fan_status[i].dev_attr))))
+                       goto ERROR3;
+
+               if (FAN_CONFIG_CONTROL(data->fan_conf, i)
+                   && (err = device_create_file(dev, &pwm[i].dev_attr)))
+                       goto ERROR3;
        }
 
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
        return 0;
 
 ERROR3:
+       /* can still remove groups whose members were added individually */
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
+
        i2c_detach_client(client);
 ERROR2:
        for (i = 0; i < 3; i++) {
@@ -1008,6 +1100,11 @@ static int pc87360_detach_client(struct i2c_client *client)
 
        hwmon_device_unregister(data->class_dev);
 
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
+       sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
+
        if ((i = i2c_detach_client(client)))
                return i;
 
index 063f71c5f07eabf14f33dc671e2b1da6df73eedf..95a4b5d9eaf29820cdba79472de2f97ea482f269 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
@@ -200,6 +201,7 @@ static void sis5595_init_client(struct i2c_client *client);
 
 static struct i2c_driver sis5595_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "sis5595",
        },
        .attach_adapter = sis5595_detect,
@@ -472,6 +474,50 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
        return sprintf(buf, "%d\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static struct attribute *sis5595_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_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_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group sis5595_group = {
+       .attrs = sis5595_attributes,
+};
+
+static struct attribute *sis5595_attributes_opt[] = {
+       &dev_attr_in4_input.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in4_max.attr,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       NULL
+};
+
+static const struct attribute_group sis5595_group_opt = {
+       .attrs = sis5595_attributes_opt,
+};
  
 /* This is called when the module is loaded */
 static int sis5595_detect(struct i2c_adapter *adapter)
@@ -565,43 +611,37 @@ static int sis5595_detect(struct i2c_adapter *adapter)
        }
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &sis5595_group)))
+               goto exit_detach;
+       if (data->maxins == 4) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_in4_input))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_in4_min))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_in4_max)))
+                       goto exit_remove_files;
+       } else {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_temp1_input))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_temp1_max))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_temp1_max_hyst)))
+                       goto exit_remove_files;
+       }
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       if (data->maxins == 4) {
-               device_create_file(&new_client->dev, &dev_attr_in4_input);
-               device_create_file(&new_client->dev, &dev_attr_in4_min);
-               device_create_file(&new_client->dev, &dev_attr_in4_max);
-       }
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-       if (data->maxins == 3) {
-               device_create_file(&new_client->dev, &dev_attr_temp1_input);
-               device_create_file(&new_client->dev, &dev_attr_temp1_max);
-               device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       }
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &sis5595_group);
+       sysfs_remove_group(&new_client->dev.kobj, &sis5595_group_opt);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -618,6 +658,8 @@ static int sis5595_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &sis5595_group);
+       sysfs_remove_group(&client->dev.kobj, &sis5595_group_opt);
 
        if ((err = i2c_detach_client(client)))
                return err;
index b6086186d2259dea1f7235beb246f6b9c5f2672d..72b0e2d8650ca1df9b5297190e28837ba5296858 100644 (file)
@@ -176,9 +176,6 @@ sysfs_temp(2);
 sysfs_temp(3);
 sysfs_temp(4);
 
-#define device_create_file_temp(client, num) \
-       device_create_file(&client->dev, &dev_attr_temp##num##_input)
-
 /* FAN: 1 RPM/bit
    REG: count of 90kHz pulses / revolution */
 static int fan_from_reg(u16 reg)
@@ -205,8 +202,22 @@ sysfs_fan(2);
 sysfs_fan(3);
 sysfs_fan(4);
 
-#define device_create_file_fan(client, num) \
-       device_create_file(&client->dev, &dev_attr_fan##num##_input)
+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,
+
+       NULL
+};
+
+static const struct attribute_group smsc47b397_group = {
+       .attrs = smsc47b397_attributes,
+};
 
 static int smsc47b397_detach_client(struct i2c_client *client)
 {
@@ -214,6 +225,7 @@ static int smsc47b397_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &smsc47b397_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
@@ -228,6 +240,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter);
 
 static struct i2c_driver smsc47b397_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "smsc47b397",
        },
        .attach_adapter = smsc47b397_detect,
@@ -267,24 +280,19 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
        if ((err = i2c_attach_client(new_client)))
                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);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto error_detach;
+               goto error_remove;
        }
 
-       device_create_file_temp(new_client, 1);
-       device_create_file_temp(new_client, 2);
-       device_create_file_temp(new_client, 3);
-       device_create_file_temp(new_client, 4);
-
-       device_create_file_fan(new_client, 1);
-       device_create_file_fan(new_client, 2);
-       device_create_file_fan(new_client, 3);
-       device_create_file_fan(new_client, 4);
-
        return 0;
 
+error_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &smsc47b397_group);
 error_detach:
        i2c_detach_client(new_client);
 error_free:
index 825e8f72698fdf8d24bf021e88d7551f167749bb..47132fd26b1bf9a4f1948864fe95a34ecb5afdf2 100644 (file)
@@ -35,6 +35,7 @@
 #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 */
@@ -128,6 +129,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 
 static struct i2c_driver smsc47m1_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "smsc47m1",
        },
        .attach_adapter = smsc47m1_detect,
@@ -346,6 +348,30 @@ fan_present(2);
 
 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, 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,
+
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group smsc47m1_group = {
+       .attrs = smsc47m1_attributes,
+};
+
 static int __init smsc47m1_find(unsigned short *addr)
 {
        u8 val;
@@ -428,7 +454,8 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
        pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
               == 0x04;
        if (!(fan1 || fan2 || pwm1 || pwm2)) {
-               dev_warn(&new_client->dev, "Device is not configured, will not use\n");
+               dev_warn(&adapter->dev, "Device at 0x%x is not configured, "
+                        "will not use\n", new_client->addr);
                err = -ENODEV;
                goto error_free;
        }
@@ -445,46 +472,62 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
        smsc47m1_update_device(&new_client->dev, 1);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
-               goto error_detach;
-       }
-
        if (fan1) {
-               device_create_file(&new_client->dev, &dev_attr_fan1_input);
-               device_create_file(&new_client->dev, &dev_attr_fan1_min);
-               device_create_file(&new_client->dev, &dev_attr_fan1_div);
+               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)))
+                       goto error_remove_files;
        } else
                dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
                        "skipping\n");
 
        if (fan2) {
-               device_create_file(&new_client->dev, &dev_attr_fan2_input);
-               device_create_file(&new_client->dev, &dev_attr_fan2_min);
-               device_create_file(&new_client->dev, &dev_attr_fan2_div);
+               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)))
+                       goto error_remove_files;
        } else
                dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
                        "skipping\n");
 
        if (pwm1) {
-               device_create_file(&new_client->dev, &dev_attr_pwm1);
-               device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_pwm1))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_pwm1_enable)))
+                       goto error_remove_files;
        } else
                dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
                        "skipping\n");
        if (pwm2) {
-               device_create_file(&new_client->dev, &dev_attr_pwm2);
-               device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_pwm2))
+                || (err = device_create_file(&new_client->dev,
+                                             &dev_attr_pwm2_enable)))
+                       goto error_remove_files;
        } else
                dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
                        "skipping\n");
 
-       device_create_file(&new_client->dev, &dev_attr_alarms);
+       if ((err = device_create_file(&new_client->dev, &dev_attr_alarms)))
+               goto error_remove_files;
+
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto error_remove_files;
+       }
 
        return 0;
 
-error_detach:
+error_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &smsc47m1_group);
        i2c_detach_client(new_client);
 error_free:
        kfree(data);
@@ -499,6 +542,7 @@ static int smsc47m1_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &smsc47m1_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
index bdc4570acf9a868893c2de71709c51dd0d639a7e..a6833f4373950c8f46295cdb3b579945c7feb668 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
+#include <linux/sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
@@ -370,6 +371,75 @@ static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200);
 static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400);
 static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800);
 
+static struct attribute *smsc47m192_attributes[] = {
+       &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_in0_alarm.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_in1_alarm.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_in2_alarm.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_in3_alarm.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_in5_alarm.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,
+       &sensor_dev_attr_in6_alarm.dev_attr.attr,
+       &sensor_dev_attr_in7_input.dev_attr.attr,
+       &sensor_dev_attr_in7_min.dev_attr.attr,
+       &sensor_dev_attr_in7_max.dev_attr.attr,
+       &sensor_dev_attr_in7_alarm.dev_attr.attr,
+
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_offset.dev_attr.attr,
+       &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_offset.dev_attr.attr,
+       &sensor_dev_attr_temp2_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_min.dev_attr.attr,
+       &sensor_dev_attr_temp3_offset.dev_attr.attr,
+       &sensor_dev_attr_temp3_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_input_fault.dev_attr.attr,
+
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       NULL
+};
+
+static const struct attribute_group smsc47m192_group = {
+       .attrs = smsc47m192_attributes,
+};
+
+static struct attribute *smsc47m192_attributes_in4[] = {
+       &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_in4_alarm.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group smsc47m192_group_in4 = {
+       .attrs = smsc47m192_attributes_in4,
+};
+
 /* This function is called when:
     * smsc47m192_driver is inserted (when this module is loaded), for each
       available adapter
@@ -471,80 +541,28 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
        smsc47m192_init_client(client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group)))
                goto exit_detach;
-       }
-
-       device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr);
 
        /* Pin 110 is either in4 (+12V) or VID4 */
        config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
        if (!(config & 0x20)) {
-               device_create_file(&client->dev,
-                                  &sensor_dev_attr_in4_input.dev_attr);
-               device_create_file(&client->dev,
-                                  &sensor_dev_attr_in4_min.dev_attr);
-               device_create_file(&client->dev,
-                                  &sensor_dev_attr_in4_max.dev_attr);
-               device_create_file(&client->dev,
-                                  &sensor_dev_attr_in4_alarm.dev_attr);
+               if ((err = sysfs_create_group(&client->dev.kobj,
+                                             &smsc47m192_group_in4)))
+                       goto exit_remove_files;
+       }
+
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove_files;
        }
-       device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr);
-       device_create_file(&client->dev,
-                          &sensor_dev_attr_temp1_offset.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr);
-       device_create_file(&client->dev,
-                          &sensor_dev_attr_temp2_offset.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr);
-       device_create_file(&client->dev,
-                          &sensor_dev_attr_temp2_input_fault.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr);
-       device_create_file(&client->dev,
-                          &sensor_dev_attr_temp3_offset.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr);
-       device_create_file(&client->dev,
-                          &sensor_dev_attr_temp3_input_fault.dev_attr);
-       device_create_file(&client->dev, &dev_attr_cpu0_vid);
-       device_create_file(&client->dev, &dev_attr_vrm);
 
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
+       sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
 exit_detach:
        i2c_detach_client(client);
 exit_free:
@@ -559,6 +577,8 @@ static int smsc47m192_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
+       sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
 
        if ((err = i2c_detach_client(client)))
                return err;
index 166298f1f19023dc349feda1a62f78d104132420..f8acada0537a7894d6dd318558e3bc71ca1dd546 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
@@ -570,10 +571,53 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *via686a_attributes[] = {
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       &dev_attr_in4_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in2_min.attr,
+       &dev_attr_in3_min.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in1_max.attr,
+       &dev_attr_in2_max.attr,
+       &dev_attr_in3_max.attr,
+       &dev_attr_in4_max.attr,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_temp2_max_hyst.attr,
+       &dev_attr_temp3_max_hyst.attr,
+
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan2_div.attr,
+
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group via686a_group = {
+       .attrs = via686a_attributes,
+};
+
 /* The driver. I choose to use type i2c_driver, as at is identical to both
    smbus_driver and isa_driver, and clients could be of either kind */
 static struct i2c_driver via686a_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "via686a",
        },
        .attach_adapter = via686a_detect,
@@ -649,46 +693,19 @@ static int via686a_detect(struct i2c_adapter *adapter)
        via686a_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in4_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in4_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in4_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp3_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp3_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &via686a_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -704,6 +721,7 @@ static int via686a_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &via686a_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
new file mode 100644 (file)
index 0000000..25cc560
--- /dev/null
@@ -0,0 +1,1355 @@
+/*
+ * vt1211.c - driver for the VIA VT1211 Super-I/O chip integrated hardware
+ *            monitoring features
+ * Copyright (C) 2006 Juerg Haefliger <juergh@gmail.com>
+ *
+ * This driver is based on the driver for kernel 2.4 by Mark D. Studebaker
+ * and its port to kernel 2.6 by Lars Ekman.
+ *
+ * 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/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <asm/io.h>
+
+static int uch_config = -1;
+module_param(uch_config, int, 0);
+MODULE_PARM_DESC(uch_config, "Initialize the universal channel configuration");
+
+static int int_mode = -1;
+module_param(int_mode, int, 0);
+MODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode");
+
+static struct platform_device *pdev;
+
+#define DRVNAME "vt1211"
+
+/* ---------------------------------------------------------------------
+ * Registers
+ *
+ * The sensors are defined as follows.
+ *
+ * Sensor          Voltage Mode   Temp Mode   Notes (from the datasheet)
+ * --------        ------------   ---------   --------------------------
+ * Reading 1                      temp1       Intel thermal diode
+ * Reading 3                      temp2       Internal thermal diode
+ * UCH1/Reading2   in0            temp3       NTC type thermistor
+ * UCH2            in1            temp4       +2.5V
+ * UCH3            in2            temp5       VccP
+ * UCH4            in3            temp6       +5V
+ * UCH5            in4            temp7       +12V
+ * 3.3V            in5                        Internal VDD (+3.3V)
+ *
+ * --------------------------------------------------------------------- */
+
+/* Voltages (in) numbered 0-5 (ix) */
+#define VT1211_REG_IN(ix)              (0x21 + (ix))
+#define VT1211_REG_IN_MIN(ix)          ((ix) == 0 ? 0x3e : 0x2a + 2 * (ix))
+#define VT1211_REG_IN_MAX(ix)          ((ix) == 0 ? 0x3d : 0x29 + 2 * (ix))
+
+/* Temperatures (temp) numbered 0-6 (ix) */
+static u8 regtemp[]    = {0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25};
+static u8 regtempmax[] = {0x39, 0x1d, 0x3d, 0x2b, 0x2d, 0x2f, 0x31};
+static u8 regtemphyst[]        = {0x3a, 0x1e, 0x3e, 0x2c, 0x2e, 0x30, 0x32};
+
+/* Fans numbered 0-1 (ix) */
+#define VT1211_REG_FAN(ix)             (0x29 + (ix))
+#define VT1211_REG_FAN_MIN(ix)         (0x3b + (ix))
+#define VT1211_REG_FAN_DIV              0x47
+
+/* PWMs numbered 0-1 (ix) */
+/* Auto points numbered 0-3 (ap) */
+#define VT1211_REG_PWM(ix)             (0x60 + (ix))
+#define VT1211_REG_PWM_CLK              0x50
+#define VT1211_REG_PWM_CTL              0x51
+#define VT1211_REG_PWM_AUTO_TEMP(ap)   (0x55 - (ap))
+#define VT1211_REG_PWM_AUTO_PWM(ix, ap)        (0x58 + 2 * (ix) - (ap))
+
+/* Miscellaneous registers */
+#define VT1211_REG_CONFIG              0x40
+#define VT1211_REG_ALARM1              0x41
+#define VT1211_REG_ALARM2              0x42
+#define VT1211_REG_VID                 0x45
+#define VT1211_REG_UCH_CONFIG          0x4a
+#define VT1211_REG_TEMP1_CONFIG                0x4b
+#define VT1211_REG_TEMP2_CONFIG                0x4c
+
+/* In, temp & fan alarm bits */
+static const u8 bitalarmin[]   = {11, 0, 1, 3, 8, 2, 9};
+static const u8 bitalarmtemp[] = {4, 15, 11, 0, 1, 3, 8};
+static const u8 bitalarmfan[]  = {6, 7};
+
+/* ---------------------------------------------------------------------
+ * Data structures and manipulation thereof
+ * --------------------------------------------------------------------- */
+
+struct vt1211_data {
+       unsigned short addr;
+       const char *name;
+       struct class_device *class_dev;
+
+       struct mutex update_lock;
+       char valid;                     /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+
+       /* Register values */
+       u8  in[6];
+       u8  in_max[6];
+       u8  in_min[6];
+       u8  temp[7];
+       u8  temp_max[7];
+       u8  temp_hyst[7];
+       u8  fan[2];
+       u8  fan_min[2];
+       u8  fan_div[2];
+       u8  fan_ctl;
+       u8  pwm[2];
+       u8  pwm_ctl[2];
+       u8  pwm_clk;
+       u8  pwm_auto_temp[4];
+       u8  pwm_auto_pwm[2][4];
+       u8  vid;                /* Read once at init time */
+       u8  vrm;
+       u8  uch_config;         /* Read once at init time */
+       u16 alarms;
+};
+
+/* ix = [0-5] */
+#define ISVOLT(ix, uch_config) ((ix) > 4 ? 1 : \
+                                !(((uch_config) >> ((ix) + 2)) & 1))
+
+/* ix = [0-6] */
+#define ISTEMP(ix, uch_config) ((ix) < 2 ? 1 : \
+                                ((uch_config) >> (ix)) & 1)
+
+/* in5 (ix = 5) is special. It's the internal 3.3V so it's scaled in the
+   driver according to the VT1211 BIOS porting guide */
+#define IN_FROM_REG(ix, reg)   ((reg) < 3 ? 0 : (ix) == 5 ? \
+                                (((reg) - 3) * 15882 + 479) / 958 : \
+                                (((reg) - 3) * 10000 + 479) / 958)
+#define IN_TO_REG(ix, val)     (SENSORS_LIMIT((ix) == 5 ? \
+                                ((val) * 958 + 7941) / 15882 + 3 : \
+                                ((val) * 958 + 5000) / 10000 + 3, 0, 255))
+
+/* temp1 (ix = 0) is an intel thermal diode which is scaled in user space.
+   temp2 (ix = 1) is the internal temp diode so it's scaled in the driver
+   according to some measurements that I took on an EPIA M10000.
+   temp3-7 are thermistor based so the driver returns the voltage measured at
+   the pin (range 0V - 2.2V). */
+#define TEMP_FROM_REG(ix, reg) ((ix) == 0 ? (reg) * 1000 : \
+                                (ix) == 1 ? (reg) < 51 ? 0 : \
+                                ((reg) - 51) * 1000 : \
+                                ((253 - (reg)) * 2200 + 105) / 210)
+#define TEMP_TO_REG(ix, val)   SENSORS_LIMIT( \
+                                ((ix) == 0 ? ((val) + 500) / 1000 : \
+                                 (ix) == 1 ? ((val) + 500) / 1000 + 51 : \
+                                 253 - ((val) * 210 + 1100) / 2200), 0, 255)
+
+#define DIV_FROM_REG(reg)      (1 << (reg))
+
+#define RPM_FROM_REG(reg, div) (((reg) == 0) || ((reg) == 255) ? 0 : \
+                                1310720 / (reg) / DIV_FROM_REG(div))
+#define RPM_TO_REG(val, div)   ((val) == 0 ? 255 : \
+                                SENSORS_LIMIT((1310720 / (val) / \
+                                DIV_FROM_REG(div)), 1, 254))
+
+/* ---------------------------------------------------------------------
+ * Super-I/O constants and functions
+ * --------------------------------------------------------------------- */
+
+/* Configuration & data index port registers */
+#define SIO_REG_CIP            0x2e
+#define SIO_REG_DIP            0x2f
+
+/* Configuration registers */
+#define SIO_VT1211_LDN         0x07    /* logical device number */
+#define SIO_VT1211_DEVID       0x20    /* device ID */
+#define SIO_VT1211_DEVREV      0x21    /* device revision */
+#define SIO_VT1211_ACTIVE      0x30    /* HW monitor active */
+#define SIO_VT1211_BADDR       0x60    /* base I/O address */
+#define SIO_VT1211_ID          0x3c    /* VT1211 device ID */
+
+/* VT1211 logical device numbers */
+#define SIO_VT1211_LDN_HWMON   0x0b    /* HW monitor */
+
+static inline void superio_outb(int reg, int val)
+{
+       outb(reg, SIO_REG_CIP);
+       outb(val, SIO_REG_DIP);
+}
+
+static inline int superio_inb(int reg)
+{
+       outb(reg, SIO_REG_CIP);
+       return inb(SIO_REG_DIP);
+}
+
+static inline void superio_select(int ldn)
+{
+       outb(SIO_VT1211_LDN, SIO_REG_CIP);
+       outb(ldn, SIO_REG_DIP);
+}
+
+static inline void superio_enter(void)
+{
+       outb(0x87, SIO_REG_CIP);
+       outb(0x87, SIO_REG_CIP);
+}
+
+static inline void superio_exit(void)
+{
+       outb(0xaa, SIO_REG_CIP);
+}
+
+/* ---------------------------------------------------------------------
+ * Device I/O access
+ * --------------------------------------------------------------------- */
+
+static inline u8 vt1211_read8(struct vt1211_data *data, u8 reg)
+{
+       return inb(data->addr + reg);
+}
+
+static inline void vt1211_write8(struct vt1211_data *data, u8 reg, u8 val)
+{
+       outb(val, data->addr + reg);
+}
+
+static struct vt1211_data *vt1211_update_device(struct device *dev)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       int ix, val;
+
+       mutex_lock(&data->update_lock);
+
+       /* registers cache is refreshed after 1 second */
+       if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+               /* read VID */
+               data->vid = vt1211_read8(data, VT1211_REG_VID) & 0x1f;
+
+               /* voltage (in) registers */
+               for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
+                       if (ISVOLT(ix, data->uch_config)) {
+                               data->in[ix] = vt1211_read8(data,
+                                               VT1211_REG_IN(ix));
+                               data->in_min[ix] = vt1211_read8(data,
+                                               VT1211_REG_IN_MIN(ix));
+                               data->in_max[ix] = vt1211_read8(data,
+                                               VT1211_REG_IN_MAX(ix));
+                       }
+               }
+
+               /* temp registers */
+               for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) {
+                       if (ISTEMP(ix, data->uch_config)) {
+                               data->temp[ix] = vt1211_read8(data,
+                                               regtemp[ix]);
+                               data->temp_max[ix] = vt1211_read8(data,
+                                               regtempmax[ix]);
+                               data->temp_hyst[ix] = vt1211_read8(data,
+                                               regtemphyst[ix]);
+                       }
+               }
+
+               /* fan & pwm registers */
+               for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) {
+                       data->fan[ix] = vt1211_read8(data,
+                                               VT1211_REG_FAN(ix));
+                       data->fan_min[ix] = vt1211_read8(data,
+                                               VT1211_REG_FAN_MIN(ix));
+                       data->pwm[ix] = vt1211_read8(data,
+                                               VT1211_REG_PWM(ix));
+               }
+               val = vt1211_read8(data, VT1211_REG_FAN_DIV);
+               data->fan_div[0] = (val >> 4) & 3;
+               data->fan_div[1] = (val >> 6) & 3;
+               data->fan_ctl = val & 0xf;
+
+               val = vt1211_read8(data, VT1211_REG_PWM_CTL);
+               data->pwm_ctl[0] = val & 0xf;
+               data->pwm_ctl[1] = (val >> 4) & 0xf;
+
+               data->pwm_clk = vt1211_read8(data, VT1211_REG_PWM_CLK);
+
+               /* pwm & temp auto point registers */
+               data->pwm_auto_pwm[0][1] = vt1211_read8(data,
+                                               VT1211_REG_PWM_AUTO_PWM(0, 1));
+               data->pwm_auto_pwm[0][2] = vt1211_read8(data,
+                                               VT1211_REG_PWM_AUTO_PWM(0, 2));
+               data->pwm_auto_pwm[1][1] = vt1211_read8(data,
+                                               VT1211_REG_PWM_AUTO_PWM(1, 1));
+               data->pwm_auto_pwm[1][2] = vt1211_read8(data,
+                                               VT1211_REG_PWM_AUTO_PWM(1, 2));
+               for (ix = 0; ix < ARRAY_SIZE(data->pwm_auto_temp); ix++) {
+                       data->pwm_auto_temp[ix] = vt1211_read8(data,
+                                               VT1211_REG_PWM_AUTO_TEMP(ix));
+               }
+
+               /* alarm registers */
+               data->alarms = (vt1211_read8(data, VT1211_REG_ALARM2) << 8) |
+                               vt1211_read8(data, VT1211_REG_ALARM1);
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->update_lock);
+
+       return data;
+}
+
+/* ---------------------------------------------------------------------
+ * Voltage sysfs interfaces
+ * ix = [0-5]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_IN_INPUT  0
+#define SHOW_SET_IN_MIN        1
+#define SHOW_SET_IN_MAX        2
+#define SHOW_IN_ALARM  3
+
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+                      char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       int res;
+
+       switch (fn) {
+       case SHOW_IN_INPUT:
+               res = IN_FROM_REG(ix, data->in[ix]);
+               break;
+       case SHOW_SET_IN_MIN:
+               res = IN_FROM_REG(ix, data->in_min[ix]);
+               break;
+       case SHOW_SET_IN_MAX:
+               res = IN_FROM_REG(ix, data->in_max[ix]);
+               break;
+       case SHOW_IN_ALARM:
+               res = (data->alarms >> bitalarmin[ix]) & 1;
+               break;
+       default:
+               res = 0;
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+
+       return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_in(struct device *dev, struct device_attribute *attr,
+                     const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       long val = simple_strtol(buf, NULL, 10);
+
+       mutex_lock(&data->update_lock);
+       switch (fn) {
+       case SHOW_SET_IN_MIN:
+               data->in_min[ix] = IN_TO_REG(ix, val);
+               vt1211_write8(data, VT1211_REG_IN_MIN(ix), data->in_min[ix]);
+               break;
+       case SHOW_SET_IN_MAX:
+               data->in_max[ix] = IN_TO_REG(ix, val);
+               vt1211_write8(data, VT1211_REG_IN_MAX(ix), data->in_max[ix]);
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Temperature sysfs interfaces
+ * ix = [0-6]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_TEMP_INPUT                0
+#define SHOW_SET_TEMP_MAX      1
+#define SHOW_SET_TEMP_MAX_HYST 2
+#define SHOW_TEMP_ALARM                3
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       int res;
+
+       switch (fn) {
+       case SHOW_TEMP_INPUT:
+               res = TEMP_FROM_REG(ix, data->temp[ix]);
+               break;
+       case SHOW_SET_TEMP_MAX:
+               res = TEMP_FROM_REG(ix, data->temp_max[ix]);
+               break;
+       case SHOW_SET_TEMP_MAX_HYST:
+               res = TEMP_FROM_REG(ix, data->temp_hyst[ix]);
+               break;
+       case SHOW_TEMP_ALARM:
+               res = (data->alarms >> bitalarmtemp[ix]) & 1;
+               break;
+       default:
+               res = 0;
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+
+       return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       long val = simple_strtol(buf, NULL, 10);
+
+       mutex_lock(&data->update_lock);
+       switch (fn) {
+       case SHOW_SET_TEMP_MAX:
+               data->temp_max[ix] = TEMP_TO_REG(ix, val);
+               vt1211_write8(data, regtempmax[ix],
+                             data->temp_max[ix]);
+               break;
+       case SHOW_SET_TEMP_MAX_HYST:
+               data->temp_hyst[ix] = TEMP_TO_REG(ix, val);
+               vt1211_write8(data, regtemphyst[ix],
+                             data->temp_hyst[ix]);
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Fan sysfs interfaces
+ * ix = [0-1]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_FAN_INPUT         0
+#define SHOW_SET_FAN_MIN       1
+#define SHOW_SET_FAN_DIV       2
+#define SHOW_FAN_ALARM         3
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       int res;
+
+       switch (fn) {
+       case SHOW_FAN_INPUT:
+               res = RPM_FROM_REG(data->fan[ix], data->fan_div[ix]);
+               break;
+       case SHOW_SET_FAN_MIN:
+               res = RPM_FROM_REG(data->fan_min[ix], data->fan_div[ix]);
+               break;
+       case SHOW_SET_FAN_DIV:
+               res = DIV_FROM_REG(data->fan_div[ix]);
+               break;
+       case SHOW_FAN_ALARM:
+               res = (data->alarms >> bitalarmfan[ix]) & 1;
+               break;
+       default:
+               res = 0;
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+
+       return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       long val = simple_strtol(buf, NULL, 10);
+       int reg;
+
+       mutex_lock(&data->update_lock);
+
+       /* sync the data cache */
+       reg = vt1211_read8(data, VT1211_REG_FAN_DIV);
+       data->fan_div[0] = (reg >> 4) & 3;
+       data->fan_div[1] = (reg >> 6) & 3;
+       data->fan_ctl = reg & 0xf;
+
+       switch (fn) {
+       case SHOW_SET_FAN_MIN:
+               data->fan_min[ix] = RPM_TO_REG(val, data->fan_div[ix]);
+               vt1211_write8(data, VT1211_REG_FAN_MIN(ix),
+                             data->fan_min[ix]);
+               break;
+       case SHOW_SET_FAN_DIV:
+               switch (val) {
+                       case 1: data->fan_div[ix] = 0; break;
+                       case 2: data->fan_div[ix] = 1; break;
+                       case 4: data->fan_div[ix] = 2; break;
+                       case 8: data->fan_div[ix] = 3; break;
+                       default:
+                               count = -EINVAL;
+                               dev_warn(dev, "fan div value %ld not "
+                                        "supported. Choose one of 1, 2, "
+                                        "4, or 8.\n", val);
+                               goto EXIT;
+               }
+               vt1211_write8(data, VT1211_REG_FAN_DIV,
+                             ((data->fan_div[1] << 6) |
+                              (data->fan_div[0] << 4) |
+                               data->fan_ctl));
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+
+EXIT:
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+/* ---------------------------------------------------------------------
+ * PWM sysfs interfaces
+ * ix = [0-1]
+ * --------------------------------------------------------------------- */
+
+#define SHOW_PWM                       0
+#define SHOW_SET_PWM_ENABLE            1
+#define SHOW_SET_PWM_FREQ              2
+#define SHOW_SET_PWM_AUTO_CHANNELS_TEMP        3
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       int res;
+
+       switch (fn) {
+       case SHOW_PWM:
+               res = data->pwm[ix];
+               break;
+       case SHOW_SET_PWM_ENABLE:
+               res = ((data->pwm_ctl[ix] >> 3) & 1) ? 2 : 0;
+               break;
+       case SHOW_SET_PWM_FREQ:
+               res = 90000 >> (data->pwm_clk & 7);
+               break;
+       case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
+               res = (data->pwm_ctl[ix] & 7) + 1;
+               break;
+       default:
+               res = 0;
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+
+       return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int fn = sensor_attr_2->nr;
+       long val = simple_strtol(buf, NULL, 10);
+       int tmp, reg;
+
+       mutex_lock(&data->update_lock);
+
+       switch (fn) {
+       case SHOW_SET_PWM_ENABLE:
+               /* sync the data cache */
+               reg = vt1211_read8(data, VT1211_REG_FAN_DIV);
+               data->fan_div[0] = (reg >> 4) & 3;
+               data->fan_div[1] = (reg >> 6) & 3;
+               data->fan_ctl = reg & 0xf;
+               reg = vt1211_read8(data, VT1211_REG_PWM_CTL);
+               data->pwm_ctl[0] = reg & 0xf;
+               data->pwm_ctl[1] = (reg >> 4) & 0xf;
+               switch (val) {
+               case 0:
+                       data->pwm_ctl[ix] &= 7;
+                       /* disable SmartGuardian if both PWM outputs are
+                        * disabled */
+                       if ((data->pwm_ctl[ix ^ 1] & 1) == 0) {
+                               data->fan_ctl &= 0xe;
+                       }
+                       break;
+               case 2:
+                       data->pwm_ctl[ix] |= 8;
+                       data->fan_ctl |= 1;
+                       break;
+               default:
+                       count = -EINVAL;
+                       dev_warn(dev, "pwm mode %ld not supported. "
+                                "Choose one of 0 or 2.\n", val);
+                       goto EXIT;
+               }
+               vt1211_write8(data, VT1211_REG_PWM_CTL,
+                             ((data->pwm_ctl[1] << 4) |
+                               data->pwm_ctl[0]));
+               vt1211_write8(data, VT1211_REG_FAN_DIV,
+                             ((data->fan_div[1] << 6) |
+                              (data->fan_div[0] << 4) |
+                               data->fan_ctl));
+               break;
+       case SHOW_SET_PWM_FREQ:
+               val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000);
+               /* calculate tmp = log2(val) */
+               tmp = 0;
+               for (val >>= 1; val > 0; val >>= 1) {
+                       tmp++;
+               }
+               /* sync the data cache */
+               reg = vt1211_read8(data, VT1211_REG_PWM_CLK);
+               data->pwm_clk = (reg & 0xf8) | tmp;
+               vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk);
+               break;
+       case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
+               if ((val < 1) || (val > 7)) {
+                       count = -EINVAL;
+                       dev_warn(dev, "temp channel %ld not supported. "
+                                "Choose a value between 1 and 7.\n", val);
+                       goto EXIT;
+               }
+               if (!ISTEMP(val - 1, data->uch_config)) {
+                       count = -EINVAL;
+                       dev_warn(dev, "temp channel %ld is not available.\n",
+                                val);
+                       goto EXIT;
+               }
+               /* sync the data cache */
+               reg = vt1211_read8(data, VT1211_REG_PWM_CTL);
+               data->pwm_ctl[0] = reg & 0xf;
+               data->pwm_ctl[1] = (reg >> 4) & 0xf;
+               data->pwm_ctl[ix] = (data->pwm_ctl[ix] & 8) | (val - 1);
+               vt1211_write8(data, VT1211_REG_PWM_CTL,
+                             ((data->pwm_ctl[1] << 4) | data->pwm_ctl[0]));
+               break;
+       default:
+               dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+       }
+
+EXIT:
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+/* ---------------------------------------------------------------------
+ * PWM auto point definitions
+ * ix = [0-1]
+ * ap = [0-3]
+ * --------------------------------------------------------------------- */
+
+/*
+ * pwm[ix+1]_auto_point[ap+1]_temp mapping table:
+ * Note that there is only a single set of temp auto points that controls both
+ * PWM controllers. We still create 2 sets of sysfs files to make it look
+ * more consistent even though they map to the same registers.
+ *
+ * ix ap : description
+ * -------------------
+ * 0  0  : pwm1/2 off temperature        (pwm_auto_temp[0])
+ * 0  1  : pwm1/2 low speed temperature  (pwm_auto_temp[1])
+ * 0  2  : pwm1/2 high speed temperature (pwm_auto_temp[2])
+ * 0  3  : pwm1/2 full speed temperature (pwm_auto_temp[3])
+ * 1  0  : pwm1/2 off temperature        (pwm_auto_temp[0])
+ * 1  1  : pwm1/2 low speed temperature  (pwm_auto_temp[1])
+ * 1  2  : pwm1/2 high speed temperature (pwm_auto_temp[2])
+ * 1  3  : pwm1/2 full speed temperature (pwm_auto_temp[3])
+ */
+
+static ssize_t show_pwm_auto_point_temp(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int ap = sensor_attr_2->nr;
+
+       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->pwm_ctl[ix] & 7,
+                      data->pwm_auto_temp[ap]));
+}
+
+static ssize_t set_pwm_auto_point_temp(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int ap = sensor_attr_2->nr;
+       long val = simple_strtol(buf, NULL, 10);
+       int reg;
+
+       mutex_lock(&data->update_lock);
+
+       /* sync the data cache */
+       reg = vt1211_read8(data, VT1211_REG_PWM_CTL);
+       data->pwm_ctl[0] = reg & 0xf;
+       data->pwm_ctl[1] = (reg >> 4) & 0xf;
+
+       data->pwm_auto_temp[ap] = TEMP_TO_REG(data->pwm_ctl[ix] & 7, val);
+       vt1211_write8(data, VT1211_REG_PWM_AUTO_TEMP(ap),
+                     data->pwm_auto_temp[ap]);
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/*
+ * pwm[ix+1]_auto_point[ap+1]_pwm mapping table:
+ * Note that the PWM auto points 0 & 3 are hard-wired in the VT1211 and can't
+ * be changed.
+ *
+ * ix ap : description
+ * -------------------
+ * 0  0  : pwm1 off                   (pwm_auto_pwm[0][0], hard-wired to 0)
+ * 0  1  : pwm1 low speed duty cycle  (pwm_auto_pwm[0][1])
+ * 0  2  : pwm1 high speed duty cycle (pwm_auto_pwm[0][2])
+ * 0  3  : pwm1 full speed            (pwm_auto_pwm[0][3], hard-wired to 255)
+ * 1  0  : pwm2 off                   (pwm_auto_pwm[1][0], hard-wired to 0)
+ * 1  1  : pwm2 low speed duty cycle  (pwm_auto_pwm[1][1])
+ * 1  2  : pwm2 high speed duty cycle (pwm_auto_pwm[1][2])
+ * 1  3  : pwm2 full speed            (pwm_auto_pwm[1][3], hard-wired to 255)
+*/
+
+static ssize_t show_pwm_auto_point_pwm(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int ap = sensor_attr_2->nr;
+
+       return sprintf(buf, "%d\n", data->pwm_auto_pwm[ix][ap]);
+}
+
+static ssize_t set_pwm_auto_point_pwm(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sensor_attr_2 =
+                                               to_sensor_dev_attr_2(attr);
+       int ix = sensor_attr_2->index;
+       int ap = sensor_attr_2->nr;
+       long val = simple_strtol(buf, NULL, 10);
+
+       if ((val < 0) || (val > 255)) {
+               dev_err(dev, "pwm value %ld is out of range. "
+                       "Choose a value between 0 and 255." , val);
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->update_lock);
+       data->pwm_auto_pwm[ix][ap] = val;
+       vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap),
+                     data->pwm_auto_pwm[ix][ap]);
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Miscellaneous sysfs interfaces (VRM, VID, name, and (legacy) alarms)
+ * --------------------------------------------------------------------- */
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+       long val = simple_strtol(buf, NULL, 10);
+
+       data->vrm = val;
+
+       return count;
+}
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static ssize_t show_name(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       struct vt1211_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", data->name);
+}
+
+static ssize_t show_alarms(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       struct vt1211_data *data = vt1211_update_device(dev);
+
+       return sprintf(buf, "%d\n", data->alarms);
+}
+
+/* ---------------------------------------------------------------------
+ * Device attribute structs
+ * --------------------------------------------------------------------- */
+
+#define SENSOR_ATTR_IN_INPUT(ix) \
+       SENSOR_ATTR_2(in##ix##_input, S_IRUGO, \
+               show_in, NULL, SHOW_IN_INPUT, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_input[] = {
+       SENSOR_ATTR_IN_INPUT(0),
+       SENSOR_ATTR_IN_INPUT(1),
+       SENSOR_ATTR_IN_INPUT(2),
+       SENSOR_ATTR_IN_INPUT(3),
+       SENSOR_ATTR_IN_INPUT(4),
+       SENSOR_ATTR_IN_INPUT(5),
+};
+
+#define SENSOR_ATTR_IN_MIN(ix) \
+       SENSOR_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \
+               show_in, set_in, SHOW_SET_IN_MIN, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_min[] = {
+       SENSOR_ATTR_IN_MIN(0),
+       SENSOR_ATTR_IN_MIN(1),
+       SENSOR_ATTR_IN_MIN(2),
+       SENSOR_ATTR_IN_MIN(3),
+       SENSOR_ATTR_IN_MIN(4),
+       SENSOR_ATTR_IN_MIN(5),
+};
+
+#define SENSOR_ATTR_IN_MAX(ix) \
+       SENSOR_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \
+               show_in, set_in, SHOW_SET_IN_MAX, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_max[] = {
+       SENSOR_ATTR_IN_MAX(0),
+       SENSOR_ATTR_IN_MAX(1),
+       SENSOR_ATTR_IN_MAX(2),
+       SENSOR_ATTR_IN_MAX(3),
+       SENSOR_ATTR_IN_MAX(4),
+       SENSOR_ATTR_IN_MAX(5),
+};
+
+#define SENSOR_ATTR_IN_ALARM(ix) \
+       SENSOR_ATTR_2(in##ix##_alarm, S_IRUGO, \
+               show_in, NULL, SHOW_IN_ALARM, ix)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_in_alarm[] = {
+       SENSOR_ATTR_IN_ALARM(0),
+       SENSOR_ATTR_IN_ALARM(1),
+       SENSOR_ATTR_IN_ALARM(2),
+       SENSOR_ATTR_IN_ALARM(3),
+       SENSOR_ATTR_IN_ALARM(4),
+       SENSOR_ATTR_IN_ALARM(5),
+};
+
+#define SENSOR_ATTR_TEMP_INPUT(ix) \
+       SENSOR_ATTR_2(temp##ix##_input, S_IRUGO, \
+               show_temp, NULL, SHOW_TEMP_INPUT, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_input[] = {
+       SENSOR_ATTR_TEMP_INPUT(1),
+       SENSOR_ATTR_TEMP_INPUT(2),
+       SENSOR_ATTR_TEMP_INPUT(3),
+       SENSOR_ATTR_TEMP_INPUT(4),
+       SENSOR_ATTR_TEMP_INPUT(5),
+       SENSOR_ATTR_TEMP_INPUT(6),
+       SENSOR_ATTR_TEMP_INPUT(7),
+};
+
+#define SENSOR_ATTR_TEMP_MAX(ix) \
+       SENSOR_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \
+               show_temp, set_temp, SHOW_SET_TEMP_MAX, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_max[] = {
+       SENSOR_ATTR_TEMP_MAX(1),
+       SENSOR_ATTR_TEMP_MAX(2),
+       SENSOR_ATTR_TEMP_MAX(3),
+       SENSOR_ATTR_TEMP_MAX(4),
+       SENSOR_ATTR_TEMP_MAX(5),
+       SENSOR_ATTR_TEMP_MAX(6),
+       SENSOR_ATTR_TEMP_MAX(7),
+};
+
+#define SENSOR_ATTR_TEMP_MAX_HYST(ix) \
+       SENSOR_ATTR_2(temp##ix##_max_hyst, S_IRUGO | S_IWUSR, \
+               show_temp, set_temp, SHOW_SET_TEMP_MAX_HYST, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_max_hyst[] = {
+       SENSOR_ATTR_TEMP_MAX_HYST(1),
+       SENSOR_ATTR_TEMP_MAX_HYST(2),
+       SENSOR_ATTR_TEMP_MAX_HYST(3),
+       SENSOR_ATTR_TEMP_MAX_HYST(4),
+       SENSOR_ATTR_TEMP_MAX_HYST(5),
+       SENSOR_ATTR_TEMP_MAX_HYST(6),
+       SENSOR_ATTR_TEMP_MAX_HYST(7),
+};
+
+#define SENSOR_ATTR_TEMP_ALARM(ix) \
+       SENSOR_ATTR_2(temp##ix##_alarm, S_IRUGO, \
+               show_temp, NULL, SHOW_TEMP_ALARM, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_temp_alarm[] = {
+       SENSOR_ATTR_TEMP_ALARM(1),
+       SENSOR_ATTR_TEMP_ALARM(2),
+       SENSOR_ATTR_TEMP_ALARM(3),
+       SENSOR_ATTR_TEMP_ALARM(4),
+       SENSOR_ATTR_TEMP_ALARM(5),
+       SENSOR_ATTR_TEMP_ALARM(6),
+       SENSOR_ATTR_TEMP_ALARM(7),
+};
+
+#define SENSOR_ATTR_FAN(ix) \
+       SENSOR_ATTR_2(fan##ix##_input, S_IRUGO, \
+               show_fan, NULL, SHOW_FAN_INPUT, ix-1), \
+       SENSOR_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \
+               show_fan, set_fan, SHOW_SET_FAN_MIN, ix-1), \
+       SENSOR_ATTR_2(fan##ix##_div, S_IRUGO | S_IWUSR, \
+               show_fan, set_fan, SHOW_SET_FAN_DIV, ix-1), \
+       SENSOR_ATTR_2(fan##ix##_alarm, S_IRUGO, \
+               show_fan, NULL, SHOW_FAN_ALARM, ix-1)
+
+#define SENSOR_ATTR_PWM(ix) \
+       SENSOR_ATTR_2(pwm##ix, S_IRUGO, \
+               show_pwm, NULL, SHOW_PWM, ix-1), \
+       SENSOR_ATTR_2(pwm##ix##_enable, S_IRUGO | S_IWUSR, \
+               show_pwm, set_pwm, SHOW_SET_PWM_ENABLE, ix-1), \
+       SENSOR_ATTR_2(pwm##ix##_auto_channels_temp, S_IRUGO | S_IWUSR, \
+               show_pwm, set_pwm, SHOW_SET_PWM_AUTO_CHANNELS_TEMP, ix-1)
+
+#define SENSOR_ATTR_PWM_FREQ(ix) \
+       SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \
+               show_pwm, set_pwm, SHOW_SET_PWM_FREQ, ix-1)
+
+#define SENSOR_ATTR_PWM_FREQ_RO(ix) \
+       SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO, \
+               show_pwm, NULL, SHOW_SET_PWM_FREQ, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP(ix, ap) \
+       SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO | S_IWUSR, \
+               show_pwm_auto_point_temp, set_pwm_auto_point_temp, \
+               ap-1, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(ix, ap) \
+       SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO, \
+               show_pwm_auto_point_temp, NULL, \
+               ap-1, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_PWM(ix, ap) \
+       SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO | S_IWUSR, \
+               show_pwm_auto_point_pwm, set_pwm_auto_point_pwm, \
+               ap-1, ix-1)
+
+#define SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(ix, ap) \
+       SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO, \
+               show_pwm_auto_point_pwm, NULL, \
+               ap-1, ix-1)
+
+static struct sensor_device_attribute_2 vt1211_sysfs_fan_pwm[] = {
+       SENSOR_ATTR_FAN(1),
+       SENSOR_ATTR_FAN(2),
+       SENSOR_ATTR_PWM(1),
+       SENSOR_ATTR_PWM(2),
+       SENSOR_ATTR_PWM_FREQ(1),
+       SENSOR_ATTR_PWM_FREQ_RO(2),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 1),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 2),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 3),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 4),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 1),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 2),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 3),
+       SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 4),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 1),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 2),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 3),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 4),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 1),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 2),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 3),
+       SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 4),
+};
+
+static struct device_attribute vt1211_sysfs_misc[] = {
+       __ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm),
+       __ATTR(cpu0_vid, S_IRUGO, show_vid, NULL),
+       __ATTR(name, S_IRUGO, show_name, NULL),
+       __ATTR(alarms, S_IRUGO, show_alarms, NULL),
+};
+
+/* ---------------------------------------------------------------------
+ * Device registration and initialization
+ * --------------------------------------------------------------------- */
+
+static void __devinit vt1211_init_device(struct vt1211_data *data)
+{
+       /* set VRM */
+       data->vrm = vid_which_vrm();
+
+       /* Read (and initialize) UCH config */
+       data->uch_config = vt1211_read8(data, VT1211_REG_UCH_CONFIG);
+       if (uch_config > -1) {
+               data->uch_config = (data->uch_config & 0x83) |
+                                  (uch_config << 2);
+               vt1211_write8(data, VT1211_REG_UCH_CONFIG, data->uch_config);
+       }
+
+       /* Initialize the interrupt mode (if request at module load time).
+        * The VT1211 implements 3 different modes for clearing interrupts:
+        * 0: Clear INT when status register is read. Regenerate INT as long
+        *    as temp stays above hysteresis limit.
+        * 1: Clear INT when status register is read. DON'T regenerate INT
+        *    until temp falls below hysteresis limit and exceeds hot limit
+        *    again.
+        * 2: Clear INT when temp falls below max limit.
+        *
+        * The driver only allows to force mode 0 since that's the only one
+        * that makes sense for 'sensors' */
+       if (int_mode == 0) {
+               vt1211_write8(data, VT1211_REG_TEMP1_CONFIG, 0);
+               vt1211_write8(data, VT1211_REG_TEMP2_CONFIG, 0);
+       }
+
+       /* Fill in some hard wired values into our data struct */
+       data->pwm_auto_pwm[0][3] = 255;
+       data->pwm_auto_pwm[1][3] = 255;
+}
+
+static void vt1211_remove_sysfs(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_in_input); i++) {
+               device_remove_file(dev,
+                       &vt1211_sysfs_in_input[i].dev_attr);
+               device_remove_file(dev,
+                       &vt1211_sysfs_in_min[i].dev_attr);
+               device_remove_file(dev,
+                       &vt1211_sysfs_in_max[i].dev_attr);
+               device_remove_file(dev,
+                       &vt1211_sysfs_in_alarm[i].dev_attr);
+       }
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_temp_input); i++) {
+               device_remove_file(dev,
+                       &vt1211_sysfs_temp_input[i].dev_attr);
+               device_remove_file(dev,
+                       &vt1211_sysfs_temp_max[i].dev_attr);
+               device_remove_file(dev,
+                       &vt1211_sysfs_temp_max_hyst[i].dev_attr);
+               device_remove_file(dev,
+                       &vt1211_sysfs_temp_alarm[i].dev_attr);
+       }
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) {
+               device_remove_file(dev,
+                       &vt1211_sysfs_fan_pwm[i].dev_attr);
+       }
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) {
+               device_remove_file(dev, &vt1211_sysfs_misc[i]);
+       }
+}
+
+static int __devinit vt1211_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct vt1211_data *data;
+       struct resource *res;
+       int i, err;
+
+       if (!(data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               dev_err(dev, "Out of memory\n");
+               goto EXIT;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       data->addr = res->start;
+       data->name = DRVNAME;
+       mutex_init(&data->update_lock);
+
+       platform_set_drvdata(pdev, data);
+
+       /* Initialize the VT1211 chip */
+       vt1211_init_device(data);
+
+       /* Create sysfs interface files */
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_in_input); i++) {
+               if (ISVOLT(i, data->uch_config)) {
+                       if ((err = device_create_file(dev,
+                               &vt1211_sysfs_in_input[i].dev_attr)) ||
+                           (err = device_create_file(dev,
+                               &vt1211_sysfs_in_min[i].dev_attr)) ||
+                           (err = device_create_file(dev,
+                               &vt1211_sysfs_in_max[i].dev_attr)) ||
+                           (err = device_create_file(dev,
+                               &vt1211_sysfs_in_alarm[i].dev_attr))) {
+                               goto EXIT_DEV_REMOVE;
+                       }
+               }
+       }
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_temp_input); i++) {
+               if (ISTEMP(i, data->uch_config)) {
+                       if ((err = device_create_file(dev,
+                               &vt1211_sysfs_temp_input[i].dev_attr)) ||
+                           (err = device_create_file(dev,
+                               &vt1211_sysfs_temp_max[i].dev_attr)) ||
+                           (err = device_create_file(dev,
+                               &vt1211_sysfs_temp_max_hyst[i].dev_attr)) ||
+                           (err = device_create_file(dev,
+                               &vt1211_sysfs_temp_alarm[i].dev_attr))) {
+                               goto EXIT_DEV_REMOVE;
+                       }
+               }
+       }
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) {
+               err = device_create_file(dev,
+                       &vt1211_sysfs_fan_pwm[i].dev_attr);
+               if (err) {
+                       goto EXIT_DEV_REMOVE;
+               }
+       }
+       for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) {
+               err = device_create_file(dev,
+                      &vt1211_sysfs_misc[i]);
+               if (err) {
+                       goto EXIT_DEV_REMOVE;
+               }
+       }
+
+       /* Register device */
+       data->class_dev = hwmon_device_register(dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               dev_err(dev, "Class registration failed (%d)\n", err);
+               goto EXIT_DEV_REMOVE_SILENT;
+       }
+
+       return 0;
+
+EXIT_DEV_REMOVE:
+       dev_err(dev, "Sysfs interface creation failed (%d)\n", err);
+EXIT_DEV_REMOVE_SILENT:
+       vt1211_remove_sysfs(pdev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+EXIT:
+       return err;
+}
+
+static int __devexit vt1211_remove(struct platform_device *pdev)
+{
+       struct vt1211_data *data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(data->class_dev);
+       vt1211_remove_sysfs(pdev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+
+       return 0;
+}
+
+static struct platform_driver vt1211_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name  = DRVNAME,
+       },
+       .probe  = vt1211_probe,
+       .remove = __devexit_p(vt1211_remove),
+};
+
+static int __init vt1211_device_add(unsigned short address)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + 0x7f,
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc(DRVNAME, address);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n",
+                      err);
+               goto EXIT;
+       }
+
+       res.name = pdev->name;
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device resource addition failed "
+                      "(%d)\n", err);
+               goto EXIT_DEV_PUT;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto EXIT_DEV_PUT;
+       }
+
+       return 0;
+
+EXIT_DEV_PUT:
+       platform_device_put(pdev);
+EXIT:
+       return err;
+}
+
+static int __init vt1211_find(unsigned short *address)
+{
+       int err = -ENODEV;
+
+       superio_enter();
+
+       if (superio_inb(SIO_VT1211_DEVID) != SIO_VT1211_ID) {
+               goto EXIT;
+       }
+
+       superio_select(SIO_VT1211_LDN_HWMON);
+
+       if ((superio_inb(SIO_VT1211_ACTIVE) & 1) == 0) {
+               printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
+                      "skipping\n");
+               goto EXIT;
+       }
+
+       *address = ((superio_inb(SIO_VT1211_BADDR) << 8) |
+                   (superio_inb(SIO_VT1211_BADDR + 1))) & 0xff00;
+       if (*address == 0) {
+               printk(KERN_WARNING DRVNAME ": Base address is not set, "
+                      "skipping\n");
+               goto EXIT;
+       }
+
+       err = 0;
+       printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
+              "revision %u\n", *address, superio_inb(SIO_VT1211_DEVREV));
+
+EXIT:
+       superio_exit();
+       return err;
+}
+
+static int __init vt1211_init(void)
+{
+       int err;
+       unsigned short address = 0;
+
+       err = vt1211_find(&address);
+       if (err) {
+               goto EXIT;
+       }
+
+       if ((uch_config < -1) || (uch_config > 31)) {
+               err = -EINVAL;
+               printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. "
+                      "Choose a value between 0 and 31.\n", uch_config);
+         goto EXIT;
+       }
+
+       if ((int_mode < -1) || (int_mode > 0)) {
+               err = -EINVAL;
+               printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. "
+                      "Only mode 0 is supported.\n", int_mode);
+         goto EXIT;
+       }
+
+       err = platform_driver_register(&vt1211_driver);
+       if (err) {
+               goto EXIT;
+       }
+
+       /* Sets global pdev as a side effect */
+       err = vt1211_device_add(address);
+       if (err) {
+               goto EXIT_DRV_UNREGISTER;
+       }
+
+       return 0;
+
+EXIT_DRV_UNREGISTER:
+       platform_driver_unregister(&vt1211_driver);
+EXIT:
+       return err;
+}
+
+static void __exit vt1211_exit(void)
+{
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&vt1211_driver);
+}
+
+MODULE_AUTHOR("Juerg Haefliger <juergh@gmail.com>");
+MODULE_DESCRIPTION("VT1211 sensors");
+MODULE_LICENSE("GPL");
+
+module_init(vt1211_init);
+module_exit(vt1211_exit);
index 686f3deb3093844f4129a338b8e441052225b344..93f93d4fb8aec2126e86131e9077703c4e1e171d 100644 (file)
@@ -451,37 +451,6 @@ define_temperature_sysfs(4);
 define_temperature_sysfs(5);
 define_temperature_sysfs(6);
 
-#define CFG_INFO_TEMP(id)      { &sensor_dev_attr_temp##id##_input.dev_attr, \
-                               &sensor_dev_attr_temp##id##_max_hyst.dev_attr, \
-                               &sensor_dev_attr_temp##id##_max.dev_attr }
-#define CFG_INFO_VOLT(id)      { &sensor_dev_attr_in##id##_input.dev_attr, \
-                               &sensor_dev_attr_in##id##_min.dev_attr, \
-                               &sensor_dev_attr_in##id##_max.dev_attr }
-
-struct str_device_attr_table {
-       struct device_attribute *input;
-       struct device_attribute *min;
-       struct device_attribute *max;
-};
-
-static struct str_device_attr_table cfg_info_temp[] = {
-       { &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max },
-       CFG_INFO_TEMP(2),
-       CFG_INFO_TEMP(3),
-       CFG_INFO_TEMP(4),
-       CFG_INFO_TEMP(5),
-       CFG_INFO_TEMP(6)
-};
-
-static struct str_device_attr_table cfg_info_volt[] = {
-       CFG_INFO_VOLT(0),
-       CFG_INFO_VOLT(1),
-       CFG_INFO_VOLT(2),
-       CFG_INFO_VOLT(3),
-       CFG_INFO_VOLT(4),
-       { &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max }
-};
-
 /* Fans */
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
                char *buf)
@@ -585,8 +554,110 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *vt8231_attributes_temps[6][4] = {
+       {
+               &dev_attr_temp1_input.attr,
+               &dev_attr_temp1_max_hyst.attr,
+               &dev_attr_temp1_max.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_temp2_input.dev_attr.attr,
+               &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+               &sensor_dev_attr_temp2_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_temp3_input.dev_attr.attr,
+               &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+               &sensor_dev_attr_temp3_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_temp4_input.dev_attr.attr,
+               &sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
+               &sensor_dev_attr_temp4_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_temp5_input.dev_attr.attr,
+               &sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
+               &sensor_dev_attr_temp5_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_temp6_input.dev_attr.attr,
+               &sensor_dev_attr_temp6_max_hyst.dev_attr.attr,
+               &sensor_dev_attr_temp6_max.dev_attr.attr,
+               NULL
+       }
+};
+
+static const struct attribute_group vt8231_group_temps[6] = {
+       { .attrs = vt8231_attributes_temps[0] },
+       { .attrs = vt8231_attributes_temps[1] },
+       { .attrs = vt8231_attributes_temps[2] },
+       { .attrs = vt8231_attributes_temps[3] },
+       { .attrs = vt8231_attributes_temps[4] },
+       { .attrs = vt8231_attributes_temps[5] },
+};
+
+static struct attribute *vt8231_attributes_volts[6][4] = {
+       {
+               &sensor_dev_attr_in0_input.dev_attr.attr,
+               &sensor_dev_attr_in0_min.dev_attr.attr,
+               &sensor_dev_attr_in0_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_in1_input.dev_attr.attr,
+               &sensor_dev_attr_in1_min.dev_attr.attr,
+               &sensor_dev_attr_in1_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_in2_input.dev_attr.attr,
+               &sensor_dev_attr_in2_min.dev_attr.attr,
+               &sensor_dev_attr_in2_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_in3_input.dev_attr.attr,
+               &sensor_dev_attr_in3_min.dev_attr.attr,
+               &sensor_dev_attr_in3_max.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_in4_input.dev_attr.attr,
+               &sensor_dev_attr_in4_min.dev_attr.attr,
+               &sensor_dev_attr_in4_max.dev_attr.attr,
+               NULL
+       }, {
+               &dev_attr_in5_input.attr,
+               &dev_attr_in5_min.attr,
+               &dev_attr_in5_max.attr,
+               NULL
+       }
+};
+
+static const struct attribute_group vt8231_group_volts[6] = {
+       { .attrs = vt8231_attributes_volts[0] },
+       { .attrs = vt8231_attributes_volts[1] },
+       { .attrs = vt8231_attributes_volts[2] },
+       { .attrs = vt8231_attributes_volts[3] },
+       { .attrs = vt8231_attributes_volts[4] },
+       { .attrs = vt8231_attributes_volts[5] },
+};
+
+static struct attribute *vt8231_attributes[] = {
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_fan2_div.dev_attr.attr,
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group vt8231_group = {
+       .attrs = vt8231_attributes,
+};
+
 static struct i2c_driver vt8231_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "vt8231",
        },
        .attach_adapter = vt8231_detect,
@@ -670,43 +741,43 @@ int vt8231_detect(struct i2c_adapter *adapter)
        vt8231_init_client(client);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&client->dev.kobj, &vt8231_group)))
                goto exit_detach;
-       }
 
        /* Must update device information to find out the config field */
        data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG);
 
-       for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) {
+       for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) {
                if (ISTEMP(i, data->uch_config)) {
-                       device_create_file(&client->dev,
-                                          cfg_info_temp[i].input);
-                       device_create_file(&client->dev, cfg_info_temp[i].max);
-                       device_create_file(&client->dev, cfg_info_temp[i].min);
+                       if ((err = sysfs_create_group(&client->dev.kobj,
+                                       &vt8231_group_temps[i])))
+                               goto exit_remove_files;
                }
        }
 
-       for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) {
+       for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) {
                if (ISVOLT(i, data->uch_config)) {
-                       device_create_file(&client->dev,
-                                          cfg_info_volt[i].input);
-                       device_create_file(&client->dev, cfg_info_volt[i].max);
-                       device_create_file(&client->dev, cfg_info_volt[i].min);
+                       if ((err = sysfs_create_group(&client->dev.kobj,
+                                       &vt8231_group_volts[i])))
+                               goto exit_remove_files;
                }
        }
 
-       device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr);
-       device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr);
-
-       device_create_file(&client->dev, &dev_attr_alarms);
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove_files;
+       }
        return 0;
 
+exit_remove_files:
+       for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
+               sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]);
+
+       for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
+               sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]);
+
+       sysfs_remove_group(&client->dev.kobj, &vt8231_group);
 exit_detach:
        i2c_detach_client(client);
 exit_free:
@@ -719,10 +790,18 @@ exit_release:
 static int vt8231_detach_client(struct i2c_client *client)
 {
        struct vt8231_data *data = i2c_get_clientdata(client);
-       int err;
+       int err, i;
 
        hwmon_device_unregister(data->class_dev);
 
+       for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
+               sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]);
+
+       for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
+               sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]);
+
+       sysfs_remove_group(&client->dev.kobj, &vt8231_group);
+
        if ((err = i2c_detach_client(client))) {
                return err;
        }
index 40301bc6ce186e5a1c92c7a7d9964e945807dac7..833faa275ffaed22b8eb5caa57172a965595ca7a 100644 (file)
@@ -2,6 +2,9 @@
     w83627ehf - Driver for the hardware monitoring functionality of
                 the Winbond W83627EHF Super-I/O chip
     Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2006  Yuan Mu (Winbond),
+                        Rudolf Marek <r.marek@sh.cvut.cz>
+                        David Hubbard <david.c.hubbard@gmail.com>
 
     Shamelessly ripped from the w83627hf driver
     Copyright (C) 2003  Mark Studebaker
@@ -29,8 +32,8 @@
 
     Supports the following chips:
 
-    Chip        #vin    #fan    #pwm    #temp   chip_id man_id
-    w83627ehf   10      5       -       3       0x88    0x5ca3
+    Chip        #vin    #fan    #pwm    #temp   chip_id    man_id
+    w83627ehf   10      5       4       3       0x88,0xa1  0x5ca3
 */
 
 #include <linux/module.h>
@@ -145,10 +148,44 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
 #define W83627EHF_REG_ALARM2           0x45A
 #define W83627EHF_REG_ALARM3           0x45B
 
+/* SmartFan registers */
+/* DC or PWM output fan configuration */
+static const u8 W83627EHF_REG_PWM_ENABLE[] = {
+       0x04,                   /* SYS FAN0 output mode and PWM mode */
+       0x04,                   /* CPU FAN0 output mode and PWM mode */
+       0x12,                   /* AUX FAN mode */
+       0x62,                   /* CPU fan1 mode */
+};
+
+static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
+static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
+
+/* FAN Duty Cycle, be used to control */
+static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
+static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
+static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
+
+
+/* Advanced Fan control, some values are common for all fans */
+static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
+static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 };
+
 /*
  * Conversions
  */
 
+/* 1 is PWM mode, output in ms */
+static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
+{
+       return mode ? 100 * reg : 400 * reg;
+}
+
+static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
+{
+       return SENSORS_LIMIT((mode ? (msec + 50) / 100 :
+                                               (msec + 200) / 400), 1, 255);
+}
+
 static inline unsigned int
 fan_from_reg(u8 reg, unsigned int div)
 {
@@ -170,12 +207,12 @@ temp1_from_reg(s8 reg)
 }
 
 static inline s8
-temp1_to_reg(int temp)
+temp1_to_reg(int temp, int min, int max)
 {
-       if (temp <= -128000)
-               return -128;
-       if (temp >= 127000)
-               return 127;
+       if (temp <= min)
+               return min / 1000;
+       if (temp >= max)
+               return max / 1000;
        if (temp < 0)
                return (temp - 500) / 1000;
        return (temp + 500) / 1000;
@@ -223,6 +260,16 @@ struct w83627ehf_data {
        s16 temp_max[2];
        s16 temp_max_hyst[2];
        u32 alarms;
+
+       u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
+       u8 pwm_enable[4]; /* 1->manual
+                            2->thermal cruise (also called SmartFan I) */
+       u8 pwm[4];
+       u8 target_temp[4];
+       u8 tolerance[4];
+
+       u8 fan_min_output[4]; /* minimum fan speed */
+       u8 fan_stop_time[4];
 };
 
 static inline int is_word_sized(u16 reg)
@@ -349,6 +396,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct w83627ehf_data *data = i2c_get_clientdata(client);
+       int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
        int i;
 
        mutex_lock(&data->update_lock);
@@ -416,6 +464,34 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
                        }
                }
 
+               for (i = 0; i < 4; i++) {
+                       /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
+                       if (i != 1) {
+                               pwmcfg = w83627ehf_read_value(client,
+                                               W83627EHF_REG_PWM_ENABLE[i]);
+                               tolerance = w83627ehf_read_value(client,
+                                               W83627EHF_REG_TOLERANCE[i]);
+                       }
+                       data->pwm_mode[i] =
+                               ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
+                               ? 0 : 1;
+                       data->pwm_enable[i] =
+                                       ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
+                                               & 3) + 1;
+                       data->pwm[i] = w83627ehf_read_value(client,
+                                               W83627EHF_REG_PWM[i]);
+                       data->fan_min_output[i] = w83627ehf_read_value(client,
+                                               W83627EHF_REG_FAN_MIN_OUTPUT[i]);
+                       data->fan_stop_time[i] = w83627ehf_read_value(client,
+                                               W83627EHF_REG_FAN_STOP_TIME[i]);
+                       data->target_temp[i] =
+                               w83627ehf_read_value(client,
+                                       W83627EHF_REG_TARGET[i]) &
+                                       (data->pwm_mode[i] == 1 ? 0x7f : 0xff);
+                       data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
+                                                                       & 0x0f;
+               }
+
                /* Measured temperatures and limits */
                data->temp1 = w83627ehf_read_value(client,
                              W83627EHF_REG_TEMP1);
@@ -546,14 +622,6 @@ static struct sensor_device_attribute sda_in_max[] = {
        SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
 };
 
-static void device_create_file_in(struct device *dev, int i)
-{
-       device_create_file(dev, &sda_in_input[i].dev_attr);
-       device_create_file(dev, &sda_in_alarm[i].dev_attr);
-       device_create_file(dev, &sda_in_min[i].dev_attr);
-       device_create_file(dev, &sda_in_max[i].dev_attr);
-}
-
 #define show_fan_reg(reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
@@ -681,14 +749,6 @@ static struct sensor_device_attribute sda_fan_div[] = {
        SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
 };
 
-static void device_create_file_fan(struct device *dev, int i)
-{
-       device_create_file(dev, &sda_fan_input[i].dev_attr);
-       device_create_file(dev, &sda_fan_alarm[i].dev_attr);
-       device_create_file(dev, &sda_fan_div[i].dev_attr);
-       device_create_file(dev, &sda_fan_min[i].dev_attr);
-}
-
 #define show_temp1_reg(reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
@@ -711,7 +771,7 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
        u32 val = simple_strtoul(buf, NULL, 10); \
  \
        mutex_lock(&data->update_lock); \
-       data->temp1_##reg = temp1_to_reg(val); \
+       data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
        w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
                              data->temp1_##reg); \
        mutex_unlock(&data->update_lock); \
@@ -777,10 +837,309 @@ static struct sensor_device_attribute sda_temp[] = {
        SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
 };
 
+#define show_pwm_reg(reg) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+                               char *buf) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       return sprintf(buf, "%d\n", data->reg[nr]); \
+}
+
+show_pwm_reg(pwm_mode)
+show_pwm_reg(pwm_enable)
+show_pwm_reg(pwm)
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       u32 val = simple_strtoul(buf, NULL, 10);
+       u16 reg;
+
+       if (val > 1)
+               return -EINVAL;
+       mutex_lock(&data->update_lock);
+       reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
+       data->pwm_mode[nr] = val;
+       reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]);
+       if (!val)
+               reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
+       w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
+
+       mutex_lock(&data->update_lock);
+       data->pwm[nr] = val;
+       w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+static ssize_t
+store_pwm_enable(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       u32 val = simple_strtoul(buf, NULL, 10);
+       u16 reg;
+
+       if (!val || (val > 2))  /* only modes 1 and 2 are supported */
+               return -EINVAL;
+       mutex_lock(&data->update_lock);
+       reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
+       data->pwm_enable[nr] = val;
+       reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
+       reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
+       w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+
+#define show_tol_temp(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+                               char *buf) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \
+}
+
+show_tol_temp(tolerance)
+show_tol_temp(target_temp)
+
+static ssize_t
+store_target_temp(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
+
+       mutex_lock(&data->update_lock);
+       data->target_temp[nr] = val;
+       w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+static ssize_t
+store_tolerance(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       u16 reg;
+       /* Limit the temp to 0C - 15C */
+       u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
+
+       mutex_lock(&data->update_lock);
+       reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]);
+       data->tolerance[nr] = val;
+       if (nr == 1)
+               reg = (reg & 0x0f) | (val << 4);
+       else
+               reg = (reg & 0xf0) | val;
+       w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+static struct sensor_device_attribute sda_pwm[] = {
+       SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
+       SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
+       SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
+       SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
+};
+
+static struct sensor_device_attribute sda_pwm_mode[] = {
+       SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+                   store_pwm_mode, 0),
+       SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+                   store_pwm_mode, 1),
+       SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+                   store_pwm_mode, 2),
+       SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+                   store_pwm_mode, 3),
+};
+
+static struct sensor_device_attribute sda_pwm_enable[] = {
+       SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+                   store_pwm_enable, 0),
+       SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+                   store_pwm_enable, 1),
+       SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+                   store_pwm_enable, 2),
+       SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+                   store_pwm_enable, 3),
+};
+
+static struct sensor_device_attribute sda_target_temp[] = {
+       SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp,
+                   store_target_temp, 0),
+       SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp,
+                   store_target_temp, 1),
+       SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp,
+                   store_target_temp, 2),
+       SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp,
+                   store_target_temp, 3),
+};
+
+static struct sensor_device_attribute sda_tolerance[] = {
+       SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+                   store_tolerance, 0),
+       SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+                   store_tolerance, 1),
+       SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+                   store_tolerance, 2),
+       SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance,
+                   store_tolerance, 3),
+};
+
+/* Smart Fan registers */
+
+#define fan_functions(reg, REG) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+                      char *buf) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       return sprintf(buf, "%d\n", data->reg[nr]); \
+}\
+static ssize_t \
+store_##reg(struct device *dev, struct device_attribute *attr, \
+                           const char *buf, size_t count) \
+{\
+       struct i2c_client *client = to_i2c_client(dev); \
+       struct w83627ehf_data *data = i2c_get_clientdata(client); \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
+       mutex_lock(&data->update_lock); \
+       data->reg[nr] = val; \
+       w83627ehf_write_value(client, W83627EHF_REG_##REG[nr],  val); \
+       mutex_unlock(&data->update_lock); \
+       return count; \
+}
+
+fan_functions(fan_min_output, FAN_MIN_OUTPUT)
+
+#define fan_time_functions(reg, REG) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+                               char *buf) \
+{ \
+       struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       return sprintf(buf, "%d\n", \
+                       step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \
+} \
+\
+static ssize_t \
+store_##reg(struct device *dev, struct device_attribute *attr, \
+                       const char *buf, size_t count) \
+{ \
+       struct i2c_client *client = to_i2c_client(dev); \
+       struct w83627ehf_data *data = i2c_get_clientdata(client); \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
+                                       data->pwm_mode[nr]); \
+       mutex_lock(&data->update_lock); \
+       data->reg[nr] = val; \
+       w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
+       mutex_unlock(&data->update_lock); \
+       return count; \
+} \
+
+fan_time_functions(fan_stop_time, FAN_STOP_TIME)
+
+
+static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
+       SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+                   store_fan_stop_time, 3),
+       SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+                   store_fan_min_output, 3),
+};
+
+static struct sensor_device_attribute sda_sf3_arrays[] = {
+       SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+                   store_fan_stop_time, 0),
+       SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+                   store_fan_stop_time, 1),
+       SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+                   store_fan_stop_time, 2),
+       SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+                   store_fan_min_output, 0),
+       SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+                   store_fan_min_output, 1),
+       SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output,
+                   store_fan_min_output, 2),
+};
+
 /*
  * Driver and client management
  */
 
+static void w83627ehf_device_remove_files(struct device *dev)
+{
+       /* some entries in the following arrays may not have been used in
+        * device_create_file(), but device_remove_file() will ignore them */
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
+               device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
+       for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
+               device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
+       for (i = 0; i < 10; i++) {
+               device_remove_file(dev, &sda_in_input[i].dev_attr);
+               device_remove_file(dev, &sda_in_alarm[i].dev_attr);
+               device_remove_file(dev, &sda_in_min[i].dev_attr);
+               device_remove_file(dev, &sda_in_max[i].dev_attr);
+       }
+       for (i = 0; i < 5; i++) {
+               device_remove_file(dev, &sda_fan_input[i].dev_attr);
+               device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
+               device_remove_file(dev, &sda_fan_div[i].dev_attr);
+               device_remove_file(dev, &sda_fan_min[i].dev_attr);
+       }
+       for (i = 0; i < 4; i++) {
+               device_remove_file(dev, &sda_pwm[i].dev_attr);
+               device_remove_file(dev, &sda_pwm_mode[i].dev_attr);
+               device_remove_file(dev, &sda_pwm_enable[i].dev_attr);
+               device_remove_file(dev, &sda_target_temp[i].dev_attr);
+               device_remove_file(dev, &sda_tolerance[i].dev_attr);
+       }
+       for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
+               device_remove_file(dev, &sda_temp[i].dev_attr);
+}
+
 static struct i2c_driver w83627ehf_driver;
 
 static void w83627ehf_init_client(struct i2c_client *client)
@@ -810,6 +1169,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
        struct i2c_client *client;
        struct w83627ehf_data *data;
        struct device *dev;
+       u8 fan4pin, fan5pin;
        int i, err = 0;
 
        if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
@@ -848,35 +1208,87 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
                data->fan_min[i] = w83627ehf_read_value(client,
                                   W83627EHF_REG_FAN_MIN[i]);
 
+       /* fan4 and fan5 share some pins with the GPIO and serial flash */
+
+       superio_enter();
+       fan5pin = superio_inb(0x24) & 0x2;
+       fan4pin = superio_inb(0x29) & 0x6;
+       superio_exit();
+
        /* It looks like fan4 and fan5 pins can be alternatively used
           as fan on/off switches */
+
        data->has_fan = 0x07; /* fan1, fan2 and fan3 */
        i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
-       if (i & (1 << 2))
+       if ((i & (1 << 2)) && (!fan4pin))
                data->has_fan |= (1 << 3);
-       if (i & (1 << 0))
+       if ((i & (1 << 0)) && (!fan5pin))
                data->has_fan |= (1 << 4);
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
-               goto exit_detach;
-       }
+       for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
+               if ((err = device_create_file(dev,
+                       &sda_sf3_arrays[i].dev_attr)))
+                       goto exit_remove;
+
+       /* if fan4 is enabled create the sf3 files for it */
+       if (data->has_fan & (1 << 3))
+               for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
+                       if ((err = device_create_file(dev,
+                               &sda_sf3_arrays_fan4[i].dev_attr)))
+                               goto exit_remove;
+               }
 
        for (i = 0; i < 10; i++)
-               device_create_file_in(dev, i);
+               if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
+                       || (err = device_create_file(dev,
+                               &sda_in_alarm[i].dev_attr))
+                       || (err = device_create_file(dev,
+                               &sda_in_min[i].dev_attr))
+                       || (err = device_create_file(dev,
+                               &sda_in_max[i].dev_attr)))
+                       goto exit_remove;
 
        for (i = 0; i < 5; i++) {
-               if (data->has_fan & (1 << i))
-                       device_create_file_fan(dev, i);
+               if (data->has_fan & (1 << i)) {
+                       if ((err = device_create_file(dev,
+                                       &sda_fan_input[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_fan_alarm[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_fan_div[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_fan_min[i].dev_attr)))
+                               goto exit_remove;
+                       if (i < 4 && /* w83627ehf only has 4 pwm */
+                               ((err = device_create_file(dev,
+                                       &sda_pwm[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_pwm_mode[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_pwm_enable[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_target_temp[i].dev_attr))
+                               || (err = device_create_file(dev,
+                                       &sda_tolerance[i].dev_attr))))
+                               goto exit_remove;
+               }
        }
+
        for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
-               device_create_file(dev, &sda_temp[i].dev_attr);
+               if ((err = device_create_file(dev, &sda_temp[i].dev_attr)))
+                       goto exit_remove;
+
+       data->class_dev = hwmon_device_register(dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove;
+       }
 
        return 0;
 
-exit_detach:
+exit_remove:
+       w83627ehf_device_remove_files(dev);
        i2c_detach_client(client);
 exit_free:
        kfree(data);
@@ -892,6 +1304,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       w83627ehf_device_remove_files(&client->dev);
 
        if ((err = i2c_detach_client(client)))
                return err;
@@ -903,6 +1316,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
 
 static struct i2c_driver w83627ehf_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "w83627ehf",
        },
        .attach_adapter = w83627ehf_detect,
index 79368d53c3634645a4a72b9425dd142df9fc4817..dfdc29c77123a7e0530984f5251f229f000a9f89 100644 (file)
@@ -339,6 +339,7 @@ static void w83627hf_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83627hf_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "w83627hf",
        },
        .attach_adapter = w83627hf_detect,
@@ -511,13 +512,6 @@ static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
        show_regs_in_max0, store_regs_in_max0);
 
-#define device_create_file_in(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-device_create_file(&client->dev, &dev_attr_in##offset##_min); \
-device_create_file(&client->dev, &dev_attr_in##offset##_max); \
-} while (0)
-
 #define show_fan_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -575,12 +569,6 @@ sysfs_fan_min_offset(2);
 sysfs_fan_offset(3);
 sysfs_fan_min_offset(3);
 
-#define device_create_file_fan(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
-} while (0)
-
 #define show_temp_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -655,13 +643,6 @@ sysfs_temp_offsets(1);
 sysfs_temp_offsets(2);
 sysfs_temp_offsets(3);
 
-#define device_create_file_temp(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
-} while (0)
-
 static ssize_t
 show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -669,8 +650,6 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 static ssize_t
 show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -691,8 +670,6 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf
        return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm)
 
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -701,8 +678,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "%ld\n", (long) data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-#define device_create_file_alarms(client) \
-device_create_file(&client->dev, &dev_attr_alarms)
 
 #define show_beep_reg(REG, reg) \
 static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
@@ -765,12 +740,6 @@ static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \
 sysfs_beep(ENABLE, enable);
 sysfs_beep(MASK, mask);
 
-#define device_create_file_beep(client) \
-do { \
-device_create_file(&client->dev, &dev_attr_beep_enable); \
-device_create_file(&client->dev, &dev_attr_beep_mask); \
-} while (0)
-
 static ssize_t
 show_fan_div_reg(struct device *dev, char *buf, int nr)
 {
@@ -836,11 +805,6 @@ sysfs_fan_div(1);
 sysfs_fan_div(2);
 sysfs_fan_div(3);
 
-#define device_create_file_fan_div(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-} while (0)
-
 static ssize_t
 show_pwm_reg(struct device *dev, char *buf, int nr)
 {
@@ -895,11 +859,6 @@ sysfs_pwm(1);
 sysfs_pwm(2);
 sysfs_pwm(3);
 
-#define device_create_file_pwm(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_pwm##offset); \
-} while (0)
-
 static ssize_t
 show_sensor_reg(struct device *dev, char *buf, int nr)
 {
@@ -971,12 +930,6 @@ sysfs_sensor(1);
 sysfs_sensor(2);
 sysfs_sensor(3);
 
-#define device_create_file_sensor(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
-} while (0)
-
-
 static int __init w83627hf_find(int sioaddr, unsigned short *addr)
 {
        u16 val;
@@ -1008,6 +961,85 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr)
        return 0;
 }
 
+static struct attribute *w83627hf_attributes[] = {
+       &dev_attr_in0_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in0_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_in7_input.attr,
+       &dev_attr_in7_min.attr,
+       &dev_attr_in7_max.attr,
+       &dev_attr_in8_input.attr,
+       &dev_attr_in8_min.attr,
+       &dev_attr_in8_max.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_temp1_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_temp1_type.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp2_max_hyst.attr,
+       &dev_attr_temp2_type.attr,
+
+       &dev_attr_alarms.attr,
+       &dev_attr_beep_enable.attr,
+       &dev_attr_beep_mask.attr,
+
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm2.attr,
+
+       NULL
+};
+
+static const struct attribute_group w83627hf_group = {
+       .attrs = w83627hf_attributes,
+};
+
+static struct attribute *w83627hf_attributes_opt[] = {
+       &dev_attr_in1_input.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in1_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,
+
+       &dev_attr_fan3_input.attr,
+       &dev_attr_fan3_min.attr,
+       &dev_attr_fan3_div.attr,
+
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_temp3_max_hyst.attr,
+       &dev_attr_temp3_type.attr,
+
+       &dev_attr_pwm3.attr,
+
+       NULL
+};
+
+static const struct attribute_group w83627hf_group_opt = {
+       .attrs = w83627hf_attributes_opt,
+};
+
 static int w83627hf_detect(struct i2c_adapter *adapter)
 {
        int val, kind;
@@ -1107,62 +1139,72 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
        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));
 
-       /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       /* Register common device attributes */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group)))
                goto ERROR3;
-       }
-
-       device_create_file_in(new_client, 0);
-       if (kind != w83697hf)
-               device_create_file_in(new_client, 1);
-       device_create_file_in(new_client, 2);
-       device_create_file_in(new_client, 3);
-       device_create_file_in(new_client, 4);
-       if (kind == w83627hf || kind == w83697hf) {
-               device_create_file_in(new_client, 5);
-               device_create_file_in(new_client, 6);
-       }
-       device_create_file_in(new_client, 7);
-       device_create_file_in(new_client, 8);
-
-       device_create_file_fan(new_client, 1);
-       device_create_file_fan(new_client, 2);
-       if (kind != w83697hf)
-               device_create_file_fan(new_client, 3);
-
-       device_create_file_temp(new_client, 1);
-       device_create_file_temp(new_client, 2);
-       if (kind != w83697hf)
-               device_create_file_temp(new_client, 3);
 
-       if (kind != w83697hf && data->vid != 0xff) {
-               device_create_file_vid(new_client);
-               device_create_file_vrm(new_client);
-       }
+       /* 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)))
+                       goto ERROR4;
 
-       device_create_file_fan_div(new_client, 1);
-       device_create_file_fan_div(new_client, 2);
        if (kind != w83697hf)
-               device_create_file_fan_div(new_client, 3);
-
-       device_create_file_alarms(new_client);
-
-       device_create_file_beep(new_client);
+               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)))
+                       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)))
+                       goto ERROR4;
 
-       device_create_file_pwm(new_client, 1);
-       device_create_file_pwm(new_client, 2);
        if (kind == w83627thf || kind == w83637hf || kind == w83687thf)
-               device_create_file_pwm(new_client, 3);
+               if ((err = device_create_file(&new_client->dev,
+                                       &dev_attr_pwm3)))
+                       goto ERROR4;
 
-       device_create_file_sensor(new_client, 1);
-       device_create_file_sensor(new_client, 2);
-       if (kind != w83697hf)
-               device_create_file_sensor(new_client, 3);
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR4;
+       }
 
        return 0;
 
+      ERROR4:
+       sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group);
+       sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt);
       ERROR3:
        i2c_detach_client(new_client);
       ERROR2:
@@ -1180,6 +1222,9 @@ static int w83627hf_detach_client(struct i2c_client *client)
 
        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;
 
index 7be469ed0f8f4a41cc30c6ecd48eaf09210fafa8..a4584ec69842fba9910d234fc6c80bb58b2a357f 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/i2c-isa.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
+#include <linux/sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
@@ -288,6 +289,7 @@ static struct i2c_driver w83781d_driver = {
 
 static struct i2c_driver w83781d_isa_driver = {
        .driver = {
+               .owner = THIS_MODULE,
                .name = "w83781d-isa",
        },
        .attach_adapter = w83781d_isa_attach_adapter,
@@ -359,13 +361,6 @@ sysfs_in_offsets(6);
 sysfs_in_offsets(7);
 sysfs_in_offsets(8);
 
-#define device_create_file_in(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_in##offset##_input); \
-device_create_file(&client->dev, &dev_attr_in##offset##_min); \
-device_create_file(&client->dev, &dev_attr_in##offset##_max); \
-} while (0)
-
 #define show_fan_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -420,12 +415,6 @@ sysfs_fan_min_offset(2);
 sysfs_fan_offset(3);
 sysfs_fan_min_offset(3);
 
-#define device_create_file_fan(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
-device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
-} while (0)
-
 #define show_temp_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
@@ -496,13 +485,6 @@ sysfs_temp_offsets(1);
 sysfs_temp_offsets(2);
 sysfs_temp_offsets(3);
 
-#define device_create_file_temp(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
-device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
-} while (0)
-
 static ssize_t
 show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -510,10 +492,8 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 
-static
-DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-#define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_cpu0_vid);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
+
 static ssize_t
 show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -534,10 +514,8 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf
        return count;
 }
 
-static
-DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-#define device_create_file_vrm(client) \
-device_create_file(&client->dev, &dev_attr_vrm);
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
+
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -545,10 +523,8 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "%u\n", data->alarms);
 }
 
-static
-DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-#define device_create_file_alarms(client) \
-device_create_file(&client->dev, &dev_attr_alarms);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+
 static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct w83781d_data *data = w83781d_update_device(dev);
@@ -614,12 +590,6 @@ static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_re
 sysfs_beep(ENABLE, enable);
 sysfs_beep(MASK, mask);
 
-#define device_create_file_beep(client) \
-do { \
-device_create_file(&client->dev, &dev_attr_beep_enable); \
-device_create_file(&client->dev, &dev_attr_beep_mask); \
-} while (0)
-
 static ssize_t
 show_fan_div_reg(struct device *dev, char *buf, int nr)
 {
@@ -685,11 +655,6 @@ sysfs_fan_div(1);
 sysfs_fan_div(2);
 sysfs_fan_div(3);
 
-#define device_create_file_fan_div(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
-} while (0)
-
 static ssize_t
 show_pwm_reg(struct device *dev, char *buf, int nr)
 {
@@ -786,16 +751,6 @@ sysfs_pwmenable(2);                /* only PWM2 can be enabled/disabled */
 sysfs_pwm(3);
 sysfs_pwm(4);
 
-#define device_create_file_pwm(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_pwm##offset); \
-} while (0)
-
-#define device_create_file_pwmenable(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_pwm##offset##_enable); \
-} while (0)
-
 static ssize_t
 show_sensor_reg(struct device *dev, char *buf, int nr)
 {
@@ -864,11 +819,6 @@ sysfs_sensor(1);
 sysfs_sensor(2);
 sysfs_sensor(3);
 
-#define device_create_file_sensor(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
-} while (0)
-
 /* This function is called when:
      * w83781d_driver is inserted (when this module is loaded), for each
        available adapter
@@ -993,11 +943,69 @@ 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 FAN_UNIT_ATTRS(X)                      \
+       &dev_attr_fan##X##_input.attr,          \
+       &dev_attr_fan##X##_min.attr,            \
+       &dev_attr_fan##X##_div.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
+
+static struct attribute* w83781d_attributes[] = {
+       IN_UNIT_ATTRS(0),
+       IN_UNIT_ATTRS(2),
+       IN_UNIT_ATTRS(3),
+       IN_UNIT_ATTRS(4),
+       IN_UNIT_ATTRS(5),
+       IN_UNIT_ATTRS(6),
+       FAN_UNIT_ATTRS(1),
+       FAN_UNIT_ATTRS(2),
+       FAN_UNIT_ATTRS(3),
+       TEMP_UNIT_ATTRS(1),
+       TEMP_UNIT_ATTRS(2),
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_beep_mask.attr,
+       &dev_attr_beep_enable.attr,
+       NULL
+};
+static const struct attribute_group w83781d_group = {
+       .attrs = w83781d_attributes,
+};
+
+static struct attribute *w83781d_attributes_opt[] = {
+       IN_UNIT_ATTRS(1),
+       IN_UNIT_ATTRS(7),
+       IN_UNIT_ATTRS(8),
+       TEMP_UNIT_ATTRS(3),
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm2.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,
+       NULL
+};
+static const struct attribute_group w83781d_group_opt = {
+       .attrs = w83781d_attributes_opt,
+};
+
 static int
 w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i = 0, val1 = 0, val2;
-       struct i2c_client *new_client;
+       struct i2c_client *client;
+       struct device *dev;
        struct w83781d_data *data;
        int err;
        const char *client_name = "";
@@ -1074,13 +1082,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                goto ERROR1;
        }
 
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
        mutex_init(&data->lock);
-       new_client->adapter = adapter;
-       new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
-       new_client->flags = 0;
+       client->adapter = adapter;
+       client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
+       client->flags = 0;
+       dev = &client->dev;
 
        /* Now, we do the remaining detection. */
 
@@ -1089,20 +1098,18 @@ 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(new_client, W83781D_REG_CONFIG) & 0x80) {
-                       dev_dbg(&new_client->dev, "Detection failed at step "
-                               "3\n");
+               if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
+                       dev_dbg(dev, "Detection failed at step 3\n");
                        err = -ENODEV;
                        goto ERROR2;
                }
-               val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
-               val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+               val1 = w83781d_read_value(client, W83781D_REG_BANK);
+               val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
                /* Check for Winbond or Asus ID if in bank 0 */
                if ((!(val1 & 0x07)) &&
                    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
                     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
-                       dev_dbg(&new_client->dev, "Detection failed at step "
-                               "4\n");
+                       dev_dbg(dev, "Detection failed at step 4\n");
                        err = -ENODEV;
                        goto ERROR2;
                }
@@ -1111,9 +1118,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
                                  ((val1 & 0x80) && (val2 == 0x5c)))) {
                        if (w83781d_read_value
-                           (new_client, W83781D_REG_I2C_ADDR) != address) {
-                               dev_dbg(&new_client->dev, "Detection failed "
-                                       "at step 5\n");
+                           (client, W83781D_REG_I2C_ADDR) != address) {
+                               dev_dbg(dev, "Detection failed at step 5\n");
                                err = -ENODEV;
                                goto ERROR2;
                        }
@@ -1122,27 +1128,26 @@ 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(new_client, W83781D_REG_BANK,
-                           (w83781d_read_value(new_client,
-                                               W83781D_REG_BANK) & 0x78) |
-                           0x80);
+       w83781d_write_value(client, W83781D_REG_BANK,
+                           (w83781d_read_value(client, W83781D_REG_BANK)
+                            & 0x78) | 0x80);
 
        /* Determine the chip type. */
        if (kind <= 0) {
                /* get vendor ID */
-               val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+               val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
                if (val2 == 0x5c)
                        vendid = winbond;
                else if (val2 == 0x12)
                        vendid = asus;
                else {
-                       dev_dbg(&new_client->dev, "Chip was made by neither "
+                       dev_dbg(dev, "Chip was made by neither "
                                "Winbond nor Asus?\n");
                        err = -ENODEV;
                        goto ERROR2;
                }
 
-               val1 = w83781d_read_value(new_client, W83781D_REG_WCHIPID);
+               val1 = w83781d_read_value(client, W83781D_REG_WCHIPID);
                if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
                        kind = w83781d;
                else if (val1 == 0x30 && vendid == winbond)
@@ -1156,7 +1161,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                        kind = as99127f;
                else {
                        if (kind == 0)
-                               dev_warn(&new_client->dev, "Ignoring 'force' "
+                               dev_warn(dev, "Ignoring 'force' "
                                         "parameter for unknown chip at "
                                         "adapter %d, address 0x%02x\n",
                                         i2c_adapter_id(adapter), address);
@@ -1178,20 +1183,20 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Fill in the remaining client fields and put into the global list */
-       strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+       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(new_client)))
+       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, new_client)))
+                               kind, client)))
                        goto ERROR3;
        } else {
                data->lm75[0] = NULL;
@@ -1199,11 +1204,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Initialize the chip */
-       w83781d_init_client(new_client);
+       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(new_client,
+               data->fan_min[i - 1] = w83781d_read_value(client,
                                        W83781D_REG_FAN_MIN(i));
        }
        if (kind != w83781d && kind != as99127f)
@@ -1211,65 +1216,68 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                        data->pwmenable[i] = 1;
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
                goto ERROR4;
-       }
 
-       device_create_file_in(new_client, 0);
-       if (kind != w83783s)
-               device_create_file_in(new_client, 1);
-       device_create_file_in(new_client, 2);
-       device_create_file_in(new_client, 3);
-       device_create_file_in(new_client, 4);
-       device_create_file_in(new_client, 5);
-       device_create_file_in(new_client, 6);
+       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) {
-               device_create_file_in(new_client, 7);
-               device_create_file_in(new_client, 8);
+               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;
        }
-
-       device_create_file_fan(new_client, 1);
-       device_create_file_fan(new_client, 2);
-       device_create_file_fan(new_client, 3);
-
-       device_create_file_temp(new_client, 1);
-       device_create_file_temp(new_client, 2);
-       if (kind != w83783s)
-               device_create_file_temp(new_client, 3);
-
-       device_create_file_vid(new_client);
-       device_create_file_vrm(new_client);
-
-       device_create_file_fan_div(new_client, 1);
-       device_create_file_fan_div(new_client, 2);
-       device_create_file_fan_div(new_client, 3);
-
-       device_create_file_alarms(new_client);
-
-       device_create_file_beep(new_client);
 
        if (kind != w83781d && kind != as99127f) {
-               device_create_file_pwm(new_client, 1);
-               device_create_file_pwm(new_client, 2);
-               device_create_file_pwmenable(new_client, 2);
+               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) {
-               device_create_file_pwm(new_client, 3);
-               device_create_file_pwm(new_client, 4);
+               if ((err = device_create_file(dev, &dev_attr_pwm3))
+                   || (err = device_create_file(dev, &dev_attr_pwm4)))
+                       goto ERROR4;
        }
 
        if (kind != as99127f && kind != w83781d) {
-               device_create_file_sensor(new_client, 1);
-               device_create_file_sensor(new_client, 2);
-               if (kind != w83783s)
-                       device_create_file_sensor(new_client, 3);
+               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);
+               goto ERROR4;
        }
 
        return 0;
 
 ERROR4:
+       sysfs_remove_group(&dev->kobj, &w83781d_group);
+       sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
+
        if (data->lm75[1]) {
                i2c_detach_client(data->lm75[1]);
                kfree(data->lm75[1]);
@@ -1279,7 +1287,7 @@ ERROR4:
                kfree(data->lm75[0]);
        }
 ERROR3:
-       i2c_detach_client(new_client);
+       i2c_detach_client(client);
 ERROR2:
        kfree(data);
 ERROR1:
@@ -1296,9 +1304,11 @@ w83781d_detach_client(struct i2c_client *client)
        int err;
 
        /* main client */
-       if (data)
+       if (data) {
                hwmon_device_unregister(data->class_dev);
-
+               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);
 
index eec43abd57fb1e59801d311c95357efac86b2265..d965d074cd61c8ee3c3335dd850acc266f456106 100644 (file)
@@ -27,9 +27,9 @@
 
     The w83791d chip appears to be part way between the 83781d and the
     83792d. Thus, this file is derived from both the w83792d.c and
-    w83781d.c files, but its output is more along the lines of the
-    83781d (which means there are no changes to the user-mode sensors
-    program which treats the 83791d as an 83781d).
+    w83781d.c files.
+
+    The w83791g chip is the same as the w83791d but lead-free.
 */
 
 #include <linux/config.h>
@@ -1172,6 +1172,7 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
                        (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) +
                        (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16);
 
+               /* Extract global beep enable flag */
                data->beep_enable =
                        (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01;
 
index 7576ec9426a35b0e733d08f5552058aa67e9cd73..4e108262576fa9bcf7887b94a21225d14d013d50 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
@@ -381,41 +382,6 @@ static ssize_t store_in_##reg (struct device *dev, \
 store_in_reg(MIN, min);
 store_in_reg(MAX, max);
 
-static struct sensor_device_attribute sda_in_input[] = {
-       SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
-       SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
-       SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
-       SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
-       SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
-       SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
-       SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
-       SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
-       SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
-};
-static struct sensor_device_attribute sda_in_min[] = {
-       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
-       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
-       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
-       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
-       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
-       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
-       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
-       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
-       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
-};
-static struct sensor_device_attribute sda_in_max[] = {
-       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
-       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
-       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
-       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
-       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
-       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
-       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
-       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
-       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
-};
-
-
 #define show_fan_reg(reg) \
 static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
                        char *buf) \
@@ -499,35 +465,6 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute sda_fan_input[] = {
-       SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1),
-       SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2),
-       SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3),
-       SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4),
-       SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5),
-       SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6),
-       SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7),
-};
-static struct sensor_device_attribute sda_fan_min[] = {
-       SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1),
-       SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2),
-       SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3),
-       SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4),
-       SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5),
-       SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6),
-       SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7),
-};
-static struct sensor_device_attribute sda_fan_div[] = {
-       SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1),
-       SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2),
-       SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3),
-       SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4),
-       SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5),
-       SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6),
-       SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7),
-};
-
-
 /* read/write the temperature1, includes measured value and limits */
 
 static ssize_t show_temp1(struct device *dev, struct device_attribute *attr,
@@ -595,24 +532,6 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute_2 sda_temp_input[] = {
-       SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
-       SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
-       SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
-};
-
-static struct sensor_device_attribute_2 sda_temp_max[] = {
-       SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1),
-       SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2),
-       SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2),
-};
-
-static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
-       SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2),
-       SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4),
-       SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4),
-};
-
 /* get reatime status of all sensors items: voltage, temp, fan */
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -621,9 +540,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
        return sprintf(buf, "%d\n", data->alarms);
 }
 
-static
-DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-
 static ssize_t
 show_pwm(struct device *dev, struct device_attribute *attr,
                char *buf)
@@ -715,21 +631,6 @@ store_pwmenable(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute sda_pwm[] = {
-       SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
-       SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
-       SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
-};
-static struct sensor_device_attribute sda_pwm_enable[] = {
-       SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
-                   show_pwmenable, store_pwmenable, 1),
-       SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
-                   show_pwmenable, store_pwmenable, 2),
-       SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
-                   show_pwmenable, store_pwmenable, 3),
-};
-
-
 static ssize_t
 show_pwm_mode(struct device *dev, struct device_attribute *attr,
                        char *buf)
@@ -767,16 +668,6 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute sda_pwm_mode[] = {
-       SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
-                   show_pwm_mode, store_pwm_mode, 0),
-       SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO,
-                   show_pwm_mode, store_pwm_mode, 1),
-       SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO,
-                   show_pwm_mode, store_pwm_mode, 2),
-};
-
-
 static ssize_t
 show_regs_chassis(struct device *dev, struct device_attribute *attr,
                        char *buf)
@@ -785,8 +676,6 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%d\n", data->chassis);
 }
 
-static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
-
 static ssize_t
 show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -815,9 +704,6 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
-               show_chassis_clear, store_chassis_clear);
-
 /* For Smart Fan I / Thermal Cruise */
 static ssize_t
 show_thermal_cruise(struct device *dev, struct device_attribute *attr,
@@ -853,15 +739,6 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute sda_thermal_cruise[] = {
-       SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO,
-                   show_thermal_cruise, store_thermal_cruise, 1),
-       SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO,
-                   show_thermal_cruise, store_thermal_cruise, 2),
-       SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO,
-                   show_thermal_cruise, store_thermal_cruise, 3),
-};
-
 /* For Smart Fan I/Thermal Cruise and Smart Fan II */
 static ssize_t
 show_tolerance(struct device *dev, struct device_attribute *attr,
@@ -901,15 +778,6 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute sda_tolerance[] = {
-       SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO,
-                   show_tolerance, store_tolerance, 1),
-       SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO,
-                   show_tolerance, store_tolerance, 2),
-       SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO,
-                   show_tolerance, store_tolerance, 3),
-};
-
 /* For Smart Fan II */
 static ssize_t
 show_sf2_point(struct device *dev, struct device_attribute *attr,
@@ -946,36 +814,6 @@ store_sf2_point(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute_2 sda_sf2_point[] = {
-       SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 1, 1),
-       SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 2, 1),
-       SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 3, 1),
-       SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 4, 1),
-
-       SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 1, 2),
-       SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 2, 2),
-       SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 3, 2),
-       SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 4, 2),
-
-       SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 1, 3),
-       SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 2, 3),
-       SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 3, 3),
-       SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_point, store_sf2_point, 4, 3),
-};
-
-
 static ssize_t
 show_sf2_level(struct device *dev, struct device_attribute *attr,
                char *buf)
@@ -1016,29 +854,6 @@ store_sf2_level(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct sensor_device_attribute_2 sda_sf2_level[] = {
-       SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 1, 1),
-       SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 2, 1),
-       SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 3, 1),
-
-       SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 1, 2),
-       SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 2, 2),
-       SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 3, 2),
-
-       SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 1, 3),
-       SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 2, 3),
-       SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR,
-                     show_sf2_level, store_sf2_level, 3, 3),
-};
-
 /* This function is called when:
      * w83792d_driver is inserted (when this module is loaded), for each
        available adapter
@@ -1139,12 +954,297 @@ ERROR_SC_0:
        return err;
 }
 
-static void device_create_file_fan(struct device *dev, int i)
-{
-       device_create_file(dev, &sda_fan_input[i].dev_attr);
-       device_create_file(dev, &sda_fan_div[i].dev_attr);
-       device_create_file(dev, &sda_fan_min[i].dev_attr);
-}
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
+static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 0);
+static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 1);
+static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 2);
+static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 3);
+static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 4);
+static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 5);
+static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 6);
+static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 7);
+static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO,
+                       show_in_min, store_in_min, 8);
+static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 0);
+static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 1);
+static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 2);
+static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 3);
+static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 4);
+static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 5);
+static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 6);
+static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 7);
+static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO,
+                       show_in_max, store_in_max, 8);
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
+                       show_temp1, store_temp1, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23,
+                       store_temp23, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23,
+                       store_temp23, 1, 2);
+static SENSOR_DEVICE_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
+                       show_temp1, store_temp1, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
+                       show_temp23, store_temp23, 0, 4);
+static SENSOR_DEVICE_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR,
+                       show_temp23, store_temp23, 1, 4);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
+static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
+                       show_chassis_clear, store_chassis_clear);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+                       show_pwmenable, store_pwmenable, 1);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
+                       show_pwmenable, store_pwmenable, 2);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
+                       show_pwmenable, store_pwmenable, 3);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
+                       show_pwm_mode, store_pwm_mode, 0);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO,
+                       show_pwm_mode, store_pwm_mode, 1);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO,
+                       show_pwm_mode, store_pwm_mode, 2);
+static SENSOR_DEVICE_ATTR(tolerance1, S_IWUSR | S_IRUGO,
+                       show_tolerance, store_tolerance, 1);
+static SENSOR_DEVICE_ATTR(tolerance2, S_IWUSR | S_IRUGO,
+                       show_tolerance, store_tolerance, 2);
+static SENSOR_DEVICE_ATTR(tolerance3, S_IWUSR | S_IRUGO,
+                       show_tolerance, store_tolerance, 3);
+static SENSOR_DEVICE_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO,
+                       show_thermal_cruise, store_thermal_cruise, 1);
+static SENSOR_DEVICE_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO,
+                       show_thermal_cruise, store_thermal_cruise, 2);
+static SENSOR_DEVICE_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO,
+                       show_thermal_cruise, store_thermal_cruise, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 1, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 2, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 3, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 4, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 1, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 2, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 3, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 4, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 1, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 2, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 3, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_point, store_sf2_point, 4, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 1, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 2, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 3, 1);
+static SENSOR_DEVICE_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 1, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 2, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 3, 2);
+static SENSOR_DEVICE_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 1, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 2, 3);
+static SENSOR_DEVICE_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR,
+                       show_sf2_level, store_sf2_level, 3, 3);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 3);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 4);
+static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 5);
+static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 6);
+static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 7);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 1);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 2);
+static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 3);
+static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 4);
+static SENSOR_DEVICE_ATTR(fan5_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 5);
+static SENSOR_DEVICE_ATTR(fan6_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 6);
+static SENSOR_DEVICE_ATTR(fan7_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 7);
+
+static struct attribute *w83792d_attributes_fan[4][4] = {
+       {
+               &sensor_dev_attr_fan4_input.dev_attr.attr,
+               &sensor_dev_attr_fan4_min.dev_attr.attr,
+               &sensor_dev_attr_fan4_div.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_fan5_input.dev_attr.attr,
+               &sensor_dev_attr_fan5_min.dev_attr.attr,
+               &sensor_dev_attr_fan5_div.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_fan6_input.dev_attr.attr,
+               &sensor_dev_attr_fan6_min.dev_attr.attr,
+               &sensor_dev_attr_fan6_div.dev_attr.attr,
+               NULL
+       }, {
+               &sensor_dev_attr_fan7_input.dev_attr.attr,
+               &sensor_dev_attr_fan7_min.dev_attr.attr,
+               &sensor_dev_attr_fan7_div.dev_attr.attr,
+               NULL
+       }
+};
+
+static const struct attribute_group w83792d_group_fan[4] = {
+       { .attrs = w83792d_attributes_fan[0] },
+       { .attrs = w83792d_attributes_fan[1] },
+       { .attrs = w83792d_attributes_fan[2] },
+       { .attrs = w83792d_attributes_fan[3] },
+};
+
+static struct attribute *w83792d_attributes[] = {
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_max.dev_attr.attr,
+       &sensor_dev_attr_in0_min.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_max.dev_attr.attr,
+       &sensor_dev_attr_in1_min.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_max.dev_attr.attr,
+       &sensor_dev_attr_in2_min.dev_attr.attr,
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in5_max.dev_attr.attr,
+       &sensor_dev_attr_in5_min.dev_attr.attr,
+       &sensor_dev_attr_in6_input.dev_attr.attr,
+       &sensor_dev_attr_in6_max.dev_attr.attr,
+       &sensor_dev_attr_in6_min.dev_attr.attr,
+       &sensor_dev_attr_in7_input.dev_attr.attr,
+       &sensor_dev_attr_in7_max.dev_attr.attr,
+       &sensor_dev_attr_in7_min.dev_attr.attr,
+       &sensor_dev_attr_in8_input.dev_attr.attr,
+       &sensor_dev_attr_in8_max.dev_attr.attr,
+       &sensor_dev_attr_in8_min.dev_attr.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,
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+       &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm2.dev_attr.attr,
+       &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+       &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm3.dev_attr.attr,
+       &sensor_dev_attr_pwm3_mode.dev_attr.attr,
+       &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+       &dev_attr_alarms.attr,
+       &dev_attr_chassis.attr,
+       &dev_attr_chassis_clear.attr,
+       &sensor_dev_attr_tolerance1.dev_attr.attr,
+       &sensor_dev_attr_thermal_cruise1.dev_attr.attr,
+       &sensor_dev_attr_tolerance2.dev_attr.attr,
+       &sensor_dev_attr_thermal_cruise2.dev_attr.attr,
+       &sensor_dev_attr_tolerance3.dev_attr.attr,
+       &sensor_dev_attr_thermal_cruise3.dev_attr.attr,
+       &sensor_dev_attr_sf2_point1_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_point2_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_point3_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_point4_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_point1_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_point2_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_point3_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_point4_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_point1_fan3.dev_attr.attr,
+       &sensor_dev_attr_sf2_point2_fan3.dev_attr.attr,
+       &sensor_dev_attr_sf2_point3_fan3.dev_attr.attr,
+       &sensor_dev_attr_sf2_point4_fan3.dev_attr.attr,
+       &sensor_dev_attr_sf2_level1_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_level2_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_level3_fan1.dev_attr.attr,
+       &sensor_dev_attr_sf2_level1_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_level2_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_level3_fan2.dev_attr.attr,
+       &sensor_dev_attr_sf2_level1_fan3.dev_attr.attr,
+       &sensor_dev_attr_sf2_level2_fan3.dev_attr.attr,
+       &sensor_dev_attr_sf2_level3_fan3.dev_attr.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,
+       NULL
+};
+
+static const struct attribute_group w83792d_group = {
+       .attrs = w83792d_attributes,
+};
 
 static int
 w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -1268,59 +1368,46 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       if ((err = sysfs_create_group(&dev->kobj, &w83792d_group)))
                goto ERROR3;
-       }
-       for (i = 0; i < 9; i++) {
-               device_create_file(dev, &sda_in_input[i].dev_attr);
-               device_create_file(dev, &sda_in_max[i].dev_attr);
-               device_create_file(dev, &sda_in_min[i].dev_attr);
-       }
-       for (i = 0; i < 3; i++)
-               device_create_file_fan(dev, i);
 
        /* Read GPIO enable register to check if pins for fan 4,5 are used as
           GPIO */
        val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN);
+
        if (!(val1 & 0x40))
-               device_create_file_fan(dev, 3);
+               if ((err = sysfs_create_group(&dev->kobj,
+                                             &w83792d_group_fan[0])))
+                       goto exit_remove_files;
+
        if (!(val1 & 0x20))
-               device_create_file_fan(dev, 4);
+               if ((err = sysfs_create_group(&dev->kobj,
+                                             &w83792d_group_fan[1])))
+                       goto exit_remove_files;
 
        val1 = w83792d_read_value(client, W83792D_REG_PIN);
        if (val1 & 0x40)
-               device_create_file_fan(dev, 5);
+               if ((err = sysfs_create_group(&dev->kobj,
+                                             &w83792d_group_fan[2])))
+                       goto exit_remove_files;
+
        if (val1 & 0x04)
-               device_create_file_fan(dev, 6);
-
-       for (i = 0; i < 3; i++) {
-               device_create_file(dev, &sda_temp_input[i].dev_attr);
-               device_create_file(dev, &sda_temp_max[i].dev_attr);
-               device_create_file(dev, &sda_temp_max_hyst[i].dev_attr);
-               device_create_file(dev, &sda_thermal_cruise[i].dev_attr);
-               device_create_file(dev, &sda_tolerance[i].dev_attr);
-       }
+               if ((err = sysfs_create_group(&dev->kobj,
+                                             &w83792d_group_fan[3])))
+                       goto exit_remove_files;
 
-       for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) {
-               device_create_file(dev, &sda_pwm[i].dev_attr);
-               device_create_file(dev, &sda_pwm_enable[i].dev_attr);
-               device_create_file(dev, &sda_pwm_mode[i].dev_attr);
+       data->class_dev = hwmon_device_register(dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_remove_files;
        }
 
-       device_create_file(dev, &dev_attr_alarms);
-       device_create_file(dev, &dev_attr_chassis);
-       device_create_file(dev, &dev_attr_chassis_clear);
-
-       for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++)
-               device_create_file(dev, &sda_sf2_point[i].dev_attr);
-
-       for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++)
-               device_create_file(dev, &sda_sf2_level[i].dev_attr);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&dev->kobj, &w83792d_group);
+       for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
+               sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]);
 ERROR3:
        if (data->lm75[0] != NULL) {
                i2c_detach_client(data->lm75[0]);
@@ -1342,11 +1429,16 @@ static int
 w83792d_detach_client(struct i2c_client *client)
 {
        struct w83792d_data *data = i2c_get_clientdata(client);
-       int err;
+       int err, i;
 
        /* main client */
-       if (data)
+       if (data) {
                hwmon_device_unregister(data->class_dev);
+               sysfs_remove_group(&client->dev.kobj, &w83792d_group);
+               for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++)
+                       sysfs_remove_group(&client->dev.kobj,
+                                          &w83792d_group_fan[i]);
+       }
 
        if ((err = i2c_detach_client(client)))
                return err;
index 3f2bac125fb19b8a346c19fde04d6ceded5704e9..a3fcace412f0c41099f243e7349b07932515d84d 100644 (file)
@@ -236,21 +236,30 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
         * Nothing yet, assume it is already started.
         */
 
+       err = device_create_file(&new_client->dev,
+                                &sensor_dev_attr_temp1_input.dev_attr);
+       if (err)
+               goto exit_remove;
+
+       err = device_create_file(&new_client->dev,
+                                &sensor_dev_attr_temp1_max.dev_attr);
+       if (err)
+               goto exit_remove;
+
        /* Register sysfs hooks */
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove;
        }
 
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_input.dev_attr);
-       device_create_file(&new_client->dev,
-                          &sensor_dev_attr_temp1_max.dev_attr);
-
        return 0;
 
-exit_detach:
+exit_remove:
+       device_remove_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_remove_file(&new_client->dev,
+                          &sensor_dev_attr_temp1_max.dev_attr);
        i2c_detach_client(new_client);
 exit_free:
        kfree(data);
@@ -264,7 +273,10 @@ static int w83l785ts_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
-
+       device_remove_file(&client->dev,
+                          &sensor_dev_attr_temp1_input.dev_attr);
+       device_remove_file(&client->dev,
+                          &sensor_dev_attr_temp1_max.dev_attr);
        if ((err = i2c_detach_client(client)))
                return err;
 
index 24383afdda76d4c446445381b91482e0a9938f2b..11935f66fcd8fcf839bafc73c74fbb1eb1a9f009 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Character device configuration
+# I2C subsystem configuration
 #
 
 menu "I2C support"
index 30408015d231fa485157020b477f4ee892389eef..c034820615bb7ff8bdea1d161f3590b3cd6685a7 100644 (file)
@@ -53,12 +53,6 @@ config I2C_ALGO8XX
        tristate "MPC8xx CPM I2C interface"
        depends on 8xx && I2C
 
-config I2C_ALGO_SIBYTE
-       tristate "SiByte SMBus interface"
-       depends on SIBYTE_SB1xxx_SOC && I2C
-       help
-         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
-
 config I2C_ALGO_SGI
        tristate "I2C SGI interfaces"
        depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
index 867fe1f67401c31f3cfabfa598894cdc59d8d70e..208be04a3dbdc6eb097e57a23ad4a4e7bc0d60ed 100644 (file)
@@ -6,7 +6,6 @@ obj-$(CONFIG_I2C_ALGOBIT)       += i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)      += i2c-algo-pcf.o
 obj-$(CONFIG_I2C_ALGOPCA)      += i2c-algo-pca.o
 obj-$(CONFIG_I2C_ALGOITE)      += i2c-algo-ite.o
-obj-$(CONFIG_I2C_ALGO_SIBYTE)  += i2c-algo-sibyte.o
 obj-$(CONFIG_I2C_ALGO_SGI)     += i2c-algo-sgi.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
index ab230c033f9930ce293cf7ae1057db559f60b80e..21c36bfb5e6bf1b25522e7492bef978e29a8bde0 100644 (file)
@@ -76,17 +76,15 @@ static inline void scllo(struct i2c_algo_bit_data *adap)
  * Raise scl line, and do checking for delays. This is necessary for slower
  * devices.
  */
-static inline int sclhi(struct i2c_algo_bit_data *adap)
+static int sclhi(struct i2c_algo_bit_data *adap)
 {
        unsigned long start;
 
        setscl(adap,1);
 
        /* Not all adapters have scl sense line... */
-       if (adap->getscl == NULL ) {
-               udelay(adap->udelay);
-               return 0;
-       }
+       if (!adap->getscl)
+               goto done;
 
        start=jiffies;
        while (! getscl(adap) ) {       
@@ -101,6 +99,8 @@ static inline int sclhi(struct i2c_algo_bit_data *adap)
                cond_resched();
        }
        DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
+
+done:
        udelay(adap->udelay);
        return 0;
 } 
@@ -121,7 +121,6 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
        DEBPROTO(printk(" Sr "));
        setsda(adap,1);
        sclhi(adap);
-       udelay(adap->udelay);
        
        sdalo(adap);
        scllo(adap);
@@ -306,7 +305,7 @@ bailout:
  * 0 chip did not answer
  * -x transmission error
  */
-static inline int try_address(struct i2c_adapter *i2c_adap,
+static int try_address(struct i2c_adapter *i2c_adap,
                       unsigned char addr, int retries)
 {
        struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
@@ -354,15 +353,11 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        return (retval<0)? retval : -EFAULT;
                                /* got a better one ?? */
                }
-#if 0
-               /* from asm/delay.h */
-               __delay(adap->mdelay * (loops_per_sec / 1000) );
-#endif
        }
        return wrcount;
 }
 
-static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
        int inval;
        int rdcount=0;          /* counts bytes read */
@@ -412,7 +407,7 @@ static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
  * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
  *     -ETIMEDOUT, for example if the lines are stuck...) 
  */
-static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) 
+static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
        unsigned short flags = msg->flags;
        unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
@@ -517,7 +512,7 @@ static u32 bit_func(struct i2c_adapter *adap)
 
 /* -----exported algorithm data: ------------------------------------- */
 
-static struct i2c_algorithm i2c_bit_algo = {
+static const struct i2c_algorithm i2c_bit_algo = {
        .master_xfer    = bit_xfer,
        .functionality  = bit_func,
 };
index b88a6fcf7bd094abf75c67ba940cefe0fbd9ce58..9081c9fbcd2940a84f82827ee39ba60f1e08d086 100644 (file)
@@ -355,7 +355,7 @@ static int pca_init(struct i2c_algo_pca_data *adap)
        return 0;
 }
 
-static struct i2c_algorithm pca_algo = {
+static const struct i2c_algorithm pca_algo = {
        .master_xfer    = pca_xfer,
        .functionality  = pca_func,
 };
index 5b24930adb5a7b9e23721f47aca79daa7b450d04..3b2003398966910ec80236ccef17a41e6fe0c71f 100644 (file)
@@ -458,7 +458,7 @@ static u32 pcf_func(struct i2c_adapter *adap)
 
 /* -----exported algorithm data: ------------------------------------- */
 
-static struct i2c_algorithm pcf_algo = {
+static const struct i2c_algorithm pcf_algo = {
        .master_xfer    = pcf_xfer,
        .functionality  = pcf_func,
 };
index 932c4fa86c7374eb9cf667ab14a8d20cc94adcbf..490d99997fd098ffd9aa65f5321cfc2700bc2f65 100644 (file)
@@ -157,7 +157,7 @@ static u32 sgi_func(struct i2c_adapter *adap)
        return I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm sgi_algo = {
+static const struct i2c_algorithm sgi_algo = {
        .master_xfer    = sgi_xfer,
        .functionality  = sgi_func,
 };
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
deleted file mode 100644 (file)
index 32d41c6..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters                   */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 2001,2002,2003 Broadcom Corporation
-     Copyright (C) 1995-2000 Simon G. Vogl
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
-   Frodo Looijaard <frodol@dds.nl>.  */
-
-/* Ported for SiByte SOCs by Broadcom Corporation.  */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-sibyte.h>
-
-/* ----- global defines ----------------------------------------------- */
-#define SMB_CSR(a,r) ((long)(a->reg_base + r))
-
-/* ----- global variables ---------------------------------------------        */
-
-/* module parameters:
- */
-static int bit_scan;   /* have a look at what's hanging 'round         */
-
-
-static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, 
-                      unsigned short flags, char read_write,
-                      u8 command, int size, union i2c_smbus_data * data)
-{
-       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
-        int data_bytes = 0;
-        int error;
-
-        while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        switch (size) {
-        case I2C_SMBUS_QUICK:
-                csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
-                          V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
-                break;
-        case I2C_SMBUS_BYTE:
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 1;
-                } else {
-                        csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        case I2C_SMBUS_BYTE_DATA:
-                csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 1;
-                } else {
-                        csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        case I2C_SMBUS_WORD_DATA:
-                csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 2;
-                } else {
-                        csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        default:
-                return -1;      /* XXXKW better error code? */
-        }
-
-        while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
-        if (error & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
-                return -1;      /* XXXKW better error code? */
-        }
-
-        if (data_bytes == 1)
-                data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
-        if (data_bytes == 2)
-                data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
-
-        return 0;
-}
-
-static int algo_control(struct i2c_adapter *adapter, 
-       unsigned int cmd, unsigned long arg)
-{
-       return 0;
-}
-
-static u32 bit_func(struct i2c_adapter *adap)
-{
-       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
-                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
-}
-
-
-/* -----exported algorithm data: ------------------------------------- */
-
-static struct i2c_algorithm i2c_sibyte_algo = {
-       .smbus_xfer     = smbus_xfer,
-       .algo_control   = algo_control, /* ioctl */
-       .functionality  = bit_func,
-};
-
-/* 
- * registering functions to load algorithms at runtime 
- */
-int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
-{
-       int i;
-       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
-
-       /* register new adapter to i2c module... */
-       i2c_adap->algo = &i2c_sibyte_algo;
-        
-        /* Set the frequency to 100 kHz */
-        csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
-        csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
-
-       /* scan bus */
-       if (bit_scan) {
-                union i2c_smbus_data data;
-                int rc;
-               printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
-                      i2c_adap->name);
-               for (i = 0x00; i < 0x7f; i++) {
-                        /* XXXKW is this a realistic probe? */
-                        rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
-                                        I2C_SMBUS_BYTE_DATA, &data);
-                       if (!rc) {
-                               printk("(%02x)",i); 
-                       } else 
-                               printk("."); 
-               }
-               printk("\n");
-       }
-
-       return i2c_add_adapter(i2c_adap);
-}
-
-
-int i2c_sibyte_del_bus(struct i2c_adapter *adap)
-{
-       int res;
-
-       if ((res = i2c_del_adapter(adap)) < 0)
-               return res;
-
-       return 0;
-}
-
-int __init i2c_algo_sibyte_init (void)
-{
-       printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n");
-       return 0;
-}
-
-
-EXPORT_SYMBOL(i2c_sibyte_add_bus);
-EXPORT_SYMBOL(i2c_sibyte_del_bus);
-
-#ifdef MODULE
-MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
-MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
-module_param(bit_scan, int, 0);
-MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
-MODULE_LICENSE("GPL");
-
-int init_module(void) 
-{
-       return i2c_algo_sibyte_init();
-}
-
-void cleanup_module(void) 
-{
-}
-#endif
index 884320e70403f0776b891e99332e6808f190a128..0d9667921f618494f1dba82f5b1674ff18bf1c4c 100644 (file)
@@ -75,11 +75,11 @@ config I2C_AMD8111
          will be called i2c-amd8111.
 
 config I2C_AU1550
-       tristate "Au1550 SMBus interface"
-       depends on I2C && SOC_AU1550
+       tristate "Au1550/Au1200 SMBus interface"
+       depends on I2C && (SOC_AU1550 || SOC_AU1200)
        help
          If you say yes to this option, support will be included for the
-         Au1550 SMBus interface.
+         Au1550 and Au1200 SMBus interface.
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-au1550.
@@ -196,7 +196,7 @@ config I2C_IBM_IIC
 
 config I2C_IOP3XX
        tristate "Intel IOP3xx and IXP4xx on-chip I2C interface"
-       depends on (ARCH_IOP3XX || ARCH_IXP4XX) && I2C
+       depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX) && I2C
        help
          Say Y here if you want to use the IIC bus controller on
          the Intel IOP3xx I/O Processors or IXP4xx Network Processors.
@@ -287,6 +287,16 @@ config I2C_OCORES
          This driver can also be built as a module.  If so, the module
          will be called i2c-ocores.
 
+config I2C_OMAP
+       tristate "OMAP I2C adapter"
+       depends on I2C && ARCH_OMAP
+       default y if MACH_OMAP_H3 || MACH_OMAP_OSK
+       help
+         If you say yes to this option, support will be included for the
+         I2C interface on the Texas Instruments OMAP1/2 family of processors.
+         Like OMAP1510/1610/1710/5912 and OMAP242x.
+         For details see http://www.ti.com/omap.
+
 config I2C_PARPORT
        tristate "Parallel port adapter"
        depends on I2C && PARPORT
@@ -482,19 +492,19 @@ config I2C_VIA
          will be called i2c-via.
 
 config I2C_VIAPRO
-       tristate "VIA 82C596/82C686/823x"
+       tristate "VIA 82C596/82C686/82xx"
        depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the VIA
-         82C596/82C686/823x I2C interfaces.  Specifically, the following 
+         82C596/82C686/82xx I2C interfaces.  Specifically, the following
          chipsets are supported:
-         82C596A/B
-         82C686A/B
-         8231
-         8233
-         8233A
-         8235
-         8237
+           VT82C596A/B
+           VT82C686A/B
+           VT8231
+           VT8233/A
+           VT8235
+           VT8237R/A
+           VT8251
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-viapro.
index ac56df53155baf0f0fa95bd9c2e8c5fec0d699ae..493c87289b6262fa0a02c46d19970479df71e9ab 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_I2C_MPC)         += i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)      += i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)      += i2c-nforce2.o
 obj-$(CONFIG_I2C_OCORES)       += i2c-ocores.o
+obj-$(CONFIG_I2C_OMAP)         += i2c-omap.o
 obj-$(CONFIG_I2C_PARPORT)      += i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)        += i2c-parport-light.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
index d3ef46aeeb3ca5eb5a365d5a507f16146ecaba1b..e75d339a3481e9dcd03acb7dda20d14ba73352ae 100644 (file)
@@ -468,7 +468,7 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = ali1535_access,
        .functionality  = ali1535_func,
 };
index e6f63208fc4a631df15682ed6a32c3c5f68793bd..33fbb47100a36d02a45492cc8233301d66c4b7c1 100644 (file)
@@ -367,7 +367,7 @@ static void ali1563_shutdown(struct pci_dev *dev)
        release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
 }
 
-static struct i2c_algorithm ali1563_algorithm = {
+static const struct i2c_algorithm ali1563_algorithm = {
        .smbus_xfer     = ali1563_access,
        .functionality  = ali1563_func,
 };
index 7a5c0941dbc13f396aaabaf5881f48eb0650761c..3f11b6e1a3418c5bc5dad86681b7eae67c429af7 100644 (file)
@@ -463,7 +463,7 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = ali15x3_access,
        .functionality  = ali15x3_func,
 };
index 1750dedaf4b5620a553455778efd62d3bf9ca2fd..2d21afdc5b1cc7f3961c3e4f480de0444ec4292f 100644 (file)
@@ -294,7 +294,7 @@ static u32 amd756_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = amd756_access,
        .functionality  = amd756_func,
 };
index e5ef560e686ae8c5f8bdab1b8a2d38e0d90e933f..0fbc7186c91ab63f8ac8f6b32365db3a850efc6f 100644 (file)
@@ -316,7 +316,7 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer = amd8111_access,
        .functionality = amd8111_func,
 };
index d06edce03bf40dd83604708018d4ce5165cd852f..d7e7c359fc364831a9ad1a0bed6001f2e88d9b41 100644 (file)
@@ -34,8 +34,7 @@
 #include <linux/errno.h>
 #include <linux/i2c.h>
 
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-pb1x00/pb1550.h>
+#include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
 #include "i2c-au1550.h"
@@ -118,13 +117,19 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
 
        /* Reset the FIFOs, clear events.
        */
-       sp->psc_smbpcr = PSC_SMBPCR_DC;
+       stat = sp->psc_smbstat;
        sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
        au_sync();
-       do {
-               stat = sp->psc_smbpcr;
+
+       if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
+               sp->psc_smbpcr = PSC_SMBPCR_DC;
                au_sync();
-       } while ((stat & PSC_SMBPCR_DC) != 0);
+               do {
+                       stat = sp->psc_smbpcr;
+                       au_sync();
+               } while ((stat & PSC_SMBPCR_DC) != 0);
+               udelay(50);
+       }
 
        /* Write out the i2c chip address and specify operation
        */
@@ -279,10 +284,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 static u32
 au1550_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C;
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm au1550_algo = {
+static const struct i2c_algorithm au1550_algo = {
        .master_xfer    = au1550_xfer,
        .functionality  = au1550_func,
 };
index 59f8308c2356cc834f9015074bfb196b4e09312b..caa8e5c8bfbbdc6f8d4cfc844b59237466867e6d 100644 (file)
@@ -196,7 +196,6 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
        .getclock   = pcf_isa_getclock,
        .waitforpin = pcf_isa_waitforpin,
        .udelay     = 10,
-       .mdelay     = 10,
        .timeout    = 100,
 };
 
index e0cb3b0f92faba50a64d40f437188f106aaa9c57..457d48a0ab9dcf0c3993917df67ccf924c899cd7 100644 (file)
@@ -99,7 +99,6 @@ static struct i2c_algo_bit_data hydra_bit_data = {
        .getsda         = hydra_bit_getsda,
        .getscl         = hydra_bit_getscl,
        .udelay         = 5,
-       .mdelay         = 5,
        .timeout        = HZ
 };
 
index 7be1d0a3e8f8f59856562013e1b6361d569c6510..bbb2fbee836fe45c855dfef454a66cecd560b213 100644 (file)
@@ -434,7 +434,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
             | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = i801_access,
        .functionality  = i801_func,
 };
index 748be30f2bae3d740d35914dba90ba72f7b7f3bc..b66fb6bb18700d78068d1ee845ce392c27dce388 100644 (file)
@@ -166,7 +166,6 @@ static struct i2c_algo_bit_data i810_i2c_bit_data = {
        .getsda         = bit_i810i2c_getsda,
        .getscl         = bit_i810i2c_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT,
 };
 
@@ -182,7 +181,6 @@ static struct i2c_algo_bit_data i810_ddc_bit_data = {
        .getsda         = bit_i810ddc_getsda,
        .getscl         = bit_i810ddc_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT,
 };
 
index 0599bbd65d93b196fd946b1f270b89af48932730..5bccb5d68318b6ea5fdfc0387a3136138d8bb20b 100644 (file)
@@ -625,7 +625,7 @@ static u32 iic_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
 }
 
-static struct i2c_algorithm iic_algo = {
+static const struct i2c_algorithm iic_algo = {
        .master_xfer    = iic_xfer,
        .functionality  = iic_func
 };
index 48c56939c8619abaae4e6289fb86cd2856d03921..4436c89be58eb838c6b05dba1ecffecbc8fb18b0 100644 (file)
@@ -82,14 +82,16 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
 
        /* 
         * Every time unit enable is asserted, GPOD needs to be cleared
-        * on IOP321 to avoid data corruption on the bus.
+        * on IOP3XX to avoid data corruption on the bus.
         */
-#ifdef CONFIG_ARCH_IOP321
-#define IOP321_GPOD_I2C0    0x00c0  /* clear these bits to enable ch0 */
-#define IOP321_GPOD_I2C1    0x0030  /* clear these bits to enable ch1 */
-
-       *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 : 
-               ~IOP321_GPOD_I2C1;
+#ifdef CONFIG_PLAT_IOP
+       if (iop3xx_adap->id == 0) {
+               gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
+               gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
+       } else {
+               gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW);
+               gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW);
+       }
 #endif
        /* NB SR bits not same position as CR IE bits :-( */
        iop3xx_adap->SR_enabled = 
@@ -401,7 +403,7 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm iop3xx_i2c_algo = {
+static const struct i2c_algorithm iop3xx_i2c_algo = {
        .master_xfer    = iop3xx_i2c_master_xfer,
        .algo_control   = iop3xx_i2c_algo_control,
        .functionality  = iop3xx_i2c_func,
index c3e1d3e888d7b25c20d90ae4a7ecb8f5be420b98..4380653748a4c155065bb057148f91e1e1b7eddd 100644 (file)
@@ -43,7 +43,7 @@
 static u32 isa_func(struct i2c_adapter *adapter);
 
 /* This is the actual algorithm we define */
-static struct i2c_algorithm isa_algorithm = {
+static const struct i2c_algorithm isa_algorithm = {
        .functionality  = isa_func,
 };
 
@@ -89,9 +89,14 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
        dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
 
        /* Now look for clients */
-       driver->attach_adapter(&isa_adapter);
-
-       return 0;
+       res = driver->attach_adapter(&isa_adapter);
+       if (res) {
+               dev_err(&isa_adapter.dev,
+                       "Driver %s failed to attach adapter, unregistering\n",
+                       driver->driver.name);
+               driver_unregister(&driver->driver);
+       }
+       return res;
 }
 
 int i2c_isa_del_driver(struct i2c_driver *driver)
@@ -125,6 +130,8 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
 
 static int __init i2c_isa_init(void)
 {
+       int err;
+
        mutex_init(&isa_adapter.clist_lock);
        INIT_LIST_HEAD(&isa_adapter.clients);
 
@@ -133,8 +140,16 @@ static int __init i2c_isa_init(void)
        sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
        isa_adapter.dev.driver = &i2c_adapter_driver;
        isa_adapter.dev.release = &i2c_adapter_dev_release;
-       device_register(&isa_adapter.dev);
-       device_create_file(&isa_adapter.dev, &dev_attr_name);
+       err = device_register(&isa_adapter.dev);
+       if (err) {
+               printk(KERN_ERR "i2c-isa: Failed to register device\n");
+               goto exit;
+       }
+       err = device_create_file(&isa_adapter.dev, &dev_attr_name);
+       if (err) {
+               printk(KERN_ERR "i2c-isa: Failed to create name file\n");
+               goto exit_unregister;
+       }
 
        /* Add this adapter to the i2c_adapter class */
        memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
@@ -142,11 +157,24 @@ static int __init i2c_isa_init(void)
        isa_adapter.class_dev.class = &i2c_adapter_class;
        strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
                BUS_ID_SIZE);
-       class_device_register(&isa_adapter.class_dev);
+       err = class_device_register(&isa_adapter.class_dev);
+       if (err) {
+               printk(KERN_ERR "i2c-isa: Failed to register class device\n");
+               goto exit_remove_name;
+       }
 
        dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
 
        return 0;
+
+exit_remove_name:
+       device_remove_file(&isa_adapter.dev, &dev_attr_name);
+exit_unregister:
+       init_completion(&isa_adapter.dev_released); /* Needed? */
+       device_unregister(&isa_adapter.dev);
+       wait_for_completion(&isa_adapter.dev_released);
+exit:
+       return err;
 }
 
 static void __exit i2c_isa_exit(void)
index d82e6dae84070951f625622229154cb32d3f2333..559a62b04ee9aa0269c69ae6104725b53aabe783 100644 (file)
@@ -109,7 +109,7 @@ static int iic_ite_getclock(void *data)
 static void iic_ite_waitforpin(void) {
    DEFINE_WAIT(wait);
    int timeout = 2;
-   long flags;
+   unsigned long flags;
 
    /* If interrupts are enabled (which they are), then put the process to
     * sleep.  This process will be awakened by two events -- either the
index cd6f45d186ab4d6a3b51ade91cf7bbb8f68a4f3a..dd3f4cd3aa6849cc7945b379705608f18d1f72a2 100644 (file)
@@ -114,7 +114,6 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
        drv_data->algo_data.getsda = ixp2000_bit_getsda;
        drv_data->algo_data.getscl = ixp2000_bit_getscl;
        drv_data->algo_data.udelay = 6;
-       drv_data->algo_data.mdelay = 6;
        drv_data->algo_data.timeout = 100;
 
        drv_data->adapter.id = I2C_HW_B_IXP2000,
index 2ed07112d683fa7cd1c72b0a31a7e95c6645543d..ab573254a8aa305c1703f4005b9477e296819397 100644 (file)
@@ -122,7 +122,6 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
        drv_data->algo_data.getsda = ixp4xx_bit_getsda;
        drv_data->algo_data.getscl = ixp4xx_bit_getscl;
        drv_data->algo_data.udelay = 10;
-       drv_data->algo_data.mdelay = 10;
        drv_data->algo_data.timeout = 100;
 
        drv_data->adapter.id = I2C_HW_B_IXP4XX;
index 377ab40944b8d3cbecfc02ab3c0fe1fb7673ec7c..155a986de516616d2ed5d70074cb28240a1878dd 100644 (file)
@@ -272,7 +272,7 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm mpc_algo = {
+static const struct i2c_algorithm mpc_algo = {
        .master_xfer = mpc_xfer,
        .functionality = mpc_functionality,
 };
index ac5cde1bbd2ba24333d2360ce3b253d60a3426c8..eacbaf745b64527798c74fc5ddd48acdbd8e11b6 100644 (file)
@@ -431,7 +431,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        return num;
 }
 
-static struct i2c_algorithm mv64xxx_i2c_algo = {
+static const struct i2c_algorithm mv64xxx_i2c_algo = {
        .master_xfer = mv64xxx_i2c_xfer,
        .functionality = mv64xxx_i2c_functionality,
 };
index 604b49e22df144748da5b9e4b29a8c53287bec7c..e0292e414ab2ccadb5110cc6e94af0827b0adcce 100644 (file)
@@ -109,7 +109,7 @@ static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
 static u32 nforce2_func(struct i2c_adapter *adapter);
 
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer = nforce2_access,
        .functionality = nforce2_func,
 };
index 592824087c490d4c488fbf1b9841701fb18c9eb4..952a28d485ce9e593b26f6d7d4b7336582c11564 100644 (file)
@@ -199,7 +199,7 @@ static u32 ocores_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm ocores_algorithm = {
+static const struct i2c_algorithm ocores_algorithm = {
        .master_xfer    = ocores_xfer,
        .functionality  = ocores_func,
 };
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
new file mode 100644 (file)
index 0000000..81d87d2
--- /dev/null
@@ -0,0 +1,676 @@
+/*
+ * TI OMAP I2C master mode driver
+ *
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Updated to work with multiple I2C interfaces on 24xx by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Cleaned up 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
+ * 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/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+/* timeout waiting for the controller to respond */
+#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+#define OMAP_I2C_REV_REG               0x00
+#define OMAP_I2C_IE_REG                        0x04
+#define OMAP_I2C_STAT_REG              0x08
+#define OMAP_I2C_IV_REG                        0x0c
+#define OMAP_I2C_SYSS_REG              0x10
+#define OMAP_I2C_BUF_REG               0x14
+#define OMAP_I2C_CNT_REG               0x18
+#define OMAP_I2C_DATA_REG              0x1c
+#define OMAP_I2C_SYSC_REG              0x20
+#define OMAP_I2C_CON_REG               0x24
+#define OMAP_I2C_OA_REG                        0x28
+#define OMAP_I2C_SA_REG                        0x2c
+#define OMAP_I2C_PSC_REG               0x30
+#define OMAP_I2C_SCLL_REG              0x34
+#define OMAP_I2C_SCLH_REG              0x38
+#define OMAP_I2C_SYSTEST_REG           0x3c
+
+/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XRDY       (1 << 4)        /* TX data ready int enable */
+#define OMAP_I2C_IE_RRDY       (1 << 3)        /* RX data ready int enable */
+#define OMAP_I2C_IE_ARDY       (1 << 2)        /* Access ready int enable */
+#define OMAP_I2C_IE_NACK       (1 << 1)        /* No ack interrupt enable */
+#define OMAP_I2C_IE_AL         (1 << 0)        /* Arbitration lost int ena */
+
+/* I2C Status Register (OMAP_I2C_STAT): */
+#define OMAP_I2C_STAT_SBD      (1 << 15)       /* Single byte data */
+#define OMAP_I2C_STAT_BB       (1 << 12)       /* Bus busy */
+#define OMAP_I2C_STAT_ROVR     (1 << 11)       /* Receive overrun */
+#define OMAP_I2C_STAT_XUDF     (1 << 10)       /* Transmit underflow */
+#define OMAP_I2C_STAT_AAS      (1 << 9)        /* Address as slave */
+#define OMAP_I2C_STAT_AD0      (1 << 8)        /* Address zero */
+#define OMAP_I2C_STAT_XRDY     (1 << 4)        /* Transmit data ready */
+#define OMAP_I2C_STAT_RRDY     (1 << 3)        /* Receive data ready */
+#define OMAP_I2C_STAT_ARDY     (1 << 2)        /* Register access ready */
+#define OMAP_I2C_STAT_NACK     (1 << 1)        /* No ack interrupt enable */
+#define OMAP_I2C_STAT_AL       (1 << 0)        /* Arbitration lost int ena */
+
+/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
+#define OMAP_I2C_BUF_RDMA_EN   (1 << 15)       /* RX DMA channel enable */
+#define OMAP_I2C_BUF_XDMA_EN   (1 << 7)        /* TX DMA channel enable */
+
+/* I2C Configuration Register (OMAP_I2C_CON): */
+#define OMAP_I2C_CON_EN                (1 << 15)       /* I2C module enable */
+#define OMAP_I2C_CON_BE                (1 << 14)       /* Big endian mode */
+#define OMAP_I2C_CON_STB       (1 << 11)       /* Start byte mode (master) */
+#define OMAP_I2C_CON_MST       (1 << 10)       /* Master/slave mode */
+#define OMAP_I2C_CON_TRX       (1 << 9)        /* TX/RX mode (master only) */
+#define OMAP_I2C_CON_XA                (1 << 8)        /* Expand address */
+#define OMAP_I2C_CON_RM                (1 << 2)        /* Repeat mode (master only) */
+#define OMAP_I2C_CON_STP       (1 << 1)        /* Stop cond (master only) */
+#define OMAP_I2C_CON_STT       (1 << 0)        /* Start condition (master) */
+
+/* I2C System Test Register (OMAP_I2C_SYSTEST): */
+#ifdef DEBUG
+#define OMAP_I2C_SYSTEST_ST_EN         (1 << 15)       /* System test enable */
+#define OMAP_I2C_SYSTEST_FREE          (1 << 14)       /* Free running mode */
+#define OMAP_I2C_SYSTEST_TMODE_MASK    (3 << 12)       /* Test mode select */
+#define OMAP_I2C_SYSTEST_TMODE_SHIFT   (12)            /* Test mode select */
+#define OMAP_I2C_SYSTEST_SCL_I         (1 << 3)        /* SCL line sense in */
+#define OMAP_I2C_SYSTEST_SCL_O         (1 << 2)        /* SCL line drive out */
+#define OMAP_I2C_SYSTEST_SDA_I         (1 << 1)        /* SDA line sense in */
+#define OMAP_I2C_SYSTEST_SDA_O         (1 << 0)        /* SDA line drive out */
+#endif
+
+/* I2C System Status register (OMAP_I2C_SYSS): */
+#define OMAP_I2C_SYSS_RDONE            (1 << 0)        /* Reset Done */
+
+/* I2C System Configuration Register (OMAP_I2C_SYSC): */
+#define OMAP_I2C_SYSC_SRST             (1 << 1)        /* Soft Reset */
+
+/* REVISIT: Use platform_data instead of module parameters */
+/* Fast Mode = 400 kHz, Standard = 100 kHz */
+static int clock = 100; /* Default: 100 kHz */
+module_param(clock, int, 0);
+MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
+
+struct omap_i2c_dev {
+       struct device           *dev;
+       void __iomem            *base;          /* virtual */
+       int                     irq;
+       struct clk              *iclk;          /* Interface clock */
+       struct clk              *fclk;          /* Functional clock */
+       struct completion       cmd_complete;
+       struct resource         *ioarea;
+       u16                     cmd_err;
+       u8                      *buf;
+       size_t                  buf_len;
+       struct i2c_adapter      adapter;
+       unsigned                rev1:1;
+};
+
+static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
+                                     int reg, u16 val)
+{
+       __raw_writew(val, i2c_dev->base + reg);
+}
+
+static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
+{
+       return __raw_readw(i2c_dev->base + reg);
+}
+
+static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+{
+       if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+               dev->iclk = clk_get(dev->dev, "i2c_ick");
+               if (IS_ERR(dev->iclk)) {
+                       dev->iclk = NULL;
+                       return -ENODEV;
+               }
+       }
+
+       dev->fclk = clk_get(dev->dev, "i2c_fck");
+       if (IS_ERR(dev->fclk)) {
+               if (dev->iclk != NULL) {
+                       clk_put(dev->iclk);
+                       dev->iclk = NULL;
+               }
+               dev->fclk = NULL;
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
+{
+       clk_put(dev->fclk);
+       dev->fclk = NULL;
+       if (dev->iclk != NULL) {
+               clk_put(dev->iclk);
+               dev->iclk = NULL;
+       }
+}
+
+static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev)
+{
+       if (dev->iclk != NULL)
+               clk_enable(dev->iclk);
+       clk_enable(dev->fclk);
+}
+
+static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
+{
+       if (dev->iclk != NULL)
+               clk_disable(dev->iclk);
+       clk_disable(dev->fclk);
+}
+
+static int omap_i2c_init(struct omap_i2c_dev *dev)
+{
+       u16 psc = 0;
+       unsigned long fclk_rate = 12000000;
+       unsigned long timeout;
+
+       if (!dev->rev1) {
+               omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+               /* For some reason we need to set the EN bit before the
+                * reset done bit gets set. */
+               timeout = jiffies + OMAP_I2C_TIMEOUT;
+               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+               while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
+                        OMAP_I2C_SYSS_RDONE)) {
+                       if (time_after(jiffies, timeout)) {
+                               dev_warn(dev->dev, "timeout waiting"
+                                               "for controller reset\n");
+                               return -ETIMEDOUT;
+                       }
+                       msleep(1);
+               }
+       }
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+
+       if (cpu_class_is_omap1()) {
+               struct clk *armxor_ck;
+
+               armxor_ck = clk_get(NULL, "armxor_ck");
+               if (IS_ERR(armxor_ck))
+                       dev_warn(dev->dev, "Could not get armxor_ck\n");
+               else {
+                       fclk_rate = clk_get_rate(armxor_ck);
+                       clk_put(armxor_ck);
+               }
+               /* TRM for 5912 says the I2C clock must be prescaled to be
+                * between 7 - 12 MHz. The XOR input clock is typically
+                * 12, 13 or 19.2 MHz. So we should have code that produces:
+                *
+                * XOR MHz      Divider         Prescaler
+                * 12           1               0
+                * 13           2               1
+                * 19.2         2               1
+                */
+               if (fclk_rate > 16000000)
+                       psc = (fclk_rate + 8000000) / 12000000;
+       }
+
+       /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+       omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
+
+       /* Program desired operating rate */
+       fclk_rate /= (psc + 1) * 1000;
+       if (psc > 2)
+               psc = 2;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
+                          fclk_rate / (clock * 2) - 7 + psc);
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
+                          fclk_rate / (clock * 2) - 7 + psc);
+
+       /* Take the I2C module out of reset: */
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+
+       /* Enable interrupts */
+       omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
+                          (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+                           OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+                           OMAP_I2C_IE_AL));
+       return 0;
+}
+
+/*
+ * Waiting on Bus Busy
+ */
+static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + OMAP_I2C_TIMEOUT;
+       while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
+               if (time_after(jiffies, timeout)) {
+                       dev_warn(dev->dev, "timeout waiting for bus ready\n");
+                       return -ETIMEDOUT;
+               }
+               msleep(1);
+       }
+
+       return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
+                            struct i2c_msg *msg, int stop)
+{
+       struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+       int r;
+       u16 w;
+
+       dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+               msg->addr, msg->len, msg->flags, stop);
+
+       if (msg->len == 0)
+               return -EINVAL;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
+
+       /* REVISIT: Could the STB bit of I2C_CON be used with probing? */
+       dev->buf = msg->buf;
+       dev->buf_len = msg->len;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+
+       init_completion(&dev->cmd_complete);
+       dev->cmd_err = 0;
+
+       w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+       if (msg->flags & I2C_M_TEN)
+               w |= OMAP_I2C_CON_XA;
+       if (!(msg->flags & I2C_M_RD))
+               w |= OMAP_I2C_CON_TRX;
+       if (stop)
+               w |= OMAP_I2C_CON_STP;
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+
+       r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+                                                     OMAP_I2C_TIMEOUT);
+       dev->buf_len = 0;
+       if (r < 0)
+               return r;
+       if (r == 0) {
+               dev_err(dev->dev, "controller timed out\n");
+               omap_i2c_init(dev);
+               return -ETIMEDOUT;
+       }
+
+       if (likely(!dev->cmd_err))
+               return 0;
+
+       /* We have an error */
+       if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
+                           OMAP_I2C_STAT_XUDF)) {
+               omap_i2c_init(dev);
+               return -EIO;
+       }
+
+       if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
+               if (msg->flags & I2C_M_IGNORE_NAK)
+                       return 0;
+               if (stop) {
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+                       w |= OMAP_I2C_CON_STP;
+                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+               }
+               return -EREMOTEIO;
+       }
+       return -EIO;
+}
+
+
+/*
+ * Prepare controller for a transaction and call omap_i2c_xfer_msg
+ * to do the work during IRQ processing.
+ */
+static int
+omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+       struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+       int i;
+       int r;
+
+       omap_i2c_enable_clocks(dev);
+
+       /* REVISIT: initialize and use adap->retries. This is an optional
+        * feature */
+       if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+               goto out;
+
+       for (i = 0; i < num; i++) {
+               r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+               if (r != 0)
+                       break;
+       }
+
+       if (r == 0)
+               r = num;
+out:
+       omap_i2c_disable_clocks(dev);
+       return r;
+}
+
+static u32
+omap_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static inline void
+omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err)
+{
+       dev->cmd_err |= err;
+       complete(&dev->cmd_complete);
+}
+
+static inline void
+omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
+{
+       omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+}
+
+static irqreturn_t
+omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_i2c_dev *dev = dev_id;
+       u16 iv, w;
+
+       iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+       switch (iv) {
+       case 0x00:      /* None */
+               break;
+       case 0x01:      /* Arbitration lost */
+               dev_err(dev->dev, "Arbitration lost\n");
+               omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+               break;
+       case 0x02:      /* No acknowledgement */
+               omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP);
+               break;
+       case 0x03:      /* Register access ready */
+               omap_i2c_complete_cmd(dev, 0);
+               break;
+       case 0x04:      /* Receive data ready */
+               if (dev->buf_len) {
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                       *dev->buf++ = w;
+                       dev->buf_len--;
+                       if (dev->buf_len) {
+                               *dev->buf++ = w >> 8;
+                               dev->buf_len--;
+                       }
+               } else
+                       dev_err(dev->dev, "RRDY IRQ while no data requested\n");
+               break;
+       case 0x05:      /* Transmit data ready */
+               if (dev->buf_len) {
+                       w = *dev->buf++;
+                       dev->buf_len--;
+                       if (dev->buf_len) {
+                               w |= *dev->buf++ << 8;
+                               dev->buf_len--;
+                       }
+                       omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+               } else
+                       dev_err(dev->dev, "XRDY IRQ while no data to send\n");
+               break;
+       default:
+               return IRQ_NONE;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_i2c_dev *dev = dev_id;
+       u16 bits;
+       u16 stat, w;
+       int count = 0;
+
+       bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+       while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
+               dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
+               if (count++ == 100) {
+                       dev_warn(dev->dev, "Too much work in one IRQ\n");
+                       break;
+               }
+
+               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+
+               if (stat & OMAP_I2C_STAT_ARDY) {
+                       omap_i2c_complete_cmd(dev, 0);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_RRDY) {
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                       if (dev->buf_len) {
+                               *dev->buf++ = w;
+                               dev->buf_len--;
+                               if (dev->buf_len) {
+                                       *dev->buf++ = w >> 8;
+                                       dev->buf_len--;
+                               }
+                       } else
+                               dev_err(dev->dev, "RRDY IRQ while no data"
+                                               "requested\n");
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_XRDY) {
+                       w = 0;
+                       if (dev->buf_len) {
+                               w = *dev->buf++;
+                               dev->buf_len--;
+                               if (dev->buf_len) {
+                                       w |= *dev->buf++ << 8;
+                                       dev->buf_len--;
+                               }
+                       } else
+                               dev_err(dev->dev, "XRDY IRQ while no"
+                                       "data to send\n");
+                       omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_ROVR) {
+                       dev_err(dev->dev, "Receive overrun\n");
+                       dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+               }
+               if (stat & OMAP_I2C_STAT_XUDF) {
+                       dev_err(dev->dev, "Transmit overflow\n");
+                       dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+               }
+               if (stat & OMAP_I2C_STAT_NACK) {
+                       omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+                                          OMAP_I2C_CON_STP);
+               }
+               if (stat & OMAP_I2C_STAT_AL) {
+                       dev_err(dev->dev, "Arbitration lost\n");
+                       omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+               }
+       }
+
+       return count ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static const struct i2c_algorithm omap_i2c_algo = {
+       .master_xfer    = omap_i2c_xfer,
+       .functionality  = omap_i2c_func,
+};
+
+static int
+omap_i2c_probe(struct platform_device *pdev)
+{
+       struct omap_i2c_dev     *dev;
+       struct i2c_adapter      *adap;
+       struct resource         *mem, *irq, *ioarea;
+       int r;
+
+       /* NOTE: driver uses the static register mapping */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               return -ENODEV;
+       }
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return -ENODEV;
+       }
+
+       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+                       pdev->name);
+       if (!ioarea) {
+               dev_err(&pdev->dev, "I2C region already claimed\n");
+               return -EBUSY;
+       }
+
+       if (clock > 200)
+               clock = 400;    /* Fast mode */
+       else
+               clock = 100;    /* Standard mode */
+
+       dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
+       if (!dev) {
+               r = -ENOMEM;
+               goto err_release_region;
+       }
+
+       dev->dev = &pdev->dev;
+       dev->irq = irq->start;
+       dev->base = (void __iomem *) IO_ADDRESS(mem->start);
+       platform_set_drvdata(pdev, dev);
+
+       if ((r = omap_i2c_get_clocks(dev)) != 0)
+               goto err_free_mem;
+
+       omap_i2c_enable_clocks(dev);
+
+       if (cpu_is_omap15xx())
+               dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+
+       /* reset ASAP, clearing any IRQs */
+       omap_i2c_init(dev);
+
+       r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
+                       0, pdev->name, dev);
+
+       if (r) {
+               dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
+               goto err_unuse_clocks;
+       }
+       r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+       dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
+                pdev->id, r >> 4, r & 0xf, clock);
+
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_HWMON;
+       strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+       adap->algo = &omap_i2c_algo;
+       adap->dev.parent = &pdev->dev;
+
+       /* i2c device drivers may be active on return from add_adapter() */
+       r = i2c_add_adapter(adap);
+       if (r) {
+               dev_err(dev->dev, "failure adding adapter\n");
+               goto err_free_irq;
+       }
+
+       omap_i2c_disable_clocks(dev);
+
+       return 0;
+
+err_free_irq:
+       free_irq(dev->irq, dev);
+err_unuse_clocks:
+       omap_i2c_disable_clocks(dev);
+       omap_i2c_put_clocks(dev);
+err_free_mem:
+       platform_set_drvdata(pdev, NULL);
+       kfree(dev);
+err_release_region:
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+       return r;
+}
+
+static int
+omap_i2c_remove(struct platform_device *pdev)
+{
+       struct omap_i2c_dev     *dev = platform_get_drvdata(pdev);
+       struct resource         *mem;
+
+       platform_set_drvdata(pdev, NULL);
+
+       free_irq(dev->irq, dev);
+       i2c_del_adapter(&dev->adapter);
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       omap_i2c_put_clocks(dev);
+       kfree(dev);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       return 0;
+}
+
+static struct platform_driver omap_i2c_driver = {
+       .probe          = omap_i2c_probe,
+       .remove         = omap_i2c_remove,
+       .driver         = {
+               .name   = "i2c_omap",
+               .owner  = THIS_MODULE,
+       },
+};
+
+/* I2C may be needed to bring up other drivers */
+static int __init
+omap_i2c_init_driver(void)
+{
+       return platform_driver_register(&omap_i2c_driver);
+}
+subsys_initcall(omap_i2c_init_driver);
+
+static void __exit omap_i2c_exit_driver(void)
+{
+       platform_driver_unregister(&omap_i2c_driver);
+}
+module_exit(omap_i2c_exit_driver);
+
+MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+MODULE_LICENSE("GPL");
index e09ebbb2f9f09dc14dc00129211c82cfd4da95cb..5eb2bd294fd97478f78592e26bcb6dd75e027b1e 100644 (file)
@@ -103,7 +103,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
        .getsda         = parport_getsda,
        .getscl         = parport_getscl,
        .udelay         = 50,
-       .mdelay         = 50,
        .timeout        = HZ,
 }; 
 
index 934bd55bae15da1164ca7b14b79a5c7bb2cfcf18..48a829431c7bd1dcdb481776f9dd6e993d3df1c1 100644 (file)
@@ -138,7 +138,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
        .getsda         = parport_getsda,
        .getscl         = parport_getscl,
        .udelay         = 60,
-       .mdelay         = 60,
        .timeout        = HZ,
 }; 
 
index 8f2f65b793b9a355e5f8b0022cd42711e0755644..30c7a1b38cbd7e5202106b8f060bb55a83f29e5d 100644 (file)
@@ -376,7 +376,7 @@ static u32 piix4_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = piix4_access,
        .functionality  = piix4_func,
 };
index d658d91079550d56f8c38bd8f31dce1c6e415160..a508cb962d244e89b4addc108f2c159212639364 100644 (file)
@@ -175,7 +175,7 @@ static u32 i2c_powermac_func(struct i2c_adapter * adapter)
 }
 
 /* For now, we only handle smbus */
-static struct i2c_algorithm i2c_powermac_algorithm = {
+static const struct i2c_algorithm i2c_powermac_algorithm = {
        .smbus_xfer     = i2c_powermac_smbus_xfer,
        .master_xfer    = i2c_powermac_master_xfer,
        .functionality  = i2c_powermac_func,
index 9479525892e3e337d0872eef7f630041776bf0ff..7745e21874a8e145c8caa5b0a1a9fea44fd32fac 100644 (file)
@@ -180,7 +180,6 @@ static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iom
        p->algo.getsda    = bit_s3via_getsda;
        p->algo.getscl    = bit_s3via_getscl;
        p->algo.udelay    = CYCLE_DELAY;
-       p->algo.mdelay    = CYCLE_DELAY;
        p->algo.timeout   = TIMEOUT;
        p->algo.data      = p;
        p->mmvga          = mmvga;
index ee114b48face4e2662f85cd4b6ab09f697b03656..cd4ad98ad517f9f0315208564922dfef8d69fffe 100644 (file)
@@ -926,7 +926,7 @@ static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm i2c_pxa_algorithm = {
+static const struct i2c_algorithm i2c_pxa_algorithm = {
        .master_xfer    = i2c_pxa_xfer,
        .functionality  = i2c_pxa_functionality,
 };
index 5d2950e91fc5fce62a6e3566791abcf2b1738d4c..9ebe429a0a0ffd2fc853b6268e5e1e0d1be1738d 100644 (file)
@@ -566,7 +566,7 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
 
 /* i2c bus registration info */
 
-static struct i2c_algorithm s3c24xx_i2c_algorithm = {
+static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
        .master_xfer            = s3c24xx_i2c_xfer,
        .functionality          = s3c24xx_i2c_func,
 };
index 0c8518298e4da3da0df6188849c6b3881393dabf..209f47ea175057c7ed3816dd294a4f9d9f6f52a4 100644 (file)
@@ -140,7 +140,6 @@ static struct i2c_algo_bit_data sav_i2c_bit_data = {
        .getsda         = bit_savi2c_getsda,
        .getscl         = bit_savi2c_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT
 };
 
index fa503ed9f86db6d8fb32899d817a9db78d6e60f7..0ca599d3b4029851ddf022bab424759824060ec2 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004 Steven J. Hill
  * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ * Copyright (C) 1995-2000 Simon G. Vogl
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/i2c-algo-sibyte.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_smbus.h>
 
+
+struct i2c_algo_sibyte_data {
+       void *data;             /* private data */
+       int   bus;              /* which bus */
+       void *reg_base;         /* CSR base */
+};
+
+/* ----- global defines ----------------------------------------------- */
+#define SMB_CSR(a,r) ((long)(a->reg_base + r))
+
+/* ----- global variables --------------------------------------------- */
+
+/* module parameters:
+ */
+static int bit_scan;   /* have a look at what's hanging 'round */
+module_param(bit_scan, int, 0);
+MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+
+
+static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
+                     unsigned short flags, char read_write,
+                     u8 command, int size, union i2c_smbus_data * data)
+{
+       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+       int data_bytes = 0;
+       int error;
+
+       while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+               ;
+
+       switch (size) {
+       case I2C_SMBUS_QUICK:
+               csr_out32((V_SMB_ADDR(addr) |
+                          (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
+                          V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
+               break;
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_READ) {
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+                       data_bytes = 1;
+               } else {
+                       csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+               }
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+               if (read_write == I2C_SMBUS_READ) {
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+                       data_bytes = 1;
+               } else {
+                       csr_out32(V_SMB_LB(data->byte),
+                                 SMB_CSR(adap, R_SMB_DATA));
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+               }
+               break;
+       case I2C_SMBUS_WORD_DATA:
+               csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+               if (read_write == I2C_SMBUS_READ) {
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+                       data_bytes = 2;
+               } else {
+                       csr_out32(V_SMB_LB(data->word & 0xff),
+                                 SMB_CSR(adap, R_SMB_DATA));
+                       csr_out32(V_SMB_MB(data->word >> 8),
+                                 SMB_CSR(adap, R_SMB_DATA));
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+               }
+               break;
+       default:
+               return -1;      /* XXXKW better error code? */
+       }
+
+       while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+               ;
+
+       error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
+       if (error & M_SMB_ERROR) {
+               /* Clear error bit by writing a 1 */
+               csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
+               return -1;      /* XXXKW better error code? */
+       }
+
+       if (data_bytes == 1)
+               data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
+       if (data_bytes == 2)
+               data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
+
+       return 0;
+}
+
+static u32 bit_func(struct i2c_adapter *adap)
+{
+       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static const struct i2c_algorithm i2c_sibyte_algo = {
+       .smbus_xfer     = smbus_xfer,
+       .functionality  = bit_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+{
+       int i;
+       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+
+       /* register new adapter to i2c module... */
+       i2c_adap->algo = &i2c_sibyte_algo;
+
+       /* Set the frequency to 100 kHz */
+       csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
+       csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+
+       /* scan bus */
+       if (bit_scan) {
+               union i2c_smbus_data data;
+               int rc;
+               printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
+                      i2c_adap->name);
+               for (i = 0x00; i < 0x7f; i++) {
+                       /* XXXKW is this a realistic probe? */
+                       rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
+                                       I2C_SMBUS_BYTE_DATA, &data);
+                       if (!rc) {
+                               printk("(%02x)",i);
+                       } else
+                               printk(".");
+               }
+               printk("\n");
+       }
+
+       return i2c_add_adapter(i2c_adap);
+}
+
+
 static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
        { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
        { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
@@ -58,13 +210,13 @@ static int __init i2c_sibyte_init(void)
 
 static void __exit i2c_sibyte_exit(void)
 {
-       i2c_sibyte_del_bus(&sibyte_board_adapter[0]);
-       i2c_sibyte_del_bus(&sibyte_board_adapter[1]);
+       i2c_del_adapter(&sibyte_board_adapter[0]);
+       i2c_del_adapter(&sibyte_board_adapter[1]);
 }
 
 module_init(i2c_sibyte_init);
 module_exit(i2c_sibyte_exit);
 
-MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>");
 MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
 MODULE_LICENSE("GPL");
index b57ab74d23ecaa42c14ff8d0a22a225766ba7c12..38bbfd840b6b181c51aab35856ceebfdfb737cdf 100644 (file)
@@ -358,7 +358,7 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = sis5595_access,
        .functionality  = sis5595_func,
 };
index acb75e2824140220fcea0b4e010fac3e0c69f0fb..dec0bafb52ab5cd5f241b7675800048a790c7cd8 100644 (file)
@@ -450,7 +450,7 @@ exit:
 }
 
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = sis630_access,
        .functionality  = sis630_func,
 };
index 1a73c0532fc770bb6c1f812ba7959cdc511427b5..7fd07fbac33681c3f81f49e66acad11660aa3533 100644 (file)
@@ -242,7 +242,7 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = sis96x_access,
        .functionality  = sis96x_func,
 };
index 73f481e93a36458c3040e391d3a16ac649d9affd..a54adc50d162a5a580ae60a709b87bb802280c75 100644 (file)
 #include <linux/errno.h>
 #include <linux/i2c.h>
 
+static unsigned short chip_addr;
+module_param(chip_addr, ushort, S_IRUGO);
+MODULE_PARM_DESC(chip_addr, "Chip address (between 0x03 and 0x77)\n");
+
 static u8  stub_pointer;
 static u8  stub_bytes[256];
 static u16 stub_words[256];
@@ -37,6 +41,9 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
 {
        s32 ret;
 
+       if (addr != chip_addr)
+               return -ENODEV;
+
        switch (size) {
 
        case I2C_SMBUS_QUICK:
@@ -108,7 +115,7 @@ static u32 stub_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .functionality  = stub_func,
        .smbus_xfer     = stub_xfer,
 };
@@ -122,7 +129,17 @@ static struct i2c_adapter stub_adapter = {
 
 static int __init i2c_stub_init(void)
 {
-       printk(KERN_INFO "i2c-stub loaded\n");
+       if (!chip_addr) {
+               printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
+               return -ENODEV;
+       }
+       if (chip_addr < 0x03 || chip_addr > 0x77) {
+               printk(KERN_ERR "i2c-stub: Invalid chip address 0x%02x\n",
+                      chip_addr);
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", chip_addr);
        return i2c_add_adapter(&stub_adapter);
 }
 
index 484bbacfce6bf005fc435f7f1a653fdc7659495f..910e200ad5001a0ee2e37c2444e0f2c58a3a5595 100644 (file)
@@ -81,7 +81,6 @@ static struct i2c_algo_bit_data bit_data = {
        .getsda         = bit_via_getsda,
        .getscl         = bit_via_getscl,
        .udelay         = 5,
-       .mdelay         = 5,
        .timeout        = HZ
 };
 
index 47e52bf2c5ec836f606e3c1a66684b1489771745..efc6bbf0cc0a49818b569208f92f92062acefaf2 100644 (file)
@@ -34,6 +34,8 @@
    VT8233A            0x3147             yes?
    VT8235             0x3177             yes
    VT8237R            0x3227             yes
+   VT8237A            0x3337             yes
+   VT8251             0x3287             yes
 
    Note: we assume there can only be one device, with one SMBus interface.
 */
@@ -297,7 +299,7 @@ static u32 vt596_func(struct i2c_adapter *adapter)
        return func;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = vt596_access,
        .functionality  = vt596_func,
 };
@@ -381,7 +383,9 @@ found:
        dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
 
        switch (pdev->device) {
+       case PCI_DEVICE_ID_VIA_8251:
        case PCI_DEVICE_ID_VIA_8237:
+       case PCI_DEVICE_ID_VIA_8237A:
        case PCI_DEVICE_ID_VIA_8235:
        case PCI_DEVICE_ID_VIA_8233A:
        case PCI_DEVICE_ID_VIA_8233_0:
@@ -432,8 +436,12 @@ static struct pci_device_id vt596_ids[] = {
          .driver_data = SMBBA3 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
          .driver_data = SMBBA3 },
+       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
+         .driver_data = SMBBA3 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
          .driver_data = SMBBA1 },
+       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
+         .driver_data = SMBBA3 },
        { 0, }
 };
 
index b675773b0cc1d19a9222b87fd319027b4bfef773..6c8d25183382ed7feb150cb72d193b03af4a4f95 100644 (file)
@@ -160,7 +160,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
        .getsda         = bit_vooi2c_getsda,
        .getscl         = bit_vooi2c_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT
 };
 
@@ -177,7 +176,6 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
        .getsda         = bit_vooddc_getsda,
        .getscl         = bit_vooddc_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT
 };
 
index eae9e81be375acecb2a697fd23b7afdcab944b6a..32aab0d34ee930eb3b9a6f0a95fa752c7f32b7d9 100644 (file)
@@ -383,7 +383,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
 }
 
 /* For now, we only handle combined mode (smbus) */
-static struct i2c_algorithm scx200_acb_algorithm = {
+static const struct i2c_algorithm scx200_acb_algorithm = {
        .smbus_xfer     = scx200_acb_smbus_xfer,
        .functionality  = scx200_acb_func,
 };
index cb3ef5ac99fd06976c0145fd4be0399044f03b90..8b65a5cf8251f1791f389750518529f7e0e69ec6 100644 (file)
@@ -71,12 +71,12 @@ static int scx200_i2c_getsda(void *data)
  */
 
 static struct i2c_algo_bit_data scx200_i2c_data = {
-       NULL,
-       scx200_i2c_setsda,
-       scx200_i2c_setscl,
-       scx200_i2c_getsda,
-       scx200_i2c_getscl,
-       10, 10, 100,            /* waits, timeout */
+       .setsda         = scx200_i2c_setsda,
+       .setscl         = scx200_i2c_setscl,
+       .getsda         = scx200_i2c_getsda,
+       .getscl         = scx200_i2c_getscl,
+       .udelay         = 10,
+       .timeout        = 100,
 };
 
 static struct i2c_adapter scx200_i2c_ops = {
index 13c108269a6da9227f669b472b4b3e6e5ca9e4ec..cec3a0c3894dda7912024c769e04057d2a47c5ad 100644 (file)
@@ -209,10 +209,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* create the sysfs eeprom file */
-       sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+       err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+       if (err)
+               goto exit_detach;
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_kfree:
        kfree(data);
 exit:
@@ -223,6 +227,8 @@ static int eeprom_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
+
        err = i2c_detach_client(client);
        if (err)
                return err;
index f92505b94c61fb80b2907faacbfe1419df66d05b..182f04953466080e5f443e6b091bbbd2766a23ad 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 
index 88d2ddee449065f7db62578e41255d8a54f3ffb6..76645c1429776e182b87e3d2578adc40222cffa1 100644 (file)
@@ -199,8 +199,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
        mutex_init(&data->update_lock);
 
        /* Init fake client data */
-       /* set the client data to the i2c_client so that it will get freed */
-       i2c_set_clientdata(fake_client, fake_client);
+       i2c_set_clientdata(fake_client, NULL);
        fake_client->addr = address | 1;
        fake_client->adapter = adapter;
        fake_client->driver = &max6875_driver;
@@ -214,13 +213,17 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit_kfree2;
 
        if ((err = i2c_attach_client(fake_client)) != 0)
-               goto exit_detach;
+               goto exit_detach1;
 
-       sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+       err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+       if (err)
+               goto exit_detach2;
 
        return 0;
 
-exit_detach:
+exit_detach2:
+       i2c_detach_client(fake_client);
+exit_detach1:
        i2c_detach_client(real_client);
 exit_kfree2:
        kfree(fake_client);
@@ -229,14 +232,24 @@ exit_kfree1:
        return err;
 }
 
+/* Will be called for both the real client and the fake client */
 static int max6875_detach_client(struct i2c_client *client)
 {
        int err;
+       struct max6875_data *data = i2c_get_clientdata(client);
+
+       /* data is NULL for the fake client */
+       if (data)
+               sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
 
        err = i2c_detach_client(client);
        if (err)
                return err;
-       kfree(i2c_get_clientdata(client));
+
+       if (data)               /* real client */
+               kfree(data);
+       else                    /* fake client */
+               kfree(client);
        return 0;
 }
 
index cb22280cdd277cb08c738abcc4064588413226a8..f43c4e79b55e9b3cf9bf0bba1317a0196aadddea 100644 (file)
@@ -148,11 +148,16 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
        if ((err = i2c_attach_client(new_client)))
                goto exit_kfree;
 
-       /* Register sysfs hooks (don't care about failure) */
-       sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
+       /* Register sysfs hooks */
+       err = sysfs_create_group(&new_client->dev.kobj,
+                                &pca9539_defattr_group);
+       if (err)
+               goto exit_detach;
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_kfree:
        kfree(data);
 exit:
@@ -163,6 +168,8 @@ static int pca9539_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
+
        if ((err = i2c_detach_client(client)))
                return err;
 
index c3e6449c4481fd1c219ed38f33c44293fa45acd1..32b25427eaba6e54ecc0a6674ab60a0a18f2c297 100644 (file)
@@ -105,6 +105,16 @@ static ssize_t set_write(struct device *dev, struct device_attribute *attr, cons
 
 static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
 
+static struct attribute *pcf8574_attributes[] = {
+       &dev_attr_read.attr,
+       &dev_attr_write.attr,
+       NULL
+};
+
+static const struct attribute_group pcf8574_attr_group = {
+       .attrs = pcf8574_attributes,
+};
+
 /*
  * Real code
  */
@@ -166,13 +176,13 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
        pcf8574_init_client(new_client);
 
        /* Register sysfs hooks */
-       device_create_file(&new_client->dev, &dev_attr_read);
-       device_create_file(&new_client->dev, &dev_attr_write);
+       err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group);
+       if (err)
+               goto exit_detach;
        return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
-
+      exit_detach:
+       i2c_detach_client(new_client);
       exit_free:
        kfree(data);
       exit:
@@ -183,6 +193,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
+
        if ((err = i2c_detach_client(client)))
                return err;
 
index 925a6b371fd248651238cad2f92bb89b67dfc1c7..4dc36376eb3267f5b702b33ccdc80f0a5a7d926d 100644 (file)
@@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
 static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 
                   show_out0_enable, set_out0_enable);
 
+static struct attribute *pcf8591_attributes[] = {
+       &dev_attr_out0_enable.attr,
+       &dev_attr_out0_output.attr,
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       NULL
+};
+
+static const struct attribute_group pcf8591_attr_group = {
+       .attrs = pcf8591_attributes,
+};
+
+static struct attribute *pcf8591_attributes_opt[] = {
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       NULL
+};
+
+static const struct attribute_group pcf8591_attr_group_opt = {
+       .attrs = pcf8591_attributes_opt,
+};
+
 /*
  * Real code
  */
@@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
        pcf8591_init_client(new_client);
 
        /* Register sysfs hooks */
-       device_create_file(&new_client->dev, &dev_attr_out0_enable);
-       device_create_file(&new_client->dev, &dev_attr_out0_output);
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
+       err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
+       if (err)
+               goto exit_detach;
 
        /* Register input2 if not in "two differential inputs" mode */
-       if (input_mode != 3 )
-               device_create_file(&new_client->dev, &dev_attr_in2_input);
-               
+       if (input_mode != 3) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_in2_input)))
+                       goto exit_sysfs_remove;
+       }
+
        /* Register input3 only in "four single ended inputs" mode */
-       if (input_mode == 0)
-               device_create_file(&new_client->dev, &dev_attr_in3_input);
-       
+       if (input_mode == 0) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_in3_input)))
+                       goto exit_sysfs_remove;
+       }
+
        return 0;
-       
-       /* OK, this is not exactly good programming practice, usually. But it is
-          very code-efficient in this case. */
 
+exit_sysfs_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
+       sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
+exit_detach:
+       i2c_detach_client(new_client);
 exit_kfree:
        kfree(data);
 exit:
@@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
+       sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
+
        if ((err = i2c_detach_client(client)))
                return err;
 
index 0be6fd6a267d0ae2037966ad07d966beaca17b4c..6a7578217177ba4808f97dbbc35ebf45b68440f9 100644 (file)
@@ -305,7 +305,7 @@ static int dbg_show(struct seq_file *s, void *_)
 
 static int dbg_tps_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, dbg_show, inode->u.generic_ip);
+       return single_open(file, dbg_show, inode->i_private);
 }
 
 static struct file_operations debug_fops = {
index 9cb277d6aa48bbff97dc6582051e5ab03e912850..7ca81f42d14bfd7c1ab5834b2a6cb853587259a9 100644 (file)
@@ -183,15 +183,21 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
        adap->dev.driver = &i2c_adapter_driver;
        adap->dev.release = &i2c_adapter_dev_release;
-       device_register(&adap->dev);
-       device_create_file(&adap->dev, &dev_attr_name);
+       res = device_register(&adap->dev);
+       if (res)
+               goto out_list;
+       res = device_create_file(&adap->dev, &dev_attr_name);
+       if (res)
+               goto out_unregister;
 
        /* Add this adapter to the i2c_adapter class */
        memset(&adap->class_dev, 0x00, sizeof(struct class_device));
        adap->class_dev.dev = &adap->dev;
        adap->class_dev.class = &i2c_adapter_class;
        strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
-       class_device_register(&adap->class_dev);
+       res = class_device_register(&adap->class_dev);
+       if (res)
+               goto out_remove_name;
 
        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
@@ -206,6 +212,17 @@ int i2c_add_adapter(struct i2c_adapter *adap)
 out_unlock:
        mutex_unlock(&core_lists);
        return res;
+
+out_remove_name:
+       device_remove_file(&adap->dev, &dev_attr_name);
+out_unregister:
+       init_completion(&adap->dev_released); /* Needed? */
+       device_unregister(&adap->dev);
+       wait_for_completion(&adap->dev_released);
+out_list:
+       list_del(&adap->list);
+       idr_remove(&i2c_adapter_idr, adap->nr);
+       goto out_unlock;
 }
 
 
@@ -394,23 +411,15 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 int i2c_attach_client(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int res = 0;
 
        mutex_lock(&adapter->clist_lock);
        if (__i2c_check_addr(client->adapter, client->addr)) {
-               mutex_unlock(&adapter->clist_lock);
-               return -EBUSY;
+               res = -EBUSY;
+               goto out_unlock;
        }
        list_add_tail(&client->list,&adapter->clients);
-       mutex_unlock(&adapter->clist_lock);
        
-       if (adapter->client_register)  {
-               if (adapter->client_register(client))  {
-                       dev_dbg(&adapter->dev, "client_register "
-                               "failed for client [%s] at 0x%02x\n",
-                               client->name, client->addr);
-               }
-       }
-
        client->usage_count = 0;
 
        client->dev.parent = &client->adapter->dev;
@@ -422,10 +431,35 @@ int i2c_attach_client(struct i2c_client *client)
                "%d-%04x", i2c_adapter_id(adapter), client->addr);
        dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
                client->name, client->dev.bus_id);
-       device_register(&client->dev);
-       device_create_file(&client->dev, &dev_attr_client_name);
-       
+       res = device_register(&client->dev);
+       if (res)
+               goto out_list;
+       res = device_create_file(&client->dev, &dev_attr_client_name);
+       if (res)
+               goto out_unregister;
+       mutex_unlock(&adapter->clist_lock);
+
+       if (adapter->client_register)  {
+               if (adapter->client_register(client)) {
+                       dev_dbg(&adapter->dev, "client_register "
+                               "failed for client [%s] at 0x%02x\n",
+                               client->name, client->addr);
+               }
+       }
+
        return 0;
+
+out_unregister:
+       init_completion(&client->released); /* Needed? */
+       device_unregister(&client->dev);
+       wait_for_completion(&client->released);
+out_list:
+       list_del(&client->list);
+       dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
+               "(%d)\n", client->name, client->addr, res);
+out_unlock:
+       mutex_unlock(&adapter->clist_lock);
+       return res;
 }
 
 
@@ -674,11 +708,16 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
 
        /* Finally call the custom detection function */
        err = found_proc(adapter, addr, kind);
-
        /* -ENODEV can be returned if there is a chip at the given address
           but it isn't supported by this chip driver. We catch it here as
           this isn't an error. */
-       return (err == -ENODEV) ? 0 : err;
+       if (err == -ENODEV)
+               err = 0;
+
+       if (err)
+               dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n",
+                        addr, err);
+       return err;
 }
 
 int i2c_probe(struct i2c_adapter *adapter,
@@ -868,7 +907,7 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
                           I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
                return -1;
        else
-               return 0x0FF & data.byte;
+               return data.byte;
 }
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
@@ -884,7 +923,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
                           I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
                return -1;
        else
-               return 0x0FF & data.byte;
+               return data.byte;
 }
 
 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
@@ -903,7 +942,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
                           I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
                return -1;
        else
-               return 0x0FFFF & data.word;
+               return data.word;
 }
 
 s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
@@ -1006,7 +1045,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                else {
                        msg[0].len=3;
                        msgbuf0[1] = data->word & 0xff;
-                       msgbuf0[2] = (data->word >> 8) & 0xff;
+                       msgbuf0[2] = data->word >> 8;
                }
                break;
        case I2C_SMBUS_PROC_CALL:
@@ -1015,7 +1054,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                msg[0].len = 3;
                msg[1].len = 2;
                msgbuf0[1] = data->word & 0xff;
-               msgbuf0[2] = (data->word >> 8) & 0xff;
+               msgbuf0[2] = data->word >> 8;
                break;
        case I2C_SMBUS_BLOCK_DATA:
                if (read_write == I2C_SMBUS_READ) {
index 58ccddd5c237dd5823140da8857691ed9780cc9f..3f869033ed70cd212c6a99a6d54f4b615abfbed1 100644 (file)
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
-#include <linux/platform_device.h>
 #include <asm/uaccess.h>
 
-static struct i2c_client i2cdev_client_template;
+static struct i2c_driver i2cdev_driver;
 
 struct i2c_dev {
-       int minor;
+       struct list_head list;
        struct i2c_adapter *adap;
        struct class_device *class_dev;
 };
-#define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
 
 #define I2C_MINORS     256
-static struct i2c_dev *i2c_dev_array[I2C_MINORS];
-static DEFINE_SPINLOCK(i2c_dev_array_lock);
+static LIST_HEAD(i2c_dev_list);
+static DEFINE_SPINLOCK(i2c_dev_list_lock);
 
 static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
 {
        struct i2c_dev *i2c_dev;
 
-       spin_lock(&i2c_dev_array_lock);
-       i2c_dev = i2c_dev_array[index];
-       spin_unlock(&i2c_dev_array_lock);
-       return i2c_dev;
-}
-
-static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
-{
-       struct i2c_dev *i2c_dev = NULL;
-
-       spin_lock(&i2c_dev_array_lock);
-       if ((i2c_dev_array[adap->nr]) &&
-           (i2c_dev_array[adap->nr]->adap == adap))
-               i2c_dev = i2c_dev_array[adap->nr];
-       spin_unlock(&i2c_dev_array_lock);
+       spin_lock(&i2c_dev_list_lock);
+       list_for_each_entry(i2c_dev, &i2c_dev_list, list) {
+               if (i2c_dev->adap->nr == index)
+                       goto found;
+       }
+       i2c_dev = NULL;
+found:
+       spin_unlock(&i2c_dev_list_lock);
        return i2c_dev;
 }
 
@@ -76,30 +68,28 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
 {
        struct i2c_dev *i2c_dev;
 
+       if (adap->nr >= I2C_MINORS) {
+               printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",
+                      adap->nr);
+               return ERR_PTR(-ENODEV);
+       }
+
        i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
        if (!i2c_dev)
                return ERR_PTR(-ENOMEM);
+       i2c_dev->adap = adap;
 
-       spin_lock(&i2c_dev_array_lock);
-       if (i2c_dev_array[adap->nr]) {
-               spin_unlock(&i2c_dev_array_lock);
-               dev_err(&adap->dev, "i2c-dev already has a device assigned to this adapter\n");
-               goto error;
-       }
-       i2c_dev->minor = adap->nr;
-       i2c_dev_array[adap->nr] = i2c_dev;
-       spin_unlock(&i2c_dev_array_lock);
+       spin_lock(&i2c_dev_list_lock);
+       list_add_tail(&i2c_dev->list, &i2c_dev_list);
+       spin_unlock(&i2c_dev_list_lock);
        return i2c_dev;
-error:
-       kfree(i2c_dev);
-       return ERR_PTR(-ENODEV);
 }
 
 static void return_i2c_dev(struct i2c_dev *i2c_dev)
 {
-       spin_lock(&i2c_dev_array_lock);
-       i2c_dev_array[i2c_dev->minor] = NULL;
-       spin_unlock(&i2c_dev_array_lock);
+       spin_lock(&i2c_dev_list_lock);
+       list_del(&i2c_dev->list);
+       spin_unlock(&i2c_dev_list_lock);
 }
 
 static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
@@ -375,12 +365,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
        if (!adap)
                return -ENODEV;
 
-       client = kmalloc(sizeof(*client), GFP_KERNEL);
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
        if (!client) {
                i2c_put_adapter(adap);
                return -ENOMEM;
        }
-       memcpy(client, &i2cdev_client_template, sizeof(*client));
+       snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
+       client->driver = &i2cdev_driver;
 
        /* registered with adapter, passed as client to user */
        client->adapter = adap;
@@ -415,41 +406,47 @@ static struct class *i2c_dev_class;
 static int i2cdev_attach_adapter(struct i2c_adapter *adap)
 {
        struct i2c_dev *i2c_dev;
-       struct device *dev;
+       int res;
 
        i2c_dev = get_free_i2c_dev(adap);
        if (IS_ERR(i2c_dev))
                return PTR_ERR(i2c_dev);
 
-       pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
-                adap->name, i2c_dev->minor);
-
        /* register this i2c device with the driver core */
-       i2c_dev->adap = adap;
-       dev = &adap->dev;
        i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
-                                                MKDEV(I2C_MAJOR, i2c_dev->minor),
-                                                dev, "i2c-%d", i2c_dev->minor);
-       if (!i2c_dev->class_dev)
+                                                MKDEV(I2C_MAJOR, adap->nr),
+                                                &adap->dev, "i2c-%d",
+                                                adap->nr);
+       if (!i2c_dev->class_dev) {
+               res = -ENODEV;
                goto error;
-       class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+       }
+       res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+       if (res)
+               goto error_destroy;
+
+       pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+                adap->name, adap->nr);
        return 0;
+error_destroy:
+       class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
 error:
        return_i2c_dev(i2c_dev);
        kfree(i2c_dev);
-       return -ENODEV;
+       return res;
 }
 
 static int i2cdev_detach_adapter(struct i2c_adapter *adap)
 {
        struct i2c_dev *i2c_dev;
 
-       i2c_dev = i2c_dev_get_by_adapter(adap);
-       if (!i2c_dev)
-               return -ENODEV;
+       i2c_dev = i2c_dev_get_by_minor(adap->nr);
+       if (!i2c_dev) /* attach_adapter must have failed */
+               return 0;
 
+       class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
        return_i2c_dev(i2c_dev);
-       class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
+       class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
        kfree(i2c_dev);
 
        pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -471,12 +468,6 @@ static struct i2c_driver i2cdev_driver = {
        .detach_client  = i2cdev_detach_client,
 };
 
-static struct i2c_client i2cdev_client_template = {
-       .name           = "I2C /dev entry",
-       .addr           = -1,
-       .driver         = &i2cdev_driver,
-};
-
 static int __init i2c_dev_init(void)
 {
        int res;
index b6fb167e20f681980a54c9baa7ef14a0de4fea83..69d627bd537a8cb7ca1095a7915291995c9dfbc6 100644 (file)
@@ -4,6 +4,8 @@
 # Andre Hedrick <andre@linux-ide.org>
 #
 
+if BLOCK
+
 menu "ATA/ATAPI/MFM/RLL support"
 
 config IDE
@@ -1082,3 +1084,5 @@ config BLK_DEV_HD
 endif
 
 endmenu
+
+endif
index 654d4cd09847cebdcad66b77fc5c9f0167f78149..69bbb6206a00ef5673638c0ccfb4a59bfa272b1d 100644 (file)
@@ -372,7 +372,7 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
 {
        int log = 0;
 
-       if (!sense || !rq || (rq->flags & REQ_QUIET))
+       if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
                return 0;
 
        switch (sense->sense_key) {
@@ -597,7 +597,7 @@ static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
        struct cdrom_info *cd = drive->driver_data;
 
        ide_init_drive_cmd(rq);
-       rq->flags = REQ_PC;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->rq_disk = cd->disk;
 }
 
@@ -617,7 +617,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
        rq->cmd[0] = GPCMD_REQUEST_SENSE;
        rq->cmd[4] = rq->data_len = 18;
 
-       rq->flags = REQ_SENSE;
+       rq->cmd_type = REQ_TYPE_SENSE;
 
        /* NOTE! Save the failed command in "rq->buffer" */
        rq->buffer = (void *) failed_command;
@@ -630,10 +630,10 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
        struct request *rq = HWGROUP(drive)->rq;
        int nsectors = rq->hard_cur_sectors;
 
-       if ((rq->flags & REQ_SENSE) && uptodate) {
+       if (blk_sense_request(rq) && uptodate) {
                /*
-                * For REQ_SENSE, "rq->buffer" points to the original failed
-                * request
+                * For REQ_TYPE_SENSE, "rq->buffer" points to the original
+                * failed request
                 */
                struct request *failed = (struct request *) rq->buffer;
                struct cdrom_info *info = drive->driver_data;
@@ -706,17 +706,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                return 1;
        }
 
-       if (rq->flags & REQ_SENSE) {
+       if (blk_sense_request(rq)) {
                /* We got an error trying to get sense info
                   from the drive (probably while trying
                   to recover from a former error).  Just give up. */
 
-               rq->flags |= REQ_FAILED;
+               rq->cmd_flags |= REQ_FAILED;
                cdrom_end_request(drive, 0);
                ide_error(drive, "request sense failure", stat);
                return 1;
 
-       } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
+       } else if (blk_pc_request(rq)) {
                /* All other functions, except for READ. */
                unsigned long flags;
 
@@ -724,7 +724,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                 * if we have an error, pass back CHECK_CONDITION as the
                 * scsi status byte
                 */
-               if ((rq->flags & REQ_BLOCK_PC) && !rq->errors)
+               if (!rq->errors)
                        rq->errors = SAM_STAT_CHECK_CONDITION;
 
                /* Check for tray open. */
@@ -735,12 +735,12 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                        cdrom_saw_media_change (drive);
                        /*printk("%s: media changed\n",drive->name);*/
                        return 0;
-               } else if (!(rq->flags & REQ_QUIET)) {
+               } else if (!(rq->cmd_flags & REQ_QUIET)) {
                        /* Otherwise, print an error. */
                        ide_dump_status(drive, "packet command error", stat);
                }
                
-               rq->flags |= REQ_FAILED;
+               rq->cmd_flags |= REQ_FAILED;
 
                /*
                 * instead of playing games with moving completions around,
@@ -881,7 +881,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
                        wait = ATAPI_WAIT_PC;
                        break;
                default:
-                       if (!(rq->flags & REQ_QUIET))
+                       if (!(rq->cmd_flags & REQ_QUIET))
                                printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
                        wait = 0;
                        break;
@@ -1124,7 +1124,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
                if (rq->current_nr_sectors > 0) {
                        printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
                                drive->name, rq->current_nr_sectors);
-                       rq->flags |= REQ_FAILED;
+                       rq->cmd_flags |= REQ_FAILED;
                        cdrom_end_request(drive, 0);
                } else
                        cdrom_end_request(drive, 1);
@@ -1456,7 +1456,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
                        printk ("%s: cdrom_pc_intr: data underrun %d\n",
                                drive->name, pc->buflen);
                        */
-                       rq->flags |= REQ_FAILED;
+                       rq->cmd_flags |= REQ_FAILED;
                        cdrom_end_request(drive, 0);
                }
                return ide_stopped;
@@ -1509,7 +1509,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
                rq->data += thislen;
                rq->data_len -= thislen;
 
-               if (rq->flags & REQ_SENSE)
+               if (blk_sense_request(rq))
                        rq->sense_len += thislen;
        } else {
 confused:
@@ -1517,7 +1517,7 @@ confused:
                        "appears confused (ireason = 0x%02x). "
                        "Trying to recover by ending request.\n",
                        drive->name, ireason);
-               rq->flags |= REQ_FAILED;
+               rq->cmd_flags |= REQ_FAILED;
                cdrom_end_request(drive, 0);
                return ide_stopped;
        }
@@ -1546,7 +1546,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
        struct cdrom_info *info = drive->driver_data;
 
        info->dma = 0;
-       rq->flags &= ~REQ_FAILED;
+       rq->cmd_flags &= ~REQ_FAILED;
        len = rq->data_len;
 
        /* Start sending the command to the drive. */
@@ -1558,7 +1558,7 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
 {
        struct request_sense sense;
        int retries = 10;
-       unsigned int flags = rq->flags;
+       unsigned int flags = rq->cmd_flags;
 
        if (rq->sense == NULL)
                rq->sense = &sense;
@@ -1567,14 +1567,14 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
        do {
                int error;
                unsigned long time = jiffies;
-               rq->flags = flags;
+               rq->cmd_flags = flags;
 
                error = ide_do_drive_cmd(drive, rq, ide_wait);
                time = jiffies - time;
 
                /* FIXME: we should probably abort/retry or something 
                 * in case of failure */
-               if (rq->flags & REQ_FAILED) {
+               if (rq->cmd_flags & REQ_FAILED) {
                        /* The request failed.  Retry if it was due to a unit
                           attention status
                           (usually means media was changed). */
@@ -1596,10 +1596,10 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
                }
 
                /* End of retry loop. */
-       } while ((rq->flags & REQ_FAILED) && retries >= 0);
+       } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
 
        /* Return an error if the command failed. */
-       return (rq->flags & REQ_FAILED) ? -EIO : 0;
+       return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
 }
 
 /*
@@ -1963,7 +1963,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
 {
        struct cdrom_info *info = drive->driver_data;
 
-       rq->flags |= REQ_QUIET;
+       rq->cmd_flags |= REQ_QUIET;
 
        info->dma = 0;
 
@@ -2023,11 +2023,11 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
                }
                info->last_block = block;
                return action;
-       } else if (rq->flags & (REQ_PC | REQ_SENSE)) {
+       } else if (rq->cmd_type == REQ_TYPE_SENSE) {
                return cdrom_do_packet_command(drive);
-       } else if (rq->flags & REQ_BLOCK_PC) {
+       } else if (blk_pc_request(rq)) {
                return cdrom_do_block_pc(drive, rq);
-       } else if (rq->flags & REQ_SPECIAL) {
+       } else if (blk_special_request(rq)) {
                /*
                 * right now this can only be a reset...
                 */
@@ -2105,7 +2105,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
 
        req.sense = sense;
        req.cmd[0] = GPCMD_TEST_UNIT_READY;
-       req.flags |= REQ_QUIET;
+       req.cmd_flags |= REQ_QUIET;
 
 #if ! STANDARD_ATAPI
         /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
@@ -2207,7 +2207,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
        req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
        req.data = (char *)&capbuf;
        req.data_len = sizeof(capbuf);
-       req.flags |= REQ_QUIET;
+       req.cmd_flags |= REQ_QUIET;
 
        stat = cdrom_queue_packet_command(drive, &req);
        if (stat == 0) {
@@ -2230,7 +2230,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
        req.sense = sense;
        req.data =  buf;
        req.data_len = buflen;
-       req.flags |= REQ_QUIET;
+       req.cmd_flags |= REQ_QUIET;
        req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
        req.cmd[6] = trackno;
        req.cmd[7] = (buflen >> 8);
@@ -2531,7 +2531,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
        req.timeout = cgc->timeout;
 
        if (cgc->quiet)
-               req.flags |= REQ_QUIET;
+               req.cmd_flags |= REQ_QUIET;
 
        req.sense = cgc->sense;
        cgc->stat = cdrom_queue_packet_command(drive, &req);
@@ -2629,7 +2629,8 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
        int ret;
 
        cdrom_prepare_request(drive, &req);
-       req.flags = REQ_SPECIAL | REQ_QUIET;
+       req.cmd_type = REQ_TYPE_SPECIAL;
+       req.cmd_flags = REQ_QUIET;
        ret = ide_do_drive_cmd(drive, &req, ide_wait);
 
        /*
@@ -3116,9 +3117,9 @@ static int ide_cdrom_prep_pc(struct request *rq)
 
 static int ide_cdrom_prep_fn(request_queue_t *q, struct request *rq)
 {
-       if (rq->flags & REQ_CMD)
+       if (blk_fs_request(rq))
                return ide_cdrom_prep_fs(q, rq);
-       else if (rq->flags & REQ_BLOCK_PC)
+       else if (blk_pc_request(rq))
                return ide_cdrom_prep_pc(rq);
 
        return 0;
index 7cf3eb02352140d8f8558533aee4107c8fd1a445..0a05a377d66ac54a77056fd67cf484cf5bdf8fec 100644 (file)
@@ -699,7 +699,8 @@ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq)
                rq->cmd[0] = WIN_FLUSH_CACHE;
 
 
-       rq->flags |= REQ_DRIVE_TASK;
+       rq->cmd_type = REQ_TYPE_ATA_TASK;
+       rq->cmd_flags |= REQ_SOFTBARRIER;
        rq->buffer = rq->cmd;
 }
 
@@ -740,7 +741,7 @@ static int set_multcount(ide_drive_t *drive, int arg)
        if (drive->special.b.set_multmode)
                return -EBUSY;
        ide_init_drive_cmd (&rq);
-       rq.flags = REQ_DRIVE_CMD;
+       rq.cmd_type = REQ_TYPE_ATA_CMD;
        drive->mult_req = arg;
        drive->special.b.set_multmode = 1;
        (void) ide_do_drive_cmd (drive, &rq, ide_wait);
index 7c3a13e1cf647a4cbca6ee39c327c36f9de8d422..c3546fe9af63dbc718447523d116ed75ede19083 100644 (file)
@@ -205,7 +205,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
        ide_hwif_t *hwif = HWIF(drive);
        struct scatterlist *sg = hwif->sg_table;
 
-       BUG_ON((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256);
+       BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256);
 
        ide_map_sg(drive, rq);
 
index adbe9f76a50533c64355078e77bf1ce564de746e..8ccee9c769f8ad54ee80f539a16eaa3a15615684 100644 (file)
@@ -588,7 +588,7 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
        /* Why does this happen? */
        if (!rq)
                return 0;
-       if (!(rq->flags & REQ_SPECIAL)) { //if (!IDEFLOPPY_RQ_CMD (rq->cmd)) {
+       if (!blk_special_request(rq)) {
                /* our real local end request function */
                ide_end_request(drive, uptodate, nsecs);
                return 0;
@@ -689,7 +689,7 @@ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struc
 
        ide_init_drive_cmd(rq);
        rq->buffer = (char *) pc;
-       rq->flags = REQ_SPECIAL;        //rq->cmd = IDEFLOPPY_PC_RQ;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
        rq->rq_disk = floppy->disk;
        (void) ide_do_drive_cmd(drive, rq, ide_preempt);
 }
@@ -1250,7 +1250,7 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t
        pc->callback = &idefloppy_rw_callback;
        pc->rq = rq;
        pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
-       if (rq->flags & REQ_RW)
+       if (rq->cmd_flags & REQ_RW)
                set_bit(PC_WRITING, &pc->flags);
        pc->buffer = NULL;
        pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;
@@ -1281,8 +1281,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
        idefloppy_pc_t *pc;
        unsigned long block = (unsigned long)block_s;
 
-       debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
-                       rq->rq_status,
+       debug_log(KERN_INFO "dev: %s, flags: %lx, errors: %d\n",
                        rq->rq_disk ? rq->rq_disk->disk_name : "?",
                        rq->flags, rq->errors);
        debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
@@ -1303,7 +1302,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
                idefloppy_do_end_request(drive, 0, 0);
                return ide_stopped;
        }
-       if (rq->flags & REQ_CMD) {
+       if (blk_fs_request(rq)) {
                if (((long)rq->sector % floppy->bs_factor) ||
                    (rq->nr_sectors % floppy->bs_factor)) {
                        printk("%s: unsupported r/w request size\n",
@@ -1313,9 +1312,9 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
                }
                pc = idefloppy_next_pc_storage(drive);
                idefloppy_create_rw_cmd(floppy, pc, rq, block);
-       } else if (rq->flags & REQ_SPECIAL) {
+       } else if (blk_special_request(rq)) {
                pc = (idefloppy_pc_t *) rq->buffer;
-       } else if (rq->flags & REQ_BLOCK_PC) {
+       } else if (blk_pc_request(rq)) {
                pc = idefloppy_next_pc_storage(drive);
                if (idefloppy_blockpc_cmd(floppy, pc, rq)) {
                        idefloppy_do_end_request(drive, 0, 0);
@@ -1343,7 +1342,7 @@ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
 
        ide_init_drive_cmd (&rq);
        rq.buffer = (char *) pc;
-       rq.flags = REQ_SPECIAL;         //      rq.cmd = IDEFLOPPY_PC_RQ;
+       rq.cmd_type = REQ_TYPE_SPECIAL;
        rq.rq_disk = floppy->disk;
 
        return ide_do_drive_cmd(drive, &rq, ide_wait);
index fb6795236e76c677c9bf990a48dc62ec675da8da..38479a29d3e10a4e07236c0466fc0b81b4ba4a3b 100644 (file)
@@ -59,7 +59,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
 {
        int ret = 1;
 
-       BUG_ON(!(rq->flags & REQ_STARTED));
+       BUG_ON(!blk_rq_started(rq));
 
        /*
         * if failfast is set on a request, override number of sectors and
@@ -141,7 +141,7 @@ enum {
 
 static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
 {
-       struct request_pm_state *pm = rq->end_io_data;
+       struct request_pm_state *pm = rq->data;
 
        if (drive->media != ide_disk)
                return;
@@ -164,7 +164,7 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
 
 static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
 {
-       struct request_pm_state *pm = rq->end_io_data;
+       struct request_pm_state *pm = rq->data;
        ide_task_t *args = rq->special;
 
        memset(args, 0, sizeof(*args));
@@ -244,7 +244,7 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
 
        spin_lock_irqsave(&ide_lock, flags);
 
-       BUG_ON(!(rq->flags & REQ_STARTED));
+       BUG_ON(!blk_rq_started(rq));
 
        /*
         * if failfast is set on a request, override number of sectors and
@@ -366,7 +366,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
        rq = HWGROUP(drive)->rq;
        spin_unlock_irqrestore(&ide_lock, flags);
 
-       if (rq->flags & REQ_DRIVE_CMD) {
+       if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
                u8 *args = (u8 *) rq->buffer;
                if (rq->errors == 0)
                        rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
@@ -376,7 +376,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
                        args[1] = err;
                        args[2] = hwif->INB(IDE_NSECTOR_REG);
                }
-       } else if (rq->flags & REQ_DRIVE_TASK) {
+       } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
                u8 *args = (u8 *) rq->buffer;
                if (rq->errors == 0)
                        rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
@@ -390,7 +390,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
                        args[5] = hwif->INB(IDE_HCYL_REG);
                        args[6] = hwif->INB(IDE_SELECT_REG);
                }
-       } else if (rq->flags & REQ_DRIVE_TASKFILE) {
+       } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
                ide_task_t *args = (ide_task_t *) rq->special;
                if (rq->errors == 0)
                        rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
@@ -421,7 +421,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
                        }
                }
        } else if (blk_pm_request(rq)) {
-               struct request_pm_state *pm = rq->end_io_data;
+               struct request_pm_state *pm = rq->data;
 #ifdef DEBUG_PM
                printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
                        drive->name, rq->pm->pm_step, stat, err);
@@ -587,7 +587,7 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
                return ide_stopped;
 
        /* retry only "normal" I/O: */
-       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
+       if (!blk_fs_request(rq)) {
                rq->errors = 1;
                ide_end_drive_cmd(drive, stat, err);
                return ide_stopped;
@@ -638,7 +638,7 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
                return ide_stopped;
 
        /* retry only "normal" I/O: */
-       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
+       if (!blk_fs_request(rq)) {
                rq->errors = 1;
                ide_end_drive_cmd(drive, BUSY_STAT, 0);
                return ide_stopped;
@@ -808,7 +808,7 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq)
        if (hwif->sg_mapped)    /* needed by ide-scsi */
                return;
 
-       if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) {
+       if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) {
                hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
        } else {
                sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
@@ -844,7 +844,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
                struct request *rq)
 {
        ide_hwif_t *hwif = HWIF(drive);
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
+       if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
                ide_task_t *args = rq->special;
  
                if (!args)
@@ -866,7 +866,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
                if (args->tf_out_flags.all != 0) 
                        return flagged_taskfile(drive, args);
                return do_rw_taskfile(drive, args);
-       } else if (rq->flags & REQ_DRIVE_TASK) {
+       } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
                u8 *args = rq->buffer;
                u8 sel;
  
@@ -892,7 +892,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
                hwif->OUTB(sel, IDE_SELECT_REG);
                ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
                return ide_started;
-       } else if (rq->flags & REQ_DRIVE_CMD) {
+       } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
                u8 *args = rq->buffer;
 
                if (!args)
@@ -933,7 +933,7 @@ done:
 
 static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
 {
-       struct request_pm_state *pm = rq->end_io_data;
+       struct request_pm_state *pm = rq->data;
 
        if (blk_pm_suspend_request(rq) &&
            pm->pm_step == ide_pm_state_start_suspend)
@@ -980,7 +980,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
        ide_startstop_t startstop;
        sector_t block;
 
-       BUG_ON(!(rq->flags & REQ_STARTED));
+       BUG_ON(!blk_rq_started(rq));
 
 #ifdef DEBUG
        printk("%s: start_request: current=0x%08lx\n",
@@ -1013,12 +1013,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
        if (!drive->special.all) {
                ide_driver_t *drv;
 
-               if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK))
-                       return execute_drive_cmd(drive, rq);
-               else if (rq->flags & REQ_DRIVE_TASKFILE)
+               if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+                   rq->cmd_type == REQ_TYPE_ATA_TASK ||
+                   rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
                        return execute_drive_cmd(drive, rq);
                else if (blk_pm_request(rq)) {
-                       struct request_pm_state *pm = rq->end_io_data;
+                       struct request_pm_state *pm = rq->data;
 #ifdef DEBUG_PM
                        printk("%s: start_power_step(step: %d)\n",
                                drive->name, rq->pm->pm_step);
@@ -1264,7 +1264,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                 * We count how many times we loop here to make sure we service
                 * all drives in the hwgroup without looping for ever
                 */
-               if (drive->blocked && !blk_pm_request(rq) && !(rq->flags & REQ_PREEMPT)) {
+               if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) {
                        drive = drive->next ? drive->next : hwgroup->drive;
                        if (loops++ < 4 && !blk_queue_plugged(drive->queue))
                                goto again;
@@ -1670,7 +1670,7 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs)
 void ide_init_drive_cmd (struct request *rq)
 {
        memset(rq, 0, sizeof(*rq));
-       rq->flags = REQ_DRIVE_CMD;
+       rq->cmd_type = REQ_TYPE_ATA_CMD;
        rq->ref_count = 1;
 }
 
@@ -1710,7 +1710,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
        int must_wait = (action == ide_wait || action == ide_head_wait);
 
        rq->errors = 0;
-       rq->rq_status = RQ_ACTIVE;
 
        /*
         * we need to hold an extra reference to request for safe inspection
@@ -1718,7 +1717,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
         */
        if (must_wait) {
                rq->ref_count++;
-               rq->waiting = &wait;
+               rq->end_io_data = &wait;
                rq->end_io = blk_end_sync_rq;
        }
 
@@ -1727,7 +1726,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
                hwgroup->rq = NULL;
        if (action == ide_preempt || action == ide_head_wait) {
                where = ELEVATOR_INSERT_FRONT;
-               rq->flags |= REQ_PREEMPT;
+               rq->cmd_flags |= REQ_PREEMPT;
        }
        __elv_add_request(drive->queue, rq, where, 0);
        ide_do_request(hwgroup, IDE_NO_IRQ);
@@ -1736,7 +1735,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
        err = 0;
        if (must_wait) {
                wait_for_completion(&wait);
-               rq->waiting = NULL;
                if (rq->errors)
                        err = -EIO;
 
index 1feff23487d44f515574809e153744a615c7ad26..850ef63cc986ba695ba643f5b13483c49a430a6c 100644 (file)
@@ -456,13 +456,14 @@ static void ide_dump_opcode(ide_drive_t *drive)
        spin_unlock(&ide_lock);
        if (!rq)
                return;
-       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+       if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+           rq->cmd_type == REQ_TYPE_ATA_TASK) {
                char *args = rq->buffer;
                if (args) {
                        opcode = args[0];
                        found = 1;
                }
-       } else if (rq->flags & REQ_DRIVE_TASKFILE) {
+       } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
                ide_task_t *args = rq->special;
                if (args) {
                        task_struct_t *tf = (task_struct_t *) args->tfRegister;
index 7067ab997927d5515f32f2b09c8a48af1cc34cdf..e2f4bb5490638de5c1326dc863c322417c99002b 100644 (file)
@@ -1776,7 +1776,7 @@ static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
 static void idetape_init_rq(struct request *rq, u8 cmd)
 {
        memset(rq, 0, sizeof(*rq));
-       rq->flags = REQ_SPECIAL;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
        rq->cmd[0] = cmd;
 }
 
@@ -2423,8 +2423,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
 #if IDETAPE_DEBUG_LOG
 #if 0
        if (tape->debug_level >= 5)
-               printk(KERN_INFO "ide-tape: rq_status: %d, "
-                       "dev: %s, cmd: %ld, errors: %d\n", rq->rq_status,
+               printk(KERN_INFO "ide-tape:  %d, "
+                       "dev: %s, cmd: %ld, errors: %d\n",
                         rq->rq_disk->disk_name, rq->cmd[0], rq->errors);
 #endif
        if (tape->debug_level >= 2)
@@ -2433,12 +2433,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                        rq->sector, rq->nr_sectors, rq->current_nr_sectors);
 #endif /* IDETAPE_DEBUG_LOG */
 
-       if ((rq->flags & REQ_SPECIAL) == 0) {
+       if (!blk_special_request(rq)) {
                /*
                 * We do not support buffer cache originated requests.
                 */
                printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
-                       "request queue (%ld)\n", drive->name, rq->flags);
+                       "request queue (%d)\n", drive->name, rq->cmd_type);
                ide_end_request(drive, 0, 0);
                return ide_stopped;
        }
@@ -2764,16 +2764,16 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
  */
 static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
 {
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
        idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_BUGS
-       if (rq == NULL || (rq->flags & REQ_SPECIAL) == 0) {
+       if (rq == NULL || !blk_special_request(rq)) {
                printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
                return;
        }
 #endif /* IDETAPE_DEBUG_BUGS */
-       rq->waiting = &wait;
+       rq->end_io_data = &wait;
        rq->end_io = blk_end_sync_rq;
        spin_unlock_irq(&tape->spinlock);
        wait_for_completion(&wait);
index 97a9244312fc0492fc813e2effa99cbbe2542b55..1d0470c1f9579d262f0e93c2fcebab6dd89ad399 100644 (file)
@@ -363,7 +363,7 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
 
 static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
 {
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
+       if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
                ide_task_t *task = rq->special;
 
                if (task->tf_out_flags.all) {
@@ -474,7 +474,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
        struct request rq;
 
        memset(&rq, 0, sizeof(rq));
-       rq.flags = REQ_DRIVE_TASKFILE;
+       rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
        rq.buffer = buf;
 
        /*
@@ -499,7 +499,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
                rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
 
                if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-                       rq.flags |= REQ_RW;
+                       rq.cmd_flags |= REQ_RW;
        }
 
        rq.special = args;
@@ -737,7 +737,7 @@ static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
        struct request rq;
 
        ide_init_drive_cmd(&rq);
-       rq.flags = REQ_DRIVE_TASK;
+       rq.cmd_type = REQ_TYPE_ATA_TASK;
        rq.buffer = buf;
        return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
index 9c8468de1a7521aa62c179cd6bf952fa461a2a4c..2b1a1389c31880b16d492f8145ddfe5ac96acd90 100644 (file)
@@ -1217,9 +1217,9 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
        memset(&rq, 0, sizeof(rq));
        memset(&rqpm, 0, sizeof(rqpm));
        memset(&args, 0, sizeof(args));
-       rq.flags = REQ_PM_SUSPEND;
+       rq.cmd_type = REQ_TYPE_PM_SUSPEND;
        rq.special = &args;
-       rq.end_io_data = &rqpm;
+       rq.data = &rqpm;
        rqpm.pm_step = ide_pm_state_start_suspend;
        if (mesg.event == PM_EVENT_PRETHAW)
                mesg.event = PM_EVENT_FREEZE;
@@ -1238,9 +1238,9 @@ static int generic_ide_resume(struct device *dev)
        memset(&rq, 0, sizeof(rq));
        memset(&rqpm, 0, sizeof(rqpm));
        memset(&args, 0, sizeof(args));
-       rq.flags = REQ_PM_RESUME;
+       rq.cmd_type = REQ_TYPE_PM_RESUME;
        rq.special = &args;
-       rq.end_io_data = &rqpm;
+       rq.data = &rqpm;
        rqpm.pm_step = ide_pm_state_start_resume;
        rqpm.pm_state = PM_EVENT_ON;
 
index aebecd8f51ccd7be2119164ff3bf3d58a9525b46..4ab93114567389122323e22a413280216c5729d1 100644 (file)
@@ -626,7 +626,7 @@ repeat:
                req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
                cyl, head, sec, nsect, req->buffer);
 #endif
-       if (req->flags & REQ_CMD) {
+       if (blk_fs_request(req)) {
                switch (rq_data_dir(req)) {
                case READ:
                        hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
index a574de5f083572933ce68c5898ccae7192d5218c..d55b938b1aebeb83bc7d60e3016e7e2b28fdc40b 100644 (file)
@@ -318,6 +318,20 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
        hwif->drives[0].autodma = hwif->autodma;
 }
 
+static void __devinit init_hwif_sb600_legacy(ide_hwif_t *hwif)
+{
+
+       hwif->atapi_dma = 1;
+       hwif->ultra_mask = 0x7f;
+       hwif->mwdma_mask = 0x07;
+       hwif->swdma_mask = 0x07;
+
+       if (!noautodma)
+               hwif->autodma = 1;
+       hwif->drives[0].autodma = hwif->autodma;
+       hwif->drives[1].autodma = hwif->autodma;
+}
+
 static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
        {       /* 0 */
                .name           = "ATIIXP",
@@ -326,6 +340,12 @@ static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
                .autodma        = AUTODMA,
                .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
                .bootable       = ON_BOARD,
+       },{     /* 1 */
+               .name           = "ATI SB600 SATA Legacy IDE",
+               .init_hwif      = init_hwif_sb600_legacy,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = ON_BOARD,
        }
 };
 
@@ -348,6 +368,7 @@ static struct pci_device_id atiixp_pci_tbl[] = {
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, PCI_ANY_ID, PCI_ANY_ID, (PCI_CLASS_STORAGE_IDE<<8)|0x8a, 0xffff05, 1},
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
index 50332ddd5ddb9d3a2efd3617760cfb9191ae0f8a..eb5bab1890cd1d484b553597e0ced72962da8f1b 100644 (file)
@@ -615,7 +615,7 @@ static void __devinit piix_check_450nx(void)
        struct pci_dev *pdev = NULL;
        u16 cfg;
        u8 rev;
-       while((pdev=pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
+       while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
        {
                /* Look for 450NX PXB. Check for problem configurations
                   A PCI quirk checks bit 6 already */
index f063d954236c02baf9e04f04f5bb7e0d4b651dbb..057548d072056dfe70e63667d21d483d402be317 100644 (file)
@@ -359,7 +359,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
 
        /* OSB4 : South Bridge and IDE */
        if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-               isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
+               isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
                          PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
                if (isa_dev) {
                        pci_read_config_dword(isa_dev, 0x64, &reg);
@@ -380,7 +380,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
                if (!(PCI_FUNC(dev->devfn) & 1)) {
                        struct pci_dev * findev = NULL;
                        u32 reg4c = 0;
-                       findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
+                       findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
                                PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
                        if (findev) {
                                pci_read_config_dword(findev, 0x4C, &reg4c);
@@ -388,6 +388,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
                                reg4c |=  0x00000040;
                                reg4c |=  0x00000020;
                                pci_write_config_dword(findev, 0x4C, reg4c);
+                               pci_dev_put(findev);
                        }
                        outb_p(0x06, 0x0c00);
                        dev->irq = inb_p(0x0c01);
@@ -395,12 +396,13 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
                        struct pci_dev * findev = NULL;
                        u8 reg41 = 0;
 
-                       findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
+                       findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
                                        PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL);
                        if (findev) {
                                pci_read_config_byte(findev, 0x41, &reg41);
                                reg41 &= ~0x40;
                                pci_write_config_byte(findev, 0x41, reg41);
+                               pci_dev_put(findev);
                        }
                        /*
                         * This is a device pin issue on CSB6.
index f03196c5db37a49c2290b46f0be030de7108fb47..92edf76bd7adb1880b677558a56bc7d1528c47b2 100644 (file)
@@ -739,7 +739,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
 
        for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {
 
-               host = pci_find_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
+               host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
 
                if (!host)
                        continue;
@@ -753,6 +753,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
                        if (hostrev >= 0x30)
                                chipset_family = ATA_100a;
                }
+               pci_dev_put(host);
        
                printk(KERN_INFO "SIS5513: %s %s controller\n",
                         SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
index 186737539cf5f4fe32fac373fe982724bd5ac7ec..2769e505f051530cb676cf60df41b59a34161ceb 100644 (file)
@@ -120,12 +120,19 @@ config IEEE1394_VIDEO1394
          this option only if you have an IEEE 1394 video device connected to
          an OHCI-1394 card.
 
+comment "SBP-2 support (for storage devices) requires SCSI"
+       depends on IEEE1394 && SCSI=n
+
 config IEEE1394_SBP2
        tristate "SBP-2 support (Harddisks etc.)"
        depends on IEEE1394 && SCSI && (PCI || BROKEN)
        help
-         This option enables you to use SBP-2 devices connected to your IEEE
-         1394 bus.  SBP-2 devices include harddrives and DVD devices.
+         This option enables you to use SBP-2 devices connected to an IEEE
+         1394 bus.  SBP-2 devices include storage devices like harddisks and
+         DVD drives, also some other FireWire devices like scanners.
+
+         You should also enable support for disks, CD-ROMs, etc. in the SCSI
+         configuration section.
 
 config IEEE1394_SBP2_PHYS_DMA
        bool "Enable replacement for physical DMA in SBP2"
index 149573db91c5a1dc35d727694de54263f0dc96f3..ab0c80f61b9d184152d6ed2005cfae5f360e7835 100644 (file)
  *
  */
 
-#include <linux/string.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/param.h>
 #include <linux/spinlock.h>
+#include <linux/string.h>
 
 #include "csr1212.h"
 #include "ieee1394_types.h"
@@ -149,31 +151,18 @@ static void host_reset(struct hpsb_host *host)
 
 /*
  * HI == seconds (bits 0:2)
- * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31)
- *
- * Convert to units and then to HZ, for comparison to jiffies.
- *
- * By default this will end up being 800 units, or 100ms (125usec per
- * unit).
+ * LO == fractions of a second in units of 125usec (bits 19:31)
  *
- * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192
- * like CSR specifies. Should make our math less complex.
+ * Convert SPLIT_TIMEOUT to jiffies.
+ * The default and minimum as per 1394a-2000 clause 8.3.2.2.6 is 100ms.
  */
 static inline void calculate_expire(struct csr_control *csr)
 {
-       unsigned long units;
-
-       /* Take the seconds, and convert to units */
-       units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13;
-
-       /* Add in the fractional units */
-       units += (unsigned long)(csr->split_timeout_lo >> 19);
-
-       /* Convert to jiffies */
-       csr->expire = (unsigned long)(units * HZ) >> 13UL;
+       unsigned long usecs =
+               (csr->split_timeout_hi & 0x07) * USEC_PER_SEC +
+               (csr->split_timeout_lo >> 19) * 125L;
 
-       /* Just to keep from rounding low */
-       csr->expire++;
+       csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L);
 
        HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
 }
index ea9aa4f53ab688dd3703d5f4ddc400eee047c0b7..f11546550d84efa01bfdf03f127d50e467dc2820 100644 (file)
@@ -1,75 +1,73 @@
-
 #ifndef _IEEE1394_CSR_H
 #define _IEEE1394_CSR_H
 
-#ifdef CONFIG_PREEMPT
-#include <linux/sched.h>
-#endif
+#include <linux/spinlock_types.h>
 
 #include "csr1212.h"
+#include "ieee1394_types.h"
 
-#define CSR_REGISTER_BASE  0xfffff0000000ULL
+#define CSR_REGISTER_BASE              0xfffff0000000ULL
 
 /* register offsets relative to CSR_REGISTER_BASE */
-#define CSR_STATE_CLEAR           0x0
-#define CSR_STATE_SET             0x4
-#define CSR_NODE_IDS              0x8
-#define CSR_RESET_START           0xc
-#define CSR_SPLIT_TIMEOUT_HI      0x18
-#define CSR_SPLIT_TIMEOUT_LO      0x1c
-#define CSR_CYCLE_TIME            0x200
-#define CSR_BUS_TIME              0x204
-#define CSR_BUSY_TIMEOUT          0x210
-#define CSR_BUS_MANAGER_ID        0x21c
-#define CSR_BANDWIDTH_AVAILABLE   0x220
-#define CSR_CHANNELS_AVAILABLE    0x224
-#define CSR_CHANNELS_AVAILABLE_HI 0x224
-#define CSR_CHANNELS_AVAILABLE_LO 0x228
-#define CSR_BROADCAST_CHANNEL     0x234
-#define CSR_CONFIG_ROM            0x400
-#define CSR_CONFIG_ROM_END        0x800
-#define CSR_FCP_COMMAND           0xB00
-#define CSR_FCP_RESPONSE          0xD00
-#define CSR_FCP_END               0xF00
-#define CSR_TOPOLOGY_MAP          0x1000
-#define CSR_TOPOLOGY_MAP_END      0x1400
-#define CSR_SPEED_MAP             0x2000
-#define CSR_SPEED_MAP_END         0x3000
+#define CSR_STATE_CLEAR                        0x0
+#define CSR_STATE_SET                  0x4
+#define CSR_NODE_IDS                   0x8
+#define CSR_RESET_START                        0xc
+#define CSR_SPLIT_TIMEOUT_HI           0x18
+#define CSR_SPLIT_TIMEOUT_LO           0x1c
+#define CSR_CYCLE_TIME                 0x200
+#define CSR_BUS_TIME                   0x204
+#define CSR_BUSY_TIMEOUT               0x210
+#define CSR_BUS_MANAGER_ID             0x21c
+#define CSR_BANDWIDTH_AVAILABLE                0x220
+#define CSR_CHANNELS_AVAILABLE         0x224
+#define CSR_CHANNELS_AVAILABLE_HI      0x224
+#define CSR_CHANNELS_AVAILABLE_LO      0x228
+#define CSR_BROADCAST_CHANNEL          0x234
+#define CSR_CONFIG_ROM                 0x400
+#define CSR_CONFIG_ROM_END             0x800
+#define CSR_FCP_COMMAND                        0xB00
+#define CSR_FCP_RESPONSE               0xD00
+#define CSR_FCP_END                    0xF00
+#define CSR_TOPOLOGY_MAP               0x1000
+#define CSR_TOPOLOGY_MAP_END           0x1400
+#define CSR_SPEED_MAP                  0x2000
+#define CSR_SPEED_MAP_END              0x3000
 
 /* IEEE 1394 bus specific Configuration ROM Key IDs */
 #define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
 
-/* IEEE 1394 Bus Inforamation Block specifics */
+/* IEEE 1394 Bus Information Block specifics */
 #define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
 
-#define CSR_IRMC_SHIFT 31
-#define CSR_CMC_SHIFT  30
-#define CSR_ISC_SHIFT  29
-#define CSR_BMC_SHIFT  28
-#define CSR_PMC_SHIFT  27
-#define CSR_CYC_CLK_ACC_SHIFT 16
-#define CSR_MAX_REC_SHIFT 12
-#define CSR_MAX_ROM_SHIFT 8
-#define CSR_GENERATION_SHIFT 4
+#define CSR_IRMC_SHIFT                 31
+#define CSR_CMC_SHIFT                  30
+#define CSR_ISC_SHIFT                  29
+#define CSR_BMC_SHIFT                  28
+#define CSR_PMC_SHIFT                  27
+#define CSR_CYC_CLK_ACC_SHIFT          16
+#define CSR_MAX_REC_SHIFT              12
+#define CSR_MAX_ROM_SHIFT              8
+#define CSR_GENERATION_SHIFT           4
 
 #define CSR_SET_BUS_INFO_GENERATION(csr, gen)                          \
        ((csr)->bus_info_data[2] =                                      \
                cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) &     \
-                            ~(0xf << CSR_GENERATION_SHIFT)) |          \
+                            ~(0xf << CSR_GENERATION_SHIFT)) |          \
                            (gen) << CSR_GENERATION_SHIFT))
 
 struct csr_control {
-        spinlock_t lock;
-
-        quadlet_t state;
-        quadlet_t node_ids;
-        quadlet_t split_timeout_hi, split_timeout_lo;
-       unsigned long expire;   // Calculated from split_timeout
-        quadlet_t cycle_time;
-        quadlet_t bus_time;
-        quadlet_t bus_manager_id;
-        quadlet_t bandwidth_available;
-        quadlet_t channels_available_hi, channels_available_lo;
+       spinlock_t lock;
+
+       quadlet_t state;
+       quadlet_t node_ids;
+       quadlet_t split_timeout_hi, split_timeout_lo;
+       unsigned long expire;   /* Calculated from split_timeout */
+       quadlet_t cycle_time;
+       quadlet_t bus_time;
+       quadlet_t bus_manager_id;
+       quadlet_t bandwidth_available;
+       quadlet_t channels_available_hi, channels_available_lo;
        quadlet_t broadcast_channel;
 
        /* Bus Info */
@@ -84,8 +82,8 @@ struct csr_control {
 
        struct csr1212_csr *rom;
 
-        quadlet_t topology_map[256];
-        quadlet_t speed_map[1024];
+       quadlet_t topology_map[256];
+       quadlet_t speed_map[1024];
 };
 
 extern struct csr1212_bus_ops csr_bus_ops;
@@ -93,4 +91,9 @@ extern struct csr1212_bus_ops csr_bus_ops;
 int init_csr(void);
 void cleanup_csr(void);
 
+/* hpsb_update_config_rom() is deprecated */
+struct hpsb_host;
+int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
+                          size_t size, unsigned char rom_version);
+
 #endif /* _IEEE1394_CSR_H */
index ca5167de707d645de7f3305bdfc61ef2434c678b..c68f328e1a29c9c8e7db039610831ae9a0a7900b 100644 (file)
@@ -7,10 +7,13 @@
  * directory of the kernel sources for details.
  */
 
+#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/vmalloc.h>
+#include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/scatterlist.h>
+
 #include "dma.h"
 
 /* dma_prog_region */
index 061550a6fb9941669655e5eb68463b01c089ac5d..a1682aba71c7caa5aa4259825817a2498e3bcf07 100644 (file)
 #ifndef IEEE1394_DMA_H
 #define IEEE1394_DMA_H
 
-#include <linux/pci.h>
-#include <asm/scatterlist.h>
-
-/* struct dma_prog_region
-
-   a small, physically-contiguous DMA buffer with random-access,
-   synchronous usage characteristics
-*/
-
+#include <asm/types.h>
+
+struct pci_dev;
+struct scatterlist;
+struct vm_area_struct;
+
+/**
+ * struct dma_prog_region - small contiguous DMA buffer
+ * @kvirt:    kernel virtual address
+ * @dev:      PCI device
+ * @n_pages:  number of kernel pages
+ * @bus_addr: base bus address
+ *
+ * a small, physically contiguous DMA buffer with random-access, synchronous
+ * usage characteristics
+ */
 struct dma_prog_region {
-       unsigned char    *kvirt;     /* kernel virtual address */
-       struct pci_dev   *dev;       /* PCI device */
-       unsigned int      n_pages;   /* # of kernel pages */
-       dma_addr_t        bus_addr;  /* base bus address */
+       unsigned char *kvirt;
+       struct pci_dev *dev;
+       unsigned int n_pages;
+       dma_addr_t bus_addr;
 };
 
 /* clear out all fields but do not allocate any memory */
 void dma_prog_region_init(struct dma_prog_region *prog);
-int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev);
+int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
+                         struct pci_dev *dev);
 void dma_prog_region_free(struct dma_prog_region *prog);
 
-static inline dma_addr_t dma_prog_region_offset_to_bus(struct dma_prog_region *prog, unsigned long offset)
+static inline dma_addr_t dma_prog_region_offset_to_bus(
+               struct dma_prog_region *prog, unsigned long offset)
 {
        return prog->bus_addr + offset;
 }
 
-/* struct dma_region
-
-   a large, non-physically-contiguous DMA buffer with streaming,
-   asynchronous usage characteristics
-*/
-
+/**
+ * struct dma_region - large non-contiguous DMA buffer
+ * @virt:        kernel virtual address
+ * @dev:         PCI device
+ * @n_pages:     number of kernel pages
+ * @n_dma_pages: number of IOMMU pages
+ * @sglist:      IOMMU mapping
+ * @direction:   PCI_DMA_TODEVICE, etc.
+ *
+ * a large, non-physically-contiguous DMA buffer with streaming, asynchronous
+ * usage characteristics
+ */
 struct dma_region {
-       unsigned char      *kvirt;       /* kernel virtual address */
-       struct pci_dev     *dev;         /* PCI device */
-       unsigned int        n_pages;     /* # of kernel pages */
-       unsigned int        n_dma_pages; /* # of IOMMU pages */
-       struct scatterlist *sglist;      /* IOMMU mapping */
-       int                 direction;   /* PCI_DMA_TODEVICE, etc */
+       unsigned char *kvirt;
+       struct pci_dev *dev;
+       unsigned int n_pages;
+       unsigned int n_dma_pages;
+       struct scatterlist *sglist;
+       int direction;
 };
 
 /* clear out all fields but do not allocate anything */
 void dma_region_init(struct dma_region *dma);
 
 /* allocate the buffer and map it to the IOMMU */
-int  dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction);
+int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
+                    struct pci_dev *dev, int direction);
 
 /* unmap and free the buffer */
 void dma_region_free(struct dma_region *dma);
 
 /* sync the CPU's view of the buffer */
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len);
+void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
+                            unsigned long len);
+
 /* sync the IO bus' view of the buffer */
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len);
+void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
+                               unsigned long len);
 
 /* map the buffer into a user space process */
-int  dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma);
+int  dma_region_mmap(struct dma_region *dma, struct file *file,
+                    struct vm_area_struct *vma);
 
 /* macro to index into a DMA region (or dma_prog_region) */
-#define dma_region_i(_dma, _type, _index) ( ((_type*) ((_dma)->kvirt)) + (_index) )
+#define dma_region_i(_dma, _type, _index) \
+       ( ((_type*) ((_dma)->kvirt)) + (_index) )
 
 /* return the DMA bus address of the byte with the given offset
-   relative to the beginning of the dma_region */
-dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset);
+ * relative to the beginning of the dma_region */
+dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
+                                   unsigned long offset);
 
 #endif /* IEEE1394_DMA_H */
index 80b5ac7fe38341d547d0dd3f912af21dc7594c32..7d1d2845b42065a64c696b5fb19f8e0a3770275b 100644 (file)
@@ -460,7 +460,7 @@ struct video_card {
        int dma_running;
 
        /*
-         3) the sleeping semaphore 'sem' - this is used from process context only,
+         3) the sleeping mutex 'mtx' - this is used from process context only,
          to serialize various operations on the video_card. Even though only one
          open() is allowed, we still need to prevent multiple threads of execution
          from entering calls like read, write, ioctl, etc.
@@ -468,9 +468,9 @@ struct video_card {
          I honestly can't think of a good reason to use dv1394 from several threads
          at once, but we need to serialize anyway to prevent oopses =).
 
-         NOTE: if you need both spinlock and sem, take sem first to avoid deadlock!
+         NOTE: if you need both spinlock and mtx, take mtx first to avoid deadlock!
         */
-       struct semaphore sem;
+       struct mutex mtx;
 
        /* people waiting for buffer space, please form a line here... */
        wait_queue_head_t waitq;
index 87532dd43374f9625d9f06693503a63c07a2758f..6c72f04b2b5db0399f5be66ecbe5653101819892 100644 (file)
@@ -95,6 +95,7 @@
 #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>
 #include <asm/atomic.h>
 #include <linux/compat.h>
 #include <linux/cdev.h>
 
+#include "dv1394.h"
+#include "dv1394-private.h"
+#include "highlevel.h"
+#include "hosts.h"
 #include "ieee1394.h"
+#include "ieee1394_core.h"
+#include "ieee1394_hotplug.h"
 #include "ieee1394_types.h"
 #include "nodemgr.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "dv1394.h"
-#include "dv1394-private.h"
-
 #include "ohci1394.h"
 
 /* DEBUG LEVELS:
 #if DV1394_DEBUG_LEVEL >= 2
 #define irq_printk( args... ) printk( args )
 #else
-#define irq_printk( args... )
+#define irq_printk( args... ) do {} while (0)
 #endif
 
 #if DV1394_DEBUG_LEVEL >= 1
 #define debug_printk( args... ) printk( args)
 #else
-#define debug_printk( args... )
+#define debug_printk( args... ) do {} while (0)
 #endif
 
 /* issue a dummy PCI read to force the preceding write
@@ -247,7 +248,7 @@ static void frame_delete(struct frame *f)
 
    Frame_prepare() must be called OUTSIDE the video->spinlock.
    However, frame_prepare() must still be serialized, so
-   it should be called WITH the video->sem taken.
+   it should be called WITH the video->mtx taken.
  */
 
 static void frame_prepare(struct video_card *video, unsigned int this_frame)
@@ -1271,7 +1272,7 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
        int retval = -EINVAL;
 
        /* serialize mmap */
-       down(&video->sem);
+       mutex_lock(&video->mtx);
 
        if ( ! video_card_initialized(video) ) {
                retval = do_dv1394_init_default(video);
@@ -1281,7 +1282,7 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
 
        retval = dma_region_mmap(&video->dv_buf, file, vma);
 out:
-       up(&video->sem);
+       mutex_unlock(&video->mtx);
        return retval;
 }
 
@@ -1337,17 +1338,17 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t
 
        /* serialize this to prevent multi-threaded mayhem */
        if (file->f_flags & O_NONBLOCK) {
-               if (down_trylock(&video->sem))
+               if (!mutex_trylock(&video->mtx))
                        return -EAGAIN;
        } else {
-               if (down_interruptible(&video->sem))
+               if (mutex_lock_interruptible(&video->mtx))
                        return -ERESTARTSYS;
        }
 
        if ( !video_card_initialized(video) ) {
                ret = do_dv1394_init_default(video);
                if (ret) {
-                       up(&video->sem);
+                       mutex_unlock(&video->mtx);
                        return ret;
                }
        }
@@ -1418,7 +1419,7 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t
 
        remove_wait_queue(&video->waitq, &wait);
        set_current_state(TASK_RUNNING);
-       up(&video->sem);
+       mutex_unlock(&video->mtx);
        return ret;
 }
 
@@ -1434,17 +1435,17 @@ static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count
 
        /* serialize this to prevent multi-threaded mayhem */
        if (file->f_flags & O_NONBLOCK) {
-               if (down_trylock(&video->sem))
+               if (!mutex_trylock(&video->mtx))
                        return -EAGAIN;
        } else {
-               if (down_interruptible(&video->sem))
+               if (mutex_lock_interruptible(&video->mtx))
                        return -ERESTARTSYS;
        }
 
        if ( !video_card_initialized(video) ) {
                ret = do_dv1394_init_default(video);
                if (ret) {
-                       up(&video->sem);
+                       mutex_unlock(&video->mtx);
                        return ret;
                }
                video->continuity_counter = -1;
@@ -1526,7 +1527,7 @@ static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count
 
        remove_wait_queue(&video->waitq, &wait);
        set_current_state(TASK_RUNNING);
-       up(&video->sem);
+       mutex_unlock(&video->mtx);
        return ret;
 }
 
@@ -1547,12 +1548,12 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        /* serialize this to prevent multi-threaded mayhem */
        if (file->f_flags & O_NONBLOCK) {
-               if (down_trylock(&video->sem)) {
+               if (!mutex_trylock(&video->mtx)) {
                        unlock_kernel();
                        return -EAGAIN;
                }
        } else {
-               if (down_interruptible(&video->sem)) {
+               if (mutex_lock_interruptible(&video->mtx)) {
                        unlock_kernel();
                        return -ERESTARTSYS;
                }
@@ -1778,7 +1779,7 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        }
 
  out:
-       up(&video->sem);
+       mutex_unlock(&video->mtx);
        unlock_kernel();
        return ret;
 }
@@ -2253,7 +2254,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
        clear_bit(0, &video->open);
        spin_lock_init(&video->spinlock);
        video->dma_running = 0;
-       init_MUTEX(&video->sem);
+       mutex_init(&video->mtx);
        init_waitqueue_head(&video->waitq);
        video->fasync = NULL;
 
index 2d5b57be98c3b024d1f40c7cad7d6a841aee3db1..8a7b8fab62383670a600abfda49f6d718b971a5c 100644 (file)
 #include <linux/ethtool.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
-#include <asm/semaphore.h>
 #include <net/arp.h>
 
+#include "config_roms.h"
 #include "csr1212.h"
-#include "ieee1394_types.h"
+#include "eth1394.h"
+#include "highlevel.h"
+#include "ieee1394.h"
 #include "ieee1394_core.h"
+#include "ieee1394_hotplug.h"
 #include "ieee1394_transactions.h"
-#include "ieee1394.h"
-#include "highlevel.h"
+#include "ieee1394_types.h"
 #include "iso.h"
 #include "nodemgr.h"
-#include "eth1394.h"
-#include "config_roms.h"
 
 #define ETH1394_PRINT_G(level, fmt, args...) \
        printk(level "%s: " fmt, driver_name, ## args)
index e119fb87e5b594c82fae757242f8802bbac3ec20..50f2dd2c7e20afecc2dde1b95c78eeac070730da 100644 (file)
@@ -1,60 +1,61 @@
-
 #ifndef IEEE1394_HIGHLEVEL_H
 #define IEEE1394_HIGHLEVEL_H
 
+#include <linux/list.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
 
-struct hpsb_address_serve {
-        struct list_head host_list; /* per host list */
+struct module;
 
-        struct list_head hl_list; /* hpsb_highlevel list */
+#include "ieee1394_types.h"
 
-        struct hpsb_address_ops *op;
+struct hpsb_host;
 
+/* internal to ieee1394 core */
+struct hpsb_address_serve {
+       struct list_head host_list;     /* per host list */
+       struct list_head hl_list;       /* hpsb_highlevel list */
+       struct hpsb_address_ops *op;
        struct hpsb_host *host;
-
-        /* first address handled and first address behind, quadlet aligned */
-        u64 start, end;
+       u64 start;      /* first address handled, quadlet aligned */
+       u64 end;        /* first address behind, quadlet aligned */
 };
 
-
-/*
- * The above structs are internal to highlevel driver handling.  Only the
- * following structures are of interest to actual highlevel drivers.
- */
+/* Only the following structures are of interest to actual highlevel drivers. */
 
 struct hpsb_highlevel {
        struct module *owner;
        const char *name;
 
-        /* Any of the following pointers can legally be NULL, except for
-         * iso_receive which can only be NULL when you don't request
-         * channels. */
+       /* Any of the following pointers can legally be NULL, except for
+        * iso_receive which can only be NULL when you don't request
+        * channels. */
 
-        /* New host initialized.  Will also be called during
-         * hpsb_register_highlevel for all hosts already installed. */
-        void (*add_host) (struct hpsb_host *host);
+       /* New host initialized.  Will also be called during
+        * hpsb_register_highlevel for all hosts already installed. */
+       void (*add_host)(struct hpsb_host *host);
 
-        /* Host about to be removed.  Will also be called during
-         * hpsb_unregister_highlevel once for each host. */
-        void (*remove_host) (struct hpsb_host *host);
+       /* Host about to be removed.  Will also be called during
+        * hpsb_unregister_highlevel once for each host. */
+       void (*remove_host)(struct hpsb_host *host);
 
-        /* Host experienced bus reset with possible configuration changes.
+       /* Host experienced bus reset with possible configuration changes.
         * Note that this one may occur during interrupt/bottom half handling.
         * You can not expect to be able to do stock hpsb_reads. */
-        void (*host_reset) (struct hpsb_host *host);
+       void (*host_reset)(struct hpsb_host *host);
 
-        /* An isochronous packet was received.  Channel contains the channel
-         * number for your convenience, it is also contained in the included
-         * packet header (first quadlet, CRCs are missing).  You may get called
-         * for channel/host combinations you did not request. */
-        void (*iso_receive) (struct hpsb_host *host, int channel,
-                             quadlet_t *data, size_t length);
+       /* An isochronous packet was received.  Channel contains the channel
+        * number for your convenience, it is also contained in the included
+        * packet header (first quadlet, CRCs are missing).  You may get called
+        * for channel/host combinations you did not request. */
+       void (*iso_receive)(struct hpsb_host *host, int channel,
+                           quadlet_t *data, size_t length);
 
-        /* A write request was received on either the FCP_COMMAND (direction =
-         * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
-         * contains the cts field (first byte of data). */
-        void (*fcp_request) (struct hpsb_host *host, int nodeid, int direction,
-                             int cts, u8 *data, size_t length);
+       /* A write request was received on either the FCP_COMMAND (direction =
+        * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
+        * contains the cts field (first byte of data). */
+       void (*fcp_request)(struct hpsb_host *host, int nodeid, int direction,
+                           int cts, u8 *data, size_t length);
 
        /* These are initialized by the subsystem when the
         * hpsb_higlevel is registered. */
@@ -67,61 +68,62 @@ struct hpsb_highlevel {
 };
 
 struct hpsb_address_ops {
-        /*
-         * Null function pointers will make the respective operation complete
-         * with RCODE_TYPE_ERROR.  Makes for easy to implement read-only
-         * registers (just leave everything but read NULL).
-         *
-         * All functions shall return appropriate IEEE 1394 rcodes.
-         */
-
-        /* These functions have to implement block reads for themselves. */
-        /* These functions either return a response code
-           or a negative number. In the first case a response will be generated; in the
-           later case, no response will be sent and the driver, that handled the request
-           will send the response itself
-        */
-        int (*read) (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                     u64 addr, size_t length, u16 flags);
-        int (*write) (struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, size_t length, u16 flags);
-
-        /* Lock transactions: write results of ext_tcode operation into
-         * *store. */
-        int (*lock) (struct hpsb_host *host, int nodeid, quadlet_t *store,
-                     u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
-        int (*lock64) (struct hpsb_host *host, int nodeid, octlet_t *store,
-                       u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
+       /*
+        * Null function pointers will make the respective operation complete
+        * with RCODE_TYPE_ERROR.  Makes for easy to implement read-only
+        * registers (just leave everything but read NULL).
+        *
+        * All functions shall return appropriate IEEE 1394 rcodes.
+        */
+
+       /* These functions have to implement block reads for themselves.
+        *
+        * These functions either return a response code or a negative number.
+        * In the first case a response will be generated.  In the latter case,
+        * no response will be sent and the driver which handled the request
+        * will send the response itself. */
+       int (*read)(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
+                   u64 addr, size_t length, u16 flags);
+       int (*write)(struct hpsb_host *host, int nodeid, int destid,
+                    quadlet_t *data, u64 addr, size_t length, u16 flags);
+
+       /* Lock transactions: write results of ext_tcode operation into
+        * *store. */
+       int (*lock)(struct hpsb_host *host, int nodeid, quadlet_t *store,
+                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+                   u16 flags);
+       int (*lock64)(struct hpsb_host *host, int nodeid, octlet_t *store,
+                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+                     u16 flags);
 };
 
-
 void highlevel_add_host(struct hpsb_host *host);
 void highlevel_remove_host(struct hpsb_host *host);
 void highlevel_host_reset(struct hpsb_host *host);
 
-
-/* these functions are called to handle transactions. They are called, when
-   a packet arrives. The flags argument contains the second word of the first header
-   quadlet of the incoming packet (containing transaction label, retry code,
-   transaction code and priority). These functions either return a response code
  or a negative number. In the first case a response will be generated; in the
-   later case, no response will be sent and the driver, that handled the request
  will send the response itself.
-*/
-int highlevel_read(struct hpsb_host *host, int nodeid, void *data,
-                   u64 addr, unsigned int length, u16 flags);
-int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
-                   void *data, u64 addr, unsigned int length, u16 flags);
+/*
+ * These functions are called to handle transactions. They are called when a
+ * packet arrives.  The flags argument contains the second word of the first
+ * header quadlet of the incoming packet (containing transaction label, retry
+ * code, transaction code and priority).  These functions either return a
* response code or a negative number.  In the first case a response will be
+ * generated.  In the latter case, no response will be sent and the driver which
* handled the request will send the response itself.
+ */
+int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
+                  unsigned int length, u16 flags);
+int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
+                   u64 addr, unsigned int length, u16 flags);
 int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
+                  u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+                  u16 flags);
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
+                    u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+                    u16 flags);
 
-void highlevel_iso_receive(struct hpsb_host *host, void *data,
-                           size_t length);
+void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                           void *data, size_t length);
-
+                          void *data, size_t length);
 
 /*
  * Register highlevel driver.  The name pointer has to stay valid at all times
@@ -132,13 +134,15 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
 
 /*
  * Register handlers for host address spaces.  Start and end are 48 bit pointers
- * and have to be quadlet aligned (end points to the first address behind the
- * handled addresses.  This function can be called multiple times for a single
- * hpsb_highlevel to implement sparse register sets.  The requested region must
- * not overlap any previously allocated region, otherwise registering will fail.
+ * and have to be quadlet aligned.  Argument "end" points to the first address
+ * behind the handled addresses.  This function can be called multiple times for
+ * a single hpsb_highlevel to implement sparse register sets.  The requested
+ * region must not overlap any previously allocated region, otherwise
+ * registering will fail.
  *
- * It returns true for successful allocation.  There is no unregister function,
- * all address spaces are deallocated together with the hpsb_highlevel.
+ * It returns true for successful allocation.  Address spaces can be
+ * unregistered with hpsb_unregister_addrspace.  All remaining address spaces
+ * are automatically deallocated together with the hpsb_highlevel.
  */
 u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
                                         struct hpsb_host *host,
@@ -146,20 +150,18 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
                                         u64 size, u64 alignment,
                                         u64 start, u64 end);
 int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                            struct hpsb_address_ops *ops, u64 start, u64 end);
-
+                           struct hpsb_address_ops *ops, u64 start, u64 end);
 int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                              u64 start);
+                             u64 start);
 
 /*
  * Enable or disable receving a certain isochronous channel through the
  * iso_receive op.
  */
 int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                         unsigned int channel);
+                        unsigned int channel);
 void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                           unsigned int channel);
-
+                          unsigned int channel);
 
 /* Retrieve a hostinfo pointer bound to this driver/host */
 void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
@@ -172,19 +174,24 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
 void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
 
 /* Set an alternate lookup key for the hostinfo bound to this driver/host */
-void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key);
+void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
+                          unsigned long key);
 
-/* Retrieve the alternate lookup key for the hostinfo bound to this driver/host */
-unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host);
+/* Retrieve the alternate lookup key for the hostinfo bound to this
+ * driver/host */
+unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl,
+                                   struct hpsb_host *host);
 
 /* Retrieve a hostinfo pointer bound to this driver using its alternate key */
 void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key);
 
 /* Set the hostinfo pointer to something useful. Usually follows a call to
  * hpsb_create_hostinfo, where the size is 0. */
-int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data);
+int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
+                     void *data);
 
 /* Retrieve hpsb_host using a highlevel handle and a key */
-struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key);
+struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl,
+                                     unsigned long key);
 
 #endif /* IEEE1394_HIGHLEVEL_H */
index 4feead4a35c5b7b404b2aacee5e2282f1dd4cd52..d90a3a1898c0d4276bd6a1c7c0688f62a184a46b 100644 (file)
@@ -90,6 +90,16 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
        return 0;
 }
 
+/*
+ * The pending_packet_queue is special in that it's processed
+ * from hardirq context too (such as hpsb_bus_reset()). Hence
+ * split the lock class from the usual networking skb-head
+ * lock class by using a separate key for it:
+ */
+static struct lock_class_key pending_packet_queue_key;
+
+static DEFINE_MUTEX(host_num_alloc);
+
 /**
  * hpsb_alloc_host - allocate a new host controller.
  * @drv: the driver that will manage the host controller
@@ -105,16 +115,6 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
  * Return Value: a pointer to the &hpsb_host if successful, %NULL if
  * no memory was available.
  */
-static DEFINE_MUTEX(host_num_alloc);
-
-/*
- * The pending_packet_queue is special in that it's processed
- * from hardirq context too (such as hpsb_bus_reset()). Hence
- * split the lock class from the usual networking skb-head
- * lock class by using a separate key for it:
- */
-static struct lock_class_key pending_packet_queue_key;
-
 struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
                                  struct device *dev)
 {
@@ -143,9 +143,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
        for (i = 2; i < 16; i++)
                h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
 
-       for (i = 0; i < ARRAY_SIZE(h->tpool); i++)
-               HPSB_TPOOL_INIT(&h->tpool[i]);
-
        atomic_set(&h->generation, 0);
 
        INIT_WORK(&h->delayed_reset, delayed_reset_bus, h);
index 9ad4b2463077656ff166a752b6fd89e462b59163..bc6dbfadb8914a751764a2704c9db751f63987f0 100644 (file)
@@ -2,17 +2,19 @@
 #define _IEEE1394_HOSTS_H
 
 #include <linux/device.h>
-#include <linux/wait.h>
 #include <linux/list.h>
-#include <linux/timer.h>
 #include <linux/skbuff.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
 
-#include <asm/semaphore.h>
+struct pci_dev;
+struct module;
 
 #include "ieee1394_types.h"
 #include "csr.h"
 
-
 struct hpsb_packet;
 struct hpsb_iso;
 
@@ -33,7 +35,6 @@ struct hpsb_host {
        int node_count;      /* number of identified nodes on this bus */
        int selfid_count;    /* total number of SelfIDs received */
        int nodes_active;    /* number of nodes with active link layer */
-       u8 speed[ALL_NODES]; /* speed between each node and local node */
 
        nodeid_t node_id;    /* node ID of this host */
        nodeid_t irm_id;     /* ID of this bus' isochronous resource manager */
@@ -53,31 +54,29 @@ struct hpsb_host {
        int reset_retries;
        quadlet_t *topology_map;
        u8 *speed_map;
-       struct csr_control csr;
-
-       /* Per node tlabel pool allocation */
-       struct hpsb_tlabel_pool tpool[ALL_NODES];
 
+       int id;
        struct hpsb_host_driver *driver;
-
        struct pci_dev *pdev;
-
-       int id;
-
        struct device device;
        struct class_device class_dev;
 
        int update_config_rom;
        struct work_struct delayed_reset;
-
        unsigned int config_roms;
 
        struct list_head addr_space;
        u64 low_addr_space;     /* upper bound of physical DMA area */
        u64 middle_addr_space;  /* upper bound of posted write area */
-};
 
+       u8 speed[ALL_NODES];    /* speed between each node and local node */
+
+       /* per node tlabel allocation */
+       u8 next_tl[ALL_NODES];
+       struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
 
+       struct csr_control csr;
+};
 
 enum devctl_cmd {
        /* Host is requested to reset its bus and cancel all outstanding async
@@ -112,7 +111,7 @@ enum devctl_cmd {
 
 enum isoctl_cmd {
        /* rawiso API - see iso.h for the meanings of these commands
-          (they correspond exactly to the hpsb_iso_* API functions)
+        * (they correspond exactly to the hpsb_iso_* API functions)
         * INIT = allocate resources
         * START = begin transmission/reception
         * STOP = halt transmission/reception
@@ -160,7 +159,8 @@ struct hpsb_host_driver {
        /* The hardware driver may optionally support a function that is used
         * to set the hardware ConfigROM if the hardware supports handling
         * reads to the ConfigROM on its own. */
-       void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom);
+       void (*set_hw_config_rom)(struct hpsb_host *host,
+                                 quadlet_t *config_rom);
 
        /* This function shall implement packet transmission based on
         * packet->type.  It shall CRC both parts of the packet (unless
@@ -170,20 +170,21 @@ struct hpsb_host_driver {
         * called.  Return 0 on success, negative errno on failure.
         * NOTE: The function must be callable in interrupt context.
         */
-       int (*transmit_packet) (struct hpsb_host *host,
-                               struct hpsb_packet *packet);
+       int (*transmit_packet)(struct hpsb_host *host,
+                              struct hpsb_packet *packet);
 
        /* This function requests miscellanous services from the driver, see
         * above for command codes and expected actions.  Return -1 for unknown
         * command, though that should never happen.
         */
-       int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
+       int (*devctl)(struct hpsb_host *host, enum devctl_cmd command, int arg);
 
         /* ISO transmission/reception functions. Return 0 on success, -1
          * (or -EXXX errno code) on failure. If the low-level driver does not
          * support the new ISO API, set isoctl to NULL.
          */
-       int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg);
+       int (*isoctl)(struct hpsb_iso *iso, enum isoctl_cmd command,
+                     unsigned long arg);
 
        /* This function is mainly to redirect local CSR reads/locks to the iso
         * management registers (bus manager id, bandwidth available, channels
@@ -196,19 +197,11 @@ struct hpsb_host_driver {
                                 quadlet_t data, quadlet_t compare);
 };
 
-
 struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
                                  struct device *dev);
 int hpsb_add_host(struct hpsb_host *host);
 void hpsb_remove_host(struct hpsb_host *h);
 
-/* The following 2 functions are deprecated and will be removed when the
- * raw1394/libraw1394 update is complete. */
-int hpsb_update_config_rom(struct hpsb_host *host,
-      const quadlet_t *new_rom, size_t size, unsigned char rom_version);
-int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
-      size_t buffersize, size_t *rom_size, unsigned char *rom_version);
-
 /* Updates the configuration rom image of a host.  rom_version must be the
  * current version, otherwise it will fail with return value -1. If this
  * host does not support config-rom-update, it will return -EINVAL.
index 156703986348cddade654814eaa4de4ce465bcdb..8f207508ed1dae62dc4ba417df8a5cb14089d62a 100644 (file)
@@ -1,5 +1,7 @@
-/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#'
- * with a range of 0x00-0x3f. */
+/*
+ * Base file for all ieee1394 ioctl's.
+ * Linux-1394 has allocated base '#' with a range of 0x00-0x3f.
+ */
 
 #ifndef __IEEE1394_IOCTL_H
 #define __IEEE1394_IOCTL_H
@@ -96,8 +98,7 @@
        _IOW ('#', 0x27, struct raw1394_iso_packets)
 #define RAW1394_IOC_ISO_XMIT_SYNC              \
        _IO  ('#', 0x28)
-#define RAW1394_IOC_ISO_RECV_FLUSH              \
+#define RAW1394_IOC_ISO_RECV_FLUSH             \
        _IO  ('#', 0x29)
 
-
 #endif /* __IEEE1394_IOCTL_H */
index 936d776de00a883bdcd0301f7bde5742e64f1384..40492074c013c9d42af0eda8f4363506ab32e1da 100644 (file)
@@ -5,77 +5,78 @@
 #ifndef _IEEE1394_IEEE1394_H
 #define _IEEE1394_IEEE1394_H
 
-#define TCODE_WRITEQ             0x0
-#define TCODE_WRITEB             0x1
-#define TCODE_WRITE_RESPONSE     0x2
-#define TCODE_READQ              0x4
-#define TCODE_READB              0x5
-#define TCODE_READQ_RESPONSE     0x6
-#define TCODE_READB_RESPONSE     0x7
-#define TCODE_CYCLE_START        0x8
-#define TCODE_LOCK_REQUEST       0x9
-#define TCODE_ISO_DATA           0xa
-#define TCODE_STREAM_DATA        0xa
-#define TCODE_LOCK_RESPONSE      0xb
-
-#define RCODE_COMPLETE           0x0
-#define RCODE_CONFLICT_ERROR     0x4
-#define RCODE_DATA_ERROR         0x5
-#define RCODE_TYPE_ERROR         0x6
-#define RCODE_ADDRESS_ERROR      0x7
-
-#define EXTCODE_MASK_SWAP        0x1
-#define EXTCODE_COMPARE_SWAP     0x2
-#define EXTCODE_FETCH_ADD        0x3
-#define EXTCODE_LITTLE_ADD       0x4
-#define EXTCODE_BOUNDED_ADD      0x5
-#define EXTCODE_WRAP_ADD         0x6
-
-#define ACK_COMPLETE             0x1
-#define ACK_PENDING              0x2
-#define ACK_BUSY_X               0x4
-#define ACK_BUSY_A               0x5
-#define ACK_BUSY_B               0x6
-#define ACK_TARDY                0xb
-#define ACK_CONFLICT_ERROR       0xc
-#define ACK_DATA_ERROR           0xd
-#define ACK_TYPE_ERROR           0xe
-#define ACK_ADDRESS_ERROR        0xf
+#define TCODE_WRITEQ           0x0
+#define TCODE_WRITEB           0x1
+#define TCODE_WRITE_RESPONSE   0x2
+#define TCODE_READQ            0x4
+#define TCODE_READB            0x5
+#define TCODE_READQ_RESPONSE   0x6
+#define TCODE_READB_RESPONSE   0x7
+#define TCODE_CYCLE_START      0x8
+#define TCODE_LOCK_REQUEST     0x9
+#define TCODE_ISO_DATA         0xa
+#define TCODE_STREAM_DATA      0xa
+#define TCODE_LOCK_RESPONSE    0xb
+
+#define RCODE_COMPLETE         0x0
+#define RCODE_CONFLICT_ERROR   0x4
+#define RCODE_DATA_ERROR       0x5
+#define RCODE_TYPE_ERROR       0x6
+#define RCODE_ADDRESS_ERROR    0x7
+
+#define EXTCODE_MASK_SWAP      0x1
+#define EXTCODE_COMPARE_SWAP   0x2
+#define EXTCODE_FETCH_ADD      0x3
+#define EXTCODE_LITTLE_ADD     0x4
+#define EXTCODE_BOUNDED_ADD    0x5
+#define EXTCODE_WRAP_ADD       0x6
+
+#define ACK_COMPLETE           0x1
+#define ACK_PENDING            0x2
+#define ACK_BUSY_X             0x4
+#define ACK_BUSY_A             0x5
+#define ACK_BUSY_B             0x6
+#define ACK_TARDY              0xb
+#define ACK_CONFLICT_ERROR     0xc
+#define ACK_DATA_ERROR         0xd
+#define ACK_TYPE_ERROR         0xe
+#define ACK_ADDRESS_ERROR      0xf
 
 /* Non-standard "ACK codes" for internal use */
-#define ACKX_NONE                (-1)
-#define ACKX_SEND_ERROR          (-2)
-#define ACKX_ABORTED             (-3)
-#define ACKX_TIMEOUT             (-4)
-
-
-#define IEEE1394_SPEED_100             0x00
-#define IEEE1394_SPEED_200             0x01
-#define IEEE1394_SPEED_400             0x02
-#define IEEE1394_SPEED_800             0x03
-#define IEEE1394_SPEED_1600            0x04
-#define IEEE1394_SPEED_3200            0x05
+#define ACKX_NONE              (-1)
+#define ACKX_SEND_ERROR                (-2)
+#define ACKX_ABORTED           (-3)
+#define ACKX_TIMEOUT           (-4)
+
+#define IEEE1394_SPEED_100     0x00
+#define IEEE1394_SPEED_200     0x01
+#define IEEE1394_SPEED_400     0x02
+#define IEEE1394_SPEED_800     0x03
+#define IEEE1394_SPEED_1600    0x04
+#define IEEE1394_SPEED_3200    0x05
+
 /* The current highest tested speed supported by the subsystem */
-#define IEEE1394_SPEED_MAX             IEEE1394_SPEED_800
+#define IEEE1394_SPEED_MAX     IEEE1394_SPEED_800
 
 /* Maps speed values above to a string representation */
 extern const char *hpsb_speedto_str[];
 
-
 /* 1394a cable PHY packets */
-#define SELFID_PWRCL_NO_POWER    0x0
-#define SELFID_PWRCL_PROVIDE_15W 0x1
-#define SELFID_PWRCL_PROVIDE_30W 0x2
-#define SELFID_PWRCL_PROVIDE_45W 0x3
-#define SELFID_PWRCL_USE_1W      0x4
-#define SELFID_PWRCL_USE_3W      0x5
-#define SELFID_PWRCL_USE_6W      0x6
-#define SELFID_PWRCL_USE_10W     0x7
-
-#define SELFID_PORT_CHILD        0x3
-#define SELFID_PORT_PARENT       0x2
-#define SELFID_PORT_NCONN        0x1
-#define SELFID_PORT_NONE         0x0
+#define SELFID_PWRCL_NO_POWER          0x0
+#define SELFID_PWRCL_PROVIDE_15W       0x1
+#define SELFID_PWRCL_PROVIDE_30W       0x2
+#define SELFID_PWRCL_PROVIDE_45W       0x3
+#define SELFID_PWRCL_USE_1W            0x4
+#define SELFID_PWRCL_USE_3W            0x5
+#define SELFID_PWRCL_USE_6W            0x6
+#define SELFID_PWRCL_USE_10W           0x7
+
+#define SELFID_PORT_CHILD              0x3
+#define SELFID_PORT_PARENT             0x2
+#define SELFID_PORT_NCONN              0x1
+#define SELFID_PORT_NONE               0x0
+
+#define SELFID_SPEED_UNKNOWN           0x3     /* 1394b PHY */
 
 #define PHYPACKET_LINKON                       0x40000000
 #define PHYPACKET_PHYCONFIG_R                  0x00800000
@@ -91,76 +92,76 @@ extern const char *hpsb_speedto_str[];
 
 #define EXTPHYPACKET_TYPEMASK                  0xC0FC0000
 
-#define PHYPACKET_PORT_SHIFT     24
-#define PHYPACKET_GAPCOUNT_SHIFT 16
+#define PHYPACKET_PORT_SHIFT           24
+#define PHYPACKET_GAPCOUNT_SHIFT       16
 
 /* 1394a PHY register map bitmasks */
-#define PHY_00_PHYSICAL_ID       0xFC
-#define PHY_00_R                 0x02 /* Root */
-#define PHY_00_PS                0x01 /* Power Status*/
-#define PHY_01_RHB               0x80 /* Root Hold-Off */
-#define PHY_01_IBR               0x80 /* Initiate Bus Reset */
-#define PHY_01_GAP_COUNT         0x3F
-#define PHY_02_EXTENDED          0xE0 /* 0x7 for 1394a-compliant PHY */
-#define PHY_02_TOTAL_PORTS       0x1F
-#define PHY_03_MAX_SPEED         0xE0
-#define PHY_03_DELAY             0x0F
-#define PHY_04_LCTRL             0x80 /* Link Active Report Control */
-#define PHY_04_CONTENDER         0x40
-#define PHY_04_JITTER            0x38
-#define PHY_04_PWR_CLASS         0x07 /* Power Class */
-#define PHY_05_WATCHDOG          0x80
-#define PHY_05_ISBR              0x40 /* Initiate Short Bus Reset */
-#define PHY_05_LOOP              0x20 /* Loop Detect */
-#define PHY_05_PWR_FAIL          0x10 /* Cable Power Failure Detect */
-#define PHY_05_TIMEOUT           0x08 /* Arbitration State Machine Timeout */
-#define PHY_05_PORT_EVENT        0x04 /* Port Event Detect */
-#define PHY_05_ENAB_ACCEL        0x02 /* Enable Arbitration Acceleration */
-#define PHY_05_ENAB_MULTI        0x01 /* Ena. Multispeed Packet Concatenation */
+#define PHY_00_PHYSICAL_ID     0xFC
+#define PHY_00_R               0x02 /* Root */
+#define PHY_00_PS              0x01 /* Power Status*/
+#define PHY_01_RHB             0x80 /* Root Hold-Off */
+#define PHY_01_IBR             0x80 /* Initiate Bus Reset */
+#define PHY_01_GAP_COUNT       0x3F
+#define PHY_02_EXTENDED                0xE0 /* 0x7 for 1394a-compliant PHY */
+#define PHY_02_TOTAL_PORTS     0x1F
+#define PHY_03_MAX_SPEED       0xE0
+#define PHY_03_DELAY           0x0F
+#define PHY_04_LCTRL           0x80 /* Link Active Report Control */
+#define PHY_04_CONTENDER       0x40
+#define PHY_04_JITTER          0x38
+#define PHY_04_PWR_CLASS       0x07 /* Power Class */
+#define PHY_05_WATCHDOG                0x80
+#define PHY_05_ISBR            0x40 /* Initiate Short Bus Reset */
+#define PHY_05_LOOP            0x20 /* Loop Detect */
+#define PHY_05_PWR_FAIL                0x10 /* Cable Power Failure Detect */
+#define PHY_05_TIMEOUT         0x08 /* Arbitration State Machine Timeout */
+#define PHY_05_PORT_EVENT      0x04 /* Port Event Detect */
+#define PHY_05_ENAB_ACCEL      0x02 /* Enable Arbitration Acceleration */
+#define PHY_05_ENAB_MULTI      0x01 /* Ena. Multispeed Packet Concatenation */
 
 #include <asm/byteorder.h>
 
 #ifdef __BIG_ENDIAN_BITFIELD
 
 struct selfid {
-        u32 packet_identifier:2; /* always binary 10 */
-        u32 phy_id:6;
-        /* byte */
-        u32 extended:1; /* if true is struct ext_selfid */
-        u32 link_active:1;
-        u32 gap_count:6;
-        /* byte */
-        u32 speed:2;
-        u32 phy_delay:2;
-        u32 contender:1;
-        u32 power_class:3;
-        /* byte */
-        u32 port0:2;
-        u32 port1:2;
-        u32 port2:2;
-        u32 initiated_reset:1;
-        u32 more_packets:1;
+       u32 packet_identifier:2; /* always binary 10 */
+       u32 phy_id:6;
+       /* byte */
+       u32 extended:1; /* if true is struct ext_selfid */
+       u32 link_active:1;
+       u32 gap_count:6;
+       /* byte */
+       u32 speed:2;
+       u32 phy_delay:2;
+       u32 contender:1;
+       u32 power_class:3;
+       /* byte */
+       u32 port0:2;
+       u32 port1:2;
+       u32 port2:2;
+       u32 initiated_reset:1;
+       u32 more_packets:1;
 } __attribute__((packed));
 
 struct ext_selfid {
-        u32 packet_identifier:2; /* always binary 10 */
-        u32 phy_id:6;
-        /* byte */
-        u32 extended:1; /* if false is struct selfid */
-        u32 seq_nr:3;
-        u32 reserved:2;
-        u32 porta:2;
-        /* byte */
-        u32 portb:2;
-        u32 portc:2;
-        u32 portd:2;
-        u32 porte:2;
-        /* byte */
-        u32 portf:2;
-        u32 portg:2;
-        u32 porth:2;
-        u32 reserved2:1;
-        u32 more_packets:1;
+       u32 packet_identifier:2; /* always binary 10 */
+       u32 phy_id:6;
+       /* byte */
+       u32 extended:1; /* if false is struct selfid */
+       u32 seq_nr:3;
+       u32 reserved:2;
+       u32 porta:2;
+       /* byte */
+       u32 portb:2;
+       u32 portc:2;
+       u32 portd:2;
+       u32 porte:2;
+       /* byte */
+       u32 portf:2;
+       u32 portg:2;
+       u32 porth:2;
+       u32 reserved2:1;
+       u32 more_packets:1;
 } __attribute__((packed));
 
 #elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */
@@ -171,49 +172,48 @@ struct ext_selfid {
  */
 
 struct selfid {
-        u32 phy_id:6;
-        u32 packet_identifier:2; /* always binary 10 */
-        /* byte */
-        u32 gap_count:6;
-        u32 link_active:1;
-        u32 extended:1; /* if true is struct ext_selfid */
-        /* byte */
-        u32 power_class:3;
-        u32 contender:1;
-        u32 phy_delay:2;
-        u32 speed:2;
-        /* byte */
-        u32 more_packets:1;
-        u32 initiated_reset:1;
-        u32 port2:2;
-        u32 port1:2;
-        u32 port0:2;
+       u32 phy_id:6;
+       u32 packet_identifier:2; /* always binary 10 */
+       /* byte */
+       u32 gap_count:6;
+       u32 link_active:1;
+       u32 extended:1; /* if true is struct ext_selfid */
+       /* byte */
+       u32 power_class:3;
+       u32 contender:1;
+       u32 phy_delay:2;
+       u32 speed:2;
+       /* byte */
+       u32 more_packets:1;
+       u32 initiated_reset:1;
+       u32 port2:2;
+       u32 port1:2;
+       u32 port0:2;
 } __attribute__((packed));
 
 struct ext_selfid {
-        u32 phy_id:6;
-        u32 packet_identifier:2; /* always binary 10 */
-        /* byte */
-        u32 porta:2;
-        u32 reserved:2;
-        u32 seq_nr:3;
-        u32 extended:1; /* if false is struct selfid */
-        /* byte */
-        u32 porte:2;
-        u32 portd:2;
-        u32 portc:2;
-        u32 portb:2;
-        /* byte */
-        u32 more_packets:1;
-        u32 reserved2:1;
-        u32 porth:2;
-        u32 portg:2;
-        u32 portf:2;
+       u32 phy_id:6;
+       u32 packet_identifier:2; /* always binary 10 */
+       /* byte */
+       u32 porta:2;
+       u32 reserved:2;
+       u32 seq_nr:3;
+       u32 extended:1; /* if false is struct selfid */
+       /* byte */
+       u32 porte:2;
+       u32 portd:2;
+       u32 portc:2;
+       u32 portb:2;
+       /* byte */
+       u32 more_packets:1;
+       u32 reserved2:1;
+       u32 porth:2;
+       u32 portg:2;
+       u32 portf:2;
 } __attribute__((packed));
 
 #else
 #error What? PDP endian?
 #endif /* __BIG_ENDIAN_BITFIELD */
 
-
 #endif /* _IEEE1394_IEEE1394_H */
index f43739c5cab2ed11176c8493d4cf90de2e9a5f49..5fccf9f7a1d2e2a72eabffa78404156824156950 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kthread.h>
 
 #include <asm/byteorder.h>
-#include <asm/semaphore.h>
 
 #include "ieee1394_types.h"
 #include "ieee1394.h"
@@ -86,7 +85,7 @@ static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
        printk("\n");
 }
 #else
-#define dump_packet(a,b,c,d)
+#define dump_packet(a,b,c,d) do {} while (0)
 #endif
 
 static void abort_requests(struct hpsb_host *host);
@@ -355,10 +354,12 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
                }
        }
 
+#if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX
        /* assume maximum speed for 1394b PHYs, nodemgr will correct it */
        for (n = 0; n < nodecount; n++)
-               if (speedcap[n] == 3)
+               if (speedcap[n] == SELFID_SPEED_UNKNOWN)
                        speedcap[n] = IEEE1394_SPEED_MAX;
+#endif
 }
 
 
@@ -1169,7 +1170,7 @@ static void __exit ieee1394_cleanup(void)
        unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-module_init(ieee1394_init);
+fs_initcall(ieee1394_init); /* same as ohci1394 */
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
index 0ecbf335c64f5591e476b0c327abd1e7efdaeb31..af4a78a8ef3b124f61e9a9b667cc8b9f5383ee7f 100644 (file)
@@ -1,12 +1,15 @@
-
 #ifndef _IEEE1394_CORE_H
 #define _IEEE1394_CORE_H
 
-#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
 #include <asm/atomic.h>
-#include <asm/semaphore.h>
-#include "hosts.h"
 
+#include "hosts.h"
+#include "ieee1394_types.h"
 
 struct hpsb_packet {
        /* This struct is basically read-only for hosts with the exception of
@@ -58,7 +61,6 @@ struct hpsb_packet {
        size_t header_size;
        size_t data_size;
 
-
        struct hpsb_host *host;
        unsigned int generation;
 
@@ -80,7 +82,7 @@ struct hpsb_packet {
 
 /* Set a task for when a packet completes */
 void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
-               void (*routine)(void *), void *data);
+                                  void (*routine)(void *), void *data);
 
 static inline struct hpsb_packet *driver_packet(struct list_head *l)
 {
@@ -92,7 +94,6 @@ void abort_timedouts(unsigned long __opaque);
 struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
 void hpsb_free_packet(struct hpsb_packet *packet);
 
-
 /*
  * Generation counter for the complete 1394 subsystem.  Generation gets
  * incremented on every change in the subsystem (e.g. bus reset).
@@ -204,10 +205,14 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
 #define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
 
 #define IEEE1394_CORE_DEV        MKDEV(IEEE1394_MAJOR, 0)
-#define IEEE1394_RAW1394_DEV     MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
-#define IEEE1394_VIDEO1394_DEV   MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
-#define IEEE1394_DV1394_DEV      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
+#define IEEE1394_RAW1394_DEV     MKDEV(IEEE1394_MAJOR, \
+                                       IEEE1394_MINOR_BLOCK_RAW1394 * 16)
+#define IEEE1394_VIDEO1394_DEV   MKDEV(IEEE1394_MAJOR, \
+                                       IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
+#define IEEE1394_DV1394_DEV      MKDEV(IEEE1394_MAJOR, \
+                                       IEEE1394_MINOR_BLOCK_DV1394 * 16)
+#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \
+                                       IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
 
 /* return the index (within a minor number block) of a file */
 static inline unsigned char ieee1394_file_to_instance(struct file *file)
@@ -223,4 +228,3 @@ extern struct class hpsb_host_class;
 extern struct class *hpsb_protocol_class;
 
 #endif /* _IEEE1394_CORE_H */
-
index 5be70d31b007151492e306a3e621812d3ce07e7d..dd5500ed83221ef3c856310ba07c63a69be6b8df 100644 (file)
@@ -1,33 +1,19 @@
 #ifndef _IEEE1394_HOTPLUG_H
 #define _IEEE1394_HOTPLUG_H
 
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mod_devicetable.h>
-
 /* Unit spec id and sw version entry for some protocols */
 #define AVC_UNIT_SPEC_ID_ENTRY         0x0000A02D
 #define AVC_SW_VERSION_ENTRY           0x00010001
 #define CAMERA_UNIT_SPEC_ID_ENTRY      0x0000A02D
 #define CAMERA_SW_VERSION_ENTRY                0x00000100
 
-/* Check to make sure this all isn't already defined */
-#ifndef IEEE1394_MATCH_VENDOR_ID
-
-#define IEEE1394_MATCH_VENDOR_ID       0x0001
-#define IEEE1394_MATCH_MODEL_ID                0x0002
-#define IEEE1394_MATCH_SPECIFIER_ID    0x0004
-#define IEEE1394_MATCH_VERSION         0x0008
-
-struct ieee1394_device_id {
-       u32 match_flags;
-       u32 vendor_id;
-       u32 model_id;
-       u32 specifier_id;
-       u32 version;
-       void *driver_data;
-};
-
-#endif
+/* /include/linux/mod_devicetable.h defines:
+ *     IEEE1394_MATCH_VENDOR_ID
+ *     IEEE1394_MATCH_MODEL_ID
+ *     IEEE1394_MATCH_SPECIFIER_ID
+ *     IEEE1394_MATCH_VERSION
+ *     struct ieee1394_device_id
+ */
+#include <linux/mod_devicetable.h>
 
 #endif /* _IEEE1394_HOTPLUG_H */
index a114b91d606db640ce5ffa46acc13abef2ebe6a2..0833fc9f50c4ad1914513620bbaae219889a1b42 100644 (file)
@@ -9,19 +9,17 @@
  * directory of the kernel sources for details.
  */
 
-#include <linux/sched.h>
 #include <linux/bitops.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
 
+#include <asm/bug.h>
 #include <asm/errno.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
-#include "highlevel.h"
-#include "nodemgr.h"
 #include "ieee1394_transactions.h"
 
 #define PREP_ASYNC_HEAD_ADDRESS(tc) \
         packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
         packet->header[2] = addr & 0xffffffff
 
+#ifndef HPSB_DEBUG_TLABELS
+static
+#endif
+spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED;
+
+static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
+
 static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
 {
        PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
@@ -114,9 +119,41 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
        packet->tcode = TCODE_ISO_DATA;
 }
 
+/* same as hpsb_get_tlabel, except that it returns immediately */
+static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet)
+{
+       unsigned long flags, *tp;
+       u8 *next;
+       int tlabel, n = NODEID_TO_NODE(packet->node_id);
+
+       /* Broadcast transactions are complete once the request has been sent.
+        * Use the same transaction label for all broadcast transactions. */
+       if (unlikely(n == ALL_NODES)) {
+               packet->tlabel = 0;
+               return 0;
+       }
+       tp = packet->host->tl_pool[n].map;
+       next = &packet->host->next_tl[n];
+
+       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
+       tlabel = find_next_zero_bit(tp, 64, *next);
+       if (tlabel > 63)
+               tlabel = find_first_zero_bit(tp, 64);
+       if (tlabel > 63) {
+               spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
+               return -EAGAIN;
+       }
+       __set_bit(tlabel, tp);
+       *next = (tlabel + 1) & 63;
+       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
+
+       packet->tlabel = tlabel;
+       return 0;
+}
+
 /**
  * hpsb_get_tlabel - allocate a transaction label
- * @packet: the packet who's tlabel/tpool we set
+ * @packet: the packet whose tlabel and tl_pool we set
  *
  * Every asynchronous transaction on the 1394 bus needs a transaction
  * label to match the response to the request.  This label has to be
@@ -130,42 +167,25 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
  * Return value: Zero on success, otherwise non-zero. A non-zero return
  * generally means there are no available tlabels. If this is called out
  * of interrupt or atomic context, then it will sleep until can return a
- * tlabel.
+ * tlabel or a signal is received.
  */
 int hpsb_get_tlabel(struct hpsb_packet *packet)
 {
-       unsigned long flags;
-       struct hpsb_tlabel_pool *tp;
-       int n = NODEID_TO_NODE(packet->node_id);
-
-       if (unlikely(n == ALL_NODES))
-               return 0;
-       tp = &packet->host->tpool[n];
-
-       if (irqs_disabled() || in_atomic()) {
-               if (down_trylock(&tp->count))
-                       return 1;
-       } else {
-               down(&tp->count);
-       }
-
-       spin_lock_irqsave(&tp->lock, flags);
-
-       packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
-       if (packet->tlabel > 63)
-               packet->tlabel = find_first_zero_bit(tp->pool, 64);
-       tp->next = (packet->tlabel + 1) % 64;
-       /* Should _never_ happen */
-       BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
-       tp->allocations++;
-       spin_unlock_irqrestore(&tp->lock, flags);
-
-       return 0;
+       if (irqs_disabled() || in_atomic())
+               return hpsb_get_tlabel_atomic(packet);
+
+       /* NB: The macro wait_event_interruptible() is called with a condition
+        * argument with side effect.  This is only possible because the side
+        * effect does not occur until the condition became true, and
+        * wait_event_interruptible() won't evaluate the condition again after
+        * that. */
+       return wait_event_interruptible(tlabel_wq,
+                                       !hpsb_get_tlabel_atomic(packet));
 }
 
 /**
  * hpsb_free_tlabel - free an allocated transaction label
- * @packet: packet whos tlabel/tpool needs to be cleared
+ * @packet: packet whose tlabel and tl_pool needs to be cleared
  *
  * Frees the transaction label allocated with hpsb_get_tlabel().  The
  * tlabel has to be freed after the transaction is complete (i.e. response
@@ -176,21 +196,20 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
  */
 void hpsb_free_tlabel(struct hpsb_packet *packet)
 {
-       unsigned long flags;
-       struct hpsb_tlabel_pool *tp;
-       int n = NODEID_TO_NODE(packet->node_id);
+       unsigned long flags, *tp;
+       int tlabel, n = NODEID_TO_NODE(packet->node_id);
 
        if (unlikely(n == ALL_NODES))
                return;
-       tp = &packet->host->tpool[n];
+       tp = packet->host->tl_pool[n].map;
+       tlabel = packet->tlabel;
+       BUG_ON(tlabel > 63 || tlabel < 0);
 
-       BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
+       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
+       BUG_ON(!__test_and_clear_bit(tlabel, tp));
+       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
 
-       spin_lock_irqsave(&tp->lock, flags);
-       BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
-       spin_unlock_irqrestore(&tp->lock, flags);
-
-       up(&tp->count);
+       wake_up_interruptible(&tlabel_wq);
 }
 
 int hpsb_packet_success(struct hpsb_packet *packet)
@@ -214,7 +233,7 @@ int hpsb_packet_success(struct hpsb_packet *packet)
                                 packet->node_id);
                        return -EAGAIN;
                }
-               HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
+               BUG();
 
        case ACK_BUSY_X:
        case ACK_BUSY_A:
@@ -261,8 +280,7 @@ int hpsb_packet_success(struct hpsb_packet *packet)
                         packet->ack_code, packet->node_id, packet->tcode);
                return -EAGAIN;
        }
-
-       HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
+       BUG();
 }
 
 struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
index 45ba784fe6da044b4114cfa40f1a26f96bb0fdc2..c1369c41469b5464cb66b4a3bad22ee2d996846b 100644 (file)
@@ -1,32 +1,32 @@
 #ifndef _IEEE1394_TRANSACTIONS_H
 #define _IEEE1394_TRANSACTIONS_H
 
-#include "ieee1394_core.h"
+#include <linux/types.h>
 
+#include "ieee1394_types.h"
+
+struct hpsb_packet;
+struct hpsb_host;
 
-/*
- * Get and free transaction labels.
- */
 int hpsb_get_tlabel(struct hpsb_packet *packet);
 void hpsb_free_tlabel(struct hpsb_packet *packet);
-
 struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
                                         u64 addr, size_t length);
 struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
-                                         u64 addr, int extcode, quadlet_t *data,
+                                        u64 addr, int extcode, quadlet_t *data,
                                         quadlet_t arg);
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
-                                          u64 addr, int extcode, octlet_t *data,
-                                         octlet_t arg);
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
-                                        quadlet_t data) ;
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
-                                       int length, int channel,
-                                       int tag, int sync);
-struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node,
-                                          u64 addr, quadlet_t *buffer, size_t length);
+struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
+                                          nodeid_t node, u64 addr, int extcode,
+                                          octlet_t *data, octlet_t arg);
+struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
+struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
+                                       int channel, int tag, int sync);
+struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
+                                         nodeid_t node, u64 addr,
+                                         quadlet_t *buffer, size_t length);
 struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
-                                           int length, int channel, int tag, int sync);
+                                           int length, int channel, int tag,
+                                          int sync);
 
 /*
  * hpsb_packet_success - Make sense of the ack and reply codes and
@@ -40,9 +40,8 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
  */
 int hpsb_packet_success(struct hpsb_packet *packet);
 
-
 /*
- * The generic read, write and lock functions.  All recognize the local node ID
+ * The generic read and write functions.  All recognize the local node ID
  * and act accordingly.  Read and write automatically use quadlet commands if
  * length == 4 and and block commands otherwise (however, they do not yet
  * support lengths that are not a multiple of 4).  You must explicitly specifiy
@@ -54,4 +53,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
               u64 addr, quadlet_t *buffer, size_t length);
 
+#ifdef HPSB_DEBUG_TLABELS
+extern spinlock_t hpsb_tlabel_lock;
+#endif
+
 #endif /* _IEEE1394_TRANSACTIONS_H */
index 3165609ec1ec3019a03f19fa8e0ff7775466bc7d..9803aaa15be04431994e8a8a764fd887bd42456c 100644 (file)
@@ -1,37 +1,11 @@
-
 #ifndef _IEEE1394_TYPES_H
 #define _IEEE1394_TYPES_H
 
 #include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
 #include <linux/string.h>
-
-#include <asm/semaphore.h>
+#include <linux/types.h>
 #include <asm/byteorder.h>
 
-
-/* Transaction Label handling */
-struct hpsb_tlabel_pool {
-       DECLARE_BITMAP(pool, 64);
-       spinlock_t lock;
-       u8 next;
-       u32 allocations;
-       struct semaphore count;
-};
-
-#define HPSB_TPOOL_INIT(_tp)                   \
-do {                                           \
-       bitmap_zero((_tp)->pool, 64);           \
-       spin_lock_init(&(_tp)->lock);           \
-       (_tp)->next = 0;                        \
-       (_tp)->allocations = 0;                 \
-       sema_init(&(_tp)->count, 63);           \
-} while (0)
-
-
 typedef u32 quadlet_t;
 typedef u64 octlet_t;
 typedef u16 nodeid_t;
@@ -54,46 +28,40 @@ typedef u16 arm_length_t;
 #define NODE_BUS_ARGS(__host, __nodeid)        \
        __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid)
 
-#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
+#define HPSB_PRINT(level, fmt, args...) \
+       printk(level "ieee1394: " fmt "\n" , ## args)
 
-#define HPSB_DEBUG(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args)
-#define HPSB_INFO(fmt, args...) HPSB_PRINT(KERN_INFO, fmt , ## args)
-#define HPSB_NOTICE(fmt, args...) HPSB_PRINT(KERN_NOTICE, fmt , ## args)
-#define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args)
-#define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args)
+#define HPSB_DEBUG(fmt, args...)       HPSB_PRINT(KERN_DEBUG, fmt , ## args)
+#define HPSB_INFO(fmt, args...)                HPSB_PRINT(KERN_INFO, fmt , ## args)
+#define HPSB_NOTICE(fmt, args...)      HPSB_PRINT(KERN_NOTICE, fmt , ## args)
+#define HPSB_WARN(fmt, args...)                HPSB_PRINT(KERN_WARNING, fmt , ## args)
+#define HPSB_ERR(fmt, args...)         HPSB_PRINT(KERN_ERR, fmt , ## args)
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args)
+#define HPSB_VERBOSE(fmt, args...)     HPSB_PRINT(KERN_DEBUG, fmt , ## args)
+#define HPSB_DEBUG_TLABELS
 #else
-#define HPSB_VERBOSE(fmt, args...)
+#define HPSB_VERBOSE(fmt, args...)     do {} while (0)
 #endif
 
-#define HPSB_PANIC(fmt, args...) panic("ieee1394: " fmt "\n" , ## args)
-
-#define HPSB_TRACE() HPSB_PRINT(KERN_INFO, "TRACE - %s, %s(), line %d", __FILE__, __FUNCTION__, __LINE__)
-
-
 #ifdef __BIG_ENDIAN
 
-static __inline__ void *memcpy_le32(u32 *dest, const u32 *__src, size_t count)
+static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count)
 {
-        void *tmp = dest;
+       void *tmp = dest;
        u32 *src = (u32 *)__src;
 
-        count /= 4;
-
-        while (count--) {
-                *dest++ = swab32p(src++);
-        }
-
-        return tmp;
+       count /= 4;
+       while (count--)
+               *dest++ = swab32p(src++);
+       return tmp;
 }
 
 #else
 
 static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count)
 {
-        return memcpy(dest, src, count);
+       return memcpy(dest, src, count);
 }
 
 #endif /* __BIG_ENDIAN */
index f26680ebef7cdcd5387627a98c79120d48dc77bb..08bd15d2a7b6cea63a675664ea333e9e0837b376 100644 (file)
@@ -9,8 +9,11 @@
  * directory of the kernel sources for details.
  */
 
-#include <linux/slab.h>
+#include <linux/pci.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
+
+#include "hosts.h"
 #include "iso.h"
 
 void hpsb_iso_stop(struct hpsb_iso *iso)
index 3efc60b33a88734f40baca223b3654e78fff94f0..1210a97e8685624f7a5ccf669e892111d619d462 100644 (file)
 #ifndef IEEE1394_ISO_H
 #define IEEE1394_ISO_H
 
-#include "hosts.h"
+#include <linux/spinlock_types.h>
+#include <asm/atomic.h>
+#include <asm/types.h>
+
 #include "dma.h"
 
-/* high-level ISO interface */
+struct hpsb_host;
 
-/* This API sends and receives isochronous packets on a large,
-   virtually-contiguous kernel memory buffer. The buffer may be mapped
-   into a user-space process for zero-copy transmission and reception.
+/* high-level ISO interface */
 
-   There are no explicit boundaries between packets in the buffer. A
-   packet may be transmitted or received at any location. However,
-   low-level drivers may impose certain restrictions on alignment or
-   size of packets. (e.g. in OHCI no packet may cross a page boundary,
-   and packets should be quadlet-aligned)
-*/
+/*
+ * This API sends and receives isochronous packets on a large,
+ * virtually-contiguous kernel memory buffer. The buffer may be mapped
+ * into a user-space process for zero-copy transmission and reception.
+ *
+ * There are no explicit boundaries between packets in the buffer. A
+ * packet may be transmitted or received at any location. However,
+ * low-level drivers may impose certain restrictions on alignment or
+ * size of packets. (e.g. in OHCI no packet may cross a page boundary,
+ * and packets should be quadlet-aligned)
+ */
 
 /* Packet descriptor - the API maintains a ring buffer of these packet
-   descriptors in kernel memory (hpsb_iso.infos[]).  */
-
+ * descriptors in kernel memory (hpsb_iso.infos[]).  */
 struct hpsb_iso_packet_info {
        /* offset of data payload relative to the first byte of the buffer */
        __u32 offset;
 
-       /* length of the data payload, in bytes (not including the isochronous header) */
+       /* length of the data payload, in bytes (not including the isochronous
+        * header) */
        __u16 len;
 
-       /* (recv only) the cycle number (mod 8000) on which the packet was received */
+       /* (recv only) the cycle number (mod 8000) on which the packet was
+        * received */
        __u16 cycle;
 
        /* (recv only) channel on which the packet was received */
@@ -48,12 +55,10 @@ struct hpsb_iso_packet_info {
        __u8 tag;
        __u8 sy;
 
-       /*
-        * length in bytes of the packet including header/trailer.
-        * MUST be at structure end, since the first part of this structure is also 
-        * defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is copied to 
-        * userspace and is accessed there through libraw1394. 
-        */
+       /* length in bytes of the packet including header/trailer.
+        * MUST be at structure end, since the first part of this structure is
+        * also defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is
+        * copied to userspace and is accessed there through libraw1394. */
        __u16 total_len;
 };
 
@@ -75,8 +80,8 @@ struct hpsb_iso {
        void *hostdata;
 
        /* a function to be called (from interrupt context) after
-           outgoing packets have been sent, or incoming packets have
-           arrived */
+        * outgoing packets have been sent, or incoming packets have
+        * arrived */
        void (*callback)(struct hpsb_iso*);
 
        /* wait for buffer space */
@@ -88,7 +93,7 @@ struct hpsb_iso {
 
 
        /* greatest # of packets between interrupts - controls
-          the maximum latency of the buffer */
+        * the maximum latency of the buffer */
        int irq_interval;
 
        /* the buffer for packet data payloads */
@@ -112,8 +117,8 @@ struct hpsb_iso {
        int pkt_dma;
 
        /* how many packets, starting at first_packet:
-          (transmit) are ready to be filled with data
-          (receive)  contain received data */
+        * (transmit) are ready to be filled with data
+        * (receive)  contain received data */
        int n_ready_packets;
 
        /* how many times the buffer has overflowed or underflowed */
@@ -134,7 +139,7 @@ struct hpsb_iso {
        int start_cycle;
 
        /* cycle at which next packet will be transmitted,
-          -1 if not known */
+        * -1 if not known */
        int xmit_cycle;
 
        /* ringbuffer of packet descriptors in regular kernel memory
@@ -170,25 +175,30 @@ int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
 int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask);
 
 /* start/stop DMA */
-int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer);
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync);
+int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle,
+                       int prebuffer);
+int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle,
+                       int tag_mask, int sync);
 void hpsb_iso_stop(struct hpsb_iso *iso);
 
 /* deallocate buffer and DMA context */
 void hpsb_iso_shutdown(struct hpsb_iso *iso);
 
-/* queue a packet for transmission. 'offset' is relative to the beginning of the
-   DMA buffer, where the packet's data payload should already have been placed */
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy);
+/* queue a packet for transmission.
+ * 'offset' is relative to the beginning of the DMA buffer, where the packet's
+ * data payload should already have been placed. */
+int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
+                              u8 tag, u8 sy);
 
 /* wait until all queued packets have been transmitted to the bus */
 int hpsb_iso_xmit_sync(struct hpsb_iso *iso);
 
 /* N packets have been read out of the buffer, re-use the buffer space */
-int  hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets);
+int  hpsb_iso_recv_release_packets(struct hpsb_iso *recv,
+                                  unsigned int n_packets);
 
 /* check for arrival of new packets immediately (even if irq_interval
  has not yet been reached) */
* has not yet been reached) */
 int hpsb_iso_recv_flush(struct hpsb_iso *iso);
 
 /* returns # of packets ready to send or receive */
@@ -197,14 +207,15 @@ int hpsb_iso_n_ready(struct hpsb_iso *iso);
 /* the following are callbacks available to low-level drivers */
 
 /* call after a packet has been transmitted to the bus (interrupt context is OK)
  'cycle' is the _exact_ cycle the packet was sent on
-   'error' should be non-zero if some sort of error occurred when sending the packet
-*/
* 'cycle' is the _exact_ cycle the packet was sent on
+ * 'error' should be non-zero if some sort of error occurred when sending the
+ *  packet */
 void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error);
 
 /* call after a packet has been received (interrupt context OK) */
 void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
-                             u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy);
+                             u16 total_len, u16 cycle, u8 channel, u8 tag,
+                             u8 sy);
 
 /* call to wake waiting processes after buffer space has opened up. */
 void hpsb_iso_wake(struct hpsb_iso *iso);
index d541b508a159b8103c128a0cc4f3d76d9bdd6d6a..3e7974c5744326464e4f26eda25a4eef69e4468e 100644 (file)
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kmod.h>
-#include <linux/completion.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
+#include <linux/kthread.h>
 #include <linux/moduleparam.h>
 #include <asm/atomic.h>
 
-#include "ieee1394_types.h"
+#include "csr.h"
+#include "highlevel.h"
+#include "hosts.h"
 #include "ieee1394.h"
 #include "ieee1394_core.h"
-#include "hosts.h"
+#include "ieee1394_hotplug.h"
+#include "ieee1394_types.h"
 #include "ieee1394_transactions.h"
-#include "highlevel.h"
-#include "csr.h"
 #include "nodemgr.h"
 
 static int ignore_drivers;
-module_param(ignore_drivers, int, 0444);
+module_param(ignore_drivers, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers.");
 
 struct nodemgr_csr_info {
@@ -71,7 +68,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
        u8 i, *speed, old_speed, good_speed;
        int ret;
 
-       speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid);
+       speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
        old_speed = *speed;
        good_speed = IEEE1394_SPEED_MAX + 1;
 
@@ -161,16 +158,12 @@ static struct csr1212_bus_ops nodemgr_csr_ops = {
  * but now we are much simpler because of the LDM.
  */
 
-static DECLARE_MUTEX(nodemgr_serialize);
+static DEFINE_MUTEX(nodemgr_serialize);
 
 struct host_info {
        struct hpsb_host *host;
        struct list_head list;
-       struct completion exited;
-       struct semaphore reset_sem;
-       int pid;
-       char daemon_name[15];
-       int kill_me;
+       struct task_struct *thread;
 };
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
@@ -334,34 +327,44 @@ static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribut
 static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
 
 
-/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically
- * here, therefore displayed values may be occasionally wrong. */
-static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf)
+#ifdef HPSB_DEBUG_TLABELS
+static ssize_t fw_show_ne_tlabels_free(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
 {
        struct node_entry *ne = container_of(dev, struct node_entry, device);
-       return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64));
-}
-static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
+       unsigned long flags;
+       unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
+       int tf;
 
+       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
+       tf = 64 - bitmap_weight(tp, 64);
+       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
 
-static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-       return sprintf(buf, "%u\n", ne->tpool->allocations);
+       return sprintf(buf, "%d\n", tf);
 }
-static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL);
+static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
 
 
-static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
 {
        struct node_entry *ne = container_of(dev, struct node_entry, device);
+       unsigned long flags;
+       unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
+       u64 tm;
+
+       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
 #if (BITS_PER_LONG <= 32)
-       return sprintf(buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]);
+       tm = ((u64)tp[0] << 32) + tp[1];
 #else
-       return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]);
+       tm = tp[0];
 #endif
+       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
+
+       return sprintf(buf, "0x%016llx\n", tm);
 }
 static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
+#endif /* HPSB_DEBUG_TLABELS */
 
 
 static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -408,26 +411,11 @@ static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
 }
 static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
 
-static int nodemgr_rescan_bus_thread(void *__unused)
-{
-       /* No userlevel access needed */
-       daemonize("kfwrescan");
-
-       bus_rescan_devices(&ieee1394_bus_type);
-
-       return 0;
-}
 
 static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count)
 {
-       int state = simple_strtoul(buf, NULL, 10);
-
-       /* Don't wait for this, or care about errors. Root could do
-        * something stupid and spawn this a lot of times, but that's
-        * root's fault. */
-       if (state == 1)
-               kernel_thread(nodemgr_rescan_bus_thread, NULL, CLONE_KERNEL);
-
+       if (simple_strtoul(buf, NULL, 10) == 1)
+               bus_rescan_devices(&ieee1394_bus_type);
        return count;
 }
 static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
@@ -483,9 +471,10 @@ static struct device_attribute *const fw_ne_attrs[] = {
        &dev_attr_ne_vendor_id,
        &dev_attr_ne_nodeid,
        &dev_attr_bus_options,
+#ifdef HPSB_DEBUG_TLABELS
        &dev_attr_tlabels_free,
-       &dev_attr_tlabels_allocations,
        &dev_attr_tlabels_mask,
+#endif
 };
 
 
@@ -804,8 +793,6 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
        if (!ne)
                return NULL;
 
-       ne->tpool = &host->tpool[nodeid & NODE_MASK];
-
        ne->host = host;
        ne->nodeid = nodeid;
        ne->generation = generation;
@@ -1251,6 +1238,7 @@ static void nodemgr_node_scan_one(struct host_info *hi,
        octlet_t guid;
        struct csr1212_csr *csr;
        struct nodemgr_csr_info *ci;
+       u8 *speed;
 
        ci = kmalloc(sizeof(*ci), GFP_KERNEL);
        if (!ci)
@@ -1259,8 +1247,12 @@ static void nodemgr_node_scan_one(struct host_info *hi,
        ci->host = host;
        ci->nodeid = nodeid;
        ci->generation = generation;
-       ci->speed_unverified =
-               host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100;
+
+       /* Prepare for speed probe which occurs when reading the ROM */
+       speed = &(host->speed[NODEID_TO_NODE(nodeid)]);
+       if (*speed > host->csr.lnk_spd)
+               *speed = host->csr.lnk_spd;
+       ci->speed_unverified = *speed > IEEE1394_SPEED_100;
 
        /* We need to detect when the ConfigROM's generation has changed,
         * so we only update the node's info when it needs to be.  */
@@ -1300,8 +1292,6 @@ static void nodemgr_node_scan_one(struct host_info *hi,
                nodemgr_create_node(guid, csr, hi, nodeid, generation);
        else
                nodemgr_update_node(ne, csr, hi, nodeid, generation);
-
-       return;
 }
 
 
@@ -1326,6 +1316,7 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
 }
 
 
+/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
 static void nodemgr_suspend_ne(struct node_entry *ne)
 {
        struct class_device *cdev;
@@ -1361,6 +1352,7 @@ static void nodemgr_resume_ne(struct node_entry *ne)
        ne->in_limbo = 0;
        device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
+       down_read(&nodemgr_ud_class.subsys.rwsem);
        down_read(&ne->device.bus->subsys.rwsem);
        list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
                ud = container_of(cdev, struct unit_directory, class_dev);
@@ -1372,21 +1364,21 @@ static void nodemgr_resume_ne(struct node_entry *ne)
                        ud->device.driver->resume(&ud->device);
        }
        up_read(&ne->device.bus->subsys.rwsem);
+       up_read(&nodemgr_ud_class.subsys.rwsem);
 
        HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
                   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
 }
 
 
+/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
        struct unit_directory *ud;
        struct hpsb_protocol_driver *pdrv;
-       struct class *class = &nodemgr_ud_class;
        struct class_device *cdev;
 
-       down_read(&class->subsys.rwsem);
-       list_for_each_entry(cdev, &class->children, node) {
+       list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
                ud = container_of(cdev, struct unit_directory, class_dev);
                if (ud->ne != ne || !ud->device.driver)
                        continue;
@@ -1399,7 +1391,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
                        up_write(&ud->device.bus->subsys.rwsem);
                }
        }
-       up_read(&class->subsys.rwsem);
 }
 
 
@@ -1430,6 +1421,8 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
 }
 
 
+/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the
+ * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */
 static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
 {
        struct device *dev;
@@ -1492,9 +1485,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
        /* If we had a bus reset while we were scanning the bus, it is
         * possible that we did not probe all nodes.  In that case, we
         * skip the clean up for now, since we could remove nodes that
-        * were still on the bus.  The bus reset increased hi->reset_sem,
-        * so there's a bus scan pending which will do the clean up
-        * eventually.
+        * were still on the bus.  Another bus scan is pending which will
+        * do the clean up eventually.
         *
         * Now let's tell the bus to rescan our devices. This may seem
         * like overhead, but the driver-model core will only scan a
@@ -1622,41 +1614,37 @@ static int nodemgr_host_thread(void *__hi)
 {
        struct host_info *hi = (struct host_info *)__hi;
        struct hpsb_host *host = hi->host;
-       int reset_cycles = 0;
-
-       /* No userlevel access needed */
-       daemonize(hi->daemon_name);
+       unsigned int g, generation = get_hpsb_generation(host) - 1;
+       int i, reset_cycles = 0;
 
        /* Setup our device-model entries */
        nodemgr_create_host_dev_files(host);
 
-       /* Sit and wait for a signal to probe the nodes on the bus. This
-        * happens when we get a bus reset. */
-       while (1) {
-               unsigned int generation = 0;
-               int i;
+       for (;;) {
+               /* Sleep until next bus reset */
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (get_hpsb_generation(host) == generation)
+                       schedule();
+               __set_current_state(TASK_RUNNING);
+
+               /* Thread may have been woken up to freeze or to exit */
+               if (try_to_freeze())
+                       continue;
+               if (kthread_should_stop())
+                       goto exit;
 
-               if (down_interruptible(&hi->reset_sem) ||
-                   down_interruptible(&nodemgr_serialize)) {
+               if (mutex_lock_interruptible(&nodemgr_serialize)) {
                        if (try_to_freeze())
                                continue;
-                       printk("NodeMgr: received unexpected signal?!\n" );
-                       break;
-               }
-
-               if (hi->kill_me) {
-                       up(&nodemgr_serialize);
-                       break;
+                       goto exit;
                }
 
                /* Pause for 1/4 second in 1/16 second intervals,
                 * to make sure things settle down. */
+               g = get_hpsb_generation(host);
                for (i = 0; i < 4 ; i++) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (msleep_interruptible(63)) {
-                               up(&nodemgr_serialize);
-                               goto caught_signal;
-                       }
+                       if (msleep_interruptible(63) || kthread_should_stop())
+                               goto unlock_exit;
 
                        /* Now get the generation in which the node ID's we collect
                         * are valid.  During the bus scan we will use this generation
@@ -1667,20 +1655,14 @@ static int nodemgr_host_thread(void *__hi)
 
                        /* If we get a reset before we are done waiting, then
                         * start the the waiting over again */
-                       while (!down_trylock(&hi->reset_sem))
-                               i = 0;
-
-                       /* Check the kill_me again */
-                       if (hi->kill_me) {
-                               up(&nodemgr_serialize);
-                               goto caught_signal;
-                       }
+                       if (generation != g)
+                               g = generation, i = 0;
                }
 
                if (!nodemgr_check_irm_capability(host, reset_cycles) ||
                    !nodemgr_do_irm_duties(host, reset_cycles)) {
                        reset_cycles++;
-                       up(&nodemgr_serialize);
+                       mutex_unlock(&nodemgr_serialize);
                        continue;
                }
                reset_cycles = 0;
@@ -1698,13 +1680,13 @@ static int nodemgr_host_thread(void *__hi)
                /* Update some of our sysfs symlinks */
                nodemgr_update_host_dev_links(host);
 
-               up(&nodemgr_serialize);
+               mutex_unlock(&nodemgr_serialize);
        }
-
-caught_signal:
+unlock_exit:
+       mutex_unlock(&nodemgr_serialize);
+exit:
        HPSB_VERBOSE("NodeMgr: Exiting thread");
-
-       complete_and_exit(&hi->exited, 0);
+       return 0;
 }
 
 int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
@@ -1764,41 +1746,27 @@ static void nodemgr_add_host(struct hpsb_host *host)
        struct host_info *hi;
 
        hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi));
-
        if (!hi) {
-               HPSB_ERR ("NodeMgr: out of memory in add host");
+               HPSB_ERR("NodeMgr: out of memory in add host");
                return;
        }
-
        hi->host = host;
-       init_completion(&hi->exited);
-        sema_init(&hi->reset_sem, 0);
-
-       sprintf(hi->daemon_name, "knodemgrd_%d", host->id);
-
-       hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_KERNEL);
-
-       if (hi->pid < 0) {
-               HPSB_ERR ("NodeMgr: failed to start %s thread for %s",
-                         hi->daemon_name, host->driver->name);
+       hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d",
+                                host->id);
+       if (IS_ERR(hi->thread)) {
+               HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
                hpsb_destroy_hostinfo(&nodemgr_highlevel, host);
-               return;
        }
-
-       return;
 }
 
 static void nodemgr_host_reset(struct hpsb_host *host)
 {
        struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
 
-       if (hi != NULL) {
-               HPSB_VERBOSE("NodeMgr: Processing host reset for %s", hi->daemon_name);
-               up(&hi->reset_sem);
-       } else
-               HPSB_ERR ("NodeMgr: could not process reset of unused host");
-
-       return;
+       if (hi) {
+               HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id);
+               wake_up_process(hi->thread);
+       }
 }
 
 static void nodemgr_remove_host(struct hpsb_host *host)
@@ -1806,18 +1774,9 @@ static void nodemgr_remove_host(struct hpsb_host *host)
        struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
 
        if (hi) {
-               if (hi->pid >= 0) {
-                       hi->kill_me = 1;
-                       mb();
-                       up(&hi->reset_sem);
-                       wait_for_completion(&hi->exited);
-                       nodemgr_remove_host_dev(&host->device);
-               }
-       } else
-               HPSB_ERR("NodeMgr: host %s does not exist, cannot remove",
-                        host->driver->name);
-
-       return;
+               kthread_stop(hi->thread);
+               nodemgr_remove_host_dev(&host->device);
+       }
 }
 
 static struct hpsb_highlevel nodemgr_highlevel = {
index 0b26616e16c3f715daeaf57333d41449647e2ffc..0e1e7d930783e7320a78a7f993fc10f756cadc6f 100644 (file)
 #define _IEEE1394_NODEMGR_H
 
 #include <linux/device.h>
-#include "csr1212.h"
+#include <asm/types.h>
+
 #include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
+#include "ieee1394_types.h"
+
+struct csr1212_csr;
+struct csr1212_keyval;
+struct hpsb_host;
+struct ieee1394_device_id;
 
 /* '1' '3' '9' '4' in ASCII */
 #define IEEE1394_BUSID_MAGIC   __constant_cpu_to_be32(0x31333934)
@@ -44,7 +50,6 @@ struct bus_options {
        u16     max_rec;        /* Maximum packet size node can receive */
 };
 
-
 #define UNIT_DIRECTORY_VENDOR_ID               0x01
 #define UNIT_DIRECTORY_MODEL_ID                        0x02
 #define UNIT_DIRECTORY_SPECIFIER_ID            0x04
@@ -59,8 +64,8 @@ struct bus_options {
  * unit directory for each of these protocols.
  */
 struct unit_directory {
-       struct node_entry *ne;  /* The node which this directory belongs to */
-       octlet_t address;       /* Address of the unit directory on the node */
+       struct node_entry *ne;  /* The node which this directory belongs to */
+       octlet_t address;       /* Address of the unit directory on the node */
        u8 flags;               /* Indicates which entries were read */
 
        quadlet_t vendor_id;
@@ -79,11 +84,10 @@ struct unit_directory {
        int length;             /* Number of quadlets */
 
        struct device device;
-
        struct class_device class_dev;
 
        struct csr1212_keyval *ud_kv;
-       u32 lun;                /* logical unit number immediate value */
+       u32 lun;                /* logical unit number immediate value */
 };
 
 struct node_entry {
@@ -103,10 +107,8 @@ struct node_entry {
        const char *vendor_oui;
 
        u32 capabilities;
-       struct hpsb_tlabel_pool *tpool;
 
        struct device device;
-
        struct class_device class_dev;
 
        /* Means this node is not attached anymore */
@@ -153,8 +155,8 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
 /*
  * This will fill in the given, pre-initialised hpsb_packet with the current
  * information from the node entry (host, node ID, generation number).  It will
- * return false if the node owning the GUID is not accessible (and not modify the
- * hpsb_packet) and return true otherwise.
+ * return false if the node owning the GUID is not accessible (and not modify
+ * the hpsb_packet) and return true otherwise.
  *
  * Note that packet sending may still fail in hpsb_send_packet if a bus reset
  * happens while you are trying to set up the packet (due to obsolete generation
@@ -170,16 +172,13 @@ int hpsb_node_write(struct node_entry *ne, u64 addr,
 int hpsb_node_lock(struct node_entry *ne, u64 addr,
                   int extcode, quadlet_t *data, quadlet_t arg);
 
-
 /* Iterate the hosts, calling a given function with supplied data for each
  * host. */
 int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *));
 
-
 int init_ieee1394_nodemgr(void);
 void cleanup_ieee1394_nodemgr(void);
 
-
 /* The template for a host device */
 extern struct device nodemgr_dev_template_host;
 
index 448df27733778d61d31781e475993c53555cf8f1..8fd0030475ba70db16de13164e5af5aa293c0ed2 100644 (file)
 #define DBGMSG(fmt, args...) \
 printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
 #else
-#define DBGMSG(fmt, args...)
+#define DBGMSG(fmt, args...) do {} while (0)
 #endif
 
 #ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
@@ -148,8 +148,8 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->
                --global_outstanding_dmas, ## args)
 static int global_outstanding_dmas = 0;
 #else
-#define OHCI_DMA_ALLOC(fmt, args...)
-#define OHCI_DMA_FREE(fmt, args...)
+#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
+#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
 #endif
 
 /* print general (card independent) information */
@@ -181,36 +181,35 @@ static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
 static void ohci1394_pci_remove(struct pci_dev *pdev);
 
 #ifndef __LITTLE_ENDIAN
-static unsigned hdr_sizes[] =
-{
+const static size_t hdr_sizes[] = {
        3,      /* TCODE_WRITEQ */
        4,      /* TCODE_WRITEB */
        3,      /* TCODE_WRITE_RESPONSE */
-       0,      /* ??? */
+       0,      /* reserved */
        3,      /* TCODE_READQ */
        4,      /* TCODE_READB */
        3,      /* TCODE_READQ_RESPONSE */
        4,      /* TCODE_READB_RESPONSE */
-       1,      /* TCODE_CYCLE_START (???) */
+       1,      /* TCODE_CYCLE_START */
        4,      /* TCODE_LOCK_REQUEST */
        2,      /* TCODE_ISO_DATA */
        4,      /* TCODE_LOCK_RESPONSE */
+               /* rest is reserved or link-internal */
 };
 
-/* Swap headers */
-static inline void packet_swab(quadlet_t *data, int tcode)
+static inline void header_le32_to_cpu(quadlet_t *data, unsigned char tcode)
 {
-       size_t size = hdr_sizes[tcode];
+       size_t size;
 
-       if (tcode > TCODE_LOCK_RESPONSE || hdr_sizes[tcode] == 0)
+       if (unlikely(tcode >= ARRAY_SIZE(hdr_sizes)))
                return;
 
+       size = hdr_sizes[tcode];
        while (size--)
-               data[size] = swab32(data[size]);
+               data[size] = le32_to_cpu(data[size]);
 }
 #else
-/* Don't waste cycles on same sex byte swaps */
-#define packet_swab(w,x)
+#define header_le32_to_cpu(w,x) do {} while (0)
 #endif /* !LITTLE_ENDIAN */
 
 /***********************************
@@ -701,7 +700,7 @@ static void insert_packet(struct ti_ohci *ohci,
                                d->prg_cpu[idx]->data[2] = packet->header[2];
                                d->prg_cpu[idx]->data[3] = packet->header[3];
                        }
-                       packet_swab(d->prg_cpu[idx]->data, packet->tcode);
+                       header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode);
                 }
 
                 if (packet->data_size) { /* block transmit */
@@ -777,7 +776,7 @@ static void insert_packet(struct ti_ohci *ohci,
                 d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
                         (packet->header[0] & 0xFFFF);
                 d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
-               packet_swab(d->prg_cpu[idx]->data, packet->tcode);
+               header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode);
 
                 d->prg_cpu[idx]->begin.control =
                        cpu_to_le32(DMA_CTL_OUTPUT_MORE |
@@ -2598,8 +2597,9 @@ static const int TCODE_SIZE[16] = {20, 0, 16, -1, 16, 20, 20, 0,
  * Determine the length of a packet in the buffer
  * Optimization suggested by Pascal Drolet <pascal.drolet@informission.ca>
  */
-static __inline__ int packet_length(struct dma_rcv_ctx *d, int idx, quadlet_t *buf_ptr,
-                        int offset, unsigned char tcode, int noswap)
+static inline int packet_length(struct dma_rcv_ctx *d, int idx,
+                               quadlet_t *buf_ptr, int offset,
+                               unsigned char tcode, int noswap)
 {
        int length = -1;
 
@@ -2730,7 +2730,7 @@ static void dma_rcv_tasklet (unsigned long data)
                 * bus reset. We always ignore it.  */
                if (tcode != OHCI1394_TCODE_PHY) {
                        if (!ohci->no_swap_incoming)
-                               packet_swab(d->spb, tcode);
+                               header_le32_to_cpu(d->spb, tcode);
                        DBGMSG("Packet received from node"
                                " %d ack=0x%02X spd=%d tcode=0x%X"
                                " length=%d ctx=%d tlabel=%d",
@@ -2738,7 +2738,7 @@ static void dma_rcv_tasklet (unsigned long data)
                                (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
                                (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
                                tcode, length, d->ctx,
-                               (cond_le32_to_cpu(d->spb[0], ohci->no_swap_incoming)>>10)&0x3f);
+                               (d->spb[0]>>10)&0x3f);
 
                        ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
                                == 0x11) ? 1 : 0;
@@ -3529,9 +3529,10 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
                put_device(dev);
 }
 
-
+#ifdef CONFIG_PM
 static int ohci1394_pci_resume (struct pci_dev *pdev)
 {
+/* PowerMac resume code comes first */
 #ifdef CONFIG_PPC_PMAC
        if (machine_is(powermac)) {
                struct device_node *of_node;
@@ -3543,17 +3544,23 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
        }
 #endif /* CONFIG_PPC_PMAC */
 
+       pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       pci_enable_device(pdev);
-
-       return 0;
+       return pci_enable_device(pdev);
 }
 
-
 static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
 {
-       pci_save_state(pdev);
+       int err;
+
+       err = pci_save_state(pdev);
+       if (err)
+               goto out;
+       err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       if (err)
+               goto out;
 
+/* PowerMac suspend code comes last */
 #ifdef CONFIG_PPC_PMAC
        if (machine_is(powermac)) {
                struct device_node *of_node;
@@ -3563,11 +3570,11 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
                if (of_node)
                        pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
        }
-#endif
-
-       return 0;
+#endif /* CONFIG_PPC_PMAC */
+out:
+       return err;
 }
-
+#endif /* CONFIG_PM */
 
 #define PCI_CLASS_FIREWIRE_OHCI     ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
 
@@ -3590,8 +3597,10 @@ static struct pci_driver ohci1394_pci_driver = {
        .id_table =     ohci1394_pci_tbl,
        .probe =        ohci1394_pci_probe,
        .remove =       ohci1394_pci_remove,
+#ifdef CONFIG_PM
        .resume =       ohci1394_pci_resume,
        .suspend =      ohci1394_pci_suspend,
+#endif
 };
 
 /***********************************
@@ -3718,5 +3727,7 @@ static int __init ohci1394_init(void)
        return pci_register_driver(&ohci1394_pci_driver);
 }
 
-module_init(ohci1394_init);
+/* Register before most other device drivers.
+ * Useful for remote debugging via physical DMA, e.g. using firescope. */
+fs_initcall(ohci1394_init);
 module_exit(ohci1394_cleanup);
index e6f41238f5e8c6c2f579cb5de5ae1fe0d66ce224..b4f146f2c951c9f7f2f208d8ec972d29e95f77eb 100644 (file)
@@ -137,7 +137,6 @@ static struct i2c_algo_bit_data bit_data = {
        .getsda                 = bit_getsda,
        .getscl                 = bit_getscl,
        .udelay                 = 5,
-       .mdelay                 = 5,
        .timeout                = 100,
 };
 
index c93587be9cab411d5232d174046dca67b5e38821..c7731d1bcd89da69559e342be57f2fe6aa1fae3d 100644 (file)
@@ -29,9 +29,8 @@ struct file_info {
 
         struct list_head req_pending;
         struct list_head req_complete;
-        struct semaphore complete_sem;
         spinlock_t reqlists_lock;
-        wait_queue_head_t poll_wait_complete;
+        wait_queue_head_t wait_complete;
 
         struct list_head addr_list;
 
index 571ea68c0cf2fe446d0508768a6460d7ca5036b6..5ec4f5eb6b19834b56fe7a53827321470c24ae20 100644 (file)
 #include <linux/compat.h>
 
 #include "csr1212.h"
+#include "highlevel.h"
+#include "hosts.h"
 #include "ieee1394.h"
-#include "ieee1394_types.h"
 #include "ieee1394_core.h"
-#include "nodemgr.h"
-#include "hosts.h"
-#include "highlevel.h"
-#include "iso.h"
+#include "ieee1394_hotplug.h"
 #include "ieee1394_transactions.h"
+#include "ieee1394_types.h"
+#include "iso.h"
+#include "nodemgr.h"
 #include "raw1394.h"
 #include "raw1394-private.h"
 
@@ -66,7 +67,7 @@
 #define DBGMSG(fmt, args...) \
 printk(KERN_INFO "raw1394:" fmt "\n" , ## args)
 #else
-#define DBGMSG(fmt, args...)
+#define DBGMSG(fmt, args...) do {} while (0)
 #endif
 
 static LIST_HEAD(host_info_list);
@@ -132,10 +133,9 @@ static void free_pending_request(struct pending_request *req)
 static void __queue_complete_req(struct pending_request *req)
 {
        struct file_info *fi = req->file_info;
-       list_move_tail(&req->list, &fi->req_complete);
 
-       up(&fi->complete_sem);
-       wake_up_interruptible(&fi->poll_wait_complete);
+       list_move_tail(&req->list, &fi->req_complete);
+       wake_up(&fi->wait_complete);
 }
 
 static void queue_complete_req(struct pending_request *req)
@@ -463,13 +463,36 @@ raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
 
 #endif
 
+/* get next completed request  (caller must hold fi->reqlists_lock) */
+static inline struct pending_request *__next_complete_req(struct file_info *fi)
+{
+       struct list_head *lh;
+       struct pending_request *req = NULL;
+
+       if (!list_empty(&fi->req_complete)) {
+               lh = fi->req_complete.next;
+               list_del(lh);
+               req = list_entry(lh, struct pending_request, list);
+       }
+       return req;
+}
+
+/* atomically get next completed request */
+static struct pending_request *next_complete_req(struct file_info *fi)
+{
+       unsigned long flags;
+       struct pending_request *req;
+
+       spin_lock_irqsave(&fi->reqlists_lock, flags);
+       req = __next_complete_req(fi);
+       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
+       return req;
+}
 
 static ssize_t raw1394_read(struct file *file, char __user * buffer,
                            size_t count, loff_t * offset_is_ignored)
 {
-       unsigned long flags;
        struct file_info *fi = (struct file_info *)file->private_data;
-       struct list_head *lh;
        struct pending_request *req;
        ssize_t ret;
 
@@ -487,22 +510,21 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer,
        }
 
        if (file->f_flags & O_NONBLOCK) {
-               if (down_trylock(&fi->complete_sem)) {
+               if (!(req = next_complete_req(fi)))
                        return -EAGAIN;
-               }
        } else {
-               if (down_interruptible(&fi->complete_sem)) {
+               /*
+                * NB: We call the macro wait_event_interruptible() with a
+                * condition argument with side effect.  This is only possible
+                * because the side effect does not occur until the condition
+                * became true, and wait_event_interruptible() won't evaluate
+                * the condition again after that.
+                */
+               if (wait_event_interruptible(fi->wait_complete,
+                                            (req = next_complete_req(fi))))
                        return -ERESTARTSYS;
-               }
        }
 
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       lh = fi->req_complete.next;
-       list_del(lh);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       req = list_entry(lh, struct pending_request, list);
-
        if (req->req.length) {
                if (copy_to_user(int2ptr(req->req.recvb), req->data,
                                 req->req.length)) {
@@ -1752,6 +1774,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
        addr->notification_options |= addr->client_transactions;
        addr->recvb = req->req.recvb;
        addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
+
        spin_lock_irqsave(&host_info_lock, flags);
        hi = find_host_info(fi->host);
        same_host = 0;
@@ -1777,9 +1800,9 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
        }
        if (same_host) {
                /* addressrange occupied by same host */
+               spin_unlock_irqrestore(&host_info_lock, flags);
                vfree(addr->addr_space_buffer);
                kfree(addr);
-               spin_unlock_irqrestore(&host_info_lock, flags);
                return (-EALREADY);
        }
        /* another host with valid address-entry containing same addressrange */
@@ -1807,6 +1830,8 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
                        }
                }
        }
+       spin_unlock_irqrestore(&host_info_lock, flags);
+
        if (another_host) {
                DBGMSG("another hosts entry is valid -> SUCCESS");
                if (copy_to_user(int2ptr(req->req.recvb),
@@ -1815,11 +1840,11 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
                               " address-range-entry is invalid -> EFAULT !!!\n");
                        vfree(addr->addr_space_buffer);
                        kfree(addr);
-                       spin_unlock_irqrestore(&host_info_lock, flags);
                        return (-EFAULT);
                }
                free_pending_request(req);      /* immediate success or fail */
                /* INSERT ENTRY */
+               spin_lock_irqsave(&host_info_lock, flags);
                list_add_tail(&addr->addr_list, &fi->addr_list);
                spin_unlock_irqrestore(&host_info_lock, flags);
                return sizeof(struct raw1394_request);
@@ -1830,15 +1855,15 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
                                    req->req.address + req->req.length);
        if (retval) {
                /* INSERT ENTRY */
+               spin_lock_irqsave(&host_info_lock, flags);
                list_add_tail(&addr->addr_list, &fi->addr_list);
+               spin_unlock_irqrestore(&host_info_lock, flags);
        } else {
                DBGMSG("arm_register failed errno: %d \n", retval);
                vfree(addr->addr_space_buffer);
                kfree(addr);
-               spin_unlock_irqrestore(&host_info_lock, flags);
                return (-EALREADY);
        }
-       spin_unlock_irqrestore(&host_info_lock, flags);
        free_pending_request(req);      /* immediate success or fail */
        return sizeof(struct raw1394_request);
 }
@@ -1904,10 +1929,10 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
        if (another_host) {
                DBGMSG("delete entry from list -> success");
                list_del(&addr->addr_list);
+               spin_unlock_irqrestore(&host_info_lock, flags);
                vfree(addr->addr_space_buffer);
                kfree(addr);
                free_pending_request(req);      /* immediate success or fail */
-               spin_unlock_irqrestore(&host_info_lock, flags);
                return sizeof(struct raw1394_request);
        }
        retval =
@@ -1949,23 +1974,19 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
                    (arm_addr->end > req->req.address)) {
                        if (req->req.address + req->req.length <= arm_addr->end) {
                                offset = req->req.address - arm_addr->start;
+                               spin_unlock_irqrestore(&host_info_lock, flags);
 
                                DBGMSG
                                    ("arm_get_buf copy_to_user( %08X, %p, %u )",
                                     (u32) req->req.recvb,
                                     arm_addr->addr_space_buffer + offset,
                                     (u32) req->req.length);
-
                                if (copy_to_user
                                    (int2ptr(req->req.recvb),
                                     arm_addr->addr_space_buffer + offset,
-                                    req->req.length)) {
-                                       spin_unlock_irqrestore(&host_info_lock,
-                                                              flags);
+                                    req->req.length))
                                        return (-EFAULT);
-                               }
 
-                               spin_unlock_irqrestore(&host_info_lock, flags);
                                /* We have to free the request, because we
                                 * queue no response, and therefore nobody
                                 * will free it. */
@@ -2005,24 +2026,23 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
                    (arm_addr->end > req->req.address)) {
                        if (req->req.address + req->req.length <= arm_addr->end) {
                                offset = req->req.address - arm_addr->start;
+                               spin_unlock_irqrestore(&host_info_lock, flags);
 
                                DBGMSG
                                    ("arm_set_buf copy_from_user( %p, %08X, %u )",
                                     arm_addr->addr_space_buffer + offset,
                                     (u32) req->req.sendb,
                                     (u32) req->req.length);
-
                                if (copy_from_user
                                    (arm_addr->addr_space_buffer + offset,
                                     int2ptr(req->req.sendb),
-                                    req->req.length)) {
-                                       spin_unlock_irqrestore(&host_info_lock,
-                                                              flags);
+                                    req->req.length))
                                        return (-EFAULT);
-                               }
 
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-                               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
+                               /* We have to free the request, because we
+                                * queue no response, and therefore nobody
+                                * will free it. */
+                               free_pending_request(req);
                                return sizeof(struct raw1394_request);
                        } else {
                                DBGMSG("arm_set_buf request exceeded mapping");
@@ -2744,7 +2764,7 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt)
        unsigned int mask = POLLOUT | POLLWRNORM;
        unsigned long flags;
 
-       poll_wait(file, &fi->poll_wait_complete, pt);
+       poll_wait(file, &fi->wait_complete, pt);
 
        spin_lock_irqsave(&fi->reqlists_lock, flags);
        if (!list_empty(&fi->req_complete)) {
@@ -2769,9 +2789,8 @@ static int raw1394_open(struct inode *inode, struct file *file)
        fi->state = opened;
        INIT_LIST_HEAD(&fi->req_pending);
        INIT_LIST_HEAD(&fi->req_complete);
-       sema_init(&fi->complete_sem, 0);
        spin_lock_init(&fi->reqlists_lock);
-       init_waitqueue_head(&fi->poll_wait_complete);
+       init_waitqueue_head(&fi->wait_complete);
        INIT_LIST_HEAD(&fi->addr_list);
 
        file->private_data = fi;
@@ -2784,7 +2803,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
        struct file_info *fi = file->private_data;
        struct list_head *lh;
        struct pending_request *req;
-       int done = 0, i, fail = 0;
+       int i, fail;
        int retval = 0;
        struct list_head *entry;
        struct arm_addr *addr = NULL;
@@ -2864,25 +2883,28 @@ static int raw1394_release(struct inode *inode, struct file *file)
                       "error(s) occurred \n");
        }
 
-       while (!done) {
+       for (;;) {
+               /* This locked section guarantees that neither
+                * complete nor pending requests exist once i!=0 */
                spin_lock_irqsave(&fi->reqlists_lock, flags);
-
-               while (!list_empty(&fi->req_complete)) {
-                       lh = fi->req_complete.next;
-                       list_del(lh);
-
-                       req = list_entry(lh, struct pending_request, list);
-
+               while ((req = __next_complete_req(fi)))
                        free_pending_request(req);
-               }
-
-               if (list_empty(&fi->req_pending))
-                       done = 1;
 
+               i = list_empty(&fi->req_pending);
                spin_unlock_irqrestore(&fi->reqlists_lock, flags);
 
-               if (!done)
-                       down_interruptible(&fi->complete_sem);
+               if (i)
+                       break;
+               /*
+                * Sleep until more requests can be freed.
+                *
+                * NB: We call the macro wait_event() with a condition argument
+                * with side effect.  This is only possible because the side
+                * effect does not occur until the condition became true, and
+                * wait_event() won't evaluate the condition again after that.
+                */
+               wait_event(fi->wait_complete, (req = next_complete_req(fi)));
+               free_pending_request(req);
        }
 
        /* Remove any sub-trees left by user space programs */
index b08755e2e68f31115ff11920f598835001ea0bd3..6986ac188281745eda188c9b1c26110a9fe7f62f 100644 (file)
  *       but the code needs additional debugging.
  */
 
+#include <linux/blkdev.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/wait.h>
 
-#include <asm/current.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
+#include <asm/errno.h>
+#include <asm/param.h>
 #include <asm/scatterlist.h>
+#include <asm/system.h>
+#include <asm/types.h>
+
+#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
+#include <asm/io.h> /* for bus_to_virt */
+#endif
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 
 #include "csr1212.h"
+#include "highlevel.h"
+#include "hosts.h"
 #include "ieee1394.h"
-#include "ieee1394_types.h"
 #include "ieee1394_core.h"
-#include "nodemgr.h"
-#include "hosts.h"
-#include "highlevel.h"
+#include "ieee1394_hotplug.h"
 #include "ieee1394_transactions.h"
+#include "ieee1394_types.h"
+#include "nodemgr.h"
 #include "sbp2.h"
 
 /*
@@ -173,11 +179,6 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
        ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
        ", or a combination)");
 
-/* legacy parameter */
-static int force_inquiry_hack;
-module_param(force_inquiry_hack, int, 0644);
-MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'");
-
 /*
  * Export information about protocols/devices supported by this driver.
  */
@@ -208,9 +209,9 @@ static u32 global_outstanding_command_orbs = 0;
 #define outstanding_orb_incr global_outstanding_command_orbs++
 #define outstanding_orb_decr global_outstanding_command_orbs--
 #else
-#define SBP2_ORB_DEBUG(fmt, args...)
-#define outstanding_orb_incr
-#define outstanding_orb_decr
+#define SBP2_ORB_DEBUG(fmt, args...)   do {} while (0)
+#define outstanding_orb_incr           do {} while (0)
+#define outstanding_orb_decr           do {} while (0)
 #endif
 
 #ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA
@@ -222,8 +223,8 @@ static u32 global_outstanding_command_orbs = 0;
                 --global_outstanding_dmas, ## args)
 static u32 global_outstanding_dmas = 0;
 #else
-#define SBP2_DMA_ALLOC(fmt, args...)
-#define SBP2_DMA_FREE(fmt, args...)
+#define SBP2_DMA_ALLOC(fmt, args...)   do {} while (0)
+#define SBP2_DMA_FREE(fmt, args...)    do {} while (0)
 #endif
 
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 2
@@ -237,7 +238,7 @@ static u32 global_outstanding_dmas = 0;
 #define SBP2_NOTICE(fmt, args...)      HPSB_NOTICE("sbp2: "fmt, ## args)
 #define SBP2_WARN(fmt, args...)                HPSB_WARN("sbp2: "fmt, ## args)
 #else
-#define SBP2_DEBUG(fmt, args...)
+#define SBP2_DEBUG(fmt, args...)       do {} while (0)
 #define SBP2_INFO(fmt, args...)                HPSB_INFO("sbp2: "fmt, ## args)
 #define SBP2_NOTICE(fmt, args...)       HPSB_NOTICE("sbp2: "fmt, ## args)
 #define SBP2_WARN(fmt, args...)         HPSB_WARN("sbp2: "fmt, ## args)
@@ -356,7 +357,7 @@ static const struct {
 /*
  * Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
  */
-static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
+static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
 {
        u32 *temp = buffer;
 
@@ -369,7 +370,7 @@ static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
 /*
  * Converts a buffer from cpu to be32 byte ordering. Length is in bytes.
  */
-static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
+static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 {
        u32 *temp = buffer;
 
@@ -380,8 +381,8 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 }
 #else /* BIG_ENDIAN */
 /* Why waste the cpu cycles? */
-#define sbp2util_be32_to_cpu_buffer(x,y)
-#define sbp2util_cpu_to_be32_buffer(x,y)
+#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0)
+#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0)
 #endif
 
 #ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP
@@ -417,24 +418,26 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name,
        return;
 }
 #else
-#define sbp2util_packet_dump(w,x,y,z)
+#define sbp2util_packet_dump(w,x,y,z) do {} while (0)
 #endif
 
+static DECLARE_WAIT_QUEUE_HEAD(access_wq);
+
 /*
- * Goofy routine that basically does a down_timeout function.
+ * Waits for completion of an SBP-2 access request.
+ * Returns nonzero if timed out or prematurely interrupted.
  */
-static int sbp2util_down_timeout(atomic_t *done, int timeout)
+static int sbp2util_access_timeout(struct scsi_id_instance_data *scsi_id,
+                                  int timeout)
 {
-       int i;
+       long leftover = wait_event_interruptible_timeout(
+                               access_wq, scsi_id->access_complete, timeout);
 
-       for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
-               if (msleep_interruptible(100))  /* 100ms */
-                       return 1;
-       }
-       return (i > 0) ? 0 : 1;
+       scsi_id->access_complete = 0;
+       return leftover <= 0;
 }
 
-/* Free's an allocated packet */
+/* Frees an allocated packet */
 static void sbp2_free_packet(struct hpsb_packet *packet)
 {
        hpsb_free_tlabel(packet);
@@ -468,6 +471,44 @@ static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
        return 0;
 }
 
+static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id,
+                                       u64 offset, quadlet_t *data, size_t len)
+{
+       /*
+        * There is a small window after a bus reset within which the node
+        * entry's generation is current but the reconnect wasn't completed.
+        */
+       if (unlikely(atomic_read(&scsi_id->state) == SBP2LU_STATE_IN_RESET))
+               return;
+
+       if (hpsb_node_write(scsi_id->ne,
+                           scsi_id->sbp2_command_block_agent_addr + offset,
+                           data, len))
+               SBP2_ERR("sbp2util_notify_fetch_agent failed.");
+       /*
+        * Now accept new SCSI commands, unless a bus reset happended during
+        * hpsb_node_write.
+        */
+       if (likely(atomic_read(&scsi_id->state) != SBP2LU_STATE_IN_RESET))
+               scsi_unblock_requests(scsi_id->scsi_host);
+}
+
+static void sbp2util_write_orb_pointer(void *p)
+{
+       quadlet_t data[2];
+
+       data[0] = ORB_SET_NODE_ID(
+                       ((struct scsi_id_instance_data *)p)->hi->host->node_id);
+       data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma;
+       sbp2util_cpu_to_be32_buffer(data, 8);
+       sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8);
+}
+
+static void sbp2util_write_doorbell(void *p)
+{
+       sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4);
+}
+
 /*
  * This function is called to create a pool of command orbs used for
  * command processing. It is called when a new sbp2 device is detected.
@@ -492,7 +533,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
                command->command_orb_dma =
                    pci_map_single(hi->host->pdev, &command->command_orb,
                                   sizeof(struct sbp2_command_orb),
-                                  PCI_DMA_BIDIRECTIONAL);
+                                  PCI_DMA_TODEVICE);
                SBP2_DMA_ALLOC("single command orb DMA");
                command->sge_dma =
                    pci_map_single(hi->host->pdev,
@@ -525,7 +566,7 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_
                        /* Release our generic DMA's */
                        pci_unmap_single(host->pdev, command->command_orb_dma,
                                         sizeof(struct sbp2_command_orb),
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        PCI_DMA_TODEVICE);
                        SBP2_DMA_FREE("single command orb DMA");
                        pci_unmap_single(host->pdev, command->sge_dma,
                                         sizeof(command->scatter_gather_element),
@@ -715,6 +756,7 @@ static int sbp2_remove(struct device *dev)
                        sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
                /* scsi_remove_device() will trigger shutdown functions of SCSI
                 * highlevel drivers which would deadlock if blocked. */
+               atomic_set(&scsi_id->state, SBP2LU_STATE_IN_SHUTDOWN);
                scsi_unblock_requests(scsi_id->scsi_host);
        }
        sdev = scsi_id->sdev;
@@ -766,10 +808,12 @@ static int sbp2_update(struct unit_directory *ud)
         */
        sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
 
-       /* Make sure we unblock requests (since this is likely after a bus
-        * reset). */
-       scsi_unblock_requests(scsi_id->scsi_host);
-
+       /* Accept new commands unless there was another bus reset in the
+        * meantime. */
+       if (hpsb_node_entry_valid(scsi_id->ne)) {
+               atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
+               scsi_unblock_requests(scsi_id->scsi_host);
+       }
        return 0;
 }
 
@@ -794,11 +838,12 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
        scsi_id->speed_code = IEEE1394_SPEED_100;
        scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
        scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
        INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
        INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
        INIT_LIST_HEAD(&scsi_id->scsi_list);
        spin_lock_init(&scsi_id->sbp2_command_orb_lock);
+       atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
+       INIT_WORK(&scsi_id->protocol_work, NULL, NULL);
 
        ud->device.driver_data = scsi_id;
 
@@ -881,11 +926,14 @@ static void sbp2_host_reset(struct hpsb_host *host)
        struct scsi_id_instance_data *scsi_id;
 
        hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-
-       if (hi) {
-               list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
+       if (!hi)
+               return;
+       list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
+               if (likely(atomic_read(&scsi_id->state) !=
+                          SBP2LU_STATE_IN_SHUTDOWN)) {
+                       atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET);
                        scsi_block_requests(scsi_id->scsi_host);
-       }
+               }
 }
 
 /*
@@ -970,8 +1018,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
         * connected to the sbp2 device being removed. That host would
         * have a certain amount of time to relogin before the sbp2 device
         * allows someone else to login instead. One second makes sense. */
-       msleep_interruptible(1000);
-       if (signal_pending(current)) {
+       if (msleep_interruptible(1000)) {
                sbp2_remove_device(scsi_id);
                return -EINTR;
        }
@@ -1036,7 +1083,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
                scsi_remove_host(scsi_id->scsi_host);
                scsi_host_put(scsi_id->scsi_host);
        }
-
+       flush_scheduled_work();
        sbp2util_remove_command_orb_pool(scsi_id);
 
        list_del(&scsi_id->scsi_list);
@@ -1182,17 +1229,14 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
                             "sbp2 query logins orb", scsi_id->query_logins_orb_dma);
 
        memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->query_logins_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
+       if (sbp2util_access_timeout(scsi_id, 2*HZ)) {
                SBP2_INFO("Error querying logins to SBP-2 device - timed out");
                return -EIO;
        }
@@ -1202,11 +1246,8 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
                return -EIO;
        }
 
-       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-               SBP2_INFO("Error querying logins to SBP-2 device - timed out");
+       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+               SBP2_INFO("Error querying logins to SBP-2 device - failed");
                return -EIO;
        }
 
@@ -1278,21 +1319,18 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
                             "sbp2 login orb", scsi_id->login_orb_dma);
 
        memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->login_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 
        /*
         * Wait for login status (up to 20 seconds)...
         */
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) {
-               SBP2_ERR("Error logging into SBP-2 device - login timed-out");
+       if (sbp2util_access_timeout(scsi_id, 20*HZ)) {
+               SBP2_ERR("Error logging into SBP-2 device - timed out");
                return -EIO;
        }
 
@@ -1300,18 +1338,12 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
         * Sanity. Make sure status returned matches login orb.
         */
        if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
-               SBP2_ERR("Error logging into SBP-2 device - login timed-out");
+               SBP2_ERR("Error logging into SBP-2 device - timed out");
                return -EIO;
        }
 
-       /*
-        * Check status
-        */
-       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-               SBP2_ERR("Error logging into SBP-2 device - login failed");
+       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+               SBP2_ERR("Error logging into SBP-2 device - failed");
                return -EIO;
        }
 
@@ -1335,9 +1367,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
        scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
 
        SBP2_INFO("Logged into SBP-2 device");
-
        return 0;
-
 }
 
 /*
@@ -1387,21 +1417,17 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
        data[1] = scsi_id->logout_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        error = hpsb_node_write(scsi_id->ne,
                                scsi_id->sbp2_management_agent_addr, data, 8);
        if (error)
                return error;
 
        /* Wait for device to logout...1 second. */
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ))
+       if (sbp2util_access_timeout(scsi_id, HZ))
                return -EIO;
 
        SBP2_INFO("Logged out of SBP-2 device");
-
        return 0;
-
 }
 
 /*
@@ -1445,20 +1471,10 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
        sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb),
                             "sbp2 reconnect orb", scsi_id->reconnect_orb_dma);
 
-       /*
-        * Initialize status fifo
-        */
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
-
-       /*
-        * Ok, let's write to the target's management agent register
-        */
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->reconnect_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        error = hpsb_node_write(scsi_id->ne,
                                scsi_id->sbp2_management_agent_addr, data, 8);
        if (error)
@@ -1467,8 +1483,8 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
        /*
         * Wait for reconnect status (up to 1 second)...
         */
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
+       if (sbp2util_access_timeout(scsi_id, HZ)) {
+               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
                return -EIO;
        }
 
@@ -1476,25 +1492,17 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
         * Sanity. Make sure status returned matches reconnect orb.
         */
        if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
+               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
                return -EIO;
        }
 
-       /*
-        * Check status
-        */
-       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-               SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
+       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+               SBP2_ERR("Error reconnecting to SBP-2 device - failed");
                return -EIO;
        }
 
        HPSB_DEBUG("Reconnected to SBP-2 device");
-
        return 0;
-
 }
 
 /*
@@ -1592,11 +1600,6 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
        }
 
        workarounds = sbp2_default_workarounds;
-       if (force_inquiry_hack) {
-               SBP2_WARN("force_inquiry_hack is deprecated. "
-                         "Use parameter 'workarounds' instead.");
-               workarounds |= SBP2_WORKAROUND_INQUIRY_36;
-       }
 
        if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
                for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
@@ -1705,9 +1708,14 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
        quadlet_t data;
        u64 addr;
        int retval;
+       unsigned long flags;
 
        SBP2_DEBUG_ENTER();
 
+       cancel_delayed_work(&scsi_id->protocol_work);
+       if (wait)
+               flush_scheduled_work();
+
        data = ntohl(SBP2_AGENT_RESET_DATA);
        addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
 
@@ -1724,7 +1732,9 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
        /*
         * Need to make sure orb pointer is written on next command
         */
+       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
        scsi_id->last_orb = NULL;
+       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
        return 0;
 }
@@ -1961,13 +1971,17 @@ static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
 /*
  * This function is called in order to begin a regular SBP-2 command.
  */
-static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
+static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
                                 struct sbp2_command_info *command)
 {
        struct sbp2scsi_host_info *hi = scsi_id->hi;
        struct sbp2_command_orb *command_orb = &command->command_orb;
-       struct node_entry *ne = scsi_id->ne;
-       u64 addr;
+       struct sbp2_command_orb *last_orb;
+       dma_addr_t last_orb_dma;
+       u64 addr = scsi_id->sbp2_command_block_agent_addr;
+       quadlet_t data[2];
+       size_t length;
+       unsigned long flags;
 
        outstanding_orb_incr;
        SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
@@ -1975,73 +1989,70 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 
        pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,
                                       sizeof(struct sbp2_command_orb),
-                                      PCI_DMA_BIDIRECTIONAL);
+                                      PCI_DMA_TODEVICE);
        pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma,
                                       sizeof(command->scatter_gather_element),
                                       PCI_DMA_BIDIRECTIONAL);
        /*
         * Check to see if there are any previous orbs to use
         */
-       if (scsi_id->last_orb == NULL) {
-               quadlet_t data[2];
-
+       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+       last_orb = scsi_id->last_orb;
+       last_orb_dma = scsi_id->last_orb_dma;
+       if (!last_orb) {
                /*
-                * Ok, let's write to the target's management agent register
+                * last_orb == NULL means: We know that the target's fetch agent
+                * is not active right now.
                 */
-               addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET;
+               addr += SBP2_ORB_POINTER_OFFSET;
                data[0] = ORB_SET_NODE_ID(hi->host->node_id);
                data[1] = command->command_orb_dma;
                sbp2util_cpu_to_be32_buffer(data, 8);
-
-               SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
-
-               if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) {
-                       SBP2_ERR("sbp2util_node_write_no_wait failed.\n");
-                       return -EIO;
-               }
-
-               SBP2_ORB_DEBUG("write command agent complete");
-
-               scsi_id->last_orb = command_orb;
-               scsi_id->last_orb_dma = command->command_orb_dma;
-
+               length = 8;
        } else {
-               quadlet_t data;
-
                /*
-                * We have an orb already sent (maybe or maybe not
-                * processed) that we can append this orb to. So do so,
-                * and ring the doorbell. Have to be very careful
-                * modifying these next orb pointers, as they are accessed
-                * both by the sbp2 device and us.
+                * last_orb != NULL means: We know that the target's fetch agent
+                * is (very probably) not dead or in reset state right now.
+                * We have an ORB already sent that we can append a new one to.
+                * The target's fetch agent may or may not have read this
+                * previous ORB yet.
                 */
-               scsi_id->last_orb->next_ORB_lo =
-                   cpu_to_be32(command->command_orb_dma);
+               pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma,
+                                           sizeof(struct sbp2_command_orb),
+                                           PCI_DMA_TODEVICE);
+               last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);
+               wmb();
                /* Tells hardware that this pointer is valid */
-               scsi_id->last_orb->next_ORB_hi = 0x0;
-               pci_dma_sync_single_for_device(hi->host->pdev,
-                                              scsi_id->last_orb_dma,
+               last_orb->next_ORB_hi = 0;
+               pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma,
                                               sizeof(struct sbp2_command_orb),
-                                              PCI_DMA_BIDIRECTIONAL);
+                                              PCI_DMA_TODEVICE);
+               addr += SBP2_DOORBELL_OFFSET;
+               data[0] = 0;
+               length = 4;
+       }
+       scsi_id->last_orb = command_orb;
+       scsi_id->last_orb_dma = command->command_orb_dma;
+       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
+       SBP2_ORB_DEBUG("write to %s register, command orb %p",
+                       last_orb ? "DOORBELL" : "ORB_POINTER", command_orb);
+       if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) {
                /*
-                * Ring the doorbell
+                * sbp2util_node_write_no_wait failed. We certainly ran out
+                * of transaction labels, perhaps just because there were no
+                * context switches which gave khpsbpkt a chance to collect
+                * free tlabels. Try again in non-atomic context. If necessary,
+                * the workqueue job will sleep to guaranteedly get a tlabel.
+                * We do not accept new commands until the job is over.
                 */
-               data = cpu_to_be32(command->command_orb_dma);
-               addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET;
-
-               SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
-
-               if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
-                       SBP2_ERR("sbp2util_node_write_no_wait failed");
-                       return -EIO;
-               }
-
-               scsi_id->last_orb = command_orb;
-               scsi_id->last_orb_dma = command->command_orb_dma;
-
+               scsi_block_requests(scsi_id->scsi_host);
+               PREPARE_WORK(&scsi_id->protocol_work,
+                            last_orb ? sbp2util_write_doorbell:
+                                       sbp2util_write_orb_pointer,
+                            scsi_id);
+               schedule_work(&scsi_id->protocol_work);
        }
-       return 0;
 }
 
 /*
@@ -2077,11 +2088,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
        sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb),
                             "sbp2 command orb", command->command_orb_dma);
 
-       /*
-        * Initialize status fifo
-        */
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
-
        /*
         * Link up the orb, and ring the doorbell if needed
         */
@@ -2123,12 +2129,14 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
 /*
  * This function deals with status writes from the SBP-2 device
  */
-static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
-                                   quadlet_t *data, u64 addr, size_t length, u16 fl)
+static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
+                                   int destid, quadlet_t *data, u64 addr,
+                                   size_t length, u16 fl)
 {
        struct sbp2scsi_host_info *hi;
        struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
        struct scsi_cmnd *SCpnt = NULL;
+       struct sbp2_status_block *sb;
        u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
        struct sbp2_command_info *command;
        unsigned long flags;
@@ -2137,18 +2145,19 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
 
        sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
 
-       if (!host) {
+       if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) {
+               SBP2_ERR("Wrong size of status block");
+               return RCODE_ADDRESS_ERROR;
+       }
+       if (unlikely(!host)) {
                SBP2_ERR("host is NULL - this is bad!");
                return RCODE_ADDRESS_ERROR;
        }
-
        hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-
-       if (!hi) {
+       if (unlikely(!hi)) {
                SBP2_ERR("host info is NULL - this is bad!");
                return RCODE_ADDRESS_ERROR;
        }
-
        /*
         * Find our scsi_id structure by looking at the status fifo address
         * written to by the sbp2 device.
@@ -2160,32 +2169,35 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                        break;
                }
        }
-
-       if (!scsi_id) {
+       if (unlikely(!scsi_id)) {
                SBP2_ERR("scsi_id is NULL - device is gone?");
                return RCODE_ADDRESS_ERROR;
        }
 
        /*
-        * Put response into scsi_id status fifo...
+        * Put response into scsi_id status fifo buffer. The first two bytes
+        * come in big endian bit order. Often the target writes only a
+        * truncated status block, minimally the first two quadlets. The rest
+        * is implied to be zeros.
         */
-       memcpy(&scsi_id->status_block, data, length);
+       sb = &scsi_id->status_block;
+       memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent));
+       memcpy(sb, data, length);
+       sbp2util_be32_to_cpu_buffer(sb, 8);
 
        /*
-        * Byte swap first two quadlets (8 bytes) of status for processing
+        * Ignore unsolicited status. Handle command ORB status.
         */
-       sbp2util_be32_to_cpu_buffer(&scsi_id->status_block, 8);
-
-       /*
-        * Handle command ORB status here if necessary. First, need to match status with command.
-        */
-       command = sbp2util_find_command_for_orb(scsi_id, scsi_id->status_block.ORB_offset_lo);
+       if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2))
+               command = NULL;
+       else
+               command = sbp2util_find_command_for_orb(scsi_id,
+                                                       sb->ORB_offset_lo);
        if (command) {
-
                SBP2_DEBUG("Found status for command ORB");
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma,
                                            sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_BIDIRECTIONAL);
+                                           PCI_DMA_TODEVICE);
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma,
                                            sizeof(command->scatter_gather_element),
                                            PCI_DMA_BIDIRECTIONAL);
@@ -2194,7 +2206,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                outstanding_orb_decr;
 
                /*
-                * Matched status with command, now grab scsi command pointers and check status
+                * Matched status with command, now grab scsi command pointers
+                * and check status.
+                */
+               /*
+                * FIXME: If the src field in the status is 1, the ORB DMA must
+                * not be reused until status for a subsequent ORB is received.
                 */
                SCpnt = command->Current_SCpnt;
                spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
@@ -2202,61 +2219,64 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
                if (SCpnt) {
-
+                       u32 h = sb->ORB_offset_hi_misc;
+                       u32 r = STATUS_GET_RESP(h);
+
+                       if (r != RESP_STATUS_REQUEST_COMPLETE) {
+                               SBP2_WARN("resp 0x%x, sbp_status 0x%x",
+                                         r, STATUS_GET_SBP_STATUS(h));
+                               scsi_status =
+                                       r == RESP_STATUS_TRANSPORT_FAILURE ?
+                                       SBP2_SCSI_STATUS_BUSY :
+                                       SBP2_SCSI_STATUS_COMMAND_TERMINATED;
+                       }
                        /*
-                        * See if the target stored any scsi status information
+                        * See if the target stored any scsi status information.
                         */
-                       if (STATUS_GET_LENGTH(scsi_id->status_block.ORB_offset_hi_misc) > 1) {
-                               /*
-                                * Translate SBP-2 status to SCSI sense data
-                                */
+                       if (STATUS_GET_LEN(h) > 1) {
                                SBP2_DEBUG("CHECK CONDITION");
-                               scsi_status = sbp2_status_to_sense_data((unchar *)&scsi_id->status_block, SCpnt->sense_buffer);
+                               scsi_status = sbp2_status_to_sense_data(
+                                       (unchar *)sb, SCpnt->sense_buffer);
                        }
-
                        /*
-                        * Check to see if the dead bit is set. If so, we'll have to initiate
-                        * a fetch agent reset.
+                        * Check to see if the dead bit is set. If so, we'll
+                        * have to initiate a fetch agent reset.
                         */
-                       if (STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-                               /*
-                                * Initiate a fetch agent reset.
-                                */
-                               SBP2_DEBUG("Dead bit set - initiating fetch agent reset");
+                       if (STATUS_TEST_DEAD(h)) {
+                               SBP2_DEBUG("Dead bit set - "
+                                          "initiating fetch agent reset");
                                 sbp2_agent_reset(scsi_id, 0);
                        }
-
                        SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb);
                }
 
                /*
-                * Check here to see if there are no commands in-use. If there are none, we can
-                * null out last orb so that next time around we write directly to the orb pointer...
-                * Quick start saves one 1394 bus transaction.
+                * Check here to see if there are no commands in-use. If there
+                * are none, we know that the fetch agent left the active state
+                * _and_ that we did not reactivate it yet. Therefore clear
+                * last_orb so that next time we write directly to the
+                * ORB_POINTER register. That way the fetch agent does not need
+                * to refetch the next_ORB.
                 */
                spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-               if (list_empty(&scsi_id->sbp2_command_orb_inuse)) {
+               if (list_empty(&scsi_id->sbp2_command_orb_inuse))
                        scsi_id->last_orb = NULL;
-               }
                spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
        } else {
-
                /*
                 * It's probably a login/logout/reconnect status.
                 */
-               if ((scsi_id->login_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
-                   (scsi_id->query_logins_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
-                   (scsi_id->reconnect_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
-                   (scsi_id->logout_orb_dma == scsi_id->status_block.ORB_offset_lo)) {
-                       atomic_set(&scsi_id->sbp2_login_complete, 1);
+               if ((sb->ORB_offset_lo == scsi_id->reconnect_orb_dma) ||
+                   (sb->ORB_offset_lo == scsi_id->login_orb_dma) ||
+                   (sb->ORB_offset_lo == scsi_id->query_logins_orb_dma) ||
+                   (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) {
+                       scsi_id->access_complete = 1;
+                       wake_up_interruptible(&access_wq);
                }
        }
 
        if (SCpnt) {
-
-               /* Complete the SCSI command. */
                SBP2_DEBUG("Completing SCSI command");
                sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt,
                                          command->Current_done);
@@ -2372,7 +2392,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
                command = list_entry(lh, struct sbp2_command_info, list);
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma,
                                            sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_BIDIRECTIONAL);
+                                           PCI_DMA_TODEVICE);
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma,
                                            sizeof(command->scatter_gather_element),
                                            PCI_DMA_BIDIRECTIONAL);
@@ -2495,6 +2515,7 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
                (struct scsi_id_instance_data *)sdev->host->hostdata[0];
 
        scsi_id->sdev = sdev;
+       sdev->allow_restart = 1;
 
        if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
                sdev->inquiry_len = 36;
@@ -2508,16 +2529,12 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
 
        blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
        sdev->use_10_for_rw = 1;
-       sdev->use_10_for_ms = 1;
 
        if (sdev->type == TYPE_DISK &&
            scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
                sdev->skip_ms_page_8 = 1;
        if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
                sdev->fix_capacity = 1;
-       if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
-           (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
-               sdev->allow_restart = 1;
        return 0;
 }
 
@@ -2555,7 +2572,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                        pci_dma_sync_single_for_cpu(hi->host->pdev,
                                                    command->command_orb_dma,
                                                    sizeof(struct sbp2_command_orb),
-                                                   PCI_DMA_BIDIRECTIONAL);
+                                                   PCI_DMA_TODEVICE);
                        pci_dma_sync_single_for_cpu(hi->host->pdev,
                                                    command->sge_dma,
                                                    sizeof(command->scatter_gather_element),
@@ -2571,7 +2588,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                /*
                 * Initiate a fetch agent reset.
                 */
-               sbp2_agent_reset(scsi_id, 0);
+               sbp2_agent_reset(scsi_id, 1);
                sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
        }
 
@@ -2590,7 +2607,7 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 
        if (sbp2util_node_is_available(scsi_id)) {
                SBP2_ERR("Generating sbp2 fetch agent reset");
-               sbp2_agent_reset(scsi_id, 0);
+               sbp2_agent_reset(scsi_id, 1);
        }
 
        return SUCCESS;
index b22ce1aa8fe4e5a716f2313920120c65c943e8eb..abbe48e646c3a7397d8a355de0e8f0757b426647 100644 (file)
@@ -46,8 +46,8 @@
 #define ORB_SET_DIRECTION(value)               ((value & 0x1) << 27)
 
 struct sbp2_command_orb {
-       volatile u32 next_ORB_hi;
-       volatile u32 next_ORB_lo;
+       u32 next_ORB_hi;
+       u32 next_ORB_lo;
        u32 data_descriptor_hi;
        u32 data_descriptor_lo;
        u32 misc;
@@ -180,12 +180,14 @@ struct sbp2_unrestricted_page_table {
 
 #define SBP2_SCSI_STATUS_SELECTION_TIMEOUT     0xff
 
-#define STATUS_GET_ORB_OFFSET_HI(value)         (value & 0xffff)
-#define STATUS_GET_SBP_STATUS(value)            ((value >> 16) & 0xff)
-#define STATUS_GET_LENGTH(value)                ((value >> 24) & 0x7)
-#define STATUS_GET_DEAD_BIT(value)              ((value >> 27) & 0x1)
-#define STATUS_GET_RESP(value)                  ((value >> 28) & 0x3)
-#define STATUS_GET_SRC(value)                   ((value >> 30) & 0x3)
+#define STATUS_GET_SRC(value)                  (((value) >> 30) & 0x3)
+#define STATUS_GET_RESP(value)                 (((value) >> 28) & 0x3)
+#define STATUS_GET_LEN(value)                  (((value) >> 24) & 0x7)
+#define STATUS_GET_SBP_STATUS(value)           (((value) >> 16) & 0xff)
+#define STATUS_GET_ORB_OFFSET_HI(value)                ((value) & 0x0000ffff)
+#define STATUS_TEST_DEAD(value)                        ((value) & 0x08000000)
+/* test 'resp' | 'dead' | 'sbp2_status' */
+#define STATUS_TEST_RDS(value)                 ((value) & 0x38ff0000)
 
 struct sbp2_status_block {
        u32 ORB_offset_hi_misc;
@@ -318,9 +320,9 @@ struct scsi_id_instance_data {
        u64 status_fifo_addr;
 
        /*
-        * Variable used for logins, reconnects, logouts, query logins
+        * Waitqueue flag for logins, reconnects, logouts, query logins
         */
-       atomic_t sbp2_login_complete;
+       int access_complete:1;
 
        /*
         * Pool of command orbs, so we can have more than overlapped command per id
@@ -344,6 +346,16 @@ struct scsi_id_instance_data {
 
        /* Device specific workarounds/brokeness */
        unsigned workarounds;
+
+       atomic_t state;
+       struct work_struct protocol_work;
+};
+
+/* For use in scsi_id_instance_data.state */
+enum sbp2lu_state_types {
+       SBP2LU_STATE_RUNNING,           /* all normal */
+       SBP2LU_STATE_IN_RESET,          /* between bus reset and reconnect */
+       SBP2LU_STATE_IN_SHUTDOWN        /* when sbp2_remove was called */
 };
 
 /* Sbp2 host data structure (one per IEEE1394 host) */
@@ -390,11 +402,6 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
                                    quadlet_t *data, u64 addr, size_t length, u16 flags);
 static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
-static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
-                                struct sbp2_command_info *command);
-static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
-                            struct scsi_cmnd *SCpnt,
-                            void (*done)(struct scsi_cmnd *));
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
                                              unchar *sense_data);
 static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
index c6e3f02bc6d74a731fd36ed3e6616e9d839c72bd..9bc65059cc6901eba8eb4f3cb09e46ca312f5da0 100644 (file)
 #include <linux/compat.h>
 #include <linux/cdev.h>
 
-#include "ieee1394.h"
-#include "ieee1394_types.h"
+#include "dma.h"
+#include "highlevel.h"
 #include "hosts.h"
+#include "ieee1394.h"
 #include "ieee1394_core.h"
-#include "highlevel.h"
-#include "video1394.h"
+#include "ieee1394_hotplug.h"
+#include "ieee1394_types.h"
 #include "nodemgr.h"
-#include "dma.h"
-
 #include "ohci1394.h"
+#include "video1394.h"
 
 #define ISO_CHANNELS 64
 
@@ -129,7 +129,7 @@ struct file_ctx {
 #define DBGMSG(card, fmt, args...) \
 printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args)
 #else
-#define DBGMSG(card, fmt, args...)
+#define DBGMSG(card, fmt, args...) do {} while (0)
 #endif
 
 /* print general (card independent) information */
@@ -1181,7 +1181,8 @@ static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
 
        lock_kernel();
        if (ctx->current_ctx == NULL) {
-               PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set");
+               PRINT(KERN_ERR, ctx->ohci->host->id,
+                               "Current iso context not set");
        } else
                res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
        unlock_kernel();
@@ -1189,6 +1190,40 @@ static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
        return res;
 }
 
+static unsigned int video1394_poll(struct file *file, poll_table *pt)
+{
+       struct file_ctx *ctx;
+       unsigned int mask = 0;
+       unsigned long flags;
+       struct dma_iso_ctx *d;
+       int i;
+
+       lock_kernel();
+       ctx = file->private_data;
+       d = ctx->current_ctx;
+       if (d == NULL) {
+               PRINT(KERN_ERR, ctx->ohci->host->id,
+                               "Current iso context not set");
+               mask = POLLERR;
+               goto done;
+       }
+
+       poll_wait(file, &d->waitq, pt);
+
+       spin_lock_irqsave(&d->lock, flags);
+       for (i = 0; i < d->num_desc; i++) {
+               if (d->buffer_status[i] == VIDEO1394_BUFFER_READY) {
+                       mask |= POLLIN | POLLRDNORM;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&d->lock, flags);
+done:
+       unlock_kernel();
+
+       return mask;
+}
+
 static int video1394_open(struct inode *inode, struct file *file)
 {
        int i = ieee1394_file_to_instance(file);
@@ -1257,6 +1292,7 @@ static struct file_operations video1394_fops=
 #ifdef CONFIG_COMPAT
        .compat_ioctl = video1394_compat_ioctl,
 #endif
+       .poll =         video1394_poll,
        .mmap =         video1394_mmap,
        .open =         video1394_open,
        .release =      video1394_release
index 9cbf09e2052f87d5845b41a3d348f129f7f5250d..60d3fbdd216c72833958cca3b51db16e3cd3d722 100644 (file)
@@ -86,7 +86,7 @@ EXPORT_SYMBOL(rdma_copy_addr);
 int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
 {
        struct net_device *dev;
-       u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+       __be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
        int ret;
 
        dev = ip_dev_find(ip);
@@ -239,7 +239,7 @@ static int addr_resolve_local(struct sockaddr_in *src_in,
 {
        struct net_device *dev;
        u32 src_ip = src_in->sin_addr.s_addr;
-       u32 dst_ip = dst_in->sin_addr.s_addr;
+       __be32 dst_ip = dst_in->sin_addr.s_addr;
        int ret;
 
        dev = ip_dev_find(dst_ip);
index 082f03c158f006825bba87446b442fc0f726eb60..493f4c65c7a2b5acaa5ca753a08bf772772d70a2 100644 (file)
@@ -2987,10 +2987,7 @@ error1:
 static void __exit ib_mad_cleanup_module(void)
 {
        ib_unregister_client(&mad_client);
-
-       if (kmem_cache_destroy(ib_mad_cache)) {
-               printk(KERN_DEBUG PFX "Failed to destroy ib_mad cache\n");
-       }
+       kmem_cache_destroy(ib_mad_cache);
 }
 
 module_init(ib_mad_init_module);
index 08f46c83a3a43c92d796a76557293bfa37074256..3aae4978e1cbc574eb4e816b2fdb74cc18c7dd55 100644 (file)
@@ -197,7 +197,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
                        "resource=%x, qp_state=%s\n",
                        __FUNCTION__,
                        to_event_str(event_id),
-                       be64_to_cpu(wr->ae.ae_generic.user_context),
+                       (unsigned long long) be64_to_cpu(wr->ae.ae_generic.user_context),
                        be32_to_cpu(wr->ae.ae_generic.resource_type),
                        be32_to_cpu(wr->ae.ae_generic.resource),
                        to_qp_state_str(be32_to_cpu(wr->ae.ae_generic.qp_state)));
index 1d2529992c0c954018faea5090ada7d1597d67ce..028a60bbfca9ce2db18fb7506a8c84649d4e20a6 100644 (file)
@@ -115,7 +115,7 @@ u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
                            ((unsigned long) &(head->shared_ptr[mqsp]) -
                             (unsigned long) head);
                pr_debug("%s addr %p dma_addr %llx\n", __FUNCTION__,
-                        &(head->shared_ptr[mqsp]), (u64)*dma_addr);
+                        &(head->shared_ptr[mqsp]), (unsigned long long) *dma_addr);
                return &(head->shared_ptr[mqsp]);
        }
        return NULL;
index 485254efdd1e57fc02af3ecb53ed618f56a8baf1..75b93e9b88100638a10c3d59b77e51a59ad420be 100644 (file)
@@ -302,7 +302,7 @@ int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
        vq_req = vq_req_alloc(c2dev);
        if (!vq_req) {
                err = -ENOMEM;
-               goto bail1;
+               goto bail0;
        }
        vq_req->qp = qp;
        vq_req->cm_id = cm_id;
@@ -311,7 +311,7 @@ int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
        wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL);
        if (!wr) {
                err = -ENOMEM;
-               goto bail2;
+               goto bail1;
        }
 
        /* Build the WR */
@@ -331,7 +331,7 @@ int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
        /* Validate private_data length */
        if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) {
                err = -EINVAL;
-               goto bail2;
+               goto bail1;
        }
 
        if (iw_param->private_data) {
@@ -348,19 +348,19 @@ int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
        err = vq_send_wr(c2dev, (union c2wr *) wr);
        if (err) {
                vq_req_put(c2dev, vq_req);
-               goto bail2;
+               goto bail1;
        }
 
        /* Wait for reply from adapter */
        err = vq_wait_for_reply(c2dev, vq_req);
        if (err)
-               goto bail2;
+               goto bail1;
 
        /* Check that reply is present */
        reply = (struct c2wr_cr_accept_rep *) (unsigned long) vq_req->reply_msg;
        if (!reply) {
                err = -ENOMEM;
-               goto bail2;
+               goto bail1;
        }
 
        err = c2_errno(reply);
@@ -368,9 +368,8 @@ int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
 
        if (!err)
                c2_set_qp_state(qp, C2_QP_STATE_RTS);
- bail2:
-       kfree(wr);
  bail1:
+       kfree(wr);
        vq_req_free(c2dev, vq_req);
  bail0:
        if (err) {
index dd6af551108bc111a87c4bb0cbd8ebd449007a6e..da98d9f714295062d7e46c5ccd9e03b6e9a93bb2 100644 (file)
@@ -390,14 +390,18 @@ static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd,
        }
 
        mr = kmalloc(sizeof(*mr), GFP_KERNEL);
-       if (!mr)
+       if (!mr) {
+               vfree(page_list);
                return ERR_PTR(-ENOMEM);
+       }
 
        mr->pd = to_c2pd(ib_pd);
        pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, "
                "*iova_start %llx, first pa %llx, last pa %llx\n",
                __FUNCTION__, page_shift, pbl_depth, total_len,
-               *iova_start, page_list[0], page_list[pbl_depth-1]);
+               (unsigned long long) *iova_start,
+               (unsigned long long) page_list[0],
+               (unsigned long long) page_list[pbl_depth-1]);
        err = c2_nsmr_register_phys_kern(to_c2dev(ib_pd->device), page_list,
                                         (1 << page_shift), pbl_depth,
                                         total_len, 0, iova_start,
index f49a32b7a8f6472545a2594f5c888232142f6d63..e37c5688c2146c969a609cc9a913d01319b86700 100644 (file)
@@ -527,7 +527,7 @@ int c2_rnic_init(struct c2_dev *c2dev)
                                                DMA_FROM_DEVICE);
        pci_unmap_addr_set(&c2dev->rep_vq, mapping, c2dev->rep_vq.host_dma);
        pr_debug("%s rep_vq va %p dma %llx\n", __FUNCTION__, q1_pages,
-                (u64)c2dev->rep_vq.host_dma);
+                (unsigned long long) c2dev->rep_vq.host_dma);
        c2_mq_rep_init(&c2dev->rep_vq,
                   1,
                   qsize,
@@ -550,7 +550,7 @@ int c2_rnic_init(struct c2_dev *c2dev)
                                                DMA_FROM_DEVICE);
        pci_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma);
        pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q1_pages,
-                (u64)c2dev->rep_vq.host_dma);
+                (unsigned long long) c2dev->rep_vq.host_dma);
        c2_mq_rep_init(&c2dev->aeq,
                       2,
                       qsize,
index f577905e3acaafc3d624c04a00dca92b6f08be35..54139d3981812a2ffdc78166d2dcf7722ea29b91 100644 (file)
@@ -141,8 +141,9 @@ struct infinipath_stats {
         * packets if ipath not configured, etc.)
         */
        __u64 sps_krdrops;
+       __u64 sps_txeparity; /* PIO buffer parity error, recovered */
        /* pad for future growth */
-       __u64 __sps_pad[46];
+       __u64 __sps_pad[45];
 };
 
 /*
@@ -185,6 +186,9 @@ typedef enum _ipath_ureg {
 #define IPATH_RUNTIME_PCIE     0x2
 #define IPATH_RUNTIME_FORCE_WC_ORDER   0x4
 #define IPATH_RUNTIME_RCVHDR_COPY      0x8
+#define IPATH_RUNTIME_MASTER   0x10
+#define IPATH_RUNTIME_PBC_REWRITE 0x20
+#define IPATH_RUNTIME_LOOSE_DMA_ALIGN 0x40
 
 /*
  * This structure is returned by ipath_userinit() immediately after
@@ -202,7 +206,8 @@ struct ipath_base_info {
        /* version of software, for feature checking. */
        __u32 spi_sw_version;
        /* InfiniPath port assigned, goes into sent packets */
-       __u32 spi_port;
+       __u16 spi_port;
+       __u16 spi_subport;
        /*
         * IB MTU, packets IB data must be less than this.
         * The MTU is in bytes, and will be a multiple of 4 bytes.
@@ -218,7 +223,7 @@ struct ipath_base_info {
        __u32 spi_tidcnt;
        /* size of the TID Eager list in infinipath, in entries */
        __u32 spi_tidegrcnt;
-       /* size of a single receive header queue entry. */
+       /* size of a single receive header queue entry in words. */
        __u32 spi_rcvhdrent_size;
        /*
         * Count of receive header queue entries allocated.
@@ -310,6 +315,12 @@ struct ipath_base_info {
        __u32 spi_filler_for_align;
        /* address of readonly memory copy of the rcvhdrq tail register. */
        __u64 spi_rcvhdr_tailaddr;
+
+       /* shared memory pages for subports if IPATH_RUNTIME_MASTER is set */
+       __u64 spi_subport_uregbase;
+       __u64 spi_subport_rcvegrbuf;
+       __u64 spi_subport_rcvhdr_base;
+
 } __attribute__ ((aligned(8)));
 
 
@@ -328,12 +339,12 @@ struct ipath_base_info {
 
 /*
  * Minor version differences are always compatible
- * a within a major version, however if if user software is larger
+ * a within a major version, however if user software is larger
  * than driver software, some new features and/or structure fields
  * may not be implemented; the user code must deal with this if it
- * cares, or it must abort after initialization reports the difference
+ * cares, or it must abort after initialization reports the difference.
  */
-#define IPATH_USER_SWMINOR 2
+#define IPATH_USER_SWMINOR 3
 
 #define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
 
@@ -379,7 +390,16 @@ struct ipath_user_info {
         */
        __u32 spu_rcvhdrsize;
 
-       __u64 spu_unused; /* kept for compatible layout */
+       /*
+        * If two or more processes wish to share a port, each process
+        * must set the spu_subport_cnt and spu_subport_id to the same
+        * values.  The only restriction on the spu_subport_id is that
+        * it be unique for a given node.
+        */
+       __u16 spu_subport_cnt;
+       __u16 spu_subport_id;
+
+       __u32 spu_unused; /* kept for compatible layout */
 
        /*
         * address of struct base_info to write to
@@ -392,19 +412,25 @@ struct ipath_user_info {
 
 #define IPATH_CMD_MIN          16
 
-#define IPATH_CMD_USER_INIT    16      /* set up userspace */
+#define __IPATH_CMD_USER_INIT  16      /* old set up userspace (for old user code) */
 #define IPATH_CMD_PORT_INFO    17      /* find out what resources we got */
 #define IPATH_CMD_RECV_CTRL    18      /* control receipt of packets */
 #define IPATH_CMD_TID_UPDATE   19      /* update expected TID entries */
 #define IPATH_CMD_TID_FREE     20      /* free expected TID entries */
 #define IPATH_CMD_SET_PART_KEY 21      /* add partition key */
+#define IPATH_CMD_SLAVE_INFO   22      /* return info on slave processes */
+#define IPATH_CMD_ASSIGN_PORT  23      /* allocate HCA and port */
+#define IPATH_CMD_USER_INIT    24      /* set up userspace */
 
-#define IPATH_CMD_MAX          21
+#define IPATH_CMD_MAX          24
 
 struct ipath_port_info {
        __u32 num_active;       /* number of active units */
        __u32 unit;             /* unit (chip) assigned to caller */
-       __u32 port;             /* port on unit assigned to caller */
+       __u16 port;             /* port on unit assigned to caller */
+       __u16 subport;          /* subport on unit assigned to caller */
+       __u16 num_ports;        /* number of ports available on unit */
+       __u16 num_subports;     /* number of subport slaves opened on port */
 };
 
 struct ipath_tid_info {
@@ -435,6 +461,8 @@ struct ipath_cmd {
                __u32 recv_ctrl;
                /* partition key to set */
                __u16 part_key;
+               /* user address of __u32 bitmask of active slaves */
+               __u64 slave_mask_addr;
        } cmd;
 };
 
@@ -596,6 +624,10 @@ struct infinipath_counters {
 
 /* K_PktFlags bits */
 #define INFINIPATH_KPF_INTR 0x1
+#define INFINIPATH_KPF_SUBPORT_MASK 0x3
+#define INFINIPATH_KPF_SUBPORT_SHIFT 1
+
+#define INFINIPATH_MAX_SUBPORT 4
 
 /* SendPIO per-buffer control */
 #define INFINIPATH_SP_TEST    0x40
@@ -610,7 +642,7 @@ struct ipath_header {
        /*
         * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset -
         * 14 bits before ECO change ~28 Dec 03.  After that, Vers 4,
-        * Port 3, TID 11, offset 14.
+        * Port 4, TID 11, offset 13.
         */
        __le32 ver_port_tid_offset;
        __le16 chksum;
index 049221bc590e0eda2c2c743eca6da06af88a0259..87462e0cb4d2f5e95bf41f12b9ec9910429eb24e 100644 (file)
@@ -46,7 +46,7 @@
  */
 void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
 {
-       struct ipath_cq_wc *wc = cq->queue;
+       struct ipath_cq_wc *wc;
        unsigned long flags;
        u32 head;
        u32 next;
@@ -57,6 +57,7 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
         * Note that the head pointer might be writable by user processes.
         * Take care to verify it is a sane value.
         */
+       wc = cq->queue;
        head = wc->head;
        if (head >= (unsigned) cq->ibcq.cqe) {
                head = cq->ibcq.cqe;
@@ -109,21 +110,27 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
 int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
 {
        struct ipath_cq *cq = to_icq(ibcq);
-       struct ipath_cq_wc *wc = cq->queue;
+       struct ipath_cq_wc *wc;
        unsigned long flags;
        int npolled;
+       u32 tail;
 
        spin_lock_irqsave(&cq->lock, flags);
 
+       wc = cq->queue;
+       tail = wc->tail;
+       if (tail > (u32) cq->ibcq.cqe)
+               tail = (u32) cq->ibcq.cqe;
        for (npolled = 0; npolled < num_entries; ++npolled, ++entry) {
-               if (wc->tail == wc->head)
+               if (tail == wc->head)
                        break;
-               *entry = wc->queue[wc->tail];
-               if (wc->tail >= cq->ibcq.cqe)
-                       wc->tail = 0;
+               *entry = wc->queue[tail];
+               if (tail >= cq->ibcq.cqe)
+                       tail = 0;
                else
-                       wc->tail++;
+                       tail++;
        }
+       wc->tail = tail;
 
        spin_unlock_irqrestore(&cq->lock, flags);
 
@@ -177,11 +184,6 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
                goto done;
        }
 
-       if (dev->n_cqs_allocated == ib_ipath_max_cqs) {
-               ret = ERR_PTR(-ENOMEM);
-               goto done;
-       }
-
        /* Allocate the completion queue structure. */
        cq = kmalloc(sizeof(*cq), GFP_KERNEL);
        if (!cq) {
@@ -237,6 +239,16 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
        } else
                cq->ip = NULL;
 
+       spin_lock(&dev->n_cqs_lock);
+       if (dev->n_cqs_allocated == ib_ipath_max_cqs) {
+               spin_unlock(&dev->n_cqs_lock);
+               ret = ERR_PTR(-ENOMEM);
+               goto bail_wc;
+       }
+
+       dev->n_cqs_allocated++;
+       spin_unlock(&dev->n_cqs_lock);
+
        /*
         * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe.
         * The number of entries should be >= the number requested or return
@@ -253,7 +265,6 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
 
        ret = &cq->ibcq;
 
-       dev->n_cqs_allocated++;
        goto done;
 
 bail_wc:
@@ -280,7 +291,9 @@ int ipath_destroy_cq(struct ib_cq *ibcq)
        struct ipath_cq *cq = to_icq(ibcq);
 
        tasklet_kill(&cq->comptask);
+       spin_lock(&dev->n_cqs_lock);
        dev->n_cqs_allocated--;
+       spin_unlock(&dev->n_cqs_lock);
        if (cq->ip)
                kref_put(&cq->ip->ref, ipath_release_mmap_info);
        else
@@ -316,10 +329,16 @@ int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
        return 0;
 }
 
+/**
+ * ipath_resize_cq - change the size of the CQ
+ * @ibcq: the completion queue
+ *
+ * Returns 0 for success.
+ */
 int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
 {
        struct ipath_cq *cq = to_icq(ibcq);
-       struct ipath_cq_wc *old_wc = cq->queue;
+       struct ipath_cq_wc *old_wc;
        struct ipath_cq_wc *wc;
        u32 head, tail, n;
        int ret;
@@ -355,6 +374,7 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
         * Make sure head and tail are sane since they
         * might be user writable.
         */
+       old_wc = cq->queue;
        head = old_wc->head;
        if (head > (u32) cq->ibcq.cqe)
                head = (u32) cq->ibcq.cqe;
index 2108466c7e337169649c4a64e0f9157995a9aca7..12cefa658f3ba888f808c79b902f9fb018fb380c 100644 (file)
@@ -95,16 +95,6 @@ const char *ipath_ibcstatus_str[] = {
        "RecovIdle",
 };
 
-/*
- * These variables are initialized in the chip-specific files
- * but are defined here.
- */
-u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
-u64 ipath_gpio_sda, ipath_gpio_scl;
-u64 infinipath_i_bitsextant;
-ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
-u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
-
 static void __devexit ipath_remove_one(struct pci_dev *);
 static int __devinit ipath_init_one(struct pci_dev *,
                                    const struct pci_device_id *);
@@ -527,28 +517,146 @@ bail:
        return ret;
 }
 
+static void __devexit cleanup_device(struct ipath_devdata *dd)
+{
+       int port;
+
+       ipath_shutdown_device(dd);
+
+       if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) {
+               /* can't do anything more with chip; needs re-init */
+               *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT;
+               if (dd->ipath_kregbase) {
+                       /*
+                        * if we haven't already cleaned up before these are
+                        * to ensure any register reads/writes "fail" until
+                        * re-init
+                        */
+                       dd->ipath_kregbase = NULL;
+                       dd->ipath_uregbase = 0;
+                       dd->ipath_sregbase = 0;
+                       dd->ipath_cregbase = 0;
+                       dd->ipath_kregsize = 0;
+               }
+               ipath_disable_wc(dd);
+       }
+
+       if (dd->ipath_pioavailregs_dma) {
+               dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
+                                 (void *) dd->ipath_pioavailregs_dma,
+                                 dd->ipath_pioavailregs_phys);
+               dd->ipath_pioavailregs_dma = NULL;
+       }
+       if (dd->ipath_dummy_hdrq) {
+               dma_free_coherent(&dd->pcidev->dev,
+                       dd->ipath_pd[0]->port_rcvhdrq_size,
+                       dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys);
+               dd->ipath_dummy_hdrq = NULL;
+       }
+
+       if (dd->ipath_pageshadow) {
+               struct page **tmpp = dd->ipath_pageshadow;
+               dma_addr_t *tmpd = dd->ipath_physshadow;
+               int i, cnt = 0;
+
+               ipath_cdbg(VERBOSE, "Unlocking any expTID pages still "
+                          "locked\n");
+               for (port = 0; port < dd->ipath_cfgports; port++) {
+                       int port_tidbase = port * dd->ipath_rcvtidcnt;
+                       int maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+                       for (i = port_tidbase; i < maxtid; i++) {
+                               if (!tmpp[i])
+                                       continue;
+                               pci_unmap_page(dd->pcidev, tmpd[i],
+                                       PAGE_SIZE, PCI_DMA_FROMDEVICE);
+                               ipath_release_user_pages(&tmpp[i], 1);
+                               tmpp[i] = NULL;
+                               cnt++;
+                       }
+               }
+               if (cnt) {
+                       ipath_stats.sps_pageunlocks += cnt;
+                       ipath_cdbg(VERBOSE, "There were still %u expTID "
+                                  "entries locked\n", cnt);
+               }
+               if (ipath_stats.sps_pagelocks ||
+                   ipath_stats.sps_pageunlocks)
+                       ipath_cdbg(VERBOSE, "%llu pages locked, %llu "
+                                  "unlocked via ipath_m{un}lock\n",
+                                  (unsigned long long)
+                                  ipath_stats.sps_pagelocks,
+                                  (unsigned long long)
+                                  ipath_stats.sps_pageunlocks);
+
+               ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n",
+                          dd->ipath_pageshadow);
+               vfree(dd->ipath_pageshadow);
+               dd->ipath_pageshadow = NULL;
+       }
+
+       /*
+        * free any resources still in use (usually just kernel ports)
+        * at unload; we do for portcnt, not cfgports, because cfgports
+        * could have changed while we were loaded.
+        */
+       for (port = 0; port < dd->ipath_portcnt; port++) {
+               struct ipath_portdata *pd = dd->ipath_pd[port];
+               dd->ipath_pd[port] = NULL;
+               ipath_free_pddata(dd, pd);
+       }
+       kfree(dd->ipath_pd);
+       /*
+        * debuggability, in case some cleanup path tries to use it
+        * after this
+        */
+       dd->ipath_pd = NULL;
+}
+
 static void __devexit ipath_remove_one(struct pci_dev *pdev)
 {
-       struct ipath_devdata *dd;
+       struct ipath_devdata *dd = pci_get_drvdata(pdev);
 
-       ipath_cdbg(VERBOSE, "removing, pdev=%p\n", pdev);
-       if (!pdev)
-               return;
+       ipath_cdbg(VERBOSE, "removing, pdev=%p, dd=%p\n", pdev, dd);
+
+       if (dd->verbs_dev)
+               ipath_unregister_ib_device(dd->verbs_dev);
 
-       dd = pci_get_drvdata(pdev);
-       ipath_unregister_ib_device(dd->verbs_dev);
        ipath_diag_remove(dd);
        ipath_user_remove(dd);
        ipathfs_remove_device(dd);
        ipath_device_remove_group(&pdev->dev, dd);
+
        ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, "
                   "unit %u\n", dd, (u32) dd->ipath_unit);
-       if (dd->ipath_kregbase) {
-               ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n",
-                          dd->ipath_kregbase);
-               iounmap((volatile void __iomem *) dd->ipath_kregbase);
-               dd->ipath_kregbase = NULL;
-       }
+
+       cleanup_device(dd);
+
+       /*
+        * turn off rcv, send, and interrupts for all ports, all drivers
+        * should also hard reset the chip here?
+        * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs
+        * for all versions of the driver, if they were allocated
+        */
+       if (pdev->irq) {
+               ipath_cdbg(VERBOSE,
+                          "unit %u free_irq of irq %x\n",
+                          dd->ipath_unit, pdev->irq);
+               free_irq(pdev->irq, dd);
+       } else
+               ipath_dbg("irq is 0, not doing free_irq "
+                         "for unit %u\n", dd->ipath_unit);
+       /*
+        * we check for NULL here, because it's outside
+        * the kregbase check, and we need to call it
+        * after the free_irq.  Thus it's possible that
+        * the function pointers were never initialized.
+        */
+       if (dd->ipath_f_cleanup)
+               /* clean up chip-specific stuff */
+               dd->ipath_f_cleanup(dd);
+
+       ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n", dd->ipath_kregbase);
+       iounmap((volatile void __iomem *) dd->ipath_kregbase);
        pci_release_regions(pdev);
        ipath_cdbg(VERBOSE, "calling pci_disable_device\n");
        pci_disable_device(pdev);
@@ -760,8 +868,8 @@ static void get_rhf_errstring(u32 err, char *msg, size_t len)
 static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
                                     int err)
 {
-       return dd->ipath_port0_skbs ?
-               (void *)dd->ipath_port0_skbs[bufnum]->data : NULL;
+       return dd->ipath_port0_skbinfo ?
+               (void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL;
 }
 
 /**
@@ -783,31 +891,34 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd,
         */
 
        /*
-        * We need 4 extra bytes for unaligned transfer copying
+        * We need 2 extra bytes for ipath_ether data sent in the
+        * key header.  In order to keep everything dword aligned,
+        * we'll reserve 4 bytes.
         */
+       len = dd->ipath_ibmaxlen + 4;
+
        if (dd->ipath_flags & IPATH_4BYTE_TID) {
-               /* we need a 4KB multiple alignment, and there is no way
+               /* We need a 2KB multiple alignment, and there is no way
                 * to do it except to allocate extra and then skb_reserve
                 * enough to bring it up to the right alignment.
                 */
-               len = dd->ipath_ibmaxlen + 4 + (1 << 11) - 1;
+               len += 2047;
        }
-       else
-               len = dd->ipath_ibmaxlen + 4;
+
        skb = __dev_alloc_skb(len, gfp_mask);
        if (!skb) {
                ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n",
                              len);
                goto bail;
        }
+
+       skb_reserve(skb, 4);
+
        if (dd->ipath_flags & IPATH_4BYTE_TID) {
-               u32 una = ((1 << 11) - 1) & (unsigned long)(skb->data + 4);
+               u32 una = (unsigned long)skb->data & 2047;
                if (una)
-                       skb_reserve(skb, 4 + (1 << 11) - una);
-               else
-                       skb_reserve(skb, 4);
-       } else
-               skb_reserve(skb, 4);
+                       skb_reserve(skb, 2048 - una);
+       }
 
 bail:
        return skb;
@@ -1326,6 +1437,9 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
                                      "for port %u rcvhdrqtailaddr failed\n",
                                      pd->port_port);
                        ret = -ENOMEM;
+                       dma_free_coherent(&dd->pcidev->dev, amt,
+                                         pd->port_rcvhdrq, pd->port_rcvhdrq_phys);
+                       pd->port_rcvhdrq = NULL;
                        goto bail;
                }
                pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail;
@@ -1347,12 +1461,13 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
                ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; "
                           "hdrtailaddr@%p %llx physical\n",
                           pd->port_port, pd->port_rcvhdrq,
-                          pd->port_rcvhdrq_phys, pd->port_rcvhdrtail_kvaddr,
-                          (unsigned long long)pd->port_rcvhdrqtailaddr_phys);
+                          (unsigned long long) pd->port_rcvhdrq_phys,
+                          pd->port_rcvhdrtail_kvaddr, (unsigned long long)
+                          pd->port_rcvhdrqtailaddr_phys);
 
        /* clear for security and sanity on each use */
        memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size);
-       memset((void *)pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
+       memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
 
        /*
         * tell chip each time we init it, even if we are re-using previous
@@ -1805,7 +1920,7 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
                pd->port_rcvhdrq = NULL;
                if (pd->port_rcvhdrtail_kvaddr) {
                        dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
-                                        (void *)pd->port_rcvhdrtail_kvaddr,
+                                        pd->port_rcvhdrtail_kvaddr,
                                         pd->port_rcvhdrqtailaddr_phys);
                        pd->port_rcvhdrtail_kvaddr = NULL;
                }
@@ -1824,24 +1939,32 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
                        dma_free_coherent(&dd->pcidev->dev, size,
                                base, pd->port_rcvegrbuf_phys[e]);
                }
-               vfree(pd->port_rcvegrbuf);
+               kfree(pd->port_rcvegrbuf);
                pd->port_rcvegrbuf = NULL;
-               vfree(pd->port_rcvegrbuf_phys);
+               kfree(pd->port_rcvegrbuf_phys);
                pd->port_rcvegrbuf_phys = NULL;
                pd->port_rcvegrbuf_chunks = 0;
-       } else if (pd->port_port == 0 && dd->ipath_port0_skbs) {
+       } else if (pd->port_port == 0 && dd->ipath_port0_skbinfo) {
                unsigned e;
-               struct sk_buff **skbs = dd->ipath_port0_skbs;
+               struct ipath_skbinfo *skbinfo = dd->ipath_port0_skbinfo;
 
-               dd->ipath_port0_skbs = NULL;
-               ipath_cdbg(VERBOSE, "free closed port %d ipath_port0_skbs "
-                          "@ %p\n", pd->port_port, skbs);
+               dd->ipath_port0_skbinfo = NULL;
+               ipath_cdbg(VERBOSE, "free closed port %d "
+                          "ipath_port0_skbinfo @ %p\n", pd->port_port,
+                          skbinfo);
                for (e = 0; e < dd->ipath_rcvegrcnt; e++)
-                       if (skbs[e])
-                               dev_kfree_skb(skbs[e]);
-               vfree(skbs);
+               if (skbinfo[e].skb) {
+                       pci_unmap_single(dd->pcidev, skbinfo[e].phys,
+                                        dd->ipath_ibmaxlen,
+                                        PCI_DMA_FROMDEVICE);
+                       dev_kfree_skb(skbinfo[e].skb);
+               }
+               vfree(skbinfo);
        }
        kfree(pd->port_tid_pg_list);
+       vfree(pd->subport_uregbase);
+       vfree(pd->subport_rcvegrbuf);
+       vfree(pd->subport_rcvhdr_base);
        kfree(pd);
 }
 
@@ -1907,150 +2030,12 @@ bail:
        return ret;
 }
 
-static void cleanup_device(struct ipath_devdata *dd)
-{
-       int port;
-
-       ipath_shutdown_device(dd);
-
-       if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) {
-               /* can't do anything more with chip; needs re-init */
-               *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT;
-               if (dd->ipath_kregbase) {
-                       /*
-                        * if we haven't already cleaned up before these are
-                        * to ensure any register reads/writes "fail" until
-                        * re-init
-                        */
-                       dd->ipath_kregbase = NULL;
-                       dd->ipath_uregbase = 0;
-                       dd->ipath_sregbase = 0;
-                       dd->ipath_cregbase = 0;
-                       dd->ipath_kregsize = 0;
-               }
-               ipath_disable_wc(dd);
-       }
-
-       if (dd->ipath_pioavailregs_dma) {
-               dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
-                                 (void *) dd->ipath_pioavailregs_dma,
-                                 dd->ipath_pioavailregs_phys);
-               dd->ipath_pioavailregs_dma = NULL;
-       }
-       if (dd->ipath_dummy_hdrq) {
-               dma_free_coherent(&dd->pcidev->dev,
-                       dd->ipath_pd[0]->port_rcvhdrq_size,
-                       dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys);
-               dd->ipath_dummy_hdrq = NULL;
-       }
-
-       if (dd->ipath_pageshadow) {
-               struct page **tmpp = dd->ipath_pageshadow;
-               int i, cnt = 0;
-
-               ipath_cdbg(VERBOSE, "Unlocking any expTID pages still "
-                          "locked\n");
-               for (port = 0; port < dd->ipath_cfgports; port++) {
-                       int port_tidbase = port * dd->ipath_rcvtidcnt;
-                       int maxtid = port_tidbase + dd->ipath_rcvtidcnt;
-                       for (i = port_tidbase; i < maxtid; i++) {
-                               if (!tmpp[i])
-                                       continue;
-                               ipath_release_user_pages(&tmpp[i], 1);
-                               tmpp[i] = NULL;
-                               cnt++;
-                       }
-               }
-               if (cnt) {
-                       ipath_stats.sps_pageunlocks += cnt;
-                       ipath_cdbg(VERBOSE, "There were still %u expTID "
-                                  "entries locked\n", cnt);
-               }
-               if (ipath_stats.sps_pagelocks ||
-                   ipath_stats.sps_pageunlocks)
-                       ipath_cdbg(VERBOSE, "%llu pages locked, %llu "
-                                  "unlocked via ipath_m{un}lock\n",
-                                  (unsigned long long)
-                                  ipath_stats.sps_pagelocks,
-                                  (unsigned long long)
-                                  ipath_stats.sps_pageunlocks);
-
-               ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n",
-                          dd->ipath_pageshadow);
-               vfree(dd->ipath_pageshadow);
-               dd->ipath_pageshadow = NULL;
-       }
-
-       /*
-        * free any resources still in use (usually just kernel ports)
-        * at unload; we do for portcnt, not cfgports, because cfgports
-        * could have changed while we were loaded.
-        */
-       for (port = 0; port < dd->ipath_portcnt; port++) {
-               struct ipath_portdata *pd = dd->ipath_pd[port];
-               dd->ipath_pd[port] = NULL;
-               ipath_free_pddata(dd, pd);
-       }
-       kfree(dd->ipath_pd);
-       /*
-        * debuggability, in case some cleanup path tries to use it
-        * after this
-        */
-       dd->ipath_pd = NULL;
-}
-
 static void __exit infinipath_cleanup(void)
 {
-       struct ipath_devdata *dd, *tmp;
-       unsigned long flags;
-
-       ipath_diagpkt_remove();
-
        ipath_exit_ipathfs();
 
        ipath_driver_remove_group(&ipath_driver.driver);
 
-       spin_lock_irqsave(&ipath_devs_lock, flags);
-
-       /*
-        * turn off rcv, send, and interrupts for all ports, all drivers
-        * should also hard reset the chip here?
-        * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs
-        * for all versions of the driver, if they were allocated
-        */
-       list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
-               spin_unlock_irqrestore(&ipath_devs_lock, flags);
-
-               if (dd->ipath_kregbase)
-                       cleanup_device(dd);
-
-               if (dd->pcidev) {
-                       if (dd->pcidev->irq) {
-                               ipath_cdbg(VERBOSE,
-                                          "unit %u free_irq of irq %x\n",
-                                          dd->ipath_unit, dd->pcidev->irq);
-                               free_irq(dd->pcidev->irq, dd);
-                       } else
-                               ipath_dbg("irq is 0, not doing free_irq "
-                                         "for unit %u\n", dd->ipath_unit);
-
-                       /*
-                        * we check for NULL here, because it's outside
-                        * the kregbase check, and we need to call it
-                        * after the free_irq.  Thus it's possible that
-                        * the function pointers were never initialized.
-                        */
-                       if (dd->ipath_f_cleanup)
-                               /* clean up chip-specific stuff */
-                               dd->ipath_f_cleanup(dd);
-
-                       dd->pcidev = NULL;
-               }
-               spin_lock_irqsave(&ipath_devs_lock, flags);
-       }
-
-       spin_unlock_irqrestore(&ipath_devs_lock, flags);
-
        ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
        pci_unregister_driver(&ipath_driver);
 
index 3313356ab93aa13d1c6b3fe4bb60d543f21402fc..a4019a6b75602c760ef5774ed2216cd33b9d6576 100644 (file)
@@ -100,9 +100,9 @@ static int i2c_gpio_set(struct ipath_devdata *dd,
        gpioval = &dd->ipath_gpio_out;
        read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
        if (line == i2c_line_scl)
-               mask = ipath_gpio_scl;
+               mask = dd->ipath_gpio_scl;
        else
-               mask = ipath_gpio_sda;
+               mask = dd->ipath_gpio_sda;
 
        if (new_line_state == i2c_line_high)
                /* tri-state the output rather than force high */
@@ -119,12 +119,12 @@ static int i2c_gpio_set(struct ipath_devdata *dd,
                write_val = 0x0UL;
 
        if (line == i2c_line_scl) {
-               write_val <<= ipath_gpio_scl_num;
-               *gpioval = *gpioval & ~(1UL << ipath_gpio_scl_num);
+               write_val <<= dd->ipath_gpio_scl_num;
+               *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_scl_num);
                *gpioval |= write_val;
        } else {
-               write_val <<= ipath_gpio_sda_num;
-               *gpioval = *gpioval & ~(1UL << ipath_gpio_sda_num);
+               write_val <<= dd->ipath_gpio_sda_num;
+               *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_sda_num);
                *gpioval |= write_val;
        }
        ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
@@ -157,9 +157,9 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
        read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
        /* config line to be an input */
        if (line == i2c_line_scl)
-               mask = ipath_gpio_scl;
+               mask = dd->ipath_gpio_scl;
        else
-               mask = ipath_gpio_sda;
+               mask = dd->ipath_gpio_sda;
        write_val = read_val & ~mask;
        ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
        read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
@@ -187,6 +187,7 @@ bail:
 static void i2c_wait_for_writes(struct ipath_devdata *dd)
 {
        (void)ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
+       rmb();
 }
 
 static void scl_out(struct ipath_devdata *dd, u8 bit)
index 29930e22318e5a09f78349fe4c8d9e052db9aa62..a9ddc6911f66f89478740c9b994f66038236c692 100644 (file)
 #include "ipath_kernel.h"
 #include "ipath_common.h"
 
+/*
+ * mmap64 doesn't allow all 64 bits for 32-bit applications
+ * so only use the low 43 bits.
+ */
+#define MMAP64_MASK    0x7FFFFFFFFFFUL
+
 static int ipath_open(struct inode *, struct file *);
 static int ipath_close(struct inode *, struct file *);
 static ssize_t ipath_write(struct file *, const char __user *, size_t,
@@ -57,18 +63,35 @@ static struct file_operations ipath_file_ops = {
        .mmap = ipath_mmap
 };
 
-static int ipath_get_base_info(struct ipath_portdata *pd,
+static int ipath_get_base_info(struct file *fp,
                               void __user *ubase, size_t ubase_size)
 {
+       struct ipath_portdata *pd = port_fp(fp);
        int ret = 0;
        struct ipath_base_info *kinfo = NULL;
        struct ipath_devdata *dd = pd->port_dd;
+       unsigned subport_cnt;
+       int shared, master;
+       size_t sz;
+
+       subport_cnt = pd->port_subport_cnt;
+       if (!subport_cnt) {
+               shared = 0;
+               master = 0;
+               subport_cnt = 1;
+       } else {
+               shared = 1;
+               master = !subport_fp(fp);
+       }
 
-       if (ubase_size < sizeof(*kinfo)) {
+       sz = sizeof(*kinfo);
+       /* If port sharing is not requested, allow the old size structure */
+       if (!shared)
+               sz -= 3 * sizeof(u64);
+       if (ubase_size < sz) {
                ipath_cdbg(PROC,
-                          "Base size %lu, need %lu (version mismatch?)\n",
-                          (unsigned long) ubase_size,
-                          (unsigned long) sizeof(*kinfo));
+                          "Base size %zu, need %zu (version mismatch?)\n",
+                          ubase_size, sz);
                ret = -EINVAL;
                goto bail;
        }
@@ -95,7 +118,9 @@ static int ipath_get_base_info(struct ipath_portdata *pd,
        kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk;
        kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen /
                pd->port_rcvegrbuf_chunks;
-       kinfo->spi_tidcnt = dd->ipath_rcvtidcnt;
+       kinfo->spi_tidcnt = dd->ipath_rcvtidcnt / subport_cnt;
+       if (master)
+               kinfo->spi_tidcnt += dd->ipath_rcvtidcnt % subport_cnt;
        /*
         * for this use, may be ipath_cfgports summed over all chips that
         * are are configured and present
@@ -118,31 +143,75 @@ static int ipath_get_base_info(struct ipath_portdata *pd,
         * page_address() macro worked, but in 2.6.11, even that returns the
         * full 64 bit address (upper bits all 1's).  So far, using the
         * physical addresses (or chip offsets, for chip mapping) works, but
-        * no doubt some future kernel release will chang that, and we'll be
-        * on to yet another method of dealing with this
+        * no doubt some future kernel release will change that, and we'll be
+        * on to yet another method of dealing with this.
         */
        kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys;
-       kinfo->spi_rcvhdr_tailaddr = (u64)pd->port_rcvhdrqtailaddr_phys;
+       kinfo->spi_rcvhdr_tailaddr = (u64) pd->port_rcvhdrqtailaddr_phys;
        kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys;
        kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys;
        kinfo->spi_status = (u64) kinfo->spi_pioavailaddr +
                (void *) dd->ipath_statusp -
                (void *) dd->ipath_pioavailregs_dma;
-       kinfo->spi_piobufbase = (u64) pd->port_piobufs;
-       kinfo->__spi_uregbase =
-               dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+       if (!shared) {
+               kinfo->spi_piocnt = dd->ipath_pbufsport;
+               kinfo->spi_piobufbase = (u64) pd->port_piobufs;
+               kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
+                       dd->ipath_palign * pd->port_port;
+       } else if (master) {
+               kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
+                                   (dd->ipath_pbufsport % subport_cnt);
+               /* Master's PIO buffers are after all the slave's */
+               kinfo->spi_piobufbase = (u64) pd->port_piobufs +
+                       dd->ipath_palign *
+                       (dd->ipath_pbufsport - kinfo->spi_piocnt);
+               kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
+                       dd->ipath_palign * pd->port_port;
+       } else {
+               unsigned slave = subport_fp(fp) - 1;
+
+               kinfo->spi_piocnt = dd->ipath_pbufsport / subport_cnt;
+               kinfo->spi_piobufbase = (u64) pd->port_piobufs +
+                       dd->ipath_palign * kinfo->spi_piocnt * slave;
+               kinfo->__spi_uregbase = ((u64) pd->subport_uregbase +
+                       PAGE_SIZE * slave) & MMAP64_MASK;
 
-       kinfo->spi_pioindex = dd->ipath_pbufsport * (pd->port_port - 1);
-       kinfo->spi_piocnt = dd->ipath_pbufsport;
+               kinfo->spi_rcvhdr_base = ((u64) pd->subport_rcvhdr_base +
+                       pd->port_rcvhdrq_size * slave) & MMAP64_MASK;
+               kinfo->spi_rcvhdr_tailaddr =
+                       (u64) pd->port_rcvhdrqtailaddr_phys & MMAP64_MASK;
+               kinfo->spi_rcv_egrbufs = ((u64) pd->subport_rcvegrbuf +
+                       dd->ipath_rcvegrcnt * dd->ipath_rcvegrbufsize * slave) &
+                       MMAP64_MASK;
+       }
+
+       kinfo->spi_pioindex = (kinfo->spi_piobufbase - dd->ipath_piobufbase) /
+               dd->ipath_palign;
        kinfo->spi_pioalign = dd->ipath_palign;
 
        kinfo->spi_qpair = IPATH_KD_QP;
        kinfo->spi_piosize = dd->ipath_ibmaxlen;
        kinfo->spi_mtu = dd->ipath_ibmaxlen;    /* maxlen, not ibmtu */
        kinfo->spi_port = pd->port_port;
+       kinfo->spi_subport = subport_fp(fp);
        kinfo->spi_sw_version = IPATH_KERN_SWVERSION;
        kinfo->spi_hw_version = dd->ipath_revision;
 
+       if (master) {
+               kinfo->spi_runtime_flags |= IPATH_RUNTIME_MASTER;
+               kinfo->spi_subport_uregbase =
+                       (u64) pd->subport_uregbase & MMAP64_MASK;
+               kinfo->spi_subport_rcvegrbuf =
+                       (u64) pd->subport_rcvegrbuf & MMAP64_MASK;
+               kinfo->spi_subport_rcvhdr_base =
+                       (u64) pd->subport_rcvhdr_base & MMAP64_MASK;
+               ipath_cdbg(PROC, "port %u flags %x %llx %llx %llx\n",
+                       kinfo->spi_port, kinfo->spi_runtime_flags,
+                       (unsigned long long) kinfo->spi_subport_uregbase,
+                       (unsigned long long) kinfo->spi_subport_rcvegrbuf,
+                       (unsigned long long) kinfo->spi_subport_rcvhdr_base);
+       }
+
        if (copy_to_user(ubase, kinfo, sizeof(*kinfo)))
                ret = -EFAULT;
 
@@ -154,6 +223,7 @@ bail:
 /**
  * ipath_tid_update - update a port TID
  * @pd: the port
+ * @fp: the ipath device file
  * @ti: the TID information
  *
  * The new implementation as of Oct 2004 is that the driver assigns
@@ -176,11 +246,11 @@ bail:
  * virtually contiguous pages, that should change to improve
  * performance.
  */
-static int ipath_tid_update(struct ipath_portdata *pd,
+static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
                            const struct ipath_tid_info *ti)
 {
        int ret = 0, ntids;
-       u32 tid, porttid, cnt, i, tidcnt;
+       u32 tid, porttid, cnt, i, tidcnt, tidoff;
        u16 *tidlist;
        struct ipath_devdata *dd = pd->port_dd;
        u64 physaddr;
@@ -188,6 +258,7 @@ static int ipath_tid_update(struct ipath_portdata *pd,
        u64 __iomem *tidbase;
        unsigned long tidmap[8];
        struct page **pagep = NULL;
+       unsigned subport = subport_fp(fp);
 
        if (!dd->ipath_pageshadow) {
                ret = -ENOMEM;
@@ -204,20 +275,34 @@ static int ipath_tid_update(struct ipath_portdata *pd,
                ret = -EFAULT;
                goto done;
        }
-       tidcnt = dd->ipath_rcvtidcnt;
-       if (cnt >= tidcnt) {
+       porttid = pd->port_port * dd->ipath_rcvtidcnt;
+       if (!pd->port_subport_cnt) {
+               tidcnt = dd->ipath_rcvtidcnt;
+               tid = pd->port_tidcursor;
+               tidoff = 0;
+       } else if (!subport) {
+               tidcnt = (dd->ipath_rcvtidcnt / pd->port_subport_cnt) +
+                        (dd->ipath_rcvtidcnt % pd->port_subport_cnt);
+               tidoff = dd->ipath_rcvtidcnt - tidcnt;
+               porttid += tidoff;
+               tid = tidcursor_fp(fp);
+       } else {
+               tidcnt = dd->ipath_rcvtidcnt / pd->port_subport_cnt;
+               tidoff = tidcnt * (subport - 1);
+               porttid += tidoff;
+               tid = tidcursor_fp(fp);
+       }
+       if (cnt > tidcnt) {
                /* make sure it all fits in port_tid_pg_list */
                dev_info(&dd->pcidev->dev, "Process tried to allocate %u "
                         "TIDs, only trying max (%u)\n", cnt, tidcnt);
                cnt = tidcnt;
        }
-       pagep = (struct page **)pd->port_tid_pg_list;
-       tidlist = (u16 *) (&pagep[cnt]);
+       pagep = &((struct page **) pd->port_tid_pg_list)[tidoff];
+       tidlist = &((u16 *) &pagep[dd->ipath_rcvtidcnt])[tidoff];
 
        memset(tidmap, 0, sizeof(tidmap));
-       tid = pd->port_tidcursor;
        /* before decrement; chip actual # */
-       porttid = pd->port_port * tidcnt;
        ntids = tidcnt;
        tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
                                   dd->ipath_rcvtidbase +
@@ -274,16 +359,19 @@ static int ipath_tid_update(struct ipath_portdata *pd,
                        ret = -ENOMEM;
                        break;
                }
-               tidlist[i] = tid;
+               tidlist[i] = tid + tidoff;
                ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, "
-                          "vaddr %lx\n", i, tid, vaddr);
+                          "vaddr %lx\n", i, tid + tidoff, vaddr);
                /* we "know" system pages and TID pages are same size */
                dd->ipath_pageshadow[porttid + tid] = pagep[i];
+               dd->ipath_physshadow[porttid + tid] = ipath_map_page(
+                       dd->pcidev, pagep[i], 0, PAGE_SIZE,
+                       PCI_DMA_FROMDEVICE);
                /*
                 * don't need atomic or it's overhead
                 */
                __set_bit(tid, tidmap);
-               physaddr = page_to_phys(pagep[i]);
+               physaddr = dd->ipath_physshadow[porttid + tid];
                ipath_stats.sps_pagelocks++;
                ipath_cdbg(VERBOSE,
                           "TID %u, vaddr %lx, physaddr %llx pgp %p\n",
@@ -317,6 +405,9 @@ static int ipath_tid_update(struct ipath_portdata *pd,
                                           tid);
                                dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
                                                    dd->ipath_tidinvalid);
+                               pci_unmap_page(dd->pcidev,
+                                       dd->ipath_physshadow[porttid + tid],
+                                       PAGE_SIZE, PCI_DMA_FROMDEVICE);
                                dd->ipath_pageshadow[porttid + tid] = NULL;
                                ipath_stats.sps_pageunlocks++;
                        }
@@ -341,7 +432,10 @@ static int ipath_tid_update(struct ipath_portdata *pd,
                }
                if (tid == tidcnt)
                        tid = 0;
-               pd->port_tidcursor = tid;
+               if (!pd->port_subport_cnt)
+                       pd->port_tidcursor = tid;
+               else
+                       tidcursor_fp(fp) = tid;
        }
 
 done:
@@ -354,6 +448,7 @@ done:
 /**
  * ipath_tid_free - free a port TID
  * @pd: the port
+ * @subport: the subport
  * @ti: the TID info
  *
  * right now we are unlocking one page at a time, but since
@@ -367,7 +462,7 @@ done:
  * they pass in to us.
  */
 
-static int ipath_tid_free(struct ipath_portdata *pd,
+static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport,
                          const struct ipath_tid_info *ti)
 {
        int ret = 0;
@@ -388,11 +483,20 @@ static int ipath_tid_free(struct ipath_portdata *pd,
        }
 
        porttid = pd->port_port * dd->ipath_rcvtidcnt;
+       if (!pd->port_subport_cnt)
+               tidcnt = dd->ipath_rcvtidcnt;
+       else if (!subport) {
+               tidcnt = (dd->ipath_rcvtidcnt / pd->port_subport_cnt) +
+                        (dd->ipath_rcvtidcnt % pd->port_subport_cnt);
+               porttid += dd->ipath_rcvtidcnt - tidcnt;
+       } else {
+               tidcnt = dd->ipath_rcvtidcnt / pd->port_subport_cnt;
+               porttid += tidcnt * (subport - 1);
+       }
        tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
                                   dd->ipath_rcvtidbase +
                                   porttid * sizeof(*tidbase));
 
-       tidcnt = dd->ipath_rcvtidcnt;
        limit = sizeof(tidmap) * BITS_PER_BYTE;
        if (limit > tidcnt)
                /* just in case size changes in future */
@@ -417,6 +521,9 @@ static int ipath_tid_free(struct ipath_portdata *pd,
                                   pd->port_pid, tid);
                        dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
                                            dd->ipath_tidinvalid);
+                       pci_unmap_page(dd->pcidev,
+                               dd->ipath_physshadow[porttid + tid],
+                               PAGE_SIZE, PCI_DMA_FROMDEVICE);
                        ipath_release_user_pages(
                                &dd->ipath_pageshadow[porttid + tid], 1);
                        dd->ipath_pageshadow[porttid + tid] = NULL;
@@ -581,20 +688,24 @@ bail:
 /**
  * ipath_manage_rcvq - manage a port's receive queue
  * @pd: the port
+ * @subport: the subport
  * @start_stop: action to carry out
  *
  * start_stop == 0 disables receive on the port, for use in queue
  * overflow conditions.  start_stop==1 re-enables, to be used to
  * re-init the software copy of the head register
  */
-static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop)
+static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
+                            int start_stop)
 {
        struct ipath_devdata *dd = pd->port_dd;
        u64 tval;
 
-       ipath_cdbg(PROC, "%sabling rcv for unit %u port %u\n",
+       ipath_cdbg(PROC, "%sabling rcv for unit %u port %u:%u\n",
                   start_stop ? "en" : "dis", dd->ipath_unit,
-                  pd->port_port);
+                  pd->port_port, subport);
+       if (subport)
+               goto bail;
        /* atomically clear receive enable port. */
        if (start_stop) {
                /*
@@ -609,7 +720,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop)
                 * updated and correct itself, even in the face of software
                 * bugs.
                 */
-               *pd->port_rcvhdrtail_kvaddr = 0;
+               *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0;
                set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
                        &dd->ipath_rcvctrl);
        } else
@@ -630,6 +741,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop)
                tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
        }
        /* always; new head should be equal to new tail; see above */
+bail:
        return 0;
 }
 
@@ -687,6 +799,36 @@ static void ipath_clean_part_key(struct ipath_portdata *pd,
        }
 }
 
+/*
+ * Initialize the port data with the receive buffer sizes
+ * so this can be done while the master port is locked.
+ * Otherwise, there is a race with a slave opening the port
+ * and seeing these fields uninitialized.
+ */
+static void init_user_egr_sizes(struct ipath_portdata *pd)
+{
+       struct ipath_devdata *dd = pd->port_dd;
+       unsigned egrperchunk, egrcnt, size;
+
+       /*
+        * to avoid wasting a lot of memory, we allocate 32KB chunks of
+        * physically contiguous memory, advance through it until used up
+        * and then allocate more.  Of course, we need memory to store those
+        * extra pointers, now.  Started out with 256KB, but under heavy
+        * memory pressure (creating large files and then copying them over
+        * NFS while doing lots of MPI jobs), we hit some allocation
+        * failures, even though we can sleep...  (2.6.10) Still get
+        * failures at 64K.  32K is the lowest we can go without wasting
+        * additional memory.
+        */
+       size = 0x8000;
+       egrperchunk = size / dd->ipath_rcvegrbufsize;
+       egrcnt = dd->ipath_rcvegrcnt;
+       pd->port_rcvegrbuf_chunks = (egrcnt + egrperchunk - 1) / egrperchunk;
+       pd->port_rcvegrbufs_perchunk = egrperchunk;
+       pd->port_rcvegrbuf_size = size;
+}
+
 /**
  * ipath_create_user_egr - allocate eager TID buffers
  * @pd: the port to allocate TID buffers for
@@ -702,7 +844,7 @@ static void ipath_clean_part_key(struct ipath_portdata *pd,
 static int ipath_create_user_egr(struct ipath_portdata *pd)
 {
        struct ipath_devdata *dd = pd->port_dd;
-       unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff;
+       unsigned e, egrcnt, egrperchunk, chunk, egrsize, egroff;
        size_t size;
        int ret;
        gfp_t gfp_flags;
@@ -722,31 +864,18 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
        ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
                   "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
 
-       /*
-        * to avoid wasting a lot of memory, we allocate 32KB chunks of
-        * physically contiguous memory, advance through it until used up
-        * and then allocate more.  Of course, we need memory to store those
-        * extra pointers, now.  Started out with 256KB, but under heavy
-        * memory pressure (creating large files and then copying them over
-        * NFS while doing lots of MPI jobs), we hit some allocation
-        * failures, even though we can sleep...  (2.6.10) Still get
-        * failures at 64K.  32K is the lowest we can go without wasting
-        * additional memory.
-        */
-       size = 0x8000;
-       alloced = ALIGN(egrsize * egrcnt, size);
-       egrperchunk = size / egrsize;
-       chunk = (egrcnt + egrperchunk - 1) / egrperchunk;
-       pd->port_rcvegrbuf_chunks = chunk;
-       pd->port_rcvegrbufs_perchunk = egrperchunk;
-       pd->port_rcvegrbuf_size = size;
-       pd->port_rcvegrbuf = vmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]));
+       chunk = pd->port_rcvegrbuf_chunks;
+       egrperchunk = pd->port_rcvegrbufs_perchunk;
+       size = pd->port_rcvegrbuf_size;
+       pd->port_rcvegrbuf = kmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]),
+                                    GFP_KERNEL);
        if (!pd->port_rcvegrbuf) {
                ret = -ENOMEM;
                goto bail;
        }
        pd->port_rcvegrbuf_phys =
-               vmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]));
+               kmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]),
+                       GFP_KERNEL);
        if (!pd->port_rcvegrbuf_phys) {
                ret = -ENOMEM;
                goto bail_rcvegrbuf;
@@ -791,105 +920,23 @@ bail_rcvegrbuf_phys:
                                  pd->port_rcvegrbuf_phys[e]);
 
        }
-       vfree(pd->port_rcvegrbuf_phys);
+       kfree(pd->port_rcvegrbuf_phys);
        pd->port_rcvegrbuf_phys = NULL;
 bail_rcvegrbuf:
-       vfree(pd->port_rcvegrbuf);
+       kfree(pd->port_rcvegrbuf);
        pd->port_rcvegrbuf = NULL;
 bail:
        return ret;
 }
 
-static int ipath_do_user_init(struct ipath_portdata *pd,
-                             const struct ipath_user_info *uinfo)
-{
-       int ret = 0;
-       struct ipath_devdata *dd = pd->port_dd;
-       u32 head32;
-
-       /* for now, if major version is different, bail */
-       if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
-               dev_info(&dd->pcidev->dev,
-                        "User major version %d not same as driver "
-                        "major %d\n", uinfo->spu_userversion >> 16,
-                        IPATH_USER_SWMAJOR);
-               ret = -ENODEV;
-               goto done;
-       }
-
-       if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR)
-               ipath_dbg("User minor version %d not same as driver "
-                         "minor %d\n", uinfo->spu_userversion & 0xffff,
-                         IPATH_USER_SWMINOR);
-
-       if (uinfo->spu_rcvhdrsize) {
-               ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize);
-               if (ret)
-                       goto done;
-       }
-
-       /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */
-
-       /* for right now, kernel piobufs are at end, so port 1 is at 0 */
-       pd->port_piobufs = dd->ipath_piobufbase +
-               dd->ipath_pbufsport * (pd->port_port -
-                                      1) * dd->ipath_palign;
-       ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
-                  pd->port_port, pd->port_piobufs);
-
-       /*
-        * Now allocate the rcvhdr Q and eager TIDs; skip the TID
-        * array for time being.  If pd->port_port > chip-supported,
-        * we need to do extra stuff here to handle by handling overflow
-        * through port 0, someday
-        */
-       ret = ipath_create_rcvhdrq(dd, pd);
-       if (!ret)
-               ret = ipath_create_user_egr(pd);
-       if (ret)
-               goto done;
-
-       /*
-        * set the eager head register for this port to the current values
-        * of the tail pointers, since we don't know if they were
-        * updated on last use of the port.
-        */
-       head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
-       ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
-       dd->ipath_lastegrheads[pd->port_port] = -1;
-       dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
-       ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n",
-               pd->port_port, head32);
-       pd->port_tidcursor = 0; /* start at beginning after open */
-       /*
-        * now enable the port; the tail registers will be written to memory
-        * by the chip as soon as it sees the write to
-        * dd->ipath_kregs->kr_rcvctrl.  The update only happens on
-        * transition from 0 to 1, so clear it first, then set it as part of
-        * enabling the port.  This will (very briefly) affect any other
-        * open ports, but it shouldn't be long enough to be an issue.
-        * We explictly set the in-memory copy to 0 beforehand, so we don't
-        * have to wait to be sure the DMA update has happened.
-        */
-       *pd->port_rcvhdrtail_kvaddr = 0ULL;
-       set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
-               &dd->ipath_rcvctrl);
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-                        dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-                        dd->ipath_rcvctrl);
-done:
-       return ret;
-}
-
 
 /* common code for the mappings on dma_alloc_coherent mem */
 static int ipath_mmap_mem(struct vm_area_struct *vma,
-                            struct ipath_portdata *pd, unsigned len,
-                            int write_ok, dma_addr_t addr, char *what)
+       struct ipath_portdata *pd, unsigned len, int write_ok,
+       void *kvaddr, char *what)
 {
        struct ipath_devdata *dd = pd->port_dd;
-       unsigned pfn = (unsigned long)addr >> PAGE_SHIFT;
+       unsigned long pfn;
        int ret;
 
        if ((vma->vm_end - vma->vm_start) > len) {
@@ -912,17 +959,17 @@ static int ipath_mmap_mem(struct vm_area_struct *vma,
                vma->vm_flags &= ~VM_MAYWRITE;
        }
 
+       pfn = virt_to_phys(kvaddr) >> PAGE_SHIFT;
        ret = remap_pfn_range(vma, vma->vm_start, pfn,
                              len, vma->vm_page_prot);
        if (ret)
-               dev_info(&dd->pcidev->dev,
-                        "%s port%u mmap of %lx, %x bytes r%c failed: %d\n",
-                        what, pd->port_port, (unsigned long)addr, len,
-                        write_ok?'w':'o', ret);
+               dev_info(&dd->pcidev->dev, "%s port%u mmap of %lx, %x "
+                        "bytes r%c failed: %d\n", what, pd->port_port,
+                        pfn, len, write_ok?'w':'o', ret);
        else
-               ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes r%c\n",
-                       what, pd->port_port, (unsigned long)addr, len,
-                        write_ok?'w':'o');
+               ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes "
+                          "r%c\n", what, pd->port_port, pfn, len,
+                          write_ok?'w':'o');
 bail:
        return ret;
 }
@@ -957,7 +1004,8 @@ static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd,
 
 static int mmap_piobufs(struct vm_area_struct *vma,
                        struct ipath_devdata *dd,
-                       struct ipath_portdata *pd)
+                       struct ipath_portdata *pd,
+                       unsigned piobufs, unsigned piocnt)
 {
        unsigned long phys;
        int ret;
@@ -968,16 +1016,15 @@ static int mmap_piobufs(struct vm_area_struct *vma,
         * process data, and catches users who might try to read the i/o
         * space due to a bug.
         */
-       if ((vma->vm_end - vma->vm_start) >
-           (dd->ipath_pbufsport * dd->ipath_palign)) {
+       if ((vma->vm_end - vma->vm_start) > (piocnt * dd->ipath_palign)) {
                dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: "
                         "reqlen %lx > PAGE\n",
                         vma->vm_end - vma->vm_start);
-               ret = -EFAULT;
+               ret = -EINVAL;
                goto bail;
        }
 
-       phys = dd->ipath_physaddr + pd->port_piobufs;
+       phys = dd->ipath_physaddr + piobufs;
 
        /*
         * Don't mark this as non-cached, or we don't get the
@@ -1011,7 +1058,7 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma,
        struct ipath_devdata *dd = pd->port_dd;
        unsigned long start, size;
        size_t total_size, i;
-       dma_addr_t *phys;
+       unsigned long pfn;
        int ret;
 
        size = pd->port_rcvegrbuf_size;
@@ -1021,7 +1068,7 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma,
                         "reqlen %lx > actual %lx\n",
                         vma->vm_end - vma->vm_start,
                         (unsigned long) total_size);
-               ret = -EFAULT;
+               ret = -EINVAL;
                goto bail;
        }
 
@@ -1035,11 +1082,11 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma,
        vma->vm_flags &= ~VM_MAYWRITE;
 
        start = vma->vm_start;
-       phys = pd->port_rcvegrbuf_phys;
 
        for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) {
-               ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT,
-                                     size, vma->vm_page_prot);
+               pfn = virt_to_phys(pd->port_rcvegrbuf[i]) >> PAGE_SHIFT;
+               ret = remap_pfn_range(vma, start, pfn, size,
+                                     vma->vm_page_prot);
                if (ret < 0)
                        goto bail;
        }
@@ -1049,6 +1096,122 @@ bail:
        return ret;
 }
 
+/*
+ * ipath_file_vma_nopage - handle a VMA page fault.
+ */
+static struct page *ipath_file_vma_nopage(struct vm_area_struct *vma,
+                                         unsigned long address, int *type)
+{
+       unsigned long offset = address - vma->vm_start;
+       struct page *page = NOPAGE_SIGBUS;
+       void *pageptr;
+
+       /*
+        * Convert the vmalloc address into a struct page.
+        */
+       pageptr = (void *)(offset + (vma->vm_pgoff << PAGE_SHIFT));
+       page = vmalloc_to_page(pageptr);
+       if (!page)
+               goto out;
+
+       /* Increment the reference count. */
+       get_page(page);
+       if (type)
+               *type = VM_FAULT_MINOR;
+out:
+       return page;
+}
+
+static struct vm_operations_struct ipath_file_vm_ops = {
+       .nopage = ipath_file_vma_nopage,
+};
+
+static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
+                      struct ipath_portdata *pd, unsigned subport)
+{
+       unsigned long len;
+       struct ipath_devdata *dd;
+       void *addr;
+       size_t size;
+       int ret;
+
+       /* If the port is not shared, all addresses should be physical */
+       if (!pd->port_subport_cnt) {
+               ret = -EINVAL;
+               goto bail;
+       }
+
+       dd = pd->port_dd;
+       size = pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size;
+
+       /*
+        * Master has all the slave uregbase, rcvhdrq, and
+        * rcvegrbufs mmapped.
+        */
+       if (subport == 0) {
+               unsigned num_slaves = pd->port_subport_cnt - 1;
+
+               if (pgaddr == ((u64) pd->subport_uregbase & MMAP64_MASK)) {
+                       addr = pd->subport_uregbase;
+                       size = PAGE_SIZE * num_slaves;
+               } else if (pgaddr == ((u64) pd->subport_rcvhdr_base &
+                                     MMAP64_MASK)) {
+                       addr = pd->subport_rcvhdr_base;
+                       size = pd->port_rcvhdrq_size * num_slaves;
+               } else if (pgaddr == ((u64) pd->subport_rcvegrbuf &
+                                     MMAP64_MASK)) {
+                       addr = pd->subport_rcvegrbuf;
+                       size *= num_slaves;
+               } else {
+                       ret = -EINVAL;
+                       goto bail;
+               }
+       } else if (pgaddr == (((u64) pd->subport_uregbase +
+                              PAGE_SIZE * (subport - 1)) & MMAP64_MASK)) {
+               addr = pd->subport_uregbase + PAGE_SIZE * (subport - 1);
+               size = PAGE_SIZE;
+       } else if (pgaddr == (((u64) pd->subport_rcvhdr_base +
+                              pd->port_rcvhdrq_size * (subport - 1)) &
+                             MMAP64_MASK)) {
+               addr = pd->subport_rcvhdr_base +
+                       pd->port_rcvhdrq_size * (subport - 1);
+               size = pd->port_rcvhdrq_size;
+       } else if (pgaddr == (((u64) pd->subport_rcvegrbuf +
+                              size * (subport - 1)) & MMAP64_MASK)) {
+               addr = pd->subport_rcvegrbuf + size * (subport - 1);
+               /* rcvegrbufs are read-only on the slave */
+               if (vma->vm_flags & VM_WRITE) {
+                       dev_info(&dd->pcidev->dev,
+                                "Can't map eager buffers as "
+                                "writable (flags=%lx)\n", vma->vm_flags);
+                       ret = -EPERM;
+                       goto bail;
+               }
+               /*
+                * Don't allow permission to later change to writeable
+                * with mprotect.
+                */
+               vma->vm_flags &= ~VM_MAYWRITE;
+       } else {
+               ret = -EINVAL;
+               goto bail;
+       }
+       len = vma->vm_end - vma->vm_start;
+       if (len > size) {
+               ipath_cdbg(MM, "FAIL: reqlen %lx > %zx\n", len, size);
+               ret = -EINVAL;
+               goto bail;
+       }
+
+       vma->vm_pgoff = (unsigned long) addr >> PAGE_SHIFT;
+       vma->vm_ops = &ipath_file_vm_ops;
+       vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
+       ret = 0;
+
+bail:
+       return ret;
+}
+
 /**
  * ipath_mmap - mmap various structures into user space
  * @fp: the file pointer
@@ -1064,73 +1227,99 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
        struct ipath_portdata *pd;
        struct ipath_devdata *dd;
        u64 pgaddr, ureg;
+       unsigned piobufs, piocnt;
        int ret;
 
        pd = port_fp(fp);
+       if (!pd) {
+               ret = -EINVAL;
+               goto bail;
+       }
        dd = pd->port_dd;
 
        /*
         * This is the ipath_do_user_init() code, mapping the shared buffers
         * into the user process. The address referred to by vm_pgoff is the
-        * virtual, not physical, address; we only do one mmap for each
-        * space mapped.
+        * file offset passed via mmap().  For shared ports, this is the
+        * kernel vmalloc() address of the pages to share with the master.
+        * For non-shared or master ports, this is a physical address.
+        * We only do one mmap for each space mapped.
         */
        pgaddr = vma->vm_pgoff << PAGE_SHIFT;
 
        /*
-        * Must fit in 40 bits for our hardware; some checked elsewhere,
-        * but we'll be paranoid.  Check for 0 is mostly in case one of the
-        * allocations failed, but user called mmap anyway.   We want to catch
-        * that before it can match.
+        * Check for 0 in case one of the allocations failed, but user
+        * called mmap anyway.
         */
-       if (!pgaddr || pgaddr >= (1ULL<<40))  {
-               ipath_dev_err(dd, "Bad phys addr %llx, start %lx, end %lx\n",
-                       (unsigned long long)pgaddr, vma->vm_start, vma->vm_end);
-               return -EINVAL;
+       if (!pgaddr)  {
+               ret = -EINVAL;
+               goto bail;
        }
 
-       /* just the offset of the port user registers, not physical addr */
-       ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
-
-       ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n",
+       ipath_cdbg(MM, "pgaddr %llx vm_start=%lx len %lx port %u:%u:%u\n",
                   (unsigned long long) pgaddr, vma->vm_start,
-                  vma->vm_end - vma->vm_start);
+                  vma->vm_end - vma->vm_start, dd->ipath_unit,
+                  pd->port_port, subport_fp(fp));
 
-       if (vma->vm_start & (PAGE_SIZE-1)) {
-               ipath_dev_err(dd,
-                       "vm_start not aligned: %lx, end=%lx phys %lx\n",
-                       vma->vm_start, vma->vm_end, (unsigned long)pgaddr);
-               ret = -EINVAL;
+       /*
+        * Physical addresses must fit in 40 bits for our hardware.
+        * Check for kernel virtual addresses first, anything else must
+        * match a HW or memory address.
+        */
+       if (pgaddr >= (1ULL<<40)) {
+               ret = mmap_kvaddr(vma, pgaddr, pd, subport_fp(fp));
+               goto bail;
        }
-       else if (pgaddr == ureg)
+
+       if (!pd->port_subport_cnt) {
+               /* port is not shared */
+               ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+               piocnt = dd->ipath_pbufsport;
+               piobufs = pd->port_piobufs;
+       } else if (!subport_fp(fp)) {
+               /* caller is the master */
+               ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+               piocnt = (dd->ipath_pbufsport / pd->port_subport_cnt) +
+                        (dd->ipath_pbufsport % pd->port_subport_cnt);
+               piobufs = pd->port_piobufs +
+                       dd->ipath_palign * (dd->ipath_pbufsport - piocnt);
+       } else {
+               unsigned slave = subport_fp(fp) - 1;
+
+               /* caller is a slave */
+               ureg = 0;
+               piocnt = dd->ipath_pbufsport / pd->port_subport_cnt;
+               piobufs = pd->port_piobufs + dd->ipath_palign * piocnt * slave;
+       }
+
+       if (pgaddr == ureg)
                ret = mmap_ureg(vma, dd, ureg);
-       else if (pgaddr == pd->port_piobufs)
-               ret = mmap_piobufs(vma, dd, pd);
-       else if (pgaddr == (u64) pd->port_rcvegr_phys)
+       else if (pgaddr == piobufs)
+               ret = mmap_piobufs(vma, dd, pd, piobufs, piocnt);
+       else if (pgaddr == dd->ipath_pioavailregs_phys)
+               /* in-memory copy of pioavail registers */
+               ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0,
+                                    (void *) dd->ipath_pioavailregs_dma,
+                                    "pioavail registers");
+       else if (subport_fp(fp))
+               /* Subports don't mmap the physical receive buffers */
+               ret = -EINVAL;
+       else if (pgaddr == pd->port_rcvegr_phys)
                ret = mmap_rcvegrbufs(vma, pd);
-       else if (pgaddr == (u64) pd->port_rcvhdrq_phys) {
+       else if (pgaddr == (u64) pd->port_rcvhdrq_phys)
                /*
                 * The rcvhdrq itself; readonly except on HT (so have
                 * to allow writable mapping), multiple pages, contiguous
                 * from an i/o perspective.
                 */
-               unsigned total_size =
-                       ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize
-                          * sizeof(u32), PAGE_SIZE);
-               ret = ipath_mmap_mem(vma, pd, total_size, 1,
-                                    pd->port_rcvhdrq_phys,
+               ret = ipath_mmap_mem(vma, pd, pd->port_rcvhdrq_size, 1,
+                                    pd->port_rcvhdrq,
                                     "rcvhdrq");
-       }
-       else if (pgaddr == (u64)pd->port_rcvhdrqtailaddr_phys)
+       else if (pgaddr == (u64) pd->port_rcvhdrqtailaddr_phys)
                /* in-memory copy of rcvhdrq tail register */
                ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0,
-                                    pd->port_rcvhdrqtailaddr_phys,
+                                    pd->port_rcvhdrtail_kvaddr,
                                     "rcvhdrq tail");
-       else if (pgaddr == dd->ipath_pioavailregs_phys)
-               /* in-memory copy of pioavail registers */
-               ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0,
-                                    dd->ipath_pioavailregs_phys,
-                                    "pioavail registers");
        else
                ret = -EINVAL;
 
@@ -1138,9 +1327,10 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
 
        if (ret < 0)
                dev_info(&dd->pcidev->dev,
-                        "Failure %d on addr %lx, off %lx\n",
-                        -ret, vma->vm_start, vma->vm_pgoff);
-
+                        "Failure %d on off %llx len %lx\n",
+                        -ret, (unsigned long long)pgaddr,
+                        vma->vm_end - vma->vm_start);
+bail:
        return ret;
 }
 
@@ -1154,6 +1344,8 @@ static unsigned int ipath_poll(struct file *fp,
        struct ipath_devdata *dd;
 
        pd = port_fp(fp);
+       if (!pd)
+               goto bail;
        dd = pd->port_dd;
 
        bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
@@ -1176,7 +1368,7 @@ static unsigned int ipath_poll(struct file *fp,
 
        if (tail == head) {
                set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
-               if(dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
+               if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
                        (void)ipath_write_ureg(dd, ur_rcvhdrhead,
                                               dd->ipath_rhdrhead_intr_off
                                               | head, pd->port_port);
@@ -1200,18 +1392,80 @@ static unsigned int ipath_poll(struct file *fp,
        ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
                         dd->ipath_rcvctrl);
 
+bail:
        return pollflag;
 }
 
+static int init_subports(struct ipath_devdata *dd,
+                        struct ipath_portdata *pd,
+                        const struct ipath_user_info *uinfo)
+{
+       int ret = 0;
+       unsigned num_slaves;
+       size_t size;
+
+       /* Old user binaries don't know about subports */
+       if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR)
+               goto bail;
+       /*
+        * If the user is requesting zero or one port,
+        * skip the subport allocation.
+        */
+       if (uinfo->spu_subport_cnt <= 1)
+               goto bail;
+       if (uinfo->spu_subport_cnt > 4) {
+               ret = -EINVAL;
+               goto bail;
+       }
+
+       num_slaves = uinfo->spu_subport_cnt - 1;
+       pd->subport_uregbase = vmalloc(PAGE_SIZE * num_slaves);
+       if (!pd->subport_uregbase) {
+               ret = -ENOMEM;
+               goto bail;
+       }
+       /* Note: pd->port_rcvhdrq_size isn't initialized yet. */
+       size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+                    sizeof(u32), PAGE_SIZE) * num_slaves;
+       pd->subport_rcvhdr_base = vmalloc(size);
+       if (!pd->subport_rcvhdr_base) {
+               ret = -ENOMEM;
+               goto bail_ureg;
+       }
+
+       pd->subport_rcvegrbuf = vmalloc(pd->port_rcvegrbuf_chunks *
+                                       pd->port_rcvegrbuf_size *
+                                       num_slaves);
+       if (!pd->subport_rcvegrbuf) {
+               ret = -ENOMEM;
+               goto bail_rhdr;
+       }
+
+       pd->port_subport_cnt = uinfo->spu_subport_cnt;
+       pd->port_subport_id = uinfo->spu_subport_id;
+       pd->active_slaves = 1;
+       goto bail;
+
+bail_rhdr:
+       vfree(pd->subport_rcvhdr_base);
+bail_ureg:
+       vfree(pd->subport_uregbase);
+       pd->subport_uregbase = NULL;
+bail:
+       return ret;
+}
+
 static int try_alloc_port(struct ipath_devdata *dd, int port,
-                         struct file *fp)
+                         struct file *fp,
+                         const struct ipath_user_info *uinfo)
 {
+       struct ipath_portdata *pd;
        int ret;
 
-       if (!dd->ipath_pd[port]) {
-               void *p, *ptmp;
+       if (!(pd = dd->ipath_pd[port])) {
+               void *ptmp;
 
-               p = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL);
+               pd = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL);
 
                /*
                 * Allocate memory for use in ipath_tid_update() just once
@@ -1221,34 +1475,36 @@ static int try_alloc_port(struct ipath_devdata *dd, int port,
                ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) +
                               dd->ipath_rcvtidcnt * sizeof(struct page **),
                               GFP_KERNEL);
-               if (!p || !ptmp) {
+               if (!pd || !ptmp) {
                        ipath_dev_err(dd, "Unable to allocate portdata "
                                      "memory, failing open\n");
                        ret = -ENOMEM;
-                       kfree(p);
+                       kfree(pd);
                        kfree(ptmp);
                        goto bail;
                }
-               dd->ipath_pd[port] = p;
+               dd->ipath_pd[port] = pd;
                dd->ipath_pd[port]->port_port = port;
                dd->ipath_pd[port]->port_dd = dd;
                dd->ipath_pd[port]->port_tid_pg_list = ptmp;
                init_waitqueue_head(&dd->ipath_pd[port]->port_wait);
        }
-       if (!dd->ipath_pd[port]->port_cnt) {
-               dd->ipath_pd[port]->port_cnt = 1;
-               fp->private_data = (void *) dd->ipath_pd[port];
+       if (!pd->port_cnt) {
+               pd->userversion = uinfo->spu_userversion;
+               init_user_egr_sizes(pd);
+               if ((ret = init_subports(dd, pd, uinfo)) != 0)
+                       goto bail;
                ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n",
                           current->comm, current->pid, dd->ipath_unit,
                           port);
-               dd->ipath_pd[port]->port_pid = current->pid;
-               strncpy(dd->ipath_pd[port]->port_comm, current->comm,
-                       sizeof(dd->ipath_pd[port]->port_comm));
+               pd->port_cnt = 1;
+               port_fp(fp) = pd;
+               pd->port_pid = current->pid;
+               strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm));
                ipath_stats.sps_ports++;
                ret = 0;
-               goto bail;
-       }
-       ret = -EBUSY;
+       } else
+               ret = -EBUSY;
 
 bail:
        return ret;
@@ -1264,7 +1520,8 @@ static inline int usable(struct ipath_devdata *dd)
                                     | IPATH_LINKUNK));
 }
 
-static int find_free_port(int unit, struct file *fp)
+static int find_free_port(int unit, struct file *fp,
+                         const struct ipath_user_info *uinfo)
 {
        struct ipath_devdata *dd = ipath_lookup(unit);
        int ret, i;
@@ -1279,8 +1536,8 @@ static int find_free_port(int unit, struct file *fp)
                goto bail;
        }
 
-       for (i = 0; i < dd->ipath_cfgports; i++) {
-               ret = try_alloc_port(dd, i, fp);
+       for (i = 1; i < dd->ipath_cfgports; i++) {
+               ret = try_alloc_port(dd, i, fp, uinfo);
                if (ret != -EBUSY)
                        goto bail;
        }
@@ -1290,13 +1547,14 @@ bail:
        return ret;
 }
 
-static int find_best_unit(struct file *fp)
+static int find_best_unit(struct file *fp,
+                         const struct ipath_user_info *uinfo)
 {
        int ret = 0, i, prefunit = -1, devmax;
        int maxofallports, npresent, nup;
        int ndev;
 
-       (void) ipath_count_units(&npresent, &nup, &maxofallports);
+       devmax = ipath_count_units(&npresent, &nup, &maxofallports);
 
        /*
         * This code is present to allow a knowledgeable person to
@@ -1343,8 +1601,6 @@ static int find_best_unit(struct file *fp)
 
        if (prefunit != -1)
                devmax = prefunit + 1;
-       else
-               devmax = ipath_count_units(NULL, NULL, NULL);
 recheck:
        for (i = 1; i < maxofallports; i++) {
                for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax;
@@ -1359,7 +1615,7 @@ recheck:
                                 * next.
                                 */
                                continue;
-                       ret = try_alloc_port(dd, i, fp);
+                       ret = try_alloc_port(dd, i, fp, uinfo);
                        if (!ret)
                                goto done;
                }
@@ -1395,22 +1651,183 @@ done:
        return ret;
 }
 
+static int find_shared_port(struct file *fp,
+                           const struct ipath_user_info *uinfo)
+{
+       int devmax, ndev, i;
+       int ret = 0;
+
+       devmax = ipath_count_units(NULL, NULL, NULL);
+
+       for (ndev = 0; ndev < devmax; ndev++) {
+               struct ipath_devdata *dd = ipath_lookup(ndev);
+
+               if (!dd)
+                       continue;
+               for (i = 1; i < dd->ipath_cfgports; i++) {
+                       struct ipath_portdata *pd = dd->ipath_pd[i];
+
+                       /* Skip ports which are not yet open */
+                       if (!pd || !pd->port_cnt)
+                               continue;
+                       /* Skip port if it doesn't match the requested one */
+                       if (pd->port_subport_id != uinfo->spu_subport_id)
+                               continue;
+                       /* Verify the sharing process matches the master */
+                       if (pd->port_subport_cnt != uinfo->spu_subport_cnt ||
+                           pd->userversion != uinfo->spu_userversion ||
+                           pd->port_cnt >= pd->port_subport_cnt) {
+                               ret = -EINVAL;
+                               goto done;
+                       }
+                       port_fp(fp) = pd;
+                       subport_fp(fp) = pd->port_cnt++;
+                       tidcursor_fp(fp) = 0;
+                       pd->active_slaves |= 1 << subport_fp(fp);
+                       ipath_cdbg(PROC,
+                                  "%s[%u] %u sharing %s[%u] unit:port %u:%u\n",
+                                  current->comm, current->pid,
+                                  subport_fp(fp),
+                                  pd->port_comm, pd->port_pid,
+                                  dd->ipath_unit, pd->port_port);
+                       ret = 1;
+                       goto done;
+               }
+       }
+
+done:
+       return ret;
+}
+
 static int ipath_open(struct inode *in, struct file *fp)
 {
-       int ret, user_minor;
+       /* The real work is performed later in ipath_assign_port() */
+       fp->private_data = kzalloc(sizeof(struct ipath_filedata), GFP_KERNEL);
+       return fp->private_data ? 0 : -ENOMEM;
+}
+
+
+/* Get port early, so can set affinity prior to memory allocation */
+static int ipath_assign_port(struct file *fp,
+                             const struct ipath_user_info *uinfo)
+{
+       int ret;
+       int i_minor;
+       unsigned swminor;
+
+       /* Check to be sure we haven't already initialized this file */
+       if (port_fp(fp)) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /* for now, if major version is different, bail */
+       if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+               ipath_dbg("User major version %d not same as driver "
+                         "major %d\n", uinfo->spu_userversion >> 16,
+                         IPATH_USER_SWMAJOR);
+               ret = -ENODEV;
+               goto done;
+       }
+
+       swminor = uinfo->spu_userversion & 0xffff;
+       if (swminor != IPATH_USER_SWMINOR)
+               ipath_dbg("User minor version %d not same as driver "
+                         "minor %d\n", swminor, IPATH_USER_SWMINOR);
 
        mutex_lock(&ipath_mutex);
 
-       user_minor = iminor(in) - IPATH_USER_MINOR_BASE;
+       if (swminor == IPATH_USER_SWMINOR && uinfo->spu_subport_cnt &&
+           (ret = find_shared_port(fp, uinfo))) {
+               mutex_unlock(&ipath_mutex);
+               if (ret > 0)
+                       ret = 0;
+               goto done;
+       }
+
+       i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE;
        ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
-                  (long)in->i_rdev, user_minor);
+                  (long)fp->f_dentry->d_inode->i_rdev, i_minor);
 
-       if (user_minor)
-               ret = find_free_port(user_minor - 1, fp);
+       if (i_minor)
+               ret = find_free_port(i_minor - 1, fp, uinfo);
        else
-               ret = find_best_unit(fp);
+               ret = find_best_unit(fp, uinfo);
 
        mutex_unlock(&ipath_mutex);
+
+done:
+       return ret;
+}
+
+
+static int ipath_do_user_init(struct file *fp,
+                             const struct ipath_user_info *uinfo)
+{
+       int ret;
+       struct ipath_portdata *pd;
+       struct ipath_devdata *dd;
+       u32 head32;
+
+       pd = port_fp(fp);
+       dd = pd->port_dd;
+
+       if (uinfo->spu_rcvhdrsize) {
+               ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize);
+               if (ret)
+                       goto done;
+       }
+
+       /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */
+
+       /* for right now, kernel piobufs are at end, so port 1 is at 0 */
+       pd->port_piobufs = dd->ipath_piobufbase +
+               dd->ipath_pbufsport * (pd->port_port - 1) * dd->ipath_palign;
+       ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
+                  pd->port_port, pd->port_piobufs);
+
+       /*
+        * Now allocate the rcvhdr Q and eager TIDs; skip the TID
+        * array for time being.  If pd->port_port > chip-supported,
+        * we need to do extra stuff here to handle by handling overflow
+        * through port 0, someday
+        */
+       ret = ipath_create_rcvhdrq(dd, pd);
+       if (!ret)
+               ret = ipath_create_user_egr(pd);
+       if (ret)
+               goto done;
+
+       /*
+        * set the eager head register for this port to the current values
+        * of the tail pointers, since we don't know if they were
+        * updated on last use of the port.
+        */
+       head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
+       ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
+       dd->ipath_lastegrheads[pd->port_port] = -1;
+       dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
+       ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n",
+               pd->port_port, head32);
+       pd->port_tidcursor = 0; /* start at beginning after open */
+       /*
+        * now enable the port; the tail registers will be written to memory
+        * by the chip as soon as it sees the write to
+        * dd->ipath_kregs->kr_rcvctrl.  The update only happens on
+        * transition from 0 to 1, so clear it first, then set it as part of
+        * enabling the port.  This will (very briefly) affect any other
+        * open ports, but it shouldn't be long enough to be an issue.
+        * We explictly set the in-memory copy to 0 beforehand, so we don't
+        * have to wait to be sure the DMA update has happened.
+        */
+       *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL;
+       set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+               &dd->ipath_rcvctrl);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+                        dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
+       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+                        dd->ipath_rcvctrl);
+done:
        return ret;
 }
 
@@ -1433,6 +1850,8 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
                if (!dd->ipath_pageshadow[i])
                        continue;
 
+               pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i],
+                       PAGE_SIZE, PCI_DMA_FROMDEVICE);
                ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
                                                  1);
                dd->ipath_pageshadow[i] = NULL;
@@ -1453,6 +1872,7 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
 static int ipath_close(struct inode *in, struct file *fp)
 {
        int ret = 0;
+       struct ipath_filedata *fd;
        struct ipath_portdata *pd;
        struct ipath_devdata *dd;
        unsigned port;
@@ -1462,9 +1882,24 @@ static int ipath_close(struct inode *in, struct file *fp)
 
        mutex_lock(&ipath_mutex);
 
-       pd = port_fp(fp);
-       port = pd->port_port;
+       fd = (struct ipath_filedata *) fp->private_data;
        fp->private_data = NULL;
+       pd = fd->pd;
+       if (!pd) {
+               mutex_unlock(&ipath_mutex);
+               goto bail;
+       }
+       if (--pd->port_cnt) {
+               /*
+                * XXX If the master closes the port before the slave(s),
+                * revoke the mmap for the eager receive queue so
+                * the slave(s) don't wait for receive data forever.
+                */
+               pd->active_slaves &= ~(1 << fd->subport);
+               mutex_unlock(&ipath_mutex);
+               goto bail;
+       }
+       port = pd->port_port;
        dd = pd->port_dd;
 
        if (pd->port_hdrqfull) {
@@ -1503,8 +1938,6 @@ static int ipath_close(struct inode *in, struct file *fp)
 
                /* clean up the pkeys for this port user */
                ipath_clean_part_key(pd, dd);
-
-
                /*
                 * be paranoid, and never write 0's to these, just use an
                 * unused part of the port 0 tail page.  Of course,
@@ -1523,39 +1956,49 @@ static int ipath_close(struct inode *in, struct file *fp)
                i = dd->ipath_pbufsport * (port - 1);
                ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
 
+               dd->ipath_f_clear_tids(dd, pd->port_port);
+
                if (dd->ipath_pageshadow)
                        unlock_expected_tids(pd);
                ipath_stats.sps_ports--;
                ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
                           pd->port_comm, pd->port_pid,
                           dd->ipath_unit, port);
-
-               dd->ipath_f_clear_tids(dd, pd->port_port);
        }
 
-       pd->port_cnt = 0;
        pd->port_pid = 0;
-
        dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */
        mutex_unlock(&ipath_mutex);
        ipath_free_pddata(dd, pd); /* after releasing the mutex */
 
+bail:
+       kfree(fd);
        return ret;
 }
 
-static int ipath_port_info(struct ipath_portdata *pd,
+static int ipath_port_info(struct ipath_portdata *pd, u16 subport,
                           struct ipath_port_info __user *uinfo)
 {
        struct ipath_port_info info;
        int nup;
        int ret;
+       size_t sz;
 
        (void) ipath_count_units(NULL, &nup, NULL);
        info.num_active = nup;
        info.unit = pd->port_dd->ipath_unit;
        info.port = pd->port_port;
+       info.subport = subport;
+       /* Don't return new fields if old library opened the port. */
+       if ((pd->userversion & 0xffff) == IPATH_USER_SWMINOR) {
+               /* Number of user ports available for this device. */
+               info.num_ports = pd->port_dd->ipath_cfgports - 1;
+               info.num_subports = pd->port_subport_cnt;
+               sz = sizeof(info);
+       } else
+               sz = sizeof(info) - 2 * sizeof(u16);
 
-       if (copy_to_user(uinfo, &info, sizeof(info))) {
+       if (copy_to_user(uinfo, &info, sz)) {
                ret = -EFAULT;
                goto bail;
        }
@@ -1565,6 +2008,16 @@ bail:
        return ret;
 }
 
+static int ipath_get_slave_info(struct ipath_portdata *pd,
+                               void __user *slave_mask_addr)
+{
+       int ret = 0;
+
+       if (copy_to_user(slave_mask_addr, &pd->active_slaves, sizeof(u32)))
+               ret = -EFAULT;
+       return ret;
+}
+
 static ssize_t ipath_write(struct file *fp, const char __user *data,
                           size_t count, loff_t *off)
 {
@@ -1591,6 +2044,8 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
        consumed = sizeof(cmd.type);
 
        switch (cmd.type) {
+       case IPATH_CMD_ASSIGN_PORT:
+       case __IPATH_CMD_USER_INIT:
        case IPATH_CMD_USER_INIT:
                copy = sizeof(cmd.cmd.user_info);
                dest = &cmd.cmd.user_info;
@@ -1617,6 +2072,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
                dest = &cmd.cmd.part_key;
                src = &ucmd->cmd.part_key;
                break;
+       case IPATH_CMD_SLAVE_INFO:
+               copy = sizeof(cmd.cmd.slave_mask_addr);
+               dest = &cmd.cmd.slave_mask_addr;
+               src = &ucmd->cmd.slave_mask_addr;
+               break;
        default:
                ret = -EINVAL;
                goto bail;
@@ -1634,34 +2094,55 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
 
        consumed += copy;
        pd = port_fp(fp);
+       if (!pd && cmd.type != __IPATH_CMD_USER_INIT &&
+               cmd.type != IPATH_CMD_ASSIGN_PORT) {
+               ret = -EINVAL;
+               goto bail;
+       }
 
        switch (cmd.type) {
+       case IPATH_CMD_ASSIGN_PORT:
+               ret = ipath_assign_port(fp, &cmd.cmd.user_info);
+               if (ret)
+                       goto bail;
+               break;
+       case __IPATH_CMD_USER_INIT:
+               /* backwards compatibility, get port first */
+               ret = ipath_assign_port(fp, &cmd.cmd.user_info);
+               if (ret)
+                       goto bail;
+               /* and fall through to current version. */
        case IPATH_CMD_USER_INIT:
-               ret = ipath_do_user_init(pd, &cmd.cmd.user_info);
-               if (ret < 0)
+               ret = ipath_do_user_init(fp, &cmd.cmd.user_info);
+               if (ret)
                        goto bail;
                ret = ipath_get_base_info(
-                       pd, (void __user *) (unsigned long)
+                       fp, (void __user *) (unsigned long)
                        cmd.cmd.user_info.spu_base_info,
                        cmd.cmd.user_info.spu_base_info_size);
                break;
        case IPATH_CMD_RECV_CTRL:
-               ret = ipath_manage_rcvq(pd, cmd.cmd.recv_ctrl);
+               ret = ipath_manage_rcvq(pd, subport_fp(fp), cmd.cmd.recv_ctrl);
                break;
        case IPATH_CMD_PORT_INFO:
-               ret = ipath_port_info(pd,
+               ret = ipath_port_info(pd, subport_fp(fp),
                                      (struct ipath_port_info __user *)
                                      (unsigned long) cmd.cmd.port_info);
                break;
        case IPATH_CMD_TID_UPDATE:
-               ret = ipath_tid_update(pd, &cmd.cmd.tid_info);
+               ret = ipath_tid_update(pd, fp, &cmd.cmd.tid_info);
                break;
        case IPATH_CMD_TID_FREE:
-               ret = ipath_tid_free(pd, &cmd.cmd.tid_info);
+               ret = ipath_tid_free(pd, subport_fp(fp), &cmd.cmd.tid_info);
                break;
        case IPATH_CMD_SET_PART_KEY:
                ret = ipath_set_part_key(pd, cmd.cmd.part_key);
                break;
+       case IPATH_CMD_SLAVE_INFO:
+               ret = ipath_get_slave_info(pd,
+                                          (void __user *) (unsigned long)
+                                          cmd.cmd.slave_mask_addr);
+               break;
        }
 
        if (ret >= 0)
@@ -1858,4 +2339,3 @@ void ipath_user_remove(struct ipath_devdata *dd)
 bail:
        return;
 }
-
index a5eb30a06a5cb0698c2f93f44202ac3bcf76a200..d9ff283f725e75dc900e436ebde42dee65e5fa53 100644 (file)
@@ -61,14 +61,13 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
        inode->i_mode = mode;
        inode->i_uid = 0;
        inode->i_gid = 0;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       inode->u.generic_ip = data;
+       inode->i_private = data;
        if ((mode & S_IFMT) == S_IFDIR) {
                inode->i_op = &simple_dir_inode_operations;
-               inode->i_nlink++;
-               dir->i_nlink++;
+               inc_nlink(inode);
+               inc_nlink(dir);
        }
 
        inode->i_fop = fops;
@@ -119,7 +118,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
        u16 i;
        struct ipath_devdata *dd;
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
 
        for (i = 0; i < NUM_COUNTERS; i++)
                counters[i] = ipath_snap_cntr(dd, i);
@@ -139,7 +138,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
        struct ipath_devdata *dd;
        u64 guid;
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
 
        guid = be64_to_cpu(dd->ipath_guid);
 
@@ -178,7 +177,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
        u32 tmp, tmp2;
        struct ipath_devdata *dd;
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
 
        /* so we only initialize non-zero fields. */
        memset(portinfo, 0, sizeof portinfo);
@@ -325,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf,
                goto bail;
        }
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
        if (ipath_eeprom_read(dd, pos, tmp, count)) {
                ipath_dev_err(dd, "failed to read from flash\n");
                ret = -ENXIO;
@@ -357,19 +356,16 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
 
        pos = *ppos;
 
-       if ( pos < 0) {
+       if (pos != 0) {
                ret = -EINVAL;
                goto bail;
        }
 
-       if (pos >= sizeof(struct ipath_flash)) {
-               ret = 0;
+       if (count != sizeof(struct ipath_flash)) {
+               ret = -EINVAL;
                goto bail;
        }
 
-       if (count > sizeof(struct ipath_flash) - pos)
-               count = sizeof(struct ipath_flash) - pos;
-
        tmp = kmalloc(count, GFP_KERNEL);
        if (!tmp) {
                ret = -ENOMEM;
@@ -381,7 +377,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
                goto bail_tmp;
        }
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
        if (ipath_eeprom_write(dd, pos, tmp, count)) {
                ret = -ENXIO;
                ipath_dev_err(dd, "failed to write to flash\n");
index bf2455a6d56238024136ba00655df965900e3561..9e4e8d4c6e2035769ddef2a080a1f7163bef8678 100644 (file)
@@ -252,8 +252,8 @@ static const struct ipath_cregs ipath_ht_cregs = {
 };
 
 /* kr_intstatus, kr_intclear, kr_intmask bits */
-#define INFINIPATH_I_RCVURG_MASK 0x1FF
-#define INFINIPATH_I_RCVAVAIL_MASK 0x1FF
+#define INFINIPATH_I_RCVURG_MASK ((1U<<9)-1)
+#define INFINIPATH_I_RCVAVAIL_MASK ((1U<<9)-1)
 
 /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
 #define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
@@ -338,7 +338,7 @@ static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs,
        if (crcbits) {
                u16 ctrl0, ctrl1;
                snprintf(bitsmsg, sizeof bitsmsg,
-                        "[HT%s lane %s CRC (%llx); ignore till reload]",
+                        "[HT%s lane %s CRC (%llx); powercycle to completely clear]",
                         !(crcbits & _IPATH_HTLINK1_CRCBITS) ?
                         "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS)
                                    ? "1 (B)" : "0+1 (A+B)"),
@@ -389,17 +389,28 @@ static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs,
                                     _IPATH_HTLINK1_CRCBITS)));
 }
 
+/* 6110 specific hardware errors... */
+static const struct ipath_hwerror_msgs ipath_6110_hwerror_msgs[] = {
+       INFINIPATH_HWE_MSG(HTCBUSIREQPARITYERR, "HTC Ireq Parity"),
+       INFINIPATH_HWE_MSG(HTCBUSTREQPARITYERR, "HTC Treq Parity"),
+       INFINIPATH_HWE_MSG(HTCBUSTRESPPARITYERR, "HTC Tresp Parity"),
+       INFINIPATH_HWE_MSG(HTCMISCERR5, "HT core Misc5"),
+       INFINIPATH_HWE_MSG(HTCMISCERR6, "HT core Misc6"),
+       INFINIPATH_HWE_MSG(HTCMISCERR7, "HT core Misc7"),
+       INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),
+       INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),
+};
+
 /**
- * ipath_ht_handle_hwerrors - display hardware errors
+ * ipath_ht_handle_hwerrors - display hardware errors.
  * @dd: the infinipath device
  * @msg: the output buffer
  * @msgl: the size of the output buffer
  *
- * Use same msg buffer as regular errors to avoid
- * excessive stack use.  Most hardware errors are catastrophic, but for
- * right now, we'll print them and continue.
- * We reuse the same message buffer as ipath_handle_errors() to avoid
- * excessive stack usage.
+ * Use same msg buffer as regular errors to avoid excessive stack
+ * use.  Most hardware errors are catastrophic, but for right now,
+ * we'll print them and continue.  We reuse the same message buffer as
+ * ipath_handle_errors() to avoid excessive stack usage.
  */
 static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                                     size_t msgl)
@@ -440,19 +451,49 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
         * make sure we get this much out, unless told to be quiet,
         * or it's occurred within the last 5 seconds
         */
-       if ((hwerrs & ~dd->ipath_lasthwerror) ||
+       if ((hwerrs & ~(dd->ipath_lasthwerror |
+                       ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+                         INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+                       << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||
            (ipath_debug & __IPATH_VERBDBG))
                dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
                         "(cleared)\n", (unsigned long long) hwerrs);
        dd->ipath_lasthwerror |= hwerrs;
 
-       if (hwerrs & ~infinipath_hwe_bitsextant)
+       if (hwerrs & ~dd->ipath_hwe_bitsextant)
                ipath_dev_err(dd, "hwerror interrupt with unknown errors "
                              "%llx set\n", (unsigned long long)
-                             (hwerrs & ~infinipath_hwe_bitsextant));
+                             (hwerrs & ~dd->ipath_hwe_bitsextant));
 
        ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
        if (ctrl & INFINIPATH_C_FREEZEMODE) {
+               /*
+                * parity errors in send memory are recoverable,
+                * just cancel the send (if indicated in * sendbuffererror),
+                * count the occurrence, unfreeze (if no other handled
+                * hardware error bits are set), and continue. They can
+                * occur if a processor speculative read is done to the PIO
+                * buffer while we are sending a packet, for example.
+                */
+               if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+                              INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+                             << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+                       ipath_stats.sps_txeparity++;
+                       ipath_dbg("Recovering from TXE parity error (%llu), "
+                                 "hwerrstatus=%llx\n",
+                                 (unsigned long long) ipath_stats.sps_txeparity,
+                                 (unsigned long long) hwerrs);
+                       ipath_disarm_senderrbufs(dd);
+                       hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+                                    INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+                                   << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT);
+                       if (!hwerrs) { /* else leave in freeze mode */
+                               ipath_write_kreg(dd,
+                                                dd->ipath_kregs->kr_control,
+                                                dd->ipath_control);
+                               return;
+                       }
+               }
                if (hwerrs) {
                        /*
                         * if any set that we aren't ignoring; only
@@ -499,44 +540,16 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                         bits);
                strlcat(msg, bitsmsg, msgl);
        }
-       if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
-                     << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
-               bits = (u32) ((hwerrs >>
-                              INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
-                             INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
-               snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
-                        bits);
-               strlcat(msg, bitsmsg, msgl);
-       }
-       if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
-                     << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
-               bits = (u32) ((hwerrs >>
-                              INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
-                             INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
-               snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
-                        bits);
-               strlcat(msg, bitsmsg, msgl);
-       }
-       if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
-               strlcat(msg, "[IB2IPATH Parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
-               strlcat(msg, "[IPATH2IB Parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_HTCBUSIREQPARITYERR)
-               strlcat(msg, "[HTC Ireq Parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_HTCBUSTREQPARITYERR)
-               strlcat(msg, "[HTC Treq Parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_HTCBUSTRESPPARITYERR)
-               strlcat(msg, "[HTC Tresp Parity]", msgl);
+
+       ipath_format_hwerrors(hwerrs,
+                             ipath_6110_hwerror_msgs,
+                             sizeof(ipath_6110_hwerror_msgs) /
+                             sizeof(ipath_6110_hwerror_msgs[0]),
+                             msg, msgl);
 
        if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS))
                hwerr_crcbits(dd, hwerrs, msg, msgl);
 
-       if (hwerrs & INFINIPATH_HWE_HTCMISCERR5)
-               strlcat(msg, "[HT core Misc5]", msgl);
-       if (hwerrs & INFINIPATH_HWE_HTCMISCERR6)
-               strlcat(msg, "[HT core Misc6]", msgl);
-       if (hwerrs & INFINIPATH_HWE_HTCMISCERR7)
-               strlcat(msg, "[HT core Misc7]", msgl);
        if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
                strlcat(msg, "[Memory BIST test failed, InfiniPath hardware unusable]",
                        msgl);
@@ -573,11 +586,6 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                                 dd->ipath_hwerrmask);
        }
 
-       if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
-               strlcat(msg, "[Rx Dsync]", msgl);
-       if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
-               strlcat(msg, "[SerDes PLL]", msgl);
-
        ipath_dev_err(dd, "%s hardware error\n", msg);
        if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)
                /*
@@ -742,7 +750,6 @@ static int ipath_setup_ht_reset(struct ipath_devdata *dd)
        return 0;
 }
 
-#define HT_CAPABILITY_ID   0x08        /* HT capabilities not defined in kernel */
 #define HT_INTR_DISC_CONFIG  0x80      /* HT interrupt and discovery cap */
 #define HT_INTR_REG_INDEX    2 /* intconfig requires indirect accesses */
 
@@ -973,7 +980,7 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
         * do this early, before we ever enable errors or hardware errors,
         * mostly to avoid causing the chip to enter freeze mode.
         */
-       pos = pci_find_capability(pdev, HT_CAPABILITY_ID);
+       pos = pci_find_capability(pdev, PCI_CAP_ID_HT);
        if (!pos) {
                ipath_dev_err(dd, "Couldn't find HyperTransport "
                              "capability; no interrupts\n");
@@ -996,7 +1003,7 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
                else if (cap_type == HT_INTR_DISC_CONFIG)
                        ihandler = set_int_handler(dd, pdev, pos);
        } while ((pos = pci_find_next_capability(pdev, pos,
-                                                HT_CAPABILITY_ID)));
+                                                PCI_CAP_ID_HT)));
 
        if (!ihandler) {
                ipath_dev_err(dd, "Couldn't find interrupt handler in "
@@ -1081,21 +1088,21 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
        ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
 }
 
-static void ipath_init_ht_variables(void)
+static void ipath_init_ht_variables(struct ipath_devdata *dd)
 {
-       ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
-       ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
-       ipath_gpio_sda = IPATH_GPIO_SDA;
-       ipath_gpio_scl = IPATH_GPIO_SCL;
+       dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+       dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+       dd->ipath_gpio_sda = IPATH_GPIO_SDA;
+       dd->ipath_gpio_scl = IPATH_GPIO_SCL;
 
-       infinipath_i_bitsextant =
+       dd->ipath_i_bitsextant =
                (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
                (INFINIPATH_I_RCVAVAIL_MASK <<
                 INFINIPATH_I_RCVAVAIL_SHIFT) |
                INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
                INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
 
-       infinipath_e_bitsextant =
+       dd->ipath_e_bitsextant =
                INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
                INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
                INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
@@ -1113,7 +1120,7 @@ static void ipath_init_ht_variables(void)
                INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
                INFINIPATH_E_HARDWARE;
 
-       infinipath_hwe_bitsextant =
+       dd->ipath_hwe_bitsextant =
                (INFINIPATH_HWE_HTCMEMPARITYERR_MASK <<
                 INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) |
                (INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
@@ -1142,8 +1149,8 @@ static void ipath_init_ht_variables(void)
                INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
                INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
 
-       infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
-       infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+       dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+       dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
 }
 
 /**
@@ -1608,5 +1615,5 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd)
         * do very early init that is needed before ipath_f_bus is
         * called
         */
-       ipath_init_ht_variables();
+       ipath_init_ht_variables(dd);
 }
index d86516d23df618ef369fb183a061a8f761228754..a72ab9de386a4e0e0d92ae04afa0cba1f7b8f3f7 100644 (file)
@@ -263,8 +263,8 @@ static const struct ipath_cregs ipath_pe_cregs = {
 };
 
 /* kr_intstatus, kr_intclear, kr_intmask bits */
-#define INFINIPATH_I_RCVURG_MASK 0x1F
-#define INFINIPATH_I_RCVAVAIL_MASK 0x1F
+#define INFINIPATH_I_RCVURG_MASK ((1U<<5)-1)
+#define INFINIPATH_I_RCVAVAIL_MASK ((1U<<5)-1)
 
 /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
 #define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK  0x000000000000003fULL
@@ -294,6 +294,33 @@ static const struct ipath_cregs ipath_pe_cregs = {
 #define IPATH_GPIO_SCL (1ULL << \
        (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
 
+/*
+ * Rev2 silicon allows suppressing check for ArmLaunch errors.
+ * this can speed up short packet sends on systems that do
+ * not guaranteee write-order.
+ */
+#define INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR (1ULL<<63)
+
+/* 6120 specific hardware errors... */
+static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
+       INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
+       INFINIPATH_HWE_MSG(PCIECPLTIMEOUT, "PCIe completion timeout"),
+       /*
+        * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
+        * parity or memory parity error failures, because most likely we
+        * won't be able to talk to the core of the chip.  Nonetheless, we
+        * might see them, if they are in parts of the PCIe core that aren't
+        * essential.
+        */
+       INFINIPATH_HWE_MSG(PCIE1PLLFAILED, "PCIePLL1"),
+       INFINIPATH_HWE_MSG(PCIE0PLLFAILED, "PCIePLL0"),
+       INFINIPATH_HWE_MSG(PCIEBUSPARITYXTLH, "PCIe XTLH core parity"),
+       INFINIPATH_HWE_MSG(PCIEBUSPARITYXADM, "PCIe ADM TX core parity"),
+       INFINIPATH_HWE_MSG(PCIEBUSPARITYRADM, "PCIe ADM RX core parity"),
+       INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),
+       INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),
+};
+
 /**
  * ipath_pe_handle_hwerrors - display hardware errors.
  * @dd: the infinipath device
@@ -343,19 +370,49 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
         * make sure we get this much out, unless told to be quiet,
         * or it's occurred within the last 5 seconds
         */
-       if ((hwerrs & ~dd->ipath_lasthwerror) ||
+       if ((hwerrs & ~(dd->ipath_lasthwerror |
+                       ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+                         INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+                        << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||
            (ipath_debug & __IPATH_VERBDBG))
                dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
                         "(cleared)\n", (unsigned long long) hwerrs);
        dd->ipath_lasthwerror |= hwerrs;
 
-       if (hwerrs & ~infinipath_hwe_bitsextant)
+       if (hwerrs & ~dd->ipath_hwe_bitsextant)
                ipath_dev_err(dd, "hwerror interrupt with unknown errors "
                              "%llx set\n", (unsigned long long)
-                             (hwerrs & ~infinipath_hwe_bitsextant));
+                             (hwerrs & ~dd->ipath_hwe_bitsextant));
 
        ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
        if (ctrl & INFINIPATH_C_FREEZEMODE) {
+               /*
+                * parity errors in send memory are recoverable,
+                * just cancel the send (if indicated in * sendbuffererror),
+                * count the occurrence, unfreeze (if no other handled
+                * hardware error bits are set), and continue. They can
+                * occur if a processor speculative read is done to the PIO
+                * buffer while we are sending a packet, for example.
+                */
+               if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+                              INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+                             << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+                       ipath_stats.sps_txeparity++;
+                       ipath_dbg("Recovering from TXE parity error (%llu), "
+                                 "hwerrstatus=%llx\n",
+                                 (unsigned long long) ipath_stats.sps_txeparity,
+                                 (unsigned long long) hwerrs);
+                       ipath_disarm_senderrbufs(dd);
+                       hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+                                    INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+                                   << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT);
+                       if (!hwerrs) { /* else leave in freeze mode */
+                               ipath_write_kreg(dd,
+                                                dd->ipath_kregs->kr_control,
+                                                dd->ipath_control);
+                           return;
+                       }
+               }
                if (hwerrs) {
                        /*
                         * if any set that we aren't ignoring only make the
@@ -379,9 +436,8 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                } else {
                        ipath_dbg("Clearing freezemode on ignored hardware "
                                  "error\n");
-                       ctrl &= ~INFINIPATH_C_FREEZEMODE;
                        ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-                                        ctrl);
+                                        dd->ipath_control);
                }
        }
 
@@ -396,24 +452,13 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
                                 dd->ipath_hwerrmask);
        }
-       if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
-                     << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
-               bits = (u32) ((hwerrs >>
-                              INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
-                             INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
-               snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
-                        bits);
-               strlcat(msg, bitsmsg, msgl);
-       }
-       if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
-                     << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
-               bits = (u32) ((hwerrs >>
-                              INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
-                             INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
-               snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
-                        bits);
-               strlcat(msg, bitsmsg, msgl);
-       }
+
+       ipath_format_hwerrors(hwerrs,
+                             ipath_6120_hwerror_msgs,
+                             sizeof(ipath_6120_hwerror_msgs)/
+                             sizeof(ipath_6120_hwerror_msgs[0]),
+                             msg, msgl);
+
        if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK
                      << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {
                bits = (u32) ((hwerrs >>
@@ -423,10 +468,6 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                         "[PCIe Mem Parity Errs %x] ", bits);
                strlcat(msg, bitsmsg, msgl);
        }
-       if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
-               strlcat(msg, "[IB2IPATH Parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
-               strlcat(msg, "[IPATH2IB Parity]", msgl);
 
 #define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP |       \
                         INFINIPATH_HWE_COREPLL_RFSLIP )
@@ -452,34 +493,6 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
                                 dd->ipath_hwerrmask);
        }
 
-       if (hwerrs & INFINIPATH_HWE_PCIEPOISONEDTLP)
-               strlcat(msg, "[PCIe Poisoned TLP]", msgl);
-       if (hwerrs & INFINIPATH_HWE_PCIECPLTIMEOUT)
-               strlcat(msg, "[PCIe completion timeout]", msgl);
-
-       /*
-        * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
-        * parity or memory parity error failures, because most likely we
-        * won't be able to talk to the core of the chip.  Nonetheless, we
-        * might see them, if they are in parts of the PCIe core that aren't
-        * essential.
-        */
-       if (hwerrs & INFINIPATH_HWE_PCIE1PLLFAILED)
-               strlcat(msg, "[PCIePLL1]", msgl);
-       if (hwerrs & INFINIPATH_HWE_PCIE0PLLFAILED)
-               strlcat(msg, "[PCIePLL0]", msgl);
-       if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXTLH)
-               strlcat(msg, "[PCIe XTLH core parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXADM)
-               strlcat(msg, "[PCIe ADM TX core parity]", msgl);
-       if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYRADM)
-               strlcat(msg, "[PCIe ADM RX core parity]", msgl);
-
-       if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
-               strlcat(msg, "[Rx Dsync]", msgl);
-       if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
-               strlcat(msg, "[SerDes PLL]", msgl);
-
        ipath_dev_err(dd, "%s hardware error\n", msg);
        if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {
                /*
@@ -525,6 +538,9 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
        case 5:
                n = "InfiniPath_QMH7140";
                break;
+       case 6:
+               n = "InfiniPath_QLE7142";
+               break;
        default:
                ipath_dev_err(dd,
                              "Don't yet know about board with ID %u\n",
@@ -571,9 +587,12 @@ static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
        if (!dd->ipath_boardrev)        // no PLL for Emulator
                val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
 
-       /* workaround bug 9460 in internal interface bus parity checking */
-       val &= ~INFINIPATH_HWE_PCIEBUSPARITYRADM;
-
+       if (dd->ipath_minrev < 2) {
+               /* workaround bug 9460 in internal interface bus parity
+                * checking. Fixed (HW bug 9490) in Rev2.
+                */
+               val &= ~INFINIPATH_HWE_PCIEBUSPARITYRADM;
+       }
        dd->ipath_hwerrmask = val;
 }
 
@@ -583,8 +602,8 @@ static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
  */
 static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
 {
-       u64 val, tmp, config1;
-       int ret = 0, change = 0;
+       u64 val, tmp, config1, prev_val;
+       int ret = 0;
 
        ipath_dbg("Trying to bringup serdes\n");
 
@@ -641,6 +660,7 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
 
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+       prev_val = val;
        if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
             INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
                val &=
@@ -648,11 +668,9 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
                          INFINIPATH_XGXS_MDIOADDR_SHIFT);
                /* MDIO address 3 */
                val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
-               change = 1;
        }
        if (val & INFINIPATH_XGXS_RESET) {
                val &= ~INFINIPATH_XGXS_RESET;
-               change = 1;
        }
        if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &
             INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {
@@ -661,9 +679,19 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
                         INFINIPATH_XGXS_RX_POL_SHIFT);
                val |= dd->ipath_rx_pol_inv <<
                        INFINIPATH_XGXS_RX_POL_SHIFT;
-               change = 1;
        }
-       if (change)
+       if (dd->ipath_minrev >= 2) {
+               /* Rev 2. can tolerate multiple writes to PBC, and
+                * allowing them can provide lower latency on some
+                * CPUs, but this feature is off by default, only
+                * turned on by setting D63 of XGXSconfig reg.
+                * May want to make this conditional more
+                * fine-grained in future. This is not exactly
+                * related to XGXS, but where the bit ended up.
+                */
+               val |= INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR;
+       }
+       if (val != prev_val)
                ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
 
        val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
@@ -717,9 +745,25 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
        ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
 }
 
-/* this is not yet needed on this chip, so just return 0. */
 static int ipath_pe_intconfig(struct ipath_devdata *dd)
 {
+       u64 val;
+       u32 chiprev;
+
+       /*
+        * If the chip supports added error indication via GPIO pins,
+        * enable interrupts on those bits so the interrupt routine
+        * can count the events. Also set flag so interrupt routine
+        * can know they are expected.
+        */
+       chiprev = dd->ipath_revision >> INFINIPATH_R_CHIPREVMINOR_SHIFT;
+       if ((chiprev & INFINIPATH_R_CHIPREVMINOR_MASK) > 1) {
+               /* Rev2+ reports extra errors via internal GPIO pins */
+               dd->ipath_flags |= IPATH_GPIO_ERRINTRS;
+               val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
+               val |= IPATH_GPIO_ERRINTR_MASK;
+               ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+       }
        return 0;
 }
 
@@ -853,21 +897,23 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
        return 0;
 }
 
-static void ipath_init_pe_variables(void)
+static void ipath_init_pe_variables(struct ipath_devdata *dd)
 {
        /*
         * bits for selecting i2c direction and values,
         * used for I2C serial flash
         */
-       ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
-       ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
-       ipath_gpio_sda = IPATH_GPIO_SDA;
-       ipath_gpio_scl = IPATH_GPIO_SCL;
+       dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+       dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+       dd->ipath_gpio_sda = IPATH_GPIO_SDA;
+       dd->ipath_gpio_scl = IPATH_GPIO_SCL;
 
        /* variables for sanity checking interrupt and errors */
-       infinipath_hwe_bitsextant =
+       dd->ipath_hwe_bitsextant =
                (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
                 INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+               (INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+                INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |
                (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<
                 INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |
                INFINIPATH_HWE_PCIE1PLLFAILED |
@@ -883,13 +929,13 @@ static void ipath_init_pe_variables(void)
                INFINIPATH_HWE_SERDESPLLFAILED |
                INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
                INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
-       infinipath_i_bitsextant =
+       dd->ipath_i_bitsextant =
                (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
                (INFINIPATH_I_RCVAVAIL_MASK <<
                 INFINIPATH_I_RCVAVAIL_SHIFT) |
                INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
                INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
-       infinipath_e_bitsextant =
+       dd->ipath_e_bitsextant =
                INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
                INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
                INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
@@ -907,8 +953,8 @@ static void ipath_init_pe_variables(void)
                INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
                INFINIPATH_E_HARDWARE;
 
-       infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
-       infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+       dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+       dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
 }
 
 /* setup the MSI stuff again after a reset.  I'd like to just call
@@ -1082,6 +1128,45 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
        mmiowb();
        spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);
 }
+/**
+ * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher
+ * @dd: the infinipath device
+ * @tidptr: pointer to the expected TID (in chip) to udpate
+ * @tidtype: 0 for eager, 1 for expected
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for selection of the
+ * appropriate "flavor". The static calls in cleanup just use the
+ * revision-agnostic form, as they are not performance critical.
+ */
+static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+                            u32 type, unsigned long pa)
+{
+       u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
+
+       if (pa != dd->ipath_tidinvalid) {
+               if (pa & ((1U << 11) - 1)) {
+                       dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
+                                "not 2KB aligned!\n", pa);
+                       return;
+               }
+               pa >>= 11;
+               /* paranoia check */
+               if (pa & (7<<29))
+                       ipath_dev_err(dd,
+                                     "BUG: Physical page address 0x%lx "
+                                     "has bits set in 31-29\n", pa);
+
+               if (type == 0)
+                       pa |= dd->ipath_tidtemplate;
+               else /* for now, always full 4KB page */
+                       pa |= 2 << 29;
+       }
+       if (dd->ipath_kregbase)
+               writel(pa, tidp32);
+       mmiowb();
+}
+
 
 /**
  * ipath_pe_clear_tid - clear all TID entries for a port, expected and eager
@@ -1203,7 +1288,7 @@ int __attribute__((weak)) ipath_unordered_wc(void)
 
 /**
  * ipath_init_pe_get_base_info - set chip-specific flags for user code
- * @dd: the infinipath device
+ * @pd: the infinipath port
  * @kbase: ipath_base_info pointer
  *
  * We set the PCIE flag because the lower bandwidth on PCIe vs
@@ -1212,6 +1297,7 @@ int __attribute__((weak)) ipath_unordered_wc(void)
 static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
 {
        struct ipath_base_info *kinfo = kbase;
+       struct ipath_devdata *dd;
 
        if (ipath_unordered_wc()) {
                kinfo->spi_runtime_flags |= IPATH_RUNTIME_FORCE_WC_ORDER;
@@ -1220,8 +1306,20 @@ static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
        else
                ipath_cdbg(PROC, "Not Intel processor, WC ordered\n");
 
-       kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
+       if (pd == NULL)
+               goto done;
 
+       dd = pd->port_dd;
+
+       if (dd != NULL && dd->ipath_minrev >= 2) {
+               ipath_cdbg(PROC, "IBA6120 Rev2, allow multiple PBC write\n");
+               kinfo->spi_runtime_flags |= IPATH_RUNTIME_PBC_REWRITE;
+               ipath_cdbg(PROC, "IBA6120 Rev2, allow loose DMA alignment\n");
+               kinfo->spi_runtime_flags |= IPATH_RUNTIME_LOOSE_DMA_ALIGN;
+       }
+
+done:
+       kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
        return 0;
 }
 
@@ -1244,7 +1342,10 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
        dd->ipath_f_quiet_serdes = ipath_pe_quiet_serdes;
        dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
        dd->ipath_f_clear_tids = ipath_pe_clear_tids;
-       dd->ipath_f_put_tid = ipath_pe_put_tid;
+       if (dd->ipath_minrev >= 2)
+               dd->ipath_f_put_tid = ipath_pe_put_tid_2;
+       else
+               dd->ipath_f_put_tid = ipath_pe_put_tid;
        dd->ipath_f_cleanup = ipath_setup_pe_cleanup;
        dd->ipath_f_setextled = ipath_setup_pe_setextled;
        dd->ipath_f_get_base_info = ipath_pe_get_base_info;
@@ -1259,6 +1360,6 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
        dd->ipath_kregs = &ipath_pe_kregs;
        dd->ipath_cregs = &ipath_pe_cregs;
 
-       ipath_init_pe_variables();
+       ipath_init_pe_variables(dd);
 }
 
index 44669dc2e22d1c502ce95503a19ed8f2f0fdb8ce..d819cca524cd9ac2260e24ee438ac131a9273eb0 100644 (file)
@@ -88,13 +88,13 @@ MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver");
 static int create_port0_egr(struct ipath_devdata *dd)
 {
        unsigned e, egrcnt;
-       struct sk_buff **skbs;
+       struct ipath_skbinfo *skbinfo;
        int ret;
 
        egrcnt = dd->ipath_rcvegrcnt;
 
-       skbs = vmalloc(sizeof(*dd->ipath_port0_skbs) * egrcnt);
-       if (skbs == NULL) {
+       skbinfo = vmalloc(sizeof(*dd->ipath_port0_skbinfo) * egrcnt);
+       if (skbinfo == NULL) {
                ipath_dev_err(dd, "allocation error for eager TID "
                              "skb array\n");
                ret = -ENOMEM;
@@ -109,13 +109,13 @@ static int create_port0_egr(struct ipath_devdata *dd)
                 * 4 bytes so that the data buffer stays word aligned.
                 * See ipath_kreceive() for more details.
                 */
-               skbs[e] = ipath_alloc_skb(dd, GFP_KERNEL);
-               if (!skbs[e]) {
+               skbinfo[e].skb = ipath_alloc_skb(dd, GFP_KERNEL);
+               if (!skbinfo[e].skb) {
                        ipath_dev_err(dd, "SKB allocation error for "
                                      "eager TID %u\n", e);
                        while (e != 0)
-                               dev_kfree_skb(skbs[--e]);
-                       vfree(skbs);
+                               dev_kfree_skb(skbinfo[--e].skb);
+                       vfree(skbinfo);
                        ret = -ENOMEM;
                        goto bail;
                }
@@ -124,14 +124,17 @@ static int create_port0_egr(struct ipath_devdata *dd)
         * After loop above, so we can test non-NULL to see if ready
         * to use at receive, etc.
         */
-       dd->ipath_port0_skbs = skbs;
+       dd->ipath_port0_skbinfo = skbinfo;
 
        for (e = 0; e < egrcnt; e++) {
-               unsigned long phys =
-                       virt_to_phys(dd->ipath_port0_skbs[e]->data);
+               dd->ipath_port0_skbinfo[e].phys =
+                 ipath_map_single(dd->pcidev,
+                                  dd->ipath_port0_skbinfo[e].skb->data,
+                                  dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE);
                dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
                                    ((char __iomem *) dd->ipath_kregbase +
-                                    dd->ipath_rcvegrbase), 0, phys);
+                                    dd->ipath_rcvegrbase), 0,
+                                   dd->ipath_port0_skbinfo[e].phys);
        }
 
        ret = 0;
@@ -432,16 +435,33 @@ done:
  */
 static void init_shadow_tids(struct ipath_devdata *dd)
 {
-       dd->ipath_pageshadow = (struct page **)
-               vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+       struct page **pages;
+       dma_addr_t *addrs;
+
+       pages = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
                        sizeof(struct page *));
-       if (!dd->ipath_pageshadow)
+       if (!pages) {
                ipath_dev_err(dd, "failed to allocate shadow page * "
                              "array, no expected sends!\n");
-       else
-               memset(dd->ipath_pageshadow, 0,
-                      dd->ipath_cfgports * dd->ipath_rcvtidcnt *
-                      sizeof(struct page *));
+               dd->ipath_pageshadow = NULL;
+               return;
+       }
+
+       addrs = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+                       sizeof(dma_addr_t));
+       if (!addrs) {
+               ipath_dev_err(dd, "failed to allocate shadow dma handle "
+                             "array, no expected sends!\n");
+               vfree(dd->ipath_pageshadow);
+               dd->ipath_pageshadow = NULL;
+               return;
+       }
+
+       memset(pages, 0, dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+              sizeof(struct page *));
+
+       dd->ipath_pageshadow = pages;
+       dd->ipath_physshadow = addrs;
 }
 
 static void enable_chip(struct ipath_devdata *dd,
index 49bf7bb15b04b2628f52bf10df0b0366c574a3b7..6bee53ce5f334a84352847ce014c9a3d2502f322 100644 (file)
 #include "ipath_verbs.h"
 #include "ipath_common.h"
 
+/*
+ * Called when we might have an error that is specific to a particular
+ * PIO buffer, and may need to cancel that buffer, so it can be re-used.
+ */
+void ipath_disarm_senderrbufs(struct ipath_devdata *dd)
+{
+       u32 piobcnt;
+       unsigned long sbuf[4];
+       /*
+        * it's possible that sendbuffererror could have bits set; might
+        * have already done this as a result of hardware error handling
+        */
+       piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+       /* read these before writing errorclear */
+       sbuf[0] = ipath_read_kreg64(
+               dd, dd->ipath_kregs->kr_sendbuffererror);
+       sbuf[1] = ipath_read_kreg64(
+               dd, dd->ipath_kregs->kr_sendbuffererror + 1);
+       if (piobcnt > 128) {
+               sbuf[2] = ipath_read_kreg64(
+                       dd, dd->ipath_kregs->kr_sendbuffererror + 2);
+               sbuf[3] = ipath_read_kreg64(
+                       dd, dd->ipath_kregs->kr_sendbuffererror + 3);
+       }
+
+       if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+               int i;
+               if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG)) {
+                       __IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG,
+                                         "SendbufErrs %lx %lx", sbuf[0],
+                                         sbuf[1]);
+                       if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128)
+                               printk(" %lx %lx ", sbuf[2], sbuf[3]);
+                       printk("\n");
+               }
+
+               for (i = 0; i < piobcnt; i++)
+                       if (test_bit(i, sbuf))
+                               ipath_disarm_piobufs(dd, i, 1);
+               dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */
+       }
+}
+
+
 /* These are all rcv-related errors which we want to count for stats */
 #define E_SUM_PKTERRS \
        (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \
 
 static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs)
 {
-       unsigned long sbuf[4];
        u64 ignore_this_time = 0;
-       u32 piobcnt;
 
-       /* if possible that sendbuffererror could be valid */
-       piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
-       /* read these before writing errorclear */
-       sbuf[0] = ipath_read_kreg64(
-               dd, dd->ipath_kregs->kr_sendbuffererror);
-       sbuf[1] = ipath_read_kreg64(
-               dd, dd->ipath_kregs->kr_sendbuffererror + 1);
-       if (piobcnt > 128) {
-               sbuf[2] = ipath_read_kreg64(
-                       dd, dd->ipath_kregs->kr_sendbuffererror + 2);
-               sbuf[3] = ipath_read_kreg64(
-                       dd, dd->ipath_kregs->kr_sendbuffererror + 3);
-       }
-
-       if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
-               int i;
-
-               ipath_cdbg(PKT, "SendbufErrs %lx %lx ", sbuf[0], sbuf[1]);
-               if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128)
-                       printk("%lx %lx ", sbuf[2], sbuf[3]);
-               for (i = 0; i < piobcnt; i++) {
-                       if (test_bit(i, sbuf)) {
-                               u32 __iomem *piobuf;
-                               if (i < dd->ipath_piobcnt2k)
-                                       piobuf = (u32 __iomem *)
-                                               (dd->ipath_pio2kbase +
-                                                i * dd->ipath_palign);
-                               else
-                                       piobuf = (u32 __iomem *)
-                                               (dd->ipath_pio4kbase +
-                                                (i - dd->ipath_piobcnt2k) *
-                                                dd->ipath_4kalign);
-
-                               ipath_cdbg(PKT,
-                                          "PIObuf[%u] @%p pbc is %x; ",
-                                          i, piobuf, readl(piobuf));
-
-                               ipath_disarm_piobufs(dd, i, 1);
-                       }
-               }
-               if (ipath_debug & __IPATH_PKTDBG)
-                       printk("\n");
-       }
+       ipath_disarm_senderrbufs(dd);
        if ((errs & E_SUM_LINK_PKTERRS) &&
            !(dd->ipath_flags & IPATH_LINKACTIVE)) {
                /*
@@ -132,6 +132,82 @@ static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs)
        return ignore_this_time;
 }
 
+/* generic hw error messages... */
+#define INFINIPATH_HWE_TXEMEMPARITYERR_MSG(a) \
+       { \
+               .mask = ( INFINIPATH_HWE_TXEMEMPARITYERR_##a <<    \
+                         INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT ),   \
+               .msg = "TXE " #a " Memory Parity"            \
+       }
+#define INFINIPATH_HWE_RXEMEMPARITYERR_MSG(a) \
+       { \
+               .mask = ( INFINIPATH_HWE_RXEMEMPARITYERR_##a <<    \
+                         INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT ),   \
+               .msg = "RXE " #a " Memory Parity"            \
+       }
+
+static const struct ipath_hwerror_msgs ipath_generic_hwerror_msgs[] = {
+       INFINIPATH_HWE_MSG(IBCBUSFRSPCPARITYERR, "IPATH2IB Parity"),
+       INFINIPATH_HWE_MSG(IBCBUSTOSPCPARITYERR, "IB2IPATH Parity"),
+
+       INFINIPATH_HWE_TXEMEMPARITYERR_MSG(PIOBUF),
+       INFINIPATH_HWE_TXEMEMPARITYERR_MSG(PIOPBC),
+       INFINIPATH_HWE_TXEMEMPARITYERR_MSG(PIOLAUNCHFIFO),
+
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(RCVBUF),
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(LOOKUPQ),
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(EAGERTID),
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(EXPTID),
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(FLAGBUF),
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(DATAINFO),
+       INFINIPATH_HWE_RXEMEMPARITYERR_MSG(HDRINFO),
+};
+
+/**
+ * ipath_format_hwmsg - format a single hwerror message
+ * @msg message buffer
+ * @msgl length of message buffer
+ * @hwmsg message to add to message buffer
+ */
+static void ipath_format_hwmsg(char *msg, size_t msgl, const char *hwmsg)
+{
+       strlcat(msg, "[", msgl);
+       strlcat(msg, hwmsg, msgl);
+       strlcat(msg, "]", msgl);
+}
+
+/**
+ * ipath_format_hwerrors - format hardware error messages for display
+ * @hwerrs hardware errors bit vector
+ * @hwerrmsgs hardware error descriptions
+ * @nhwerrmsgs number of hwerrmsgs
+ * @msg message buffer
+ * @msgl message buffer length
+ */
+void ipath_format_hwerrors(u64 hwerrs,
+                          const struct ipath_hwerror_msgs *hwerrmsgs,
+                          size_t nhwerrmsgs,
+                          char *msg, size_t msgl)
+{
+       int i;
+       const int glen =
+           sizeof(ipath_generic_hwerror_msgs) /
+           sizeof(ipath_generic_hwerror_msgs[0]);
+
+       for (i=0; i<glen; i++) {
+               if (hwerrs & ipath_generic_hwerror_msgs[i].mask) {
+                       ipath_format_hwmsg(msg, msgl,
+                                          ipath_generic_hwerror_msgs[i].msg);
+               }
+       }
+
+       for (i=0; i<nhwerrmsgs; i++) {
+               if (hwerrs & hwerrmsgs[i].mask) {
+                       ipath_format_hwmsg(msg, msgl, hwerrmsgs[i].msg);
+               }
+       }
+}
+
 /* return the strings for the most common link states */
 static char *ib_linkstate(u32 linkstate)
 {
@@ -404,10 +480,10 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
        }
 
-       if (!noprint && (errs & ~infinipath_e_bitsextant))
+       if (!noprint && (errs & ~dd->ipath_e_bitsextant))
                ipath_dev_err(dd, "error interrupt with unknown errors "
                              "%llx set\n", (unsigned long long)
-                             (errs & ~infinipath_e_bitsextant));
+                             (errs & ~dd->ipath_e_bitsextant));
 
        if (errs & E_SUM_ERRS)
                ignore_this_time = handle_e_sum_errs(dd, errs);
@@ -478,6 +554,14 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                        ~(INFINIPATH_E_HARDWARE |
                          INFINIPATH_E_IBSTATUSCHANGED);
        }
+
+       /* likely due to cancel, so suppress */
+       if ((errs & (INFINIPATH_E_SPKTLEN | INFINIPATH_E_SPIOARMLAUNCH)) &&
+               dd->ipath_lastcancel > jiffies) {
+               ipath_dbg("Suppressed armlaunch/spktlen after error send cancel\n");
+               errs &= ~(INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SPKTLEN);
+       }
+
        if (!errs)
                return 0;
 
@@ -529,7 +613,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
                                 * don't report same point multiple times,
                                 * except kernel
                                 */
-                               tl = (u32) * pd->port_rcvhdrtail_kvaddr;
+                               tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
                                if (tl == dd->ipath_lastrcvhdrqtails[i])
                                        continue;
                                hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
@@ -729,9 +813,9 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
        int rcvdint = 0;
 
        portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
-                infinipath_i_rcvavail_mask)
+                dd->ipath_i_rcvavail_mask)
                | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
-                  infinipath_i_rcvurg_mask);
+                  dd->ipath_i_rcvurg_mask);
        for (i = 1; i < dd->ipath_cfgports; i++) {
                struct ipath_portdata *pd = dd->ipath_pd[i];
                if (portr & (1 << i) && pd && pd->port_cnt &&
@@ -808,7 +892,7 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
        if (oldhead != curtail) {
                if (dd->ipath_flags & IPATH_GPIO_INTR) {
                        ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
-                                        (u64) (1 << 2));
+                                        (u64) (1 << IPATH_GPIO_PORT0_BIT));
                        istat = port0rbits | INFINIPATH_I_GPIO;
                }
                else
@@ -838,10 +922,10 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
        if (unexpected)
                unexpected = 0;
 
-       if (unlikely(istat & ~infinipath_i_bitsextant))
+       if (unlikely(istat & ~dd->ipath_i_bitsextant))
                ipath_dev_err(dd,
                              "interrupt with unknown interrupts %x set\n",
-                             istat & (u32) ~ infinipath_i_bitsextant);
+                             istat & (u32) ~ dd->ipath_i_bitsextant);
        else
                ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
 
@@ -867,26 +951,80 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
 
        if (istat & INFINIPATH_I_GPIO) {
                /*
-                * Packets are available in the port 0 rcv queue.
-                * Eventually this needs to be generalized to check
-                * IPATH_GPIO_INTR, and the specific GPIO bit, if
-                * GPIO interrupts are used for anything else.
+                * GPIO interrupts fall in two broad classes:
+                * GPIO_2 indicates (on some HT4xx boards) that a packet
+                *        has arrived for Port 0. Checking for this
+                *        is controlled by flag IPATH_GPIO_INTR.
+                * GPIO_3..5 on IBA6120 Rev2 chips indicate errors
+                *        that we need to count. Checking for this
+                *        is controlled by flag IPATH_GPIO_ERRINTRS.
                 */
-               if (unlikely(!(dd->ipath_flags & IPATH_GPIO_INTR))) {
-                       u32 gpiostatus;
-                       gpiostatus = ipath_read_kreg32(
-                               dd, dd->ipath_kregs->kr_gpio_status);
-                       ipath_dbg("Unexpected GPIO interrupt bits %x\n",
-                                 gpiostatus);
-                       ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
-                                        gpiostatus);
+               u32 gpiostatus;
+               u32 to_clear = 0;
+
+               gpiostatus = ipath_read_kreg32(
+                       dd, dd->ipath_kregs->kr_gpio_status);
+               /* First the error-counter case.
+                */
+               if ((gpiostatus & IPATH_GPIO_ERRINTR_MASK) &&
+                   (dd->ipath_flags & IPATH_GPIO_ERRINTRS)) {
+                       /* want to clear the bits we see asserted. */
+                       to_clear |= (gpiostatus & IPATH_GPIO_ERRINTR_MASK);
+
+                       /*
+                        * Count appropriately, clear bits out of our copy,
+                        * as they have been "handled".
+                        */
+                       if (gpiostatus & (1 << IPATH_GPIO_RXUVL_BIT)) {
+                               ipath_dbg("FlowCtl on UnsupVL\n");
+                               dd->ipath_rxfc_unsupvl_errs++;
+                       }
+                       if (gpiostatus & (1 << IPATH_GPIO_OVRUN_BIT)) {
+                               ipath_dbg("Overrun Threshold exceeded\n");
+                               dd->ipath_overrun_thresh_errs++;
+                       }
+                       if (gpiostatus & (1 << IPATH_GPIO_LLI_BIT)) {
+                               ipath_dbg("Local Link Integrity error\n");
+                               dd->ipath_lli_errs++;
+                       }
+                       gpiostatus &= ~IPATH_GPIO_ERRINTR_MASK;
                }
-               else {
-                       /* Clear GPIO status bit 2 */
-                       ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
-                                       (u64) (1 << 2));
+               /* Now the Port0 Receive case */
+               if ((gpiostatus & (1 << IPATH_GPIO_PORT0_BIT)) &&
+                   (dd->ipath_flags & IPATH_GPIO_INTR)) {
+                       /*
+                        * GPIO status bit 2 is set, and we expected it.
+                        * clear it and indicate in p0bits.
+                        * This probably only happens if a Port0 pkt
+                        * arrives at _just_ the wrong time, and we
+                        * handle that by seting chk0rcv;
+                        */
+                       to_clear |= (1 << IPATH_GPIO_PORT0_BIT);
+                       gpiostatus &= ~(1 << IPATH_GPIO_PORT0_BIT);
                        chk0rcv = 1;
                }
+               if (unlikely(gpiostatus)) {
+                       /*
+                        * Some unexpected bits remain. If they could have
+                        * caused the interrupt, complain and clear.
+                        * MEA: this is almost certainly non-ideal.
+                        * we should look into auto-disable of unexpected
+                        * GPIO interrupts, possibly on a "three strikes"
+                        * basis.
+                        */
+                       u32 mask;
+                       mask = ipath_read_kreg32(
+                               dd, dd->ipath_kregs->kr_gpio_mask);
+                       if (mask & gpiostatus) {
+                               ipath_dbg("Unexpected GPIO IRQ bits %x\n",
+                                 gpiostatus & mask);
+                               to_clear |= (gpiostatus & mask);
+                       }
+               }
+               if (to_clear) {
+                       ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+                                       (u64) to_clear);
+               }
        }
        chk0rcv |= istat & port0rbits;
 
@@ -911,9 +1049,9 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
                istat &= ~port0rbits;
        }
 
-       if (istat & ((infinipath_i_rcvavail_mask <<
+       if (istat & ((dd->ipath_i_rcvavail_mask <<
                      INFINIPATH_I_RCVAVAIL_SHIFT)
-                    | (infinipath_i_rcvurg_mask <<
+                    | (dd->ipath_i_rcvurg_mask <<
                        INFINIPATH_I_RCVURG_SHIFT)))
                handle_urcv(dd, istat);
 
index a8a56276ff1dbe6dd591a8756f8f0171a8d24063..d7540b71b451b624dd580deb7c074a61c61dbe6f 100644 (file)
@@ -39,6 +39,8 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 
 #include "ipath_common.h"
@@ -62,7 +64,7 @@ struct ipath_portdata {
        /* rcvhdrq base, needs mmap before useful */
        void *port_rcvhdrq;
        /* kernel virtual address where hdrqtail is updated */
-       volatile __le64 *port_rcvhdrtail_kvaddr;
+       void *port_rcvhdrtail_kvaddr;
        /*
         * temp buffer for expected send setup, allocated at open, instead
         * of each setup call
@@ -79,8 +81,8 @@ struct ipath_portdata {
        dma_addr_t port_rcvhdrq_phys;
        dma_addr_t port_rcvhdrqtailaddr_phys;
        /*
-        * number of opens on this instance (0 or 1; ignoring forks, dup,
-        * etc. for now)
+        * number of opens (including slave subports) on this instance
+        * (ignoring forks, dup, etc. for now)
         */
        int port_cnt;
        /*
@@ -89,6 +91,10 @@ struct ipath_portdata {
         */
        /* instead of calculating it */
        unsigned port_port;
+       /* non-zero if port is being shared. */
+       u16 port_subport_cnt;
+       /* non-zero if port is being shared. */
+       u16 port_subport_id;
        /* chip offset of PIO buffers for this port */
        u32 port_piobufs;
        /* how many alloc_pages() chunks in port_rcvegrbuf_pages */
@@ -121,6 +127,16 @@ struct ipath_portdata {
        u16 port_pkeys[4];
        /* so file ops can get at unit */
        struct ipath_devdata *port_dd;
+       /* A page of memory for rcvhdrhead, rcvegrhead, rcvegrtail * N */
+       void *subport_uregbase;
+       /* An array of pages for the eager receive buffers * N */
+       void *subport_rcvegrbuf;
+       /* An array of pages for the eager header queue entries * N */
+       void *subport_rcvhdr_base;
+       /* The version of the library which opened this port */
+       u32 userversion;
+       /* Bitmask of active slaves */
+       u32 active_slaves;
 };
 
 struct sk_buff;
@@ -132,6 +148,11 @@ struct _ipath_layer {
        void *l_arg;
 };
 
+struct ipath_skbinfo {
+       struct sk_buff *skb;
+       dma_addr_t phys;
+};
+
 struct ipath_devdata {
        struct list_head ipath_list;
 
@@ -154,7 +175,7 @@ struct ipath_devdata {
        /* ipath_cfgports pointers */
        struct ipath_portdata **ipath_pd;
        /* sk_buffs used by port 0 eager receive queue */
-       struct sk_buff **ipath_port0_skbs;
+       struct ipath_skbinfo *ipath_port0_skbinfo;
        /* kvirt address of 1st 2k pio buffer */
        void __iomem *ipath_pio2kbase;
        /* kvirt address of 1st 4k pio buffer */
@@ -315,12 +336,16 @@ struct ipath_devdata {
        u8 ipath_ht_slave_off;
        /* for write combining settings */
        unsigned long ipath_wc_cookie;
+       unsigned long ipath_wc_base;
+       unsigned long ipath_wc_len;
        /* ref count for each pkey */
        atomic_t ipath_pkeyrefs[4];
        /* shadow copy of all exptids physaddr; used only by funcsim */
        u64 *ipath_tidsimshadow;
        /* shadow copy of struct page *'s for exp tid pages */
        struct page **ipath_pageshadow;
+       /* shadow copy of dma handles for exp tid pages */
+       dma_addr_t *ipath_physshadow;
        /* lock to workaround chip bug 9437 */
        spinlock_t ipath_tid_lock;
 
@@ -402,6 +427,9 @@ struct ipath_devdata {
        unsigned long ipath_rcvctrl;
        /* shadow kr_sendctrl */
        unsigned long ipath_sendctrl;
+       /* ports waiting for PIOavail intr */
+       unsigned long ipath_portpiowait;
+       unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
 
        /* value we put in kr_rcvhdrcnt */
        u32 ipath_rcvhdrcnt;
@@ -465,8 +493,6 @@ struct ipath_devdata {
        u32 ipath_htwidth;
        /* HT speed (200,400,800,1000) from HT config */
        u32 ipath_htspeed;
-       /* ports waiting for PIOavail intr */
-       unsigned long ipath_portpiowait;
        /*
         * number of sequential ibcstatus change for polling active/quiet
         * (i.e., link not coming up).
@@ -510,8 +536,47 @@ struct ipath_devdata {
        u32 ipath_lli_counter;
        /* local link integrity errors */
        u32 ipath_lli_errors;
+       /*
+        * Above counts only cases where _successive_ LocalLinkIntegrity
+        * errors were seen in the receive headers of kern-packets.
+        * Below are the three (monotonically increasing) counters
+        * maintained via GPIO interrupts on iba6120-rev2.
+        */
+       u32 ipath_rxfc_unsupvl_errs;
+       u32 ipath_overrun_thresh_errs;
+       u32 ipath_lli_errs;
+
+       /*
+        * Not all devices managed by a driver instance are the same
+        * type, so these fields must be per-device.
+        */
+       u64 ipath_i_bitsextant;
+       ipath_err_t ipath_e_bitsextant;
+       ipath_err_t ipath_hwe_bitsextant;
+
+       /*
+        * Below should be computable from number of ports,
+        * since they are never modified.
+        */
+       u32 ipath_i_rcvavail_mask;
+       u32 ipath_i_rcvurg_mask;
+
+       /*
+        * Register bits for selecting i2c direction and values, used for
+        * I2C serial flash.
+        */
+       u16 ipath_gpio_sda_num;
+       u16 ipath_gpio_scl_num;
+       u64 ipath_gpio_sda;
+       u64 ipath_gpio_scl;
 };
 
+/* Private data for file operations */
+struct ipath_filedata {
+       struct ipath_portdata *pd;
+       unsigned subport;
+       unsigned tidcursor;
+};
 extern struct list_head ipath_dev_list;
 extern spinlock_t ipath_devs_lock;
 extern struct ipath_devdata *ipath_lookup(int unit);
@@ -521,6 +586,7 @@ int ipath_enable_wc(struct ipath_devdata *dd);
 void ipath_disable_wc(struct ipath_devdata *dd);
 int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
 void ipath_shutdown_device(struct ipath_devdata *);
+void ipath_disarm_senderrbufs(struct ipath_devdata *);
 
 struct file_operations;
 int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
@@ -572,7 +638,11 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8);
 int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
 
 /* for use in system calls, where we want to know device type, etc. */
-#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
+#define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
+#define subport_fp(fp) \
+       ((struct ipath_filedata *)(fp)->private_data)->subport
+#define tidcursor_fp(fp) \
+       ((struct ipath_filedata *)(fp)->private_data)->tidcursor
 
 /*
  * values for ipath_flags
@@ -612,6 +682,15 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
                /* can miss port0 rx interrupts */
 #define IPATH_POLL_RX_INTR  0x40000
 #define IPATH_DISABLED      0x80000 /* administratively disabled */
+               /* Use GPIO interrupts for new counters */
+#define IPATH_GPIO_ERRINTRS 0x100000
+
+/* Bits in GPIO for the added interrupts */
+#define IPATH_GPIO_PORT0_BIT 2
+#define IPATH_GPIO_RXUVL_BIT 3
+#define IPATH_GPIO_OVRUN_BIT 4
+#define IPATH_GPIO_LLI_BIT 5
+#define IPATH_GPIO_ERRINTR_MASK 0x38
 
 /* portdata flag bit offsets */
                /* waiting for a packet to arrive */
@@ -798,6 +877,13 @@ void ipath_exit_ipathfs(void);
 int ipathfs_add_device(struct ipath_devdata *);
 int ipathfs_remove_device(struct ipath_devdata *);
 
+/*
+ * dma_addr wrappers - all 0's invalid for hw
+ */
+dma_addr_t ipath_map_page(struct pci_dev *, struct page *, unsigned long,
+                         size_t, int);
+dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int);
+
 /*
  * Flush write combining store buffers (if present) and perform a write
  * barrier.
@@ -855,4 +941,20 @@ extern struct mutex ipath_mutex;
 
 #endif /* _IPATH_DEBUGGING */
 
+/*
+ * this is used for formatting hw error messages...
+ */
+struct ipath_hwerror_msgs {
+       u64 mask;
+       const char *msg;
+};
+
+#define INFINIPATH_HWE_MSG(a, b) { .mask = INFINIPATH_HWE_##a, .msg = b }
+
+/* in ipath_intr.c... */
+void ipath_format_hwerrors(u64 hwerrs,
+                          const struct ipath_hwerror_msgs *hwerrmsgs,
+                          size_t nhwerrmsgs,
+                          char *msg, size_t lmsg);
+
 #endif                         /* _IPATH_KERNEL_H */
index ba1b93226caa4472ca67fa1d5dade05ee271b53a..9a6cbd05adcde9e19f7d75032163b8362d6ca77c 100644 (file)
@@ -118,9 +118,10 @@ void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
  * Check the IB SGE for validity and initialize our internal version
  * of it.
  */
-int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
                  struct ib_sge *sge, int acc)
 {
+       struct ipath_lkey_table *rkt = &to_idev(qp->ibqp.device)->lk_table;
        struct ipath_mregion *mr;
        unsigned n, m;
        size_t off;
@@ -140,7 +141,8 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
                goto bail;
        }
        mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
-       if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
+       if (unlikely(mr == NULL || mr->lkey != sge->lkey ||
+                    qp->ibqp.pd != mr->pd)) {
                ret = 0;
                goto bail;
        }
@@ -188,9 +190,10 @@ bail:
  *
  * Return 1 if successful, otherwise 0.
  */
-int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss,
                  u32 len, u64 vaddr, u32 rkey, int acc)
 {
+       struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        struct ipath_lkey_table *rkt = &dev->lk_table;
        struct ipath_sge *sge = &ss->sge;
        struct ipath_mregion *mr;
@@ -214,7 +217,8 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
        }
 
        mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
-       if (unlikely(mr == NULL || mr->lkey != rkey)) {
+       if (unlikely(mr == NULL || mr->lkey != rkey ||
+                    qp->ibqp.pd != mr->pd)) {
                ret = 0;
                goto bail;
        }
index 72d1db89db8f6d3393154eb542c0b47a39208714..25908b02fbe578f57fd6ee7128ea0c9b22169f32 100644 (file)
@@ -87,7 +87,8 @@ static int recv_subn_get_nodeinfo(struct ib_smp *smp,
        struct ipath_devdata *dd = to_idev(ibdev)->dd;
        u32 vendor, majrev, minrev;
 
-       if (smp->attr_mod)
+       /* GUID 0 is illegal */
+       if (smp->attr_mod || (dd->ipath_guid == 0))
                smp->status |= IB_SMP_INVALID_FIELD;
 
        nip->base_version = 1;
@@ -131,10 +132,15 @@ static int recv_subn_get_guidinfo(struct ib_smp *smp,
         * We only support one GUID for now.  If this changes, the
         * portinfo.guid_cap field needs to be updated too.
         */
-       if (startgx == 0)
-               /* The first is a copy of the read-only HW GUID. */
-               *p = to_idev(ibdev)->dd->ipath_guid;
-       else
+       if (startgx == 0) {
+               __be64 g = to_idev(ibdev)->dd->ipath_guid;
+               if (g == 0)
+                       /* GUID 0 is illegal */
+                       smp->status |= IB_SMP_INVALID_FIELD;
+               else
+                       /* The first is a copy of the read-only HW GUID. */
+                       *p = g;
+       } else
                smp->status |= IB_SMP_INVALID_FIELD;
 
        return reply(smp);
index b36f6fb3e37a76f16ae370aa1e6ee163227b7df6..a0673c1eef716bb59655df6d55ab334626e00b9f 100644 (file)
@@ -138,6 +138,7 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
                goto bail;
        }
 
+       mr->mr.pd = pd;
        mr->mr.user_base = *iova_start;
        mr->mr.iova = *iova_start;
        mr->mr.length = 0;
@@ -197,6 +198,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
                goto bail;
        }
 
+       mr->mr.pd = pd;
        mr->mr.user_base = region->user_base;
        mr->mr.iova = region->virt_base;
        mr->mr.length = region->length;
@@ -289,6 +291,7 @@ struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
         * Resources are allocated but no valid mapping (RKEY can't be
         * used).
         */
+       fmr->mr.pd = pd;
        fmr->mr.user_base = 0;
        fmr->mr.iova = 0;
        fmr->mr.length = 0;
index 224b0f40767f0ef6b08a8aa8e451fcad419c6d87..46c1c89bf6ae2748dd5779ddca0c24a44e271af6 100644 (file)
@@ -335,6 +335,7 @@ static void ipath_reset_qp(struct ipath_qp *qp)
        qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
        qp->r_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
        qp->r_nak_state = 0;
+       qp->r_wrid_valid = 0;
        qp->s_rnr_timeout = 0;
        qp->s_head = 0;
        qp->s_tail = 0;
@@ -342,6 +343,7 @@ static void ipath_reset_qp(struct ipath_qp *qp)
        qp->s_last = 0;
        qp->s_ssn = 1;
        qp->s_lsn = 0;
+       qp->s_wait_credit = 0;
        if (qp->r_rq.wq) {
                qp->r_rq.wq->head = 0;
                qp->r_rq.wq->tail = 0;
@@ -352,12 +354,13 @@ static void ipath_reset_qp(struct ipath_qp *qp)
 /**
  * ipath_error_qp - put a QP into an error state
  * @qp: the QP to put into an error state
+ * @err: the receive completion error to signal if a RWQE is active
  *
  * Flushes both send and receive work queues.
  * QP s_lock should be held and interrupts disabled.
  */
 
-void ipath_error_qp(struct ipath_qp *qp)
+void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
 {
        struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        struct ib_wc wc;
@@ -373,7 +376,6 @@ void ipath_error_qp(struct ipath_qp *qp)
                list_del_init(&qp->piowait);
        spin_unlock(&dev->pending_lock);
 
-       wc.status = IB_WC_WR_FLUSH_ERR;
        wc.vendor_err = 0;
        wc.byte_len = 0;
        wc.imm_data = 0;
@@ -385,6 +387,12 @@ void ipath_error_qp(struct ipath_qp *qp)
        wc.sl = 0;
        wc.dlid_path_bits = 0;
        wc.port_num = 0;
+       if (qp->r_wrid_valid) {
+               qp->r_wrid_valid = 0;
+               wc.status = err;
+               ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+       }
+       wc.status = IB_WC_WR_FLUSH_ERR;
 
        while (qp->s_last != qp->s_head) {
                struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
@@ -501,7 +509,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                break;
 
        case IB_QPS_ERR:
-               ipath_error_qp(qp);
+               ipath_error_qp(qp, IB_WC_GENERAL_ERR);
                break;
 
        default:
@@ -516,7 +524,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                qp->remote_qpn = attr->dest_qp_num;
 
        if (attr_mask & IB_QP_SQ_PSN) {
-               qp->s_next_psn = attr->sq_psn;
+               qp->s_psn = qp->s_next_psn = attr->sq_psn;
                qp->s_last_psn = qp->s_next_psn - 1;
        }
 
index a08654042c03411db35b26c54acaf5105e4015cb..a504cf67f27274b2f8cd622884a09e519f7e410e 100644 (file)
@@ -201,6 +201,18 @@ int ipath_make_rc_req(struct ipath_qp *qp,
            qp->s_rnr_timeout)
                goto done;
 
+       /* Limit the number of packets sent without an ACK. */
+       if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT) > 0) {
+               qp->s_wait_credit = 1;
+               dev->n_rc_stalls++;
+               spin_lock(&dev->pending_lock);
+               if (list_empty(&qp->timerwait))
+                       list_add_tail(&qp->timerwait,
+                                     &dev->pending[dev->pending_index]);
+               spin_unlock(&dev->pending_lock);
+               goto done;
+       }
+
        /* header size in 32-bit words LRH+BTH = (8+12)/4. */
        hwords = 5;
        bth0 = 0;
@@ -221,7 +233,7 @@ int ipath_make_rc_req(struct ipath_qp *qp,
                        /* Check if send work queue is empty. */
                        if (qp->s_tail == qp->s_head)
                                goto done;
-                       qp->s_psn = wqe->psn = qp->s_next_psn;
+                       wqe->psn = qp->s_next_psn;
                        newreq = 1;
                }
                /*
@@ -393,12 +405,6 @@ int ipath_make_rc_req(struct ipath_qp *qp,
                ss = &qp->s_sge;
                len = qp->s_len;
                if (len > pmtu) {
-                       /*
-                        * Request an ACK every 1/2 MB to avoid retransmit
-                        * timeouts.
-                        */
-                       if (((wqe->length - len) % (512 * 1024)) == 0)
-                               bth2 |= 1 << 31;
                        len = pmtu;
                        break;
                }
@@ -435,12 +441,6 @@ int ipath_make_rc_req(struct ipath_qp *qp,
                ss = &qp->s_sge;
                len = qp->s_len;
                if (len > pmtu) {
-                       /*
-                        * Request an ACK every 1/2 MB to avoid retransmit
-                        * timeouts.
-                        */
-                       if (((wqe->length - len) % (512 * 1024)) == 0)
-                               bth2 |= 1 << 31;
                        len = pmtu;
                        break;
                }
@@ -498,6 +498,8 @@ int ipath_make_rc_req(struct ipath_qp *qp,
                 */
                goto done;
        }
+       if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT - 1) >= 0)
+               bth2 |= 1 << 31;        /* Request ACK. */
        qp->s_len -= len;
        qp->s_hdrwords = hwords;
        qp->s_cur_sge = ss;
@@ -737,6 +739,15 @@ bail:
        return;
 }
 
+static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
+{
+       if (qp->s_wait_credit) {
+               qp->s_wait_credit = 0;
+               tasklet_hi_schedule(&qp->s_task);
+       }
+       qp->s_last_psn = psn;
+}
+
 /**
  * do_rc_ack - process an incoming RC ACK
  * @qp: the QP the ACK came in on
@@ -805,7 +816,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                         * The last valid PSN seen is the previous
                         * request's.
                         */
-                       qp->s_last_psn = wqe->psn - 1;
+                       update_last_psn(qp, wqe->psn - 1);
                        /* Retry this request. */
                        ipath_restart_rc(qp, wqe->psn, &wc);
                        /*
@@ -864,7 +875,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                ipath_get_credit(qp, aeth);
                qp->s_rnr_retry = qp->s_rnr_retry_cnt;
                qp->s_retry = qp->s_retry_cnt;
-               qp->s_last_psn = psn;
+               update_last_psn(qp, psn);
                ret = 1;
                goto bail;
 
@@ -883,7 +894,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                        goto bail;
 
                /* The last valid PSN is the previous PSN. */
-               qp->s_last_psn = psn - 1;
+               update_last_psn(qp, psn - 1);
 
                dev->n_rc_resends += (int)qp->s_psn - (int)psn;
 
@@ -898,7 +909,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
        case 3:         /* NAK */
                /* The last valid PSN seen is the previous request's. */
                if (qp->s_last != qp->s_tail)
-                       qp->s_last_psn = wqe->psn - 1;
+                       update_last_psn(qp, wqe->psn - 1);
                switch ((aeth >> IPATH_AETH_CREDIT_SHIFT) &
                        IPATH_AETH_CREDIT_MASK) {
                case 0: /* PSN sequence error */
@@ -1071,7 +1082,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
                 * since we don't want s_sge modified.
                 */
                qp->s_len -= pmtu;
-               qp->s_last_psn = psn;
+               update_last_psn(qp, psn);
                spin_unlock_irqrestore(&qp->s_lock, flags);
                ipath_copy_sge(&qp->s_sge, data, pmtu);
                goto bail;
@@ -1223,7 +1234,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
                         * Address range must be a subset of the original
                         * request and start on pmtu boundaries.
                         */
-                       ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+                       ok = ipath_rkey_ok(qp, &qp->s_rdma_sge,
                                           qp->s_rdma_len, vaddr, rkey,
                                           IB_ACCESS_REMOTE_READ);
                        if (unlikely(!ok)) {
@@ -1282,6 +1293,14 @@ done:
        return 1;
 }
 
+static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err)
+{
+       spin_lock_irq(&qp->s_lock);
+       qp->state = IB_QPS_ERR;
+       ipath_error_qp(qp, err);
+       spin_unlock_irq(&qp->s_lock);
+}
+
 /**
  * ipath_rc_rcv - process an incoming RC packet
  * @dev: the device this packet came in on
@@ -1309,6 +1328,10 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
        struct ib_reth *reth;
        int header_in_data;
 
+       /* Validate the SLID. See Ch. 9.6.1.5 */
+       if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid))
+               goto done;
+
        /* Check for GRH */
        if (!has_grh) {
                ohdr = &hdr->u.oth;
@@ -1370,8 +1393,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                 */
                if (qp->r_ack_state >= OP(COMPARE_SWAP))
                        goto send_ack;
-               /* XXX Flush WQEs */
-               qp->state = IB_QPS_ERR;
+               ipath_rc_error(qp, IB_WC_REM_INV_REQ_ERR);
                qp->r_ack_state = OP(SEND_ONLY);
                qp->r_nak_state = IB_NAK_INVALID_REQUEST;
                qp->r_ack_psn = qp->r_psn;
@@ -1477,9 +1499,9 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        goto nack_inv;
                ipath_copy_sge(&qp->r_sge, data, tlen);
                qp->r_msn++;
-               if (opcode == OP(RDMA_WRITE_LAST) ||
-                   opcode == OP(RDMA_WRITE_ONLY))
+               if (!qp->r_wrid_valid)
                        break;
+               qp->r_wrid_valid = 0;
                wc.wr_id = qp->r_wr_id;
                wc.status = IB_WC_SUCCESS;
                wc.opcode = IB_WC_RECV;
@@ -1517,7 +1539,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        int ok;
 
                        /* Check rkey & NAK */
-                       ok = ipath_rkey_ok(dev, &qp->r_sge,
+                       ok = ipath_rkey_ok(qp, &qp->r_sge,
                                           qp->r_len, vaddr, rkey,
                                           IB_ACCESS_REMOTE_WRITE);
                        if (unlikely(!ok))
@@ -1559,7 +1581,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        int ok;
 
                        /* Check rkey & NAK */
-                       ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+                       ok = ipath_rkey_ok(qp, &qp->s_rdma_sge,
                                           qp->s_rdma_len, vaddr, rkey,
                                           IB_ACCESS_REMOTE_READ);
                        if (unlikely(!ok)) {
@@ -1618,7 +1640,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        goto nack_inv;
                rkey = be32_to_cpu(ateth->rkey);
                /* Check rkey & NAK */
-               if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge,
+               if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge,
                                            sizeof(u64), vaddr, rkey,
                                            IB_ACCESS_REMOTE_ATOMIC)))
                        goto nack_acc;
@@ -1670,8 +1692,7 @@ nack_acc:
         * is pending though.
         */
        if (qp->r_ack_state < OP(COMPARE_SWAP)) {
-               /* XXX Flush WQEs */
-               qp->state = IB_QPS_ERR;
+               ipath_rc_error(qp, IB_WC_REM_ACCESS_ERR);
                qp->r_ack_state = OP(RDMA_WRITE_ONLY);
                qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR;
                qp->r_ack_psn = qp->r_psn;
index 6e23b3d632b820eac22febb91b0aab7d0269982a..dffc76016d3c23c3a0680f89d5dbd11d223a3a57 100644 (file)
 #define INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT 40
 #define INFINIPATH_HWE_RXEMEMPARITYERR_MASK 0x7FULL
 #define INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT 44
-#define INFINIPATH_HWE_RXDSYNCMEMPARITYERR  0x0000000400000000ULL
-#define INFINIPATH_HWE_MEMBISTFAILED        0x0040000000000000ULL
 #define INFINIPATH_HWE_IBCBUSTOSPCPARITYERR 0x4000000000000000ULL
 #define INFINIPATH_HWE_IBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+/* txe mem parity errors (shift by INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) */
+#define INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF  0x1ULL
+#define INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC  0x2ULL
+#define INFINIPATH_HWE_TXEMEMPARITYERR_PIOLAUNCHFIFO 0x4ULL
+/* rxe mem parity errors (shift by INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) */
+#define INFINIPATH_HWE_RXEMEMPARITYERR_RCVBUF   0x01ULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_LOOKUPQ  0x02ULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID 0x04ULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_EXPTID   0x08ULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_FLAGBUF  0x10ULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_DATAINFO 0x20ULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_HDRINFO  0x40ULL
+/* waldo specific -- find the rest in ipath_6110.c */
+#define INFINIPATH_HWE_RXDSYNCMEMPARITYERR  0x0000000400000000ULL
+/* monty specific -- find the rest in ipath_6120.c */
+#define INFINIPATH_HWE_MEMBISTFAILED   0x0040000000000000ULL
 
 /* kr_hwdiagctrl bits */
 #define INFINIPATH_DC_FORCETXEMEMPARITYERR_MASK 0xFULL
 
 /* combination link status states that we use with some frequency */
 #define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
-               << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+               << INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | \
                (INFINIPATH_IBCS_LINKSTATE_MASK \
-               <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+               <<INFINIPATH_IBCS_LINKSTATE_SHIFT))
 #define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
                << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
                (INFINIPATH_IBCS_LT_STATE_LINKUP \
 
 typedef u64 ipath_err_t;
 
+/* The following change with the type of device, so
+ * need to be part of the ipath_devdata struct, or
+ * we could have problems plugging in devices of
+ * different types (e.g. one HT, one PCIE)
+ * in one system, to be managed by one driver.
+ * On the other hand, this file is may also be included
+ * by other code, so leave the declarations here
+ * temporarily. Minor footprint issue if common-model
+ * linker used, none if C89+ linker used.
+ */
+
 /* mask of defined bits for various registers */
 extern u64 infinipath_i_bitsextant;
 extern ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
@@ -309,13 +334,6 @@ extern ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
 /* masks that are different in various chips, or only exist in some chips */
 extern u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
 
-/*
- * register bits for selecting i2c direction and values, used for I2C serial
- * flash
- */
-extern u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
-extern u64 ipath_gpio_sda, ipath_gpio_scl;
-
 /*
  * These are the infinipath general register numbers (not offsets).
  * The kernel registers are used directly, those beyond the kernel
index 5c1da2d25e03e6c16ff4572ff59e88de613be0f5..f7530512045d0f0e7584424e020e1e5169909a29 100644 (file)
@@ -108,7 +108,6 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp)
 
 static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe)
 {
-       struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        int user = to_ipd(qp->ibqp.pd)->user;
        int i, j, ret;
        struct ib_wc wc;
@@ -119,8 +118,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe)
                        continue;
                /* Check LKEY */
                if ((user && wqe->sg_list[i].lkey == 0) ||
-                   !ipath_lkey_ok(&dev->lk_table,
-                                  &qp->r_sg_list[j], &wqe->sg_list[i],
+                   !ipath_lkey_ok(qp, &qp->r_sg_list[j], &wqe->sg_list[i],
                                   IB_ACCESS_LOCAL_WRITE))
                        goto bad_lkey;
                qp->r_len += wqe->sg_list[i].length;
@@ -231,6 +229,7 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
                }
        }
        spin_unlock_irqrestore(&rq->lock, flags);
+       qp->r_wrid_valid = 1;
 
 bail:
        return ret;
@@ -326,7 +325,7 @@ again:
        case IB_WR_RDMA_WRITE:
                if (wqe->length == 0)
                        break;
-               if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, wqe->length,
+               if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length,
                                            wqe->wr.wr.rdma.remote_addr,
                                            wqe->wr.wr.rdma.rkey,
                                            IB_ACCESS_REMOTE_WRITE))) {
@@ -350,7 +349,7 @@ again:
                break;
 
        case IB_WR_RDMA_READ:
-               if (unlikely(!ipath_rkey_ok(dev, &sqp->s_sge, wqe->length,
+               if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
                                            wqe->wr.wr.rdma.remote_addr,
                                            wqe->wr.wr.rdma.rkey,
                                            IB_ACCESS_REMOTE_READ)))
@@ -365,7 +364,7 @@ again:
 
        case IB_WR_ATOMIC_CMP_AND_SWP:
        case IB_WR_ATOMIC_FETCH_AND_ADD:
-               if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, sizeof(u64),
+               if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
                                            wqe->wr.wr.rdma.remote_addr,
                                            wqe->wr.wr.rdma.rkey,
                                            IB_ACCESS_REMOTE_ATOMIC)))
@@ -575,8 +574,7 @@ int ipath_post_ruc_send(struct ipath_qp *qp, struct ib_send_wr *wr)
                }
                if (wr->sg_list[i].length == 0)
                        continue;
-               if (!ipath_lkey_ok(&to_idev(qp->ibqp.device)->lk_table,
-                                  &wqe->sg_list[j], &wr->sg_list[i],
+               if (!ipath_lkey_ok(qp, &wqe->sg_list[j], &wr->sg_list[i],
                                   acc)) {
                        spin_unlock_irqrestore(&qp->s_lock, flags);
                        ret = -EINVAL;
index 941e866d9517ba84edb6078db94565f5090f2429..94033503400ca9f5f9d1ef617e799c9dd7ddb62f 100644 (file)
@@ -104,11 +104,6 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
        u32 sz;
        struct ib_srq *ret;
 
-       if (dev->n_srqs_allocated == ib_ipath_max_srqs) {
-               ret = ERR_PTR(-ENOMEM);
-               goto done;
-       }
-
        if (srq_init_attr->attr.max_wr == 0) {
                ret = ERR_PTR(-EINVAL);
                goto done;
@@ -180,10 +175,17 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
        spin_lock_init(&srq->rq.lock);
        srq->rq.wq->head = 0;
        srq->rq.wq->tail = 0;
-       srq->rq.max_sge = srq_init_attr->attr.max_sge;
        srq->limit = srq_init_attr->attr.srq_limit;
 
-       dev->n_srqs_allocated++;
+       spin_lock(&dev->n_srqs_lock);
+       if (dev->n_srqs_allocated == ib_ipath_max_srqs) {
+               spin_unlock(&dev->n_srqs_lock);
+               ret = ERR_PTR(-ENOMEM);
+               goto bail_wq;
+       }
+
+       dev->n_srqs_allocated++;
+       spin_unlock(&dev->n_srqs_lock);
 
        ret = &srq->ibsrq;
        goto done;
@@ -351,8 +353,13 @@ int ipath_destroy_srq(struct ib_srq *ibsrq)
        struct ipath_srq *srq = to_isrq(ibsrq);
        struct ipath_ibdev *dev = to_idev(ibsrq->device);
 
+       spin_lock(&dev->n_srqs_lock);
        dev->n_srqs_allocated--;
-       vfree(srq->rq.wq);
+       spin_unlock(&dev->n_srqs_lock);
+       if (srq->ip)
+               kref_put(&srq->ip->ref, ipath_release_mmap_info);
+       else
+               vfree(srq->rq.wq);
        kfree(srq);
 
        return 0;
index e299148c4b68ec4ae793f0805a339d3c75bbb081..182de34f9f476f84d1c289992bf61b4ff21f6cc1 100644 (file)
@@ -257,7 +257,7 @@ static ssize_t store_guid(struct device *dev,
        struct ipath_devdata *dd = dev_get_drvdata(dev);
        ssize_t ret;
        unsigned short guid[8];
-       __be64 nguid;
+       __be64 new_guid;
        u8 *ng;
        int i;
 
@@ -266,7 +266,7 @@ static ssize_t store_guid(struct device *dev,
                   &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
                goto invalid;
 
-       ng = (u8 *) &nguid;
+       ng = (u8 *) &new_guid;
 
        for (i = 0; i < 8; i++) {
                if (guid[i] > 0xff)
@@ -274,7 +274,10 @@ static ssize_t store_guid(struct device *dev,
                ng[i] = guid[i];
        }
 
-       dd->ipath_guid = nguid;
+       if (new_guid == 0)
+               goto invalid;
+
+       dd->ipath_guid = new_guid;
        dd->ipath_nguid = 1;
 
        ret = strlen(buf);
@@ -297,6 +300,16 @@ static ssize_t show_nguid(struct device *dev,
        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
 }
 
+static ssize_t show_nports(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+       /* Return the number of user ports available. */
+       return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1);
+}
+
 static ssize_t show_serial(struct device *dev,
                           struct device_attribute *attr,
                           char *buf)
@@ -608,6 +621,7 @@ static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
 static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
 static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
 static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
+static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL);
 static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
 static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
 static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
@@ -623,6 +637,7 @@ static struct attribute *dev_attributes[] = {
        &dev_attr_mlid.attr,
        &dev_attr_mtu.attr,
        &dev_attr_nguid.attr,
+       &dev_attr_nports.attr,
        &dev_attr_serial.attr,
        &dev_attr_status.attr,
        &dev_attr_status_str.attr,
index 0fd3cded16baffab97b78934c990ae5a0944f194..e636cfd67a821f74349c48d1f64f80d3bc9e94ab 100644 (file)
@@ -246,6 +246,10 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
        struct ib_reth *reth;
        int header_in_data;
 
+       /* Validate the SLID. See Ch. 9.6.1.5 */
+       if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid))
+               goto done;
+
        /* Check for GRH */
        if (!has_grh) {
                ohdr = &hdr->u.oth;
@@ -440,7 +444,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                        int ok;
 
                        /* Check rkey */
-                       ok = ipath_rkey_ok(dev, &qp->r_sge, qp->r_len,
+                       ok = ipath_rkey_ok(qp, &qp->r_sge, qp->r_len,
                                           vaddr, rkey,
                                           IB_ACCESS_REMOTE_WRITE);
                        if (unlikely(!ok)) {
index 6991d1d74e3cebab1ed461108b384e37cd746848..49f1102af8b36635427459aa52faeb76b2e2afd0 100644 (file)
@@ -39,7 +39,6 @@
 static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe,
                    u32 *lengthp, struct ipath_sge_state *ss)
 {
-       struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        int user = to_ipd(qp->ibqp.pd)->user;
        int i, j, ret;
        struct ib_wc wc;
@@ -50,8 +49,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe,
                        continue;
                /* Check LKEY */
                if ((user && wqe->sg_list[i].lkey == 0) ||
-                   !ipath_lkey_ok(&dev->lk_table,
-                                  j ? &ss->sg_list[j - 1] : &ss->sge,
+                   !ipath_lkey_ok(qp, j ? &ss->sg_list[j - 1] : &ss->sge,
                                   &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE))
                        goto bad_lkey;
                *lengthp += wqe->sg_list[i].length;
@@ -343,7 +341,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr)
 
                if (wr->sg_list[i].length == 0)
                        continue;
-               if (!ipath_lkey_ok(&dev->lk_table, ss.num_sge ?
+               if (!ipath_lkey_ok(qp, ss.num_sge ?
                                   sg_list + ss.num_sge - 1 : &ss.sge,
                                   &wr->sg_list[i], 0)) {
                        ret = -EINVAL;
index e32fca9faf80360ced178df98a67516b78dd4bff..413754b1d8a254d6fb26111dfe743a74d13ddcfc 100644 (file)
@@ -89,6 +89,62 @@ bail:
        return ret;
 }
 
+/**
+ * ipath_map_page - a safety wrapper around pci_map_page()
+ *
+ * A dma_addr of all 0's is interpreted by the chip as "disabled".
+ * Unfortunately, it can also be a valid dma_addr returned on some
+ * architectures.
+ *
+ * The powerpc iommu assigns dma_addrs in ascending order, so we don't
+ * have to bother with retries or mapping a dummy page to insure we
+ * don't just get the same mapping again.
+ *
+ * I'm sure we won't be so lucky with other iommu's, so FIXME.
+ */
+dma_addr_t ipath_map_page(struct pci_dev *hwdev, struct page *page,
+       unsigned long offset, size_t size, int direction)
+{
+       dma_addr_t phys;
+
+       phys = pci_map_page(hwdev, page, offset, size, direction);
+
+       if (phys == 0) {
+               pci_unmap_page(hwdev, phys, size, direction);
+               phys = pci_map_page(hwdev, page, offset, size, direction);
+               /*
+                * FIXME: If we get 0 again, we should keep this page,
+                * map another, then free the 0 page.
+                */
+       }
+
+       return phys;
+}
+
+/**
+ * ipath_map_single - a safety wrapper around pci_map_single()
+ *
+ * Same idea as ipath_map_page().
+ */
+dma_addr_t ipath_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
+       int direction)
+{
+       dma_addr_t phys;
+
+       phys = pci_map_single(hwdev, ptr, size, direction);
+
+       if (phys == 0) {
+               pci_unmap_single(hwdev, phys, size, direction);
+               phys = pci_map_single(hwdev, ptr, size, direction);
+               /*
+                * FIXME: If we get 0 again, we should keep this page,
+                * map another, then free the 0 page.
+                */
+       }
+
+       return phys;
+}
+
 /**
  * ipath_get_user_pages - lock user pages into memory
  * @start_page: the start page
index b8381c5e72bd689d7790ec043467f6d0c2d0afb0..42eaed88c281b2a194641c6231abc80bafa45893 100644 (file)
@@ -898,7 +898,8 @@ int ipath_get_counters(struct ipath_devdata *dd,
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) +
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) +
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) +
-               ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt);
+               ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt) +
+               dd->ipath_rxfc_unsupvl_errs;
        cntrs->port_rcv_remphys_errors =
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt);
        cntrs->port_xmit_discards =
@@ -911,8 +912,10 @@ int ipath_get_counters(struct ipath_devdata *dd,
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
        cntrs->port_rcv_packets =
                ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
-       cntrs->local_link_integrity_errors = dd->ipath_lli_errors;
-       cntrs->excessive_buffer_overrun_errors = 0; /* XXX */
+       cntrs->local_link_integrity_errors =
+               (dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
+               dd->ipath_lli_errs : dd->ipath_lli_errors;
+       cntrs->excessive_buffer_overrun_errors = dd->ipath_overrun_thresh_errs;
 
        ret = 0;
 
@@ -1199,6 +1202,7 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
        struct ipath_ah *ah;
        struct ib_ah *ret;
        struct ipath_ibdev *dev = to_idev(pd->device);
+       unsigned long flags;
 
        /* A multicast address requires a GRH (see ch. 8.4.1). */
        if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE &&
@@ -1225,16 +1229,16 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
                goto bail;
        }
 
-       spin_lock(&dev->n_ahs_lock);
+       spin_lock_irqsave(&dev->n_ahs_lock, flags);
        if (dev->n_ahs_allocated == ib_ipath_max_ahs) {
-               spin_unlock(&dev->n_ahs_lock);
+               spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
                kfree(ah);
                ret = ERR_PTR(-ENOMEM);
                goto bail;
        }
 
        dev->n_ahs_allocated++;
-       spin_unlock(&dev->n_ahs_lock);
+       spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
 
        /* ib_create_ah() will initialize ah->ibah. */
        ah->attr = *ah_attr;
@@ -1255,10 +1259,11 @@ static int ipath_destroy_ah(struct ib_ah *ibah)
 {
        struct ipath_ibdev *dev = to_idev(ibah->device);
        struct ipath_ah *ah = to_iah(ibah);
+       unsigned long flags;
 
-       spin_lock(&dev->n_ahs_lock);
+       spin_lock_irqsave(&dev->n_ahs_lock, flags);
        dev->n_ahs_allocated--;
-       spin_unlock(&dev->n_ahs_lock);
+       spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
 
        kfree(ah);
 
@@ -1380,11 +1385,13 @@ static int enable_timer(struct ipath_devdata *dd)
         * processing.
         */
        if (dd->ipath_flags & IPATH_GPIO_INTR) {
+               u64 val;
                ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
                                 0x2074076542310ULL);
                /* Enable GPIO bit 2 interrupt */
-               ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
-                                (u64) (1 << 2));
+               val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
+               val |= (u64) (1 << IPATH_GPIO_PORT0_BIT);
+               ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
        }
 
        init_timer(&dd->verbs_timer);
@@ -1399,8 +1406,17 @@ static int enable_timer(struct ipath_devdata *dd)
 static int disable_timer(struct ipath_devdata *dd)
 {
        /* Disable GPIO bit 2 interrupt */
-       if (dd->ipath_flags & IPATH_GPIO_INTR)
-               ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, 0);
+       if (dd->ipath_flags & IPATH_GPIO_INTR) {
+                u64 val;
+                /* Disable GPIO bit 2 interrupt */
+                val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_mask);
+                val &= ~((u64) (1 << IPATH_GPIO_PORT0_BIT));
+                ipath_write_kreg( dd, dd->ipath_kregs->kr_gpio_mask, val);
+               /*
+                * We might want to undo changes to debugportselect,
+                * but how?
+                */
+       }
 
        del_timer_sync(&dd->verbs_timer);
 
@@ -1683,6 +1699,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
                      "RC OTH NAKs %d\n"
                      "RC timeouts %d\n"
                      "RC RDMA dup %d\n"
+                     "RC stalls   %d\n"
                      "piobuf wait %d\n"
                      "no piobuf   %d\n"
                      "PKT drops   %d\n"
@@ -1690,7 +1707,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
                      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
                      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
                      dev->n_other_naks, dev->n_timeouts,
-                     dev->n_rdma_dup_busy, dev->n_piowait,
+                     dev->n_rdma_dup_busy, dev->n_rc_stalls, dev->n_piowait,
                      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
        for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
                const struct ipath_opcode_stats *si = &dev->opstats[i];
index 09bbb3f9a2176f495b1bafa2602da95f5b6faed9..8039f6e5f0c8b447b9a6161ac06dd50dbe11c418 100644 (file)
@@ -220,6 +220,7 @@ struct ipath_segarray {
 };
 
 struct ipath_mregion {
+       struct ib_pd *pd;       /* shares refcnt of ibmr.pd */
        u64 user_base;          /* User's address for this region */
        u64 iova;               /* IB start address of this region */
        size_t length;
@@ -364,12 +365,14 @@ struct ipath_qp {
        u8 r_min_rnr_timer;     /* retry timeout value for RNR NAKs */
        u8 r_reuse_sge;         /* for UC receive errors */
        u8 r_sge_inx;           /* current index into sg_list */
+       u8 r_wrid_valid;        /* r_wrid set but CQ entry not yet made */
        u8 qp_access_flags;
        u8 s_max_sge;           /* size of s_wq->sg_list */
        u8 s_retry_cnt;         /* number of times to retry */
        u8 s_rnr_retry_cnt;
        u8 s_retry;             /* requester retry counter */
        u8 s_rnr_retry;         /* requester RNR retry counter */
+       u8 s_wait_credit;       /* limit number of unacked packets sent */
        u8 s_pkey_index;        /* PKEY index to use */
        u8 timeout;             /* Timeout for this QP */
        enum ib_mtu path_mtu;
@@ -393,6 +396,8 @@ struct ipath_qp {
 #define IPATH_S_BUSY           0
 #define IPATH_S_SIGNAL_REQ_WR  1
 
+#define IPATH_PSN_CREDIT       2048
+
 /*
  * Since struct ipath_swqe is not a fixed size, we can't simply index into
  * struct ipath_qp.s_wq.  This function does the array index computation.
@@ -521,6 +526,7 @@ struct ipath_ibdev {
        u32 n_rnr_naks;
        u32 n_other_naks;
        u32 n_timeouts;
+       u32 n_rc_stalls;
        u32 n_pkt_drops;
        u32 n_vl15_dropped;
        u32 n_wqe_errs;
@@ -634,6 +640,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
 
 int ipath_destroy_qp(struct ib_qp *ibqp);
 
+void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err);
+
 int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                    int attr_mask, struct ib_udata *udata);
 
@@ -653,12 +661,6 @@ int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
 
 void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
 
-int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
-                 u32 len, u64 vaddr, u32 rkey, int acc);
-
-int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
-                 struct ib_sge *sge, int acc);
-
 void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length);
 
 void ipath_skip_sge(struct ipath_sge_state *ss, u32 length);
@@ -683,10 +685,10 @@ int ipath_alloc_lkey(struct ipath_lkey_table *rkt,
 
 void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey);
 
-int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
                  struct ib_sge *sge, int acc);
 
-int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss,
                  u32 len, u64 vaddr, u32 rkey, int acc);
 
 int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
index 036fde662aa9bd759e697521876073ec2d64e786..0095bb70f34e7bbe1f0257ef13402e69865a8e83 100644 (file)
 #include "ipath_kernel.h"
 
 /**
- * ipath_unordered_wc - indicate whether write combining is ordered
+ * ipath_enable_wc - enable write combining for MMIO writes to the device
+ * @dd: infinipath device
  *
- * PowerPC systems (at least those in the 970 processor family)
- * write partially filled store buffers in address order, but will write
- * completely filled store buffers in "random" order, and therefore must
- * have serialization for correctness with current InfiniPath chips.
+ * Nothing to do on PowerPC, so just return without error.
+ */
+int ipath_enable_wc(struct ipath_devdata *dd)
+{
+       return 0;
+}
+
+/**
+ * ipath_unordered_wc - indicate whether write combining is unordered
  *
+ * Because our performance depends on our ability to do write
+ * combining mmio writes in the most efficient way, we need to
+ * know if we are on a processor that may reorder stores when
+ * write combining.
  */
 int ipath_unordered_wc(void)
 {
index f8f9e2e8cbdd6217642076ff7842ed0b9036427b..04696e62da878ac3322d483bec9d62afbd3c7164 100644 (file)
@@ -123,6 +123,8 @@ int ipath_enable_wc(struct ipath_devdata *dd)
                        ipath_cdbg(VERBOSE, "Set mtrr for chip to WC, "
                                   "cookie is %d\n", cookie);
                        dd->ipath_wc_cookie = cookie;
+                       dd->ipath_wc_base = (unsigned long) pioaddr;
+                       dd->ipath_wc_len = (unsigned long) piolen;
                }
        }
 
@@ -136,9 +138,16 @@ int ipath_enable_wc(struct ipath_devdata *dd)
 void ipath_disable_wc(struct ipath_devdata *dd)
 {
        if (dd->ipath_wc_cookie) {
+               int r;
                ipath_cdbg(VERBOSE, "undoing WCCOMB on pio buffers\n");
-               mtrr_del(dd->ipath_wc_cookie, 0, 0);
-               dd->ipath_wc_cookie = 0;
+               r = mtrr_del(dd->ipath_wc_cookie, dd->ipath_wc_base,
+                            dd->ipath_wc_len);
+               if (r < 0)
+                       dev_info(&dd->pcidev->dev,
+                                "mtrr_del(%lx, %lx, %lx) failed: %d\n",
+                                dd->ipath_wc_cookie, dd->ipath_wc_base,
+                                dd->ipath_wc_len, r);
+               dd->ipath_wc_cookie = 0; /* even on failure */
        }
 }
 
index 5dde380e8dbe9c2653c0014020f32ebc8e87732d..f1cb83688b318ef62d0cf6240019e23db74676f7 100644 (file)
@@ -141,7 +141,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
                return ret;
 
        seq = file->private_data;
-       seq->private = inode->u.generic_ip;
+       seq->private = inode->i_private;
 
        return 0;
 }
@@ -247,7 +247,7 @@ static int ipoib_path_open(struct inode *inode, struct file *file)
                return ret;
 
        seq = file->private_data;
-       seq->private = inode->u.generic_ip;
+       seq->private = inode->i_private;
 
        return 0;
 }
index 365a1b5f19e044f8c427b8f34440b3e93c3a6171..aecbb9083f0c06c770dfb20aba8c1068c9629e1f 100644 (file)
@@ -1,11 +1,12 @@
 config INFINIBAND_ISER
-       tristate "ISCSI RDMA Protocol"
+       tristate "iSCSI Extensions for RDMA (iSER)"
        depends on INFINIBAND && SCSI && INET
        select SCSI_ISCSI_ATTRS
        ---help---
-         Support for the ISCSI RDMA Protocol over InfiniBand.  This
-         allows you to access storage devices that speak ISER/ISCSI
-         over InfiniBand.
+         Support for the iSCSI Extensions for RDMA (iSER) Protocol
+          over InfiniBand. This allows you to access storage devices
+          that speak iSCSI over iSER over InfiniBand.
 
-         The ISER protocol is defined by IETF.
-         See <http://www.ietf.org/>.
+         The iSER protocol is defined by IETF.
+         See <http://www.ietf.org/internet-drafts/draft-ietf-ips-iser-05.txt>
+         and <http://www.infinibandta.org/members/spec/iser_annex_060418.pdf>
index 2a14fe2e3226c7a2cb987ba4979ae0fb2ee186bb..eb6f98d822899bcf71ab05ffd376a835dcc3e89f 100644 (file)
@@ -317,6 +317,8 @@ iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
        struct iscsi_iser_conn *iser_conn = conn->dd_data;
 
        iscsi_conn_teardown(cls_conn);
+       if (iser_conn->ib_conn)
+               iser_conn->ib_conn->iser_conn = NULL;
        kfree(iser_conn);
 }
 
index 2cf9ae0def1cfb827f883992198af29d5a8b6ba1..9c53916f28c24d89a8d8e6bbd8616cfe62783423 100644 (file)
@@ -192,7 +192,7 @@ struct iser_regd_buf {
 
 struct iser_dto {
        struct iscsi_iser_cmd_task *ctask;
-       struct iscsi_iser_conn     *conn;
+       struct iser_conn *ib_conn;
        int                        notify_enable;
 
        /* vector of registered buffers */
@@ -355,4 +355,11 @@ int  iser_post_send(struct iser_desc *tx_desc);
 
 int iser_conn_state_comp(struct iser_conn *ib_conn,
                         enum iser_ib_conn_state comp);
+
+int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
+                           struct iser_data_buf       *data,
+                           enum   iser_data_dir       iser_dir,
+                           enum   dma_data_direction  dma_dir);
+
+void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask);
 #endif
index ccf56f6f7236a076be2c81c769a9bcf9f2f21a1e..9b3d79c796c8e1e9defbac5d3936d7f6fa44d9cc 100644 (file)
@@ -66,42 +66,6 @@ static void iser_dto_add_regd_buff(struct iser_dto *dto,
        dto->regd_vector_len++;
 }
 
-static int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
-                                 struct iser_data_buf       *data,
-                                 enum   iser_data_dir       iser_dir,
-                                 enum   dma_data_direction  dma_dir)
-{
-       struct device *dma_device;
-
-       iser_ctask->dir[iser_dir] = 1;
-       dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
-
-       data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir);
-       if (data->dma_nents == 0) {
-               iser_err("dma_map_sg failed!!!\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
-{
-       struct device  *dma_device;
-       struct iser_data_buf *data;
-
-       dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
-
-       if (iser_ctask->dir[ISER_DIR_IN]) {
-               data = &iser_ctask->data[ISER_DIR_IN];
-               dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE);
-       }
-
-       if (iser_ctask->dir[ISER_DIR_OUT]) {
-               data = &iser_ctask->data[ISER_DIR_OUT];
-               dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE);
-       }
-}
-
 /* Register user buffer memory and initialize passive rdma
  *  dto descriptor. Total data size is stored in
  *  iser_ctask->data[ISER_DIR_IN].data_len
@@ -249,7 +213,7 @@ static int iser_post_receive_control(struct iscsi_conn *conn)
        }
 
        recv_dto = &rx_desc->dto;
-       recv_dto->conn          = iser_conn;
+       recv_dto->ib_conn = iser_conn->ib_conn;
        recv_dto->regd_vector_len = 0;
 
        regd_hdr = &rx_desc->hdr_regd_buf;
@@ -296,7 +260,7 @@ static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn,
        regd_hdr->virt_addr  = tx_desc; /* == &tx_desc->iser_header */
        regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
 
-       send_dto->conn          = iser_conn;
+       send_dto->ib_conn         = iser_conn->ib_conn;
        send_dto->notify_enable   = 1;
        send_dto->regd_vector_len = 0;
 
@@ -588,7 +552,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
                         unsigned long dto_xfer_len)
 {
        struct iser_dto        *dto = &rx_desc->dto;
-       struct iscsi_iser_conn *conn = dto->conn;
+       struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn;
        struct iscsi_session *session = conn->iscsi_conn->session;
        struct iscsi_cmd_task *ctask;
        struct iscsi_iser_cmd_task *iser_ctask;
@@ -641,7 +605,8 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
 void iser_snd_completion(struct iser_desc *tx_desc)
 {
        struct iser_dto        *dto = &tx_desc->dto;
-       struct iscsi_iser_conn *iser_conn = dto->conn;
+       struct iser_conn       *ib_conn = dto->ib_conn;
+       struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
        struct iscsi_conn      *conn = iser_conn->iscsi_conn;
        struct iscsi_mgmt_task *mtask;
 
@@ -652,7 +617,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
        if (tx_desc->type == ISCSI_TX_DATAOUT)
                kmem_cache_free(ig.desc_cache, tx_desc);
 
-       atomic_dec(&iser_conn->ib_conn->post_send_buf_count);
+       atomic_dec(&ib_conn->post_send_buf_count);
 
        write_lock(conn->recv_lock);
        if (conn->suspend_tx) {
@@ -698,14 +663,19 @@ void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask)
 void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
 {
        int deferred;
+       int is_rdma_aligned = 1;
 
        /* if we were reading, copy back to unaligned sglist,
         * anyway dma_unmap and free the copy
         */
-       if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL)
+       if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL) {
+               is_rdma_aligned = 0;
                iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN);
-       if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL)
+       }
+       if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL) {
+               is_rdma_aligned = 0;
                iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT);
+       }
 
        if (iser_ctask->dir[ISER_DIR_IN]) {
                deferred = iser_regd_buff_release
@@ -725,7 +695,9 @@ void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
                }
        }
 
-       iser_dma_unmap_task_data(iser_ctask);
+       /* if the data was unaligned, it was already unmapped and then copied */
+       if (is_rdma_aligned)
+               iser_dma_unmap_task_data(iser_ctask);
 }
 
 void iser_dto_buffs_release(struct iser_dto *dto)
index d0b03f4265811c04f70d5d2a33acdaa9dacf8a56..0606744c3f84407b63986f7e15c097cca77a992b 100644 (file)
@@ -369,6 +369,44 @@ static void iser_page_vec_build(struct iser_data_buf *data,
        }
 }
 
+int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
+                           struct iser_data_buf       *data,
+                           enum   iser_data_dir       iser_dir,
+                           enum   dma_data_direction  dma_dir)
+{
+       struct device *dma_device;
+
+       iser_ctask->dir[iser_dir] = 1;
+       dma_device =
+               iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+       data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir);
+       if (data->dma_nents == 0) {
+               iser_err("dma_map_sg failed!!!\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
+{
+       struct device  *dma_device;
+       struct iser_data_buf *data;
+
+       dma_device =
+               iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+       if (iser_ctask->dir[ISER_DIR_IN]) {
+               data = &iser_ctask->data[ISER_DIR_IN];
+               dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE);
+       }
+
+       if (iser_ctask->dir[ISER_DIR_OUT]) {
+               data = &iser_ctask->data[ISER_DIR_OUT];
+               dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE);
+       }
+}
+
 /**
  * iser_reg_rdma_mem - Registers memory intended for RDMA,
  * obtaining rkey and va
@@ -394,6 +432,10 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
                iser_err("rdma alignment violation %d/%d aligned\n",
                         aligned_len, mem->size);
                iser_data_buf_dump(mem);
+
+               /* unmap the command data before accessing it */
+               iser_dma_unmap_task_data(iser_ctask);
+
                /* allocate copy buf, if we are writing, copy the */
                /* unaligned scatterlist, dma map the copy        */
                if (iser_start_rdma_unaligned_sg(iser_ctask, cmd_dir) != 0)
index ecdca7fc1e4cf0466f58bd6d89b4153891b71e0b..18a0000349965dc03438ecf641358c18efdbdf18 100644 (file)
@@ -571,6 +571,8 @@ void iser_conn_release(struct iser_conn *ib_conn)
        /* on EVENT_ADDR_ERROR there's no device yet for this conn */
        if (device != NULL)
                iser_device_try_release(device);
+       if (ib_conn->iser_conn)
+               ib_conn->iser_conn->ib_conn = NULL;
        kfree(ib_conn);
 }
 
@@ -694,7 +696,7 @@ int iser_post_recv(struct iser_desc *rx_desc)
        struct iser_dto   *recv_dto = &rx_desc->dto;
 
        /* Retrieve conn */
-       ib_conn = recv_dto->conn->ib_conn;
+       ib_conn = recv_dto->ib_conn;
 
        iser_dto_to_iov(recv_dto, iov, 2);
 
@@ -727,7 +729,7 @@ int iser_post_send(struct iser_desc *tx_desc)
        struct iser_conn  *ib_conn;
        struct iser_dto   *dto = &tx_desc->dto;
 
-       ib_conn = dto->conn->ib_conn;
+       ib_conn = dto->ib_conn;
 
        iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN);
 
@@ -774,7 +776,7 @@ static void iser_comp_error_worker(void *data)
 static void iser_handle_comp_error(struct iser_desc *desc)
 {
        struct iser_dto  *dto     = &desc->dto;
-       struct iser_conn *ib_conn = dto->conn->ib_conn;
+       struct iser_conn *ib_conn = dto->ib_conn;
 
        iser_dto_buffs_release(dto);
 
index a9dda56f62c412a8af7b4be41edb94abe847b361..83eac3a66bc801d11f11d6f1535f3894b9950f18 100644 (file)
@@ -183,4 +183,13 @@ config KEYBOARD_HIL
          This driver implements support for HIL-keyboards attached
          to your machine, so normally you should say Y here.
 
+config KEYBOARD_OMAP
+       tristate "TI OMAP keypad support"
+       depends on (ARCH_OMAP1 || ARCH_OMAP2)
+       help
+         Say Y here if you want to use the OMAP keypad.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap-keypad.
+
 endif
index 2708167ba17585c062a74d7d7e5ac7946da99ad2..b265391f1f10a226e6054d3496cb296f3deeafc7 100644 (file)
@@ -15,4 +15,5 @@ obj-$(CONFIG_KEYBOARD_CORGI)          += corgikbd.o
 obj-$(CONFIG_KEYBOARD_SPITZ)           += spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
+obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
 
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
new file mode 100644 (file)
index 0000000..d436287
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * linux/drivers/input/keyboard/omap-keypad.c
+ *
+ * OMAP Keypad Driver
+ *
+ * Copyright (C) 2003 Nokia Corporation
+ * Written by Timo Teräs <ext-timo.teras@nokia.com>
+ *
+ * Added support for H2 & H3 Keypad
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/arch/mux.h>
+
+#undef NEW_BOARD_LEARNING_MODE
+
+static void omap_kp_tasklet(unsigned long);
+static void omap_kp_timer(unsigned long);
+
+static unsigned char keypad_state[8];
+static DEFINE_MUTEX(kp_enable_mutex);
+static int kp_enable = 1;
+static int kp_cur_group = -1;
+
+struct omap_kp {
+       struct input_dev *input;
+       struct timer_list timer;
+       int irq;
+       unsigned int rows;
+       unsigned int cols;
+       unsigned long delay;
+       unsigned int debounce;
+};
+
+DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+
+static int *keymap;
+static unsigned int *row_gpios;
+static unsigned int *col_gpios;
+
+#ifdef CONFIG_ARCH_OMAP2
+static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value)
+{
+       int col;
+       for (col = 0; col < omap_kp->cols; col++) {
+               if (value & (1 << col))
+                       omap_set_gpio_dataout(col_gpios[col], 1);
+               else
+                       omap_set_gpio_dataout(col_gpios[col], 0);
+       }
+}
+
+static u8 get_row_gpio_val(struct omap_kp *omap_kp)
+{
+       int row;
+       u8 value = 0;
+
+       for (row = 0; row < omap_kp->rows; row++) {
+               if (omap_get_gpio_datain(row_gpios[row]))
+                       value |= (1 << row);
+       }
+       return value;
+}
+#else
+#define                set_col_gpio_val(x, y)  do {} while (0)
+#define                get_row_gpio_val(x)     0
+#endif
+
+static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
+                                    struct pt_regs *regs)
+{
+       struct omap_kp *omap_kp = dev_id;
+
+       /* disable keyboard interrupt and schedule for handling */
+       if (cpu_is_omap24xx()) {
+               int i;
+               for (i = 0; i < omap_kp->rows; i++)
+                       disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
+       } else
+               /* disable keyboard interrupt and schedule for handling */
+               omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+       tasklet_schedule(&kp_tasklet);
+
+       return IRQ_HANDLED;
+}
+
+static void omap_kp_timer(unsigned long data)
+{
+       tasklet_schedule(&kp_tasklet);
+}
+
+static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
+{
+       int col = 0;
+
+       /* read the keypad status */
+       if (cpu_is_omap24xx()) {
+               int i;
+               for (i = 0; i < omap_kp->rows; i++)
+                       disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
+
+               /* read the keypad status */
+               for (col = 0; col < omap_kp->cols; col++) {
+                       set_col_gpio_val(omap_kp, ~(1 << col));
+                       state[col] = ~(get_row_gpio_val(omap_kp)) & 0x3f;
+               }
+               set_col_gpio_val(omap_kp, 0);
+
+       } else {
+               /* disable keyboard interrupt and schedule for handling */
+               omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+               /* read the keypad status */
+               omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+               for (col = 0; col < omap_kp->cols; col++) {
+                       omap_writew(~(1 << col) & 0xff,
+                                   OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+
+                       udelay(omap_kp->delay);
+
+                       state[col] = ~omap_readw(OMAP_MPUIO_BASE +
+                                                OMAP_MPUIO_KBR_LATCH) & 0xff;
+               }
+               omap_writew(0x00, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+               udelay(2);
+       }
+}
+
+static inline int omap_kp_find_key(int col, int row)
+{
+       int i, key;
+
+       key = KEY(col, row, 0);
+       for (i = 0; keymap[i] != 0; i++)
+               if ((keymap[i] & 0xff000000) == key)
+                       return keymap[i] & 0x00ffffff;
+       return -1;
+}
+
+static void omap_kp_tasklet(unsigned long data)
+{
+       struct omap_kp *omap_kp_data = (struct omap_kp *) data;
+       unsigned char new_state[8], changed, key_down = 0;
+       int col, row;
+       int spurious = 0;
+
+       /* check for any changes */
+       omap_kp_scan_keypad(omap_kp_data, new_state);
+
+       /* check for changes and print those */
+       for (col = 0; col < omap_kp_data->cols; col++) {
+               changed = new_state[col] ^ keypad_state[col];
+               key_down |= new_state[col];
+               if (changed == 0)
+                       continue;
+
+               for (row = 0; row < omap_kp_data->rows; row++) {
+                       int key;
+                       if (!(changed & (1 << row)))
+                               continue;
+#ifdef NEW_BOARD_LEARNING_MODE
+                       printk(KERN_INFO "omap-keypad: key %d-%d %s\n", col,
+                              row, (new_state[col] & (1 << row)) ?
+                              "pressed" : "released");
+#else
+                       key = omap_kp_find_key(col, row);
+                       if (key < 0) {
+                               printk(KERN_WARNING
+                                     "omap-keypad: Spurious key event %d-%d\n",
+                                      col, row);
+                               /* We scan again after a couple of seconds */
+                               spurious = 1;
+                               continue;
+                       }
+
+                       if (!(kp_cur_group == (key & GROUP_MASK) ||
+                             kp_cur_group == -1))
+                               continue;
+
+                       kp_cur_group = key & GROUP_MASK;
+                       input_report_key(omap_kp_data->input, key & ~GROUP_MASK,
+                                        new_state[col] & (1 << row));
+#endif
+               }
+       }
+       memcpy(keypad_state, new_state, sizeof(keypad_state));
+
+       if (key_down) {
+                int delay = HZ / 20;
+               /* some key is pressed - keep irq disabled and use timer
+                * to poll the keypad */
+               if (spurious)
+                       delay = 2 * HZ;
+               mod_timer(&omap_kp_data->timer, jiffies + delay);
+       } else {
+               /* enable interrupts */
+               if (cpu_is_omap24xx()) {
+                       int i;
+                       for (i = 0; i < omap_kp_data->rows; i++)
+                               enable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
+               } else {
+                       omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+                       kp_cur_group = -1;
+               }
+       }
+}
+
+static ssize_t omap_kp_enable_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", kp_enable);
+}
+
+static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       int state;
+
+       if (sscanf(buf, "%u", &state) != 1)
+               return -EINVAL;
+
+       if ((state != 1) && (state != 0))
+               return -EINVAL;
+
+       mutex_lock(&kp_enable_mutex);
+       if (state != kp_enable) {
+               if (state)
+                       enable_irq(INT_KEYBOARD);
+               else
+                       disable_irq(INT_KEYBOARD);
+               kp_enable = state;
+       }
+       mutex_unlock(&kp_enable_mutex);
+
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store);
+
+#ifdef CONFIG_PM
+static int omap_kp_suspend(struct platform_device *dev, pm_message_t state)
+{
+       /* Nothing yet */
+
+       return 0;
+}
+
+static int omap_kp_resume(struct platform_device *dev)
+{
+       /* Nothing yet */
+
+       return 0;
+}
+#else
+#define omap_kp_suspend        NULL
+#define omap_kp_resume NULL
+#endif
+
+static int __init omap_kp_probe(struct platform_device *pdev)
+{
+       struct omap_kp *omap_kp;
+       struct input_dev *input_dev;
+       struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
+       int i, col_idx, row_idx, irq_idx, ret;
+
+       if (!pdata->rows || !pdata->cols || !pdata->keymap) {
+               printk(KERN_ERR "No rows, cols or keymap from pdata\n");
+               return -EINVAL;
+       }
+
+       omap_kp = kzalloc(sizeof(struct omap_kp), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!omap_kp || !input_dev) {
+               kfree(omap_kp);
+               input_free_device(input_dev);
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, omap_kp);
+
+       omap_kp->input = input_dev;
+
+       /* Disable the interrupt for the MPUIO keyboard */
+       if (!cpu_is_omap24xx())
+               omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+       keymap = pdata->keymap;
+
+       if (pdata->rep)
+               set_bit(EV_REP, input_dev->evbit);
+
+       if (pdata->delay)
+               omap_kp->delay = pdata->delay;
+
+       if (pdata->row_gpios && pdata->col_gpios) {
+               row_gpios = pdata->row_gpios;
+               col_gpios = pdata->col_gpios;
+       }
+
+       omap_kp->rows = pdata->rows;
+       omap_kp->cols = pdata->cols;
+
+       if (cpu_is_omap24xx()) {
+               /* Cols: outputs */
+               for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
+                       if (omap_request_gpio(col_gpios[col_idx]) < 0) {
+                               printk(KERN_ERR "Failed to request"
+                                      "GPIO%d for keypad\n",
+                                      col_gpios[col_idx]);
+                               goto err1;
+                       }
+                       omap_set_gpio_direction(col_gpios[col_idx], 0);
+               }
+               /* Rows: inputs */
+               for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
+                       if (omap_request_gpio(row_gpios[row_idx]) < 0) {
+                               printk(KERN_ERR "Failed to request"
+                                      "GPIO%d for keypad\n",
+                                      row_gpios[row_idx]);
+                               goto err2;
+                       }
+                       omap_set_gpio_direction(row_gpios[row_idx], 1);
+               }
+       }
+
+       setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
+
+       /* get the irq and init timer*/
+       tasklet_enable(&kp_tasklet);
+       kp_tasklet.data = (unsigned long) omap_kp;
+
+       ret = device_create_file(&pdev->dev, &dev_attr_enable);
+       if (ret < 0)
+               goto err2;
+
+       /* setup input device */
+       set_bit(EV_KEY, input_dev->evbit);
+       for (i = 0; keymap[i] != 0; i++)
+               set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
+       input_dev->name = "omap-keypad";
+       input_dev->phys = "omap-keypad/input0";
+       input_dev->cdev.dev = &pdev->dev;
+       input_dev->private = omap_kp;
+
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor = 0x0001;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0100;
+
+       input_dev->keycode = keymap;
+       input_dev->keycodesize = sizeof(unsigned int);
+       input_dev->keycodemax = pdata->keymapsize;
+
+       ret = input_register_device(omap_kp->input);
+       if (ret < 0) {
+               printk(KERN_ERR "Unable to register omap-keypad input device\n");
+               goto err3;
+       }
+
+       if (pdata->dbounce)
+               omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
+
+       /* scan current status and enable interrupt */
+       omap_kp_scan_keypad(omap_kp, keypad_state);
+       if (!cpu_is_omap24xx()) {
+               omap_kp->irq = platform_get_irq(pdev, 0);
+               if (omap_kp->irq >= 0) {
+                       if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
+                                       "omap-keypad", omap_kp) < 0)
+                               goto err4;
+               }
+               omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+       } else {
+               for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
+                       if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]),
+                                       omap_kp_interrupt,
+                                       IRQF_TRIGGER_FALLING,
+                                       "omap-keypad", omap_kp) < 0)
+                               goto err5;
+               }
+       }
+       return 0;
+err5:
+       for (i = irq_idx-1; i >=0; i--)
+               free_irq(row_gpios[i], 0);
+err4:
+       input_unregister_device(omap_kp->input);
+       input_dev = NULL;
+err3:
+       device_remove_file(&pdev->dev, &dev_attr_enable);
+err2:
+       for (i = row_idx-1; i >=0; i--)
+               omap_free_gpio(row_gpios[i]);
+err1:
+       for (i = col_idx-1; i >=0; i--)
+               omap_free_gpio(col_gpios[i]);
+
+       kfree(omap_kp);
+       input_free_device(input_dev);
+
+       return -EINVAL;
+}
+
+static int omap_kp_remove(struct platform_device *pdev)
+{
+       struct omap_kp *omap_kp = platform_get_drvdata(pdev);
+
+       /* disable keypad interrupt handling */
+       tasklet_disable(&kp_tasklet);
+       if (cpu_is_omap24xx()) {
+               int i;
+               for (i = 0; i < omap_kp->cols; i++)
+                       omap_free_gpio(col_gpios[i]);
+               for (i = 0; i < omap_kp->rows; i++) {
+                       omap_free_gpio(row_gpios[i]);
+                       free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0);
+               }
+       } else {
+               omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+               free_irq(omap_kp->irq, 0);
+       }
+
+       del_timer_sync(&omap_kp->timer);
+       tasklet_kill(&kp_tasklet);
+
+       /* unregister everything */
+       input_unregister_device(omap_kp->input);
+
+       kfree(omap_kp);
+
+       return 0;
+}
+
+static struct platform_driver omap_kp_driver = {
+       .probe          = omap_kp_probe,
+       .remove         = omap_kp_remove,
+       .suspend        = omap_kp_suspend,
+       .resume         = omap_kp_resume,
+       .driver         = {
+               .name   = "omap-keypad",
+       },
+};
+
+static int __devinit omap_kp_init(void)
+{
+       printk(KERN_INFO "OMAP Keypad Driver\n");
+       return platform_driver_register(&omap_kp_driver);
+}
+
+static void __exit omap_kp_exit(void)
+{
+       platform_driver_unregister(&omap_kp_driver);
+}
+
+module_init(omap_kp_init);
+module_exit(omap_kp_exit);
+
+MODULE_AUTHOR("Timo Teräs");
+MODULE_DESCRIPTION("OMAP Keypad Driver");
+MODULE_LICENSE("GPL");
index cc21914fbc72360967c117138fe75eab3db907fe..3b4e13b9ce1b9ac7317335c49f7b5bed8f854524 100644 (file)
@@ -67,25 +67,22 @@ static inline int i8042_platform_init(void)
  * On some platforms touching the i8042 data register region can do really
  * bad things. Because of this the region is always reserved on such boxes.
  */
-#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC_MERGE)
-       if (!request_region(I8042_DATA_REG, 16, "i8042"))
-               return -EBUSY;
-#endif
-
-        i8042_reset = 1;
-
 #if defined(CONFIG_PPC_MERGE)
        if (check_legacy_ioport(I8042_DATA_REG))
-               return -EBUSY;
+               return -ENODEV;
+#endif
+#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__)
        if (!request_region(I8042_DATA_REG, 16, "i8042"))
                return -EBUSY;
 #endif
+
+       i8042_reset = 1;
        return 0;
 }
 
 static inline void i8042_platform_exit(void)
 {
-#if !defined(__sh__) && !defined(__alpha__) && !defined(CONFIG_PPC64)
+#if !defined(__sh__) && !defined(__alpha__)
        release_region(I8042_DATA_REG, 16);
 #endif
 }
index fa97e0f79e7eaaa7779a0a819ddb875251035712..ee6c2f40cdf6d6c5ca14603ace5e7d69a6e7029d 100644 (file)
@@ -15,7 +15,6 @@
 #define HP680_TS_ABS_Y_MIN     80
 #define HP680_TS_ABS_Y_MAX     910
 
-#define        SCPCR   0xa4000116
 #define        PHDR    0xa400012e
 #define SCPDR  0xa4000136
 
@@ -77,19 +76,6 @@ static irqreturn_t hp680_ts_interrupt(int irq, void *dev, struct pt_regs *regs)
 
 static int __init hp680_ts_init(void)
 {
-       u8 scpdr;
-       u16 scpcr;
-
-       scpdr = ctrl_inb(SCPDR);
-       scpdr |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
-       scpdr &= ~SCPDR_TS_SCAN_ENABLE;
-       ctrl_outb(scpdr, SCPDR);
-
-       scpcr = ctrl_inw(SCPCR);
-       scpcr &= ~SCPCR_TS_MASK;
-       scpcr |= SCPCR_TS_ENABLE;
-       ctrl_outw(scpcr, SCPCR);
-
        hp680_ts_dev = input_allocate_device();
        if (!hp680_ts_dev)
                return -ENOMEM;
index 9ea6bd0ddc35bdcb2fc532b00a84e0760829e136..2dd1b57b0ba4959ab9578eb9de478410225e7094 100644 (file)
@@ -104,7 +104,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
        inode->i_ino = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_blocks = 0;
-       inode->i_blksize = 1024;
        inode->i_uid = inode->i_gid = 0;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
        inode->i_op = &simple_dir_inode_operations;
@@ -149,7 +148,6 @@ void capifs_new_ncci(unsigned int number, dev_t device)
        if (!inode)
                return;
        inode->i_ino = number+2;
-       inode->i_blksize = 1024;
        inode->i_uid = config.setuid ? config.uid : current->fsuid;
        inode->i_gid = config.setgid ? config.gid : current->fsgid;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
index 3845defd49010b840f781740ddbc7d5290e15f5d..5cfbe6a380101cb2f099b83acbb124e4b09e70a2 100644 (file)
@@ -192,7 +192,7 @@ static char *get_usb_statmsg(int status)
                return "bit stuffing error, timeout, or unknown USB error";
        case -EILSEQ:
                return "CRC mismatch, timeout, or unknown USB error";
-       case -ETIMEDOUT:
+       case -ETIME:
                return "timed out";
        case -EPIPE:
                return "endpoint stalled";
index b44950e06f3289772c431112834a6f5c7dddf5ff..fec1e381a6880791e7b1ba306c9acda4781d9790 100644 (file)
@@ -34,9 +34,6 @@
  *
  * I/O functions returns -1 on error, 0 on EOF
  */
-#define OS_SEEK_SET 0
-#define OS_SEEK_CUR 1
-#define OS_SEEK_END 2
 struct _OsFileHandle_;
 typedef long (  * OsFileIo)  (struct _OsFileHandle_    *handle,
                                 void                     *buffer,
index ec52c1a7c22afca97308f353e139eead2dd2b33a..6349367ed48096a93c436be1e5bfb84deb817873 100644 (file)
@@ -137,11 +137,11 @@ static struct hfcusb_symbolic_list urb_errlist[] = {
        {-ENXIO, "URB already queued"},
        {-EFBIG, "Too much ISO frames requested"},
        {-ENOSR, "Buffer error (overrun)"},
-       {-EPIPE, "Specified endpoint is stalled (device not responding)"},
+       {-EPIPE, "Specified endpoint is stalled"},
        {-EOVERFLOW, "Babble (bad cable?)"},
        {-EPROTO, "Bit-stuff error (bad cable?)"},
-       {-EILSEQ, "CRC/Timeout"},
-       {-ETIMEDOUT, "NAK (device does not respond)"},
+       {-EILSEQ, "CRC or missing token"},
+       {-ETIME, "Device did not respond"},
        {-ESHUTDOWN, "Device unplugged"},
        {-1, NULL}
 };
index 43da8ae1b2ada35d4b2f2bf51ef9a4f2a37f74a5..1f8d6ae66b41e47ac2be94ef6d44d25ffdc72b7b 100644 (file)
@@ -1614,8 +1614,8 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
        struct sk_buff *skb;
        unsigned char *p;
        struct in_device *in_dev = NULL;
-       u32 addr = 0;           /* local ipv4 address */
-       u32 mask = 0;           /* local netmask */
+       __be32 addr = 0;                /* local ipv4 address */
+       __be32 mask = 0;                /* local netmask */
 
        if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) {
                /* take primary(first) address of interface */
index 47f0ff196328d2808268a17701444b08faafee1a..454fb0901f8211dc31ec6b86e6edac5bec774286 100644 (file)
@@ -125,6 +125,7 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
                write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
                if (led_cdev->trigger->deactivate)
                        led_cdev->trigger->deactivate(led_cdev);
+               led_set_brightness(led_cdev, LED_OFF);
        }
        if (trigger) {
                write_lock_irqsave(&trigger->leddev_list_lock, flags);
index 713c4a8aa77dc347af774edc6ddf2f11fe58176b..45ba3d45bcb8a8387461883ae050aa308213a812 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/leds.h>
 #include <linux/err.h>
 #include <asm/io.h>
+#include <linux/nsc_gpio.h>
 #include <linux/scx200_gpio.h>
 
 #define DRVNAME "net48xx-led"
@@ -26,10 +27,7 @@ static struct platform_device *pdev;
 static void net48xx_error_led_set(struct led_classdev *led_cdev,
                enum led_brightness value)
 {
-       if (value)
-               scx200_gpio_set_high(NET48XX_ERROR_LED_GPIO);
-       else
-               scx200_gpio_set_low(NET48XX_ERROR_LED_GPIO);
+       scx200_gpio_ops.gpio_set(NET48XX_ERROR_LED_GPIO, value ? 1 : 0);
 }
 
 static struct led_classdev net48xx_error_led = {
@@ -81,7 +79,8 @@ static int __init net48xx_led_init(void)
 {
        int ret;
 
-       if (!scx200_gpio_present()) {
+       /* small hack, but scx200_gpio doesn't set .dev if the probe fails */
+       if (!scx200_gpio_ops.dev) {
                ret = -ENODEV;
                goto out;
        }
index 090e40fc501335115e51c5c3138354b0dbccedd7..c0f9d82e46625593773f77733cfbe4fe3f979700 100644 (file)
@@ -870,7 +870,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd)
 
 static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len)
 {
-       DECLARE_COMPLETION(comp);
+       DECLARE_COMPLETION_ONSTACK(comp);
        unsigned int chunk;
        struct smu_cmd cmd;
        int rc;
@@ -917,7 +917,7 @@ static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len)
 
 static struct smu_sdbp_header *smu_create_sdb_partition(int id)
 {
-       DECLARE_COMPLETION(comp);
+       DECLARE_COMPLETION_ONSTACK(comp);
        struct smu_simple_cmd cmd;
        unsigned int addr, len, tlen;
        struct smu_sdbp_header *hdr;
index a82f313d9dc97681a8d7220d25d1faa5de6eceb0..6c29fe727c0f4ea7ee30d1daac58dc5efc309fc6 100644 (file)
@@ -16,7 +16,7 @@
 #define MAX_PMU_LEVEL 0xFF
 
 static struct backlight_properties pmu_backlight_data;
-static spinlock_t pmu_backlight_lock;
+static DEFINE_SPINLOCK(pmu_backlight_lock);
 static int sleeping;
 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
 
index dda03985dcf5b804cdf7c6724561012523660942..80b89649e676a197fe941371f3fa64e5040d7a4a 100644 (file)
@@ -1827,7 +1827,7 @@ pbook_alloc_pci_save(void)
        struct pci_dev *pd = NULL;
 
        npci = 0;
-       while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
                ++npci;
        }
        if (npci == 0)
@@ -1857,9 +1857,11 @@ pbook_pci_save(void)
        if (ps == NULL)
                return;
 
-       while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-               if (npci-- == 0)
+       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+               if (npci-- == 0) {
+                       pci_dev_put(pd);
                        return;
+               }
 #ifndef HACKED_PCI_SAVE
                pci_read_config_word(pd, PCI_COMMAND, &ps->command);
                pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
@@ -1887,11 +1889,13 @@ pbook_pci_restore(void)
        int npci = pbook_npci_saves;
        int j;
 
-       while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
 #ifdef HACKED_PCI_SAVE
                int i;
-               if (npci-- == 0)
+               if (npci-- == 0) {
+                       pci_dev_put(pd);
                        return;
+               }
                ps++;
                for (i=2;i<16;i++)
                        pci_write_config_dword(pd, i<<4, ps->config[i]);
index 35b70323e7e3069e13382e4e44e18c944bd9881a..9f4eff1d1a0f672f0b3714b2ec2460ea177be3d1 100644 (file)
@@ -843,7 +843,7 @@ pbook_pci_save(void)
        struct pci_save *ps;
 
        npci = 0;
-       while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL)
+       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL)
                ++npci;
        n_pbook_pci_saves = npci;
        if (npci == 0)
@@ -854,7 +854,7 @@ pbook_pci_save(void)
                return;
 
        pd = NULL;
-       while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
                pci_read_config_word(pd, PCI_COMMAND, &ps->command);
                pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
                pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
@@ -871,7 +871,7 @@ pbook_pci_restore(void)
        struct pci_dev *pd = NULL;
        int j;
 
-       while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
                if (ps->command == 0)
                        continue;
                pci_read_config_word(pd, PCI_COMMAND, &cmd);
index bff1f372f1885ebe5082048d48e580c8e008a8a8..31b750d61206acd13091d39a68218d0e251284e8 100644 (file)
@@ -56,7 +56,7 @@ static int smu_set_fan(int pwm, u8 id, u16 value)
 {
        struct smu_cmd cmd;
        u8 buffer[16];
-       DECLARE_COMPLETION(comp);
+       DECLARE_COMPLETION_ONSTACK(comp);
        int rc;
 
        /* Fill SMU command structure */
index aceb61d9fbc8dcbc377610ac0f95e4f6b5d1c40f..83f79de7174beea3859afa905fe31b73a2bb50e4 100644 (file)
@@ -397,12 +397,7 @@ static int wf_sat_detach(struct i2c_client *client)
 
 static int __init sat_sensors_init(void)
 {
-       int err;
-
-       err = i2c_add_driver(&wf_sat_driver);
-       if (err < 0)
-               return err;
-       return 0;
+       return i2c_add_driver(&wf_sat_driver);
 }
 
 static void __exit sat_sensors_exit(void)
index defe9922ebd1b0ba287312c294d9de2fbfa122d5..01b4c50143ddc77010b0ef72bc57f85f11861a5d 100644 (file)
@@ -67,7 +67,7 @@ static void smu_ads_release(struct wf_sensor *sr)
 static int smu_read_adc(u8 id, s32 *value)
 {
        struct smu_simple_cmd   cmd;
-       DECLARE_COMPLETION(comp);
+       DECLARE_COMPLETION_ONSTACK(comp);
        int rc;
 
        rc = smu_queue_simple(&cmd, SMU_CMD_READ_ADC, 1,
index bf869ed03eed33c9b61c7c4c46d78e621b0e1b0e..6dd31a291d8436af9821d0b465866208daec3cd5 100644 (file)
@@ -2,6 +2,8 @@
 # Block device driver configuration
 #
 
+if BLOCK
+
 menu "Multi-device support (RAID and LVM)"
 
 config MD
@@ -251,3 +253,4 @@ config DM_MULTIPATH_EMC
 
 endmenu
 
+endif
index 2a374ccb30ddc0dcb165c7736c5d3abe6eab1fb0..2b2d45d7baaaaf55f9cfb45ff9b755587fc83d61 100644 (file)
@@ -126,7 +126,8 @@ static struct request *get_failover_req(struct emc_handler *h,
        memset(&rq->cmd, 0, BLK_MAX_CDB);
 
        rq->timeout = EMC_FAILOVER_TIMEOUT;
-       rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE);
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
+       rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
 
        return rq;
 }
index 1a04db4552da9dc2521867eaff7fd4c5666c7d89..f33e5d973413c2a1c064c66111c7f111383024dd 100644 (file)
@@ -4,7 +4,6 @@ config VIDEO_SAA7146
 
 config VIDEO_SAA7146_VV
        tristate
-       select VIDEO_V4L2
        select VIDEO_BUF
        select VIDEO_VIDEOBUF
        select VIDEO_SAA7146
index ca98d94789476f7c7454dc3a034f2b752e68b990..db753443587acf5a2cf7deddbeafebcb4974f18d 100644 (file)
@@ -32,6 +32,37 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_empty);
 
+/* Michal Majchrowicz <mmajchrowicz@gmail.com> */
+IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = {
+       /* numeric */
+       [ 0x00 ] = KEY_0,
+       [ 0x01 ] = KEY_1,
+       [ 0x02 ] = KEY_2,
+       [ 0x03 ] = KEY_3,
+       [ 0x04 ] = KEY_4,
+       [ 0x05 ] = KEY_5,
+       [ 0x06 ] = KEY_6,
+       [ 0x07 ] = KEY_7,
+       [ 0x08 ] = KEY_8,
+       [ 0x09 ] = KEY_9,
+
+       [ 0x5c ] = KEY_POWER,     /* power       */
+       [ 0x20 ] = KEY_F,         /* full screen */
+       [ 0x0f ] = KEY_BACKSPACE, /* recall      */
+       [ 0x1b ] = KEY_ENTER,     /* mute        */
+       [ 0x41 ] = KEY_RECORD,    /* record      */
+       [ 0x43 ] = KEY_STOP,      /* stop        */
+       [ 0x16 ] = KEY_S,
+       [ 0x1a ] = KEY_Q,         /* off         */
+       [ 0x2e ] = KEY_RED,
+       [ 0x1f ] = KEY_DOWN,      /* channel -   */
+       [ 0x1c ] = KEY_UP,        /* channel +   */
+       [ 0x10 ] = KEY_LEFT,      /* volume -    */
+       [ 0x1e ] = KEY_RIGHT,     /* volume +    */
+       [ 0x14 ] = KEY_F1,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_proteus_2309);
 /* Matt Jesson <dvb@jesson.eclipse.co.uk */
 IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
        [ 0x28 ] = KEY_0,         //'0' / 'enter'
@@ -1473,3 +1504,51 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_npgtech);
+
+/* Norwood Micro (non-Pro) TV Tuner
+   By Peter Naulls <peter@chocky.org>
+   Key comments are the functions given in the manual */
+IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
+       /* Keys 0 to 9 */
+       [ 0x20 ] = KEY_0,
+       [ 0x21 ] = KEY_1,
+       [ 0x22 ] = KEY_2,
+       [ 0x23 ] = KEY_3,
+       [ 0x24 ] = KEY_4,
+       [ 0x25 ] = KEY_5,
+       [ 0x26 ] = KEY_6,
+       [ 0x27 ] = KEY_7,
+       [ 0x28 ] = KEY_8,
+       [ 0x29 ] = KEY_9,
+
+       [ 0x78 ] = KEY_TUNER,             /* Video Source        */
+       [ 0x2c ] = KEY_EXIT,              /* Open/Close software */
+       [ 0x2a ] = KEY_SELECT,            /* 2 Digit Select      */
+       [ 0x69 ] = KEY_AGAIN,             /* Recall              */
+
+       [ 0x32 ] = KEY_BRIGHTNESSUP,      /* Brightness increase */
+       [ 0x33 ] = KEY_BRIGHTNESSDOWN,    /* Brightness decrease */
+       [ 0x6b ] = KEY_KPPLUS,            /* (not named >>>>>)   */
+       [ 0x6c ] = KEY_KPMINUS,           /* (not named <<<<<)   */
+
+       [ 0x2d ] = KEY_MUTE,              /* Mute                */
+       [ 0x30 ] = KEY_VOLUMEUP,          /* Volume up           */
+       [ 0x31 ] = KEY_VOLUMEDOWN,        /* Volume down         */
+       [ 0x60 ] = KEY_CHANNELUP,         /* Channel up          */
+       [ 0x61 ] = KEY_CHANNELDOWN,       /* Channel down        */
+
+       [ 0x3f ] = KEY_RECORD,            /* Record              */
+       [ 0x37 ] = KEY_PLAY,              /* Play                */
+       [ 0x36 ] = KEY_PAUSE,             /* Pause               */
+       [ 0x2b ] = KEY_STOP,              /* Stop                */
+       [ 0x67 ] = KEY_FASTFORWARD,       /* Foward              */
+       [ 0x66 ] = KEY_REWIND,            /* Rewind              */
+       [ 0x3e ] = KEY_SEARCH,            /* Auto Scan           */
+       [ 0x2e ] = KEY_CAMERA,            /* Capture Video       */
+       [ 0x6d ] = KEY_MENU,              /* Show/Hide Control   */
+       [ 0x2f ] = KEY_ZOOM,              /* Full Screen         */
+       [ 0x34 ] = KEY_RADIO,             /* FM                  */
+       [ 0x65 ] = KEY_POWER,             /* Computer power      */
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_norwood);
index 0027acc5b8e988b2a271ae79d1a90a96acbbd5d8..d867a6a9e43065335894bf93da8f00bc74a46c67 100644 (file)
@@ -455,7 +455,6 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
 
 static struct video_device device_template =
 {
-       .hardware       = VID_HARDWARE_SAA7146,
        .fops           = &video_fops,
        .minor          = -1,
 };
index 49a06fc54c51add4cb30df21303b0419db633171..a0dcd59da76e5833502814abf62d66eda780ae79 100644 (file)
@@ -2,13 +2,13 @@ config DVB_B2C2_FLEXCOP
        tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
        depends on DVB_CORE && I2C
        select DVB_PLL
-       select DVB_STV0299
-       select DVB_MT352
-       select DVB_MT312
-       select DVB_NXT200X
-       select DVB_STV0297
-       select DVB_BCM3510
-       select DVB_LGDT330X
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_MT312 if !DVB_FE_CUSTOMISE
+       select DVB_NXT200X if !DVB_FE_CUSTOMISE
+       select DVB_STV0297 if !DVB_FE_CUSTOMISE
+       select DVB_BCM3510 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        help
          Support for the digital TV receiver chip made by B2C2 Inc. included in
          Technisats PCI cards and USB boxes.
index 3be87c72e37b7f6bf13053f3db75a0fd9a4229af..b8ba8786345783e107aa6e7a31babc4ff0cd6bd4 100644 (file)
@@ -505,7 +505,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        struct dvb_frontend_ops *ops;
 
        /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
-       if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
@@ -519,36 +519,36 @@ int flexcop_frontend_init(struct flexcop_device *fc)
                info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
        } else
        /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
-       if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
+       if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
                fc->dev_type          = FC_AIR_DVB;
                fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
                info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
        } else
        /* try the air atsc 2nd generation (nxt2002) */
-       if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC2;
-               dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
+               dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
                info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
        } else
        /* try the air atsc 3nd generation (lgdt3303) */
-       if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC3;
                fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
                info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
        } else
        /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
-       if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC1;
                info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
        } else
        /* try the cable dvb (stv0297) */
-       if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type                        = FC_CABLE;
                fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
                info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
        } else
        /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
-       if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
@@ -571,9 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        } else {
                if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
                        err("frontend registration failed!");
-                       ops = &fc->fe->ops;
-                       if (ops->release != NULL)
-                               ops->release(fc->fe);
+                       dvb_frontend_detach(fc->fe);
                        fc->fe = NULL;
                        return -EINVAL;
                }
@@ -584,8 +582,10 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 
 void flexcop_frontend_exit(struct flexcop_device *fc)
 {
-       if (fc->init_state & FC_STATE_FE_INIT)
+       if (fc->init_state & FC_STATE_FE_INIT) {
                dvb_unregister_frontend(fc->fe);
+               dvb_frontend_detach(fc->fe);
+       }
 
        fc->init_state &= ~FC_STATE_FE_INIT;
 }
index 7d0ee1ab2903c4bb06b5c16c7146f21f14f2ce9a..ae2ff5dc238d958d03f92fe9bf2a2c4d3926e93d 100644 (file)
@@ -2,13 +2,13 @@ config DVB_BT8XX
        tristate "BT8xx based PCI cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_BT848
        select DVB_PLL
-       select DVB_MT352
-       select DVB_SP887X
-       select DVB_NXT6000
-       select DVB_CX24110
-       select DVB_OR51211
-       select DVB_LGDT330X
-       select DVB_ZL10353
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_SP887X if !DVB_FE_CUSTOMISE
+       select DVB_NXT6000 if !DVB_FE_CUSTOMISE
+       select DVB_CX24110 if !DVB_FE_CUSTOMISE
+       select DVB_OR51211 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
index 06ac899a9a26931f3bc23b87cf9a1ae7a351a1a4..9f72b7000c080281e6149318a730b814348a9baf 100644 (file)
@@ -1715,6 +1715,15 @@ static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
 static void dst_release(struct dvb_frontend *fe)
 {
        struct dst_state *state = fe->demodulator_priv;
+       if (state->dst_ca) {
+               dvb_unregister_device(state->dst_ca);
+#ifdef CONFIG_DVB_CORE_ATTACH
+               symbol_put(dst_ca_attach);
+#endif
+       }
+#ifdef CONFIG_DVB_CORE_ATTACH
+       symbol_put(dst_attach);
+#endif
        kfree(state);
 }
 
index fa923b9b346ea99440dceeac23e695c4c4b3a193..240ad084fa787ae4f5dc07b0acf47f25d2554b5c 100644 (file)
@@ -699,12 +699,17 @@ static struct dvb_device dvbdev_ca = {
        .fops = &dst_ca_fops
 };
 
-int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
+struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
 {
        struct dvb_device *dvbdev;
+
        dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
-       dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
-       return 0;
+       if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
+               dst->dst_ca = dvbdev;
+               return dst->dst_ca;
+       }
+
+       return NULL;
 }
 
 EXPORT_SYMBOL(dst_ca_attach);
index 0677b047b3a78be3381046c3ef0eb88e576cf5c3..3bf084f2e5226b883aeca002b39e75b54de04801 100644 (file)
@@ -140,6 +140,7 @@ struct dst_state {
        char *tuner_name;
        struct mutex dst_mutex;
        u8 fw_name[8];
+       struct dvb_device *dst_ca;
 };
 
 struct tuner_types {
@@ -178,7 +179,7 @@ int write_dst(struct dst_state *state, u8 * data, u8 len);
 int read_dst(struct dst_state *state, u8 * ret, u8 len);
 u8 dst_check_sum(u8 * buf, u32 len);
 struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
-int dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
+struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
 int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay);
 
 int dst_command(struct dst_state* state, u8 * data, u8 len);
index b715b972d2fcfbfdbd495d5a1cc2ed558c60e632..fb6c4cc8477db818d04fb061f0893584b428690e 100644 (file)
@@ -67,7 +67,7 @@ static void dvb_bt8xx_task(unsigned long data)
 
 static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+       struct dvb_demux*dvbdmx = dvbdmxfeed->demux;
        struct dvb_bt8xx_card *card = dvbdmx->priv;
        int rc;
 
@@ -595,15 +595,14 @@ static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
 
 static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 {
-       int ret;
        struct dst_state* state = NULL;
 
        switch(type) {
        case BTTV_BOARD_DVICO_DVBT_LITE:
-               card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);
 
                if (card->fe == NULL)
-                       card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+                       card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,
                                                  card->i2c_adapter);
 
                if (card->fe != NULL) {
@@ -615,7 +614,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
        case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
                lgdt330x_reset(card);
-               card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
+               card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
@@ -630,7 +629,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
                /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
                digitv_alps_tded4_reset(card);
-               card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
+               card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
                        dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
@@ -639,7 +638,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
                /* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
                digitv_alps_tded4_reset(card);
-               card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);
 
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
@@ -648,14 +647,14 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                break;
 
        case BTTV_BOARD_AVDVBT_761:
-               card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+               card->fe = dvb_attach(sp887x_attach, &microtune_mt7202dtf_config, card->i2c_adapter);
                if (card->fe) {
                        card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
                }
                break;
 
        case BTTV_BOARD_AVDVBT_771:
-               card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
                        card->fe->ops.info.frequency_min = 174000000;
@@ -670,22 +669,21 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                state->config = &dst_config;
                state->i2c = card->i2c_adapter;
                state->bt = card->bt;
-
+               state->dst_ca = NULL;
                /*      DST is not a frontend, attaching the ASIC       */
-               if ((dst_attach(state, &card->dvb_adapter)) == NULL) {
+               if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
                        printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
                        break;
                }
-               card->fe = &state->frontend;
-
                /*      Attach other DST peripherals if any             */
                /*      Conditional Access device                       */
+               card->fe = &state->frontend;
                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-                       ret = dst_ca_attach(state, &card->dvb_adapter);
+                       dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
                break;
 
        case BTTV_BOARD_PINNACLESAT:
-               card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+               card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
                if (card->fe) {
                        card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
                        card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
@@ -694,7 +692,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                break;
 
        case BTTV_BOARD_PC_HDTV:
-               card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
+               card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
                break;
        }
 
@@ -707,8 +705,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        else
                if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
                        printk("dvb-bt8xx: Frontend registration failed!\n");
-                       if (card->fe->ops.release)
-                               card->fe->ops.release(card->fe);
+                       dvb_frontend_detach(card->fe);
                        card->fe = NULL;
                }
 }
@@ -925,8 +922,10 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
        card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
        dvb_dmxdev_release(&card->dmxdev);
        dvb_dmx_release(&card->demux);
-       if (card->fe)
+       if (card->fe) {
                dvb_unregister_frontend(card->fe);
+               dvb_frontend_detach(card->fe);
+       }
        dvb_unregister_adapter(&card->dvb_adapter);
 
        kfree(card);
index 12ee912a5705176af05f73be9e61ffa2e140687d..e46eae3b9be2624690746413bbb2c74601e2af54 100644 (file)
@@ -9,3 +9,16 @@ config DVB_CORE
          in-kernel drivers will select this automatically if needed.
          If unsure say N.
 
+config DVB_CORE_ATTACH
+       bool "Load and attach frontend modules as needed"
+       depends on DVB_CORE
+       depends on MODULES
+       help
+         Remove the static dependency of DVB card drivers on all
+         frontend modules for all possible card variants. Instead,
+         allow the card drivers to only load the frontend modules
+         they require. This saves several KBytes of memory.
+
+         Note: You will need moudule-init-tools v3.2 or later for this feature.
+
+         If unsure say Y.
index 57b34cda99f5a6f598b9786d42af22d58a19f70d..3dd5dbafb330634c400e57d58b198eb21ef5c9a0 100644 (file)
@@ -1105,18 +1105,42 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
        mutex_lock(&frontend_mutex);
        dvb_unregister_device (fepriv->dvbdev);
        dvb_frontend_stop (fe);
-       if (fe->ops.tuner_ops.release) {
-               fe->ops.tuner_ops.release(fe);
-               if (fe->ops.i2c_gate_ctrl)
-                       fe->ops.i2c_gate_ctrl(fe, 0);
-       }
-       if (fe->ops.release)
-               fe->ops.release(fe);
-       else
-               printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
+
        /* fe is invalid now */
        kfree(fepriv);
        mutex_unlock(&frontend_mutex);
        return 0;
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
+
+#ifdef CONFIG_DVB_CORE_ATTACH
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+       void *ptr;
+
+       if (fe->ops.release_sec) {
+               fe->ops.release_sec(fe);
+               symbol_put_addr(fe->ops.release_sec);
+       }
+       if (fe->ops.tuner_ops.release) {
+               fe->ops.tuner_ops.release(fe);
+               symbol_put_addr(fe->ops.tuner_ops.release);
+       }
+       ptr = (void*)fe->ops.release;
+       if (ptr) {
+               fe->ops.release(fe);
+               symbol_put_addr(ptr);
+       }
+}
+#else
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+       if (fe->ops.release_sec)
+               fe->ops.release_sec(fe);
+       if (fe->ops.tuner_ops.release)
+               fe->ops.tuner_ops.release(fe);
+       if (fe->ops.release)
+               fe->ops.release(fe);
+}
+#endif
+EXPORT_SYMBOL(dvb_frontend_detach);
index 2887e2b862a4436d1002a5dcee6ffafb1b5aba1f..e5d5028b3694fc68663da122664e6172095c596f 100644 (file)
@@ -92,10 +92,13 @@ struct dvb_frontend_ops {
        struct dvb_frontend_info info;
 
        void (*release)(struct dvb_frontend* fe);
+       void (*release_sec)(struct dvb_frontend* fe);
 
        int (*init)(struct dvb_frontend* fe);
        int (*sleep)(struct dvb_frontend* fe);
 
+       int (*write)(struct dvb_frontend* fe, u8* buf, int len);
+
        /* if this is set, it overrides the default swzigzag */
        int (*tune)(struct dvb_frontend* fe,
                    struct dvb_frontend_parameters* params,
@@ -147,7 +150,7 @@ struct dvb_frontend {
        void* demodulator_priv;
        void* tuner_priv;
        void* frontend_priv;
-       void* misc_priv;
+       void* sec_priv;
 };
 
 extern int dvb_register_frontend(struct dvb_adapter* dvb,
@@ -155,6 +158,8 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
 
 extern int dvb_unregister_frontend(struct dvb_frontend* fe);
 
+extern void dvb_frontend_detach(struct dvb_frontend* fe);
+
 extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
 
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
index 7a7f75fd168c30f19bf622a349322994914ca336..620e7887b3d3b11c155d65cbbddc12dfdd284555 100644 (file)
@@ -102,4 +102,26 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
                            int (*func)(struct inode *inode, struct file *file,
                            unsigned int cmd, void *arg));
 
+/** generic DVB attach function. */
+#ifdef CONFIG_DVB_CORE_ATTACH
+#define dvb_attach(FUNCTION, ARGS...) ({ \
+       void *__r = NULL; \
+       typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+       if (__a) { \
+               __r = (void *) __a(ARGS); \
+               if (__r == NULL) \
+                       symbol_put(FUNCTION); \
+       } else { \
+               printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
+       } \
+       __r; \
+})
+
+#else
+#define dvb_attach(FUNCTION, ARGS...) ({ \
+       FUNCTION(ARGS); \
+})
+
+#endif
+
 #endif /* #ifndef _DVBDEV_H_ */
index 75824b77198ab2a2524f5d123c719455a1fdadfb..0a3c35399bea7480ef9bdcc84bc510e43704ade2 100644 (file)
@@ -26,6 +26,7 @@ config DVB_USB_A800
        tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
 
@@ -33,6 +34,7 @@ config DVB_USB_DIBUSB_MB
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
        depends on DVB_USB
        select DVB_DIB3000MB
+       select DVB_TUNER_MT2060
        help
          Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -65,6 +67,7 @@ config DVB_USB_DIBUSB_MC
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Support for 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -80,16 +83,17 @@ config DVB_USB_UMT_010
        tristate "HanfTek UMT-010 DVB-T USB2.0 support"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
 
 config DVB_USB_CXUSB
        tristate "Conexant USB2.0 hybrid reference design support"
        depends on DVB_USB
-       select DVB_CX22702
-       select DVB_LGDT330X
-       select DVB_MT352
-       select DVB_ZL10353
+       select DVB_CX22702 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
@@ -101,8 +105,8 @@ config DVB_USB_CXUSB
 config DVB_USB_DIGITV
        tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
        depends on DVB_USB
-       select DVB_NXT6000
-       select DVB_MT352
+       select DVB_NXT6000 if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
 
@@ -145,6 +149,7 @@ config DVB_USB_NOVA_T_USB2
        tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
 
index ce44aa6bbb838da936e9c41466819a9d226d64cf..df0c384bd4ca8a0d677afcd2507e04685d068648 100644 (file)
@@ -26,6 +26,13 @@ static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
        return 0;
 }
 
+/* assure to put cold to 0 for iManufacturer == 1 */
+static int a800_identify_state(struct usb_device *udev, struct dvb_usb_properties *props,struct dvb_usb_device_description **desc, int *cold)
+{
+       *cold = udev->descriptor.iManufacturer != 1;
+       return 0;
+}
+
 static struct dvb_usb_rc_key a800_rc_keys[] = {
        { 0x02, 0x01, KEY_PROG1 },       /* SOURCE */
        { 0x02, 0x00, KEY_POWER },       /* POWER */
@@ -113,6 +120,7 @@ static struct dvb_usb_properties a800_properties = {
        .power_ctrl       = a800_power_ctrl,
        .frontend_attach  = dibusb_dib3000mc_frontend_attach,
        .tuner_attach     = dibusb_dib3000mc_tuner_attach,
+       .identify_state   = a800_identify_state,
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = a800_rc_keys,
index ae23bdde42a82505271051024dd2d0509ec994cb..c710c0176e0737e9174d3529b88e3e5db69d3dc8 100644 (file)
@@ -349,6 +349,7 @@ static struct mt352_config cxusb_dee1601_config = {
 
 static struct zl10353_config cxusb_zl10353_dee1601_config = {
        .demod_address = 0x0f,
+       .parallel_ts = 1,
 };
 
 static struct mt352_config cxusb_mt352_config = {
@@ -409,7 +410,7 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
 
-       if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &d->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -422,7 +423,7 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -435,7 +436,7 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((d->fe = mt352_attach(&cxusb_mt352_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &d->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -448,8 +449,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
-           ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
+       if (((d->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
+               ((d->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
                return 0;
 
        return -EIO;
index abd75b4a350dab46c2d054d176edb991668f44bf..124e25ac53b3ce625660ed6819a2d92833fe1ab8 100644 (file)
@@ -131,9 +131,6 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
                return -EAGAIN;
 
-       if (num > 2)
-               warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
        for (i = 0; i < num; i++) {
                /* write/read request */
                if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
@@ -168,31 +165,137 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
 }
 EXPORT_SYMBOL(dibusb_read_eeprom_byte);
 
+/* 3000MC/P stuff */
+// Config Adjacent channels  Perf -cal22
+static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
+       .band_caps = BAND_VHF | BAND_UHF,
+       .setup     = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
+
+       .agc1_max = 48497,
+       .agc1_min = 23593,
+       .agc2_max = 46531,
+       .agc2_min = 24904,
+
+       .agc1_pt1 = 0x65,
+       .agc1_pt2 = 0x69,
+
+       .agc1_slope1 = 0x51,
+       .agc1_slope2 = 0x27,
+
+       .agc2_pt1 = 0,
+       .agc2_pt2 = 0x33,
+
+       .agc2_slope1 = 0x35,
+       .agc2_slope2 = 0x37,
+};
+
+static struct dib3000mc_config stk3000p_dib3000p_config = {
+       &dib3000p_mt2060_agc_config,
+
+       .max_time     = 0x196,
+       .ln_adc_level = 0x1cc7,
+
+       .output_mpeg2_in_188_bytes = 1,
+};
+
+static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
+       .setup    = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
+
+       .agc1_max = 56361,
+       .agc1_min = 22282,
+       .agc2_max = 47841,
+       .agc2_min = 36045,
+
+       .agc1_pt1 = 0x3b,
+       .agc1_pt2 = 0x6b,
+
+       .agc1_slope1 = 0x55,
+       .agc1_slope2 = 0x1d,
+
+       .agc2_pt1 = 0,
+       .agc2_pt2 = 0x0a,
+
+       .agc2_slope1 = 0x95,
+       .agc2_slope2 = 0x1e,
+};
+
+static struct dib3000mc_config mod3000p_dib3000p_config = {
+       &dib3000p_panasonic_agc_config,
+
+       .max_time     = 0x51,
+       .ln_adc_level = 0x1cc7,
+
+       .output_mpeg2_in_188_bytes = 1,
+};
+
 int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
 {
-       struct dib3000_config demod_cfg;
-       struct dibusb_state *st = d->priv;
-
-       for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
-               if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
-                       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-                       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
-                       d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
-                       return 0;
+       if (dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000P_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0 ||
+               dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000MC_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0) {
+               if (d->priv != NULL) {
+                       struct dibusb_state *st = d->priv;
+                       st->ops.pid_parse = dib3000mc_pid_parse;
+                       st->ops.pid_ctrl  = dib3000mc_pid_control;
                }
-
+               return 0;
+       }
        return -ENODEV;
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
 
+static struct mt2060_config stk3000p_mt2060_config = {
+       0x60
+};
+
 int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
 {
-       d->pll_addr = 0x60;
-       d->pll_desc = &dvb_pll_env57h1xd5;
-
-       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+       struct dibusb_state *st = d->priv;
+       int ret;
+       u8 a,b;
+       u16 if1 = 1220;
+       struct i2c_adapter *tun_i2c;
+
+       // First IF calibration for Liteon Sticks
+       if (d->udev->descriptor.idVendor == USB_VID_LITEON &&
+               d->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
+
+               dibusb_read_eeprom_byte(d,0x7E,&a);
+               dibusb_read_eeprom_byte(d,0x7F,&b);
+
+               if (a == 0x00)
+                       if1 += b;
+               else if (a == 0x80)
+                       if1 -= b;
+               else
+                       warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
+
+       } else if (d->udev->descriptor.idVendor  == USB_VID_DIBCOM &&
+                  d->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
+               u8 desc;
+               dibusb_read_eeprom_byte(d, 7, &desc);
+               if (desc == 2) {
+                       a = 127;
+                       do {
+                               dibusb_read_eeprom_byte(d, a, &desc);
+                               a--;
+                       } while (a > 7 && (desc == 0xff || desc == 0x00));
+                       if (desc & 0x80)
+                               if1 -= (0xff - desc);
+                       else
+                               if1 += desc;
+               }
+       }
 
+       tun_i2c = dib3000mc_get_tuner_i2c_master(d->fe, 1);
+       if ((ret = mt2060_attach(d->fe, tun_i2c, &stk3000p_mt2060_config, if1)) != 0) {
+               /* not found - use panasonic pll parameters */
+               if (dvb_pll_attach(d->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
+                       return -ENOMEM;
+       } else {
+               st->mt2060_present = 1;
+               /* set the correct parameters for the dib3000p */
+               dib3000mc_set_config(d->fe, &stk3000p_dib3000p_config);
+       }
        return 0;
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
@@ -267,6 +370,67 @@ struct dvb_usb_rc_key dibusb_rc_keys[] = {
        { 0x86, 0x1e, KEY_DOWN },
        { 0x86, 0x1f, KEY_LEFT },
        { 0x86, 0x1b, KEY_RIGHT },
+
+       /* Key codes for the DiBcom MOD3000 remote. */
+       { 0x80, 0x00, KEY_MUTE },
+       { 0x80, 0x01, KEY_TEXT },
+       { 0x80, 0x02, KEY_HOME },
+       { 0x80, 0x03, KEY_POWER },
+
+       { 0x80, 0x04, KEY_RED },
+       { 0x80, 0x05, KEY_GREEN },
+       { 0x80, 0x06, KEY_YELLOW },
+       { 0x80, 0x07, KEY_BLUE },
+
+       { 0x80, 0x08, KEY_DVD },
+       { 0x80, 0x09, KEY_AUDIO },
+       { 0x80, 0x0a, KEY_MEDIA },      /* Pictures */
+       { 0x80, 0x0b, KEY_VIDEO },
+
+       { 0x80, 0x0c, KEY_BACK },
+       { 0x80, 0x0d, KEY_UP },
+       { 0x80, 0x0e, KEY_RADIO },
+       { 0x80, 0x0f, KEY_EPG },
+
+       { 0x80, 0x10, KEY_LEFT },
+       { 0x80, 0x11, KEY_OK },
+       { 0x80, 0x12, KEY_RIGHT },
+       { 0x80, 0x13, KEY_UNKNOWN },    /* SAP */
+
+       { 0x80, 0x14, KEY_TV },
+       { 0x80, 0x15, KEY_DOWN },
+       { 0x80, 0x16, KEY_MENU },       /* DVD Menu */
+       { 0x80, 0x17, KEY_LAST },
+
+       { 0x80, 0x18, KEY_RECORD },
+       { 0x80, 0x19, KEY_STOP },
+       { 0x80, 0x1a, KEY_PAUSE },
+       { 0x80, 0x1b, KEY_PLAY },
+
+       { 0x80, 0x1c, KEY_PREVIOUS },
+       { 0x80, 0x1d, KEY_REWIND },
+       { 0x80, 0x1e, KEY_FASTFORWARD },
+       { 0x80, 0x1f, KEY_NEXT},
+
+       { 0x80, 0x40, KEY_1 },
+       { 0x80, 0x41, KEY_2 },
+       { 0x80, 0x42, KEY_3 },
+       { 0x80, 0x43, KEY_CHANNELUP },
+
+       { 0x80, 0x44, KEY_4 },
+       { 0x80, 0x45, KEY_5 },
+       { 0x80, 0x46, KEY_6 },
+       { 0x80, 0x47, KEY_CHANNELDOWN },
+
+       { 0x80, 0x48, KEY_7 },
+       { 0x80, 0x49, KEY_8 },
+       { 0x80, 0x4a, KEY_9 },
+       { 0x80, 0x4b, KEY_VOLUMEUP },
+
+       { 0x80, 0x4c, KEY_CLEAR },
+       { 0x80, 0x4d, KEY_0 },
+       { 0x80, 0x4e, KEY_ENTER },
+       { 0x80, 0x4f, KEY_VOLUMEDOWN },
 };
 EXPORT_SYMBOL(dibusb_rc_keys);
 
index f4c45f386ebc693992cb7a165bb76896c1c60086..effd34cc4b02d23601086904734a3b0ce78db57c 100644 (file)
@@ -21,11 +21,11 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
 
        demod_cfg.demod_address = 0x8;
 
-       if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
-               d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-               d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+       if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
                return -ENODEV;
-       }
+
+       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 
        d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 
@@ -169,7 +169,7 @@ static struct dvb_usb_properties dibusb1_1_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -247,7 +247,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -272,8 +272,8 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
 #endif
        .devices = {
                {       "Artec T1 USB1.1 TVBOX with AN2235",
-                       { &dibusb_dib3000mb_table[20], NULL },
                        { &dibusb_dib3000mb_table[21], NULL },
+                       { &dibusb_dib3000mb_table[22], NULL },
                },
 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
                {       "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
@@ -304,7 +304,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -355,7 +355,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
index 55802fba3c29ee71bc320cf056b6fa1a0c665eb7..eca4082a61ae4920b0e49b045b4d55ab21f6e837 100644 (file)
@@ -28,6 +28,17 @@ static struct usb_device_id dibusb_dib3000mc_table [] = {
 /* 00 */       { USB_DEVICE(USB_VID_DIBCOM,            USB_PID_DIBCOM_MOD3001_COLD) },
 /* 01 */       { USB_DEVICE(USB_VID_DIBCOM,            USB_PID_DIBCOM_MOD3001_WARM) },
 /* 02 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+/* 03 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, // ( ? )
+/* 04 */       { USB_DEVICE(USB_VID_LITEON,            USB_PID_LITEON_DVB_T_COLD) },
+/* 05 */       { USB_DEVICE(USB_VID_LITEON,            USB_PID_LITEON_DVB_T_WARM) },
+/* 06 */       { USB_DEVICE(USB_VID_EMPIA,             USB_PID_DIGIVOX_MINI_SL_COLD) },
+/* 07 */       { USB_DEVICE(USB_VID_EMPIA,             USB_PID_DIGIVOX_MINI_SL_WARM) },
+/* 08 */       { USB_DEVICE(USB_VID_GRANDTEC,          USB_PID_GRANDTEC_DVBT_USB2_COLD) },
+/* 09 */       { USB_DEVICE(USB_VID_GRANDTEC,          USB_PID_GRANDTEC_DVBT_USB2_WARM) },
+/* 10 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_COLD) },
+/* 11 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) },
+/* 12 */       { USB_DEVICE(USB_VID_LEADTEK,           USB_PID_WINFAST_DTV_DONGLE_COLD) },
+/* 13 */       { USB_DEVICE(USB_VID_LEADTEK,           USB_PID_WINFAST_DTV_DONGLE_WARM) },
                        { }             /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
@@ -50,7 +61,7 @@ static struct dvb_usb_properties dibusb_mc_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* FIXME */
+       .rc_key_map_size  = 111, /* FIXME */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -68,16 +79,38 @@ static struct dvb_usb_properties dibusb_mc_properties = {
                }
        },
 
-       .num_device_descs = 2,
+       .num_device_descs = 7,
        .devices = {
                {   "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
                        { &dibusb_dib3000mc_table[0], NULL },
                        { &dibusb_dib3000mc_table[1], NULL },
                },
-               {   "Artec T1 USB2.0 TVBOX (please report the warm ID)",
+               {   "Artec T1 USB2.0 TVBOX (please check the warm ID)",
                        { &dibusb_dib3000mc_table[2], NULL },
-                       { NULL },
+                       { &dibusb_dib3000mc_table[3], NULL },
                },
+               {   "LITE-ON USB2.0 DVB-T Tuner",
+                   /* Also rebranded as Intuix S800, Toshiba */
+                       { &dibusb_dib3000mc_table[4], NULL },
+                       { &dibusb_dib3000mc_table[5], NULL },
+               },
+               {   "MSI Digivox Mini SL",
+                       { &dibusb_dib3000mc_table[6], NULL },
+                       { &dibusb_dib3000mc_table[7], NULL },
+               },
+               {   "GRAND - USB2.0 DVB-T adapter",
+                       { &dibusb_dib3000mc_table[8], NULL },
+                       { &dibusb_dib3000mc_table[9], NULL },
+               },
+               {   "Artec T14 - USB2.0 DVB-T",
+                       { &dibusb_dib3000mc_table[10], NULL },
+                       { &dibusb_dib3000mc_table[11], NULL },
+               },
+               {   "Leadtek - USB2.0 Winfast DTV dongle",
+                       { &dibusb_dib3000mc_table[12], NULL },
+                       { &dibusb_dib3000mc_table[13], NULL },
+               },
+               { NULL },
        }
 };
 
index 2d99d05c7eab3c9f7dde14fa17db918d5e56233e..a43f87480cf608810a20c9c320a5f764770780e4 100644 (file)
@@ -17,6 +17,8 @@
 #include "dvb-usb.h"
 
 #include "dib3000.h"
+#include "dib3000mc.h"
+#include "mt2060.h"
 
 /*
  * protocol of all dibusb related devices
@@ -96,6 +98,7 @@
 
 struct dibusb_state {
        struct dib_fe_xfer_ops ops;
+       int mt2060_present;
 
        /* for RC5 remote control */
        int old_toggle;
index c14d9efb48fdb7162a809ba16b3cd5b207acebc0..015854487308b7b7f9c452dd429eb002d1350a3f 100644 (file)
@@ -128,11 +128,11 @@ static struct nxt6000_config digitv_nxt6000_config = {
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
-       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
+       if ((d->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &d->i2c_adap)) != NULL) {
                d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
                return 0;
        }
-       if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
+       if ((d->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
                d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
                return 0;
        }
@@ -147,21 +147,91 @@ static int digitv_tuner_attach(struct dvb_usb_device *d)
 }
 
 static struct dvb_usb_rc_key digitv_rc_keys[] = {
-       { 0x00, 0x16, KEY_POWER }, /* dummy key */
+       { 0x5f, 0x55, KEY_0 },
+       { 0x6f, 0x55, KEY_1 },
+       { 0x9f, 0x55, KEY_2 },
+       { 0xaf, 0x55, KEY_3 },
+       { 0x5f, 0x56, KEY_4 },
+       { 0x6f, 0x56, KEY_5 },
+       { 0x9f, 0x56, KEY_6 },
+       { 0xaf, 0x56, KEY_7 },
+       { 0x5f, 0x59, KEY_8 },
+       { 0x6f, 0x59, KEY_9 },
+       { 0x9f, 0x59, KEY_TV },
+       { 0xaf, 0x59, KEY_AUX },
+       { 0x5f, 0x5a, KEY_DVD },
+       { 0x6f, 0x5a, KEY_POWER },
+       { 0x9f, 0x5a, KEY_MHP },     /* labelled 'Picture' */
+       { 0xaf, 0x5a, KEY_AUDIO },
+       { 0x5f, 0x65, KEY_INFO },
+       { 0x6f, 0x65, KEY_F13 },     /* 16:9 */
+       { 0x9f, 0x65, KEY_F14 },     /* 14:9 */
+       { 0xaf, 0x65, KEY_EPG },
+       { 0x5f, 0x66, KEY_EXIT },
+       { 0x6f, 0x66, KEY_MENU },
+       { 0x9f, 0x66, KEY_UP },
+       { 0xaf, 0x66, KEY_DOWN },
+       { 0x5f, 0x69, KEY_LEFT },
+       { 0x6f, 0x69, KEY_RIGHT },
+       { 0x9f, 0x69, KEY_ENTER },
+       { 0xaf, 0x69, KEY_CHANNELUP },
+       { 0x5f, 0x6a, KEY_CHANNELDOWN },
+       { 0x6f, 0x6a, KEY_VOLUMEUP },
+       { 0x9f, 0x6a, KEY_VOLUMEDOWN },
+       { 0xaf, 0x6a, KEY_RED },
+       { 0x5f, 0x95, KEY_GREEN },
+       { 0x6f, 0x95, KEY_YELLOW },
+       { 0x9f, 0x95, KEY_BLUE },
+       { 0xaf, 0x95, KEY_SUBTITLE },
+       { 0x5f, 0x96, KEY_F15 },     /* AD */
+       { 0x6f, 0x96, KEY_TEXT },
+       { 0x9f, 0x96, KEY_MUTE },
+       { 0xaf, 0x96, KEY_REWIND },
+       { 0x5f, 0x99, KEY_STOP },
+       { 0x6f, 0x99, KEY_PLAY },
+       { 0x9f, 0x99, KEY_FASTFORWARD },
+       { 0xaf, 0x99, KEY_F16 },     /* chapter */
+       { 0x5f, 0x9a, KEY_PAUSE },
+       { 0x6f, 0x9a, KEY_PLAY },
+       { 0x9f, 0x9a, KEY_RECORD },
+       { 0xaf, 0x9a, KEY_F17 },     /* picture in picture */
+       { 0x5f, 0xa5, KEY_KPPLUS },  /* zoom in */
+       { 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */
+       { 0x9f, 0xa5, KEY_F18 },     /* capture */
+       { 0xaf, 0xa5, KEY_F19 },     /* web */
+       { 0x5f, 0xa6, KEY_EMAIL },
+       { 0x6f, 0xa6, KEY_PHONE },
+       { 0x9f, 0xa6, KEY_PC },
 };
 
-/* TODO is it really the NEC protocol ? */
 static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
+       int i;
        u8 key[5];
+       u8 b[4] = { 0 };
+
+       *event = 0;
+       *state = REMOTE_NO_KEY_PRESSED;
 
        digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
-       /* TODO state, maybe it is VV ? */
+
+       /* Tell the device we've read the remote. Not sure how necessary
+          this is, but the Nebula SDK does it. */
+       digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+
+       /* if something is inside the buffer, simulate key press */
        if (key[1] != 0)
-               key[0] = 0x01; /* if something is inside the buffer, simulate key press */
+       {
+                 for (i = 0; i < d->props.rc_key_map_size; i++) {
+                       if (d->props.rc_key_map[i].custom == key[1] &&
+                           d->props.rc_key_map[i].data == key[2]) {
+                               *event = d->props.rc_key_map[i].event;
+                               *state = REMOTE_KEY_PRESSED;
+                               return 0;
+                       }
+               }
+       }
 
-       /* call the universal NEC remote processor, to find out the key's state and event */
-       dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
                deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
        return 0;
index 70afcfd141ca02437eda63f7976eb8aaf85e9a05..27af4e43647936fe72a6db60704fcb5eaa804068 100644 (file)
@@ -93,6 +93,7 @@ static int dtt200u_frontend_attach(struct dvb_usb_device *d)
 }
 
 static struct dvb_usb_properties dtt200u_properties;
+static struct dvb_usb_properties wt220u_fc_properties;
 static struct dvb_usb_properties wt220u_properties;
 static struct dvb_usb_properties wt220u_zl0353_properties;
 
@@ -101,6 +102,7 @@ static int dtt200u_usb_probe(struct usb_interface *intf,
 {
        if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
                dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+               dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
                dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
                return 0;
 
@@ -114,6 +116,9 @@ static struct usb_device_id dtt200u_usb_table [] = {
        { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
        { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD)  },
        { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD)  },
        { 0 },
 };
 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -193,13 +198,54 @@ static struct dvb_usb_properties wt220u_properties = {
        .num_device_descs = 1,
        .devices = {
                { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
-                 .cold_ids = { &dtt200u_usb_table[2], NULL },
+                 .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL },
                  .warm_ids = { &dtt200u_usb_table[3], NULL },
                },
                { NULL },
        }
 };
 
+static struct dvb_usb_properties wt220u_fc_properties = {
+       .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+       .pid_filter_count = 15,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-wt220u-fc03.fw",
+
+       .power_ctrl      = dtt200u_power_ctrl,
+       .streaming_ctrl  = dtt200u_streaming_ctrl,
+       .pid_filter      = dtt200u_pid_filter,
+       .frontend_attach = dtt200u_frontend_attach,
+
+       .rc_interval     = 300,
+       .rc_key_map      = dtt200u_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+       .rc_query        = dtt200u_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_BULK,
+               .count = 7,
+               .endpoint = 0x86,
+               .u = {
+                       .bulk = {
+                               .buffersize = 4096,
+                       }
+               }
+       },
+
+       .num_device_descs = 1,
+       .devices = {
+               { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
+                 .cold_ids = { &dtt200u_usb_table[6], NULL },
+                 .warm_ids = { &dtt200u_usb_table[7], NULL },
+               },
+               { NULL },
+       }
+};
+
 static struct dvb_usb_properties wt220u_zl0353_properties = {
        .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
        .pid_filter_count = 15,
@@ -271,6 +317,6 @@ module_init(dtt200u_usb_module_init);
 module_exit(dtt200u_usb_module_exit);
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon DVB-T USB2.0 devices");
+MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
index ec631708c39480cf7d390267b452c109d2da2088..fe6208ada9037c916ffdb62c594bbe1a9f3b7dd6 100644 (file)
@@ -175,36 +175,36 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
 int dvb_usb_fe_init(struct dvb_usb_device* d)
 {
        if (d->props.frontend_attach == NULL) {
-               err("strange '%s' doesn't want to attach a frontend.",d->desc->name);
+               err("strange: '%s' doesn't want to attach a frontend.",d->desc->name);
                return 0;
        }
 
-       d->props.frontend_attach(d);
-
        /* re-assign sleep and wakeup functions */
-       if (d->fe != NULL) {
+       if (d->props.frontend_attach(d) == 0 && d->fe != NULL) {
                d->fe_init = d->fe->ops.init;   d->fe->ops.init  = dvb_usb_fe_wakeup;
                d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
 
                if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
                        err("Frontend registration failed.");
-                       if (d->fe->ops.release)
-                               d->fe->ops.release(d->fe);
+                       dvb_frontend_detach(d->fe);
                        d->fe = NULL;
                        return -ENODEV;
                }
+
+               /* only attach the tuner if the demod is there */
+               if (d->props.tuner_attach != NULL)
+                       d->props.tuner_attach(d);
        } else
                err("no frontend was attached by '%s'",d->desc->name);
 
-       if (d->props.tuner_attach != NULL)
-               d->props.tuner_attach(d);
-
        return 0;
 }
 
 int dvb_usb_fe_exit(struct dvb_usb_device *d)
 {
-       if (d->fe != NULL)
+       if (d->fe != NULL) {
                dvb_unregister_frontend(d->fe);
+               dvb_frontend_detach(d->fe);
+       }
        return 0;
 }
index 95698918bc116878da6ae4ac96f2b77661cf127d..57a10de1d3dd113c986fd858d7b07d7707e72713 100644 (file)
 #define _DVB_USB_IDS_H_
 
 /* Vendor IDs */
-#define USB_VID_ADSTECH                                                0x06e1
-#define USB_VID_ANCHOR                                         0x0547
-#define USB_VID_WIDEVIEW                                       0x14aa
-#define USB_VID_AVERMEDIA                                      0x07ca
-#define USB_VID_COMPRO                                         0x185b
-#define USB_VID_COMPRO_UNK                                     0x145f
-#define USB_VID_CYPRESS                                                0x04b4
-#define USB_VID_DIBCOM                                         0x10b8
-#define USB_VID_DVICO                                          0x0fe9
-#define USB_VID_EMPIA                                          0xeb1a
-#define USB_VID_GRANDTEC                                       0x5032
-#define USB_VID_HANFTEK                                                0x15f4
-#define USB_VID_HAUPPAUGE                                      0x2040
-#define USB_VID_HYPER_PALTEK                           0x1025
-#define USB_VID_KWORLD                                         0xeb2a
-#define USB_VID_KYE                                                    0x0458
-#define USB_VID_MEDION                                         0x1660
-#define USB_VID_PINNACLE                                       0x2304
-#define USB_VID_VISIONPLUS                                     0x13d3
-#define USB_VID_TWINHAN                                                0x1822
-#define USB_VID_ULTIMA_ELECTRONIC                      0x05d8
-#define USB_VID_GENPIX                                 0x09c0
+#define USB_VID_ADSTECH                                0x06e1
+#define USB_VID_ANCHOR                         0x0547
+#define USB_VID_AVERMEDIA                      0x07ca
+#define USB_VID_COMPRO                         0x185b
+#define USB_VID_COMPRO_UNK                     0x145f
+#define USB_VID_CYPRESS                                0x04b4
+#define USB_VID_DIBCOM                         0x10b8
+#define USB_VID_DVICO                          0x0fe9
+#define USB_VID_EMPIA                          0xeb1a
+#define USB_VID_GENPIX                         0x09c0
+#define USB_VID_GRANDTEC                       0x5032
+#define USB_VID_HANFTEK                                0x15f4
+#define USB_VID_HAUPPAUGE                      0x2040
+#define USB_VID_HYPER_PALTEK                   0x1025
+#define USB_VID_KWORLD                         0xeb2a
+#define USB_VID_KYE                            0x0458
+#define USB_VID_LEADTEK                                0x0413
+#define USB_VID_LITEON                         0x04ca
+#define USB_VID_MEDION                         0x1660
+#define USB_VID_PINNACLE                       0x2304
+#define USB_VID_VISIONPLUS                     0x13d3
+#define USB_VID_TWINHAN                                0x1822
+#define USB_VID_ULTIMA_ELECTRONIC              0x05d8
+#define USB_VID_WIDEVIEW                       0x14aa
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD                      0xa333
 #define USB_PID_ADSTECH_USB2_WARM                      0xa334
-#define USB_PID_AVERMEDIA_DVBT_USB_COLD                0x0001
-#define USB_PID_AVERMEDIA_DVBT_USB_WARM                0x0002
-#define USB_PID_AVERMEDIA_DVBT_USB2_COLD       0xa800
-#define USB_PID_AVERMEDIA_DVBT_USB2_WARM       0xa801
-#define USB_PID_COMPRO_DVBU2000_COLD           0xd000
-#define USB_PID_COMPRO_DVBU2000_WARM           0xd001
-#define USB_PID_COMPRO_DVBU2000_UNK_COLD       0x010c
-#define USB_PID_COMPRO_DVBU2000_UNK_WARM       0x010d
+#define USB_PID_AVERMEDIA_DVBT_USB_COLD                        0x0001
+#define USB_PID_AVERMEDIA_DVBT_USB_WARM                        0x0002
+#define USB_PID_AVERMEDIA_DVBT_USB2_COLD               0xa800
+#define USB_PID_AVERMEDIA_DVBT_USB2_WARM               0xa801
+#define USB_PID_COMPRO_DVBU2000_COLD                   0xd000
+#define USB_PID_COMPRO_DVBU2000_WARM                   0xd001
+#define USB_PID_COMPRO_DVBU2000_UNK_COLD               0x010c
+#define USB_PID_COMPRO_DVBU2000_UNK_WARM               0x010d
 #define USB_PID_DIBCOM_HOOK_DEFAULT                    0x0064
-#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM     0x0065
+#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM             0x0065
 #define USB_PID_DIBCOM_MOD3000_COLD                    0x0bb8
 #define USB_PID_DIBCOM_MOD3000_WARM                    0x0bb9
 #define USB_PID_DIBCOM_MOD3001_COLD                    0x0bc6
 #define USB_PID_DIBCOM_MOD3001_WARM                    0x0bc7
 #define USB_PID_DIBCOM_STK7700                         0x1e14
-#define USB_PID_DIBCOM_STK7700_REENUM          0x1e15
-#define USB_PID_DIBCOM_ANCHOR_2135_COLD                0x2131
-#define USB_PID_GRANDTEC_DVBT_USB_COLD         0x0fa0
-#define USB_PID_GRANDTEC_DVBT_USB_WARM         0x0fa1
+#define USB_PID_DIBCOM_STK7700_REENUM                  0x1e15
+#define USB_PID_DIBCOM_ANCHOR_2135_COLD                        0x2131
+#define USB_PID_GRANDTEC_DVBT_USB_COLD                 0x0fa0
+#define USB_PID_GRANDTEC_DVBT_USB_WARM                 0x0fa1
 #define USB_PID_KWORLD_VSTREAM_COLD                    0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM                    0x17df
 #define USB_PID_TWINHAN_VP7041_COLD                    0x3201
 #define USB_PID_DNTV_TINYUSB2_WARM                     0x3224
 #define USB_PID_ULTIMA_TVBOX_COLD                      0x8105
 #define USB_PID_ULTIMA_TVBOX_WARM                      0x8106
-#define USB_PID_ULTIMA_TVBOX_AN2235_COLD       0x8107
-#define USB_PID_ULTIMA_TVBOX_AN2235_WARM       0x8108
-#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD       0x2235
-#define USB_PID_ULTIMA_TVBOX_USB2_COLD         0x8109
-#define USB_PID_ULTIMA_TVBOX_USB2_WARM         0x810a
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD      0x8613
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM      0x1002
-#define USB_PID_UNK_HYPER_PALTEK_COLD          0x005e
-#define USB_PID_UNK_HYPER_PALTEK_WARM          0x005f
-#define USB_PID_HANFTEK_UMT_010_COLD           0x0001
-#define USB_PID_HANFTEK_UMT_010_WARM           0x0015
+#define USB_PID_ULTIMA_TVBOX_AN2235_COLD               0x8107
+#define USB_PID_ULTIMA_TVBOX_AN2235_WARM               0x8108
+#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD               0x2235
+#define USB_PID_ULTIMA_TVBOX_USB2_COLD                 0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_WARM                 0x810a
+#define USB_PID_ARTEC_T14_COLD                         0x810b
+#define USB_PID_ARTEC_T14_WARM                         0x810c
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD              0x8613
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM              0x1002
+#define USB_PID_UNK_HYPER_PALTEK_COLD                  0x005e
+#define USB_PID_UNK_HYPER_PALTEK_WARM                  0x005f
+#define USB_PID_HANFTEK_UMT_010_COLD                   0x0001
+#define USB_PID_HANFTEK_UMT_010_WARM                   0x0015
 #define USB_PID_DTT200U_COLD                           0x0201
 #define USB_PID_DTT200U_WARM                           0x0301
-#define USB_PID_WT220U_COLD                                    0x0222
-#define USB_PID_WT220U_WARM                                    0x0221
+#define USB_PID_WT220U_ZAP250_COLD                     0x0220
+#define USB_PID_WT220U_COLD                            0x0222
+#define USB_PID_WT220U_WARM                            0x0221
+#define USB_PID_WT220U_FC_COLD                         0x0225
+#define USB_PID_WT220U_FC_WARM                         0x0226
 #define USB_PID_WT220U_ZL0353_COLD                     0x022a
 #define USB_PID_WT220U_ZL0353_WARM                     0x022b
-#define USB_PID_WINTV_NOVA_T_USB2_COLD         0x9300
-#define USB_PID_WINTV_NOVA_T_USB2_WARM         0x9301
+#define USB_PID_WINTV_NOVA_T_USB2_COLD                 0x9300
+#define USB_PID_WINTV_NOVA_T_USB2_WARM                 0x9301
 #define USB_PID_NEBULA_DIGITV                          0x0201
 #define USB_PID_DVICO_BLUEBIRD_LGDT                    0xd820
 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD             0xd500
 #define USB_PID_MEDION_MD95700                         0x0932
 #define USB_PID_KYE_DVB_T_COLD                         0x701e
 #define USB_PID_KYE_DVB_T_WARM                         0x701f
-#define USB_PID_PCTV_200E                                      0x020e
-#define USB_PID_PCTV_400E                                      0x020f
-#define USB_PID_GENPIX_8PSK_COLD                               0x0200
-#define USB_PID_GENPIX_8PSK_WARM                               0x0201
+#define USB_PID_PCTV_200E                              0x020e
+#define USB_PID_PCTV_400E                              0x020f
+#define USB_PID_LITEON_DVB_T_COLD                      0xf000
+#define USB_PID_LITEON_DVB_T_WARM                      0xf001
+#define USB_PID_DIGIVOX_MINI_SL_COLD                   0xe360
+#define USB_PID_DIGIVOX_MINI_SL_WARM                   0xe361
+#define USB_PID_GRANDTEC_DVBT_USB2_COLD                        0x0bc6
+#define USB_PID_GRANDTEC_DVBT_USB2_WARM                        0x0bc7
+#define USB_PID_WINFAST_DTV_DONGLE_COLD                        0x6025
+#define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
+#define USB_PID_GENPIX_8PSK_COLD                       0x0200
+#define USB_PID_GENPIX_8PSK_WARM                       0x0201
+
 #endif
index e5c6d9835e06d24cac72b3ae3f342cab98b055da..380b2a45ee4c2accc59d0b8af0da13e6dc980dc5 100644 (file)
@@ -6,6 +6,7 @@
  * This file contains functions for initializing the the input-device and for handling remote-control-queries.
  */
 #include "dvb-usb-common.h"
+#include <linux/usb/input.h>
 
 /* Remote-control poll function - called every dib->rc_query_interval ms to see
  * whether the remote control has received anything.
@@ -96,7 +97,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
                return 0;
 
        usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
-       strlcpy(d->rc_phys, "/ir0", sizeof(d->rc_phys));
+       strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
        d->rc_input_dev = input_allocate_device();
        if (!d->rc_input_dev)
@@ -107,6 +108,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
        d->rc_input_dev->keycodemax = KEY_MAX;
        d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
        d->rc_input_dev->phys = d->rc_phys;
+       usb_to_input_id(d->udev, &d->rc_input_dev->id);
+       d->rc_input_dev->cdev.dev = &d->udev->dev;
 
        /* set the bits for the keys */
        deb_rc("key map size: %d\n", d->props.rc_key_map_size);
index 9002f35aa952822f7144b15bfeddf76fff08c2b8..88b283731bb8c84e1dcf7c4a90cc15b0604fd1c6 100644 (file)
@@ -80,7 +80,6 @@ static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
 
        switch (urb->status) {
                case 0:         /* success */
-               case -ETIMEDOUT:    /* NAK */
                        break;
                case -ECONNRESET:   /* kill */
                case -ENOENT:
index 412039d8dbae728a730fac25742701a7fe288ad2..79f0a02ce98719742b3ad83791145c0041e2228d 100644 (file)
@@ -156,7 +156,7 @@ static struct dvb_usb_properties nova_t_properties = {
        .pid_filter_count = 32,
 
        .usb_ctrl = CYPRESS_FX2,
-       .firmware = "dvb-usb-nova-t-usb2-01.fw",
+       .firmware = "dvb-usb-nova-t-usb2-02.fw",
 
        .size_of_priv     = sizeof(struct dibusb_state),
 
index 97d74da0dad88676457b01081a6d8eaa406d0371..418a0b707151c9071f9833d6e52f49027bd1e20f 100644 (file)
@@ -58,7 +58,7 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
        umt_config.demod_init = umt_mt352_demod_init;
        umt_config.demod_address = 0xf;
 
-       d->fe = mt352_attach(&umt_config, &d->i2c_adap);
+       d->fe = dvb_attach(mt352_attach, &umt_config, &d->i2c_adap);
 
        return 0;
 }
index db978555b1eb34d2c5819cf2b5380f6e52450c8d..080fa257a0bc25aca04bd84e77c044dfe3f9043f 100644 (file)
@@ -1,48 +1,73 @@
 menu "Customise DVB Frontends"
        depends on DVB_CORE
 
+config DVB_FE_CUSTOMISE
+       bool "Customise the frontend modules to build"
+       default N
+       help
+         This allows the user to deselect frontend drivers unnecessary
+         for their hardware from the build. Use this option with care
+         as deselecting frontends which are in fact necessary will result
+         in DVB devices which cannot be tuned due to lack of driver support.
+
+         If unsure say N.
+
 comment "DVB-S (satellite) frontends"
        depends on DVB_CORE
 
 config DVB_STV0299
        tristate "ST STV0299 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX24110
        tristate "Conexant CX24110 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX24123
        tristate "Conexant CX24123 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA8083
        tristate "Philips TDA8083 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_MT312
        tristate "Zarlink VP310/MT312 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_VES1X93
        tristate "VLSI VES1893 or VES1993 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_S5H1420
        tristate "Samsung S5H1420 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA10086
+       tristate "Philips TDA10086 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
@@ -52,6 +77,7 @@ comment "DVB-T (terrestrial) frontends"
 config DVB_SP8870
        tristate "Spase sp8870 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -64,6 +90,7 @@ config DVB_SP8870
 config DVB_SP887X
        tristate "Spase sp887x based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -76,24 +103,28 @@ config DVB_SP887X
 config DVB_CX22700
        tristate "Conexant CX22700 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX22702
        tristate "Conexant cx22702 demodulator (OFDM)"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_L64781
        tristate "LSI L64781"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA1004X
        tristate "Philips TDA10045H/TDA10046H based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -107,24 +138,28 @@ config DVB_TDA1004X
 config DVB_NXT6000
        tristate "NxtWave Communications NXT6000 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_MT352
        tristate "Zarlink MT352 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_ZL10353
        tristate "Zarlink ZL10353 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_DIB3000MB
        tristate "DiBcom 3000M-B"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -132,6 +167,7 @@ config DVB_DIB3000MB
 config DVB_DIB3000MC
        tristate "DiBcom 3000P/M-C"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -142,18 +178,21 @@ comment "DVB-C (cable) frontends"
 config DVB_VES1820
        tristate "VLSI VES1820 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA10021
        tristate "Philips TDA10021 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_STV0297
        tristate "ST STV0297 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
@@ -163,6 +202,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 config DVB_NXT200X
        tristate "NxtWave Communications NXT2002/NXT2004 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
@@ -177,6 +217,7 @@ config DVB_NXT200X
 config DVB_OR51211
        tristate "Oren OR51211 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
@@ -189,6 +230,7 @@ config DVB_OR51211
 config DVB_OR51132
        tristate "Oren OR51132 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
@@ -204,6 +246,7 @@ config DVB_OR51132
 config DVB_BCM3510
        tristate "Broadcom BCM3510"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
@@ -212,28 +255,52 @@ config DVB_BCM3510
 config DVB_LGDT330X
        tristate "LG Electronics LGDT3302/LGDT3303 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
-
-comment "Miscellaneous devices"
+comment "Tuners/PLL support"
        depends on DVB_CORE
 
 config DVB_PLL
        tristate
        depends on DVB_CORE && I2C
 
+config DVB_TDA826X
+       tristate "Philips TDA826X silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_TUNER_MT2060
+       tristate "Microtune MT2060 silicon IF tuner"
+       help
+         A driver for the silicon IF tuner MT2060 from Microtune.
+
+comment "Miscellaneous devices"
+       depends on DVB_CORE
+
 config DVB_LNBP21
        tristate "LNBP21 SEC controller"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          An SEC control chip.
 
 config DVB_ISL6421
        tristate "ISL6421 SEC controller"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          An SEC control chip.
 
+config DVB_TUA6100
+       tristate "TUA6100 PLL"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVBS PLL chip.
+
 endmenu
index 0e4880b6db14699c8204295884b3a9b0e0454cfc..dce9cf0c75c0880acc234ad7a58d5441b3b6286c 100644 (file)
@@ -11,8 +11,8 @@ obj-$(CONFIG_DVB_CX22700) += cx22700.o
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
 obj-$(CONFIG_DVB_TDA8083) += tda8083.o
 obj-$(CONFIG_DVB_L64781) += l64781.o
-obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o
-obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o
+obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
+obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
 obj-$(CONFIG_DVB_MT312) += mt312.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
 obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
@@ -33,3 +33,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
+obj-$(CONFIG_DVB_TDA10086) += tda10086.o
+obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_DVB_TUA6100) += tua6100.o
index 80f5d0953d02635797ffdf9fc97ec242ebe01b1f..6dfa839a70224612c4fe72344c78fa080fca18e8 100644 (file)
@@ -34,7 +34,16 @@ struct bcm3510_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
+#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE)
 extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_BCM3510
 
 #endif
index dcd8979c1a15e2668b5a5a8a8c276b59366edbb2..10286cc29fb40e8245ea76aae8086499d6c71858 100644 (file)
@@ -31,7 +31,16 @@ struct cx22700_config
        u8 demod_address;
 };
 
+#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE)
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX22700
 
 #endif // CX22700_H
index 4106d46c957fa2e081c637790dace69827c791c1..335219ebce2d5a5568dc6d815ffe8aaf3ac185c6 100644 (file)
@@ -399,7 +399,9 @@ static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
 {
        struct cx22702_state* state = fe->demodulator_priv;
 
-       *signal_strength = cx22702_readreg (state, 0x23);
+       u16 rs_ber = 0;
+       rs_ber = cx22702_readreg (state, 0x23);
+       *signal_strength = (rs_ber << 8) | rs_ber;
 
        return 0;
 }
index 7f2f241e5d4485985cfe0c0c23ddafd489e8add5..bc217ddf02c09f427c70822b6a4dd74106fa75db 100644 (file)
@@ -41,7 +41,16 @@ struct cx22702_config
        u8 output_mode;
 };
 
+#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE)
 extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX22702
 
 #endif // CX22702_H
index ce3c7398bac9ffa74168145b9b67d4eccf519c02..ae96395217a2e475c2c79a9b2b21ca62b2ac18bf 100644 (file)
@@ -1,4 +1,4 @@
-/*
+       /*
     cx24110 - Single Chip Satellite Channel Receiver driver module
 
     Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
@@ -311,16 +311,17 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
 
 }
 
-int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
+static int _cx24110_pll_write (struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct cx24110_state *state = fe->demodulator_priv;
 
+       if (len != 3)
+               return -EINVAL;
+
 /* tuner data is 21 bits long, must be left-aligned in data */
 /* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
 /* FIXME (low): add error handling, avoid infinite loops if HW fails... */
 
-       dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data);
-
        cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
        cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
 
@@ -329,19 +330,19 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
                cx24110_writereg(state,0x72,0);
 
        /* write the topmost 8 bits */
-       cx24110_writereg(state,0x72,(data>>24)&0xff);
+       cx24110_writereg(state,0x72,buf[0]);
 
        /* wait for the send to be completed */
        while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
                ;
 
        /* send another 8 bytes */
-       cx24110_writereg(state,0x72,(data>>16)&0xff);
+       cx24110_writereg(state,0x72,buf[1]);
        while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
                ;
 
        /* and the topmost 5 bits of this byte */
-       cx24110_writereg(state,0x72,(data>>8)&0xff);
+       cx24110_writereg(state,0x72,buf[2]);
        while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
                ;
 
@@ -642,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
        .release = cx24110_release,
 
        .init = cx24110_initfe,
+       .write = _cx24110_pll_write,
        .set_frontend = cx24110_set_frontend,
        .get_frontend = cx24110_get_frontend,
        .read_status = cx24110_read_status,
@@ -664,4 +666,3 @@ MODULE_AUTHOR("Peter Hettkamp");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(cx24110_attach);
-EXPORT_SYMBOL(cx24110_pll_write);
index b354a64e0e74970f728d4b5f905a24b5abb3ff75..c9d5ae250ebb46296e43ea20fc728dd5b24af86a 100644 (file)
@@ -33,9 +33,24 @@ struct cx24110_config
        u8 demod_address;
 };
 
+static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) {
+       int r = 0;
+       u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)};
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 3);
+       return r;
+}
+
+#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE)
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
                                           struct i2c_adapter* i2c);
-
-extern int cx24110_pll_write(struct dvb_frontend* fe, u32 data);
+#else
+static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX24110
 
 #endif // CX24110_H
index 274a87b7a5d5fe8e54acf887aaeaa155bd82def1..62d69a6ea699269e2a937c1a764fd28e1cc3976c 100644 (file)
@@ -45,9 +45,6 @@ struct cx24123_state
 
        struct dvb_frontend frontend;
 
-       u32 lastber;
-       u16 snr;
-
        /* Some PLL specifics for tuning */
        u32 VCAarg;
        u32 VGAarg;
@@ -194,7 +191,7 @@ static struct {
        {0x06, 0x31}, /* MPEG (default) */
        {0x0b, 0x00}, /* Freq search start point (default) */
        {0x0c, 0x00}, /* Demodulator sample gain (default) */
-       {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */
+       {0x0d, 0x7f}, /* Force driver to shift until the maximum (+-10 MHz) */
        {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
        {0x0f, 0xfe}, /* FEC search mask (all supported codes) */
        {0x10, 0x01}, /* Default search inversion, no repeat (default) */
@@ -223,8 +220,9 @@ static struct {
        {0x44, 0x00}, /* Constellation (default) */
        {0x45, 0x00}, /* Symbol count (default) */
        {0x46, 0x0d}, /* Symbol rate estimator on (default) */
-       {0x56, 0x41}, /* Various (default) */
+       {0x56, 0xc1}, /* Error Counter = Viterbi BER */
        {0x57, 0xff}, /* Error Counter Window (default) */
+       {0x5c, 0x20}, /* Acquisition AFC Expiration window (default is 0x10) */
        {0x67, 0x83}, /* Non-DCII symbol clock */
 };
 
@@ -321,6 +319,12 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
        if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
                fec = FEC_AUTO;
 
+       /* Set the soft decision threshold */
+       if(fec == FEC_1_2)
+               cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
+       else
+               cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);
+
        switch (fec) {
        case FEC_1_2:
                dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
@@ -657,6 +661,10 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
                cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
+       /* Set the LNB polarity */
+       if(state->config->lnb_polarity)
+               cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+
        return 0;
 }
 
@@ -674,6 +682,9 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
        case SEC_VOLTAGE_18:
                dprintk("%s: setting voltage 18V\n", __FUNCTION__);
                return cx24123_writereg(state, 0x29, val | 0x80);
+       case SEC_VOLTAGE_OFF:
+               /* already handled in cx88-dvb */
+               return 0;
        default:
                return -EINVAL;
        };
@@ -776,13 +787,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
        if (lock & 0x01)
                *status |= FE_HAS_SIGNAL;
        if (sync & 0x02)
-               *status |= FE_HAS_CARRIER;
+               *status |= FE_HAS_CARRIER;      /* Phase locked */
        if (sync & 0x04)
                *status |= FE_HAS_VITERBI;
+
+       /* Reed-Solomon Status */
        if (sync & 0x08)
                *status |= FE_HAS_SYNC;
        if (sync & 0x80)
-               *status |= FE_HAS_LOCK;
+               *status |= FE_HAS_LOCK;         /*Full Sync */
 
        return 0;
 }
@@ -795,29 +808,13 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
-       state->lastber =
-               ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+       /* The true bit error rate is this value divided by
+          the window size (set as 256 * 255) */
+       *ber = ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
                (cx24123_readreg(state, 0x1d) << 8 |
-               cx24123_readreg(state, 0x1e));
-
-       /* Do the signal quality processing here, it's derived from the BER. */
-       /* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
-       if (state->lastber < 5000)
-               state->snr = 655*100;
-       else if ( (state->lastber >=   5000) && (state->lastber <  55000) )
-               state->snr = 655*90;
-       else if ( (state->lastber >=  55000) && (state->lastber < 150000) )
-               state->snr = 655*80;
-       else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
-               state->snr = 655*70;
-       else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
-               state->snr = 655*65;
-       else
-               state->snr = 0;
-
-       dprintk("%s:  BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr);
+                cx24123_readreg(state, 0x1e));
 
-       *ber = state->lastber;
+       dprintk("%s:  BER = %d\n",__FUNCTION__,*ber);
 
        return 0;
 }
@@ -825,6 +822,7 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
 static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
 {
        struct cx24123_state *state = fe->demodulator_priv;
+
        *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
 
        dprintk("%s:  Signal strength = %d\n",__FUNCTION__,*signal_strength);
@@ -835,19 +833,13 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
 static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-       *snr = state->snr;
-
-       dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
 
-       return 0;
-}
+       /* Inverted raw Es/N0 count, totally bogus but better than the
+          BER threshold. */
+       *snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
+                        (u16)cx24123_readreg(state, 0x19));
 
-static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-       struct cx24123_state *state = fe->demodulator_priv;
-       *ucblocks = state->lastber;
-
-       dprintk("%s:  ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks);
+       dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
 
        return 0;
 }
@@ -922,6 +914,29 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        return 0;
 }
 
+static int cx24123_tune(struct dvb_frontend* fe,
+                       struct dvb_frontend_parameters* params,
+                       unsigned int mode_flags,
+                       int *delay,
+                       fe_status_t *status)
+{
+       int retval = 0;
+
+       if (params != NULL)
+               retval = cx24123_set_frontend(fe, params);
+
+       if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+               cx24123_read_status(fe, status);
+       *delay = HZ/10;
+
+       return retval;
+}
+
+static int cx24123_get_algo(struct dvb_frontend *fe)
+{
+       return 1; //FE_ALGO_HW
+}
+
 static void cx24123_release(struct dvb_frontend* fe)
 {
        struct cx24123_state* state = fe->demodulator_priv;
@@ -949,8 +964,6 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       state->lastber = 0;
-       state->snr = 0;
        state->VCAarg = 0;
        state->VGAarg = 0;
        state->bandselectarg = 0;
@@ -1003,11 +1016,12 @@ static struct dvb_frontend_ops cx24123_ops = {
        .read_ber = cx24123_read_ber,
        .read_signal_strength = cx24123_read_signal_strength,
        .read_snr = cx24123_read_snr,
-       .read_ucblocks = cx24123_read_ucblocks,
        .diseqc_send_master_cmd = cx24123_send_diseqc_msg,
        .diseqc_send_burst = cx24123_diseqc_send_burst,
        .set_tone = cx24123_set_tone,
        .set_voltage = cx24123_set_voltage,
+       .tune = cx24123_tune,
+       .get_frontend_algo = cx24123_get_algo,
 };
 
 module_param(debug, int, 0644);
index 9606f825935c8341f53b760e9c91f06e4146e9a8..57a1dae1dc40a5bc1c61434f614401f638f84b69 100644 (file)
@@ -30,9 +30,21 @@ struct cx24123_config
 
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+       /* 0 = LNB voltage normal, 1 = LNB voltage inverted */
+       int lnb_polarity;
 };
 
+#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE)
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX24123
 
 #endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c
deleted file mode 100644 (file)
index 1a4f1f7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "dib3000-common.h"
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
-#endif
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_i2c(args...) dprintk(0x02,args)
-#define deb_srch(args...) dprintk(0x04,args)
-
-
-int dib3000_read_reg(struct dib3000_state *state, u16 reg)
-{
-       u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
-       u8 rb[2];
-       struct i2c_msg msg[] = {
-               { .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
-               { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
-       };
-
-       if (i2c_transfer(state->i2c, msg, 2) != 2)
-               deb_i2c("i2c read error\n");
-
-       deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
-                       (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
-
-       return (rb[0] << 8) | rb[1];
-}
-
-int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
-{
-       u8 b[] = {
-               (reg >> 8) & 0xff, reg & 0xff,
-               (val >> 8) & 0xff, val & 0xff,
-       };
-       struct i2c_msg msg[] = {
-               { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
-       };
-       deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
-
-       return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
-}
-
-int dib3000_search_status(u16 irq,u16 lock)
-{
-       if (irq & 0x02) {
-               if (lock & 0x01) {
-                       deb_srch("auto search succeeded\n");
-                       return 1; // auto search succeeded
-               } else {
-                       deb_srch("auto search not successful\n");
-                       return 0; // auto search failed
-               }
-       } else if (irq & 0x01)  {
-               deb_srch("auto search failed\n");
-               return 0; // auto search failed
-       }
-       return -1; // try again
-}
-
-/* for auto search */
-u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
-       { /* fft */
-               { /* gua */
-                       { 0, 1 },                   /*  0   0   { 0,1 } */
-                       { 3, 9 },                   /*  0   1   { 0,1 } */
-               },
-               {
-                       { 2, 5 },                   /*  1   0   { 0,1 } */
-                       { 6, 11 },                  /*  1   1   { 0,1 } */
-               }
-       };
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
-MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000_seq);
-
-EXPORT_SYMBOL(dib3000_read_reg);
-EXPORT_SYMBOL(dib3000_write_reg);
-EXPORT_SYMBOL(dib3000_search_status);
diff --git a/drivers/media/dvb/frontends/dib3000-common.h b/drivers/media/dvb/frontends/dib3000-common.h
deleted file mode 100644 (file)
index be1c0d3..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * .h-files for the common use of the frontend drivers made by DiBcom
- * DiBcom 3000M-B/C, 3000P
- *
- * DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DibCom, which has
- *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- *     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.
- *
- * Acknowledgements
- *
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- *
- */
-
-#ifndef DIB3000_COMMON_H
-#define DIB3000_COMMON_H
-
-#include "dvb_frontend.h"
-#include "dib3000.h"
-
-/* info and err, taken from usb.h, if there is anything available like by default. */
-#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
-
-/* frontend state */
-struct dib3000_state {
-       struct i2c_adapter* i2c;
-
-/* configuration settings */
-       struct dib3000_config config;
-
-       struct dvb_frontend frontend;
-       int timing_offset;
-       int timing_offset_comp_done;
-
-       fe_bandwidth_t last_tuned_bw;
-       u32 last_tuned_freq;
-};
-
-/* commonly used methods by the dib3000mb/mc/p frontend */
-extern int dib3000_read_reg(struct dib3000_state *state, u16 reg);
-extern int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val);
-
-extern int dib3000_search_status(u16 irq,u16 lock);
-
-/* handy shortcuts */
-#define rd(reg) dib3000_read_reg(state,reg)
-
-#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
-       { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
-
-#define wr_foreach(a,v) { int i; \
-       if (sizeof(a) != sizeof(v)) \
-               err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
-       for (i=0; i < sizeof(a)/sizeof(u16); i++) \
-               wr(a[i],v[i]); \
-       }
-
-#define set_or(reg,val) wr(reg,rd(reg) | val)
-
-#define set_and(reg,val) wr(reg,rd(reg) & val)
-
-
-/* debug */
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk(level,args...) \
-    do { if ((debug & level)) { printk(args); } } while (0)
-#else
-#define dprintk(args...) do { } while (0)
-#endif
-
-/* mask for enabling a specific pid for the pid_filter */
-#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
-
-/* common values for tuning */
-#define DIB3000_ALPHA_0                                        (     0)
-#define DIB3000_ALPHA_1                                        (     1)
-#define DIB3000_ALPHA_2                                        (     2)
-#define DIB3000_ALPHA_4                                        (     4)
-
-#define DIB3000_CONSTELLATION_QPSK             (     0)
-#define DIB3000_CONSTELLATION_16QAM            (     1)
-#define DIB3000_CONSTELLATION_64QAM            (     2)
-
-#define DIB3000_GUARD_TIME_1_32                        (     0)
-#define DIB3000_GUARD_TIME_1_16                        (     1)
-#define DIB3000_GUARD_TIME_1_8                 (     2)
-#define DIB3000_GUARD_TIME_1_4                 (     3)
-
-#define DIB3000_TRANSMISSION_MODE_2K   (     0)
-#define DIB3000_TRANSMISSION_MODE_8K   (     1)
-
-#define DIB3000_SELECT_LP                              (     0)
-#define DIB3000_SELECT_HP                              (     1)
-
-#define DIB3000_FEC_1_2                                        (     1)
-#define DIB3000_FEC_2_3                                        (     2)
-#define DIB3000_FEC_3_4                                        (     3)
-#define DIB3000_FEC_5_6                                        (     5)
-#define DIB3000_FEC_7_8                                        (     7)
-
-#define DIB3000_HRCH_OFF                               (     0)
-#define DIB3000_HRCH_ON                                        (     1)
-
-#define DIB3000_DDS_INVERSION_OFF              (     0)
-#define DIB3000_DDS_INVERSION_ON               (     1)
-
-#define DIB3000_TUNER_WRITE_ENABLE(a)  (0xffff & (a << 8))
-#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
-
-/* for auto search */
-extern u16 dib3000_seq[2][2][2];
-
-#define DIB3000_REG_MANUFACTOR_ID              (  1025)
-#define DIB3000_I2C_ID_DIBCOM                  (0x01b3)
-
-#define DIB3000_REG_DEVICE_ID                  (  1026)
-#define DIB3000MB_DEVICE_ID                            (0x3000)
-#define DIB3000MC_DEVICE_ID                            (0x3001)
-#define DIB3000P_DEVICE_ID                             (0x3002)
-
-#endif // DIB3000_COMMON_H
index ec927628d2734cac2eee5ef633e5eb55de4d680e..0caac3f0f279f3b1ed461f5d7658f3900fa18a12 100644 (file)
@@ -41,9 +41,16 @@ struct dib_fe_xfer_ops
        int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
 };
 
+#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE)
 extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
                                             struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
+#else
+static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+                                            struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_DIB3000MB
 
-extern struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
-                                            struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
 #endif // DIB3000_H
index 5302e11883a24738153dfd75f1f4c6ed3c53b354..adbabfdb04a95c0fe50f23251af39e2140139d2a 100644 (file)
 #include <linux/string.h>
 #include <linux/slab.h>
 
-#include "dib3000-common.h"
-#include "dib3000mb_priv.h"
+#include "dvb_frontend.h"
+
 #include "dib3000.h"
+#include "dib3000mb_priv.h"
 
 /* Version information */
 #define DRIVER_VERSION "0.1"
@@ -44,10 +45,81 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
 #endif
 #define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...)  dprintk(0x02,args)
+#define deb_srch(args...) dprintk(0x04,args)
+#define deb_info(args...) dprintk(0x01,args)
 #define deb_xfer(args...) dprintk(0x02,args)
 #define deb_setf(args...) dprintk(0x04,args)
 #define deb_getf(args...) dprintk(0x08,args)
 
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
+#endif
+
+static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
+{
+       u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
+       u8 rb[2];
+       struct i2c_msg msg[] = {
+               { .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
+               { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+       };
+
+       if (i2c_transfer(state->i2c, msg, 2) != 2)
+               deb_i2c("i2c read error\n");
+
+       deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
+                       (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
+
+       return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
+{
+       u8 b[] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg[] = {
+               { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
+       };
+       deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
+
+       return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static int dib3000_search_status(u16 irq,u16 lock)
+{
+       if (irq & 0x02) {
+               if (lock & 0x01) {
+                       deb_srch("auto search succeeded\n");
+                       return 1; // auto search succeeded
+               } else {
+                       deb_srch("auto search not successful\n");
+                       return 0; // auto search failed
+               }
+       } else if (irq & 0x01)  {
+               deb_srch("auto search failed\n");
+               return 0; // auto search failed
+       }
+       return -1; // try again
+}
+
+/* for auto search */
+static u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
+       { /* fft */
+               { /* gua */
+                       { 0, 1 },                   /*  0   0   { 0,1 } */
+                       { 3, 9 },                   /*  0   1   { 0,1 } */
+               },
+               {
+                       { 2, 5 },                   /*  1   0   { 0,1 } */
+                       { 6, 11 },                  /*  1   1   { 0,1 } */
+               }
+       };
+
 static int dib3000mb_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep);
 
index 999b19047816dfc4402781557b9aea7a6f611de5..1a12747fdc914108bf6ee5f4d4bc26342b7c3392 100644 (file)
 #ifndef __DIB3000MB_PRIV_H_INCLUDED__
 #define __DIB3000MB_PRIV_H_INCLUDED__
 
+/* info and err, taken from usb.h, if there is anything available like by default. */
+#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
+
+/* handy shortcuts */
+#define rd(reg) dib3000_read_reg(state,reg)
+
+#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
+       { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
+
+#define wr_foreach(a,v) { int i; \
+       if (sizeof(a) != sizeof(v)) \
+               err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
+       for (i=0; i < sizeof(a)/sizeof(u16); i++) \
+               wr(a[i],v[i]); \
+       }
+
+#define set_or(reg,val) wr(reg,rd(reg) | val)
+
+#define set_and(reg,val) wr(reg,rd(reg) & val)
+
+/* debug */
+
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#define dprintk(level,args...) \
+    do { if ((debug & level)) { printk(args); } } while (0)
+#else
+#define dprintk(args...) do { } while (0)
+#endif
+
+/* mask for enabling a specific pid for the pid_filter */
+#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
+
+/* common values for tuning */
+#define DIB3000_ALPHA_0                                        (     0)
+#define DIB3000_ALPHA_1                                        (     1)
+#define DIB3000_ALPHA_2                                        (     2)
+#define DIB3000_ALPHA_4                                        (     4)
+
+#define DIB3000_CONSTELLATION_QPSK             (     0)
+#define DIB3000_CONSTELLATION_16QAM            (     1)
+#define DIB3000_CONSTELLATION_64QAM            (     2)
+
+#define DIB3000_GUARD_TIME_1_32                        (     0)
+#define DIB3000_GUARD_TIME_1_16                        (     1)
+#define DIB3000_GUARD_TIME_1_8                 (     2)
+#define DIB3000_GUARD_TIME_1_4                 (     3)
+
+#define DIB3000_TRANSMISSION_MODE_2K   (     0)
+#define DIB3000_TRANSMISSION_MODE_8K   (     1)
+
+#define DIB3000_SELECT_LP                              (     0)
+#define DIB3000_SELECT_HP                              (     1)
+
+#define DIB3000_FEC_1_2                                        (     1)
+#define DIB3000_FEC_2_3                                        (     2)
+#define DIB3000_FEC_3_4                                        (     3)
+#define DIB3000_FEC_5_6                                        (     5)
+#define DIB3000_FEC_7_8                                        (     7)
+
+#define DIB3000_HRCH_OFF                               (     0)
+#define DIB3000_HRCH_ON                                        (     1)
+
+#define DIB3000_DDS_INVERSION_OFF              (     0)
+#define DIB3000_DDS_INVERSION_ON               (     1)
+
+#define DIB3000_TUNER_WRITE_ENABLE(a)  (0xffff & (a << 8))
+#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
+
+#define DIB3000_REG_MANUFACTOR_ID              (  1025)
+#define DIB3000_I2C_ID_DIBCOM                  (0x01b3)
+
+#define DIB3000_REG_DEVICE_ID                  (  1026)
+#define DIB3000MB_DEVICE_ID                            (0x3000)
+#define DIB3000MC_DEVICE_ID                            (0x3001)
+#define DIB3000P_DEVICE_ID                             (0x3002)
+
+/* frontend state */
+struct dib3000_state {
+       struct i2c_adapter* i2c;
+
+/* configuration settings */
+       struct dib3000_config config;
+
+       struct dvb_frontend frontend;
+       int timing_offset;
+       int timing_offset_comp_done;
+
+       fe_bandwidth_t last_tuned_bw;
+       u32 last_tuned_freq;
+};
+
 /* register addresses and some of their default values */
 
 /* restart subsystems */
index 98673474a14021dd551ea887f9867e7b40ad4c79..cc28417fa33ac7fb6bc1eef2e496cd0ec682ec6e 100644 (file)
 /*
- * Frontend driver for mobile DVB-T demodulator DiBcom 3000P/M-C
- * DiBcom (http://www.dibcom.fr/)
+ * Driver for DiBcom DiB3000MC/P-demodulator.
  *
+ * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
  *
- * based on GPL code from DiBCom, which has
+ * This code is partially based on the previous dib3000mc.c .
  *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- *     This program is free software; you can redistribute it and/or
+ * 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.
- *
- * Acknowledgements
- *
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- *
  */
+
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dib3000-common.h"
-#include "dib3000mc_priv.h"
-#include "dib3000.h"
-
-/* Version information */
-#define DRIVER_VERSION "0.1"
-#define DRIVER_DESC "DiBcom 3000M-C DVB-T demodulator"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#include <linux/i2c.h>
+//#include <linux/init.h>
+//#include <linux/delay.h>
+//#include <linux/string.h>
+//#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+
+#include "dib3000mc.h"
+
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=stat (|-able)).");
-#endif
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_setf(args...) dprintk(0x04,args)
-#define deb_getf(args...) dprintk(0x08,args)
-#define deb_stat(args...) dprintk(0x10,args)
-
-static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
-       fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
-{
-       switch (transmission_mode) {
-               case TRANSMISSION_MODE_2K:
-                       wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[0]);
-                       break;
-               case TRANSMISSION_MODE_8K:
-                       wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[1]);
-                       break;
-               default:
-                       break;
-       }
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-       switch (bandwidth) {
-/*             case BANDWIDTH_5_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[0]);
-                       break; */
-               case BANDWIDTH_6_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[1]);
-                       break;
-               case BANDWIDTH_7_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[2]);
-                       break;
-               case BANDWIDTH_8_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[3]);
-                       break;
-               default:
-                       break;
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
+
+struct dib3000mc_state {
+       struct dvb_frontend demod;
+       struct dib3000mc_config *cfg;
+
+       u8 i2c_addr;
+       struct i2c_adapter *i2c_adap;
+
+       struct dibx000_i2c_master i2c_master;
+
+       fe_bandwidth_t current_bandwidth;
+
+       u16 dev_id;
+};
+
+static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
+{
+       u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+       u8 rb[2];
+       struct i2c_msg msg[2] = {
+               { .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
+               { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+       };
+
+       if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+               dprintk("i2c read error on %d\n",reg);
+
+       return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
+{
+       u8 b[4] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg = {
+               .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+       };
+       return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+
+static int dib3000mc_identify(struct dib3000mc_state *state)
+{
+       u16 value;
+       if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
+               dprintk("-E-  DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
+               return -EREMOTEIO;
        }
 
-       switch (mode) {
-               case 0: /* no impulse */ /* fall through */
-                       wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[0]);
-                       break;
-               case 1: /* new algo */
-                       wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[1]);
-                       set_or(DIB3000MC_REG_IMP_NOISE_55,DIB3000MC_IMP_NEW_ALGO(0)); /* gives 1<<10 */
-                       break;
-               default: /* old algo */
-                       wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[3]);
-                       break;
+       value = dib3000mc_read_word(state, 1026);
+       if (value != 0x3001 && value != 0x3002) {
+               dprintk("-E-  DiB3000MC/P: wrong Device ID (%x)\n",value);
+               return -EREMOTEIO;
        }
+       state->dev_id = value;
+
+       dprintk("-I-  found DiB3000MC/P: %x\n",state->dev_id);
+
        return 0;
 }
 
-static int dib3000mc_set_timing(struct dib3000_state *state, int upd_offset,
-               fe_transmit_mode_t fft, fe_bandwidth_t bw)
+static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
 {
-       u16 timf_msb,timf_lsb;
-       s32 tim_offset,tim_sgn;
-       u64 comp1,comp2,comp=0;
-
-       switch (bw) {
-               case BANDWIDTH_8_MHZ: comp = DIB3000MC_CLOCK_REF*8; break;
-               case BANDWIDTH_7_MHZ: comp = DIB3000MC_CLOCK_REF*7; break;
-               case BANDWIDTH_6_MHZ: comp = DIB3000MC_CLOCK_REF*6; break;
-               default: err("unknown bandwidth (%d)",bw); break;
-       }
-       timf_msb = (comp >> 16) & 0xff;
-       timf_lsb = (comp & 0xffff);
+/*
+       u32 timf_msb, timf_lsb, i;
+       int tim_sgn ;
+       LUInt comp1, comp2, comp ;
+//     u32 tim_offset ;
+       comp = 27700 * BW_INDEX_TO_KHZ(bw) / 1000;
+       timf_msb = (comp >> 16) & 0x00FF;
+       timf_lsb =  comp        & 0xFFFF;
 
        // Update the timing offset ;
-       if (upd_offset > 0) {
-               if (!state->timing_offset_comp_done) {
-                       msleep(200);
+       if (update_offset) {
+               if (state->timing_offset_comp_done == 0) {
+                       usleep(200000);
                        state->timing_offset_comp_done = 1;
                }
-               tim_offset = rd(DIB3000MC_REG_TIMING_OFFS_MSB);
+               tim_offset = dib3000mc_read_word(state, 416);
                if ((tim_offset & 0x2000) == 0x2000)
-                       tim_offset |= 0xC000;
-               if (fft == TRANSMISSION_MODE_2K)
-                       tim_offset <<= 2;
+                       tim_offset |= 0xC000; // PB: This only works if tim_offset is s16 - weird
+
+               if (nfft == 0)
+                       tim_offset = tim_offset << 2; // PB: Do not store the offset for different things in one variable
                state->timing_offset += tim_offset;
        }
-
        tim_offset = state->timing_offset;
+
        if (tim_offset < 0) {
                tim_sgn = 1;
                tim_offset = -tim_offset;
        } else
                tim_sgn = 0;
 
-       comp1 =  (u32)tim_offset * (u32)timf_lsb ;
-       comp2 =  (u32)tim_offset * (u32)timf_msb ;
+       comp1 = tim_offset * timf_lsb;
+       comp2 = tim_offset * timf_msb;
        comp  = ((comp1 >> 16) + comp2) >> 7;
 
        if (tim_sgn == 0)
-               comp = (u32)(timf_msb << 16) + (u32) timf_lsb + comp;
+               comp = timf_msb * (1<<16) + timf_lsb + comp;
        else
-               comp = (u32)(timf_msb << 16) + (u32) timf_lsb - comp ;
+               comp = timf_msb * (1<<16) + timf_lsb - comp;
+
+       timf_msb = (comp>>16)&0xFF ;
+       timf_lsb = comp&0xFFFF;
+*/
+       u32 timf = 1384402 * (BW_INDEX_TO_KHZ(bw) / 1000);
 
-       timf_msb = (comp >> 16) & 0xff;
-       timf_lsb = comp & 0xffff;
+       dib3000mc_write_word(state, 23, timf >> 16);
+       dib3000mc_write_word(state, 24, timf & 0xffff);
 
-       wr(DIB3000MC_REG_TIMING_FREQ_MSB,timf_msb);
-       wr(DIB3000MC_REG_TIMING_FREQ_LSB,timf_lsb);
        return 0;
 }
 
-static int dib3000mc_init_auto_scan(struct dib3000_state *state, fe_bandwidth_t bw, int boost)
+static int dib3000mc_setup_pwm3_state(struct dib3000mc_state *state)
 {
-       if (boost) {
-               wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_ON);
+    if (state->cfg->pwm3_inversion) {
+               dib3000mc_write_word(state, 51, (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
+               dib3000mc_write_word(state, 52, (0 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (2 << 0));
        } else {
-               wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_OFF);
-       }
-       switch (bw) {
-               case BANDWIDTH_8_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
-                       break;
-               case BANDWIDTH_7_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_7mhz);
-                       break;
-               case BANDWIDTH_6_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_6mhz);
-                       break;
-/*             case BANDWIDTH_5_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_5mhz);
-                       break;*/
-               case BANDWIDTH_AUTO:
-                       return -EOPNOTSUPP;
-               default:
-                       err("unknown bandwidth value (%d).",bw);
-                       return -EINVAL;
-       }
-       if (boost) {
-               u32 timeout = (rd(DIB3000MC_REG_BW_TIMOUT_MSB) << 16) +
-                       rd(DIB3000MC_REG_BW_TIMOUT_LSB);
-               timeout *= 85; timeout >>= 7;
-               wr(DIB3000MC_REG_BW_TIMOUT_MSB,(timeout >> 16) & 0xffff);
-               wr(DIB3000MC_REG_BW_TIMOUT_LSB,timeout & 0xffff);
+               dib3000mc_write_word(state, 51, (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
+               dib3000mc_write_word(state, 52, (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0));
        }
+
+    if (state->cfg->use_pwm3)
+               dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
+       else
+               dib3000mc_write_word(state, 245, 0);
+
+    dib3000mc_write_word(state, 1040, 0x3);
        return 0;
 }
 
-static int dib3000mc_set_adp_cfg(struct dib3000_state *state, fe_modulation_t con)
+static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
 {
-       switch (con) {
-               case QAM_64:
-                       wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[2]);
-                       break;
-               case QAM_16:
-                       wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[1]);
-                       break;
-               case QPSK:
-                       wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[0]);
-                       break;
-               case QAM_AUTO:
+       int    ret = 0;
+       u16 fifo_threshold = 1792;
+       u16 outreg = 0;
+       u16 outmode = 0;
+       u16 elecout = 1;
+       u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
+
+       dprintk("-I-  Setting output mode for demod %p to %d\n",
+                       &state->demod, mode);
+
+       switch (mode) {
+               case OUTMODE_HIGH_Z:  // disable
+                       elecout = 0;
+                       break;
+               case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
+                       outmode = 0;
+                       break;
+               case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
+                       outmode = 1;
+                       break;
+               case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
+                       outmode = 2;
+                       break;
+               case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
+                       elecout = 3;
+                       /*ADDR @ 206 :
+                       P_smo_error_discard  [1;6:6] = 0
+                       P_smo_rs_discard     [1;5:5] = 0
+                       P_smo_pid_parse      [1;4:4] = 0
+                       P_smo_fifo_flush     [1;3:3] = 0
+                       P_smo_mode           [2;2:1] = 11
+                       P_smo_ovf_prot       [1;0:0] = 0
+                       */
+                       smo_reg |= 3 << 1;
+                       fifo_threshold = 512;
+                       outmode = 5;
+                       break;
+               case OUTMODE_DIVERSITY:
+                       outmode = 4;
+                       elecout = 1;
                        break;
                default:
-                       warn("unkown constellation.");
+                       dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+                       outmode = 0;
                        break;
        }
-       return 0;
+
+       if ((state->cfg->output_mpeg2_in_188_bytes))
+               smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
+
+       outreg = dib3000mc_read_word(state, 244) & 0x07FF;
+       outreg |= (outmode << 11);
+       ret |= dib3000mc_write_word(state,  244, outreg);
+       ret |= dib3000mc_write_word(state,  206, smo_reg);   /*smo_ mode*/
+       ret |= dib3000mc_write_word(state,  207, fifo_threshold); /* synchronous fread */
+       ret |= dib3000mc_write_word(state, 1040, elecout);         /* P_out_cfg */
+       return ret;
 }
 
-static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_frontend_parameters *fep, int *auto_val)
+static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
 {
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-       fe_code_rate_t fe_cr = FEC_NONE;
-       u8 fft=0, guard=0, qam=0, alpha=0, sel_hp=0, cr=0, hrch=0;
-       int seq;
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       u16 bw_cfg[6] = { 0 };
+       u16 imp_bw_cfg[3] = { 0 };
+       u16 reg;
 
-       switch (ofdm->transmission_mode) {
-               case TRANSMISSION_MODE_2K: fft = DIB3000_TRANSMISSION_MODE_2K; break;
-               case TRANSMISSION_MODE_8K: fft = DIB3000_TRANSMISSION_MODE_8K; break;
-               case TRANSMISSION_MODE_AUTO: break;
-               default: return -EINVAL;
-       }
-       switch (ofdm->guard_interval) {
-               case GUARD_INTERVAL_1_32: guard = DIB3000_GUARD_TIME_1_32; break;
-               case GUARD_INTERVAL_1_16: guard = DIB3000_GUARD_TIME_1_16; break;
-               case GUARD_INTERVAL_1_8:  guard = DIB3000_GUARD_TIME_1_8; break;
-               case GUARD_INTERVAL_1_4:  guard = DIB3000_GUARD_TIME_1_4; break;
-               case GUARD_INTERVAL_AUTO: break;
-               default: return -EINVAL;
-       }
-       switch (ofdm->constellation) {
-               case QPSK:   qam = DIB3000_CONSTELLATION_QPSK; break;
-               case QAM_16: qam = DIB3000_CONSTELLATION_16QAM; break;
-               case QAM_64: qam = DIB3000_CONSTELLATION_64QAM; break;
-               case QAM_AUTO: break;
-               default: return -EINVAL;
-       }
-       switch (ofdm->hierarchy_information) {
-               case HIERARCHY_NONE: /* fall through */
-               case HIERARCHY_1: alpha = DIB3000_ALPHA_1; break;
-               case HIERARCHY_2: alpha = DIB3000_ALPHA_2; break;
-               case HIERARCHY_4: alpha = DIB3000_ALPHA_4; break;
-               case HIERARCHY_AUTO: break;
-               default: return -EINVAL;
-       }
-       if (ofdm->hierarchy_information == HIERARCHY_NONE) {
-               hrch   = DIB3000_HRCH_OFF;
-               sel_hp = DIB3000_SELECT_HP;
-               fe_cr  = ofdm->code_rate_HP;
-       } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
-               hrch   = DIB3000_HRCH_ON;
-               sel_hp = DIB3000_SELECT_LP;
-               fe_cr  = ofdm->code_rate_LP;
-       }
-       switch (fe_cr) {
-               case FEC_1_2: cr = DIB3000_FEC_1_2; break;
-               case FEC_2_3: cr = DIB3000_FEC_2_3; break;
-               case FEC_3_4: cr = DIB3000_FEC_3_4; break;
-               case FEC_5_6: cr = DIB3000_FEC_5_6; break;
-               case FEC_7_8: cr = DIB3000_FEC_7_8; break;
-               case FEC_NONE: break;
-               case FEC_AUTO: break;
-               default: return -EINVAL;
-       }
+/* settings here are for 27.7MHz */
+       switch (bw) {
+               case BANDWIDTH_8_MHZ:
+                       bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
+                       imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
+                       break;
 
-       wr(DIB3000MC_REG_DEMOD_PARM,DIB3000MC_DEMOD_PARM(alpha,qam,guard,fft));
-       wr(DIB3000MC_REG_HRCH_PARM,DIB3000MC_HRCH_PARM(sel_hp,cr,hrch));
+               case BANDWIDTH_7_MHZ:
+                       bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
+                       imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
+                       break;
 
-       switch (fep->inversion) {
-               case INVERSION_OFF:
-                       wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
+               case BANDWIDTH_6_MHZ:
+                       bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
+                       imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
                        break;
-               case INVERSION_AUTO: /* fall through */
-               case INVERSION_ON:
-                       wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_ON);
+
+               case 255 /* BANDWIDTH_5_MHZ */:
+                       bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
+                       imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
                        break;
-               default:
-                       return -EINVAL;
+
+               default: return -EINVAL;
        }
 
-       seq = dib3000_seq
-               [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]
-               [ofdm->guard_interval == GUARD_INTERVAL_AUTO]
-               [fep->inversion == INVERSION_AUTO];
-
-       deb_setf("seq? %d\n", seq);
-       wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS(seq,1));
-       *auto_val = ofdm->constellation == QAM_AUTO ||
-                       ofdm->hierarchy_information == HIERARCHY_AUTO ||
-                       ofdm->guard_interval == GUARD_INTERVAL_AUTO ||
-                       ofdm->transmission_mode == TRANSMISSION_MODE_AUTO ||
-                       fe_cr == FEC_AUTO ||
-                       fep->inversion == INVERSION_AUTO;
-       return 0;
-}
+       for (reg = 6; reg < 12; reg++)
+               dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
+       dib3000mc_write_word(state, 12, 0x0000);
+       dib3000mc_write_word(state, 13, 0x03e8);
+       dib3000mc_write_word(state, 14, 0x0000);
+       dib3000mc_write_word(state, 15, 0x03f2);
+       dib3000mc_write_word(state, 16, 0x0001);
+       dib3000mc_write_word(state, 17, 0xb0d0);
+       // P_sec_len
+       dib3000mc_write_word(state, 18, 0x0393);
+       dib3000mc_write_word(state, 19, 0x8700);
 
-static int dib3000mc_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
-{
-       struct dib3000_state* state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-       fe_code_rate_t *cr;
-       u16 tps_val,cr_val;
-       int inv_test1,inv_test2;
-       u32 dds_val, threshold = 0x1000000;
-
-       if (!(rd(DIB3000MC_REG_LOCK_507) & DIB3000MC_LOCK_507))
-               return 0;
-
-       dds_val = (rd(DIB3000MC_REG_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_DDS_FREQ_LSB);
-       deb_getf("DDS_FREQ: %6x\n",dds_val);
-       if (dds_val < threshold)
-               inv_test1 = 0;
-       else if (dds_val == threshold)
-               inv_test1 = 1;
-       else
-               inv_test1 = 2;
-
-       dds_val = (rd(DIB3000MC_REG_SET_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_SET_DDS_FREQ_LSB);
-       deb_getf("DDS_SET_FREQ: %6x\n",dds_val);
-       if (dds_val < threshold)
-               inv_test2 = 0;
-       else if (dds_val == threshold)
-               inv_test2 = 1;
-       else
-               inv_test2 = 2;
+       for (reg = 55; reg < 58; reg++)
+               dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
 
-       fep->inversion =
-               ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
-               ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
-               INVERSION_ON : INVERSION_OFF;
+       // Timing configuration
+       dib3000mc_set_timing(state, 0, bw, 0);
 
-       deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);
+       return 0;
+}
 
-       fep->frequency = state->last_tuned_freq;
-       fep->u.ofdm.bandwidth= state->last_tuned_bw;
+static u16 impulse_noise_val[29] =
 
-       tps_val = rd(DIB3000MC_REG_TUNING_PARM);
+{
+       0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
+       0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
+       0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
+};
 
-       switch (DIB3000MC_TP_QAM(tps_val)) {
-               case DIB3000_CONSTELLATION_QPSK:
-                       deb_getf("QPSK ");
-                       ofdm->constellation = QPSK;
-                       break;
-               case DIB3000_CONSTELLATION_16QAM:
-                       deb_getf("QAM16 ");
-                       ofdm->constellation = QAM_16;
-                       break;
-               case DIB3000_CONSTELLATION_64QAM:
-                       deb_getf("QAM64 ");
-                       ofdm->constellation = QAM_64;
-                       break;
-               default:
-                       err("Unexpected constellation returned by TPS (%d)", tps_val);
-                       break;
+static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
+{
+       u16 i;
+       for (i = 58; i < 87; i++)
+               dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
+
+       if (nfft == 1) {
+               dib3000mc_write_word(state, 58, 0x3b);
+               dib3000mc_write_word(state, 84, 0x00);
+               dib3000mc_write_word(state, 85, 0x8200);
        }
 
-       if (DIB3000MC_TP_HRCH(tps_val)) {
-               deb_getf("HRCH ON ");
-               cr = &ofdm->code_rate_LP;
-               ofdm->code_rate_HP = FEC_NONE;
-               switch (DIB3000MC_TP_ALPHA(tps_val)) {
-                       case DIB3000_ALPHA_0:
-                               deb_getf("HIERARCHY_NONE ");
-                               ofdm->hierarchy_information = HIERARCHY_NONE;
-                               break;
-                       case DIB3000_ALPHA_1:
-                               deb_getf("HIERARCHY_1 ");
-                               ofdm->hierarchy_information = HIERARCHY_1;
-                               break;
-                       case DIB3000_ALPHA_2:
-                               deb_getf("HIERARCHY_2 ");
-                               ofdm->hierarchy_information = HIERARCHY_2;
-                               break;
-                       case DIB3000_ALPHA_4:
-                               deb_getf("HIERARCHY_4 ");
-                               ofdm->hierarchy_information = HIERARCHY_4;
-                               break;
-                       default:
-                               err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
-                               break;
-               }
-               cr_val = DIB3000MC_TP_FEC_CR_LP(tps_val);
+       dib3000mc_write_word(state, 34, 0x1294);
+       dib3000mc_write_word(state, 35, 0x1ff8);
+       if (mode == 1)
+               dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
+}
+
+static int dib3000mc_init(struct dvb_frontend *demod)
+{
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       struct dibx000_agc_config *agc = state->cfg->agc;
+
+       // Restart Configuration
+       dib3000mc_write_word(state, 1027, 0x8000);
+       dib3000mc_write_word(state, 1027, 0x0000);
+
+       // power up the demod + mobility configuration
+       dib3000mc_write_word(state, 140, 0x0000);
+       dib3000mc_write_word(state, 1031, 0);
+
+       if (state->cfg->mobile_mode) {
+               dib3000mc_write_word(state, 139,  0x0000);
+               dib3000mc_write_word(state, 141,  0x0000);
+               dib3000mc_write_word(state, 175,  0x0002);
+               dib3000mc_write_word(state, 1032, 0x0000);
        } else {
-               deb_getf("HRCH OFF ");
-               cr = &ofdm->code_rate_HP;
-               ofdm->code_rate_LP = FEC_NONE;
-               ofdm->hierarchy_information = HIERARCHY_NONE;
-               cr_val = DIB3000MC_TP_FEC_CR_HP(tps_val);
+               dib3000mc_write_word(state, 139,  0x0001);
+               dib3000mc_write_word(state, 141,  0x0000);
+               dib3000mc_write_word(state, 175,  0x0000);
+               dib3000mc_write_word(state, 1032, 0x012C);
        }
+       dib3000mc_write_word(state, 1033, 0);
 
-       switch (cr_val) {
-               case DIB3000_FEC_1_2:
-                       deb_getf("FEC_1_2 ");
-                       *cr = FEC_1_2;
-                       break;
-               case DIB3000_FEC_2_3:
-                       deb_getf("FEC_2_3 ");
-                       *cr = FEC_2_3;
-                       break;
-               case DIB3000_FEC_3_4:
-                       deb_getf("FEC_3_4 ");
-                       *cr = FEC_3_4;
-                       break;
-               case DIB3000_FEC_5_6:
-                       deb_getf("FEC_5_6 ");
-                       *cr = FEC_4_5;
-                       break;
-               case DIB3000_FEC_7_8:
-                       deb_getf("FEC_7_8 ");
-                       *cr = FEC_7_8;
-                       break;
-               default:
-                       err("Unexpected FEC returned by TPS (%d)", tps_val);
-                       break;
-       }
+       // P_clk_cfg
+       dib3000mc_write_word(state, 1037, 12592);
 
-       switch (DIB3000MC_TP_GUARD(tps_val)) {
-               case DIB3000_GUARD_TIME_1_32:
-                       deb_getf("GUARD_INTERVAL_1_32 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_32;
-                       break;
-               case DIB3000_GUARD_TIME_1_16:
-                       deb_getf("GUARD_INTERVAL_1_16 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_16;
-                       break;
-               case DIB3000_GUARD_TIME_1_8:
-                       deb_getf("GUARD_INTERVAL_1_8 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_8;
-                       break;
-               case DIB3000_GUARD_TIME_1_4:
-                       deb_getf("GUARD_INTERVAL_1_4 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_4;
-                       break;
-               default:
-                       err("Unexpected Guard Time returned by TPS (%d)", tps_val);
-                       break;
-       }
+       // other configurations
 
-       switch (DIB3000MC_TP_FFT(tps_val)) {
-               case DIB3000_TRANSMISSION_MODE_2K:
-                       deb_getf("TRANSMISSION_MODE_2K ");
-                       ofdm->transmission_mode = TRANSMISSION_MODE_2K;
-                       break;
-               case DIB3000_TRANSMISSION_MODE_8K:
-                       deb_getf("TRANSMISSION_MODE_8K ");
-                       ofdm->transmission_mode = TRANSMISSION_MODE_8K;
-                       break;
-               default:
-                       err("unexpected transmission mode return by TPS (%d)", tps_val);
-                       break;
-       }
-       deb_getf("\n");
+       // P_ctrl_sfreq
+       dib3000mc_write_word(state, 33, (5 << 0));
+       dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
+
+       // Phase noise control
+       // P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
+       dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
+
+       if (state->cfg->phase_noise_mode == 0)
+               dib3000mc_write_word(state, 111, 0x00);
+       else
+               dib3000mc_write_word(state, 111, 0x02);
+
+       // P_agc_global
+       dib3000mc_write_word(state, 50, 0x8000);
+
+       // agc setup misc
+       dib3000mc_setup_pwm3_state(state);
+
+       // P_agc_counter_lock
+       dib3000mc_write_word(state, 53, 0x87);
+       // P_agc_counter_unlock
+       dib3000mc_write_word(state, 54, 0x87);
+
+       /* agc */
+       dib3000mc_write_word(state, 36, state->cfg->max_time);
+       dib3000mc_write_word(state, 37, agc->setup);
+       dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
+       dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
+
+       // set_agc_loop_Bw
+       dib3000mc_write_word(state, 40, 0x0179);
+       dib3000mc_write_word(state, 41, 0x03f0);
+
+       dib3000mc_write_word(state, 42, agc->agc1_max);
+       dib3000mc_write_word(state, 43, agc->agc1_min);
+       dib3000mc_write_word(state, 44, agc->agc2_max);
+       dib3000mc_write_word(state, 45, agc->agc2_min);
+       dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+       dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+       dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+       dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+// Begin: TimeOut registers
+       // P_pha3_thres
+       dib3000mc_write_word(state, 110, 3277);
+       // P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
+       dib3000mc_write_word(state,  26, 0x6680);
+       // lock_mask0
+       dib3000mc_write_word(state, 1, 4);
+       // lock_mask1
+       dib3000mc_write_word(state, 2, 4);
+       // lock_mask2
+       dib3000mc_write_word(state, 3, 0x1000);
+       // P_search_maxtrial=1
+       dib3000mc_write_word(state, 5, 1);
+
+       dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+
+       // div_lock_mask
+       dib3000mc_write_word(state,  4, 0x814);
+
+       dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
+       dib3000mc_write_word(state, 22, 0x463d);
+
+       // Spurious rm cfg
+       // P_cspu_regul, P_cspu_win_cut
+       dib3000mc_write_word(state, 120, 0x200f);
+       // P_adp_selec_monit
+       dib3000mc_write_word(state, 134, 0);
+
+       // Fec cfg
+       dib3000mc_write_word(state, 195, 0x10);
+
+       // diversity register: P_dvsy_sync_wait..
+       dib3000mc_write_word(state, 180, 0x2FF0);
+
+       // Impulse noise configuration
+       dib3000mc_set_impulse_noise(state, 0, 1);
+
+       // output mode set-up
+       dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
+
+       /* close the i2c-gate */
+       dib3000mc_write_word(state, 769, (1 << 7) );
 
        return 0;
 }
 
-static int dib3000mc_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep, int tuner)
+static int dib3000mc_sleep(struct dvb_frontend *demod)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-       int search_state,auto_val;
-       u16 val;
+       struct dib3000mc_state *state = demod->demodulator_priv;
 
-       if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
-               fe->ops.tuner_ops.set_params(fe, fep);
-               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-
-               state->last_tuned_freq = fep->frequency;
-       //      if (!scanboost) {
-                       dib3000mc_set_timing(state,0,ofdm->transmission_mode,ofdm->bandwidth);
-                       dib3000mc_init_auto_scan(state, ofdm->bandwidth, 0);
-                       state->last_tuned_bw = ofdm->bandwidth;
-
-                       wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
-                       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_AGC);
-                       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
-
-                       /* Default cfg isi offset adp */
-                       wr_foreach(dib3000mc_reg_offset,dib3000mc_offset[0]);
-
-                       wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT | DIB3000MC_ISI_INHIBIT);
-                       dib3000mc_set_adp_cfg(state,ofdm->constellation);
-                       wr(DIB3000MC_REG_UNK_133,DIB3000MC_UNK_133);
-
-                       wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
-                       /* power smoothing */
-                       if (ofdm->bandwidth != BANDWIDTH_8_MHZ) {
-                               wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[0]);
-                       } else {
-                               wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[3]);
-                       }
-                       auto_val = 0;
-                       dib3000mc_set_general_cfg(state,fep,&auto_val);
-                       dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
-                       val = rd(DIB3000MC_REG_DEMOD_PARM);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val|DIB3000MC_DEMOD_RST_DEMOD_ON);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val);
-       //      }
-               msleep(70);
-
-               /* something has to be auto searched */
-               if (auto_val) {
-                       int as_count=0;
-
-                       deb_setf("autosearch enabled.\n");
-
-                       val = rd(DIB3000MC_REG_DEMOD_PARM);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val);
-
-                       while ((search_state = dib3000_search_status(
-                                               rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100)
-                               msleep(10);
-
-                       deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count);
-
-                       if (search_state == 1) {
-                               struct dvb_frontend_parameters feps;
-                               if (dib3000mc_get_frontend(fe, &feps) == 0) {
-                                       deb_setf("reading tuning data from frontend succeeded.\n");
-                                       return dib3000mc_set_frontend(fe, &feps, 0);
-                               }
-                       }
-               } else {
-                       dib3000mc_set_impulse_noise(state,0,ofdm->transmission_mode,ofdm->bandwidth);
-                       wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
-                       dib3000mc_set_adp_cfg(state,ofdm->constellation);
-
-                       /* set_offset_cfg */
-                       wr_foreach(dib3000mc_reg_offset,
-                                       dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
-               }
-       } else { /* second call, after autosearch (fka: set_WithKnownParams) */
-//             dib3000mc_set_timing(state,1,ofdm->transmission_mode,ofdm->bandwidth);
-
-               auto_val = 0;
-               dib3000mc_set_general_cfg(state,fep,&auto_val);
-               if (auto_val)
-                       deb_info("auto_val is true, even though an auto search was already performed.\n");
-
-               dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
-               val = rd(DIB3000MC_REG_DEMOD_PARM);
-               wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
-               wr(DIB3000MC_REG_DEMOD_PARM,val);
+       dib3000mc_write_word(state, 1037, dib3000mc_read_word(state, 1037) | 0x0003);
+       dib3000mc_write_word(state, 1031, 0xFFFF);
+       dib3000mc_write_word(state, 1032, 0xFFFF);
+       dib3000mc_write_word(state, 1033, 0xFFF4);   // ****  Bin2
 
-               msleep(30);
+    return 0;
+}
 
-               wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
-                       dib3000mc_set_adp_cfg(state,ofdm->constellation);
-               wr_foreach(dib3000mc_reg_offset,
-                               dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
+static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
+{
+       u16 cfg[4] = { 0 },reg;
+       switch (qam) {
+               case 0:
+                       cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
+                       break;
+               case 1:
+                       cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
+                       break;
+               case 2:
+                       cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
+                       break;
        }
-       return 0;
+       for (reg = 129; reg < 133; reg++)
+               dib3000mc_write_word(state, reg, cfg[reg - 129]);
 }
 
-static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       deb_info("init start\n");
-
-       state->timing_offset = 0;
-       state->timing_offset_comp_done = 0;
+       u16 tmp;
 
-       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_CONFIG);
-       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
-       wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_UP);
-       wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_PUP_MOBILE);
-       wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_UP);
-       wr(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_INIT);
+       dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
 
-       wr(DIB3000MC_REG_RST_UNC,DIB3000MC_RST_UNC_OFF);
-       wr(DIB3000MC_REG_UNK_19,DIB3000MC_UNK_19);
+//     if (boost)
+//             dib3000mc_write_word(state, 100, (11 << 6) + 6);
+//     else
+               dib3000mc_write_word(state, 100, (16 << 6) + 9);
 
-       wr(33,5);
-       wr(36,81);
-       wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88);
+       dib3000mc_write_word(state, 1027, 0x0800);
+       dib3000mc_write_word(state, 1027, 0x0000);
 
-       wr(DIB3000MC_REG_UNK_99,DIB3000MC_UNK_99);
-       wr(DIB3000MC_REG_UNK_111,DIB3000MC_UNK_111_PH_N_MODE_0); /* phase noise algo off */
+       //Default cfg isi offset adp
+       dib3000mc_write_word(state, 26,  0x6680);
+       dib3000mc_write_word(state, 29,  0x1273);
+       dib3000mc_write_word(state, 33,       5);
+       dib3000mc_set_adp_cfg(state, 1);
+       dib3000mc_write_word(state, 133,  15564);
 
-       /* mobile mode - portable reception */
-       wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]);
+       dib3000mc_write_word(state, 12 , 0x0);
+       dib3000mc_write_word(state, 13 , 0x3e8);
+       dib3000mc_write_word(state, 14 , 0x0);
+       dib3000mc_write_word(state, 15 , 0x3f2);
 
-/* TUNER_PANASONIC_ENV57H12D5: */
-       wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
-       wr_foreach(dib3000mc_reg_agc_bandwidth_general,dib3000mc_agc_bandwidth_general);
-       wr_foreach(dib3000mc_reg_agc,dib3000mc_agc_tuner[1]);
+       dib3000mc_write_word(state, 93,0);
+       dib3000mc_write_word(state, 94,0);
+       dib3000mc_write_word(state, 95,0);
+       dib3000mc_write_word(state, 96,0);
+       dib3000mc_write_word(state, 97,0);
+       dib3000mc_write_word(state, 98,0);
 
-       wr(DIB3000MC_REG_UNK_110,DIB3000MC_UNK_110);
-       wr(26,0x6680);
-       wr(DIB3000MC_REG_UNK_1,DIB3000MC_UNK_1);
-       wr(DIB3000MC_REG_UNK_2,DIB3000MC_UNK_2);
-       wr(DIB3000MC_REG_UNK_3,DIB3000MC_UNK_3);
-       wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS_DEFAULT);
+       dib3000mc_set_impulse_noise(state, 0, chan->nfft);
 
-       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
-       wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
+       tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
+       dib3000mc_write_word(state, 0, tmp);
 
-       wr(DIB3000MC_REG_UNK_4,DIB3000MC_UNK_4);
+       dib3000mc_write_word(state, 5, seq);
 
-       wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
-       wr(DIB3000MC_REG_SET_DDS_FREQ_LSB,DIB3000MC_DDS_FREQ_LSB);
+       tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
+       if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
+               tmp |= chan->vit_code_rate_hp << 1;
+       else
+               tmp |= chan->vit_code_rate_lp << 1;
+       dib3000mc_write_word(state, 181, tmp);
 
-       dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
-//     wr_foreach(dib3000mc_reg_timing_freq,dib3000mc_timing_freq[3]);
+       // diversity synchro delay
+       tmp = dib3000mc_read_word(state, 180) & 0x000f;
+       tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin
+       dib3000mc_write_word(state, 180, tmp);
 
-       wr(DIB3000MC_REG_UNK_120,DIB3000MC_UNK_120);
-       wr(DIB3000MC_REG_UNK_134,DIB3000MC_UNK_134);
-       wr(DIB3000MC_REG_FEC_CFG,DIB3000MC_FEC_CFG);
+       // restart demod
+       tmp = dib3000mc_read_word(state, 0);
+       dib3000mc_write_word(state, 0, tmp | (1 << 9));
+       dib3000mc_write_word(state, 0, tmp);
 
-       wr(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
+       msleep(30);
 
-       dib3000mc_set_impulse_noise(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
+       dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
+}
 
-/* output mode control, just the MPEG2_SLAVE */
-//     set_or(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);
-       wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);
-       wr(DIB3000MC_REG_SMO_MODE,DIB3000MC_SMO_MODE_SLAVE);
-       wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_SLAVE);
-       wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_SLAVE);
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan)
+{
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       u16 reg;
+//     u32 val;
+       struct dibx000_ofdm_channel fchan;
 
-/* MPEG2_PARALLEL_CONTINUOUS_CLOCK
-       wr(DIB3000MC_REG_OUTMODE,
-               DIB3000MC_SET_OUTMODE(DIB3000MC_OM_PAR_CONT_CLK,
-                       rd(DIB3000MC_REG_OUTMODE)));
+       INIT_OFDM_CHANNEL(&fchan);
+       fchan = *chan;
 
-       wr(DIB3000MC_REG_SMO_MODE,
-                       DIB3000MC_SMO_MODE_DEFAULT |
-                       DIB3000MC_SMO_MODE_188);
 
-       wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_DEFAULT);
-       wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
-*/
+       /* a channel for autosearch */
+       reg = 0;
+       if (chan->nfft == -1 && chan->guard == -1) reg = 7;
+       if (chan->nfft == -1 && chan->guard != -1) reg = 2;
+       if (chan->nfft != -1 && chan->guard == -1) reg = 3;
 
-/* diversity */
-       wr(DIB3000MC_REG_DIVERSITY1,DIB3000MC_DIVERSITY1_DEFAULT);
-       wr(DIB3000MC_REG_DIVERSITY2,DIB3000MC_DIVERSITY2_DEFAULT);
+       fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
+       fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
+       fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
 
-       set_and(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
+       dib3000mc_set_channel_cfg(state, &fchan, reg);
 
-       set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
+       reg = dib3000mc_read_word(state, 0);
+       dib3000mc_write_word(state, 0, reg | (1 << 8));
+       dib3000mc_write_word(state, 0, reg);
 
-       deb_info("init end\n");
        return 0;
 }
-static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+
+static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       u16 lock = rd(DIB3000MC_REG_LOCKING);
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       u16 irq_pending = dib3000mc_read_word(state, 511);
 
-       *stat = 0;
-       if (DIB3000MC_AGC_LOCK(lock))
-               *stat |= FE_HAS_SIGNAL;
-       if (DIB3000MC_CARRIER_LOCK(lock))
-               *stat |= FE_HAS_CARRIER;
-       if (DIB3000MC_TPS_LOCK(lock))
-               *stat |= FE_HAS_VITERBI;
-       if (DIB3000MC_MPEG_SYNC_LOCK(lock))
-               *stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
+       if (irq_pending & 0x1) // failed
+               return 1;
 
-       deb_stat("actual status is %2x fifo_level: %x,244: %x, 206: %x, 207: %x, 1040: %x\n",*stat,rd(510),rd(244),rd(206),rd(207),rd(1040));
+       if (irq_pending & 0x2) // succeeded
+               return 2;
 
-       return 0;
+       return 0; // still pending
 }
 
-static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber)
+static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       *ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB));
+       struct dib3000mc_state *state = demod->demodulator_priv;
+
+       // ** configure demod **
+       dib3000mc_set_channel_cfg(state, ch, 0);
+
+       // activates isi
+       dib3000mc_write_word(state, 29, 0x1073);
+
+       dib3000mc_set_adp_cfg(state, (u8)ch->nqam);
+
+       if (ch->nfft == 1) {
+               dib3000mc_write_word(state, 26, 38528);
+               dib3000mc_write_word(state, 33, 8);
+       } else {
+               dib3000mc_write_word(state, 26, 30336);
+               dib3000mc_write_word(state, 33, 6);
+       }
+
+       // if (lock)
+       //      dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
+
        return 0;
 }
 
-static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-
-       *unc = rd(DIB3000MC_REG_PACKET_ERRORS);
-       return 0;
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       return dib3000mc_set_output_mode(state, mode);
 }
 
-/* see dib3000mb.c for calculation comments */
-static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB);
-       *strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f);
+       struct dib3000mc_state *st;
+       int k,ret=0;
+       u8 new_addr;
+
+       static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
+
+       for (k = no_of_demods-1; k >= 0; k--) {
+               st = demod[k]->demodulator_priv;
+
+               /* designated i2c address */
+               new_addr          = DIB3000MC_I2C_ADDRESS[k];
+
+               st->i2c_addr = new_addr;
+               if (dib3000mc_identify(st) != 0) {
+                       st->i2c_addr = default_addr;
+                       if (dib3000mc_identify(st) != 0) {
+                               dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
+                               return -EINVAL;
+                       }
+               }
+
+               /* turn on div_out */
+               dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK);
+
+               // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
+               ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1);
+               st->i2c_addr = new_addr;
+       }
+
+       for (k = 0; k < no_of_demods; k++) {
+               st = demod[k]->demodulator_priv;
+
+               ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3);
 
-       deb_stat("signal: mantisse = %d, exponent = %d\n",(*strength >> 8) & 0xff, *strength & 0xff);
+               /* turn off data output */
+               dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z);
+               dib3000mc_write_word(st, 769, (1 << 7) );
+
+       }
        return 0;
 }
 
-/* see dib3000mb.c for calculation comments */
-static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
+struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB),
-               val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB);
-       u16 sig,noise;
+       struct dib3000mc_state *st = demod->demodulator_priv;
+       return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
+}
 
-       sig =   (((val >> 6) & 0xff) << 8) + (val & 0x3f);
-       noise = (((val >> 4) & 0xff) << 8) + ((val & 0xf) << 2) + ((val2 >> 14) & 0x3);
-       if (noise == 0)
-               *snr = 0xffff;
-       else
-               *snr = (u16) sig/noise;
+EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
+
+static int dib3000mc_get_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
+{
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 tps = dib3000mc_read_word(state,458);
+
+       fep->inversion = INVERSION_AUTO;
+
+       fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+       switch ((tps >> 8) & 0x1) {
+               case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+               case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+       }
+
+       switch (tps & 0x3) {
+               case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+               case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+               case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+               case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+       }
+
+       switch ((tps >> 13) & 0x3) {
+               case 0: fep->u.ofdm.constellation = QPSK; break;
+               case 1: fep->u.ofdm.constellation = QAM_16; break;
+               case 2:
+               default: fep->u.ofdm.constellation = QAM_64; break;
+       }
+
+       /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+       /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
+
+       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       switch ((tps >> 5) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+       }
+
+       switch ((tps >> 2) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+       }
 
-       deb_stat("signal: mantisse = %d, exponent = %d\n",(sig >> 8) & 0xff, sig & 0xff);
-       deb_stat("noise:  mantisse = %d, exponent = %d\n",(noise >> 8) & 0xff, noise & 0xff);
-       deb_stat("snr: %d\n",*snr);
        return 0;
 }
 
-static int dib3000mc_sleep(struct dvb_frontend* fe)
+static int dib3000mc_set_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       struct dibx000_ofdm_channel ch;
 
-       set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN);
-       wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN);
-       wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_POWER_DOWN);
-       wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_DOWN);
-       return 0;
+       INIT_OFDM_CHANNEL(&ch);
+       FEP2DIB(fep,&ch);
+
+       state->current_bandwidth = fep->u.ofdm.bandwidth;
+       dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, fep);
+               msleep(100);
+       }
+
+       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+               fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
+               fep->u.ofdm.constellation     == QAM_AUTO ||
+               fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+               int i = 100, found;
+
+               dib3000mc_autosearch_start(fe, &ch);
+               do {
+                       msleep(1);
+                       found = dib3000mc_autosearch_is_irq(fe);
+               } while (found == 0 && i--);
+
+               dprintk("autosearch returns: %d\n",found);
+               if (found == 0 || found == 1)
+                       return 0; // no channel found
+
+               dib3000mc_get_frontend(fe, fep);
+               FEP2DIB(fep,&ch);
+       }
+
+       /* make this a config parameter */
+       dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+       return dib3000mc_tune(fe, &ch);
 }
 
-static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
 {
-       tune->min_delay_ms = 1000;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 lock = dib3000mc_read_word(state, 509);
+
+       *stat = 0;
+
+       if (lock & 0x8000)
+               *stat |= FE_HAS_SIGNAL;
+       if (lock & 0x3000)
+               *stat |= FE_HAS_CARRIER;
+       if (lock & 0x0100)
+               *stat |= FE_HAS_VITERBI;
+       if (lock & 0x0010)
+               *stat |= FE_HAS_SYNC;
+       if (lock & 0x0008)
+               *stat |= FE_HAS_LOCK;
+
        return 0;
 }
 
-static int dib3000mc_fe_init_nonmobile(struct dvb_frontend* fe)
+static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-       return dib3000mc_fe_init(fe, 0);
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       *ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
+       return 0;
 }
 
-static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)
+static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
 {
-       return dib3000mc_set_frontend(fe, fep, 1);
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       *unc = dib3000mc_read_word(state, 508);
+       return 0;
 }
 
-static void dib3000mc_release(struct dvb_frontend* fe)
+static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       kfree(state);
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 val = dib3000mc_read_word(state, 392);
+       *strength = 65535 - val;
+       return 0;
 }
 
-/* pid filter and transfer stuff */
-static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
+static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
-       wr(index+DIB3000MC_REG_FIRST_PID,pid);
+       *snr = 0x0000;
        return 0;
 }
 
-static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff)
+static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
-       deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
-
-       if (onoff) {
-               deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
-               wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
-       } else {
-               deb_xfer("%d %x\n",tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);
-               wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);
-       }
+       tune->min_delay_ms = 1000;
        return 0;
 }
 
-static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
+static void dib3000mc_release(struct dvb_frontend *fe)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
-       deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
-
-       if (onoff) {
-               wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_PID_PARSE);
-       } else {
-               wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE);
-       }
-       return 0;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       dibx000_exit_i2c_master(&state->i2c_master);
+       kfree(state);
 }
 
-static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
+int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       if (onoff) {
-               wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
-       } else {
-               wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));
-       }
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
        return 0;
 }
+EXPORT_SYMBOL(dib3000mc_pid_control);
 
-static int dib3000mc_demod_init(struct dib3000_state *state)
+int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
 {
-       u16 default_addr = 0x0a;
-       /* first init */
-       if (state->config.demod_address != default_addr) {
-               deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr);
-               wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
-               wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_PAR_CONT_CLK);
-
-               wr(DIB3000MC_REG_RST_I2C_ADDR,
-                       DIB3000MC_DEMOD_ADDR(default_addr) |
-                       DIB3000MC_DEMOD_ADDR_ON);
-
-               state->config.demod_address = default_addr;
-
-               wr(DIB3000MC_REG_RST_I2C_ADDR,
-                       DIB3000MC_DEMOD_ADDR(default_addr));
-       } else
-               deb_info("demod is already initialized. Demod addr: 0x%x\n",state->config.demod_address);
-       return 0;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
+       tmp |= (onoff << 4);
+       return dib3000mc_write_word(state, 206, tmp);
 }
+EXPORT_SYMBOL(dib3000mc_pid_parse);
 
+void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
+{
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       state->cfg = cfg;
+}
+EXPORT_SYMBOL(dib3000mc_set_config);
 
 static struct dvb_frontend_ops dib3000mc_ops;
 
-struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
-                                     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8        default_addr,                           u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[])
 {
-       struct dib3000_state* state = NULL;
-       u16 devid;
+       struct dib3000mc_state *st;
+       int k, num=0;
 
-       /* allocate memory for the internal state */
-       state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (no_of_demods < 1)
+               return -EINVAL;
 
-       /* setup the state */
-       state->i2c = i2c;
-       memcpy(&state->config,config,sizeof(struct dib3000_config));
+       for (k = 0; k < no_of_demods; k++) {
+               st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+               if (st == NULL)
+                       goto error;
 
-       /* check for the correct demod */
-       if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
-               goto error;
+               num++;
 
-       devid = rd(DIB3000_REG_DEVICE_ID);
-       if (devid != DIB3000MC_DEVICE_ID && devid != DIB3000P_DEVICE_ID)
-               goto error;
+               st->cfg = &cfg[k];
+       //      st->gpio_val = cfg[k].gpio_val;
+       //      st->gpio_dir = cfg[k].gpio_dir;
+               st->i2c_adap = i2c_adap;
 
-       switch (devid) {
-               case DIB3000MC_DEVICE_ID:
-                       info("Found a DiBcom 3000M-C, interesting...");
-                       break;
-               case DIB3000P_DEVICE_ID:
-                       info("Found a DiBcom 3000P.");
-                       break;
-       }
+               demod[k]           = &st->demod;
+               demod[k]->demodulator_priv     = st;
+               memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 
-       /* create dvb_frontend */
-       memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
-       state->frontend.demodulator_priv = state;
+//             INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st);
+//             demod[k]->register_access = &st->register_access;
+       }
 
-       /* set the xfer operations */
-       xfer_ops->pid_parse = dib3000mc_pid_parse;
-       xfer_ops->fifo_ctrl = dib3000mc_fifo_control;
-       xfer_ops->pid_ctrl = dib3000mc_pid_control;
-       xfer_ops->tuner_pass_ctrl = dib3000mc_tuner_pass_ctrl;
+       if (do_i2c_enum) {
+               if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0)
+                       goto error;
+       } else {
+               st = demod[0]->demodulator_priv;
+               st->i2c_addr = default_addr;
+               if (dib3000mc_identify(st) != 0)
+                       goto error;
+       }
 
-       dib3000mc_demod_init(state);
+       for (k = 0; k < num; k++) {
+               st = demod[k]->demodulator_priv;
+               dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
+       }
 
-       return &state->frontend;
+       return 0;
 
 error:
-       kfree(state);
-       return NULL;
+       for (k = 0; k < num; k++) {
+               kfree(demod[k]->demodulator_priv);
+               demod[k] = NULL;
+       }
+       return -EINVAL;
 }
+
 EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {
-
        .info = {
-               .name                   = "DiBcom 3000P/M-C DVB-T",
-               .type                   = FE_OFDM,
-               .frequency_min          = 44250000,
-               .frequency_max          = 867250000,
-               .frequency_stepsize     = 62500,
+               .name = "DiBcom 3000MC/P",
+               .type = FE_OFDM,
+               .frequency_min      = 44250000,
+               .frequency_max      = 867250000,
+               .frequency_stepsize = 62500,
                .caps = FE_CAN_INVERSION_AUTO |
-                               FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-                               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-                               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-                               FE_CAN_TRANSMISSION_MODE_AUTO |
-                               FE_CAN_GUARD_INTERVAL_AUTO |
-                               FE_CAN_RECOVER |
-                               FE_CAN_HIERARCHY_AUTO,
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_RECOVER |
+                       FE_CAN_HIERARCHY_AUTO,
        },
 
-       .release = dib3000mc_release,
+       .release              = dib3000mc_release,
 
-       .init = dib3000mc_fe_init_nonmobile,
-       .sleep = dib3000mc_sleep,
+       .init                 = dib3000mc_init,
+       .sleep                = dib3000mc_sleep,
 
-       .set_frontend = dib3000mc_set_frontend_and_tuner,
-       .get_frontend = dib3000mc_get_frontend,
-       .get_tune_settings = dib3000mc_fe_get_tune_settings,
+       .set_frontend         = dib3000mc_set_frontend,
+       .get_tune_settings    = dib3000mc_fe_get_tune_settings,
+       .get_frontend         = dib3000mc_get_frontend,
 
-       .read_status = dib3000mc_read_status,
-       .read_ber = dib3000mc_read_ber,
+       .read_status          = dib3000mc_read_status,
+       .read_ber             = dib3000mc_read_ber,
        .read_signal_strength = dib3000mc_read_signal_strength,
-       .read_snr = dib3000mc_read_snr,
-       .read_ucblocks = dib3000mc_read_unc_blocks,
+       .read_snr             = dib3000mc_read_snr,
+       .read_ucblocks        = dib3000mc_read_unc_blocks,
 };
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
new file mode 100644 (file)
index 0000000..fd0b2e7
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Driver for DiBcom DiB3000MC/P-demodulator.
+ *
+ * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de)
+ *
+ * This code is partially based on the previous dib3000mc.c .
+ *
+ * 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.
+ */
+#ifndef DIB3000MC_H
+#define DIB3000MC_H
+
+#include "dibx000_common.h"
+
+struct dib3000mc_config {
+       struct dibx000_agc_config *agc;
+
+       u8 phase_noise_mode;
+       u8 impulse_noise_mode;
+
+       u8  pwm3_inversion;
+       u8  use_pwm3;
+       u16 pwm3_value;
+
+       u16 max_time;
+       u16 ln_adc_level;
+
+       u8 mobile_mode;
+
+       u8 output_mpeg2_in_188_bytes;
+};
+
+#define DEFAULT_DIB3000MC_I2C_ADDRESS 16
+#define DEFAULT_DIB3000P_I2C_ADDRESS  24
+
+#if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE)
+extern int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr,
+    u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[]);
+#else
+static inline struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
+                                            struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_DIB3000MC
+
+extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating);
+
+extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
+extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);
+
+extern void dib3000mc_set_config(struct dvb_frontend *, struct dib3000mc_config *);
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib3000mc_priv.h b/drivers/media/dvb/frontends/dib3000mc_priv.h
deleted file mode 100644 (file)
index 2930aac..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * dib3000mc_priv.h
- *
- * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- * for more information see dib3000mc.c .
- */
-
-#ifndef __DIB3000MC_PRIV_H__
-#define __DIB3000MC_PRIV_H__
-
-/*
- * Demodulator parameters
- * reg: 0  1 1  1 11 11 111
- *         | |  |  |  |  |
- *         | |  |  |  |  +-- alpha (000=0, 001=1, 010=2, 100=4)
- *         | |  |  |  +----- constellation (00=QPSK, 01=16QAM, 10=64QAM)
- *         | |  |  +-------- guard (00=1/32, 01=1/16, 10=1/8, 11=1/4)
- *         | |  +----------- transmission mode (0=2k, 1=8k)
- *         | |
- *         | +-------------- restart autosearch for parameters
- *         +---------------- restart the demodulator
- * reg: 181      1 111 1
- *               |  |  |
- *               |  |  +- FEC applies for HP or LP (0=LP, 1=HP)
- *               |  +---- FEC rate (001=1/2, 010=2/3, 011=3/4, 101=5/6, 111=7/8)
- *               +------- hierarchy on (0=no, 1=yes)
- */
-
-/* demodulator tuning parameter and restart options */
-#define DIB3000MC_REG_DEMOD_PARM               (     0)
-#define DIB3000MC_DEMOD_PARM(a,c,g,t)  ( \
-                (0x7 & a) | \
-               ((0x3 & c) << 3) | \
-               ((0x3 & g) << 5) | \
-               ((0x1 & t) << 7) )
-#define DIB3000MC_DEMOD_RST_AUTO_SRCH_ON       (1 << 8)
-#define DIB3000MC_DEMOD_RST_AUTO_SRCH_OFF      (0 << 8)
-#define DIB3000MC_DEMOD_RST_DEMOD_ON           (1 << 9)
-#define DIB3000MC_DEMOD_RST_DEMOD_OFF          (0 << 9)
-
-/* register for hierarchy parameters */
-#define DIB3000MC_REG_HRCH_PARM                        (   181)
-#define DIB3000MC_HRCH_PARM(s,f,h)             ( \
-                (0x1 & s) | \
-               ((0x7 & f) << 1) | \
-               ((0x1 & h) << 4) )
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_1                            (     1)
-#define DIB3000MC_UNK_1                                        (  0x04)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_2                            (     2)
-#define DIB3000MC_UNK_2                                        (  0x04)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_3                            (     3)
-#define DIB3000MC_UNK_3                                        (0x1000)
-
-#define DIB3000MC_REG_UNK_4                            (     4)
-#define DIB3000MC_UNK_4                                        (0x0814)
-
-/* timeout ??? */
-#define DIB3000MC_REG_SEQ_TPS                  (     5)
-#define DIB3000MC_SEQ_TPS_DEFAULT              (     1)
-#define DIB3000MC_SEQ_TPS(s,t)                 ( \
-               ((s & 0x0f) << 4) | \
-               ((t & 0x01) << 8) )
-#define DIB3000MC_IS_TPS(v)                            ((v << 8) & 0x1)
-#define DIB3000MC_IS_AS(v)                             ((v >> 4) & 0xf)
-
-/* parameters for the bandwidth */
-#define DIB3000MC_REG_BW_TIMOUT_MSB            (     6)
-#define DIB3000MC_REG_BW_TIMOUT_LSB            (     7)
-
-static u16 dib3000mc_reg_bandwidth[] = { 6,7,8,9,10,11,16,17 };
-
-/*static u16 dib3000mc_bandwidth_5mhz[] =
-       { 0x28, 0x9380, 0x87, 0x4100, 0x2a4, 0x4500, 0x1, 0xb0d0 };*/
-
-static u16 dib3000mc_bandwidth_6mhz[] =
-       { 0x21, 0xd040, 0x70, 0xb62b, 0x233, 0x8ed5, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_bandwidth_7mhz[] =
-       { 0x1c, 0xfba5, 0x60, 0x9c25, 0x1e3, 0x0cb7, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_bandwidth_8mhz[] =
-       { 0x19, 0x5c30, 0x54, 0x88a0, 0x1a6, 0xab20, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_reg_bandwidth_general[] = { 12,13,14,15 };
-static u16 dib3000mc_bandwidth_general[] = { 0x0000, 0x03e8, 0x0000, 0x03f2 };
-
-/* lock mask */
-#define DIB3000MC_REG_LOCK_MASK                        (    15)
-#define DIB3000MC_ACTIVATE_LOCK_MASK   (0x0800)
-
-/* reset the uncorrected packet count (??? do it 5 times) */
-#define DIB3000MC_REG_RST_UNC                  (    18)
-#define DIB3000MC_RST_UNC_ON                   (     1)
-#define DIB3000MC_RST_UNC_OFF                  (     0)
-
-#define DIB3000MC_REG_UNK_19                   (    19)
-#define DIB3000MC_UNK_19                               (     0)
-
-/* DDS frequency value (IF position) and inversion bit */
-#define DIB3000MC_REG_INVERSION                        (    21)
-#define DIB3000MC_REG_SET_DDS_FREQ_MSB (    21)
-#define DIB3000MC_DDS_FREQ_MSB_INV_OFF (0x0164)
-#define DIB3000MC_DDS_FREQ_MSB_INV_ON  (0x0364)
-
-#define DIB3000MC_REG_SET_DDS_FREQ_LSB (    22)
-#define DIB3000MC_DDS_FREQ_LSB                 (0x463d)
-
-/* timing frequencies setting */
-#define DIB3000MC_REG_TIMING_FREQ_MSB  (    23)
-#define DIB3000MC_REG_TIMING_FREQ_LSB  (    24)
-#define DIB3000MC_CLOCK_REF                            (0x151fd1)
-
-//static u16 dib3000mc_reg_timing_freq[] = { 23,24 };
-
-//static u16 dib3000mc_timing_freq[][2] = {
-//     { 0x69, 0x9f18 }, /* 5 MHz */
-//     { 0x7e ,0xbee9 }, /* 6 MHz */
-//     { 0x93 ,0xdebb }, /* 7 MHz */
-//     { 0xa8 ,0xfe8c }, /* 8 MHz */
-//};
-
-/* timeout ??? */
-static u16 dib3000mc_reg_offset[] = { 26,33 };
-
-static u16 dib3000mc_offset[][2] = {
-       { 26240, 5 }, /* default */
-       { 30336, 6 }, /* 8K */
-       { 38528, 8 }, /* 2K */
-};
-
-#define DIB3000MC_REG_ISI                              (    29)
-#define DIB3000MC_ISI_DEFAULT                  (0x1073)
-#define DIB3000MC_ISI_ACTIVATE                 (0x0000)
-#define DIB3000MC_ISI_INHIBIT                  (0x0200)
-
-/* impulse noise control */
-static u16 dib3000mc_reg_imp_noise_ctl[] = { 34,35 };
-
-static u16 dib3000mc_imp_noise_ctl[][2] = {
-       { 0x1294, 0x1ff8 }, /* mode 0 */
-       { 0x1294, 0x1ff8 }, /* mode 1 */
-       { 0x1294, 0x1ff8 }, /* mode 2 */
-       { 0x1294, 0x1ff8 }, /* mode 3 */
-       { 0x1294, 0x1ff8 }, /* mode 4 */
-};
-
-/* AGC registers */
-static u16 dib3000mc_reg_agc[] = {
-       36,37,38,39,42,43,44,45,46,47,48,49
-};
-
-static u16 dib3000mc_agc_tuner[][12] = {
-       {       0x0051, 0x301d, 0x0000, 0x1cc7, 0xcf5c, 0x6666,
-               0xbae1, 0xa148, 0x3b5e, 0x3c1c, 0x001a, 0x2019
-       }, /* TUNER_PANASONIC_ENV77H04D5, */
-
-       {       0x0051, 0x301d, 0x0000, 0x1cc7, 0xdc29, 0x570a,
-               0xbae1, 0x8ccd, 0x3b6d, 0x551d, 0x000a, 0x951e
-       }, /* TUNER_PANASONIC_ENV57H13D5, TUNER_PANASONIC_ENV57H12D5 */
-
-       {       0x0051, 0x301d, 0x0000, 0x1cc7, 0xffff, 0xffff,
-               0xffff, 0x0000, 0xfdfd, 0x4040, 0x00fd, 0x4040
-       }, /* TUNER_SAMSUNG_DTOS333IH102, TUNER_RFAGCIN_UNKNOWN */
-
-       {       0x0196, 0x301d, 0x0000, 0x1cc7, 0xbd71, 0x5c29,
-               0xb5c3, 0x6148, 0x6569, 0x5127, 0x0033, 0x3537
-       }, /* TUNER_PROVIDER_X */
-       /* TODO TUNER_PANASONIC_ENV57H10D8, TUNER_PANASONIC_ENV57H11D8 */
-};
-
-/* AGC loop bandwidth */
-static u16 dib3000mc_reg_agc_bandwidth[] = { 40,41 };
-static u16 dib3000mc_agc_bandwidth[]  = { 0x119,0x330 };
-
-static u16 dib3000mc_reg_agc_bandwidth_general[] = { 50,51,52,53,54 };
-static u16 dib3000mc_agc_bandwidth_general[] =
-       { 0x8000, 0x91ca, 0x01ba, 0x0087, 0x0087 };
-
-#define DIB3000MC_REG_IMP_NOISE_55             (    55)
-#define DIB3000MC_IMP_NEW_ALGO(w)              (w | (1<<10))
-
-/* Impulse noise params */
-static u16 dib3000mc_reg_impulse_noise[] = { 55,56,57 };
-static u16 dib3000mc_impluse_noise[][3] = {
-       { 0x489, 0x89, 0x72 }, /* 5 MHz */
-       { 0x4a5, 0xa5, 0x89 }, /* 6 MHz */
-       { 0x4c0, 0xc0, 0xa0 }, /* 7 MHz */
-       { 0x4db, 0xdb, 0xb7 }, /* 8 Mhz */
-};
-
-static u16 dib3000mc_reg_fft[] = {
-       58,59,60,61,62,63,64,65,66,67,68,69,
-       70,71,72,73,74,75,76,77,78,79,80,81,
-       82,83,84,85,86
-};
-
-static u16 dib3000mc_fft_modes[][29] = {
-       {       0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
-               0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
-               0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
-               0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
-               0x3ffe, 0x5b3, 0x3feb, 0x76,   0x0, 0xd
-       }, /* fft mode 0 */
-       {       0x3b, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
-               0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
-               0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
-               0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
-               0x3ffe, 0x5b3, 0x3feb, 0x0,  0x8200, 0xd
-       }, /* fft mode 1 */
-};
-
-#define DIB3000MC_REG_UNK_88                   (    88)
-#define DIB3000MC_UNK_88                               (0x0410)
-
-static u16 dib3000mc_reg_bw[] = { 93,94,95,96,97,98 };
-static u16 dib3000mc_bw[][6] = {
-       { 0,0,0,0,0,0 }, /* 5 MHz */
-       { 0,0,0,0,0,0 }, /* 6 MHz */
-       { 0,0,0,0,0,0 }, /* 7 MHz */
-       { 0x20, 0x21, 0x20, 0x23, 0x20, 0x27 }, /* 8 MHz */
-};
-
-
-/* phase noise control */
-#define DIB3000MC_REG_UNK_99                   (    99)
-#define DIB3000MC_UNK_99                               (0x0220)
-
-#define DIB3000MC_REG_SCAN_BOOST               (   100)
-#define DIB3000MC_SCAN_BOOST_ON                        ((11 << 6) + 6)
-#define DIB3000MC_SCAN_BOOST_OFF               ((16 << 6) + 9)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_110                  (   110)
-#define DIB3000MC_UNK_110                              (  3277)
-
-#define DIB3000MC_REG_UNK_111                  (   111)
-#define DIB3000MC_UNK_111_PH_N_MODE_0  (     0)
-#define DIB3000MC_UNK_111_PH_N_MODE_1  (1 << 1)
-
-/* superious rm config */
-#define DIB3000MC_REG_UNK_120                  (   120)
-#define DIB3000MC_UNK_120                              (  8207)
-
-#define DIB3000MC_REG_UNK_133                  (   133)
-#define DIB3000MC_UNK_133                              ( 15564)
-
-#define DIB3000MC_REG_UNK_134                  (   134)
-#define DIB3000MC_UNK_134                              (     0)
-
-/* adapter config for constellation */
-static u16 dib3000mc_reg_adp_cfg[] = { 129, 130, 131, 132 };
-
-static u16 dib3000mc_adp_cfg[][4] = {
-       { 0x99a, 0x7fae, 0x333, 0x7ff0 }, /* QPSK  */
-       { 0x23d, 0x7fdf, 0x0a4, 0x7ff0 }, /* 16-QAM */
-       { 0x148, 0x7ff0, 0x0a4, 0x7ff8 }, /* 64-QAM */
-};
-
-static u16 dib3000mc_reg_mobile_mode[] = { 139, 140, 141, 175, 1032 };
-
-static u16 dib3000mc_mobile_mode[][5] = {
-       { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* fixed */
-       { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* portable */
-       { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* mobile */
-       { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* auto */
-};
-
-#define DIB3000MC_REG_DIVERSITY1               (   177)
-#define DIB3000MC_DIVERSITY1_DEFAULT   (     1)
-
-#define DIB3000MC_REG_DIVERSITY2               (   178)
-#define DIB3000MC_DIVERSITY2_DEFAULT   (     1)
-
-#define DIB3000MC_REG_DIVERSITY3               (   180)
-#define DIB3000MC_DIVERSITY3_IN_OFF            (0xfff0)
-#define DIB3000MC_DIVERSITY3_IN_ON             (0xfff6)
-
-#define DIB3000MC_REG_FEC_CFG                  (   195)
-#define DIB3000MC_FEC_CFG                              (  0x10)
-
-/*
- * reg 206, output mode
- *              1111 1111
- *              |||| ||||
- *              |||| |||+- unk
- *              |||| ||+-- unk
- *              |||| |+--- unk (on by default)
- *              |||| +---- fifo_ctrl (1 = inhibit (flushed), 0 = active (unflushed))
- *              |||+------ pid_parse (1 = enabled, 0 = disabled)
- *              ||+------- outp_188  (1 = TS packet size 188, 0 = packet size 204)
- *              |+-------- unk
- *              +--------- unk
- */
-
-#define DIB3000MC_REG_SMO_MODE                 (   206)
-#define DIB3000MC_SMO_MODE_DEFAULT             (1 << 2)
-#define DIB3000MC_SMO_MODE_FIFO_FLUSH  (1 << 3)
-#define DIB3000MC_SMO_MODE_FIFO_UNFLUSH        (0xfff7)
-#define DIB3000MC_SMO_MODE_PID_PARSE   (1 << 4)
-#define DIB3000MC_SMO_MODE_NO_PID_PARSE        (0xffef)
-#define DIB3000MC_SMO_MODE_188                 (1 << 5)
-#define DIB3000MC_SMO_MODE_SLAVE               (DIB3000MC_SMO_MODE_DEFAULT | \
-                       DIB3000MC_SMO_MODE_188 | DIB3000MC_SMO_MODE_PID_PARSE | (1<<1))
-
-#define DIB3000MC_REG_FIFO_THRESHOLD   (   207)
-#define DIB3000MC_FIFO_THRESHOLD_DEFAULT       (  1792)
-#define DIB3000MC_FIFO_THRESHOLD_SLAVE (   512)
-/*
- * pidfilter
- * it is not a hardware pidfilter but a filter which drops all pids
- * except the ones set. When connected to USB1.1 bandwidth this is important.
- * DiB3000P/M-C can filter up to 32 PIDs
- */
-#define DIB3000MC_REG_FIRST_PID                        (   212)
-#define DIB3000MC_NUM_PIDS                             (    32)
-
-#define DIB3000MC_REG_OUTMODE                  (   244)
-#define DIB3000MC_OM_PARALLEL_GATED_CLK        (     0)
-#define DIB3000MC_OM_PAR_CONT_CLK              (1 << 11)
-#define DIB3000MC_OM_SERIAL                            (2 << 11)
-#define DIB3000MC_OM_DIVOUT_ON                 (4 << 11)
-#define DIB3000MC_OM_SLAVE                             (DIB3000MC_OM_DIVOUT_ON | DIB3000MC_OM_PAR_CONT_CLK)
-
-#define DIB3000MC_REG_RF_POWER                 (   392)
-
-#define DIB3000MC_REG_FFT_POSITION             (   407)
-
-#define DIB3000MC_REG_DDS_FREQ_MSB             (   414)
-#define DIB3000MC_REG_DDS_FREQ_LSB             (   415)
-
-#define DIB3000MC_REG_TIMING_OFFS_MSB  (   416)
-#define DIB3000MC_REG_TIMING_OFFS_LSB  (   417)
-
-#define DIB3000MC_REG_TUNING_PARM              (   458)
-#define DIB3000MC_TP_QAM(v)                            ((v >> 13) & 0x03)
-#define DIB3000MC_TP_HRCH(v)                   ((v >> 12) & 0x01)
-#define DIB3000MC_TP_ALPHA(v)                  ((v >> 9) & 0x07)
-#define DIB3000MC_TP_FFT(v)                            ((v >> 8) & 0x01)
-#define DIB3000MC_TP_FEC_CR_HP(v)              ((v >> 5) & 0x07)
-#define DIB3000MC_TP_FEC_CR_LP(v)              ((v >> 2) & 0x07)
-#define DIB3000MC_TP_GUARD(v)                  (v & 0x03)
-
-#define DIB3000MC_REG_SIGNAL_NOISE_MSB (   483)
-#define DIB3000MC_REG_SIGNAL_NOISE_LSB (   484)
-
-#define DIB3000MC_REG_MER                              (   485)
-
-#define DIB3000MC_REG_BER_MSB                  (   500)
-#define DIB3000MC_REG_BER_LSB                  (   501)
-
-#define DIB3000MC_REG_PACKET_ERRORS            (   503)
-
-#define DIB3000MC_REG_PACKET_ERROR_COUNT       (   506)
-
-#define DIB3000MC_REG_LOCK_507                 (   507)
-#define DIB3000MC_LOCK_507                             (0x0002) // ? name correct ?
-
-#define DIB3000MC_REG_LOCKING                  (   509)
-#define DIB3000MC_AGC_LOCK(v)                  (v & 0x8000)
-#define DIB3000MC_CARRIER_LOCK(v)              (v & 0x2000)
-#define DIB3000MC_MPEG_SYNC_LOCK(v)            (v & 0x0080)
-#define DIB3000MC_MPEG_DATA_LOCK(v)            (v & 0x0040)
-#define DIB3000MC_TPS_LOCK(v)                  (v & 0x0004)
-
-#define DIB3000MC_REG_AS_IRQ                   (   511)
-#define DIB3000MC_AS_IRQ_SUCCESS               (1 << 1)
-#define DIB3000MC_AS_IRQ_FAIL                  (     1)
-
-#define DIB3000MC_REG_TUNER                            (   769)
-
-#define DIB3000MC_REG_RST_I2C_ADDR             (  1024)
-#define DIB3000MC_DEMOD_ADDR_ON                        (     1)
-#define DIB3000MC_DEMOD_ADDR(a)                        ((a << 4) & 0x03F0)
-
-#define DIB3000MC_REG_RESTART                  (  1027)
-#define DIB3000MC_RESTART_OFF                  (0x0000)
-#define DIB3000MC_RESTART_AGC                  (0x0800)
-#define DIB3000MC_RESTART_CONFIG               (0x8000)
-
-#define DIB3000MC_REG_RESTART_VIT              (  1028)
-#define DIB3000MC_RESTART_VIT_OFF              (     0)
-#define DIB3000MC_RESTART_VIT_ON               (     1)
-
-#define DIB3000MC_REG_CLK_CFG_1                        (  1031)
-#define DIB3000MC_CLK_CFG_1_POWER_UP   (     0)
-#define DIB3000MC_CLK_CFG_1_POWER_DOWN (0xffff)
-
-#define DIB3000MC_REG_CLK_CFG_2                        (  1032)
-#define DIB3000MC_CLK_CFG_2_PUP_FIXED  (0x012c)
-#define DIB3000MC_CLK_CFG_2_PUP_PORT   (0x0104)
-#define DIB3000MC_CLK_CFG_2_PUP_MOBILE  (0x0000)
-#define DIB3000MC_CLK_CFG_2_POWER_DOWN (0xffff)
-
-#define DIB3000MC_REG_CLK_CFG_3                        (  1033)
-#define DIB3000MC_CLK_CFG_3_POWER_UP   (     0)
-#define DIB3000MC_CLK_CFG_3_POWER_DOWN (0xfff5)
-
-#define DIB3000MC_REG_CLK_CFG_7                        (  1037)
-#define DIB3000MC_CLK_CFG_7_INIT               ( 12592)
-#define DIB3000MC_CLK_CFG_7_POWER_UP   (~0x0003)
-#define DIB3000MC_CLK_CFG_7_PWR_DOWN   (0x0003)
-#define DIB3000MC_CLK_CFG_7_DIV_IN_OFF (1 << 8)
-
-/* was commented out ??? */
-#define DIB3000MC_REG_CLK_CFG_8                        (  1038)
-#define DIB3000MC_CLK_CFG_8_POWER_UP   (0x160c)
-
-#define DIB3000MC_REG_CLK_CFG_9                        (  1039)
-#define DIB3000MC_CLK_CFG_9_POWER_UP   (     0)
-
-/* also clock ??? */
-#define DIB3000MC_REG_ELEC_OUT                 (  1040)
-#define DIB3000MC_ELEC_OUT_HIGH_Z              (     0)
-#define DIB3000MC_ELEC_OUT_DIV_OUT_ON  (     1)
-#define DIB3000MC_ELEC_OUT_SLAVE               (     3)
-
-#endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
new file mode 100644 (file)
index 0000000..a18c8f4
--- /dev/null
@@ -0,0 +1,152 @@
+#include <linux/i2c.h>
+
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
+
+static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+{
+       u8 b[4] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg = {
+               .addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4
+       };
+       return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+
+static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf)
+{
+       if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
+               dprintk("selecting interface: %d\n",intf);
+               mst->selected_interface = intf;
+               return dibx000_write_word(mst, mst->base_reg + 4, intf);
+       }
+       return 0;
+}
+
+static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff)
+{
+       u16 val;
+
+
+       if (onoff)
+               val = addr << 8; // bit 7 = use master or not, if 0, the gate is open
+       else
+               val = 1 << 7;
+
+       if (mst->device_rev > DIB7000)
+               val <<= 1;
+
+       tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
+       tx[1] = ( (mst->base_reg + 1)       & 0xff);
+       tx[2] = val >> 8;
+       tx[3] = val & 0xff;
+
+       return 0;
+}
+
+static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+       struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+       struct i2c_msg m[2 + num];
+       u8 tx_open[4], tx_close[4];
+
+       memset(m,0, sizeof(struct i2c_msg) * (2 + num));
+
+       dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+
+       dibx000_i2c_gate_ctrl(mst, tx_open,  msg[0].addr, 1);
+       m[0].addr = mst->i2c_addr;
+       m[0].buf  = tx_open;
+       m[0].len  = 4;
+
+       memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+
+       dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
+       m[num+1].addr = mst->i2c_addr;
+       m[num+1].buf  = tx_close;
+       m[num+1].len  = 4;
+
+       return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO;
+}
+
+static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+       .master_xfer   = dibx000_i2c_gated_tuner_xfer,
+       .functionality = dibx000_i2c_func,
+};
+
+struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating)
+{
+       struct i2c_adapter *i2c = NULL;
+
+       switch (intf) {
+               case DIBX000_I2C_INTERFACE_TUNER:
+                       if (gating)
+                               i2c = &mst->gated_tuner_i2c_adap;
+                       break;
+               default:
+                       printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
+                       break;
+       }
+
+       return i2c;
+}
+EXPORT_SYMBOL(dibx000_get_i2c_adapter);
+
+static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst)
+{
+       strncpy(i2c_adap->name, name, I2C_NAME_SIZE);
+       i2c_adap->class     = I2C_CLASS_TV_DIGITAL,
+       i2c_adap->algo      = algo;
+       i2c_adap->algo_data = NULL;
+       i2c_set_adapdata(i2c_adap, mst);
+       if (i2c_add_adapter(i2c_adap) < 0)
+               return -ENODEV;
+       return 0;
+}
+
+int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr)
+{
+       u8 tx[4];
+       struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 };
+
+       mst->device_rev = device_rev;
+       mst->i2c_adap   = i2c_adap;
+       mst->i2c_addr   = i2c_addr >> 1;
+
+       if (device_rev == DIB7000P)
+               mst->base_reg = 1024;
+       else
+               mst->base_reg = 768;
+
+    if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0)
+               printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n");
+
+       /* initialize the i2c-master by closing the gate */
+       dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
+
+       return i2c_transfer(i2c_adap, &m, 1) == 1;
+}
+EXPORT_SYMBOL(dibx000_init_i2c_master);
+
+void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
+{
+       i2c_del_adapter(&mst->gated_tuner_i2c_adap);
+}
+EXPORT_SYMBOL(dibx000_exit_i2c_master);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
new file mode 100644 (file)
index 0000000..bb0c65f
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef DIBX000_COMMON_H
+#define DIBX000_COMMON_H
+
+enum dibx000_i2c_interface {
+       DIBX000_I2C_INTERFACE_TUNER    = 0,
+       DIBX000_I2C_INTERFACE_GPIO_1_2 = 1,
+       DIBX000_I2C_INTERFACE_GPIO_3_4 = 2
+};
+
+struct dibx000_i2c_master {
+#define DIB3000MC 1
+#define DIB7000   2
+#define DIB7000P  11
+#define DIB7000MC 12
+       u16 device_rev;
+
+       enum dibx000_i2c_interface selected_interface;
+
+//     struct i2c_adapter  tuner_i2c_adap;
+       struct i2c_adapter  gated_tuner_i2c_adap;
+
+       struct i2c_adapter *i2c_adap;
+       u8                  i2c_addr;
+
+       u16 base_reg;
+};
+
+extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr);
+extern struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating);
+extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
+
+#define BAND_LBAND 0x01
+#define BAND_UHF   0x02
+#define BAND_VHF   0x04
+
+struct dibx000_agc_config {
+       /* defines the capabilities of this AGC-setting - using the BAND_-defines*/
+       u8  band_caps;
+
+       u16 setup;
+
+       u16 inv_gain;
+       u16 time_stabiliz;
+
+       u8  alpha_level;
+       u16 thlock;
+
+       u8  wbd_inv;
+       u16 wbd_ref;
+       u8 wbd_sel;
+       u8 wbd_alpha;
+
+       u16 agc1_max;
+       u16 agc1_min;
+       u16 agc2_max;
+       u16 agc2_min;
+
+       u8 agc1_pt1;
+       u8 agc1_pt2;
+       u8 agc1_pt3;
+
+       u8 agc1_slope1;
+       u8 agc1_slope2;
+
+       u8 agc2_pt1;
+       u8 agc2_pt2;
+
+       u8 agc2_slope1;
+       u8 agc2_slope2;
+
+       u8 alpha_mant;
+       u8 alpha_exp;
+
+       u8 beta_mant;
+       u8 beta_exp;
+
+       u8 perform_agc_softsplit;
+
+       struct {
+               u16 min;
+               u16 max;
+               u16 min_thres;
+               u16 max_thres;
+       } split;
+};
+
+struct dibx000_bandwidth_config {
+       u32   internal;
+       u32   sampling;
+
+       u8 pll_prediv;
+       u8 pll_ratio;
+       u8 pll_range;
+       u8 pll_reset;
+       u8 pll_bypass;
+
+       u8 enable_refdiv;
+       u8 bypclk_div;
+       u8 IO_CLK_en_core;
+       u8 ADClkSrc;
+       u8 modulo;
+
+       u16 sad_cfg;
+
+       u32 ifreq;
+       u32 timf;
+};
+
+enum dibx000_adc_states {
+       DIBX000_SLOW_ADC_ON = 0,
+       DIBX000_SLOW_ADC_OFF,
+       DIBX000_ADC_ON,
+       DIBX000_ADC_OFF,
+       DIBX000_VBG_ENABLE,
+       DIBX000_VBG_DISABLE,
+};
+
+#define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ  ? 8000 : \
+                            (v) == BANDWIDTH_7_MHZ  ? 7000 : \
+                            (v) == BANDWIDTH_6_MHZ  ? 6000 : 8000 )
+
+/* Chip output mode. */
+#define OUTMODE_HIGH_Z                      0
+#define OUTMODE_MPEG2_PAR_GATED_CLK         1
+#define OUTMODE_MPEG2_PAR_CONT_CLK          2
+#define OUTMODE_MPEG2_SERIAL                7
+#define OUTMODE_DIVERSITY                   4
+#define OUTMODE_MPEG2_FIFO                  5
+
+/* I hope I can get rid of the following kludge in the near future */
+struct dibx000_ofdm_channel {
+       u8  Bw;
+       s16 nfft;
+       s16 guard;
+       s16 nqam;
+       s16 vit_hrch;
+       s16 vit_select_hp;
+       s16 vit_alpha;
+       s16 vit_code_rate_hp;
+       s16 vit_code_rate_lp;
+};
+
+#define FEP2DIB(fep,ch) \
+       (ch)->Bw               = (fep)->u.ofdm.bandwidth; \
+       (ch)->nfft             = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
+       (ch)->guard            = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
+       (ch)->nqam             = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \
+       (ch)->vit_hrch         = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \
+       (ch)->vit_select_hp    = 1; \
+       (ch)->vit_alpha        = 1; \
+       (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
+       (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP;
+
+#define INIT_OFDM_CHANNEL(ch) do {\
+       (ch)->Bw               = 0;  \
+       (ch)->nfft             = -1; \
+       (ch)->guard            = -1; \
+       (ch)->nqam             = -1; \
+       (ch)->vit_hrch         = -1; \
+       (ch)->vit_select_hp    = -1; \
+       (ch)->vit_alpha        = -1; \
+       (ch)->vit_code_rate_hp = -1; \
+       (ch)->vit_code_rate_lp = -1; \
+} while (0)
+
+#endif
index 2be33f27c69fbfb7944140220eb34df815f15034..b7e7108ee5b3cadd0e82c562a1264575a9e9a093 100644 (file)
@@ -493,6 +493,9 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
        int i;
        int result;
 
+       if (priv->i2c == NULL)
+               return -EINVAL;
+
        for (i = 0; i < priv->pll_desc->count; i++) {
                if (priv->pll_desc->entries[i].limit == 0)
                        break;
@@ -611,7 +614,7 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
        .get_bandwidth = dvb_pll_get_bandwidth,
 };
 
-int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
 {
        u8 b1 [] = { 0 };
        struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
@@ -624,14 +627,14 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
 
                ret = i2c_transfer (i2c, &msg, 1);
                if (ret != 1)
-                       return -1;
+                       return NULL;
                if (fe->ops.i2c_gate_ctrl)
                             fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
        if (priv == NULL)
-               return -ENOMEM;
+               return NULL;
 
        priv->pll_i2c_address = pll_addr;
        priv->i2c = i2c;
@@ -643,7 +646,7 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
        fe->ops.tuner_ops.info.frequency_min = desc->max;
 
        fe->tuner_priv = priv;
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(dvb_pll_attach);
 
index 66361cd188078c6361d84d255febce35d0685aa2..ed5ac5a361ae12da3c65a850f33bbe67f48f3f63 100644 (file)
@@ -57,8 +57,8 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
  * @param pll_addr i2c address of the PLL (if used).
  * @param i2c i2c adapter to use (set to NULL if not used).
  * @param desc dvb_pll_desc to use.
- * @return 0 on success, nonzero on failure.
+ * @return Frontend pointer on success, NULL on failure
  */
-extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
 
 #endif
index 58c34db31071e948d42049022150cc14a7e72fac..ef319369ec262e2fd9016e0fa9d4b1674b433424 100644 (file)
@@ -42,12 +42,11 @@ struct isl6421 {
        u8                      override_and;
        struct i2c_adapter      *i2c;
        u8                      i2c_addr;
-       void                    (*release_chain)(struct dvb_frontend* fe);
 };
 
 static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
                                .buf = &isl6421->config,
                                .len = sizeof(isl6421->config) };
@@ -75,7 +74,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
 
 static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 {
-       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
                                .buf = &isl6421->config,
                                .len = sizeof(isl6421->config) };
@@ -93,31 +92,26 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 
 static void isl6421_release(struct dvb_frontend *fe)
 {
-       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
-
        /* power off */
        isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
 
-       /* free data & call next release routine */
-       fe->ops.release = isl6421->release_chain;
-       kfree(fe->misc_priv);
-       fe->misc_priv = NULL;
-       if (fe->ops.release)
-               fe->ops.release(fe);
+       /* free */
+       kfree(fe->sec_priv);
+       fe->sec_priv = NULL;
 }
 
-int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                   u8 override_set, u8 override_clear)
 {
        struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
        if (!isl6421)
-               return -ENOMEM;
+               return NULL;
 
        /* default configuration */
        isl6421->config = ISL6421_ISEL1;
        isl6421->i2c = i2c;
        isl6421->i2c_addr = i2c_addr;
-       fe->misc_priv = isl6421;
+       fe->sec_priv = isl6421;
 
        /* bits which should be forced to '1' */
        isl6421->override_or = override_set;
@@ -128,19 +122,17 @@ int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr
        /* detect if it is present or not */
        if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
                kfree(isl6421);
-               fe->misc_priv = NULL;
-               return -EIO;
+               return NULL;
        }
 
        /* install release callback */
-       isl6421->release_chain = fe->ops.release;
-       fe->ops.release = isl6421_release;
+       fe->ops.release_sec = isl6421_release;
 
        /* override frontend ops */
        fe->ops.set_voltage = isl6421_set_voltage;
        fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
 
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(isl6421_attach);
 
index 675f80a19b9917ad694121856d4851daaa6878f6..1916e3eb2df39c30d07b5bc889e80e0c08cc7d70 100644 (file)
 #define ISL6421_ISEL1  0x20
 #define ISL6421_DCL    0x40
 
+#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
-extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                          u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+                                                 u8 override_set, u8 override_clear)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_ISL6421
 
 #endif
index 83b8bc21027404563875208b3e559d2037ef287a..21ba4a2307601067348e4a0d50d774927357c6cb 100644 (file)
@@ -31,8 +31,16 @@ struct l64781_config
        u8 demod_address;
 };
 
-
+#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE)
 extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
                                          struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+                                         struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_L64781
 
 #endif // L64781_H
index bad903c6f0f8261111a6b1d2b7dfe3bdbabb9325..3f96b485584c663ce68deac95b0e32970aa83689 100644 (file)
@@ -52,8 +52,17 @@ struct lgdt330x_config
        int clock_polarity_flip;
 };
 
+#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE)
 extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
                                            struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+                                           struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_LGDT330X
 
 #endif /* LGDT330X_H */
 
index e933edc8dd292499b78ef7746bde7202f94da2a0..2d2f58c26226527dd7ddadd5fd4e9ba634d388a4 100644 (file)
@@ -40,12 +40,11 @@ struct lnbp21 {
        u8                      override_or;
        u8                      override_and;
        struct i2c_adapter      *i2c;
-       void                    (*release_chain)(struct dvb_frontend* fe);
 };
 
 static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
                                .buf = &lnbp21->config,
                                .len = sizeof(lnbp21->config) };
@@ -73,7 +72,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 
 static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 {
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
                                .buf = &lnbp21->config,
                                .len = sizeof(lnbp21->config) };
@@ -91,29 +90,24 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 
 static void lnbp21_release(struct dvb_frontend *fe)
 {
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
        /* LNBP power off */
        lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
 
-       /* free data & call next release routine */
-       fe->ops.release = lnbp21->release_chain;
-       kfree(fe->misc_priv);
-       fe->misc_priv = NULL;
-       if (fe->ops.release)
-               fe->ops.release(fe);
+       /* free data */
+       kfree(fe->sec_priv);
+       fe->sec_priv = NULL;
 }
 
-int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
 {
        struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
        if (!lnbp21)
-               return -ENOMEM;
+               return NULL;
 
        /* default configuration */
        lnbp21->config = LNBP21_ISEL;
        lnbp21->i2c = i2c;
-       fe->misc_priv = lnbp21;
+       fe->sec_priv = lnbp21;
 
        /* bits which should be forced to '1' */
        lnbp21->override_or = override_set;
@@ -124,19 +118,17 @@ int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_
        /* detect if it is present or not */
        if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
                kfree(lnbp21);
-               fe->misc_priv = NULL;
-               return -EIO;
+               return NULL;
        }
 
        /* install release callback */
-       lnbp21->release_chain = fe->ops.release;
-       fe->ops.release = lnbp21_release;
+       fe->ops.release_sec = lnbp21_release;
 
        /* override frontend ops */
        fe->ops.set_voltage = lnbp21_set_voltage;
        fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
 
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(lnbp21_attach);
 
index 047a4ab68c01be0a0cc0c6579eff5f0c3ec149ad..1fe1dd1793123985b813fda65b992c332e4162cb 100644 (file)
 
 #include <linux/dvb/frontend.h>
 
+#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
-extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_LNBP21
 
-#endif
+#endif // _LNBP21_H
diff --git a/drivers/media/dvb/frontends/mt2060.c b/drivers/media/dvb/frontends/mt2060.c
new file mode 100644 (file)
index 0000000..508ec1b
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ *  Copyright (c) 2006 Olivier DANET <odanet@caramail.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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "mt2060.h"
+#include "mt2060_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
+
+// Reads a single register
+static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
+{
+       struct i2c_msg msg[2] = {
+               { .addr = priv->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
+               { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val,  .len = 1 },
+       };
+
+       if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+               printk(KERN_WARNING "mt2060 I2C read failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+// Writes a single register
+static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
+{
+       u8 buf[2] = { reg, val };
+       struct i2c_msg msg = {
+               .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
+       };
+
+       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "mt2060 I2C write failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+// Writes a set of consecutive registers
+static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
+{
+       struct i2c_msg msg = {
+               .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
+       };
+       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+// Initialisation sequences
+// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
+static u8 mt2060_config1[] = {
+       REG_LO1C1,
+       0x3F,   0x74,   0x00,   0x08,   0x93
+};
+
+// FMCG=2, GP2=0, GP1=0
+static u8 mt2060_config2[] = {
+       REG_MISC_CTRL,
+       0x20,   0x1E,   0x30,   0xff,   0x80,   0xff,   0x00,   0x2c,   0x42
+};
+
+//  VGAG=3, V1CSE=1
+
+#ifdef  MT2060_SPURCHECK
+/* The function below calculates the frequency offset between the output frequency if2
+ and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
+static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
+{
+       int I,J;
+       int dia,diamin,diff;
+       diamin=1000000;
+       for (I = 1; I < 10; I++) {
+               J = ((2*I*lo1)/lo2+1)/2;
+               diff = I*(int)lo1-J*(int)lo2;
+               if (diff < 0) diff=-diff;
+               dia = (diff-(int)if2);
+               if (dia < 0) dia=-dia;
+               if (diamin > dia) diamin=dia;
+       }
+       return diamin;
+}
+
+#define BANDWIDTH 4000 // kHz
+
+/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
+static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
+{
+       u32 Spur,Sp1,Sp2;
+       int I,J;
+       I=0;
+       J=1000;
+
+       Spur=mt2060_spurcalc(lo1,lo2,if2);
+       if (Spur < BANDWIDTH) {
+               /* Potential spurs detected */
+               dprintk("Spurs before : f_lo1: %d  f_lo2: %d  (kHz)",
+                       (int)lo1,(int)lo2);
+               I=1000;
+               Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
+               Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
+
+               if (Sp1 < Sp2) {
+                       J=-J; I=-I; Spur=Sp2;
+               } else
+                       Spur=Sp1;
+
+               while (Spur < BANDWIDTH) {
+                       I += J;
+                       Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
+               }
+               dprintk("Spurs after  : f_lo1: %d  f_lo2: %d  (kHz)",
+                       (int)(lo1+I),(int)(lo2+I));
+       }
+       return I;
+}
+#endif
+
+#define IF2  36150       // IF2 frequency = 36.150 MHz
+#define FREF 16000       // Quartz oscillator 16 MHz
+
+static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct mt2060_priv *priv;
+       int ret=0;
+       int i=0;
+       u32 freq;
+       u8  lnaband;
+       u32 f_lo1,f_lo2;
+       u32 div1,num1,div2,num2;
+       u8  b[8];
+       u32 if1;
+
+       priv = fe->tuner_priv;
+
+       if1 = priv->if1_freq;
+       b[0] = REG_LO1B1;
+       b[1] = 0xFF;
+
+       mt2060_writeregs(priv,b,2);
+
+       freq = params->frequency / 1000; // Hz -> kHz
+       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+
+       f_lo1 = freq + if1 * 1000;
+       f_lo1 = (f_lo1 / 250) * 250;
+       f_lo2 = f_lo1 - freq - IF2;
+       // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
+       f_lo2 = ((f_lo2 + 25) / 50) * 50;
+       priv->frequency =  (f_lo1 - f_lo2 - IF2) * 1000,
+
+#ifdef MT2060_SPURCHECK
+       // LO-related spurs detection and correction
+       num1   = mt2060_spurcheck(f_lo1,f_lo2,IF2);
+       f_lo1 += num1;
+       f_lo2 += num1;
+#endif
+       //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
+       num1 = f_lo1 / (FREF / 64);
+       div1 = num1 / 64;
+       num1 &= 0x3f;
+
+       // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
+       num2 = f_lo2 * 64 / (FREF / 128);
+       div2 = num2 / 8192;
+       num2 &= 0x1fff;
+
+       if (freq <=  95000) lnaband = 0xB0; else
+       if (freq <= 180000) lnaband = 0xA0; else
+       if (freq <= 260000) lnaband = 0x90; else
+       if (freq <= 335000) lnaband = 0x80; else
+       if (freq <= 425000) lnaband = 0x70; else
+       if (freq <= 480000) lnaband = 0x60; else
+       if (freq <= 570000) lnaband = 0x50; else
+       if (freq <= 645000) lnaband = 0x40; else
+       if (freq <= 730000) lnaband = 0x30; else
+       if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
+
+       b[0] = REG_LO1C1;
+       b[1] = lnaband | ((num1 >>2) & 0x0F);
+       b[2] = div1;
+       b[3] = (num2 & 0x0F)  | ((num1 & 3) << 4);
+       b[4] = num2 >> 4;
+       b[5] = ((num2 >>12) & 1) | (div2 << 1);
+
+       dprintk("IF1: %dMHz",(int)if1);
+       dprintk("PLL freq=%dkHz  f_lo1=%dkHz  f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
+       dprintk("PLL div1=%d  num1=%d  div2=%d  num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
+       dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
+
+       mt2060_writeregs(priv,b,6);
+
+       //Waits for pll lock or timeout
+       i = 0;
+       do {
+               mt2060_readreg(priv,REG_LO_STATUS,b);
+               if ((b[0] & 0x88)==0x88)
+                       break;
+               msleep(4);
+               i++;
+       } while (i<10);
+
+       return ret;
+}
+
+static void mt2060_calibrate(struct mt2060_priv *priv)
+{
+       u8 b = 0;
+       int i = 0;
+
+       if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
+               return;
+       if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
+               return;
+
+       do {
+               b |= (1 << 6); // FM1SS;
+               mt2060_writereg(priv, REG_LO2C1,b);
+               msleep(20);
+
+               if (i == 0) {
+                       b |= (1 << 7); // FM1CA;
+                       mt2060_writereg(priv, REG_LO2C1,b);
+                       b &= ~(1 << 7); // FM1CA;
+                       msleep(20);
+               }
+
+               b &= ~(1 << 6); // FM1SS
+               mt2060_writereg(priv, REG_LO2C1,b);
+
+               msleep(20);
+               i++;
+       } while (i < 9);
+
+       i = 0;
+       while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
+               msleep(20);
+
+       if (i < 10) {
+               mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
+               dprintk("calibration was successful: %d", (int)priv->fmfreq);
+       } else
+               dprintk("FMCAL timed out");
+}
+
+static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct mt2060_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct mt2060_priv *priv = fe->tuner_priv;
+       *bandwidth = priv->bandwidth;
+       return 0;
+}
+
+static int mt2060_init(struct dvb_frontend *fe)
+{
+       struct mt2060_priv *priv = fe->tuner_priv;
+       return mt2060_writereg(priv, REG_VGAG,0x33);
+}
+
+static int mt2060_sleep(struct dvb_frontend *fe)
+{
+       struct mt2060_priv *priv = fe->tuner_priv;
+       return mt2060_writereg(priv, REG_VGAG,0x30);
+}
+
+static int mt2060_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static const struct dvb_tuner_ops mt2060_tuner_ops = {
+       .info = {
+               .name           = "Microtune MT2060",
+               .frequency_min  =  48000000,
+               .frequency_max  = 860000000,
+               .frequency_step =     50000,
+       },
+
+       .release       = mt2060_release,
+
+       .init          = mt2060_init,
+       .sleep         = mt2060_sleep,
+
+       .set_params    = mt2060_set_params,
+       .get_frequency = mt2060_get_frequency,
+       .get_bandwidth = mt2060_get_bandwidth
+};
+
+/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
+int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
+{
+       struct mt2060_priv *priv = NULL;
+       u8 id = 0;
+
+       priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return -ENOMEM;
+
+       priv->cfg      = cfg;
+       priv->i2c      = i2c;
+       priv->if1_freq = if1;
+
+       if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
+               kfree(priv);
+               return -ENODEV;
+       }
+
+       if (id != PART_REV) {
+               kfree(priv);
+               return -ENODEV;
+       }
+       printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
+       memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+       fe->tuner_priv = priv;
+
+       mt2060_calibrate(priv);
+
+       return 0;
+}
+EXPORT_SYMBOL(mt2060_attach);
+
+MODULE_AUTHOR("Olivier DANET");
+MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h
new file mode 100644 (file)
index 0000000..c58b03e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ *  Copyright (c) 2006 Olivier DANET <odanet@caramail.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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef MT2060_H
+#define MT2060_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct mt2060_config {
+       u8 i2c_address;
+       /* Shall we add settings for the discrete outputs ? */
+};
+
+extern int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
+
+#endif
diff --git a/drivers/media/dvb/frontends/mt2060_priv.h b/drivers/media/dvb/frontends/mt2060_priv.h
new file mode 100644 (file)
index 0000000..5eaccde
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ *  Copyright (c) 2006 Olivier DANET <odanet@caramail.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., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef MT2060_PRIV_H
+#define MT2060_PRIV_H
+
+// Uncomment the #define below to enable spurs checking. The results where quite unconvincing.
+// #define MT2060_SPURCHECK
+
+/* This driver is based on the information available in the datasheet of the
+   "Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map :
+
+   I2C Address : 0x60
+
+   Reg.No |   B7   |   B6   |   B5   |   B4   |   B3   |   B2   |   B1   |   B0   | ( defaults )
+   --------------------------------------------------------------------------------
+       00 | [              PART             ] | [              REV              ] | R  = 0x63
+       01 | [             LNABAND           ] | [              NUM1(5:2)        ] | RW = 0x3F
+       02 | [                               DIV1                                ] | RW = 0x74
+       03 | FM1CA  | FM1SS  | [  NUM1(1:0)  ] | [              NUM2(3:0)        ] | RW = 0x00
+       04 |                                 NUM2(11:4)                          ] | RW = 0x08
+       05 | [                               DIV2                       ] |NUM2(12)| RW = 0x93
+       06 | L1LK   | [        TAD1          ] | L2LK   | [         TAD2         ] | R
+       07 | [                               FMF                                 ] | R
+       08 |   ?    | FMCAL  |   ?    |   ?    |   ?    |   ?    |   ?    | TEMP   | R
+       09 |   0    |   0    | [    FMGC     ] |   0    | GP02   | GP01   |   0    | RW = 0x20
+       0A | ??
+       0B |   0    |   0    |   1    |   1    |   0    |   0    | [   VGAG      ] | RW = 0x30
+       0C | V1CSE  |   1    |   1    |   1    |   1    |   1    |   1    |   1    | RW = 0xFF
+       0D |   1    |   0    | [                      V1CS                       ] | RW = 0xB0
+       0E | ??
+       0F | ??
+       10 | ??
+       11 | [             LOTO              ] |   0    |   0    |   1    |   0    | RW = 0x42
+
+       PART    : Part code      : 6 for MT2060
+       REV     : Revision code  : 3 for current revision
+       LNABAND : Input frequency range : ( See code for details )
+       NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details )
+       FM1CA  : Calibration Start Bit
+       FM1SS  : Calibration Single Step bit
+       L1LK   : LO1 Lock Detect
+       TAD1   : Tune Line ADC ( ? )
+       L2LK   : LO2 Lock Detect
+       TAD2   : Tune Line ADC ( ? )
+       FMF    : Estimated first IF Center frequency Offset ( ? )
+       FM1CAL : Calibration done bit
+       TEMP   : On chip temperature sensor
+       FMCG   : Mixer 1 Cap Gain ( ? )
+       GP01 / GP02 : Programmable digital outputs. Unconnected pins ?
+       V1CSE  : LO1 VCO Automatic Capacitor Select Enable ( ? )
+       V1CS   : LO1 Capacitor Selection Value ( ? )
+       LOTO   : LO Timeout ( ? )
+       VGAG   : Tuner Output gain
+*/
+
+#define I2C_ADDRESS 0x60
+
+#define REG_PART_REV   0
+#define REG_LO1C1      1
+#define REG_LO1C2      2
+#define REG_LO2C1      3
+#define REG_LO2C2      4
+#define REG_LO2C3      5
+#define REG_LO_STATUS  6
+#define REG_FM_FREQ    7
+#define REG_MISC_STAT  8
+#define REG_MISC_CTRL  9
+#define REG_RESERVED_A 0x0A
+#define REG_VGAG       0x0B
+#define REG_LO1B1      0x0C
+#define REG_LO1B2      0x0D
+#define REG_LOTO       0x11
+
+#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips
+
+struct mt2060_priv {
+       struct mt2060_config *cfg;
+       struct i2c_adapter   *i2c;
+
+       u32 frequency;
+       u32 bandwidth;
+       u16 if1_freq;
+       u8  fmfreq;
+};
+
+#endif
index 666a1bd1c244ff0752c9b79a64d5abb08c5f7d07..7112fb4d58acb3a59db6c8313b9b83f309b71750 100644 (file)
@@ -34,8 +34,16 @@ struct mt312_config
        u8 demod_address;
 };
 
+#if defined(CONFIG_DVB_MT312) || defined(CONFIG_DVB_MT312_MODULE)
 struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
                                        struct i2c_adapter* i2c);
-
+#else
+static inline struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+                                       struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_MT312
 
 #endif // MT312_H
index 5de7376c94ce13e9501b1cda912c17a09be738e6..87e31ca7e1084e9d7916468eb9038e0dae6d71a5 100644 (file)
@@ -70,7 +70,7 @@ static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
        return 0;
 }
 
-int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
+static int _mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
 {
        int err,i;
        for (i=0; i < ilen-1; i++)
@@ -107,7 +107,7 @@ static int mt352_sleep(struct dvb_frontend* fe)
 {
        static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
 
-       mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
+       _mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
        return 0;
 }
 
@@ -293,14 +293,14 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
                                fe->ops.i2c_gate_ctrl(fe, 0);
                }
 
-               mt352_write(fe, buf, 8);
-               mt352_write(fe, fsm_go, 2);
+               _mt352_write(fe, buf, 8);
+               _mt352_write(fe, fsm_go, 2);
        } else {
                if (fe->ops.tuner_ops.calc_regs) {
                        fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
                        buf[8] <<= 1;
-                       mt352_write(fe, buf, sizeof(buf));
-                       mt352_write(fe, tuner_go, 2);
+                       _mt352_write(fe, buf, sizeof(buf));
+                       _mt352_write(fe, tuner_go, 2);
                }
        }
 
@@ -522,7 +522,7 @@ static int mt352_init(struct dvb_frontend* fe)
            (mt352_read_register(state, CONFIG) & 0x20) == 0) {
 
                /* Do a "hard" reset */
-               mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
+               _mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
                return state->config.demod_init(fe);
        }
 
@@ -585,6 +585,7 @@ static struct dvb_frontend_ops mt352_ops = {
 
        .init = mt352_init,
        .sleep = mt352_sleep,
+       .write = _mt352_write,
 
        .set_frontend = mt352_set_parameters,
        .get_frontend = mt352_get_parameters,
@@ -605,4 +606,3 @@ MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(mt352_attach);
-EXPORT_SYMBOL(mt352_write);
index 9e7ff4b8fe5f30156dabb28c4f46408328fe1169..0035c2e2d7c275ee8eb937304535ce643f2e8454 100644 (file)
@@ -51,9 +51,23 @@ struct mt352_config
        int (*demod_init)(struct dvb_frontend* fe);
 };
 
+#if defined(CONFIG_DVB_MT352) || defined(CONFIG_DVB_MT352_MODULE)
 extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
                                         struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+                                        struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_MT352
 
-extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
+static inline int mt352_write(struct dvb_frontend *fe, u8 *buf, int len) {
+       int r = 0;
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, len);
+       return r;
+}
 
 #endif // MT352_H
index 34d61735845be8199d3d75e3c89614250b8f57aa..2eb220e9806257e09352b3349509a520456cccf0 100644 (file)
@@ -45,8 +45,17 @@ struct nxt200x_config
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
 };
 
+#if defined(CONFIG_DVB_NXT200X) || defined(CONFIG_DVB_NXT200X_MODULE)
 extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_NXT200X
 
 #endif /* NXT200X_H */
 
index 117031d117082009c1fab69377059f29110f7a5a..9397393a6bd10ab63426d058af78b7eaa8cd1463 100644 (file)
@@ -33,7 +33,16 @@ struct nxt6000_config
        u8 clock_inversion:1;
 };
 
+#if defined(CONFIG_DVB_NXT6000) || defined(CONFIG_DVB_NXT6000_MODULE)
 extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_NXT6000
 
 #endif // NXT6000_H
index 89658883abf5eb65a241b9b8f14bd024f8a9738d..9718be4fb8358ba33e436a7ea8d2edc9da2606b5 100644 (file)
@@ -34,8 +34,17 @@ struct or51132_config
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
 };
 
+#if defined(CONFIG_DVB_OR51132) || defined(CONFIG_DVB_OR51132_MODULE)
 extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_OR51132
 
 #endif // OR51132_H
 
index 13a5a3afbf8b1e8fe8f184a3448ec82f370420f7..10a5419f9e0041c3e3cbc74a94ce66153579696c 100644 (file)
@@ -37,8 +37,17 @@ struct or51211_config
        void (*sleep)(struct dvb_frontend * fe);
 };
 
+#if defined(CONFIG_DVB_OR51211) || defined(CONFIG_DVB_OR51211_MODULE)
 extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_OR51211
 
 #endif // OR51211_H
 
index 4e39015fa67e38c17bf519e8f6b143ff81a2fb3f..efc54d7f3c5569681c68af061e95771cbcefbf0b 100644 (file)
@@ -34,7 +34,16 @@ struct s5h1420_config
        u8 invert:1;
 };
 
+#if defined(CONFIG_DVB_S5H1420) || defined(CONFIG_DVB_S5H1420_MODULE)
 extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
             struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_S5H1420
 
 #endif // S5H1420_H
index 93afbb969d6b57f7b54cc104fe575fc5ce4641f4..4cf27d3b10f2ef8d520d717b0a24236e9a7201a5 100644 (file)
@@ -35,7 +35,16 @@ struct sp8870_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
+#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
 extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
                                          struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+                                         struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_SP8870
 
 #endif // SP8870_H
index c44b0ebdf1e220e32dd2c10a469e106ba1401c9f..cab7ea644dfa485b4da728554379383cfd44cf4c 100644 (file)
@@ -17,7 +17,16 @@ struct sp887x_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
+#if defined(CONFIG_DVB_SP887X) || defined(CONFIG_DVB_SP887X_MODULE)
 extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
                                          struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+                                         struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_SP887X
 
 #endif // SP887X_H
index 1da5384fb985454b06f6aa8b027dba583853338d..760b80db43a57080ea66a92caf5c1cefccadd6c2 100644 (file)
@@ -42,7 +42,16 @@ struct stv0297_config
        u8 stop_during_read:1;
 };
 
+#if defined(CONFIG_DVB_STV0297) || defined(CONFIG_DVB_STV0297_MODULE)
 extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_STV0297
 
 #endif // STV0297_H
index 96648a75440dc9f7972bb27a1f113faec024d7b3..93483769eca842bfabfcbd83c029fd7b1c3f4599 100644 (file)
@@ -92,11 +92,14 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
-int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data)
+int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct stv0299_state* state = fe->demodulator_priv;
 
-       return stv0299_writeregI(state, reg, data);
+       if (len != 2)
+               return -EINVAL;
+
+       return stv0299_writeregI(state, buf[0], buf[1]);
 }
 
 static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
@@ -694,6 +697,7 @@ static struct dvb_frontend_ops stv0299_ops = {
 
        .init = stv0299_init,
        .sleep = stv0299_sleep,
+       .write = stv0299_write,
        .i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
 
        .set_frontend = stv0299_set_frontend,
@@ -724,5 +728,4 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
              "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(stv0299_writereg);
 EXPORT_SYMBOL(stv0299_attach);
index 1504828e423246faf41c4c5f09a9b864344af627..7ef25207081d2ee46b2b2f128ef3ea99c33b0fb1 100644 (file)
@@ -89,9 +89,24 @@ struct stv0299_config
        int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
 };
 
-extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
-
+#if defined(CONFIG_DVB_STV0299) || defined(CONFIG_DVB_STV0299_MODULE)
 extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_STV0299
+
+static inline int stv0299_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+       int r = 0;
+       u8 buf[] = {reg, val};
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 2);
+       return r;
+}
 
 #endif // STV0299_H
index 9cbd164aa281dead63829e13503bbef9fd39ebe8..dca89171be1fe232239cd5a143b8b4c855054fa6 100644 (file)
@@ -72,7 +72,7 @@ static u8 tda10021_inittab[0x40]=
        0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
 };
 
-static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
+static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
 {
        u8 buf[] = { reg, data };
        struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
@@ -88,14 +88,6 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
-int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
-{
-       struct tda10021_state* state = fe->demodulator_priv;
-
-       return tda10021_writereg(state, reg, data);
-}
-EXPORT_SYMBOL(tda10021_write_byte);
-
 static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
 {
        u8 b0 [] = { reg };
@@ -149,8 +141,8 @@ static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
        else if (INVERSION_OFF == inversion)
                DISABLE_INVERSION(reg0);
 
-       tda10021_writereg (state, 0x00, reg0 & 0xfe);
-       tda10021_writereg (state, 0x00, reg0 | 0x01);
+       _tda10021_writereg (state, 0x00, reg0 & 0xfe);
+       _tda10021_writereg (state, 0x00, reg0 | 0x01);
 
        state->reg0 = reg0;
        return 0;
@@ -198,17 +190,27 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
 
        NDEC = (NDEC << 6) | tda10021_inittab[0x03];
 
-       tda10021_writereg (state, 0x03, NDEC);
-       tda10021_writereg (state, 0x0a, BDR&0xff);
-       tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
-       tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
+       _tda10021_writereg (state, 0x03, NDEC);
+       _tda10021_writereg (state, 0x0a, BDR&0xff);
+       _tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
+       _tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
 
-       tda10021_writereg (state, 0x0d, BDRI);
-       tda10021_writereg (state, 0x0e, SFIL);
+       _tda10021_writereg (state, 0x0d, BDRI);
+       _tda10021_writereg (state, 0x0e, SFIL);
 
        return 0;
 }
 
+int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
+{
+       struct tda10021_state* state = fe->demodulator_priv;
+
+       if (len != 2)
+               return -EINVAL;
+
+       return _tda10021_writereg(state, buf[0], buf[1]);
+}
+
 static int tda10021_init (struct dvb_frontend *fe)
 {
        struct tda10021_state* state = fe->demodulator_priv;
@@ -216,12 +218,12 @@ static int tda10021_init (struct dvb_frontend *fe)
 
        dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
 
-       //tda10021_writereg (fe, 0, 0);
+       //_tda10021_writereg (fe, 0, 0);
 
        for (i=0; i<tda10021_inittab_size; i++)
-               tda10021_writereg (state, i, tda10021_inittab[i]);
+               _tda10021_writereg (state, i, tda10021_inittab[i]);
 
-       tda10021_writereg (state, 0x34, state->pwm);
+       _tda10021_writereg (state, 0x34, state->pwm);
 
        //Comment by markus
        //0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
@@ -230,7 +232,7 @@ static int tda10021_init (struct dvb_frontend *fe)
        //0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
 
        //Activate PLL
-       tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
+       _tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
        return 0;
 }
 
@@ -264,12 +266,12 @@ static int tda10021_set_parameters (struct dvb_frontend *fe,
        }
 
        tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
-       tda10021_writereg (state, 0x34, state->pwm);
+       _tda10021_writereg (state, 0x34, state->pwm);
 
-       tda10021_writereg (state, 0x01, reg0x01[qam]);
-       tda10021_writereg (state, 0x05, reg0x05[qam]);
-       tda10021_writereg (state, 0x08, reg0x08[qam]);
-       tda10021_writereg (state, 0x09, reg0x09[qam]);
+       _tda10021_writereg (state, 0x01, reg0x01[qam]);
+       _tda10021_writereg (state, 0x05, reg0x05[qam]);
+       _tda10021_writereg (state, 0x08, reg0x08[qam]);
+       _tda10021_writereg (state, 0x09, reg0x09[qam]);
 
        tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
 
@@ -342,8 +344,8 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
                *ucblocks = 0xffffffff;
 
        /* reset uncorrected block counter */
-       tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
-       tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
+       _tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
+       _tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
 
        return 0;
 }
@@ -392,8 +394,8 @@ static int tda10021_sleep(struct dvb_frontend* fe)
 {
        struct tda10021_state* state = fe->demodulator_priv;
 
-       tda10021_writereg (state, 0x1b, 0x02);  /* pdown ADC */
-       tda10021_writereg (state, 0x00, 0x80);  /* standby */
+       _tda10021_writereg (state, 0x1b, 0x02);  /* pdown ADC */
+       _tda10021_writereg (state, 0x00, 0x80);  /* standby */
 
        return 0;
 }
@@ -459,6 +461,7 @@ static struct dvb_frontend_ops tda10021_ops = {
 
        .init = tda10021_init,
        .sleep = tda10021_sleep,
+       .write = tda10021_write,
        .i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
 
        .set_frontend = tda10021_set_parameters,
index b1df4259bee9f4d7c16a0030d34f04e062517dcf..d68ae20c84129c92a6b17b6b37b58612cd420d17 100644 (file)
@@ -32,9 +32,24 @@ struct tda10021_config
        u8 demod_address;
 };
 
+#if defined(CONFIG_DVB_TDA10021) || defined(CONFIG_DVB_TDA10021_MODULE)
 extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
                                            struct i2c_adapter* i2c, u8 pwm);
-
-extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
+#else
+static inline struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
+                                           struct i2c_adapter* i2c, u8 pwm)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_TDA10021
+
+static inline int tda10021_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+       int r = 0;
+       u8 buf[] = {reg, val};
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 2);
+       return r;
+}
 
 #endif // TDA10021_H
index 59a2ed614fca4046d4bd2474851f5f2552ac55c3..11e0dca9a2d7307de9e1a6648eedd4311844f9f1 100644 (file)
@@ -579,11 +579,14 @@ static int tda1004x_decode_fec(int tdafec)
        return -1;
 }
 
-int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data)
+int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
-       return tda1004x_write_byteI(state, reg, data);
+       if (len != 2)
+               return -EINVAL;
+
+       return tda1004x_write_byteI(state, buf[0], buf[1]);
 }
 
 static int tda10045_init(struct dvb_frontend* fe)
@@ -1216,6 +1219,7 @@ static struct dvb_frontend_ops tda10045_ops = {
 
        .init = tda10045_init,
        .sleep = tda1004x_sleep,
+       .write = tda1004x_write,
        .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
 
        .set_frontend = tda1004x_set_fe,
@@ -1274,6 +1278,7 @@ static struct dvb_frontend_ops tda10046_ops = {
 
        .init = tda10046_init,
        .sleep = tda1004x_sleep,
+       .write = tda1004x_write,
        .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
 
        .set_frontend = tda1004x_set_fe,
@@ -1323,4 +1328,3 @@ MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(tda10045_attach);
 EXPORT_SYMBOL(tda10046_attach);
-EXPORT_SYMBOL(tda1004x_write_byte);
index b877b23ed734e07398f2ac9d2ee5d2ef58508fc0..e28fca05734c30f9001549dce908e249442140fb 100644 (file)
@@ -71,12 +71,33 @@ struct tda1004x_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
+#if defined(CONFIG_DVB_TDA1004X) || defined(CONFIG_DVB_TDA1004X_MODULE)
 extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c);
 
 extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c);
-
-extern int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data);
+#else
+static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+                                           struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+                                           struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_TDA1004X
+
+static inline int tda1004x_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+       int r = 0;
+       u8 buf[] = {reg, val};
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 2);
+       return r;
+}
 
 #endif // TDA1004X_H
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
new file mode 100644 (file)
index 0000000..7456b0b
--- /dev/null
@@ -0,0 +1,740 @@
+  /*
+     Driver for Philips tda10086 DVBS Demodulator
+
+     (c) 2006 Andrew de Quincey
+
+     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/moduleparam.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "tda10086.h"
+
+#define SACLK 96000000
+
+struct tda10086_state {
+       struct i2c_adapter* i2c;
+       const struct tda10086_config* config;
+       struct dvb_frontend frontend;
+
+       /* private demod data */
+       u32 frequency;
+       u32 symbol_rate;
+};
+
+static int debug = 0;
+#define dprintk(args...) \
+       do { \
+               if (debug) printk(KERN_DEBUG "tda10086: " args); \
+       } while (0)
+
+static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
+{
+       int ret;
+       u8 b0[] = { reg, data };
+       struct i2c_msg msg = { .flags = 0, .buf = b0, .len = 2 };
+
+       msg.addr = state->config->demod_address;
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+                       __FUNCTION__, reg, data, ret);
+
+       return (ret != 1) ? ret : 0;
+}
+
+static int tda10086_read_byte(struct tda10086_state *state, int reg)
+{
+       int ret;
+       u8 b0[] = { reg };
+       u8 b1[] = { 0 };
+       struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+                               { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
+
+       msg[0].addr = state->config->demod_address;
+       msg[1].addr = state->config->demod_address;
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2) {
+               dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+                       ret);
+               return ret;
+       }
+
+       return b1[0];
+}
+
+static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, int data)
+{
+       int val;
+
+       // read a byte and check
+       val = tda10086_read_byte(state, reg);
+       if (val < 0)
+               return val;
+
+       // mask if off
+       val = val & ~mask;
+       val |= data & 0xff;
+
+       // write it out again
+       return tda10086_write_byte(state, reg, val);
+}
+
+static int tda10086_init(struct dvb_frontend* fe)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       // reset
+       tda10086_write_byte(state, 0x00, 0x00);
+       msleep(10);
+
+       // misc setup
+       tda10086_write_byte(state, 0x01, 0x94);
+       tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
+       tda10086_write_byte(state, 0x03, 0x64);
+       tda10086_write_byte(state, 0x04, 0x43);
+       tda10086_write_byte(state, 0x0c, 0x0c);
+       tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
+       tda10086_write_byte(state, 0x20, 0x89); // misc
+       tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
+       tda10086_write_byte(state, 0x32, 0x00); // irq off
+       tda10086_write_byte(state, 0x31, 0x56); // setup AFC
+
+       // setup PLL (assumes 16Mhz XIN)
+       tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
+       tda10086_write_byte(state, 0x3a, 0x0b); // M=12
+       tda10086_write_byte(state, 0x3b, 0x01); // P=2
+       tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
+
+       // setup TS interface
+       tda10086_write_byte(state, 0x11, 0x81);
+       tda10086_write_byte(state, 0x12, 0x81);
+       tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
+       tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
+       tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
+       tda10086_write_byte(state, 0x10, 0x2a);
+
+       // setup ADC
+       tda10086_write_byte(state, 0x58, 0x61); // ADC setup
+       tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
+
+       // setup AGC
+       tda10086_write_byte(state, 0x05, 0x0B);
+       tda10086_write_byte(state, 0x37, 0x63);
+       tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it
+       tda10086_write_byte(state, 0x40, 0x64);
+       tda10086_write_byte(state, 0x41, 0x4f);
+       tda10086_write_byte(state, 0x42, 0x43);
+
+       // setup viterbi
+       tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
+
+       // setup carrier recovery
+       tda10086_write_byte(state, 0x3d, 0x80);
+
+       // setup SEC
+       tda10086_write_byte(state, 0x36, 0x00); // all SEC off
+       tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));      // } tone frequency
+       tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
+
+       return 0;
+}
+
+static void tda10086_diseqc_wait(struct tda10086_state *state)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(200);
+       while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
+               if(time_after(jiffies, timeout)) {
+                       printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+                       break;
+               }
+               msleep(10);
+       }
+}
+
+static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       switch(tone) {
+       case SEC_TONE_OFF:
+               tda10086_write_byte(state, 0x36, 0x00);
+               break;
+
+       case SEC_TONE_ON:
+               tda10086_write_byte(state, 0x36, 0x01);
+               break;
+       }
+
+       return 0;
+}
+
+static int tda10086_send_master_cmd (struct dvb_frontend* fe,
+                                   struct dvb_diseqc_master_cmd* cmd)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+       int i;
+       u8 oldval;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       if (cmd->msg_len > 6)
+               return -EINVAL;
+       oldval = tda10086_read_byte(state, 0x36);
+
+       for(i=0; i< cmd->msg_len; i++) {
+               tda10086_write_byte(state, 0x48+i, cmd->msg[i]);
+       }
+       tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len + 1) << 4));
+
+       tda10086_diseqc_wait(state);
+
+       tda10086_write_byte(state, 0x36, oldval);
+
+       return 0;
+}
+
+static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+       u8 oldval = tda10086_read_byte(state, 0x36);
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       switch(minicmd) {
+       case SEC_MINI_A:
+               tda10086_write_byte(state, 0x36, 0x04);
+               break;
+
+       case SEC_MINI_B:
+               tda10086_write_byte(state, 0x36, 0x06);
+               break;
+       }
+
+       tda10086_diseqc_wait(state);
+
+       tda10086_write_byte(state, 0x36, oldval);
+
+       return 0;
+}
+
+static int tda10086_set_inversion(struct tda10086_state *state,
+                                 struct dvb_frontend_parameters *fe_params)
+{
+       u8 invval = 0x80;
+
+       dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
+
+       switch(fe_params->inversion) {
+       case INVERSION_OFF:
+               if (state->config->invert)
+                       invval = 0x40;
+               break;
+       case INVERSION_ON:
+               if (!state->config->invert)
+                       invval = 0x40;
+               break;
+       case INVERSION_AUTO:
+               invval = 0x00;
+               break;
+       }
+       tda10086_write_mask(state, 0x0c, 0xc0, invval);
+
+       return 0;
+}
+
+static int tda10086_set_symbol_rate(struct tda10086_state *state,
+                                   struct dvb_frontend_parameters *fe_params)
+{
+       u8 dfn = 0;
+       u8 afs = 0;
+       u8 byp = 0;
+       u8 reg37 = 0x43;
+       u8 reg42 = 0x43;
+       u64 big;
+       u32 tmp;
+       u32 bdr;
+       u32 bdri;
+       u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
+
+       dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
+
+       // setup the decimation and anti-aliasing filters..
+       if (symbol_rate < (u32) (SACLK * 0.0137)) {
+               dfn=4;
+               afs=1;
+       } else if (symbol_rate < (u32) (SACLK * 0.0208)) {
+               dfn=4;
+               afs=0;
+       } else if (symbol_rate < (u32) (SACLK * 0.0270)) {
+               dfn=3;
+               afs=1;
+       } else if (symbol_rate < (u32) (SACLK * 0.0416)) {
+               dfn=3;
+               afs=0;
+       } else if (symbol_rate < (u32) (SACLK * 0.0550)) {
+               dfn=2;
+               afs=1;
+       } else if (symbol_rate < (u32) (SACLK * 0.0833)) {
+               dfn=2;
+               afs=0;
+       } else if (symbol_rate < (u32) (SACLK * 0.1100)) {
+               dfn=1;
+               afs=1;
+       } else if (symbol_rate < (u32) (SACLK * 0.1666)) {
+               dfn=1;
+               afs=0;
+       } else if (symbol_rate < (u32) (SACLK * 0.2200)) {
+               dfn=0;
+               afs=1;
+       } else if (symbol_rate < (u32) (SACLK * 0.3333)) {
+               dfn=0;
+               afs=0;
+       } else {
+               reg37 = 0x63;
+               reg42 = 0x4f;
+               byp=1;
+       }
+
+       // calculate BDR
+       big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
+       big += ((SACLK/1000ULL)-1ULL);
+       do_div(big, (SACLK/1000ULL));
+       bdr = big & 0xfffff;
+
+       // calculate BDRI
+       tmp = (1<<dfn)*(symbol_rate/1000);
+       bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
+
+       tda10086_write_byte(state, 0x21, (afs << 7) | dfn);
+       tda10086_write_mask(state, 0x20, 0x08, byp << 3);
+       tda10086_write_byte(state, 0x06, bdr);
+       tda10086_write_byte(state, 0x07, bdr >> 8);
+       tda10086_write_byte(state, 0x08, bdr >> 16);
+       tda10086_write_byte(state, 0x09, bdri);
+       tda10086_write_byte(state, 0x37, reg37);
+       tda10086_write_byte(state, 0x42, reg42);
+
+       return 0;
+}
+
+static int tda10086_set_fec(struct tda10086_state *state,
+                           struct dvb_frontend_parameters *fe_params)
+{
+       u8 fecval;
+
+       dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
+
+       switch(fe_params->u.qpsk.fec_inner) {
+       case FEC_1_2:
+               fecval = 0x00;
+               break;
+       case FEC_2_3:
+               fecval = 0x01;
+               break;
+       case FEC_3_4:
+               fecval = 0x02;
+               break;
+       case FEC_4_5:
+               fecval = 0x03;
+               break;
+       case FEC_5_6:
+               fecval = 0x04;
+               break;
+       case FEC_6_7:
+               fecval = 0x05;
+               break;
+       case FEC_7_8:
+               fecval = 0x06;
+               break;
+       case FEC_8_9:
+               fecval = 0x07;
+               break;
+       case FEC_AUTO:
+               fecval = 0x08;
+               break;
+       default:
+               return -1;
+       }
+       tda10086_write_byte(state, 0x0d, fecval);
+
+       return 0;
+}
+
+static int tda10086_set_frontend(struct dvb_frontend* fe,
+                                struct dvb_frontend_parameters *fe_params)
+{
+       struct tda10086_state *state = fe->demodulator_priv;
+       int ret;
+       u32 freq = 0;
+       int freqoff;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       // set params
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, fe_params);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+
+               if (fe->ops.tuner_ops.get_frequency)
+                       fe->ops.tuner_ops.get_frequency(fe, &freq);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       // calcluate the frequency offset (in *Hz* not kHz)
+       freqoff = fe_params->frequency - freq;
+       freqoff = ((1<<16) * freqoff) / (SACLK/1000);
+       tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
+       tda10086_write_byte(state, 0x3e, freqoff);
+
+       if ((ret = tda10086_set_inversion(state, fe_params)) < 0)
+               return ret;
+       if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0)
+               return ret;
+       if ((ret = tda10086_set_fec(state, fe_params)) < 0)
+               return ret;
+
+       // soft reset + disable TS output until lock
+       tda10086_write_mask(state, 0x10, 0x40, 0x40);
+       tda10086_write_mask(state, 0x00, 0x01, 0x00);
+
+       state->symbol_rate = fe_params->u.qpsk.symbol_rate;
+       state->frequency = fe_params->frequency;
+       return 0;
+}
+
+static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+       u8 val;
+       int tmp;
+       u64 tmp64;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       // calculate the updated frequency (note: we convert from Hz->kHz)
+       tmp64 = tda10086_read_byte(state, 0x52);
+       tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
+       if (tmp64 & 0x8000)
+               tmp64 |= 0xffffffffffff0000ULL;
+       tmp64 = (tmp64 * (SACLK/1000ULL));
+       do_div(tmp64, (1ULL<<15) * (1ULL<<1));
+       fe_params->frequency = (int) state->frequency + (int) tmp64;
+
+       // the inversion
+       val = tda10086_read_byte(state, 0x0c);
+       if (val & 0x80) {
+               switch(val & 0x40) {
+               case 0x00:
+                       fe_params->inversion = INVERSION_OFF;
+                       if (state->config->invert)
+                               fe_params->inversion = INVERSION_ON;
+                       break;
+               default:
+                       fe_params->inversion = INVERSION_ON;
+                       if (state->config->invert)
+                               fe_params->inversion = INVERSION_OFF;
+                       break;
+               }
+       } else {
+               tda10086_read_byte(state, 0x0f);
+               switch(val & 0x02) {
+               case 0x00:
+                       fe_params->inversion = INVERSION_OFF;
+                       if (state->config->invert)
+                               fe_params->inversion = INVERSION_ON;
+                       break;
+               default:
+                       fe_params->inversion = INVERSION_ON;
+                       if (state->config->invert)
+                               fe_params->inversion = INVERSION_OFF;
+                       break;
+               }
+       }
+
+       // calculate the updated symbol rate
+       tmp = tda10086_read_byte(state, 0x1d);
+       if (tmp & 0x80)
+               tmp |= 0xffffff00;
+       tmp = (tmp * 480 * (1<<1)) / 128;
+       tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
+       fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
+
+       // the FEC
+       val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
+       switch(val) {
+       case 0x00:
+               fe_params->u.qpsk.fec_inner = FEC_1_2;
+               break;
+       case 0x01:
+               fe_params->u.qpsk.fec_inner = FEC_2_3;
+               break;
+       case 0x02:
+               fe_params->u.qpsk.fec_inner = FEC_3_4;
+               break;
+       case 0x03:
+               fe_params->u.qpsk.fec_inner = FEC_4_5;
+               break;
+       case 0x04:
+               fe_params->u.qpsk.fec_inner = FEC_5_6;
+               break;
+       case 0x05:
+               fe_params->u.qpsk.fec_inner = FEC_6_7;
+               break;
+       case 0x06:
+               fe_params->u.qpsk.fec_inner = FEC_7_8;
+               break;
+       case 0x07:
+               fe_params->u.qpsk.fec_inner = FEC_8_9;
+               break;
+       }
+
+       return 0;
+}
+
+static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+       u8 val;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       val = tda10086_read_byte(state, 0x0e);
+       *fe_status = 0;
+       if (val & 0x01)
+               *fe_status |= FE_HAS_SIGNAL;
+       if (val & 0x02)
+               *fe_status |= FE_HAS_CARRIER;
+       if (val & 0x04)
+               *fe_status |= FE_HAS_VITERBI;
+       if (val & 0x08)
+               *fe_status |= FE_HAS_SYNC;
+       if (val & 0x10)
+               *fe_status |= FE_HAS_LOCK;
+
+       return 0;
+}
+
+static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+       u8 _str;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       _str = tda10086_read_byte(state, 0x43);
+       *signal = (_str << 8) | _str;
+
+       return 0;
+}
+
+static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+       u8 _snr;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       _snr = tda10086_read_byte(state, 0x1c);
+       *snr = (_snr << 8) | _snr;
+
+       return 0;
+}
+
+static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       // read it
+       *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
+
+       // reset counter
+       tda10086_write_byte(state, 0x18, 0x00);
+       tda10086_write_byte(state, 0x18, 0x80);
+
+       return 0;
+}
+
+static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       // read it
+       *ber = 0;
+       *ber |= tda10086_read_byte(state, 0x15);
+       *ber |= tda10086_read_byte(state, 0x16) << 8;
+       *ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16;
+
+       return 0;
+}
+
+static int tda10086_sleep(struct dvb_frontend* fe)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       tda10086_write_mask(state, 0x00, 0x08, 0x08);
+
+       return 0;
+}
+
+static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct tda10086_state* state = fe->demodulator_priv;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       if (enable) {
+               tda10086_write_mask(state, 0x00, 0x10, 0x10);
+       } else {
+               tda10086_write_mask(state, 0x00, 0x10, 0x00);
+       }
+
+       return 0;
+}
+
+static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+       if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+               fesettings->min_delay_ms = 50;
+               fesettings->step_size = 2000;
+               fesettings->max_drift = 8000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+               fesettings->min_delay_ms = 100;
+               fesettings->step_size = 1500;
+               fesettings->max_drift = 9000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+               fesettings->min_delay_ms = 100;
+               fesettings->step_size = 1000;
+               fesettings->max_drift = 8000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+               fesettings->min_delay_ms = 100;
+               fesettings->step_size = 500;
+               fesettings->max_drift = 7000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+               fesettings->min_delay_ms = 200;
+               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->max_drift = 14 * fesettings->step_size;
+       } else {
+               fesettings->min_delay_ms = 200;
+               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->max_drift = 18 * fesettings->step_size;
+       }
+
+       return 0;
+}
+
+static void tda10086_release(struct dvb_frontend* fe)
+{
+       struct tda10086_state *state = fe->demodulator_priv;
+       tda10086_sleep(fe);
+       kfree(state);
+}
+
+static struct dvb_frontend_ops tda10086_ops = {
+
+       .info = {
+               .name     = "Philips TDA10086 DVB-S",
+               .type     = FE_QPSK,
+               .frequency_min    = 950000,
+               .frequency_max    = 2150000,
+               .frequency_stepsize = 125,     /* kHz for QPSK frontends */
+               .symbol_rate_min  = 1000000,
+               .symbol_rate_max  = 45000000,
+               .caps = FE_CAN_INVERSION_AUTO |
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK
+       },
+
+       .release = tda10086_release,
+
+       .init = tda10086_init,
+       .sleep = tda10086_sleep,
+       .i2c_gate_ctrl = tda10086_i2c_gate_ctrl,
+
+       .set_frontend = tda10086_set_frontend,
+       .get_frontend = tda10086_get_frontend,
+       .get_tune_settings = tda10086_get_tune_settings,
+
+       .read_status = tda10086_read_status,
+       .read_ber = tda10086_read_ber,
+       .read_signal_strength = tda10086_read_signal_strength,
+       .read_snr = tda10086_read_snr,
+       .read_ucblocks = tda10086_read_ucblocks,
+
+       .diseqc_send_master_cmd = tda10086_send_master_cmd,
+       .diseqc_send_burst = tda10086_send_burst,
+       .set_tone = tda10086_set_tone,
+};
+
+struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+                                    struct i2c_adapter* i2c)
+{
+       struct tda10086_state *state;
+
+       dprintk ("%s\n", __FUNCTION__);
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+
+       /* check if the demod is there */
+       if (tda10086_read_byte(state, 0x1e) != 0xe1) {
+               kfree(state);
+               return NULL;
+       }
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+}
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(tda10086_attach);
diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
new file mode 100644 (file)
index 0000000..e8061db
--- /dev/null
@@ -0,0 +1,41 @@
+  /*
+     Driver for Philips tda10086 DVBS Frontend
+
+     (c) 2006 Andrew de Quincey
+
+     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 TDA10086_H
+#define TDA10086_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct tda10086_config
+{
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* does the "inversion" need inverted? */
+       u8 invert;
+};
+
+extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+                                           struct i2c_adapter* i2c);
+
+#endif // TDA10086_H
index e7a48f61ea2c6382e2e272f7f1b37f5e3c58d813..aae15bdce6ebafcc3d900c45117e473077344f50 100644 (file)
@@ -35,7 +35,16 @@ struct tda8083_config
        u8 demod_address;
 };
 
+#if defined(CONFIG_DVB_TDA8083) || defined(CONFIG_DVB_TDA8083_MODULE)
 extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_TDA8083
 
 #endif // TDA8083_H
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
new file mode 100644 (file)
index 0000000..eeab26b
--- /dev/null
@@ -0,0 +1,173 @@
+  /*
+     Driver for Philips tda8262/tda8263 DVBS Silicon tuners
+
+     (c) 2006 Andrew de Quincey
+
+     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/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "tda826x.h"
+
+static int debug = 0;
+#define dprintk(args...) \
+       do { \
+               if (debug) printk(KERN_DEBUG "tda826x: " args); \
+       } while (0)
+
+struct tda826x_priv {
+       /* i2c details */
+       int i2c_address;
+       struct i2c_adapter *i2c;
+       u8 has_loopthrough:1;
+       u32 frequency;
+};
+
+static int tda826x_release(struct dvb_frontend *fe)
+{
+       if (fe->tuner_priv)
+               kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int tda826x_sleep(struct dvb_frontend *fe)
+{
+       struct tda826x_priv *priv = fe->tuner_priv;
+       int ret;
+       u8 buf [] = { 0x00, 0x8d };
+       struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
+
+       dprintk("%s:\n", __FUNCTION__);
+
+       if (!priv->has_loopthrough)
+               buf[1] = 0xad;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+               dprintk("%s: i2c error\n", __FUNCTION__);
+       }
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return (ret == 1) ? 0 : ret;
+}
+
+static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct tda826x_priv *priv = fe->tuner_priv;
+       int ret;
+       u32 div;
+       u8 buf [11];
+       struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
+
+       dprintk("%s:\n", __FUNCTION__);
+
+       div = (params->frequency + (1000-1)) / 1000;
+
+       buf[0] = 0x00; // subaddress
+       buf[1] = 0x09; // powerdown RSSI + the magic value 1
+       if (!priv->has_loopthrough)
+               buf[1] |= 0x20; // power down loopthrough if not needed
+       buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
+       buf[3] = div >> 7;
+       buf[4] = div << 1;
+       buf[5] = 0xff; // basedband filter to max
+       buf[6] = 0xfe; // gains at max + no RF attenuation
+       buf[7] = 0x83; // charge pumps at high, tests off
+       buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
+       buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
+       buf[10] = 0xd4; // recommended value 13 for BBIAS + unknown bit set on
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+               dprintk("%s: i2c error\n", __FUNCTION__);
+       }
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       priv->frequency = div * 1000;
+
+       return (ret == 1) ? 0 : ret;
+}
+
+static int tda826x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct tda826x_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static struct dvb_tuner_ops tda826x_tuner_ops = {
+       .info = {
+               .name = "Philips TDA826X",
+               .frequency_min = 950000,
+               .frequency_min = 2175000
+       },
+       .release = tda826x_release,
+       .sleep = tda826x_sleep,
+       .set_params = tda826x_set_params,
+       .get_frequency = tda826x_get_frequency,
+};
+
+struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough)
+{
+       struct tda826x_priv *priv = NULL;
+       u8 b1 [] = { 0, 0 };
+       struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 };
+       int ret;
+
+       dprintk("%s:\n", __FUNCTION__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       ret = i2c_transfer (i2c, &msg, 1);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (ret != 1)
+               return NULL;
+       if (!(b1[1] & 0x80))
+               return NULL;
+
+       priv = kzalloc(sizeof(struct tda826x_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
+
+       priv->i2c_address = addr;
+       priv->i2c = i2c;
+       priv->has_loopthrough = has_loopthrough;
+
+       memcpy(&fe->ops.tuner_ops, &tda826x_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+       fe->tuner_priv = priv;
+
+       return fe;
+}
+EXPORT_SYMBOL(tda826x_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB TDA826x driver");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h
new file mode 100644 (file)
index 0000000..3307607
--- /dev/null
@@ -0,0 +1,40 @@
+  /*
+     Driver for Philips tda8262/tda8263 DVBS Silicon tuners
+
+     (c) 2006 Andrew de Quincey
+
+     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 __DVB_TDA826X_H__
+#define __DVB_TDA826X_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a tda826x tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param addr i2c address of the tuner.
+ * @param i2c i2c adapter to use.
+ * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector.
+ * @return FE pointer on success, NULL on failure.
+ */
+extern struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough);
+
+#endif
diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c
new file mode 100644 (file)
index 0000000..8855439
--- /dev/null
@@ -0,0 +1,205 @@
+/**
+ * Driver for Infineon tua6100 pll.
+ *
+ * (c) 2006 Andrew de Quincey
+ *
+ * Based on code found in budget-av.c, which has the following:
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ *
+ * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
+ *                               Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * Copyright (C) 1999-2002 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ * 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/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "tua6100.h"
+
+struct tua6100_priv {
+       /* i2c details */
+       int i2c_address;
+       struct i2c_adapter *i2c;
+       u32 frequency;
+};
+
+static int tua6100_release(struct dvb_frontend *fe)
+{
+       if (fe->tuner_priv)
+               kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int tua6100_sleep(struct dvb_frontend *fe)
+{
+       struct tua6100_priv *priv = fe->tuner_priv;
+       int ret;
+       u8 reg0[] = { 0x00, 0x00 };
+       struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+               printk("%s: i2c error\n", __FUNCTION__);
+       }
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return (ret == 1) ? 0 : ret;
+}
+
+static int tua6100_set_params(struct dvb_frontend *fe,
+                             struct dvb_frontend_parameters *params)
+{
+       struct tua6100_priv *priv = fe->tuner_priv;
+       u32 div;
+       u32 prediv;
+       u8 reg0[] = { 0x00, 0x00 };
+       u8 reg1[] = { 0x01, 0x00, 0x00, 0x00 };
+       u8 reg2[] = { 0x02, 0x00, 0x00 };
+       struct i2c_msg msg0 = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
+       struct i2c_msg msg1 = { .addr = priv->i2c_address, .flags = 0, .buf = reg1, .len = 4 };
+       struct i2c_msg msg2 = { .addr = priv->i2c_address, .flags = 0, .buf = reg2, .len = 3 };
+
+#define _R 4
+#define _P 32
+#define _ri 4000000
+
+       // setup register 0
+       if (params->frequency < 2000000) {
+               reg0[1] = 0x03;
+       } else {
+               reg0[1] = 0x07;
+       }
+
+       // setup register 1
+       if (params->frequency < 1630000) {
+               reg1[1] = 0x2c;
+       } else {
+               reg1[1] = 0x0c;
+       }
+       if (_P == 64)
+               reg1[1] |= 0x40;
+       if (params->frequency >= 1525000)
+               reg1[1] |= 0x80;
+
+       // register 2
+       reg2[1] = (_R >> 8) & 0x03;
+       reg2[2] = _R;
+       if (params->frequency < 1455000) {
+               reg2[1] |= 0x1c;
+       } else if (params->frequency < 1630000) {
+               reg2[1] |= 0x0c;
+       } else {
+               reg2[1] |= 0x1c;
+       }
+
+       // The N divisor ratio (note: params->frequency is in kHz, but we need it in Hz)
+       prediv = (params->frequency * _R) / (_ri / 1000);
+       div = prediv / _P;
+       reg1[1] |= (div >> 9) & 0x03;
+       reg1[2] = div >> 1;
+       reg1[3] = (div << 7);
+       priv->frequency = ((div * _P) * (_ri / 1000)) / _R;
+
+       // Finally, calculate and store the value for A
+       reg1[3] |= (prediv - (div*_P)) & 0x7f;
+
+#undef _R
+#undef _P
+#undef _ri
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(priv->i2c, &msg0, 1) != 1)
+               return -EIO;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(priv->i2c, &msg2, 1) != 1)
+               return -EIO;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(priv->i2c, &msg1, 1) != 1)
+               return -EIO;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+}
+
+static int tua6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct tua6100_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static struct dvb_tuner_ops tua6100_tuner_ops = {
+       .info = {
+               .name = "Infineon TUA6100",
+               .frequency_min = 950000,
+               .frequency_max = 2150000,
+               .frequency_step = 1000,
+       },
+       .release = tua6100_release,
+       .sleep = tua6100_sleep,
+       .set_params = tua6100_set_params,
+       .get_frequency = tua6100_get_frequency,
+};
+
+struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
+{
+       struct tua6100_priv *priv = NULL;
+       u8 b1 [] = { 0x80 };
+       u8 b2 [] = { 0x00 };
+       struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b1, .len = 1 },
+                                 { .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 } };
+       int ret;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       ret = i2c_transfer (i2c, msg, 2);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (ret != 2)
+               return NULL;
+
+       priv = kzalloc(sizeof(struct tua6100_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
+
+       priv->i2c_address = addr;
+       priv->i2c = i2c;
+
+       memcpy(&fe->ops.tuner_ops, &tua6100_tuner_ops, sizeof(struct dvb_tuner_ops));
+       fe->tuner_priv = priv;
+       return fe;
+}
+EXPORT_SYMBOL(tua6100_attach);
+
+MODULE_DESCRIPTION("DVB tua6100 driver");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb/frontends/tua6100.h
new file mode 100644 (file)
index 0000000..8f98033
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * Driver for Infineon tua6100 PLL.
+ *
+ * (c) 2006 Andrew de Quincey
+ *
+ * Based on code found in budget-av.c, which has the following:
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ *
+ * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
+ *                               Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * Copyright (C) 1999-2002 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ * 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 __DVB_TUA6100_H__
+#define __DVB_TUA6100_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_DVB_TUA6100) || defined(CONFIG_DVB_TUA6100_MODULE)
+extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_TUA6100
+
+#endif
index 520f09522fbbd0bc7604738ea61c366801aef75c..f0c9dded39d77fea63914ebb82a329ee1d976e87 100644 (file)
@@ -41,7 +41,16 @@ struct ves1820_config
        u8 selagc:1;
 };
 
+#if defined(CONFIG_DVB_VES1820) || defined(CONFIG_DVB_VES1820_MODULE)
 extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
                                           struct i2c_adapter* i2c, u8 pwm);
+#else
+static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+                                          struct i2c_adapter* i2c, u8 pwm)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_VES1820
 
 #endif // VES1820_H
index ba88ae0855c994025b4a13c5e07ae65ab919bca7..395fed39b2865527aea538c434fa953c247a4e09 100644 (file)
@@ -40,7 +40,16 @@ struct ves1x93_config
        u8 invert_pwm:1;
 };
 
+#if defined(CONFIG_DVB_VES1X93) || defined(CONFIG_DVB_VES1X93_MODULE)
 extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_VES1X93
 
 #endif // VES1X93_H
index 2b95e8b6cd3973dd8613f3edbe47e97c5b4871f4..0e9b59af271edcb96a3ffdd89f5efe92897d8b62 100644 (file)
@@ -140,6 +140,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
        zl10353_single_write(fe, 0x5E, 0x00);
        zl10353_single_write(fe, 0x65, 0x5A);
        zl10353_single_write(fe, 0x66, 0xE9);
+       zl10353_single_write(fe, 0x6C, 0xCD);
+       zl10353_single_write(fe, 0x6D, 0x7E);
        zl10353_single_write(fe, 0x62, 0x0A);
 
        // if there is no attached secondary tuner, we call set_params to program
@@ -168,6 +170,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
        // even if there isn't a PLL attached to the secondary bus
        zl10353_write(fe, pllbuf, sizeof(pllbuf));
 
+       zl10353_single_write(fe, 0x5F, 0x13);
        zl10353_single_write(fe, 0x70, 0x01);
        udelay(250);
        zl10353_single_write(fe, 0xE4, 0x00);
@@ -243,9 +246,12 @@ static int zl10353_init(struct dvb_frontend *fe)
 
        if (debug_regs)
                zl10353_dump_regs(fe);
+       if (state->config.parallel_ts)
+               zl10353_reset_attach[2] &= ~0x20;
 
        /* Do a "hard" reset if not already done */
-       if (zl10353_read_register(state, 0x50) != 0x03) {
+       if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] ||
+           zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
                rc = zl10353_write(fe, zl10353_reset_attach,
                                   sizeof(zl10353_reset_attach));
                if (debug_regs)
@@ -258,7 +264,6 @@ static int zl10353_init(struct dvb_frontend *fe)
 static void zl10353_release(struct dvb_frontend *fe)
 {
        struct zl10353_state *state = fe->demodulator_priv;
-
        kfree(state);
 }
 
@@ -314,6 +319,7 @@ static struct dvb_frontend_ops zl10353_ops = {
 
        .init = zl10353_init,
        .sleep = zl10353_sleep,
+       .write = zl10353_write,
 
        .set_frontend = zl10353_set_parameters,
        .get_tune_settings = zl10353_get_tune_settings,
@@ -330,4 +336,3 @@ MODULE_AUTHOR("Chris Pascoe");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(zl10353_attach);
-EXPORT_SYMBOL(zl10353_write);
index 9770cb840cfccbfc4ae96657201a69fbcb112455..79a947215c4d4d6a0d447dcbc39b85ba9caf6eee 100644 (file)
@@ -31,11 +31,21 @@ struct zl10353_config
 
        /* set if no pll is connected to the secondary i2c bus */
        int no_tuner;
+
+       /* set if parallel ts output is required */
+       int parallel_ts;
 };
 
+#if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE)
 extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
                                           struct i2c_adapter *i2c);
-
-extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen);
+#else
+static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+                                          struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_ZL10353
 
 #endif /* ZL10353_H */
index 5fb097595cfbdab39188b56005cca785de0a6c70..95531a624991644337b3f98dde9c98d8114e6f96 100644 (file)
@@ -1,17 +1,17 @@
 config DVB_AV7110
        tristate "AV7110 cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
-       select FW_LOADER
+       select FW_LOADER if !DVB_AV7110_FIRMWARE
        select VIDEO_SAA7146_VV
        select DVB_PLL
-       select DVB_VES1820
-       select DVB_VES1X93
-       select DVB_STV0299
-       select DVB_TDA8083
-       select DVB_SP8870
-       select DVB_STV0297
-       select DVB_L64781
-       select DVB_LNBP21
+       select DVB_VES1820 if !DVB_FE_CUSTOMISE
+       select DVB_VES1X93 if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+       select DVB_SP8870 if !DVB_FE_CUSTOMISE
+       select DVB_STV0297 if !DVB_FE_CUSTOMISE
+       select DVB_L64781 if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
        help
          Support for SAA7146 and AV7110 based DVB cards as produced
          by Fujitsu-Siemens, Technotrend, Hauppauge and others.
@@ -63,14 +63,16 @@ config DVB_BUDGET
        depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
        select VIDEO_SAA7146
        select DVB_PLL
-       select DVB_STV0299
-       select DVB_VES1X93
-       select DVB_VES1820
-       select DVB_L64781
-       select DVB_TDA8083
-       select DVB_TDA10021
-       select DVB_S5H1420
-       select DVB_LNBP21
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_VES1X93 if !DVB_FE_CUSTOMISE
+       select DVB_VES1820 if !DVB_FE_CUSTOMISE
+       select DVB_L64781 if !DVB_FE_CUSTOMISE
+       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1420 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+       select DVB_TDA826X if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
@@ -86,10 +88,10 @@ config DVB_BUDGET_CI
        depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
        select VIDEO_SAA7146
        select DVB_PLL
-       select DVB_STV0297
-       select DVB_STV0299
-       select DVB_TDA1004X
-       select DVB_LNBP21
+       select DVB_STV0297 if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
@@ -108,9 +110,10 @@ config DVB_BUDGET_AV
        depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
        select VIDEO_SAA7146_VV
        select DVB_PLL
-       select DVB_STV0299
-       select DVB_TDA1004X
-       select DVB_TDA10021
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+       select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+       select DVB_TUA6100 if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          Support for simple SAA7146 based DVB cards
@@ -127,9 +130,9 @@ config DVB_BUDGET_PATCH
        depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
        select DVB_AV7110
        select DVB_PLL
-       select DVB_STV0299
-       select DVB_VES1X93
-       select DVB_TDA8083
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_VES1X93 if !DVB_FE_CUSTOMISE
+       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
        help
          Support for Budget Patch (full TS) modification on
          SAA7146+AV7110 based cards (DVB-S cards). This
index 4506165c5de259ac9a9a2785866b3cf7048624c4..bba23bcd1b11d813326464f80fe72cfd1ff16896 100644 (file)
@@ -1383,8 +1383,10 @@ static void dvb_unregister(struct av7110 *av7110)
        dvb_dmxdev_release(&av7110->dmxdev);
        dvb_dmx_release(&av7110->demux);
 
-       if (av7110->fe != NULL)
+       if (av7110->fe != NULL) {
                dvb_unregister_frontend(av7110->fe);
+               dvb_frontend_detach(av7110->fe);
+       }
        dvb_unregister_device(av7110->osd_dev);
        av7110_av_unregister(av7110);
        av7110_ca_unregister(av7110);
@@ -1699,9 +1701,13 @@ static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
 
 static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 {
+#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
        struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
 
        return request_firmware(fw, name, &av7110->dev->pci->dev);
+#else
+       return -EINVAL;
+#endif
 }
 
 static struct sp8870_config alps_tdlb7_config = {
@@ -2077,7 +2083,7 @@ static int frontend_init(struct av7110 *av7110)
        if (av7110->dev->pci->subsystem_vendor == 0x110a) {
                switch(av7110->dev->pci->subsystem_device) {
                case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
-                       av7110->fe = ves1820_attach(&philips_cd1516_config,
+                       av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
                                                    &av7110->i2c_adap, read_pwm(av7110));
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
@@ -2092,7 +2098,7 @@ static int frontend_init(struct av7110 *av7110)
                case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
 
                        // try the ALPS BSRV2 first of all
-                       av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
                                av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
@@ -2103,7 +2109,7 @@ static int frontend_init(struct av7110 *av7110)
                        }
 
                        // try the ALPS BSRU6 now
-                       av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
                                av7110->fe->tuner_priv = &av7110->i2c_adap;
@@ -2116,7 +2122,7 @@ static int frontend_init(struct av7110 *av7110)
                        }
 
                        // Try the grundig 29504-451
-                       av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
                                av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
@@ -2130,7 +2136,7 @@ static int frontend_init(struct av7110 *av7110)
                        switch(av7110->dev->pci->subsystem_device) {
                        case 0x0000:
                                /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
-                               av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
+                               av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
                                                        read_pwm(av7110));
                                if (av7110->fe) {
                                        av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
@@ -2138,7 +2144,7 @@ static int frontend_init(struct av7110 *av7110)
                                break;
                        case 0x0003:
                                /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
-                               av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
+                               av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
                                                        read_pwm(av7110));
                                if (av7110->fe) {
                                        av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
@@ -2148,17 +2154,24 @@ static int frontend_init(struct av7110 *av7110)
                        break;
 
                case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
-
-                       // ALPS TDLB7
-                       av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+                       // try ALPS TDLB7 first, then Grundig 29504-401
+                       av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
+                               break;
                        }
+                       /* fall-thru */
+
+               case 0x0008: // Hauppauge/TT DVB-T
+                       // Grundig 29504-401
+                       av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
+                       if (av7110->fe)
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
                        break;
 
                case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
 
-                       av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+                       av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
                        }
@@ -2166,7 +2179,7 @@ static int frontend_init(struct av7110 *av7110)
 
                case 0x0004: // Galaxis DVB-S rev1.3
                        /* ALPS BSRV2 */
-                       av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
                                av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
@@ -2178,7 +2191,7 @@ static int frontend_init(struct av7110 *av7110)
 
                case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
                        /* Grundig 29504-451 */
-                       av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
                                av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
@@ -2188,17 +2201,9 @@ static int frontend_init(struct av7110 *av7110)
                        }
                        break;
 
-               case 0x0008: // Hauppauge/TT DVB-T
-
-                       av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
-                       if (av7110->fe) {
-                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
-                       }
-                       break;
-
                case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
 
-                       av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
 
@@ -2214,12 +2219,12 @@ static int frontend_init(struct av7110 *av7110)
 
                case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
                        /* ALPS BSBE1 */
-                       av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
+                       av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
                                av7110->fe->tuner_priv = &av7110->i2c_adap;
 
-                               if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
+                               if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
                                        printk("dvb-ttpci: LNBP21 not found!\n");
                                        if (av7110->fe->ops.release)
                                                av7110->fe->ops.release(av7110->fe);
@@ -2255,8 +2260,7 @@ static int frontend_init(struct av7110 *av7110)
                ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
                if (ret < 0) {
                        printk("av7110: Frontend registration failed!\n");
-                       if (av7110->fe->ops.release)
-                               av7110->fe->ops.release(av7110->fe);
+                       dvb_frontend_detach(av7110->fe);
                        av7110->fe = NULL;
                }
        }
@@ -2823,7 +2827,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 
 static struct saa7146_extension av7110_extension = {
-       .name           = "dvb\0",
+       .name           = "dvb",
        .flags          = SAA7146_I2C_SHORT_DELAY,
 
        .module         = THIS_MODULE,
index 0f3a044aeb17e82e4ee245ef1097ed41c0537b33..8c577cf30fb379359dc52841642bf2dd24d844ae 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
-#include <linux/byteorder/swabb.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
 
index 6079e8865d5b99d3f3ca4185e20b44014227df9f..dd9aee314e0a389b72f2347c347c5e45ad8df3ee 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/byteorder/swabb.h>
 #include <linux/smp_lock.h>
 
 #include "av7110.h"
index 75736f2fe83864bb6bf48e7204a28c6a9930e806..37de2e88a273b9616a8af19129f7cf880682d766 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
-#include <linux/byteorder/swabb.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
 
index 6ffe53fdcf570bced668dd68cce10233eef437ab..10cfe3131e72aad0ecdeec292d926b5fcab126eb 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/byteorder/swabb.h>
 #include <linux/smp_lock.h>
 
 #include "av7110.h"
@@ -922,7 +921,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
 static struct saa7146_ext_vv av7110_vv_data_c = {
        .inputs         = 1,
        .audios         = 1,
-       .capabilities   = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
+       .capabilities   = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,
        .flags          = SAA7146_USE_PORT_B_FOR_VBI,
 
        .stds           = &standard[0],
index 2d21fec23b4d9ea4f04694ab1678bbff747a797d..2235ff8b8a1d06b35f9273fe7dd832d8591c6b3a 100644 (file)
@@ -37,6 +37,7 @@
 #include "stv0299.h"
 #include "tda10021.h"
 #include "tda1004x.h"
+#include "tua6100.h"
 #include "dvb-pll.h"
 #include <media/saa7146_vv.h>
 #include <linux/module.h>
@@ -235,7 +236,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 
        /* set tda10021 back to original clock configuration on reset */
        if (budget_av->tda10021_poclkp) {
-               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+               tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0);
                budget_av->tda10021_ts_enabled = 0;
        }
 
@@ -257,7 +258,7 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 
        /* set tda10021 back to original clock configuration when cam removed */
        if (budget_av->tda10021_poclkp) {
-               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+               tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0);
                budget_av->tda10021_ts_enabled = 0;
        }
        return 0;
@@ -277,7 +278,7 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 
        /* tda10021 seems to need a different TS clock config when data is routed to the CAM */
        if (budget_av->tda10021_poclkp) {
-               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+               tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1);
                budget_av->tda10021_ts_enabled = 1;
        }
 
@@ -548,144 +549,6 @@ static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
        return 0;
 }
 
-#define MIN2(a,b) ((a) < (b) ? (a) : (b))
-#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
-
-static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe,
-                                                     struct dvb_frontend_parameters *params)
-{
-       u8 reg0 [2] = { 0x00, 0x00 };
-       u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
-       u8 reg2 [3] = { 0x02, 0x00, 0x00 };
-       int _fband;
-       int first_ZF;
-       int R, A, N, P, M;
-       struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
-       int freq = params->frequency;
-       struct budget *budget = (struct budget *) fe->dvb->priv;
-
-       first_ZF = (freq) / 1000;
-
-       if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) <
-                  abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890))))
-               _fband = 2;
-       else
-               _fband = 3;
-
-       if (_fband == 2) {
-               if (((first_ZF >= 950) && (first_ZF < 1350)) ||
-                                   ((first_ZF >= 1430) && (first_ZF < 1950)))
-                       reg0[1] = 0x07;
-               else if (((first_ZF >= 1350) && (first_ZF < 1430)) ||
-                                        ((first_ZF >= 1950) && (first_ZF < 2150)))
-                       reg0[1] = 0x0B;
-       }
-
-       if(_fband == 3) {
-               if (((first_ZF >= 950) && (first_ZF < 1350)) ||
-                                   ((first_ZF >= 1455) && (first_ZF < 1950)))
-                       reg0[1] = 0x07;
-               else if (((first_ZF >= 1350) && (first_ZF < 1420)) ||
-                                        ((first_ZF >= 1950) && (first_ZF < 2150)))
-                       reg0[1] = 0x0B;
-               else if ((first_ZF >= 1420) && (first_ZF < 1455))
-                       reg0[1] = 0x0F;
-       }
-
-       if (first_ZF > 1525)
-               reg1[1] |= 0x80;
-       else
-               reg1[1] &= 0x7F;
-
-       if (_fband == 2) {
-               if (first_ZF > 1430) { /* 1430MHZ */
-                       reg1[1] &= 0xCF; /* N2 */
-                       reg2[1] &= 0xCF; /* R2 */
-                       reg2[1] |= 0x10;
-               } else {
-                       reg1[1] &= 0xCF; /* N2 */
-                       reg1[1] |= 0x20;
-                       reg2[1] &= 0xCF; /* R2 */
-                       reg2[1] |= 0x10;
-               }
-       }
-
-       if (_fband == 3) {
-               if ((first_ZF >= 1455) &&
-                                  (first_ZF < 1630)) {
-                       reg1[1] &= 0xCF; /* N2 */
-                       reg1[1] |= 0x20;
-                       reg2[1] &= 0xCF; /* R2 */
-                                  } else {
-                                          if (first_ZF < 1455) {
-                                                  reg1[1] &= 0xCF; /* N2 */
-                                                  reg1[1] |= 0x20;
-                                                  reg2[1] &= 0xCF; /* R2 */
-                                                  reg2[1] |= 0x10;
-                                          } else {
-                                                  if (first_ZF >= 1630) {
-                                                          reg1[1] &= 0xCF; /* N2 */
-                                                          reg2[1] &= 0xCF; /* R2 */
-                                                          reg2[1] |= 0x10;
-                                                  }
-                                          }
-                                  }
-       }
-
-       /* set ports, enable P0 for symbol rates > 4Ms/s */
-       if (params->u.qpsk.symbol_rate >= 4000000)
-               reg1[1] |= 0x0c;
-       else
-               reg1[1] |= 0x04;
-
-       reg2[1] |= 0x0c;
-
-       R = 64;
-       A = 64;
-       P = 64;  //32
-
-       M = (freq * R) / 4;             /* in Mhz */
-       N = (M - A * 1000) / (P * 1000);
-
-       reg1[1] |= (N >> 9) & 0x03;
-       reg1[2]  = (N >> 1) & 0xff;
-       reg1[3]  = (N << 7) & 0x80;
-
-       reg2[1] |= (R >> 8) & 0x03;
-       reg2[2]  = R & 0xFF;    /* R */
-
-       reg1[3] |= A & 0x7f;    /* A */
-
-       if (P == 64)
-               reg1[1] |= 0x40; /* Prescaler 64/65 */
-
-       reg0[1] |= 0x03;
-
-       /* already enabled - do not reenable i2c repeater or TX fails */
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       msg.buf = reg0;
-       msg.len = sizeof(reg0);
-       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       msg.buf = reg1;
-       msg.len = sizeof(reg1);
-       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       msg.buf = reg2;
-       msg.len = sizeof(reg2);
-       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-
-       return 0;
-}
-
 static u8 typhoon_cinergy1200s_inittab[] = {
        0x01, 0x15,
        0x02, 0x30,
@@ -1068,9 +931,9 @@ static int tda10021_set_frontend(struct dvb_frontend *fe,
 
        result = budget_av->tda10021_set_frontend(fe, p);
        if (budget_av->tda10021_ts_enabled) {
-               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+               tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1);
        } else {
-               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+               tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0);
        }
 
        return result;
@@ -1096,15 +959,16 @@ static void frontend_init(struct budget_av *budget_av)
        switch (saa->pci->subsystem_device) {
 
        case SUBID_DVBS_KNC1:
+       case SUBID_DVBS_KNC1_PLUS:
        case SUBID_DVBS_EASYWATCH_1:
                if (saa->pci->subsystem_vendor == 0x1894) {
-                       fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
+                       fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
                                             &budget_av->budget.i2c_adap);
                        if (fe) {
-                               fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params;
+                               dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
                        }
                } else {
-                       fe = stv0299_attach(&typhoon_config,
+                       fe = dvb_attach(stv0299_attach, &typhoon_config,
                                             &budget_av->budget.i2c_adap);
                        if (fe) {
                                fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
@@ -1116,16 +980,15 @@ static void frontend_init(struct budget_av *budget_av)
        case SUBID_DVBS_TV_STAR_CI:
        case SUBID_DVBS_CYNERGY1200N:
        case SUBID_DVBS_EASYWATCH:
-               fe = stv0299_attach(&philips_sd1878_config,
+               fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
                                &budget_av->budget.i2c_adap);
                if (fe) {
                        fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
                }
                break;
 
-       case SUBID_DVBS_KNC1_PLUS:
        case SUBID_DVBS_TYPHOON:
-               fe = stv0299_attach(&typhoon_config,
+               fe = dvb_attach(stv0299_attach, &typhoon_config,
                                    &budget_av->budget.i2c_adap);
                if (fe) {
                        fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
@@ -1133,7 +996,7 @@ static void frontend_init(struct budget_av *budget_av)
                break;
 
        case SUBID_DVBS_CINERGY1200:
-               fe = stv0299_attach(&cinergy_1200s_config,
+               fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
                                    &budget_av->budget.i2c_adap);
                if (fe) {
                        fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
@@ -1141,19 +1004,10 @@ static void frontend_init(struct budget_av *budget_av)
                break;
 
        case SUBID_DVBC_KNC1:
-               budget_av->reinitialise_demod = 1;
-               fe = tda10021_attach(&philips_cu1216_config,
-                                    &budget_av->budget.i2c_adap,
-                                    read_pwm(budget_av));
-               if (fe) {
-                       fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
-               }
-               break;
-
        case SUBID_DVBC_KNC1_PLUS:
        case SUBID_DVBC_CINERGY1200:
                budget_av->reinitialise_demod = 1;
-               fe = tda10021_attach(&philips_cu1216_config,
+               fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
                                     &budget_av->budget.i2c_adap,
                                     read_pwm(budget_av));
                if (fe) {
@@ -1168,7 +1022,7 @@ static void frontend_init(struct budget_av *budget_av)
        case SUBID_DVBT_KNC1_PLUS:
        case SUBID_DVBT_CINERGY1200:
                budget_av->reinitialise_demod = 1;
-               fe = tda10046_attach(&philips_tu1216_config,
+               fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
                                     &budget_av->budget.i2c_adap);
                if (fe) {
                        fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
@@ -1192,8 +1046,7 @@ static void frontend_init(struct budget_av *budget_av)
        if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
                                  budget_av->budget.dvb_frontend)) {
                printk(KERN_ERR "budget-av: Frontend registration failed!\n");
-               if (budget_av->budget.dvb_frontend->ops.release)
-                       budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
+               dvb_frontend_detach(budget_av->budget.dvb_frontend);
                budget_av->budget.dvb_frontend = NULL;
        }
 }
@@ -1227,8 +1080,10 @@ static int budget_av_detach(struct saa7146_dev *dev)
        if (budget_av->budget.ci_present)
                ciintf_deinit(budget_av);
 
-       if (budget_av->budget.dvb_frontend != NULL)
+       if (budget_av->budget.dvb_frontend != NULL) {
                dvb_unregister_frontend(budget_av->budget.dvb_frontend);
+               dvb_frontend_detach(budget_av->budget.dvb_frontend);
+       }
        err = ttpci_budget_deinit(&budget_av->budget);
 
        kfree(budget_av);
@@ -1400,6 +1255,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
        MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
        MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
+       MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
        MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
        MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
        MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
index ffbbb3e34be482cf3071e1dabbb7d76882404e0f..2a2e9b400613ed6674c8ee69c349ec64f484be79 100644 (file)
@@ -749,17 +749,17 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
        // setup PLL filter and TDA9889
        switch (params->u.ofdm.bandwidth) {
        case BANDWIDTH_6_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0x14);
+               tda1004x_writereg(fe, 0x0C, 0x14);
                filter = 0;
                break;
 
        case BANDWIDTH_7_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0x80);
+               tda1004x_writereg(fe, 0x0C, 0x80);
                filter = 0;
                break;
 
        case BANDWIDTH_8_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0x14);
+               tda1004x_writereg(fe, 0x0C, 0x14);
                filter = 1;
                break;
 
@@ -988,7 +988,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        switch (budget_ci->budget.dev->pci->subsystem_device) {
        case 0x100c:            // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
                budget_ci->budget.dvb_frontend =
-                       stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
                        budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
@@ -998,7 +998,7 @@ static void frontend_init(struct budget_ci *budget_ci)
 
        case 0x100f:            // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
                budget_ci->budget.dvb_frontend =
-                       stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
                        break;
@@ -1008,7 +1008,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        case 0x1010:            // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
                budget_ci->tuner_pll_address = 0x61;
                budget_ci->budget.dvb_frontend =
-                       stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
                        break;
@@ -1018,7 +1018,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        case 0x1011:            // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
                budget_ci->tuner_pll_address = 0x63;
                budget_ci->budget.dvb_frontend =
-                       tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
@@ -1029,7 +1029,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        case 0x1012:            // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
                budget_ci->tuner_pll_address = 0x60;
                budget_ci->budget.dvb_frontend =
-                       tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+                       dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
@@ -1038,16 +1038,15 @@ static void frontend_init(struct budget_ci *budget_ci)
                break;
 
        case 0x1017:            // TT S-1500 PCI
-               budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap);
+               budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
                        budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
 
                        budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
-                       if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
+                       if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
                                printk("%s: No LNBP21 found!\n", __FUNCTION__);
-                               if (budget_ci->budget.dvb_frontend->ops.release)
-                                       budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
+                               dvb_frontend_detach(budget_ci->budget.dvb_frontend);
                                budget_ci->budget.dvb_frontend = NULL;
                        }
                }
@@ -1065,8 +1064,7 @@ static void frontend_init(struct budget_ci *budget_ci)
                if (dvb_register_frontend
                    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
                        printk("budget-ci: Frontend registration failed!\n");
-                       if (budget_ci->budget.dvb_frontend->ops.release)
-                               budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
+                       dvb_frontend_detach(budget_ci->budget.dvb_frontend);
                        budget_ci->budget.dvb_frontend = NULL;
                }
        }
@@ -1114,8 +1112,10 @@ static int budget_ci_detach(struct saa7146_dev *dev)
 
        if (budget_ci->budget.ci_present)
                ciintf_deinit(budget_ci);
-       if (budget_ci->budget.dvb_frontend)
+       if (budget_ci->budget.dvb_frontend) {
                dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
+               dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+       }
        err = ttpci_budget_deinit(&budget_ci->budget);
 
        tasklet_kill(&budget_ci->msp430_irq_tasklet);
@@ -1153,7 +1153,7 @@ static struct pci_device_id pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
-       .name = "budget_ci dvb\0",
+       .name = "budget_ci dvb",
        .flags = SAA7146_I2C_SHORT_DELAY,
 
        .module = THIS_MODULE,
index 57227441891e54bea5d0236417042e6f12ede756..fc1267b8c892f43627b9a8c2e1749fad25ad64fe 100644 (file)
@@ -325,7 +325,7 @@ static void frontend_init(struct budget_patch* budget)
        case 0x1013: // SATELCO Multimedia PCI
 
                // try the ALPS BSRV2 first of all
-               budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
                        budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
@@ -335,7 +335,7 @@ static void frontend_init(struct budget_patch* budget)
                }
 
                // try the ALPS BSRU6 now
-               budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
                        budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
@@ -347,7 +347,7 @@ static void frontend_init(struct budget_patch* budget)
                }
 
                // Try the grundig 29504-451
-               budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
                        budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
@@ -367,8 +367,7 @@ static void frontend_init(struct budget_patch* budget)
        } else {
                if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
                        printk("budget-av: Frontend registration failed!\n");
-                       if (budget->dvb_frontend->ops.release)
-                               budget->dvb_frontend->ops.release(budget->dvb_frontend);
+                       dvb_frontend_detach(budget->dvb_frontend);
                        budget->dvb_frontend = NULL;
                }
        }
@@ -627,8 +626,10 @@ static int budget_patch_detach (struct saa7146_dev* dev)
        struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
        int err;
 
-       if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
-
+       if (budget->dvb_frontend) {
+               dvb_unregister_frontend(budget->dvb_frontend);
+               dvb_frontend_detach(budget->dvb_frontend);
+       }
        err = ttpci_budget_deinit (budget);
 
        kfree (budget);
@@ -647,7 +648,7 @@ static void __exit budget_patch_exit(void)
 }
 
 static struct saa7146_extension budget_extension = {
-       .name           = "budget_patch dvb\0",
+       .name           = "budget_patch dvb",
        .flags          = 0,
 
        .module         = THIS_MODULE,
index 863dffb4ed8e5058b42fb31be828297945adc1f8..e58f0391e9d1ac0386a707bfaf9373dcab261dfa 100644 (file)
@@ -41,6 +41,8 @@
 #include "l64781.h"
 #include "tda8083.h"
 #include "s5h1420.h"
+#include "tda10086.h"
+#include "tda826x.h"
 #include "lnbp21.h"
 #include "bsru6.h"
 
@@ -342,6 +344,11 @@ static struct s5h1420_config s5h1420_config = {
        .invert = 1,
 };
 
+static struct tda10086_config tda10086_config = {
+       .demod_address = 0x0e,
+       .invert = 0,
+};
+
 static u8 read_pwm(struct budget* budget)
 {
        u8 b = 0xff;
@@ -361,7 +368,7 @@ static void frontend_init(struct budget *budget)
        case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
        case 0x1013:
                // try the ALPS BSRV2 first of all
-               budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
                        budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
@@ -371,7 +378,7 @@ static void frontend_init(struct budget *budget)
                }
 
                // try the ALPS BSRU6 now
-               budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
                        budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
@@ -381,7 +388,7 @@ static void frontend_init(struct budget *budget)
 
        case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
 
-               budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
+               budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
                        break;
@@ -390,7 +397,7 @@ static void frontend_init(struct budget *budget)
 
        case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
 
-               budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
                        break;
@@ -398,7 +405,7 @@ static void frontend_init(struct budget *budget)
                break;
 
        case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
-               budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
                        budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
@@ -408,7 +415,7 @@ static void frontend_init(struct budget *budget)
                break;
 
        case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
-               budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
                        budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
@@ -417,10 +424,28 @@ static void frontend_init(struct budget *budget)
                break;
 
        case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
-               budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
+               budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
                        budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
-                       if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
+                       if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
+                               printk("%s: No LNBP21 found!\n", __FUNCTION__);
+                               goto error_out;
+                       }
+                       break;
+               }
+
+       case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262)
+               // gpio2 is connected to CLB - reset it + leave it high
+               saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
+               msleep(1);
+               saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
+               msleep(1);
+
+               budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
+               if (budget->dvb_frontend) {
+                       if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
+                               printk("%s: No tda826x found!\n", __FUNCTION__);
+                       if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
                                printk("%s: No LNBP21 found!\n", __FUNCTION__);
                                goto error_out;
                        }
@@ -442,8 +467,7 @@ static void frontend_init(struct budget *budget)
 
 error_out:
        printk("budget: Frontend registration failed!\n");
-       if (budget->dvb_frontend->ops.release)
-               budget->dvb_frontend->ops.release(budget->dvb_frontend);
+       dvb_frontend_detach(budget->dvb_frontend);
        budget->dvb_frontend = NULL;
        return;
 }
@@ -481,7 +505,10 @@ static int budget_detach (struct saa7146_dev* dev)
        struct budget *budget = (struct budget*) dev->ext_priv;
        int err;
 
-       if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
+       if (budget->dvb_frontend) {
+               dvb_unregister_frontend(budget->dvb_frontend);
+               dvb_frontend_detach(budget->dvb_frontend);
+       }
 
        err = ttpci_budget_deinit (budget);
 
@@ -497,6 +524,7 @@ MAKE_BUDGET_INFO(ttbs,      "TT-Budget/WinTV-NOVA-S  PCI",  BUDGET_TT);
 MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C  PCI",  BUDGET_TT);
 MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T  PCI",  BUDGET_TT);
 MAKE_BUDGET_INFO(satel,        "SATELCO Multimedia PCI",       BUDGET_TT_HW_DISEQC);
+MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
 
@@ -506,6 +534,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
        MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1016),
+       MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
        MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
        {
@@ -516,7 +545,7 @@ static struct pci_device_id pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
 static struct saa7146_extension budget_extension = {
-       .name           = "budget dvb\0",
+       .name           = "budget dvb",
        .flags          = SAA7146_I2C_SHORT_DELAY,
 
        .module         = THIS_MODULE,
index 46a6a60d2ab9b9751ff2b9262bbe045866b0baa5..e78ea9227b0ea0c39ee22a4f45ad0961f7577fa7 100644 (file)
@@ -2,13 +2,13 @@ config DVB_TTUSB_BUDGET
        tristate "Technotrend/Hauppauge Nova-USB devices"
        depends on DVB_CORE && USB && I2C
        select DVB_PLL
-       select DVB_CX22700
-       select DVB_TDA1004X
-       select DVB_VES1820
-       select DVB_TDA8083
-       select DVB_STV0299
-       select DVB_STV0297
-       select DVB_LNBP21
+       select DVB_CX22700 if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+       select DVB_VES1820 if !DVB_FE_CUSTOMISE
+       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_STV0297 if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
        help
          Support for external USB adapters designed by Technotrend and
          produced by Hauppauge, shipped under the brand name 'Nova-USB'.
index 04cef3023457c34ccc7584cec6e83002844ff143..234199875f53f77c094251969c1713eb91dcb34d 100644 (file)
@@ -1107,17 +1107,17 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
        // setup PLL filter
        switch (params->u.ofdm.bandwidth) {
        case BANDWIDTH_6_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0);
+               tda1004x_writereg(fe, 0x0C, 0);
                filter = 0;
                break;
 
        case BANDWIDTH_7_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0);
+               tda1004x_writereg(fe, 0x0C, 0);
                filter = 0;
                break;
 
        case BANDWIDTH_8_MHZ:
-               tda1004x_write_byte(fe, 0x0C, 0xFF);
+               tda1004x_writereg(fe, 0x0C, 0xFF);
                filter = 1;
                break;
 
@@ -1564,13 +1564,13 @@ static void frontend_init(struct ttusb* ttusb)
        switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
        case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6|BSBE1(tsa5059))
                // try the stv0299 based first
-               ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap);
+               ttusb->fe = dvb_attach(stv0299_attach, &alps_stv0299_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
                        ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
 
                        if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
                                alps_stv0299_config.inittab = alps_bsbe1_inittab;
-                               lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0);
+                               dvb_attach(lnbp21_attach, ttusb->fe, &ttusb->i2c_adap, 0, 0);
                        } else { // ALPS BSRU6
                                ttusb->fe->ops.set_voltage = ttusb_set_voltage;
                        }
@@ -1578,7 +1578,7 @@ static void frontend_init(struct ttusb* ttusb)
                }
 
                // Grundig 29504-491
-               ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
+               ttusb->fe = dvb_attach(tda8083_attach, &ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
                        ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
                        ttusb->fe->ops.set_voltage = ttusb_set_voltage;
@@ -1587,13 +1587,13 @@ static void frontend_init(struct ttusb* ttusb)
                break;
 
        case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
-               ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
+               ttusb->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
                if (ttusb->fe != NULL) {
                        ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
                        break;
                }
 
-               ttusb->fe = stv0297_attach(&dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
+               ttusb->fe = dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
                        ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
                        break;
@@ -1602,14 +1602,14 @@ static void frontend_init(struct ttusb* ttusb)
 
        case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
                // try the ALPS TDMB7 first
-               ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap);
+               ttusb->fe = dvb_attach(cx22700_attach, &alps_tdmb7_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
                        ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
                        break;
                }
 
                // Philips td1316
-               ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap);
+               ttusb->fe = dvb_attach(tda10046_attach, &philips_tdm1316l_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
                        ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
                        ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
@@ -1625,8 +1625,7 @@ static void frontend_init(struct ttusb* ttusb)
        } else {
                if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
                        printk("dvb-ttusb-budget: Frontend registration failed!\n");
-                       if (ttusb->fe->ops.release)
-                               ttusb->fe->ops.release(ttusb->fe);
+                       dvb_frontend_detach(ttusb->fe);
                        ttusb->fe = NULL;
                }
        }
@@ -1763,7 +1762,10 @@ static void ttusb_disconnect(struct usb_interface *intf)
        dvb_net_release(&ttusb->dvbnet);
        dvb_dmxdev_release(&ttusb->dmxdev);
        dvb_dmx_release(&ttusb->dvb_demux);
-       if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe);
+       if (ttusb->fe != NULL) {
+               dvb_unregister_frontend(ttusb->fe);
+               dvb_frontend_detach(ttusb->fe);
+       }
        i2c_del_adapter(&ttusb->i2c_adap);
        dvb_unregister_adapter(&ttusb->adapter);
 
index 6c1cb770bcf5d28ccecd3ea2d743fc7099bea056..de077a757192de57915dda6aecb3297e123e6cf7 100644 (file)
@@ -215,7 +215,7 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
                case -ECONNRESET:
                case -ENOENT:
                case -ESHUTDOWN:
-               case -ETIMEDOUT:
+               case -ETIME:
                        /* this urb is dead, cleanup */
                        dprintk("%s:urb shutting down with status: %d\n",
                                        __FUNCTION__, urb->status);
@@ -1512,7 +1512,11 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
        dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
        dvb_dmxdev_release(&dec->dmxdev);
        dvb_dmx_release(&dec->demux);
-       if (dec->fe) dvb_unregister_frontend(dec->fe);
+       if (dec->fe) {
+               dvb_unregister_frontend(dec->fe);
+               if (dec->fe->ops.release)
+                       dec->fe->ops.release(dec->fe);
+       }
        dvb_unregister_adapter(&dec->adapter);
 }
 
index 220076b1b956df5d20434a5c5d8b2d9b9c1e7583..7015517e2c1b68aa78f84dede0289807accaace2 100644 (file)
@@ -7,7 +7,7 @@ menu "Radio Adapters"
 
 config RADIO_CADET
        tristate "ADS Cadet AM/FM Tuner"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these AM/FM radio cards, and then
          fill in the port address below.
@@ -25,7 +25,7 @@ config RADIO_CADET
 
 config RADIO_RTRACK
        tristate "AIMSlab RadioTrack (aka RadioReveal) support"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these FM radio cards, and then fill
          in the port address below.
@@ -59,7 +59,7 @@ config RADIO_RTRACK_PORT
 
 config RADIO_RTRACK2
        tristate "AIMSlab RadioTrack II support"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have this FM radio card, and then fill in the
          port address below.
@@ -82,7 +82,7 @@ config RADIO_RTRACK2_PORT
 
 config RADIO_AZTECH
        tristate "Aztech/Packard Bell Radio"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these FM radio cards, and then fill
          in the port address below.
@@ -106,7 +106,7 @@ config RADIO_AZTECH_PORT
 
 config RADIO_GEMTEK
        tristate "GemTek Radio Card support"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have this FM radio card, and then fill in the
          port address below.
@@ -131,7 +131,7 @@ config RADIO_GEMTEK_PORT
 
 config RADIO_GEMTEK_PCI
        tristate "GemTek PCI Radio Card support"
-       depends on VIDEO_V4L1 && PCI
+       depends on VIDEO_V4L2 && PCI
        ---help---
          Choose Y here if you have this PCI FM radio card.
 
@@ -145,7 +145,7 @@ config RADIO_GEMTEK_PCI
 
 config RADIO_MAXIRADIO
        tristate "Guillemot MAXI Radio FM 2000 radio"
-       depends on VIDEO_V4L1 && PCI
+       depends on VIDEO_V4L2 && PCI
        ---help---
          Choose Y here if you have this radio card.  This card may also be
          found as Gemtek PCI FM.
@@ -160,7 +160,7 @@ config RADIO_MAXIRADIO
 
 config RADIO_MAESTRO
        tristate "Maestro on board radio"
-       depends on VIDEO_V4L1
+       depends on VIDEO_V4L2 && PCI
        ---help---
          Say Y here to directly support the on-board radio tuner on the
          Maestro 2 or 2E sound card.
@@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS
 
 config RADIO_SF16FMI
        tristate "SF16FMI Radio"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these FM radio cards.  If you
          compile the driver into the kernel and your card is not PnP one, you
@@ -225,7 +225,7 @@ config RADIO_SF16FMI
 
 config RADIO_SF16FMR2
        tristate "SF16FMR2 Radio"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these FM radio cards.
 
@@ -239,7 +239,7 @@ config RADIO_SF16FMR2
 
 config RADIO_TERRATEC
        tristate "TerraTec ActiveRadio ISA Standalone"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have this FM radio card, and then fill in the
          port address below. (TODO)
@@ -268,7 +268,7 @@ config RADIO_TERRATEC_PORT
 
 config RADIO_TRUST
        tristate "Trust FM radio card"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        help
          This is a driver for the Trust FM radio cards. Say Y if you have
          such a card and want to use it under Linux.
@@ -286,7 +286,7 @@ config RADIO_TRUST_PORT
 
 config RADIO_TYPHOON
        tristate "Typhoon Radio (a.k.a. EcoRadio)"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these FM radio cards, and then fill
          in the port address and the frequency used for muting below.
@@ -330,7 +330,7 @@ config RADIO_TYPHOON_MUTEFREQ
 
 config RADIO_ZOLTRIX
        tristate "Zoltrix Radio"
-       depends on ISA && VIDEO_V4L1
+       depends on ISA && VIDEO_V4L2
        ---help---
          Choose Y here if you have one of these FM radio cards, and then fill
          in the port address below.
@@ -352,7 +352,7 @@ config RADIO_ZOLTRIX_PORT
 
 config USB_DSBR
        tristate "D-Link USB FM radio support (EXPERIMENTAL)"
-       depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+       depends on USB && VIDEO_V4L2 && EXPERIMENTAL
        ---help---
          Say Y here if you want to connect this type of radio to your
          computer's USB port. Note that the audio is not digital, and
index f7e33f9ee8e921fddbe569e0898fece377e5b97b..db865a0667e5ae8caed0fd9d8f75c879120ce2d0 100644 (file)
 
  History:
 
+ Version 0.41-ac1:
+       Alan Cox: Some cleanups and fixes
+
+ Version 0.41:
+       Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
+
  Version 0.40:
-  Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
+       Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
 
  Version 0.30:
        Markus: Updates for 2.5.x kernel and more ISO compliant source
 
 */
 
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/input.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.40"
+#include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
+
+#define DRIVER_VERSION "v0.41"
+#define RADIO_VERSION KERNEL_VERSION(0,4,1)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }
+};
+
 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
 
@@ -111,7 +131,7 @@ static int radio_nr = -1;
 module_param(radio_nr, int, 0);
 
 /* Data for one (physical) device */
-typedef struct {
+struct dsbr100_device {
        struct usb_device *usbdev;
        struct video_device *videodev;
        unsigned char transfer_buffer[TB_LEN];
@@ -119,7 +139,8 @@ typedef struct {
        int stereo;
        int users;
        int removed;
-} dsbr100_device;
+       int muted;
+};
 
 
 /* File system interface */
@@ -138,7 +159,6 @@ static struct video_device dsbr100_videodev_template=
        .owner =        THIS_MODULE,
        .name =         "D-Link DSB-R 100",
        .type =         VID_TYPE_TUNER,
-       .hardware =     VID_HARDWARE_AZTECH,
        .fops =         &usb_dsbr100_fops,
        .release = video_device_release,
 };
@@ -161,7 +181,7 @@ static struct usb_driver usb_dsbr100_driver = {
 /* Low-level device interface begins here */
 
 /* switch on radio */
-static int dsbr100_start(dsbr100_device *radio)
+static int dsbr100_start(struct dsbr100_device *radio)
 {
        if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
                        USB_REQ_GET_STATUS,
@@ -172,12 +192,13 @@ static int dsbr100_start(dsbr100_device *radio)
                        USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                        0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
                return -1;
+       radio->muted=0;
        return (radio->transfer_buffer)[0];
 }
 
 
 /* switch off radio */
-static int dsbr100_stop(dsbr100_device *radio)
+static int dsbr100_stop(struct dsbr100_device *radio)
 {
        if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
                        USB_REQ_GET_STATUS,
@@ -188,11 +209,12 @@ static int dsbr100_stop(dsbr100_device *radio)
                        USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                        0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
                return -1;
+       radio->muted=1;
        return (radio->transfer_buffer)[0];
 }
 
 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static int dsbr100_setfreq(dsbr100_device *radio, int freq)
+static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
 {
        freq = (freq/16*80)/1000+856;
        if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
@@ -217,7 +239,7 @@ static int dsbr100_setfreq(dsbr100_device *radio, int freq)
 
 /* return the device status.  This is, in effect, just whether it
 sees a stereo signal or not.  Pity. */
-static void dsbr100_getstat(dsbr100_device *radio)
+static void dsbr100_getstat(struct dsbr100_device *radio)
 {
        if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
                USB_REQ_GET_STATUS,
@@ -236,9 +258,9 @@ usb if it is */
 static int usb_dsbr100_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
-       dsbr100_device *radio;
+       struct dsbr100_device *radio;
 
-       if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL)))
+       if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
                return -ENOMEM;
        if (!(radio->videodev = video_device_alloc())) {
                kfree(radio);
@@ -271,7 +293,7 @@ code I'd expect I better did that, but if there's a memory
 leak here it's tiny (~50 bytes per disconnect) */
 static void usb_dsbr100_disconnect(struct usb_interface *intf)
 {
-       dsbr100_device *radio = usb_get_intfdata(intf);
+       struct dsbr100_device *radio = usb_get_intfdata(intf);
 
        usb_set_intfdata (intf, NULL);
        if (radio) {
@@ -291,89 +313,121 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
 static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
                                unsigned int cmd, void *arg)
 {
-       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
 
        if (!radio)
                return -EIO;
 
        switch(cmd) {
-               case VIDIOCGCAP: {
-                       struct video_capability *v = arg;
-
-                       memset(v, 0, sizeof(*v));
-                       v->type = VID_TYPE_TUNER;
-                       v->channels = 1;
-                       v->audios = 1;
-                       strcpy(v->name, "D-Link R-100 USB FM Radio");
+               case VIDIOC_QUERYCAP:
+               {
+                       struct v4l2_capability *v = arg;
+                       memset(v,0,sizeof(*v));
+                       strlcpy(v->driver, "dsbr100", sizeof (v->driver));
+                       strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER: {
-                       struct video_tuner *v = arg;
+               case VIDIOC_G_TUNER:
+               {
+                       struct v4l2_tuner *v = arg;
 
-                       dsbr100_getstat(radio);
-                       if(v->tuner)    /* Only 1 tuner */
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       dsbr100_getstat(radio);
+
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
                        v->rangelow = FREQ_MIN*FREQ_MUL;
                        v->rangehigh = FREQ_MAX*FREQ_MUL;
-                       v->flags = VIDEO_TUNER_LOW;
-                       v->mode = VIDEO_MODE_AUTO;
-                       v->signal = radio->stereo*0x7000;
-                               /* Don't know how to get signal strength */
-                       v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;
-                       strcpy(v->name, "DSB R-100");
-                       return 0;
-               }
-               case VIDIOCSTUNER: {
-                       struct video_tuner *v = arg;
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       if(radio->stereo)
+                               v->audmode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal = 0xFFFF;     /* We can't get the signal strength */
 
-                       if(v->tuner!=0)
-                               return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
                        return 0;
                }
-               case VIDIOCGFREQ: {
-                       int *freq = arg;
+               case VIDIOC_S_TUNER:
+               {
+                       struct v4l2_tuner *v = arg;
 
-                       if (radio->curfreq==-1)
+                       if (v->index > 0)
                                return -EINVAL;
-                       *freq = radio->curfreq;
+
                        return 0;
                }
-               case VIDIOCSFREQ: {
-                       int *freq = arg;
+               case VIDIOC_S_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
 
-                       radio->curfreq = *freq;
+                       radio->curfreq = f->frequency;
                        if (dsbr100_setfreq(radio, radio->curfreq)==-1)
                                warn("Set frequency failed");
                        return 0;
                }
-               case VIDIOCGAUDIO: {
-                       struct video_audio *v = arg;
-
-                       memset(v, 0, sizeof(*v));
-                       v->flags |= VIDEO_AUDIO_MUTABLE;
-                       v->mode = VIDEO_SOUND_STEREO;
-                       v->volume = 1;
-                       v->step = 1;
-                       strcpy(v->name, "Radio");
+               case VIDIOC_G_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = radio->curfreq;
+
                        return 0;
                }
-               case VIDIOCSAUDIO: {
-                       struct video_audio *v = arg;
-
-                       if (v->audio)
-                               return -EINVAL;
-                       if (v->flags&VIDEO_AUDIO_MUTE) {
-                               if (dsbr100_stop(radio)==-1)
-                                       warn("Radio did not respond properly");
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return 0;
+                               }
                        }
-                       else
-                               if (dsbr100_start(radio)==-1)
-                                       warn("Radio did not respond properly");
-                       return 0;
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                       case V4L2_CID_AUDIO_MUTE:
+                               ctrl->value=radio->muted;
+                               return 0;
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                       case V4L2_CID_AUDIO_MUTE:
+                               if (ctrl->value) {
+                                       if (dsbr100_stop(radio)==-1)
+                                               warn("Radio did not respond properly");
+                               } else {
+                                       if (dsbr100_start(radio)==-1)
+                                               warn("Radio did not respond properly");
+                               }
+                               return 0;
+                       }
+                       return -EINVAL;
                }
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         usb_dsbr100_do_ioctl);
        }
 }
 
@@ -385,9 +439,11 @@ static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
 
 static int usb_dsbr100_open(struct inode *inode, struct file *file)
 {
-       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
 
        radio->users = 1;
+       radio->muted = 1;
+
        if (dsbr100_start(radio)<0) {
                warn("Radio did not start up properly");
                radio->users = 0;
@@ -399,7 +455,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file)
 
 static int usb_dsbr100_close(struct inode *inode, struct file *file)
 {
-       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
 
        if (!radio)
                return -ENODEV;
index df22a582e7a2fae4762b07801313eec005bbc66d..3368a89bfadbe356d0b4a7ed46ee3389ea3a3bef 100644 (file)
@@ -1,5 +1,6 @@
 /* radiotrack (radioreveal) driver for Linux radio support
  * (c) 1997 M. Kirkwood
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  * Converted to new API by Alan Cox <Alan.Cox@linux.org>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_RTRACK_PORT     */
 #include <asm/semaphore.h>     /* Lock for the I/O             */
 
+#include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
 #ifndef CONFIG_RADIO_RTRACK_PORT
 #define CONFIG_RADIO_RTRACK_PORT -1
 #endif
@@ -209,6 +212,25 @@ static int rt_getsigstr(struct rt_device *dev)
        return 1;               /* signal present               */
 }
 
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 static int rt_do_ioctl(struct inode *inode, struct file *file,
                       unsigned int cmd, void *arg)
 {
@@ -217,73 +239,114 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
-                       strcpy(v->name, "RadioTrack");
+                       strlcpy(v->driver, "radio-aimslab", sizeof (v->driver));
+                       strlcpy(v->card, "RadioTrack", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
                        v->rangelow=(87*16000);
                        v->rangehigh=(108*16000);
-                       v->flags=VIDEO_TUNER_LOW;
-                       v->mode=VIDEO_MODE_AUTO;
-                       strcpy(v->name, "FM");
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_MONO;
                        v->signal=0xFFFF*rt_getsigstr(rt);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
+
                        return 0;
                }
-               case VIDIOCGFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       *freq = rt->curfreq;
+                       struct v4l2_frequency *f = arg;
+
+                       rt->curfreq = f->frequency;
+                       rt_setfreq(rt, rt->curfreq);
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_G_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       rt->curfreq = *freq;
-                       rt_setfreq(rt, rt->curfreq);
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = rt->curfreq;
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
-                       v->volume=rt->curvol * 6554;
-                       v->step=6554;
-                       strcpy(v->name, "Radio");
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-                       if(v->flags&VIDEO_AUDIO_MUTE)
-                               rt_mute(rt);
-                       else
-                               rt_setvol(rt,v->volume/6554);
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=rt->muted;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value=rt->curvol * 6554;
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               rt_mute(rt);
+                                       } else {
+                                               rt_setvol(rt,rt->curvol);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       rt_setvol(rt,ctrl->value);
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         rt_do_ioctl);
        }
 }
 
@@ -309,7 +372,7 @@ static struct video_device rtrack_radio=
        .owner          = THIS_MODULE,
        .name           = "RadioTrack radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_RTRACK,
+       .hardware       = 0,
        .fops           = &rtrack_fops,
 };
 
index 95e6322133ee43289c1077af080cf50a57825db8..3ba5fa8cf7e611f1a8f616a63a63b734827e744c 100644 (file)
@@ -1,5 +1,6 @@
 /* radio-aztech.c - Aztech radio card driver for Linux 2.2
  *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  * Adapted to support the Video for Linux API by
  * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_AZTECH_PORT     */
+
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
 
@@ -166,81 +188,121 @@ static int az_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
-                       strcpy(v->name, "Aztech Radio");
+                       strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
+                       strlcpy(v->card, "Aztech Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
                        v->rangelow=(87*16000);
                        v->rangehigh=(108*16000);
-                       v->flags=VIDEO_TUNER_LOW;
-                       v->mode=VIDEO_MODE_AUTO;
-                       v->signal=0xFFFF*az_getsigstr(az);
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
                        if(az_getstereo(az))
-                               v->flags|=VIDEO_TUNER_STEREO_ON;
-                       strcpy(v->name, "FM");
+                               v->audmode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=0xFFFF*az_getsigstr(az);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
+
                        return 0;
                }
-               case VIDIOCGFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       *freq = az->curfreq;
+                       struct v4l2_frequency *f = arg;
+
+                       az->curfreq = f->frequency;
+                       az_setfreq(az, az->curfreq);
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_G_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       az->curfreq = *freq;
-                       az_setfreq(az, az->curfreq);
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = az->curfreq;
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
-                       if(az->stereo)
-                               v->mode=VIDEO_SOUND_STEREO;
-                       else
-                               v->mode=VIDEO_SOUND_MONO;
-                       v->volume=az->curvol;
-                       v->step=16384;
-                       strcpy(v->name, "Radio");
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-                       az->curvol=v->volume;
-
-                       az->stereo=(v->mode&VIDEO_SOUND_STEREO)?1:0;
-                       if(v->flags&VIDEO_AUDIO_MUTE)
-                               az_setvol(az,0);
-                       else
-                               az_setvol(az,az->curvol);
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (az->curvol==0)
+                                               ctrl->value=1;
+                                       else
+                                               ctrl->value=0;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value=az->curvol * 6554;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               az_setvol(az,0);
+                                       } else {
+                                               az_setvol(az,az->curvol);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       az_setvol(az,ctrl->value);
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
+
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         az_do_ioctl);
        }
 }
 
@@ -266,7 +328,7 @@ static struct video_device aztech_radio=
        .owner          = THIS_MODULE,
        .name           = "Aztech radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_AZTECH,
+       .hardware       = 0,
        .fops           = &aztech_fops,
 };
 
index 8641aec7baf87093e8faf1ea90331d913abe0ca9..69d4b7919c5aa8b8f3f73783d7fc06d9b14c16ac 100644 (file)
  *
  * 2003-01-31  Alan Cox <alan@redhat.com>
  *             Cleaned up locking, delay code, general odds and ends
+ *
+ * 2006-07-30  Hans J. Koch <koch@hjk-az.de>
+ *             Changed API to V4L2
  */
 
+#include <linux/version.h>
 #include <linux/module.h>      /* Modules                      */
 #include <linux/init.h>                /* Initdata                     */
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* V4L2 API defs                */
 #include <media/v4l2-common.h>
 #include <linux/param.h>
 #include <linux/pnp.h>
 
 #define RDS_BUFFER 256
+#define RDS_RX_FLAG 1
+#define MBS_RX_FLAG 2
+
+#define CADET_VERSION KERNEL_VERSION(0,3,3)
 
 static int io=-1;              /* default to isapnp activation */
 static int radio_nr = -1;
@@ -61,44 +69,24 @@ static int cadet_probe(void);
  */
 static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}};
 
-static int cadet_getrds(void)
-{
-       int rdsstat=0;
-
-       spin_lock(&cadet_io_lock);
-       outb(3,io);                 /* Select Decoder Control/Status */
-       outb(inb(io+1)&0x7f,io+1);  /* Reset RDS detection */
-       spin_unlock(&cadet_io_lock);
-
-       msleep(100);
-
-       spin_lock(&cadet_io_lock);
-       outb(3,io);                 /* Select Decoder Control/Status */
-       if((inb(io+1)&0x80)!=0) {
-               rdsstat|=VIDEO_TUNER_RDS_ON;
-       }
-       if((inb(io+1)&0x10)!=0) {
-               rdsstat|=VIDEO_TUNER_MBS_ON;
-       }
-       spin_unlock(&cadet_io_lock);
-       return rdsstat;
-}
 
-static int cadet_getstereo(void)
+static int
+cadet_getstereo(void)
 {
-       int ret = 0;
+       int ret = V4L2_TUNER_SUB_MONO;
        if(curtuner != 0)       /* Only FM has stereo capability! */
-               return 0;
+               return V4L2_TUNER_SUB_MONO;
 
        spin_lock(&cadet_io_lock);
        outb(7,io);          /* Select tuner control */
        if( (inb(io+1) & 0x40) == 0)
-               ret = 1;
+               ret = V4L2_TUNER_SUB_STEREO;
        spin_unlock(&cadet_io_lock);
        return ret;
 }
 
-static unsigned cadet_gettune(void)
+static unsigned
+cadet_gettune(void)
 {
        int curvol,i;
        unsigned fifo=0;
@@ -135,7 +123,8 @@ static unsigned cadet_gettune(void)
        return fifo;
 }
 
-static unsigned cadet_getfreq(void)
+static unsigned
+cadet_getfreq(void)
 {
        int i;
        unsigned freq=0,test,fifo=0;
@@ -167,7 +156,8 @@ static unsigned cadet_getfreq(void)
        return freq;
 }
 
-static void cadet_settune(unsigned fifo)
+static void
+cadet_settune(unsigned fifo)
 {
        int i;
        unsigned test;
@@ -195,7 +185,8 @@ static void cadet_settune(unsigned fifo)
        spin_unlock(&cadet_io_lock);
 }
 
-static void cadet_setfreq(unsigned freq)
+static void
+cadet_setfreq(unsigned freq)
 {
        unsigned fifo;
        int i,j,test;
@@ -255,7 +246,8 @@ static void cadet_setfreq(unsigned freq)
 }
 
 
-static int cadet_getvol(void)
+static int
+cadet_getvol(void)
 {
        int ret = 0;
 
@@ -270,7 +262,8 @@ static int cadet_getvol(void)
 }
 
 
-static void cadet_setvol(int vol)
+static void
+cadet_setvol(int vol)
 {
        spin_lock(&cadet_io_lock);
        outb(7,io);                /* Select tuner control */
@@ -281,7 +274,8 @@ static void cadet_setvol(int vol)
        spin_unlock(&cadet_io_lock);
 }
 
-static void cadet_handler(unsigned long data)
+static void
+cadet_handler(unsigned long data)
 {
        /*
         * Service the RDS fifo
@@ -322,8 +316,8 @@ static void cadet_handler(unsigned long data)
 
 
 
-static ssize_t cadet_read(struct file *file, char __user *data,
-                         size_t count, loff_t *ppos)
+static ssize_t
+cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
        int i=0;
        unsigned char readbuf[RDS_BUFFER];
@@ -359,128 +353,156 @@ static int cadet_do_ioctl(struct inode *inode, struct file *file,
 {
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
-                       memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=2;
-                       v->audios=1;
-                       strcpy(v->name, "ADS Cadet");
+                       struct v4l2_capability *cap = arg;
+                       memset(cap,0,sizeof(*cap));
+                       cap->capabilities =
+                               V4L2_CAP_TUNER |
+                               V4L2_CAP_READWRITE;
+                       cap->version = CADET_VERSION;
+                       strcpy(cap->driver, "ADS Cadet");
+                       strcpy(cap->card, "ADS Cadet");
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if((v->tuner<0)||(v->tuner>1)) {
-                               return -EINVAL;
-                       }
-                       switch(v->tuner) {
-                               case 0:
-                               strcpy(v->name,"FM");
-                               v->rangelow=1400;     /* 87.5 MHz */
-                               v->rangehigh=1728;    /* 108.0 MHz */
-                               v->flags=0;
-                               v->mode=0;
-                               v->mode|=VIDEO_MODE_AUTO;
-                               v->signal=sigstrength;
-                               if(cadet_getstereo()==1) {
-                                       v->flags|=VIDEO_TUNER_STEREO_ON;
-                               }
-                               v->flags|=cadet_getrds();
-                               break;
-                               case 1:
-                               strcpy(v->name,"AM");
-                               v->rangelow=8320;      /* 520 kHz */
-                               v->rangehigh=26400;    /* 1650 kHz */
-                               v->flags=0;
-                               v->flags|=VIDEO_TUNER_LOW;
-                               v->mode=0;
-                               v->mode|=VIDEO_MODE_AUTO;
-                               v->signal=sigstrength;
-                               break;
+                       struct v4l2_tuner *t = arg;
+                       memset(t,0,sizeof(*t));
+                       t->type = V4L2_TUNER_RADIO;
+                       switch (t->index)
+                       {
+                               case 0: strcpy(t->name, "FM");
+                                       t->capability = V4L2_TUNER_CAP_STEREO;
+                                       t->rangelow = 1400;     /* 87.5 MHz */
+                                       t->rangehigh = 1728;    /* 108.0 MHz */
+                                       t->rxsubchans=cadet_getstereo();
+                                       switch (t->rxsubchans){
+                                               case V4L2_TUNER_SUB_MONO:
+                                                       t->audmode = V4L2_TUNER_MODE_MONO;
+                                                       break;
+                                               case V4L2_TUNER_SUB_STEREO:
+                                                       t->audmode = V4L2_TUNER_MODE_STEREO;
+                                                       break;
+                                               default: ;
+                                       }
+                                       break;
+                               case 1: strcpy(t->name, "AM");
+                                       t->capability = V4L2_TUNER_CAP_LOW;
+                                       t->rangelow = 8320;      /* 520 kHz */
+                                       t->rangehigh = 26400;    /* 1650 kHz */
+                                       t->rxsubchans = V4L2_TUNER_SUB_MONO;
+                                       t->audmode = V4L2_TUNER_MODE_MONO;
+                                       break;
+                               default:
+                                       return -EINVAL;
                        }
+
+                       t->signal = sigstrength; /* We might need to modify scaling of this */
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if((v->tuner<0)||(v->tuner>1)) {
+                       struct v4l2_tuner *t = arg;
+                       if((t->index != 0)&&(t->index != 1))
                                return -EINVAL;
-                       }
-                       curtuner=v->tuner;
+
+                       curtuner = t->index;
                        return 0;
                }
-               case VIDIOCGFREQ:
+               case VIDIOC_G_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       *freq = cadet_getfreq();
+                       struct v4l2_frequency *f = arg;
+                       memset(f,0,sizeof(*f));
+                       f->tuner = curtuner;
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = cadet_getfreq();
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       if((curtuner==0)&&((*freq<1400)||(*freq>1728))) {
+                       struct v4l2_frequency *f = arg;
+                       if (f->type != V4L2_TUNER_RADIO){
+                               return -EINVAL;
+                       }
+                       if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) {
                                return -EINVAL;
                        }
-                       if((curtuner==1)&&((*freq<8320)||(*freq>26400))) {
+                       if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) {
                                return -EINVAL;
                        }
-                       cadet_setfreq(*freq);
+                       cadet_setfreq(f->frequency);
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
-                       if(cadet_getstereo()==0) {
-                               v->mode=VIDEO_SOUND_MONO;
-                       } else {
-                               v->mode=VIDEO_SOUND_STEREO;
+                       struct v4l2_control *c = arg;
+                       switch (c->id){
+                               case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
+                                       c->value = (cadet_getvol() == 0);
+                                       break;
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       c->value = cadet_getvol();
+                                       break;
+                               default:
+                                       return -EINVAL;
                        }
-                       v->volume=cadet_getvol();
-                       v->step=0xffff;
-                       strcpy(v->name, "Radio");
                        return 0;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_S_CTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-                       cadet_setvol(v->volume);
-                       if(v->flags&VIDEO_AUDIO_MUTE)
-                               cadet_setvol(0);
-                       else
-                               cadet_setvol(0xffff);
+                       struct v4l2_control *c = arg;
+                       switch (c->id){
+                               case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
+                                       if (c->value) cadet_setvol(0);
+                                               else cadet_setvol(0xffff);
+                                       break;
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       cadet_setvol(c->value);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                       }
                        return 0;
                }
+
                default:
                        return -ENOIOCTLCMD;
        }
 }
 
-static int cadet_ioctl(struct inode *inode, struct file *file,
+static int
+cadet_ioctl(struct inode *inode, struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl);
 }
 
-static int cadet_open(struct inode *inode, struct file *file)
+static int
+cadet_open(struct inode *inode, struct file *file)
 {
-       if(users)
-               return -EBUSY;
        users++;
-       init_waitqueue_head(&read_queue);
+       if (1 == users) init_waitqueue_head(&read_queue);
        return 0;
 }
 
-static int cadet_release(struct inode *inode, struct file *file)
+static int
+cadet_release(struct inode *inode, struct file *file)
 {
-       del_timer_sync(&readtimer);
-       rdsstat=0;
        users--;
+       if (0 == users){
+               del_timer_sync(&readtimer);
+               rdsstat=0;
+       }
+       return 0;
+}
+
+static unsigned int
+cadet_poll(struct file *file, struct poll_table_struct *wait)
+{
+       poll_wait(file,&read_queue,wait);
+       if(rdsin != rdsout)
+               return POLLIN | POLLRDNORM;
        return 0;
 }
 
@@ -491,6 +513,7 @@ static struct file_operations cadet_fops = {
        .release        = cadet_release,
        .read           = cadet_read,
        .ioctl          = cadet_ioctl,
+       .poll           = cadet_poll,
        .compat_ioctl   = v4l_compat_ioctl32,
        .llseek         = no_llseek,
 };
@@ -500,7 +523,6 @@ static struct video_device cadet_radio=
        .owner          = THIS_MODULE,
        .name           = "Cadet radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_CADET,
        .fops           = &cadet_fops,
 };
 
index 4c82956390c1de098a28c290baba01b698fd0c5c..cfab57d6bc4a7b9d8dfcf3a86c1252affa7167da 100644 (file)
@@ -34,6 +34,8 @@
  *
  *     TODO: multiple device support and portability were not tested
  *
+ *     Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
  ***************************************************************************
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <linux/errno.h>
 
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -183,91 +207,117 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
        struct gemtek_pci_card *card = dev->priv;
 
        switch ( cmd ) {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *c = arg;
+                       struct v4l2_capability *v = arg;
+                       memset(v,0,sizeof(*v));
+                       strlcpy(v->driver, "radio-gemtek-pci", sizeof (v->driver));
+                       strlcpy(v->card, "GemTek PCI Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
 
-                       memset(c,0,sizeof(*c));
-                       c->type = VID_TYPE_TUNER;
-                       c->channels = 1;
-                       c->audios = 1;
-                       strcpy( c->name, "Gemtek PCI Radio" );
                        return 0;
                }
-
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *t = arg;
+                       struct v4l2_tuner *v = arg;
 
-                       if ( t->tuner )
+                       if (v->index > 0)
                                return -EINVAL;
 
-                       t->rangelow = GEMTEK_PCI_RANGE_LOW;
-                       t->rangehigh = GEMTEK_PCI_RANGE_HIGH;
-                       t->flags = VIDEO_TUNER_LOW;
-                       t->mode = VIDEO_MODE_AUTO;
-                       t->signal = 0xFFFF * gemtek_pci_getsignal( card );
-                       strcpy( t->name, "FM" );
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow = GEMTEK_PCI_RANGE_LOW;
+                       v->rangehigh = GEMTEK_PCI_RANGE_HIGH;
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=0xFFFF*gemtek_pci_getsignal( card );
+
                        return 0;
                }
-
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *t = arg;
-                       if ( t->tuner )
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       return 0;
-               }
 
-               case VIDIOCGFREQ:
-               {
-                       unsigned long *freq = arg;
-                       *freq = card->current_frequency;
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
+                       struct v4l2_frequency *f = arg;
 
-                       if ( (*freq < GEMTEK_PCI_RANGE_LOW) ||
-                            (*freq > GEMTEK_PCI_RANGE_HIGH) )
+                       if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) ||
+                            (f->frequency > GEMTEK_PCI_RANGE_HIGH) )
                                return -EINVAL;
 
-                       gemtek_pci_setfrequency( card, *freq );
-                       card->current_frequency = *freq;
-                       card->mute = FALSE;
 
+                       gemtek_pci_setfrequency( card, f->frequency );
+                       card->current_frequency = f->frequency;
+                       card->mute = FALSE;
                        return 0;
                }
-
-               case VIDIOCGAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *a = arg;
-
-                       memset( a, 0, sizeof( *a ) );
-                       a->flags |= VIDEO_AUDIO_MUTABLE;
-                       a->volume = 1;
-                       a->step = 65535;
-                       strcpy( a->name, "Radio" );
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *a = arg;
-
-                       if ( a->audio )
-                               return -EINVAL;
-
-                       if ( a->flags & VIDEO_AUDIO_MUTE )
-                               gemtek_pci_mute( card );
-                       else
-                               gemtek_pci_unmute( card );
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=card->mute;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       if (card->mute)
+                                               ctrl->value=0;
+                                       else
+                                               ctrl->value=65535;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               gemtek_pci_mute(card);
+                                       } else {
+                                               gemtek_pci_unmute(card);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       if (ctrl->value) {
+                                               gemtek_pci_unmute(card);
+                                       } else {
+                                               gemtek_pci_mute(card);
+                                       }
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
-
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         gemtek_pci_do_ioctl);
        }
 }
 
@@ -309,7 +359,7 @@ static struct video_device vdev_template = {
        .owner         = THIS_MODULE,
        .name          = "Gemtek PCI Radio",
        .type          = VID_TYPE_TUNER,
-       .hardware      = VID_HARDWARE_GEMTEK,
+       .hardware      = 0,
        .fops          = &gemtek_pci_fops,
 };
 
index 162f37d8bf9623f52d9e46dc120089c53879b628..730fe16126cb9598610e5821d020ce2f8f78f485 100644 (file)
@@ -13,6 +13,7 @@
  *
  * TODO: Allow for more than one of these foolish entities :-)
  *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>      /* Modules                      */
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_GEMTEK_PORT     */
 #include <linux/spinlock.h>
 
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 #ifndef CONFIG_RADIO_GEMTEK_PORT
 #define CONFIG_RADIO_GEMTEK_PORT -1
 #endif
@@ -147,77 +169,122 @@ static int gemtek_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
-                       strcpy(v->name, "GemTek");
+                       strlcpy(v->driver, "radio-gemtek", sizeof (v->driver));
+                       strlcpy(v->card, "GemTek", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       v->rangelow=87*16000;
-                       v->rangehigh=108*16000;
-                       v->flags=VIDEO_TUNER_LOW;
-                       v->mode=VIDEO_MODE_AUTO;
-                       v->signal=0xFFFF*gemtek_getsigstr(rt);
+
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow=(87*16000);
+                       v->rangehigh=(108*16000);
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=0xFFFF*gemtek_getsigstr(rt);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
-                       return 0;
-               }
-               case VIDIOCGFREQ:
-               {
-                       unsigned long *freq = arg;
-                       *freq = rt->curfreq;
+
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       rt->curfreq = *freq;
+                       struct v4l2_frequency *f = arg;
+
+                       rt->curfreq = f->frequency;
                        /* needs to be called twice in order for getsigstr to work */
                        gemtek_setfreq(rt, rt->curfreq);
                        gemtek_setfreq(rt, rt->curfreq);
                        return 0;
                }
-               case VIDIOCGAUDIO:
-               {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags|=VIDEO_AUDIO_MUTABLE;
-                       v->volume=1;
-                       v->step=65535;
-                       strcpy(v->name, "Radio");
-                       return 0;
-               }
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
+                       struct v4l2_frequency *f = arg;
 
-                       if(v->flags&VIDEO_AUDIO_MUTE)
-                               gemtek_mute(rt);
-                       else
-                               gemtek_unmute(rt);
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = rt->curfreq;
 
                        return 0;
                }
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=rt->muted;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       if (rt->muted)
+                                               ctrl->value=0;
+                                       else
+                                               ctrl->value=65535;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               gemtek_mute(rt);
+                                       } else {
+                                               gemtek_unmute(rt);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       if (ctrl->value) {
+                                               gemtek_unmute(rt);
+                                       } else {
+                                               gemtek_mute(rt);
+                                       }
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         gemtek_do_ioctl);
        }
 }
 
@@ -243,7 +310,7 @@ static struct video_device gemtek_radio=
        .owner          = THIS_MODULE,
        .name           = "GemTek radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_GEMTEK,
+       .hardware       = 0,
        .fops           = &gemtek_fops,
 };
 
index fcfa6c9fe2256df1b949014831ad0b3e000819e5..e8ce5f75cf1200630b20cf5981a192c0a39ba4e3 100644 (file)
@@ -14,6 +14,8 @@
  *  version 0.04
  * + code improvements
  * + VIDEO_TUNER_LOW is permanent
+ *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 
-#define DRIVER_VERSION "0.05"
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,6)
+#define DRIVER_VERSION "0.06"
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }
+};
 
 #define GPIO_DATA      0x60   /* port offset from ESS_IO_BASE */
 
@@ -96,7 +111,7 @@ static struct file_operations maestro_fops = {
 static struct video_device maestro_radio = {
        .name           = "Maestro radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_SF16MI,
+       .hardware       = 0,
        .fops           = &maestro_fops,
 };
 
@@ -130,7 +145,7 @@ static u32 radio_bits_get(struct radio_device *dev)
                rdata = inw(io);
                if(!l)
                        dev->stereo =  rdata & STR_MOST ?
-                       0 : VIDEO_TUNER_STEREO_ON;
+                       0 : 1;
                else
                        if(rdata & STR_DATA)
                                data++;
@@ -183,72 +198,120 @@ static inline int radio_function(struct inode *inode, struct file *file,
        struct radio_device *card = video_get_drvdata(dev);
 
        switch (cmd) {
-       case VIDIOCGCAP: {
-               struct video_capability *v = arg;
-               memset(v, 0, sizeof(*v));
-               strcpy(v->name, "Maestro radio");
-               v->type = VID_TYPE_TUNER;
-               v->channels = v->audios = 1;
-               return 0;
-       } case VIDIOCGTUNER: {
-               struct video_tuner *v = arg;
-               if (v->tuner)
-                       return -EINVAL;
-               (void)radio_bits_get(card);
-               v->flags = VIDEO_TUNER_LOW | card->stereo;
-               v->signal = card->tuned;
-               strcpy(v->name, "FM");
-               v->rangelow = FREQ_LO;
-               v->rangehigh = FREQ_HI;
-               v->mode = VIDEO_MODE_AUTO;
-               return 0;
-       } case VIDIOCSTUNER: {
-               struct video_tuner *v = arg;
-               if (v->tuner != 0)
-                       return -EINVAL;
-               return 0;
-       } case VIDIOCGFREQ: {
-               unsigned long *freq = arg;
-               *freq = BITS2FREQ(radio_bits_get(card));
-               return 0;
-       } case VIDIOCSFREQ: {
-               unsigned long *freq = arg;
-               if (*freq < FREQ_LO || *freq > FREQ_HI)
+               case VIDIOC_QUERYCAP:
+               {
+                       struct v4l2_capability *v = arg;
+                       memset(v,0,sizeof(*v));
+                       strlcpy(v->driver, "radio-maestro", sizeof (v->driver));
+                       strlcpy(v->card, "Maestro Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"PCI");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
+                       return 0;
+               }
+               case VIDIOC_G_TUNER:
+               {
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
+                               return -EINVAL;
+
+                       (void)radio_bits_get(card);
+
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow = FREQ_LO;
+                       v->rangehigh = FREQ_HI;
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       if(card->stereo)
+                               v->audmode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=card->tuned;
+
+                       return 0;
+               }
+               case VIDIOC_S_TUNER:
+               {
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
+                               return -EINVAL;
+
+                       return 0;
+               }
+               case VIDIOC_S_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
+
+                       if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
+                               return -EINVAL;
+                       radio_bits_set(card, FREQ2BITS(f->frequency));
+
+                       return 0;
+               }
+               case VIDIOC_G_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = BITS2FREQ(radio_bits_get(card));
+
+                       return 0;
+               }
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
                        return -EINVAL;
-               radio_bits_set(card, FREQ2BITS(*freq));
-               return 0;
-       } case VIDIOCGAUDIO: {
-               struct video_audio *v = arg;
-               memset(v, 0, sizeof(*v));
-               strcpy(v->name, "Radio");
-               v->flags = VIDEO_AUDIO_MUTABLE | card->muted;
-               v->mode = VIDEO_SOUND_STEREO;
-               return 0;
-       } case VIDIOCSAUDIO: {
-               struct video_audio *v = arg;
-               if (v->audio)
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=card->muted;
+                                       return (0);
+                       }
                        return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
                {
-                       register u16 io = card->io;
-                       register u16 omask = inw(io + IO_MASK);
-                       outw(~STR_WREN, io + IO_MASK);
-                       outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ?
-                               STR_WREN : 0, io);
-                       udelay(4);
-                       outw(omask, io + IO_MASK);
-                       msleep(125);
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                               {
+                                       register u16 io = card->io;
+                                       register u16 omask = inw(io + IO_MASK);
+                                       outw(~STR_WREN, io + IO_MASK);
+                                       outw((card->muted = ctrl->value ) ?
+                                               STR_WREN : 0, io);
+                                       udelay(4);
+                                       outw(omask, io + IO_MASK);
+                                       msleep(125);
+
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-       } case VIDIOCGUNIT: {
-               struct video_unit *v = arg;
-               v->video = VIDEO_NO_UNIT;
-               v->vbi = VIDEO_NO_UNIT;
-               v->radio = dev->minor;
-               v->audio = 0;
-               v->teletext = VIDEO_NO_UNIT;
-               return 0;
-       } default:
-               return -ENOIOCTLCMD;
+               default:
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         radio_function);
        }
 }
 
@@ -275,7 +338,7 @@ static u16 __devinit radio_power_on(struct radio_device *dev)
        omask = inw(io + IO_MASK);
        odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
        outw(odir & ~STR_WREN, io + IO_DIR);
-       dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE;
+       dev->muted = inw(io) & STR_WREN ? 0 : 1;
        outw(odir, io + IO_DIR);
        outw(~(STR_WREN | STR_CLK), io + IO_MASK);
        outw(dev->muted ? 0 : STR_WREN, io);
index f93d7afe7304c97d1159967f20e5ee130c41f608..c2eeae7a10d02eb37e65f1b430ca3deb959edb38 100644 (file)
  *   0.75b
  *     - better pci interface thanks to Francois Romieu <romieu@cogenit.fr>
  *
- *   0.75
+ *   0.75      Sun Feb  4 22:51:27 EET 2001
  *     - tiding up
  *     - removed support for multiple devices as it didn't work anyway
  *
  * BUGS:
  *   - card unmutes if you change frequency
  *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 
 #include <linux/mutex.h>
 
 #include <linux/pci.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 
-/* version 0.75      Sun Feb  4 22:51:27 EET 2001 */
-#define DRIVER_VERSION "0.75"
+#define DRIVER_VERSION "0.76"
+
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,7,6)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }
+};
 
 #ifndef PCI_VENDOR_ID_GUILLEMOT
 #define PCI_VENDOR_ID_GUILLEMOT 0x5046
@@ -90,7 +104,6 @@ static struct video_device maxiradio_radio =
        .owner          = THIS_MODULE,
        .name           = "Maxi Radio FM2000 radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_SF16MI,
        .fops           = &maxiradio_fops,
 };
 
@@ -176,89 +189,116 @@ static inline int radio_function(struct inode *inode, struct file *file,
        struct radio_device *card=dev->priv;
 
        switch(cmd) {
-               case VIDIOCGCAP: {
-                       struct video_capability *v = arg;
-
+               case VIDIOC_QUERYCAP:
+               {
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       strcpy(v->name, "Maxi Radio FM2000 radio");
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=v->audios=1;
+                       strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver));
+                       strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER: {
-                       struct video_tuner *v = arg;
+               case VIDIOC_G_TUNER:
+               {
+                       struct v4l2_tuner *v = arg;
 
-                       if(v->tuner)
+                       if (v->index > 0)
                                return -EINVAL;
 
-                       card->stereo = 0xffff * get_stereo(card->io);
-                       card->tuned = 0xffff * get_tune(card->io);
-
-                       v->flags = VIDEO_TUNER_LOW | card->stereo;
-                       v->signal = card->tuned;
-
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
-
-                       v->rangelow = FREQ_LO;
-                       v->rangehigh = FREQ_HI;
-                       v->mode = VIDEO_MODE_AUTO;
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow=FREQ_LO;
+                       v->rangehigh=FREQ_HI;
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       if(get_stereo(card->io))
+                               v->audmode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=0xffff*get_tune(card->io);
 
                        return 0;
                }
-               case VIDIOCSTUNER: {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+               case VIDIOC_S_TUNER:
+               {
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       return 0;
-               }
-               case VIDIOCGFREQ: {
-                       unsigned long *freq = arg;
 
-                       *freq = card->freq;
                        return 0;
                }
-               case VIDIOCSFREQ: {
-                       unsigned long *freq = arg;
+               case VIDIOC_S_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
 
-                       if (*freq < FREQ_LO || *freq > FREQ_HI)
+                       if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
                                return -EINVAL;
-                       card->freq = *freq;
+
+                       card->freq = f->frequency;
                        set_freq(card->io, FREQ2BITS(card->freq));
                        msleep(125);
                        return 0;
                }
-               case VIDIOCGAUDIO: {
-                       struct video_audio *v = arg;
-                       memset(v,0,sizeof(*v));
-                       strcpy(v->name, "Radio");
-                       v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
-                       v->mode=VIDEO_SOUND_STEREO;
-                       return 0;
-               }
+               case VIDIOC_G_FREQUENCY:
+               {
+                       struct v4l2_frequency *f = arg;
 
-               case VIDIOCSAUDIO: {
-                       struct video_audio *v = arg;
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = card->freq;
 
-                       if(v->audio)
-                               return -EINVAL;
-                       card->muted = v->flags & VIDEO_AUDIO_MUTE;
-                       if(card->muted)
-                               turn_power(card->io, 0);
-                       else
-                               set_freq(card->io, FREQ2BITS(card->freq));
                        return 0;
                }
-               case VIDIOCGUNIT: {
-                       struct video_unit *v = arg;
-
-                       v->video=VIDEO_NO_UNIT;
-                       v->vbi=VIDEO_NO_UNIT;
-                       v->radio=dev->minor;
-                       v->audio=0;
-                       v->teletext=VIDEO_NO_UNIT;
-                       return 0;
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=card->muted;
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
-               default: return -ENOIOCTLCMD;
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       card->muted = ctrl->value;
+                                       if(card->muted)
+                                               turn_power(card->io, 0);
+                                       else
+                                               set_freq(card->io, FREQ2BITS(card->freq));
+                                       return 0;
+                       }
+                       return -EINVAL;
+               }
+
+               default:
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         radio_function);
+
        }
 }
 
index 5b68ac4c7322e710c112bb787a996ef621f48e04..b9e98483e58d18e9a81c7cb56cd7c9250cd0a1e8 100644 (file)
@@ -6,6 +6,7 @@
  *
  * TODO: Allow for more than one of these foolish entities :-)
  *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>      /* Modules                      */
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_RTRACK2_PORT    */
 #include <linux/spinlock.h>
 
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 65535,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 #ifndef CONFIG_RADIO_RTRACK2_PORT
 #define CONFIG_RADIO_RTRACK2_PORT -1
 #endif
@@ -115,75 +137,120 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
-                       strcpy(v->name, "RadioTrack II");
+                       strlcpy(v->driver, "radio-rtrack2", sizeof (v->driver));
+                       strlcpy(v->card, "RadioTrack II", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       v->rangelow=88*16000;
-                       v->rangehigh=108*16000;
-                       v->flags=VIDEO_TUNER_LOW;
-                       v->mode=VIDEO_MODE_AUTO;
-                       v->signal=0xFFFF*rt_getsigstr(rt);
+
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow=(88*16000);
+                       v->rangehigh=(108*16000);
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=0xFFFF*rt_getsigstr(rt);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
+
                        return 0;
                }
-               case VIDIOCGFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       *freq = rt->curfreq;
+                       struct v4l2_frequency *f = arg;
+
+                       rt->curfreq = f->frequency;
+                       rt_setfreq(rt, rt->curfreq);
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_G_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       rt->curfreq = *freq;
-                       rt_setfreq(rt, rt->curfreq);
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = rt->curfreq;
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags|=VIDEO_AUDIO_MUTABLE;
-                       v->volume=1;
-                       v->step=65535;
-                       strcpy(v->name, "Radio");
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-
-                       if(v->flags&VIDEO_AUDIO_MUTE)
-                               rt_mute(rt);
-                       else
-                               rt_unmute(rt);
-
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=rt->muted;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       if (rt->muted)
+                                               ctrl->value=0;
+                                       else
+                                               ctrl->value=65535;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               rt_mute(rt);
+                                       } else {
+                                               rt_unmute(rt);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       if (ctrl->value) {
+                                               rt_unmute(rt);
+                                       } else {
+                                               rt_mute(rt);
+                                       }
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         rt_do_ioctl);
        }
 }
 
@@ -209,7 +276,7 @@ static struct video_device rtrack2_radio=
        .owner          = THIS_MODULE,
        .name           = "RadioTrack II radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_RTRACK2,
+       .hardware       = 0,
        .fops           = &rtrack2_fops,
 };
 
index efee6e339d15b0b7d7110160640e2c2ca35536e1..ecc854b4ba386d4c241e1195c810f64a7a5d3b49 100644 (file)
  *  No volume control - only mute/unmute - you have to use line volume
  *  control on SB-part of SF16FMI
  *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
+#include <linux/version.h>
 #include <linux/kernel.h>      /* __setup                      */
 #include <linux/module.h>      /* Modules                      */
 #include <linux/init.h>                /* Initdata                     */
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/delay.h>       /* udelay                       */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
 #include <linux/isapnp.h>
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/mutex.h>
 
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }
+};
+
 struct fmi_device
 {
        int port;
@@ -123,93 +138,122 @@ static int fmi_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       strcpy(v->name, "SF16-FMx radio");
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
+                       strlcpy(v->driver, "radio-sf16fmi", sizeof (v->driver));
+                       strlcpy(v->card, "SF16-FMx radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
+                       struct v4l2_tuner *v = arg;
                        int mult;
 
-                       if(v->tuner)    /* Only 1 tuner */
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
-                       mult = (fmi->flags & VIDEO_TUNER_LOW) ? 1 : 1000;
+                       v->type = V4L2_TUNER_RADIO;
+
+                       mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
                        v->rangelow = RSF16_MINFREQ/mult;
                        v->rangehigh = RSF16_MAXFREQ/mult;
-                       v->flags=fmi->flags;
-                       v->mode=VIDEO_MODE_AUTO;
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
+                       v->capability=fmi->flags&V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_STEREO;
                        v->signal = fmi_getsigstr(fmi);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       fmi->flags = v->flags & VIDEO_TUNER_LOW;
-                       /* Only 1 tuner so no setting needed ! */
-                       return 0;
-               }
-               case VIDIOCGFREQ:
-               {
-                       unsigned long *freq = arg;
-                       *freq = fmi->curfreq;
-                       if (!(fmi->flags & VIDEO_TUNER_LOW))
-                           *freq /= 1000;
+
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       if (!(fmi->flags & VIDEO_TUNER_LOW))
-                               *freq *= 1000;
-                       if (*freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ )
+                       struct v4l2_frequency *f = arg;
+
+                       if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
+                               f->frequency *= 1000;
+                       if (f->frequency < RSF16_MINFREQ ||
+                                       f->frequency > RSF16_MAXFREQ )
                                return -EINVAL;
                        /*rounding in steps of 800 to match th freq
                          that will be used */
-                       fmi->curfreq = (*freq/800)*800;
+                       fmi->curfreq = (f->frequency/800)*800;
                        fmi_setfreq(fmi);
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_G_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0,sizeof(*v));
-                       v->flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
-                       strcpy(v->name, "Radio");
-                       v->mode=VIDEO_SOUND_STEREO;
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = fmi->curfreq;
+                       if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
+                               f->frequency /= 1000;
+
                        return 0;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-                       fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1;
-                       fmi->curvol ?
-                               fmi_unmute(fmi->port) : fmi_mute(fmi->port);
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-               case VIDIOCGUNIT:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_unit *v = arg;
-                       v->video=VIDEO_NO_UNIT;
-                       v->vbi=VIDEO_NO_UNIT;
-                       v->radio=dev->minor;
-                       v->audio=0; /* How do we find out this??? */
-                       v->teletext=VIDEO_NO_UNIT;
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=fmi->curvol;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                               {
+                                       if (ctrl->value)
+                                               fmi_mute(fmi->port);
+                                       else
+                                               fmi_unmute(fmi->port);
+
+                                       fmi->curvol=ctrl->value;
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         fmi_do_ioctl);
        }
 }
 
@@ -235,7 +279,7 @@ static struct video_device fmi_radio=
        .owner          = THIS_MODULE,
        .name           = "SF16FMx radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_SF16MI,
+       .hardware       = 0,
        .fops           = &fmi_fops,
 };
 
@@ -294,7 +338,7 @@ static int __init fmi_init(void)
        fmi_unit.port = io;
        fmi_unit.curvol = 0;
        fmi_unit.curfreq = 0;
-       fmi_unit.flags = VIDEO_TUNER_LOW;
+       fmi_unit.flags = V4L2_TUNER_CAP_LOW;
        fmi_radio.priv = &fmi_unit;
 
        mutex_init(&lock);
index 3483b2c7bc9d70488c26cb99b9a2f696192c03e2..4444dce864a932ddeaad7ec8790ca42354d5c9bd 100644 (file)
@@ -10,6 +10,8 @@
  *  For read stereo/mono you must wait 0.1 sec after set frequency and
  *  card unmuted so I set frequency on unmute
  *  Signal handling seem to work only on autoscanning (not implemented)
+ *
+ *  Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>      /* Modules                      */
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 static struct mutex lock;
 
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 1<<12,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 #undef DEBUG
 //#define DEBUG 1
 
@@ -214,63 +238,65 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       strcpy(v->name, "SF16-FMR2 radio");
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
+                       strlcpy(v->driver, "radio-sf16fmr2", sizeof (v->driver));
+                       strlcpy(v->card, "SF16-FMR2 radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
+                       struct v4l2_tuner *v = arg;
                        int mult;
 
-                       if(v->tuner)     /* Only 1 tuner */
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
-                       mult = (fmr2->flags & VIDEO_TUNER_LOW) ? 1 : 1000;
+                       v->type = V4L2_TUNER_RADIO;
+
+                       mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
                        v->rangelow = RSF16_MINFREQ/mult;
                        v->rangehigh = RSF16_MAXFREQ/mult;
-                       v->flags = fmr2->flags | VIDEO_AUDIO_MUTABLE;
-                       if (fmr2->mute)
-                               v->flags |= VIDEO_AUDIO_MUTE;
-                       v->mode=VIDEO_MODE_AUTO;
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
+                       v->capability=fmr2->flags&V4L2_TUNER_CAP_LOW;
+
+                       v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
+                                                   V4L2_TUNER_MODE_MONO;
                        mutex_lock(&lock);
                        v->signal = fmr2_getsigstr(fmr2);
                        mutex_unlock(&lock);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if (v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       fmr2->flags = v->flags & VIDEO_TUNER_LOW;
-                       return 0;
-               }
-               case VIDIOCGFREQ:
-               {
-                       unsigned long *freq = arg;
-                       *freq = fmr2->curfreq;
-                       if (!(fmr2->flags & VIDEO_TUNER_LOW))
-                               *freq /= 1000;
+
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       if (!(fmr2->flags & VIDEO_TUNER_LOW))
-                               *freq *= 1000;
-                       if ( *freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ )
+                       struct v4l2_frequency *f = arg;
+
+                       if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
+                               f->frequency *= 1000;
+                       if (f->frequency < RSF16_MINFREQ ||
+                                       f->frequency > RSF16_MAXFREQ )
                                return -EINVAL;
-                       /* rounding in steps of 200 to match th freq
-                        * that will be used
-                        */
-                       fmr2->curfreq = (*freq/200)*200;
+                       /*rounding in steps of 200 to match th freq
+                         that will be used */
+                       fmr2->curfreq = (f->frequency/200)*200;
 
                        /* set card freq (if not muted) */
                        if (fmr2->curvol && !fmr2->mute)
@@ -279,40 +305,81 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
                                fmr2_setfreq(fmr2);
                                mutex_unlock(&lock);
                        }
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_G_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0,sizeof(*v));
-                       /* !!! do not return VIDEO_AUDIO_MUTE */
-                       v->flags = VIDEO_AUDIO_MUTABLE;
-                       strcpy(v->name, "Radio");
-                       /* get current stereo mode */
-                       v->mode = fmr2->stereo ? VIDEO_SOUND_STEREO: VIDEO_SOUND_MONO;
-                       /* volume supported ? */
-                       if (fmr2->card_type == 11)
-                       {
-                               v->flags |= VIDEO_AUDIO_VOLUME;
-                               v->step = 1 << 12;
-                               v->volume = fmr2->curvol;
-                       }
-                       debug_print((KERN_DEBUG "Get flags %d vol %d\n", v->flags, v->volume));
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = fmr2->curfreq;
+                       if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
+                               f->frequency /= 1000;
+
                        return 0;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-                       debug_print((KERN_DEBUG "Set flags %d vol %d\n", v->flags, v->volume));
-                       /* set volume */
-                       if (v->flags & VIDEO_AUDIO_VOLUME)
-                               fmr2->curvol = v->volume; /* !!! set with precision */
-                       if (fmr2->card_type != 11) fmr2->curvol = 65535;
-                       fmr2->mute = 0;
-                       if (v->flags & VIDEO_AUDIO_MUTE)
-                               fmr2->mute = 1;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if ((fmr2->card_type != 11)
+                                               && V4L2_CID_AUDIO_VOLUME)
+                                       radio_qctrl[i].step=65535;
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=fmr2->mute;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value=fmr2->curvol;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       fmr2->mute=ctrl->value;
+                                       if (fmr2->card_type != 11) {
+                                               if (!fmr2->mute) {
+                                                       fmr2->curvol = 65535;
+                                               } else {
+                                                       fmr2->curvol = 0;
+                                               }
+                                       }
+                                       break;
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       fmr2->curvol = ctrl->value;
+                                       if (fmr2->card_type != 11) {
+                                               if (fmr2->curvol) {
+                                                       fmr2->curvol = 65535;
+                                                       fmr2->mute = 0;
+                                               } else {
+                                                       fmr2->curvol = 0;
+                                                       fmr2->mute = 1;
+                                               }
+                                       }
+                                       break;
+                               default:
+                                       return -EINVAL;
+                       }
 #ifdef DEBUG
                        if (fmr2->curvol && !fmr2->mute)
                                printk(KERN_DEBUG "unmute\n");
@@ -320,27 +387,18 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
                                printk(KERN_DEBUG "mute\n");
 #endif
                        mutex_lock(&lock);
-                       if (fmr2->curvol && !fmr2->mute)
-                       {
+                       if (fmr2->curvol && !fmr2->mute) {
                                fmr2_setvolume(fmr2);
                                fmr2_setfreq(fmr2);
-                       }
-                       else fmr2_mute(fmr2->port);
+                       } else
+                               fmr2_mute(fmr2->port);
                        mutex_unlock(&lock);
-                       return 0;
-               }
-               case VIDIOCGUNIT:
-               {
-                       struct video_unit *v = arg;
-                       v->video=VIDEO_NO_UNIT;
-                       v->vbi=VIDEO_NO_UNIT;
-                       v->radio=dev->minor;
-                       v->audio=0; /* How do we find out this??? */
-                       v->teletext=VIDEO_NO_UNIT;
-                       return 0;
+                       return (0);
                }
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         fmr2_do_ioctl);
+
        }
 }
 
@@ -366,7 +424,7 @@ static struct video_device fmr2_radio=
        .owner          = THIS_MODULE,
        .name           = "SF16FMR2 radio",
        . type          = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_SF16FMR2,
+       .hardware       = 0,
        .fops           = &fmr2_fops,
 };
 
@@ -377,7 +435,7 @@ static int __init fmr2_init(void)
        fmr2_unit.mute = 0;
        fmr2_unit.curfreq = 0;
        fmr2_unit.stereo = 1;
-       fmr2_unit.flags = VIDEO_TUNER_LOW;
+       fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
        fmr2_unit.card_type = 0;
        fmr2_radio.priv = &fmr2_unit;
 
@@ -396,7 +454,6 @@ static int __init fmr2_init(void)
        }
 
        printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io);
-       debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW));
        /* mute card - prevents noisy bootups */
        mutex_lock(&lock);
        fmr2_mute(io);
index dfba4ae596cd342abb3e737234274d4488ae4e23..f539491a0d76f31e7cdfa874a075c8e24e71a043 100644 (file)
@@ -21,6 +21,7 @@
  *  If you can help me out with that, please contact me!!
  *
  *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>      /* Modules                      */
 #include <linux/delay.h>       /* udelay                       */
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
-#include <linux/videodev.h>    /* kernel radio structs         */
+#include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_TERRATEC_PORT   */
 #include <linux/spinlock.h>
 
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 #ifndef CONFIG_RADIO_TERRATEC_PORT
 #define CONFIG_RADIO_TERRATEC_PORT 0x590
 #endif
@@ -194,73 +216,117 @@ static int tt_do_ioctl(struct inode *inode, struct file *file,
 
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
-                       strcpy(v->name, "ActiveRadio");
+                       strlcpy(v->driver, "radio-terratec", sizeof (v->driver));
+                       strlcpy(v->card, "ActiveRadio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
                        v->rangelow=(87*16000);
                        v->rangehigh=(108*16000);
-                       v->flags=VIDEO_TUNER_LOW;
-                       v->mode=VIDEO_MODE_AUTO;
-                       strcpy(v->name, "FM");
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_MONO;
                        v->signal=0xFFFF*tt_getsigstr(tt);
+
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner!=0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
+
                        return 0;
                }
-               case VIDIOCGFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       *freq = tt->curfreq;
+                       struct v4l2_frequency *f = arg;
+
+                       tt->curfreq = f->frequency;
+                       tt_setfreq(tt, tt->curfreq);
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_G_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       tt->curfreq = *freq;
-                       tt_setfreq(tt, tt->curfreq);
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = tt->curfreq;
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-                       memset(v,0, sizeof(*v));
-                       v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
-                       v->volume=tt->curvol * 6554;
-                       v->step=6554;
-                       strcpy(v->name, "Radio");
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *v = arg;
-                       if(v->audio)
-                               return -EINVAL;
-                       if(v->flags&VIDEO_AUDIO_MUTE)
-                               tt_mute(tt);
-                       else
-                               tt_setvol(tt,v->volume/6554);
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (tt->muted)
+                                               ctrl->value=1;
+                                       else
+                                               ctrl->value=0;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value=tt->curvol * 6554;
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               tt_mute(tt);
+                                       } else {
+                                               tt_setvol(tt,tt->curvol);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       tt_setvol(tt,ctrl->value);
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         tt_do_ioctl);
        }
 }
 
@@ -286,7 +352,7 @@ static struct video_device terratec_radio=
        .owner          = THIS_MODULE,
        .name           = "TerraTec ActiveRadio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_TERRATEC,
+       .hardware       = 0,
        .fops           = &terratec_fops,
 };
 
index 8da4badc22b47f399ae8c3ce3f9e80e60a3f127c..bb03ad5a2033bdb117671ef50d30ba6b72fa8692 100644 (file)
@@ -12,7 +12,7 @@
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
- * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <stdarg.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_TRUST_PORT      */
+
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 2048,
+               .default_value = 65535,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_AUDIO_BASS,
+               .name          = "Bass",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 4370,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_AUDIO_TREBLE,
+               .name          = "Treble",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 4370,
+               .default_value = 32768,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },
+};
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
 
@@ -160,88 +197,125 @@ static int tr_do_ioctl(struct inode *inode, struct file *file,
 {
        switch(cmd)
        {
-               case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
-
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type=VID_TYPE_TUNER;
-                       v->channels=1;
-                       v->audios=1;
-                       strcpy(v->name, "Trust FM Radio");
+                       strlcpy(v->driver, "radio-trust", sizeof (v->driver));
+                       strlcpy(v->card, "Trust FM Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
 
                        return 0;
                }
-               case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
+                       struct v4l2_tuner *v = arg;
 
-                       if(v->tuner)    /* Only 1 tuner */
+                       if (v->index > 0)
                                return -EINVAL;
 
-                       v->rangelow = 87500 * 16;
-                       v->rangehigh = 108000 * 16;
-                       v->flags = VIDEO_TUNER_LOW;
-                       v->mode = VIDEO_MODE_AUTO;
+                       memset(v,0,sizeof(*v));
+                       strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
 
-                       v->signal = tr_getsigstr();
+                       v->rangelow=(87.5*16000);
+                       v->rangehigh=(108*16000);
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
                        if(tr_getstereo())
-                               v->flags |= VIDEO_TUNER_STEREO_ON;
-
-                       strcpy(v->name, "FM");
+                               v->audmode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=tr_getsigstr();
 
                        return 0;
                }
-               case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if(v->tuner != 0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
+
                        return 0;
                }
-               case VIDIOCGFREQ:
+               case VIDIOC_S_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       *freq = curfreq;
+                       struct v4l2_frequency *f = arg;
+
+                       curfreq = f->frequency;
+                       tr_setfreq(curfreq);
                        return 0;
                }
-               case VIDIOCSFREQ:
+               case VIDIOC_G_FREQUENCY:
                {
-                       unsigned long *freq = arg;
-                       tr_setfreq(*freq);
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = curfreq;
+
                        return 0;
                }
-               case VIDIOCGAUDIO:
+               case VIDIOC_QUERYCTRL:
                {
-                       struct video_audio *v = arg;
-
-                       memset(v,0, sizeof(*v));
-                       v->flags = VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME |
-                                 VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;
-                       v->mode = curstereo? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
-                       v->volume = curvol * 2048;
-                       v->step = 2048;
-                       v->bass = curbass * 4370;
-                       v->treble = curtreble * 4370;
-
-                       strcpy(v->name, "Trust FM Radio");
-                       return 0;
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
                }
-               case VIDIOCSAUDIO:
+               case VIDIOC_G_CTRL:
                {
-                       struct video_audio *v = arg;
-
-                       if(v->audio)
-                               return -EINVAL;
-                       tr_setvol(v->volume);
-                       tr_setbass(v->bass);
-                       tr_settreble(v->treble);
-                       tr_setstereo(v->mode & VIDEO_SOUND_STEREO);
-                       tr_setmute(v->flags & VIDEO_AUDIO_MUTE);
-                       return 0;
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=curmute;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value= curvol * 2048;
+                                       return (0);
+                               case V4L2_CID_AUDIO_BASS:
+                                       ctrl->value= curbass * 4370;
+                                       return (0);
+                               case V4L2_CID_AUDIO_TREBLE:
+                                       ctrl->value= curtreble * 4370;
+                                       return (0);
+                       }
+                       return -EINVAL;
                }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       tr_setmute(ctrl->value);
+                                       return 0;
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       tr_setvol(ctrl->value);
+                                       return 0;
+                               case V4L2_CID_AUDIO_BASS:
+                                       tr_setbass(ctrl->value);
+                                       return 0;
+                               case V4L2_CID_AUDIO_TREBLE:
+                                       tr_settreble(ctrl->value);
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+
                default:
-                       return -ENOIOCTLCMD;
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         tr_do_ioctl);
        }
 }
 
@@ -265,7 +339,7 @@ static struct video_device trust_radio=
        .owner          = THIS_MODULE,
        .name           = "Trust FM Radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_TRUST,
+       .hardware       = 0,
        .fops           = &trust_fops,
 };
 
index edd0122886693183f89245d799131869be0c0475..4a72b4d4e62a70b7c174e6cdac0252f96d84e33a 100644 (file)
@@ -27,6 +27,8 @@
  * value where I do expect just noise and turn the speaker volume down.
  * The frequency change is necessary since the card never seems to be
  * completely silent.
+ *
+ * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>      /* Modules                        */
 #include <linux/proc_fs.h>     /* radio card status report       */
 #include <asm/io.h>            /* outb, outb_p                   */
 #include <asm/uaccess.h>       /* copy to/from user              */
-#include <linux/videodev.h>    /* kernel radio structs           */
+#include <linux/videodev2.h>   /* kernel radio structs           */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_TYPHOON_*         */
 
-#define BANNER "Typhoon Radio Card driver v0.1\n"
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,1,1)
+#define BANNER "Typhoon Radio Card driver v0.1.1\n"
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 1<<14,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
 
 #ifndef CONFIG_RADIO_TYPHOON_PORT
 #define CONFIG_RADIO_TYPHOON_PORT -1
@@ -171,76 +194,114 @@ static int typhoon_do_ioctl(struct inode *inode, struct file *file,
        struct typhoon_device *typhoon = dev->priv;
 
        switch (cmd) {
-       case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type = VID_TYPE_TUNER;
-                       v->channels = 1;
-                       v->audios = 1;
-                       strcpy(v->name, "Typhoon Radio");
+                       strlcpy(v->driver, "radio-typhoon", sizeof (v->driver));
+                       strlcpy(v->card, "Typhoon Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-       case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if (v->tuner)   /* Only 1 tuner */
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       v->rangelow = 875 * 1600;
-                       v->rangehigh = 1080 * 1600;
-                       v->flags = VIDEO_TUNER_LOW;
-                       v->mode = VIDEO_MODE_AUTO;
-                       v->signal = 0xFFFF;     /* We can't get the signal strength */
+
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow=(87.5*16000);
+                       v->rangehigh=(108*16000);
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal = 0xFFFF;     /* We can't get the signal strength */
+
                        return 0;
                }
-       case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if (v->tuner != 0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
+
                        return 0;
                }
-       case VIDIOCGFREQ:
-       {
-               unsigned long *freq = arg;
-               *freq = typhoon->curfreq;
-               return 0;
-       }
-       case VIDIOCSFREQ:
-       {
-               unsigned long *freq = arg;
-               typhoon->curfreq = *freq;
-               typhoon_setfreq(typhoon, typhoon->curfreq);
-               return 0;
-       }
-       case VIDIOCGAUDIO:
+               case VIDIOC_S_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       memset(v, 0, sizeof(*v));
-                       v->flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
-                       v->mode |= VIDEO_SOUND_MONO;
-                       v->volume = typhoon->curvol;
-                       v->step = 1 << 14;
-                       strcpy(v->name, "Typhoon Radio");
+                       struct v4l2_frequency *f = arg;
+
+                       typhoon->curfreq = f->frequency;
+                       typhoon_setfreq(typhoon, typhoon->curfreq);
                        return 0;
                }
-       case VIDIOCSAUDIO:
+               case VIDIOC_G_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       if (v->audio)
-                               return -EINVAL;
-                       if (v->flags & VIDEO_AUDIO_MUTE)
-                               typhoon_mute(typhoon);
-                       else
-                               typhoon_unmute(typhoon);
-                       if (v->flags & VIDEO_AUDIO_VOLUME)
-                               typhoon_setvol(typhoon, v->volume);
+                       struct v4l2_frequency *f = arg;
+
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = typhoon->curfreq;
+
                        return 0;
                }
-       default:
-               return -ENOIOCTLCMD;
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=typhoon->muted;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value=typhoon->curvol;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               typhoon_mute(typhoon);
+                                       } else {
+                                               typhoon_unmute(typhoon);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       typhoon_setvol(typhoon, ctrl->value);
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+
+               default:
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         typhoon_do_ioctl);
        }
 }
 
@@ -271,7 +332,7 @@ static struct video_device typhoon_radio =
        .owner          = THIS_MODULE,
        .name           = "Typhoon Radio",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_TYPHOON,
+       .hardware       = 0,
        .fops           = &typhoon_fops,
 };
 
index 59b86a6b4b0e745a008276ede9a2a1d50e30e260..671fe1b1e5bcec6a028c71804699db75dfb976d4 100644 (file)
@@ -24,6 +24,9 @@
  *           - Added unmute function
  *           - Reworked ioctl functions
  * 2002-07-15 - Fix Stereo typo
+ *
+ * 2006-07-24 - Converted to V4L2 API
+ *             by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
 
 #include <linux/module.h>      /* Modules                        */
 #include <linux/delay.h>       /* udelay, msleep                 */
 #include <asm/io.h>            /* outb, outb_p                   */
 #include <asm/uaccess.h>       /* copy to/from user              */
-#include <linux/videodev.h>    /* kernel radio structs           */
+#include <linux/videodev2.h>   /* kernel radio structs           */
 #include <media/v4l2-common.h>
-#include <linux/config.h>      /* CONFIG_RADIO_ZOLTRIX_PORT      */
+
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = 0,
+               .maximum       = 65535,
+               .step          = 4096,
+               .default_value = 0xff,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
 
 #ifndef CONFIG_RADIO_ZOLTRIX_PORT
 #define CONFIG_RADIO_ZOLTRIX_PORT -1
@@ -213,78 +237,116 @@ static int zol_do_ioctl(struct inode *inode, struct file *file,
        struct zol_device *zol = dev->priv;
 
        switch (cmd) {
-       case VIDIOCGCAP:
+               case VIDIOC_QUERYCAP:
                {
-                       struct video_capability *v = arg;
-
+                       struct v4l2_capability *v = arg;
                        memset(v,0,sizeof(*v));
-                       v->type = VID_TYPE_TUNER;
-                       v->channels = 1 + zol->stereo;
-                       v->audios = 1;
-                       strcpy(v->name, "Zoltrix Radio");
+                       strlcpy(v->driver, "radio-zoltrix", sizeof (v->driver));
+                       strlcpy(v->card, "Zoltrix Radio", sizeof (v->card));
+                       sprintf(v->bus_info,"ISA");
+                       v->version = RADIO_VERSION;
+                       v->capabilities = V4L2_CAP_TUNER;
+
                        return 0;
                }
-       case VIDIOCGTUNER:
+               case VIDIOC_G_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if (v->tuner)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
+
+                       memset(v,0,sizeof(*v));
                        strcpy(v->name, "FM");
-                       v->rangelow = (int) (88.0 * 16000);
-                       v->rangehigh = (int) (108.0 * 16000);
-                       v->flags = zol_is_stereo(zol)
-                                       ? VIDEO_TUNER_STEREO_ON : 0;
-                       v->flags |= VIDEO_TUNER_LOW;
-                       v->mode = VIDEO_MODE_AUTO;
-                       v->signal = 0xFFFF * zol_getsigstr(zol);
+                       v->type = V4L2_TUNER_RADIO;
+
+                       v->rangelow=(88*16000);
+                       v->rangehigh=(108*16000);
+                       v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+                       v->capability=V4L2_TUNER_CAP_LOW;
+                       if(zol_is_stereo(zol))
+                               v->audmode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               v->audmode = V4L2_TUNER_MODE_MONO;
+                       v->signal=0xFFFF*zol_getsigstr(zol);
+
                        return 0;
                }
-       case VIDIOCSTUNER:
+               case VIDIOC_S_TUNER:
                {
-                       struct video_tuner *v = arg;
-                       if (v->tuner != 0)
+                       struct v4l2_tuner *v = arg;
+
+                       if (v->index > 0)
                                return -EINVAL;
-                       /* Only 1 tuner so no setting needed ! */
+
                        return 0;
                }
-       case VIDIOCGFREQ:
-       {
-               unsigned long *freq = arg;
-               *freq = zol->curfreq;
-               return 0;
-       }
-       case VIDIOCSFREQ:
-       {
-               unsigned long *freq = arg;
-               zol->curfreq = *freq;
-               zol_setfreq(zol, zol->curfreq);
-               return 0;
-       }
-       case VIDIOCGAUDIO:
+               case VIDIOC_S_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       memset(v, 0, sizeof(*v));
-                       v->flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
-                       v->mode |= zol_is_stereo(zol)
-                               ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
-                       v->volume = zol->curvol * 4096;
-                       v->step = 4096;
-                       strcpy(v->name, "Zoltrix Radio");
+                       struct v4l2_frequency *f = arg;
+
+                       zol->curfreq = f->frequency;
+                       zol_setfreq(zol, zol->curfreq);
                        return 0;
                }
-       case VIDIOCSAUDIO:
+               case VIDIOC_G_FREQUENCY:
                {
-                       struct video_audio *v = arg;
-                       if (v->audio)
-                               return -EINVAL;
+                       struct v4l2_frequency *f = arg;
 
-                       if (v->flags & VIDEO_AUDIO_MUTE)
-                               zol_mute(zol);
-                       else {
-                               zol_unmute(zol);
-                               zol_setvol(zol, v->volume / 4096);
-                       }
+                       f->type = V4L2_TUNER_RADIO;
+                       f->frequency = zol->curfreq;
 
+                       return 0;
+               }
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+                               if (qc->id && qc->id == radio_qctrl[i].id) {
+                                       memcpy(qc, &(radio_qctrl[i]),
+                                                               sizeof(*qc));
+                                       return (0);
+                               }
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       ctrl->value=zol->muted;
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       ctrl->value=zol->curvol * 4096;
+                                       return (0);
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *ctrl= arg;
+
+                       switch (ctrl->id) {
+                               case V4L2_CID_AUDIO_MUTE:
+                                       if (ctrl->value) {
+                                               zol_mute(zol);
+                                       } else {
+                                               zol_unmute(zol);
+                                               zol_setvol(zol,zol->curvol);
+                                       }
+                                       return (0);
+                               case V4L2_CID_AUDIO_VOLUME:
+                                       zol_setvol(zol,ctrl->value/4096);
+                                       return (0);
+                       }
+                       zol->stereo = 1;
+                       zol_setfreq(zol, zol->curfreq);
+#if 0
+/* FIXME: Implement stereo/mono switch on V4L2 */
                        if (v->mode & VIDEO_SOUND_STEREO) {
                                zol->stereo = 1;
                                zol_setfreq(zol, zol->curfreq);
@@ -293,10 +355,13 @@ static int zol_do_ioctl(struct inode *inode, struct file *file,
                                zol->stereo = 0;
                                zol_setfreq(zol, zol->curfreq);
                        }
-                       return 0;
+#endif
+                       return -EINVAL;
                }
-       default:
-               return -ENOIOCTLCMD;
+
+               default:
+                       return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+                                                         zol_do_ioctl);
        }
 }
 
@@ -323,7 +388,7 @@ static struct video_device zoltrix_radio =
        .owner          = THIS_MODULE,
        .name           = "Zoltrix Radio Plus",
        .type           = VID_TYPE_TUNER,
-       .hardware       = VID_HARDWARE_ZOLTRIX,
+       .hardware       = 0,
        .fops           = &zoltrix_fops,
 };
 
index 94d078b77bab4a7373f5dc278e4921a2a2c10700..d1183c9392217666abaa9f638c071d153097058b 100644 (file)
@@ -16,6 +16,320 @@ config VIDEO_ADV_DEBUG
          V4L devices.
          In doubt, say N.
 
+config VIDEO_HELPER_CHIPS_AUTO
+       bool "Autoselect pertinent encoders/decoders and other helper chips"
+       default y
+       ---help---
+         Most video cards may require additional modules to encode or
+         decode audio/video standards. This option will autoselect
+         all pertinent modules to each selected video module.
+
+         Unselect this only if you know exaclty what you are doing, since
+         it may break support on some boards.
+
+         In doubt, say Y.
+
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders/decoders and other helper chips"
+       depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO
+
+comment "Audio Decoders"
+
+config VIDEO_TVAUDIO
+       tristate "Simple audio decoder chips"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for several audio decoder chips found on some bt8xx boards:
+         Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
+                  tea6320, tea6420, tda8425, ta8874z.
+         Microchip: pic16c54 based design on ProVideo PV951 board.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvaudio.
+
+config VIDEO_TDA7432
+       tristate "Philips TDA7432 audio processor chip"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for tda7432 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda7432.
+
+config VIDEO_TDA9840
+       tristate "Philips TDA9840 audio processor chip"
+       depends on VIDEO_DEV && I2C
+       ---help---
+         Support for tda9840 audio decoder chip found on some Zoran boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda9840.
+
+config VIDEO_TDA9875
+       tristate "Philips TDA9875 audio processor chip"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for tda9875 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda9875.
+
+config VIDEO_TEA6415C
+       tristate "Philips TEA6415C audio processor chip"
+       depends on VIDEO_DEV && I2C
+       ---help---
+         Support for tea6415c audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tea6415c.
+
+config VIDEO_TEA6420
+       tristate "Philips TEA6420 audio processor chip"
+       depends on VIDEO_DEV && I2C
+       ---help---
+         Support for tea6420 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tea6420.
+
+config VIDEO_MSP3400
+       tristate "Micronas MSP34xx audio decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Micronas MSP34xx series of audio decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called msp3400.
+
+config VIDEO_CS53L32A
+       tristate "Cirrus Logic CS53L32A audio ADC"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Cirrus Logic CS53L32A low voltage
+         stereo A/D converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cs53l32a.
+
+config VIDEO_TLV320AIC23B
+       tristate "Texas Instruments TLV320AIC23B audio codec"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Texas Instruments TLV320AIC23B audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tlv320aic23b.
+
+config VIDEO_WM8775
+       tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Wolfson Microelectronics WM8775 high
+         performance stereo A/D Converter with a 4 channel input mixer.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm8775.
+
+config VIDEO_WM8739
+       tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Wolfson Microelectronics WM8739
+         stereo A/D Converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm8739.
+
+comment "MPEG video encoders"
+
+config VIDEO_CX2341X
+       tristate "Conexant CX2341x MPEG encoders"
+       depends on VIDEO_V4L2 && EXPERIMENTAL
+       ---help---
+         Support for the Conexant CX23416 MPEG encoders
+         and CX23415 MPEG encoder/decoders.
+
+         This module currently supports the encoding functions only.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx2341x.
+
+source "drivers/media/video/cx25840/Kconfig"
+
+comment "Video encoders"
+
+config VIDEO_SAA7127
+       tristate "Philips SAA7127/9 digital video encoders"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Philips SAA7127/9 digital video encoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7127.
+
+config VIDEO_SAA7185
+       tristate "Philips SAA7185 video encoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for the Philips SAA7185 video encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7185.
+
+config VIDEO_ADV7170
+       tristate "Analog Devices ADV7170 video encoder driver"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for the Analog Devices ADV7170 video encoder driver
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7170.
+
+config VIDEO_ADV7175
+       tristate "Analog Devices ADV7175 video encoder driver"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for the Analog Devices ADV7175 video encoder driver
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7175.
+
+comment "Video decoders"
+
+config VIDEO_BT819
+       tristate "BT819A VideoStream Decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for BT819A video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt819.
+
+config VIDEO_BT856
+       tristate "BT856 VideoStream Decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for BT856 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt856.
+
+config VIDEO_BT866
+       tristate "BT866 VideoStream Decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for BT866 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt866.
+
+config VIDEO_KS0127
+       tristate "KS0127 video decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for KS0127 video decoder.
+
+         This chip is used on AverMedia AVS6EYES Zoran-based MJPEG
+         cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ks0127.
+
+config VIDEO_SAA7110
+       tristate "Philips SAA7110 video decoder"
+       depends on VIDEO_V4L1
+       ---help---
+         Support for the Philips SAA7110 video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7110.
+
+config VIDEO_SAA7111
+       tristate "Philips SAA7111 video decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for the Philips SAA711 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7111.
+
+config VIDEO_SAA7114
+       tristate "Philips SAA7114 video decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for the Philips SAA7114 video decoder. This driver
+         is used only on Zoran driver and should be moved soon to
+         SAA711x module.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7114.
+
+config VIDEO_SAA711X
+       tristate "Philips SAA7113/4/5 video decoders"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Philips SAA7113/4/5 video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7115.
+
+config VIDEO_SAA7191
+       tristate "Philips SAA7191 video decoder"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for the Philips SAA7191 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7191.
+
+config VIDEO_TVP5150
+       tristate "Texas Instruments TVP5150 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TVP5150 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp5150.
+
+config VIDEO_VPX3220
+       tristate "vpx3220a, vpx3216b & vpx3214c video decoder driver"
+       depends on VIDEO_V4L1 && I2C
+       ---help---
+         Support for VPX322x video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vpx3220.
+
+comment "Video improvement chips"
+
+config VIDEO_UPD64031A
+       tristate "NEC Electronics uPD64031A Ghost Reduction"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the NEC Electronics uPD64031A Ghost Reduction
+         video chip. It is most often found in NTSC TV cards made for
+         Japan and is used to reduce the 'ghosting' effect that can
+         be present in analog TV broadcasts.
+
+         To compile this driver as a module, choose M here: the
+         module will be called upd64031a.
+
+config VIDEO_UPD64083
+       tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       ---help---
+         Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+         separation video chip. It is used to improve the quality of
+         the colors of a composite signal.
+
+         To compile this driver as a module, choose M here: the
+         module will be called upd64083.
+
+endmenu # encoder / decoder chips
+
 config VIDEO_VIVI
        tristate "Virtual Video Driver"
        depends on VIDEO_V4L2 && !SPARC32 && !SPARC64
@@ -135,7 +449,7 @@ source "drivers/media/video/cpia2/Kconfig"
 
 config VIDEO_SAA5246A
        tristate "SAA5246A, SAA5281 Teletext processor"
-       depends on I2C && VIDEO_V4L1
+       depends on I2C && VIDEO_V4L2
        help
          Support for I2C bus based teletext using the SAA5246A or SAA5281
          chip. Useful only if you live in Europe.
@@ -145,7 +459,7 @@ config VIDEO_SAA5246A
 
 config VIDEO_SAA5249
        tristate "SAA5249 Teletext processor"
-       depends on VIDEO_DEV && I2C && VIDEO_V4L1
+       depends on VIDEO_DEV && I2C && VIDEO_V4L2
        help
          Support for I2C bus based teletext using the SAA5249 chip. At the
          moment this is only useful on some European WinTV cards.
@@ -162,8 +476,9 @@ config TUNER_3036
 
 config VIDEO_VINO
        tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
-       depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L1
+       depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
        select I2C_ALGO_SGI
+       select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO
        help
          Say Y here to build in support for the Vino video input system found
          on SGI Indy machines.
@@ -176,6 +491,9 @@ config VIDEO_STRADIS
          driver for PCI.  There is a product page at
          <http://www.stradis.com/>.
 
+config VIDEO_ZORAN_ZR36060
+       tristate
+
 config VIDEO_ZORAN
        tristate "Zoran ZR36057/36067 Video For Linux"
        depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && !PPC64
@@ -192,12 +510,18 @@ config VIDEO_ZORAN
 config VIDEO_ZORAN_BUZ
        tristate "Iomega Buz support"
        depends on VIDEO_ZORAN
+       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ZORAN_ZR36060
        help
          Support for the Iomega Buz MJPEG capture/playback card.
 
 config VIDEO_ZORAN_DC10
        tristate "Pinnacle/Miro DC10(+) support"
        depends on VIDEO_ZORAN
+       select VIDEO_SAA7110
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ZORAN_ZR36060
        help
          Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
          card.
@@ -205,6 +529,8 @@ config VIDEO_ZORAN_DC10
 config VIDEO_ZORAN_DC30
        tristate "Pinnacle/Miro DC30(+) support"
        depends on VIDEO_ZORAN
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
        help
          Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
          card. This also supports really old DC10 cards based on the
@@ -213,6 +539,9 @@ config VIDEO_ZORAN_DC30
 config VIDEO_ZORAN_LML33
        tristate "Linux Media Labs LML33 support"
        depends on VIDEO_ZORAN
+       select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ZORAN_ZR36060
        help
          Support for the Linux Media Labs LML33 MJPEG capture/playback
          card.
@@ -220,6 +549,9 @@ config VIDEO_ZORAN_LML33
 config VIDEO_ZORAN_LML33R10
        tristate "Linux Media Labs LML33R10 support"
        depends on VIDEO_ZORAN
+       select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ZORAN_ZR36060
        help
          support for the Linux Media Labs LML33R10 MJPEG capture/playback
          card.
@@ -227,6 +559,9 @@ config VIDEO_ZORAN_LML33R10
 config VIDEO_ZORAN_AVS6EYES
        tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
        depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1
+       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ZORAN_ZR36060
        help
          Support for the AverMedia 6 Eyes video surveillance card.
 
@@ -263,6 +598,10 @@ config VIDEO_MXB
        depends on PCI && VIDEO_V4L1 && I2C
        select VIDEO_SAA7146_VV
        select VIDEO_TUNER
+       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          This is a video4linux driver for the 'Multimedia eXtension Board'
          TV card by Siemens-Nixdorf.
@@ -274,7 +613,7 @@ config VIDEO_DPC
        tristate "Philips-Semiconductors 'dpc7146 demonstration board'"
        depends on PCI && VIDEO_V4L1 && I2C
        select VIDEO_SAA7146_VV
-       select VIDEO_V4L2
+       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          This is a video4linux driver for the 'dpc7146 demonstration
          board' by Philips-Semiconductors. It's the reference design
@@ -287,9 +626,8 @@ config VIDEO_DPC
 
 config VIDEO_HEXIUM_ORION
        tristate "Hexium HV-PCI6 and Orion frame grabber"
-       depends on PCI && VIDEO_V4L1 && I2C
+       depends on PCI && VIDEO_V4L2 && I2C
        select VIDEO_SAA7146_VV
-       select VIDEO_V4L2
        ---help---
          This is a video4linux driver for the Hexium HV-PCI6 and
          Orion frame grabber cards by Hexium.
@@ -299,9 +637,8 @@ config VIDEO_HEXIUM_ORION
 
 config VIDEO_HEXIUM_GEMINI
        tristate "Hexium Gemini frame grabber"
-       depends on PCI && VIDEO_V4L1 && I2C
+       depends on PCI && VIDEO_V4L2 && I2C
        select VIDEO_SAA7146_VV
-       select VIDEO_V4L2
        ---help---
          This is a video4linux driver for the Hexium Gemini frame
          grabber card by Hexium. Please note that the Gemini Dual
@@ -320,123 +657,16 @@ config VIDEO_M32R_AR
          camera module.
 
 config VIDEO_M32R_AR_M64278
-       tristate "Use Colour AR module M64278(VGA)"
-       depends on VIDEO_M32R_AR && PLAT_M32700UT
-       ---help---
-         Say Y here to use the Renesas M64278E-800 camera module,
-         which supports VGA(640x480 pixcels) size of images.
-
-#
-# Encoder / Decoder module configuration
-#
-
-menu "Encoders and Decoders"
-       depends on VIDEO_DEV
-
-config VIDEO_MSP3400
-       tristate "Micronas MSP34xx audio decoders"
-       depends on VIDEO_DEV && I2C
-       ---help---
-         Support for the Micronas MSP34xx series of audio decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called msp3400.
-
-config VIDEO_CS53L32A
-       tristate "Cirrus Logic CS53L32A audio ADC"
-       depends on VIDEO_DEV && I2C && EXPERIMENTAL
-       ---help---
-         Support for the Cirrus Logic CS53L32A low voltage
-         stereo A/D converter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cs53l32a.
-
-config VIDEO_TLV320AIC23B
-       tristate "Texas Instruments TLV320AIC23B audio codec"
-       depends on VIDEO_DEV && I2C && EXPERIMENTAL
+       tristate "AR device with color module M64278(VGA)"
+       depends on PLAT_M32700UT
+       select VIDEO_M32R_AR
        ---help---
-         Support for the Texas Instruments TLV320AIC23B audio codec.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tlv320aic23b.
-
-config VIDEO_WM8775
-       tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
-       depends on VIDEO_DEV && I2C && EXPERIMENTAL
-       ---help---
-         Support for the Wolfson Microelectronics WM8775 high
-         performance stereo A/D Converter with a 4 channel input mixer.
+         This is a video4linux driver for the Renesas AR (Artificial
+         Retina) with M64278E-800 camera module.
+         This module supports VGA(640x480 pixels) resolutions.
 
          To compile this driver as a module, choose M here: the
-         module will be called wm8775.
-
-config VIDEO_WM8739
-       tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
-       depends on VIDEO_DEV && I2C && EXPERIMENTAL
-       ---help---
-         Support for the Wolfson Microelectronics WM8739
-         stereo A/D Converter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called wm8739.
-
-config VIDEO_CX2341X
-       tristate "Conexant CX2341x MPEG encoders"
-       depends on VIDEO_V4L2 && EXPERIMENTAL
-       ---help---
-         Support for the Conexant CX23416 MPEG encoders
-         and CX23415 MPEG encoder/decoders.
-
-         This module currently supports the encoding functions only.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx2341x.
-
-source "drivers/media/video/cx25840/Kconfig"
-
-config VIDEO_SAA711X
-       tristate "Philips SAA7113/4/5 video decoders"
-       depends on VIDEO_DEV && I2C && EXPERIMENTAL
-       ---help---
-         Support for the Philips SAA7113/4/5 video decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7115.
-
-config VIDEO_SAA7127
-       tristate "Philips SAA7127/9 digital video encoders"
-       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-       ---help---
-         Support for the Philips SAA7127/9 digital video encoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7127.
-
-config VIDEO_UPD64031A
-       tristate "NEC Electronics uPD64031A Ghost Reduction"
-       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-       ---help---
-         Support for the NEC Electronics uPD64031A Ghost Reduction
-         video chip. It is most often found in NTSC TV cards made for
-         Japan and is used to reduce the 'ghosting' effect that can
-         be present in analog TV broadcasts.
-
-         To compile this driver as a module, choose M here: the
-         module will be called upd64031a.
-
-config VIDEO_UPD64083
-       tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
-       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-       ---help---
-         Support for the NEC Electronics uPD64083 3-Dimensional Y/C
-         separation video chip. It is used to improve the quality of
-         the colors of a composite signal.
-
-         To compile this driver as a module, choose M here: the
-         module will be called upd64083.
-
-endmenu # encoder / decoder chips
+         module will be called arv.
 
 #
 # USB Multimedia device configuration
@@ -445,8 +675,6 @@ endmenu # encoder / decoder chips
 menu "V4L USB devices"
        depends on USB && VIDEO_DEV
 
-source "drivers/media/video/pvrusb2/Kconfig"
-
 source "drivers/media/video/em28xx/Kconfig"
 
 source "drivers/media/video/usbvideo/Kconfig"
index e82e511f2a72782e343c6d19258d84f7aeeca6af..af57abce8a6ecc9ccdcefd0e9724775704581d1f 100644 (file)
@@ -17,7 +17,10 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
 endif
 
 obj-$(CONFIG_VIDEO_BT848) += bt8xx/
-obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_BT848) += ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
+obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
+obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
 obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
 obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
@@ -27,17 +30,32 @@ obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
 obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
 obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
 obj-$(CONFIG_VIDEO_W9966) += w9966.o
-obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o zr36060.o
-obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o zr36060.o
-obj-$(CONFIG_VIDEO_ZORAN_DC30) += adv7175.o vpx3220.o zr36050.o \
-       zr36016.o
-obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o zr36060.o
-obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o
-obj-$(CONFIG_VIDEO_ZORAN_AVS6EYES) += bt866.o ks0127.o zr36060.o
+
+obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
+obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
+obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
+obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
+obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
+obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
+obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
+obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
+obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
+obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
+obj-$(CONFIG_VIDEO_BT819) += bt819.o
+obj-$(CONFIG_VIDEO_BT856) += bt856.o
+obj-$(CONFIG_VIDEO_BT866) += bt866.o
+obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
+
 obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
+obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
+obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
+
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_PLANB) += planb.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o saa7191.o indycam.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
 obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
 obj-$(CONFIG_VIDEO_CPIA) += cpia.o
 obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
@@ -46,7 +64,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o
 obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/
 obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
-obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
@@ -55,10 +73,10 @@ obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
 obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
 obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
-obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o
+obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
-obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o
+obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
 obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
 obj-$(CONFIG_VIDEO_TUNER) += tuner.o
@@ -70,8 +88,6 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
 obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
 
 obj-$(CONFIG_VIDEO_CX25840) += cx25840/
-obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
-obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
@@ -96,4 +112,3 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT
-
index 05e42bbcfc3d5c26a5e034f20445f3f9803c914f..772fd52d551aaf35a5a43cb363831e1f51be9bc8 100644 (file)
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");
 struct bt866 {
        struct i2c_client *i2c;
        int addr;
-       unsigned char reg[128];
+       unsigned char reg[256];
 
        int norm;
        int enable;
index cdcf556507141559be9f3284a9a8425c1069a9ce..58eae887a62992c4a542193a219a81c4f4061f8d 100644 (file)
@@ -8,7 +8,10 @@ config VIDEO_BT848
        select VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEO_MSP3400
+       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TDA9875 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          Support for BT848 based frame grabber/overlay boards. This includes
          the Miro, Hauppauge and STB boards. Please read the material in
index de14818d5cc462815ff503e206c4da1047391abe..d23a42b1504f907e16d7736a6771e99982a554ac 100644 (file)
@@ -4991,7 +4991,7 @@ void __devinit bttv_check_chipset(void)
        int pcipci_fail = 0;
        struct pci_dev *dev = NULL;
 
-       if (pci_pci_problems & PCIPCI_FAIL)
+       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))       /* should check if target is AGP */
                pcipci_fail = 1;
        if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
                triton1 = 1;
index 20dff7c316eb595e2c8e9385f90ba0ad22723de9..50dde82844ec6f431dcc2079339e97b0711204e5 100644 (file)
@@ -2431,6 +2431,14 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
                fbuf->bytesperline  = btv->fbuf.fmt.bytesperline;
                if (fh->ovfmt)
                        fbuf->depth = fh->ovfmt->depth;
+               else {
+                       if (fbuf->width)
+                               fbuf->depth   = ((fbuf->bytesperline<<3)
+                                                 + (fbuf->width-1) )
+                                                 /fbuf->width;
+                       else
+                               fbuf->depth = 0;
+               }
                return 0;
        }
        case VIDIOCSFBUF:
@@ -4186,6 +4194,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
        return;
 }
 
+#ifdef CONFIG_PM
 static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
        struct bttv *btv = pci_get_drvdata(pci_dev);
@@ -4266,6 +4275,7 @@ static int bttv_resume(struct pci_dev *pci_dev)
        spin_unlock_irqrestore(&btv->s_lock,flags);
        return 0;
 }
+#endif
 
 static struct pci_device_id bttv_pci_tbl[] = {
        {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
@@ -4286,8 +4296,10 @@ static struct pci_driver bttv_pci_driver = {
        .id_table = bttv_pci_tbl,
        .probe    = bttv_probe,
        .remove   = __devexit_p(bttv_remove),
+#ifdef CONFIG_PM
        .suspend  = bttv_suspend,
        .resume   = bttv_resume,
+#endif
 };
 
 static int bttv_init_module(void)
index 4b562b386fcf6d044882077359763bb2e84ac241..70de6c96e201c9dba69a010d1b40d9d8294bc64a 100644 (file)
@@ -8,6 +8,9 @@
                           & Marcus Metzler (mocm@thp.uni-koeln.de)
     (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
 
+    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+       - Multituner support and i2c address binding
+
     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
@@ -45,10 +48,18 @@ static int i2c_debug;
 static int i2c_hw;
 static int i2c_scan;
 module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_hw,"configure i2c debug level");
 module_param(i2c_hw,    int, 0444);
+MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
+                       "instead of software bitbang");
 module_param(i2c_scan,  int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
+static unsigned int i2c_udelay = 5;
+module_param(i2c_udelay, int, 0444);
+MODULE_PARM_DESC(i2c_udelay,"soft i2c delay at insmod time, in usecs "
+               "(should be 5 or higher). Lower value means higher bus speed.");
+
 /* ----------------------------------------------------------------------- */
 /* I2C functions - bitbanging adapter (software i2c)                       */
 
@@ -100,7 +111,6 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
        .getsda  = bttv_bit_getsda,
        .getscl  = bttv_bit_getscl,
        .udelay  = 16,
-       .mdelay  = 10,
        .timeout = 200,
 };
 
@@ -426,6 +436,11 @@ int __devinit init_bttv_i2c(struct bttv *btv)
                       sizeof(bttv_i2c_adap_hw_template));
        } else {
                /* bt848 */
+       /* Prevents usage of invalid delay values */
+               if (i2c_udelay<5)
+                       i2c_udelay=5;
+               bttv_i2c_algo_bit_template.udelay=i2c_udelay;
+
                memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_sw_template,
                       sizeof(bttv_i2c_adap_sw_template));
                memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
index b69ee1194815cf84155b109d0d8f801de4e3ff58..d82a488f12a6a5214ff15bdea70a6b4fdde51102 100644 (file)
@@ -58,6 +58,7 @@ static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user
        return 0;
 }
 
+
 struct video_buffer32 {
        compat_caddr_t base;
        compat_int_t height, width, depth, bytesperline;
@@ -618,6 +619,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                struct video_buffer vb;
                struct video_window vw;
                struct video_code vc;
+               struct video_audio va;
 #endif
                struct v4l2_format v2f;
                struct v4l2_buffer v2b;
@@ -635,31 +637,31 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        /* First, convert the command. */
        switch(cmd) {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
-       case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
-       case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
-       case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
-       case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
-       case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
-       case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
-       case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
-       case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
+       case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break;
+       case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break;
+       case VIDIOCGWIN32: realcmd = cmd = VIDIOCGWIN; break;
+       case VIDIOCGFBUF32: realcmd = cmd = VIDIOCGFBUF; break;
+       case VIDIOCSFBUF32: realcmd = cmd = VIDIOCSFBUF; break;
+       case VIDIOCGFREQ32: realcmd = cmd = VIDIOCGFREQ; break;
+       case VIDIOCSFREQ32: realcmd = cmd = VIDIOCSFREQ; break;
+       case VIDIOCSMICROCODE32: realcmd = cmd = VIDIOCSMICROCODE; break;
 #endif
-       case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
-       case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
-       case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
-       case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
-       case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
-       case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
-       case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
-       case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
-       case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
-       case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
+       case VIDIOC_G_FMT32: realcmd = cmd = VIDIOC_G_FMT; break;
+       case VIDIOC_S_FMT32: realcmd = cmd = VIDIOC_S_FMT; break;
+       case VIDIOC_QUERYBUF32: realcmd = cmd = VIDIOC_QUERYBUF; break;
+       case VIDIOC_QBUF32: realcmd = cmd = VIDIOC_QBUF; break;
+       case VIDIOC_DQBUF32: realcmd = cmd = VIDIOC_DQBUF; break;
+       case VIDIOC_STREAMON32: realcmd = cmd = VIDIOC_STREAMON; break;
+       case VIDIOC_STREAMOFF32: realcmd = cmd = VIDIOC_STREAMOFF; break;
+       case VIDIOC_G_FBUF32: realcmd = cmd = VIDIOC_G_FBUF; break;
+       case VIDIOC_S_FBUF32: realcmd = cmd = VIDIOC_S_FBUF; break;
+       case VIDIOC_OVERLAY32: realcmd = cmd = VIDIOC_OVERLAY; break;
        case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;
        case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;
-       case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break;
-       case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
-       case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
-       case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
+       case VIDIOC_S_CTRL32: realcmd = cmd = VIDIOC_S_CTRL; break;
+       case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break;
+       case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break;
+       case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break;
        };
 
        switch(cmd) {
@@ -676,6 +678,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                compatible_arg = 0;
                break;
 
+
        case VIDIOCSFREQ:
 #endif
        case VIDIOC_S_INPUT:
@@ -683,7 +686,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        case VIDIOC_STREAMON:
        case VIDIOC_STREAMOFF:
                err = get_user(karg.vx, (u32 __user *)up);
-               compatible_arg = 0;
+               compatible_arg = 1;
                break;
 
        case VIDIOC_S_FBUF:
@@ -739,6 +742,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        case VIDIOC_G_FBUF:
        case VIDIOC_G_INPUT:
                compatible_arg = 0;
+               break;
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCSMICROCODE:
                err = microcode32(&karg.vc, up);
@@ -755,7 +759,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                mm_segment_t old_fs = get_fs();
 
                set_fs(KERNEL_DS);
-               err = native_ioctl(file, realcmd, (unsigned long)&karg);
+               err = native_ioctl(file, realcmd, (unsigned long) &karg);
                set_fs(old_fs);
        }
        if(err == 0) {
@@ -772,6 +776,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                case VIDIOCGFBUF:
                        err = put_video_buffer32(&karg.vb, up);
                        break;
+
 #endif
                case VIDIOC_G_FBUF:
                        err = put_v4l2_framebuffer32(&karg.v2fb, up);
@@ -841,10 +846,14 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOCSFBUF32:
        case VIDIOCGFREQ32:
        case VIDIOCSFREQ32:
+       case VIDIOCGAUDIO:
+       case VIDIOCSAUDIO:
 #endif
        case VIDIOC_QUERYCAP:
        case VIDIOC_ENUM_FMT:
        case VIDIOC_G_FMT32:
+       case VIDIOC_CROPCAP:
+       case VIDIOC_S_CROP:
        case VIDIOC_S_FMT32:
        case VIDIOC_REQBUFS:
        case VIDIOC_QUERYBUF32:
@@ -882,8 +891,6 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOCSPICT:
        case VIDIOCCAPTURE:
        case VIDIOCKEY:
-       case VIDIOCGAUDIO:
-       case VIDIOCSAUDIO:
        case VIDIOCSYNC:
        case VIDIOCMCAPTURE:
        case VIDIOCGMBUF:
index c5ecb2be5f9313d692f0c9826e6202f2b64c357b..8d2dfc128821ab57703689fbb7ed1671e04bd432 100644 (file)
 /***
  * Image defines
  ***/
-#ifndef true
-#define true 1
-#define false 0
-#endif
 
 /*  Misc constants */
 #define ALLOW_CORRUPT 0                /* Causes collater to discard checksum */
index 65f00fc08fa961d5671ccfe5a3cf92aa38efb4ab..657e0b9691459c532803fec0b8a2d9cfc1a76494 100644 (file)
@@ -691,7 +691,7 @@ void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
        .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
        .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
        .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
-       .video_temporal_filter = 0,
+       .video_temporal_filter = 8,
        .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
        .video_luma_median_filter_top = 255,
        .video_luma_median_filter_bottom = 0,
@@ -731,6 +731,7 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
        };
 
        int err = 0;
+       u16 temporal = new->video_temporal_filter;
 
        cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
 
@@ -741,6 +742,7 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
 
        if (old == NULL || old->width != new->width || old->height != new->height ||
                        old->video_encoding != new->video_encoding) {
+               int is_scaling;
                u16 w = new->width;
                u16 h = new->height;
 
@@ -750,6 +752,20 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
                }
                err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
                if (err) return err;
+
+               /* Adjust temporal filter if necessary. The problem with the temporal
+                  filter is that it works well with full resolution capturing, but
+                  not when the capture window is scaled (the filter introduces
+                  a ghosting effect). So if the capture window changed, and there is
+                  no updated filter value, then the filter is set depending on whether
+                  the new window is full resolution or not.
+
+                  For full resolution a setting of 8 really improves the video
+                  quality, especially if the original video quality is suboptimal. */
+               is_scaling = new->width != 720 || new->height != (new->is_50hz ? 576 : 480);
+               if (old && old->video_temporal_filter == temporal) {
+                       temporal = is_scaling ? 0 : 8;
+               }
        }
 
        if (old == NULL || old->stream_type != new->stream_type) {
@@ -815,9 +831,9 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
        }
        if (old == NULL ||
                old->video_spatial_filter != new->video_spatial_filter ||
-               old->video_temporal_filter != new->video_temporal_filter) {
+               old->video_temporal_filter != temporal) {
                err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
-                       new->video_spatial_filter, new->video_temporal_filter);
+                       new->video_spatial_filter, temporal);
                if (err) return err;
        }
        if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
@@ -855,6 +871,9 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
        printk(KERN_INFO "%s: Stream: %s\n",
                prefix,
                cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
+       printk(KERN_INFO "%s: VBI Format: %s\n",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
 
        /* Video */
        printk(KERN_INFO "%s: Video:  %dx%d, %d fps\n",
index 854264e42ec03e4b02af9809f000ce241b7ee4ef..7cf29a03ed63a9d3da53f9d3823627e86e23b47c 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_CX25840
        tristate "Conexant CX2584x audio/video decoders"
-       depends on VIDEO_DEV && I2C && EXPERIMENTAL
+       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
        select FW_LOADER
        ---help---
          Support for the Conexant CX2584x audio/video decoders.
index 6cc8bf215e851c548beedecd46d254d626dc052f..48014a254e15fdcf10b31c2ac255d5543083643d 100644 (file)
@@ -111,6 +111,10 @@ void cx25840_vbi_setup(struct i2c_client *client)
                        uv_lpf=0;
                        comb=0;
                        sc=0x0a425f;
+               } else if (std == V4L2_STD_PAL_Nc) {
+                       uv_lpf=1;
+                       comb=0x20;
+                       sc=556453;
                } else {
                        uv_lpf=1;
                        comb=0x20;
index 7a94e6a11927bdf877b7f8440fc5b499adff002c..51d68f32aa068f9e7fa2c39d21ac31c56b7ae463 100644 (file)
@@ -1,7 +1,3 @@
-config VIDEO_CX88_VP3054
-       tristate
-       depends on VIDEO_CX88_DVB && DVB_MT352
-
 config VIDEO_CX88
        tristate "Conexant 2388x (bt878 successor) support"
        depends on VIDEO_DEV && PCI && I2C
@@ -52,6 +48,14 @@ config VIDEO_CX88_DVB
        depends on VIDEO_CX88 && DVB_CORE
        select VIDEO_BUF_DVB
        select DVB_PLL
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_OR51132 if !DVB_FE_CUSTOMISE
+       select DVB_CX22702 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_NXT200X if !DVB_FE_CUSTOMISE
+       select DVB_CX24123 if !DVB_FE_CUSTOMISE
+       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
@@ -59,101 +63,12 @@ config VIDEO_CX88_DVB
          To compile this driver as a module, choose M here: the
          module will be called cx88-dvb.
 
-         You must also select one or more DVB/ATSC demodulators.
-         If you are unsure which you need, choose all of them.
-
-config VIDEO_CX88_DVB_ALL_FRONTENDS
-       bool "Build all supported frontends for cx2388x based TV cards"
-       default y
-       depends on VIDEO_CX88_DVB
-       select DVB_MT352
-       select VIDEO_CX88_VP3054
-       select DVB_ZL10353
-       select DVB_OR51132
-       select DVB_CX22702
-       select DVB_LGDT330X
-       select DVB_NXT200X
-       select DVB_CX24123
-       select DVB_ISL6421
-       ---help---
-         This builds cx88-dvb with all currently supported frontend
-         demodulators.  If you wish to tweak your configuration, and
-         only include support for the hardware that you need, choose N here.
-
-         If you are unsure, choose Y.
-
-config VIDEO_CX88_DVB_MT352
-       bool "Zarlink MT352 DVB-T Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_MT352
-       ---help---
-         This adds DVB-T support for cards based on the
-         Connexant 2388x chip and the MT352 demodulator.
-
-config VIDEO_CX88_DVB_VP3054
-       bool "VP-3054 Secondary I2C Bus Support"
-       default y
-       depends on VIDEO_CX88_DVB_MT352
-       select VIDEO_CX88_VP3054
+config VIDEO_CX88_VP3054
+       tristate "VP-3054 Secondary I2C Bus Support"
+       default m
+       depends on VIDEO_CX88_DVB && DVB_MT352
        ---help---
          This adds DVB-T support for cards based on the
          Connexant 2388x chip and the MT352 demodulator,
          which also require support for the VP-3054
          Secondary I2C bus, such at DNTV Live! DVB-T Pro.
-
-config VIDEO_CX88_DVB_ZL10353
-       bool "Zarlink ZL10353 DVB-T Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_ZL10353
-       ---help---
-         This adds DVB-T support for cards based on the
-         Connexant 2388x chip and the ZL10353 demodulator,
-         successor to the Zarlink MT352.
-
-config VIDEO_CX88_DVB_OR51132
-       bool "OR51132 ATSC Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_OR51132
-       ---help---
-         This adds ATSC 8VSB and QAM64/256 support for cards based on the
-         Connexant 2388x chip and the OR51132 demodulator.
-
-config VIDEO_CX88_DVB_CX22702
-       bool "Conexant CX22702 DVB-T Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_CX22702
-       ---help---
-         This adds DVB-T support for cards based on the
-         Connexant 2388x chip and the CX22702 demodulator.
-
-config VIDEO_CX88_DVB_LGDT330X
-       bool "LG Electronics DT3302/DT3303 ATSC Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_LGDT330X
-       ---help---
-         This adds ATSC 8VSB and QAM64/256 support for cards based on the
-         Connexant 2388x chip and the LGDT3302/LGDT3303 demodulator.
-
-config VIDEO_CX88_DVB_NXT200X
-       bool "NXT2002/NXT2004 ATSC Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_NXT200X
-       ---help---
-         This adds ATSC 8VSB and QAM64/256 support for cards based on the
-         Connexant 2388x chip and the NXT2002/NXT2004 demodulator.
-
-config VIDEO_CX88_DVB_CX24123
-       bool "Conexant CX24123 DVB-S Support"
-       default y
-       depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
-       select DVB_CX24123
-       select DVB_ISL6421
-       ---help---
-         This adds DVB-S support for cards based on the
-         Connexant 2388x chip and the CX24123 demodulator.
index 352b919f30c4a41a4ab896f3d1f686d393211879..639c3b659d0ecf098c4805d70ced3038fc5bc270 100644 (file)
@@ -14,13 +14,6 @@ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
 extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
-extra-cflags-$(CONFIG_DVB_CX22702)   += -DHAVE_CX22702=1
-extra-cflags-$(CONFIG_DVB_OR51132)   += -DHAVE_OR51132=1
-extra-cflags-$(CONFIG_DVB_LGDT330X)  += -DHAVE_LGDT330X=1
-extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
-extra-cflags-$(CONFIG_DVB_ZL10353)   += -DHAVE_ZL10353=1
-extra-cflags-$(CONFIG_DVB_NXT200X)   += -DHAVE_NXT200X=1
-extra-cflags-$(CONFIG_DVB_CX24123)   += -DHAVE_CX24123=1
 extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
 
 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
index b60177f173c3c1162726ca3da7eaa105781c8043..a7921f9d45d844d77e1a5019fe1d2f477863cfa7 100644 (file)
@@ -1160,8 +1160,10 @@ static struct pci_driver blackbird_pci_driver = {
        .id_table = cx8802_pci_tbl,
        .probe    = blackbird_probe,
        .remove   = __devexit_p(blackbird_remove),
+#ifdef CONFIG_PM
        .suspend  = cx8802_suspend_common,
        .resume   = cx8802_resume_common,
+#endif
 };
 
 static int blackbird_init(void)
index 14bd4863d157514d526bc61735743cebe214a8e2..6214eb823b29afffc94b0da20d628846ed72c41c 100644 (file)
@@ -1041,11 +1041,11 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
-                       .gpio0  = 0x000027df,
+                       .gpio0  = 0x000067df,
                 },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
-                       .gpio0  = 0x000027df,
+                       .gpio0  = 0x000067df,
                }},
                .dvb            = 1,
        },
@@ -1209,6 +1209,100 @@ struct cx88_board cx88_boards[] = {
                }},
                .dvb      = 1,
        },
+       [CX88_BOARD_HAUPPAUGE_HVR3000] = {
+               /* FIXME: Add dvb & radio support */
+               .name           = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x84bf,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x84bf,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x84bf,
+               }},
+       },
+       [CX88_BOARD_NORWOOD_MICRO] = {
+               .name           = "Norwood Micro TV Tuner",
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0709,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x070b,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x070b,
+               }},
+       },
+       [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
+              .name           = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
+              .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+              .radio_type     = UNSET,
+              .tuner_addr     = ADDR_UNSET,
+              .radio_addr     = ADDR_UNSET,
+              .input          = {{
+                      .type   = CX88_VMUX_TELEVISION,
+                      .vmux   = 0,
+                      .gpio0  = 0x003fffff,
+                      .gpio1  = 0x00e00000,
+                      .gpio2  = 0x003fffff,
+                      .gpio3  = 0x02000000,
+              },{
+                      .type   = CX88_VMUX_COMPOSITE1,
+                      .vmux   = 1,
+                      .gpio0  = 0x003fffff,
+                      .gpio1  = 0x00e00000,
+                      .gpio2  = 0x003fffff,
+                      .gpio3  = 0x02000000,
+               },{
+                      .type   = CX88_VMUX_SVIDEO,
+                      .vmux   = 2,
+                      .gpio0  = 0x003fffff,
+                      .gpio1  = 0x00e00000,
+                      .gpio2  = 0x003fffff,
+                      .gpio3  = 0x02000000,
+              }},
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR1300] = {
+               .name           = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xe780,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xe780,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xe780,
+               }},
+               /* fixme: Add radio support */
+               .dvb            = 1,
+       },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -1254,7 +1348,7 @@ struct cx88_subid cx88_subids[] = {
                .card      = CX88_BOARD_LEADTEK_PVR2000,
        },{
                .subvendor = 0x107d,
-               .subdevice = 0x663C,
+               .subdevice = 0x663c,
                .card      = CX88_BOARD_LEADTEK_PVR2000,
        },{
                .subvendor = 0x1461,
@@ -1458,6 +1552,35 @@ struct cx88_subid cx88_subids[] = {
                .subvendor = 0x14f1,
                .subdevice = 0x0084,
                .card      = CX88_BOARD_GENIATECH_DVBS,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x1404,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+       },{
+               .subvendor = 0x1461,
+               .subdevice = 0xc111, /* AverMedia M150-D */
+               /* This board is known to work with the ASUS PVR416 config */
+               .card      = CX88_BOARD_ASUS_PVR_416,
+       },{
+               .subvendor = 0xc180,
+               .subdevice = 0xc980,
+               .card      = CX88_BOARD_TE_DTV_250_OEM_SWANN,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9600,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9601,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9602,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x6632,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
        },
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -1501,6 +1624,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
        /* Make sure we support the board model */
        switch (tv.model)
        {
+       case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
        case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
        case 34519: /* WinTV-PCI-FM */
        case 90002: /* Nova-T-PCI (9002) */
@@ -1512,6 +1636,11 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
        case 92000: /* Nova-SE2 (OEM, No Video or IR) */
        case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
        case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
+       case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
+       case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */
+       case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */
+       case 96569: /* WinTV-HVR1300 () */
+       case 96659: /* WinTV-HVR1300 () */
        case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
                /* known */
                break;
@@ -1638,6 +1767,22 @@ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
                       core->name, i, cx88_boards[i].name);
 }
 
+void cx88_card_setup_pre_i2c(struct cx88_core *core)
+{
+       switch (core->board) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */
+               /* We leave here with the 702 on the bus */
+               cx_write(MO_GP0_IO, 0x0000e780);
+               udelay(1000);
+               cx_clear(MO_GP0_IO, 0x00000080);
+               udelay(50);
+               cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+               udelay(1000);
+               break;
+       }
+}
+
 void cx88_card_setup(struct cx88_core *core)
 {
        static u8 eeprom[256];
@@ -1666,6 +1811,8 @@ void cx88_card_setup(struct cx88_core *core)
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
                if (0 == core->i2c_rc)
                        hauppauge_eeprom(core,eeprom);
                break;
@@ -1673,9 +1820,15 @@ void cx88_card_setup(struct cx88_core *core)
                cx_write(MO_GP0_IO, 0x000007f8);
                cx_write(MO_GP1_IO, 0x00000001);
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+               /* GPIO0:6 is hooked to FX2 reset pin */
+               cx_set(MO_GP0_IO, 0x00004040);
+               cx_clear(MO_GP0_IO, 0x00000040);
+               msleep(1000);
+               cx_set(MO_GP0_IO, 0x00004040);
+               /* FALLTHROUGH */
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
                /* GPIO0:0 is hooked to mt352 reset pin */
                cx_set(MO_GP0_IO, 0x00000101);
index 973d3f39b2d540133c5398abd4e028956dee212b..f379ede3049a5cfce78002b62f83346b9e72e52c 100644 (file)
@@ -105,7 +105,7 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
                        *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
                        offset+=bpl;
                } else {
-                       /* scanline needs to be splitted */
+                       /* scanline needs to be split */
                        todo = bpl;
                        *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
                                            (sg_dma_len(sg)-offset));
@@ -792,6 +792,11 @@ int cx88_start_audio_dma(struct cx88_core *core)
 {
        /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
        int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
+
+       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+               return 0;
+
        /* setup fifo + format */
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
@@ -801,11 +806,16 @@ int cx88_start_audio_dma(struct cx88_core *core)
 
        /* start dma */
        cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
+
        return 0;
 }
 
 int cx88_stop_audio_dma(struct cx88_core *core)
 {
+       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+               return 0;
+
        /* stop dma */
        cx_write(MO_AUD_DMACNTRL, 0x0000);
 
@@ -1123,6 +1133,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
 
        /* init hardware */
        cx88_reset(core);
+       cx88_card_setup_pre_i2c(core);
        cx88_i2c_init(core,pci);
        cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
        cx88_card_setup(core);
index afde3789d702e2f295cc66a4d953b2c028c9ddce..c87041dee21e7d677b835fdc6683da01e1a110ef 100644 (file)
 #include "dvb-pll.h"
 #include <media/v4l2-common.h>
 
-#ifdef HAVE_MT352
-# include "mt352.h"
-# include "mt352_priv.h"
-# ifdef HAVE_VP3054_I2C
-#  include "cx88-vp3054-i2c.h"
-# endif
-#endif
-#ifdef HAVE_ZL10353
-# include "zl10353.h"
-#endif
-#ifdef HAVE_CX22702
-# include "cx22702.h"
-#endif
-#ifdef HAVE_OR51132
-# include "or51132.h"
-#endif
-#ifdef HAVE_LGDT330X
-# include "lgdt330x.h"
-# include "lg_h06xf.h"
-#endif
-#ifdef HAVE_NXT200X
-# include "nxt200x.h"
-#endif
-#ifdef HAVE_CX24123
-# include "cx24123.h"
+#include "mt352.h"
+#include "mt352_priv.h"
+#ifdef HAVE_VP3054_I2C
+# include "cx88-vp3054-i2c.h"
 #endif
+#include "zl10353.h"
+#include "cx22702.h"
+#include "or51132.h"
+#include "lgdt330x.h"
+#include "lg_h06xf.h"
+#include "nxt200x.h"
+#include "cx24123.h"
 #include "isl6421.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
@@ -114,8 +100,6 @@ static struct videobuf_queue_ops dvb_qops = {
 };
 
 /* ------------------------------------------------------------------ */
-
-#ifdef HAVE_MT352
 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
 {
        static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
@@ -181,7 +165,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
 }
 
 static struct mt352_config dvico_fusionhdtv = {
-       .demod_address = 0x0F,
+       .demod_address = 0x0f,
        .demod_init    = dvico_fusionhdtv_demod_init,
 };
 
@@ -191,7 +175,7 @@ static struct mt352_config dntv_live_dvbt_config = {
 };
 
 static struct mt352_config dvico_fusionhdtv_dual = {
-       .demod_address = 0x0F,
+       .demod_address = 0x0f,
        .demod_init    = dvico_dual_demod_init,
 };
 
@@ -266,8 +250,8 @@ static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe,
        if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
 
                printk(KERN_WARNING "cx88-dvb: %s error "
-                          "(addr %02x <- %02x, err = %i)\n",
-                          __FUNCTION__, dev->core->pll_addr, buf[0], err);
+                      "(addr %02x <- %02x, err = %i)\n",
+                      __FUNCTION__, dev->core->pll_addr, buf[0], err);
                if (err < 0)
                        return err;
                else
@@ -283,9 +267,7 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
        .demod_init    = dntv_live_dvbt_pro_demod_init,
 };
 #endif
-#endif
 
-#ifdef HAVE_ZL10353
 static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
                                         struct dvb_frontend_parameters *params)
 {
@@ -304,8 +286,8 @@ static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
                printk(KERN_WARNING "cx88-dvb: %s error "
-                          "(addr %02x <- %02x, err = %i)\n",
-                          __FUNCTION__, pllbuf[0], pllbuf[1], err);
+                      "(addr %02x <- %02x, err = %i)\n",
+                      __FUNCTION__, pllbuf[0], pllbuf[1], err);
                if (err < 0)
                        return err;
                else
@@ -316,16 +298,14 @@ static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
 }
 
 static struct zl10353_config dvico_fusionhdtv_hybrid = {
-       .demod_address = 0x0F,
+       .demod_address = 0x0f,
        .no_tuner      = 1,
 };
 
 static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
-       .demod_address = 0x0F,
+       .demod_address = 0x0f,
 };
-#endif
 
-#ifdef HAVE_CX22702
 static struct cx22702_config connexant_refboard_config = {
        .demod_address = 0x43,
        .output_mode   = CX22702_SERIAL_OUTPUT,
@@ -339,9 +319,11 @@ static struct cx22702_config hauppauge_hvr1100_config = {
        .demod_address = 0x63,
        .output_mode   = CX22702_SERIAL_OUTPUT,
 };
-#endif
+static struct cx22702_config hauppauge_hvr1300_config = {
+       .demod_address = 0x63,
+       .output_mode   = CX22702_SERIAL_OUTPUT,
+};
 
-#ifdef HAVE_OR51132
 static int or51132_set_ts_param(struct dvb_frontend* fe,
                                int is_punctured)
 {
@@ -351,12 +333,10 @@ static int or51132_set_ts_param(struct dvb_frontend* fe,
 }
 
 static struct or51132_config pchdtv_hd3000 = {
-       .demod_address    = 0x15,
-       .set_ts_params    = or51132_set_ts_param,
+       .demod_address = 0x15,
+       .set_ts_params = or51132_set_ts_param,
 };
-#endif
 
-#ifdef HAVE_LGDT330X
 static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
                                     struct dvb_frontend_parameters* params)
 {
@@ -373,14 +353,14 @@ static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
 
        dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
        dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-                       __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+               __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1);
        if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
                printk(KERN_WARNING "cx88-dvb: %s error "
-                          "(addr %02x <- %02x, err = %i)\n",
-                          __FUNCTION__, buf[0], buf[1], err);
+                      "(addr %02x <- %02x, err = %i)\n",
+                      __FUNCTION__, buf[0], buf[1], err);
                if (err < 0)
                        return err;
                else
@@ -425,28 +405,26 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
 }
 
 static struct lgdt330x_config fusionhdtv_3_gold = {
-       .demod_address    = 0x0e,
-       .demod_chip       = LGDT3302,
-       .serial_mpeg      = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
-       .set_ts_params    = lgdt330x_set_ts_param,
+       .demod_address = 0x0e,
+       .demod_chip    = LGDT3302,
+       .serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
+       .set_ts_params = lgdt330x_set_ts_param,
 };
 
 static struct lgdt330x_config fusionhdtv_5_gold = {
-       .demod_address    = 0x0e,
-       .demod_chip       = LGDT3303,
-       .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .set_ts_params    = lgdt330x_set_ts_param,
+       .demod_address = 0x0e,
+       .demod_chip    = LGDT3303,
+       .serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+       .set_ts_params = lgdt330x_set_ts_param,
 };
 
 static struct lgdt330x_config pchdtv_hd5500 = {
-       .demod_address    = 0x59,
-       .demod_chip       = LGDT3303,
-       .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .set_ts_params    = lgdt330x_set_ts_param,
+       .demod_address = 0x59,
+       .demod_chip    = LGDT3303,
+       .serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+       .set_ts_params = lgdt330x_set_ts_param,
 };
-#endif
 
-#ifdef HAVE_NXT200X
 static int nxt200x_set_ts_param(struct dvb_frontend* fe,
                                int is_punctured)
 {
@@ -465,28 +443,27 @@ static int nxt200x_set_pll_input(u8* buf, int input)
 }
 
 static struct nxt200x_config ati_hdtvwonder = {
-       .demod_address    = 0x0a,
-       .set_pll_input    = nxt200x_set_pll_input,
-       .set_ts_params    = nxt200x_set_ts_param,
+       .demod_address = 0x0a,
+       .set_pll_input = nxt200x_set_pll_input,
+       .set_ts_params = nxt200x_set_ts_param,
 };
-#endif
 
-#ifdef HAVE_CX24123
 static int cx24123_set_ts_param(struct dvb_frontend* fe,
        int is_punctured)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
-       dev->ts_gen_cntrl = 0x2;
+       dev->ts_gen_cntrl = 0x02;
        return 0;
 }
 
-static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
+                                      fe_sec_voltage_t voltage)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
 
        if (voltage == SEC_VOLTAGE_OFF) {
-               cx_write(MO_GP0_IO, 0x000006fB);
+               cx_write(MO_GP0_IO, 0x000006fb);
        } else {
                cx_write(MO_GP0_IO, 0x000006f9);
        }
@@ -496,7 +473,8 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t
        return 0;
 }
 
-static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
+                                     fe_sec_voltage_t voltage)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
@@ -512,20 +490,20 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t
 }
 
 static struct cx24123_config geniatech_dvbs_config = {
-       .demod_address  = 0x55,
-       .set_ts_params  = cx24123_set_ts_param,
+       .demod_address = 0x55,
+       .set_ts_params = cx24123_set_ts_param,
 };
 
 static struct cx24123_config hauppauge_novas_config = {
-       .demod_address          = 0x55,
-       .set_ts_params          = cx24123_set_ts_param,
+       .demod_address = 0x55,
+       .set_ts_params = cx24123_set_ts_param,
 };
 
 static struct cx24123_config kworld_dvbs_100_config = {
-       .demod_address          = 0x15,
-       .set_ts_params          = cx24123_set_ts_param,
+       .demod_address = 0x15,
+       .set_ts_params = cx24123_set_ts_param,
+       .lnb_polarity  = 1,
 };
-#endif
 
 static int dvb_register(struct cx8802_dev *dev)
 {
@@ -535,114 +513,114 @@ static int dvb_register(struct cx8802_dev *dev)
 
        /* init frontend */
        switch (dev->core->board) {
-#ifdef HAVE_CX22702
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
-               dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_novat_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt759x);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_thomson_dtt759x);
                }
                break;
        case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
        case CX88_BOARD_CONEXANT_DVB_T1:
        case CX88_BOARD_KWORLD_DVB_T_CX22702:
        case CX88_BOARD_WINFAST_DTV1000:
-               dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &connexant_refboard_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x60,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt7579);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_thomson_dtt7579);
                }
                break;
        case CX88_BOARD_WINFAST_DTV2000H:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
-               dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr1100_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_fmd1216me);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_fmd1216me);
+               }
+               break;
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               dev->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr1300_config,
+                                              &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_fmd1216me);
                }
                break;
-#endif
-#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-#ifdef HAVE_MT352
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
-                                                &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dvico_fusionhdtv,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x60,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt7579);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+                                  NULL, &dvb_pll_thomson_dtt7579);
                        break;
                }
-#endif
-#ifdef HAVE_ZL10353
                /* ZL10353 replaces MT352 on later cards */
-               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_plus_v1_1,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x60,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt7579);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+                                  NULL, &dvb_pll_thomson_dtt7579);
                }
-#endif
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
-#ifdef HAVE_MT352
                /* The tin box says DEE1601, but it seems to be DTT7579
                 * compatible, with a slightly different MT352 AGC gain. */
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
-                                                &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dvico_fusionhdtv_dual,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt7579);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_thomson_dtt7579);
                        break;
                }
-#endif
-#ifdef HAVE_ZL10353
                /* ZL10353 replaces MT352 on later cards */
-               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_plus_v1_1,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt7579);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_thomson_dtt7579);
                }
-#endif
                break;
-#endif /* HAVE_MT352 || HAVE_ZL10353 */
-#ifdef HAVE_MT352
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
-                                                &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dvico_fusionhdtv,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_lg_z201);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_lg_z201);
                }
                break;
        case CX88_BOARD_KWORLD_DVB_T:
        case CX88_BOARD_DNTV_LIVE_DVB_T:
        case CX88_BOARD_ADSTECH_DVB_T_PCI:
-               dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
-                                                &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dntv_live_dvbt_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_unknown_1);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_unknown_1);
                }
                break;
        case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 #ifdef HAVE_VP3054_I2C
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_fmd1216me;
-               dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
                        &((struct vp3054_i2c_state *)dev->card_priv)->adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params;
@@ -651,30 +629,26 @@ static int dvb_register(struct cx8802_dev *dev)
                printk("%s: built without vp3054 support\n", dev->core->name);
 #endif
                break;
-#endif
-#ifdef HAVE_ZL10353
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_thomson_fe6600;
-               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_hybrid,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
                }
                break;
-#endif
-#ifdef HAVE_OR51132
        case CX88_BOARD_PCHDTV_HD3000:
-               dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
-                                                &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(or51132_attach,
+                                              &pchdtv_hd3000,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_thomson_dtt761x);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  &dev->core->i2c_adap,
+                                  &dvb_pll_thomson_dtt761x);
                }
                break;
-#endif
-#ifdef HAVE_LGDT330X
        case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
                dev->ts_gen_cntrl = 0x08;
                {
@@ -690,8 +664,9 @@ static int dvb_register(struct cx8802_dev *dev)
                fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_microtune_4042;
-               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
-                                                   &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &fusionhdtv_3_gold,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
                }
@@ -709,8 +684,9 @@ static int dvb_register(struct cx8802_dev *dev)
                mdelay(200);
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
-               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
-                                                   &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &fusionhdtv_3_gold,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
                }
@@ -726,8 +702,9 @@ static int dvb_register(struct cx8802_dev *dev)
                mdelay(100);
                cx_set(MO_GP0_IO, 1);
                mdelay(200);
-               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
-                                                   &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &fusionhdtv_5_gold,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
                }
@@ -743,52 +720,51 @@ static int dvb_register(struct cx8802_dev *dev)
                mdelay(100);
                cx_set(MO_GP0_IO, 1);
                mdelay(200);
-               dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500,
-                                                   &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &pchdtv_hd5500,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
                }
                }
                break;
-#endif
-#ifdef HAVE_NXT200X
        case CX88_BOARD_ATI_HDTVWONDER:
-               dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder,
-                                                &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(nxt200x_attach,
+                                              &ati_hdtvwonder,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
-                                      &dev->core->i2c_adap,
-                                      &dvb_pll_tuv1236d);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_tuv1236d);
                }
                break;
-#endif
-#ifdef HAVE_CX24123
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-               dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
-                       &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(cx24123_attach,
+                                              &hauppauge_novas_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend) {
-                       isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap,
-                                      0x08, 0x00, 0x00);
+                       dvb_attach(isl6421_attach, dev->dvb.frontend,
+                                  &dev->core->i2c_adap, 0x08, 0x00, 0x00);
                }
                break;
        case CX88_BOARD_KWORLD_DVBS_100:
-               dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
-                       &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(cx24123_attach,
+                                              &kworld_dvbs_100_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
                        dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
                }
                break;
        case CX88_BOARD_GENIATECH_DVBS:
-               dev->dvb.frontend = cx24123_attach(&geniatech_dvbs_config,
-                                                  &dev->core->i2c_adap);
+               dev->dvb.frontend = dvb_attach(cx24123_attach,
+                                              &geniatech_dvbs_config,
+                                              &dev->core->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
                        dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
                }
                break;
-#endif
        default:
                printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
                       dev->core->name);
@@ -908,8 +884,10 @@ static struct pci_driver dvb_pci_driver = {
        .id_table = cx8802_pci_tbl,
        .probe    = dvb_probe,
        .remove   = __devexit_p(dvb_remove),
+#ifdef CONFIG_PM
        .suspend  = cx8802_suspend_common,
        .resume   = cx8802_resume_common,
+#endif
 };
 
 static int dvb_init(void)
index 70663805cc301234efc682a4901179322b72aa1f..27b5dbb2ca1a12d5ddb33a6249987f6f4947ea7a 100644 (file)
@@ -7,6 +7,9 @@
     (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
     (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
 
+    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+       - Multituner support and i2c address binding
+
     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
@@ -40,6 +43,11 @@ static unsigned int i2c_scan = 0;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
+static unsigned int i2c_udelay = 5;
+module_param(i2c_udelay, int, 0644);
+MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "
+               "(should be 5 or higher). Lower value means higher bus speed.");
+
 #define dprintk(level,fmt, arg...)     if (i2c_debug >= level) \
        printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
 
@@ -155,7 +163,6 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
        .getsda  = cx8800_bit_getsda,
        .getscl  = cx8800_bit_getscl,
        .udelay  = 16,
-       .mdelay  = 10,
        .timeout = 200,
 };
 
@@ -199,6 +206,11 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
 /* init + register i2c algo-bit adapter */
 int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
 {
+       /* Prevents usage of invalid delay values */
+       if (i2c_udelay<5)
+               i2c_udelay=5;
+       cx8800_i2c_algo_template.udelay=i2c_udelay;
+
        memcpy(&core->i2c_adap, &cx8800_i2c_adap_template,
               sizeof(core->i2c_adap));
        memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
index c255646489933f19170ec466badc8d1c896693cf..83ebf7a3c054a9bfa44d384175bdba3d72acae48 100644 (file)
@@ -107,7 +107,15 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
                   (gpio & ir->mask_keydown) ? " down" : "",
                   (gpio & ir->mask_keyup) ? " up" : "");
 
-       if (ir->mask_keydown) {
+       if (ir->core->board == CX88_BOARD_NORWOOD_MICRO) {
+               u32 gpio_key = cx_read(MO_GP0_IO);
+
+               data = (data << 4) | ((gpio_key & 0xf0) >> 4);
+
+               ir_input_keydown(ir->input, &ir->ir, data, data);
+               ir_input_nokey(ir->input, &ir->ir);
+
+       } else if (ir->mask_keydown) {
                /* bit set on keydown */
                if (gpio & ir->mask_keydown) {
                        ir_input_keydown(ir->input, &ir->ir, data, data);
@@ -187,6 +195,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
                ir_codes = ir_codes_hauppauge_new;
                ir_type = IR_TYPE_RC5;
                ir->sampling = 1;
@@ -248,6 +257,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir_type = IR_TYPE_PD;
                ir->sampling = 0xff00; /* address */
                break;
+       case CX88_BOARD_NORWOOD_MICRO:
+               ir_codes         = ir_codes_norwood;
+               ir->gpio_addr    = MO_GP1_IO;
+               ir->mask_keycode = 0x0e;
+               ir->mask_keyup   = 0x80;
+               ir->polling      = 50; /* ms */
+               break;
        case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
                ir_codes = ir_codes_npgtech;
                ir->gpio_addr = MO_GP0_IO;
@@ -402,6 +418,7 @@ void cx88_ir_irq(struct cx88_core *core)
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
                ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
                ir_dprintk("biphase decoded: %x\n", ircode);
                if ((ircode & 0xfffff000) != 0x3000)
index 5785c3481579d1dda8b77d4cfb8af9300ed14b82..741e7c5e69ec7085d2d68cb53f05dddef74ad9e1 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
-#include <linux/config.h>
 #include <linux/kthread.h>
 
 #include "cx88.h"
@@ -138,14 +137,10 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
 {
        u32 volume;
 
-#ifndef CONFIG_VIDEO_CX88_ALSA
        /* restart dma; This avoids buzz in NICAM and is good in others  */
        cx88_stop_audio_dma(core);
-#endif
        cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
-#ifndef CONFIG_VIDEO_CX88_ALSA
        cx88_start_audio_dma(core);
-#endif
 
        if (cx88_boards[core->board].blackbird) {
                /* sets sound input from external adc */
index 94c92bacc342be219f78035e855c78d43ce1a763..fbc79e9842aa70299c2d4b98147805eaffdc2996 100644 (file)
@@ -497,6 +497,7 @@ static int start_video_dma(struct cx8800_dev    *dev,
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int stop_video_dma(struct cx8800_dev    *dev)
 {
        struct cx88_core *core = dev->core;
@@ -512,6 +513,7 @@ static int stop_video_dma(struct cx8800_dev    *dev)
        cx_clear(MO_VID_INTMSK, 0x0f0011);
        return 0;
 }
+#endif
 
 static int restart_video_queue(struct cx8800_dev    *dev,
                               struct cx88_dmaqueue *q)
@@ -2017,6 +2019,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
        kfree(dev);
 }
 
+#ifdef CONFIG_PM
 static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
@@ -2092,6 +2095,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
 
        return 0;
 }
+#endif
 
 /* ----------------------------------------------------------- */
 
@@ -2112,9 +2116,10 @@ static struct pci_driver cx8800_pci_driver = {
        .id_table = cx8800_pci_tbl,
        .probe    = cx8800_initdev,
        .remove   = __devexit_p(cx8800_finidev),
-
+#ifdef CONFIG_PM
        .suspend  = cx8800_suspend,
        .resume   = cx8800_resume,
+#endif
 };
 
 static int cx8800_init(void)
index 751a754a45e9c02041d29fea98a933516461d100..2b4f1970c7dfec814bf04572de62b14bc75e42e7 100644 (file)
@@ -100,7 +100,6 @@ static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
        .getsda  = vp3054_bit_getsda,
        .getscl  = vp3054_bit_getscl,
        .udelay  = 16,
-       .mdelay  = 10,
        .timeout = 200,
 };
 
index e7810955dd4f845c803e954de86644eab40f4d73..89f12e273b7f83a5ac7f47e241028e321f9dd839 100644 (file)
@@ -197,6 +197,10 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_NPGTECH_REALTV_TOP10FM  50
 #define CX88_BOARD_WINFAST_DTV2000H        51
 #define CX88_BOARD_GENIATECH_DVBS          52
+#define CX88_BOARD_HAUPPAUGE_HVR3000       53
+#define CX88_BOARD_NORWOOD_MICRO           54
+#define CX88_BOARD_TE_DTV_250_OEM_SWANN    55
+#define CX88_BOARD_HAUPPAUGE_HVR1300       56
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -545,6 +549,7 @@ extern const unsigned int cx88_idcount;
 
 extern void cx88_card_list(struct cx88_core *core, struct pci_dev *pci);
 extern void cx88_card_setup(struct cx88_core *core);
+extern void cx88_card_setup_pre_i2c(struct cx88_core *core);
 
 /* ----------------------------------------------------------- */
 /* cx88-tvaudio.c                                              */
index dfb15bfb83dcad2f03b47a521a10d26174ccdd22..9285a58e47aae9a166723809b1df65c57f1525a4 100644 (file)
@@ -5,7 +5,8 @@ config VIDEO_EM28XX
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_IR
-       select VIDEO_SAA711X
+       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          This is a video4linux driver for Empia 28xx based TV cards.
 
index 2a461dde480c89c0dcf339920861764a709c89f9..20df657b70c8f1c63bbef43fbdb2c1ee3c4855e6 100644 (file)
@@ -174,7 +174,7 @@ static void em28xx_config_i2c(struct em28xx *dev)
 
        route.input = INPUT(dev->ctl_input)->vmux;
        route.output = 0;
-       em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
+       em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, 0);
        em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
        em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
 
index 3bf7ac4f52882ff40193c7d9811d4c0e38cf0d3e..c1a377f797d9b21679bf6c23d4fe23bb51c2ac6e 100644 (file)
@@ -832,8 +832,7 @@ static int ks0127_detach(struct i2c_client *client)
 static int __devinit ks0127_init_module(void)
 {
        init_reg_defaults();
-       i2c_add_driver(&i2c_driver_ks0127);
-       return 0;
+       return i2c_add_driver(&i2c_driver_ks0127);
 }
 
 static void __devexit ks0127_cleanup_module(void)
index 1b07a61c2ebb7dd98854e7d40dcea077189868cb..5d8cd283fcd8e747767eb5b4e7e6470be5568322 100644 (file)
@@ -301,10 +301,11 @@ static struct symbolic_list senlist[] = {
 static struct symbolic_list urb_errlist[] = {
        { -ENOSR,       "Buffer error (overrun)" },
        { -EPIPE,       "Stalled (device not responding)" },
-       { -EOVERFLOW,   "Babble (bad cable?)" },
+       { -EOVERFLOW,   "Babble (device sends too much data)" },
        { -EPROTO,      "Bit-stuff error (bad cable?)" },
-       { -EILSEQ,      "CRC/Timeout" },
-       { -ETIMEDOUT,   "NAK (device does not respond)" },
+       { -EILSEQ,      "CRC/Timeout (bad cable?)" },
+       { -ETIME,       "Device does not respond to token" },
+       { -ETIMEDOUT,   "Device does not respond to command" },
        { -1, NULL }
 };
 
index 7e727fe14b322876914ee9445dd495db04a73d70..a52171ef6134ca6bf77c1c82f3f972e65209e9e5 100644 (file)
@@ -5,8 +5,6 @@ config VIDEO_PVRUSB2
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
-       select VIDEO_SAA711X
-       select VIDEO_MSP3400
        ---help---
          This is a video4linux driver for Conexant 23416 based
          usb2 personal video recorder devices.
@@ -14,6 +12,20 @@ config VIDEO_PVRUSB2
          To compile this driver as a module, choose M here: the
          module will be called pvrusb2
 
+config VIDEO_PVRUSB2_29XXX
+       bool "Hauppauge WinTV-PVR USB2 support for 29xxx model series"
+       depends on VIDEO_PVRUSB2 && EXPERIMENTAL
+       select VIDEO_SAA711X
+       select VIDEO_MSP3400
+       ---help---
+         This option enables support for WinTV-PVR USB2 devices whose 
+         model number is of the form "29xxx" (leading prefix of "29" 
+         followed by 3 digits).
+         To see if you may need this option, examine the white
+         sticker on the underside of your device.
+
+         If you are in doubt, say Y.
+
 config VIDEO_PVRUSB2_24XXX
        bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series"
        depends on VIDEO_PVRUSB2 && EXPERIMENTAL
@@ -60,3 +72,5 @@ config VIDEO_PVRUSB2_DEBUGIFC
          You do not need to select this option unless you plan
          on debugging the driver or performing a manual firmware
          extraction.
+
+         If you are in doubt, say N.
index 02e414210dac4ab61be1baa43558c5fc32610bd8..69b3e43cd0ebb8175cd3b5f465186947a7092955 100644 (file)
@@ -1,10 +1,6 @@
 obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
 obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
 
-obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \
-                  pvrusb2-cx2584x-v4l.o \
-                  pvrusb2-wm8775.o
-
 pvrusb2-objs   := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
                   pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
                   pvrusb2-encoder.o pvrusb2-video-v4l.o \
@@ -12,7 +8,7 @@ pvrusb2-objs   := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
                   pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
                   pvrusb2-ctrl.o pvrusb2-std.o \
                   pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
-                  $(obj-pvrusb2-24xxx-y) \
+                  pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
                   $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
 
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
index fb6198f1df98629dbb04d14eeb643838300c8041..c77de859cc8e109989b6ebc0ec55d45c496747f8 100644 (file)
@@ -43,12 +43,17 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
                        if (cptr->info->type == pvr2_ctl_bitmask) {
                                mask &= cptr->info->def.type_bitmask.valid_bits;
                        } else if (cptr->info->type == pvr2_ctl_int) {
-                               if (val < cptr->info->def.type_int.min_value) {
-                                       break;
+                               int lim;
+                               lim = cptr->info->def.type_int.min_value;
+                               if (cptr->info->get_min_value) {
+                                       cptr->info->get_min_value(cptr,&lim);
                                }
-                               if (val > cptr->info->def.type_int.max_value) {
-                                       break;
+                               if (val < lim) break;
+                               lim = cptr->info->def.type_int.max_value;
+                               if (cptr->info->get_max_value) {
+                                       cptr->info->get_max_value(cptr,&lim);
                                }
+                               if (val > lim) break;
                        } else if (cptr->info->type == pvr2_ctl_enum) {
                                if (val >= cptr->info->def.type_enum.count) {
                                        break;
@@ -91,7 +96,9 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
        int ret = 0;
        if (!cptr) return 0;
        LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->type == pvr2_ctl_int) {
+               if (cptr->info->get_max_value) {
+                       cptr->info->get_max_value(cptr,&ret);
+               } else if (cptr->info->type == pvr2_ctl_int) {
                        ret = cptr->info->def.type_int.max_value;
                }
        } while(0); LOCK_GIVE(cptr->hdw->big_lock);
@@ -105,7 +112,9 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
        int ret = 0;
        if (!cptr) return 0;
        LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->type == pvr2_ctl_int) {
+               if (cptr->info->get_min_value) {
+                       cptr->info->get_min_value(cptr,&ret);
+               } else if (cptr->info->type == pvr2_ctl_int) {
                        ret = cptr->info->def.type_int.min_value;
                }
        } while(0); LOCK_GIVE(cptr->hdw->big_lock);
index c80c26be6e4d31dd048964525184d676cc96bf0d..df8feac16aee78a7ba4a744bf0d12ecf580adfd7 100644 (file)
@@ -221,7 +221,7 @@ static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
 static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
 {
        int ret;
-       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL);
+       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,0);
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
 }
 
index 18a7073501c6037fd845dfdf414d70cee51aefbc..c94f97b7939246ff0dd61e6ad417f438861a621d 100644 (file)
@@ -317,7 +317,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to configure cx32416");
+                          "Failed to configure cx23416");
                return ret;
        }
 
@@ -337,7 +337,7 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 
        if (ret) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to initialize cx32416 video input");
+                          "Failed to initialize cx23416 video input");
                return ret;
        }
 
index 0d6dc33ca32046db2e34cd6aef0f7502af2af968..34b08fbcc6eaf8ca0beb49417408a8c17f66cfad 100644 (file)
@@ -33,7 +33,6 @@
 
 */
 
-#include <linux/config.h>
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include "pvrusb2-io.h"
 #include <media/cx2341x.h>
 
-/* Legal values for the SRATE state variable */
-#define PVR2_CVAL_SRATE_48 0
-#define PVR2_CVAL_SRATE_44_1 1
-
-/* Legal values for the AUDIOBITRATE state variable */
-#define PVR2_CVAL_AUDIOBITRATE_384 0
-#define PVR2_CVAL_AUDIOBITRATE_320 1
-#define PVR2_CVAL_AUDIOBITRATE_256 2
-#define PVR2_CVAL_AUDIOBITRATE_224 3
-#define PVR2_CVAL_AUDIOBITRATE_192 4
-#define PVR2_CVAL_AUDIOBITRATE_160 5
-#define PVR2_CVAL_AUDIOBITRATE_128 6
-#define PVR2_CVAL_AUDIOBITRATE_112 7
-#define PVR2_CVAL_AUDIOBITRATE_96 8
-#define PVR2_CVAL_AUDIOBITRATE_80 9
-#define PVR2_CVAL_AUDIOBITRATE_64 10
-#define PVR2_CVAL_AUDIOBITRATE_56 11
-#define PVR2_CVAL_AUDIOBITRATE_48 12
-#define PVR2_CVAL_AUDIOBITRATE_32 13
-#define PVR2_CVAL_AUDIOBITRATE_VBR 14
-
-/* Legal values for the AUDIOEMPHASIS state variable */
-#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0
-#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1
-#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2
-
 /* Legal values for PVR2_CID_HSM */
 #define PVR2_CVAL_HSM_FAIL 0
 #define PVR2_CVAL_HSM_FULL 1
@@ -107,6 +80,8 @@ struct pvr2_ctl_info {
 
        /* Control's implementation */
        pvr2_ctlf_get_value get_value;      /* Get its value */
+       pvr2_ctlf_get_value get_min_value;  /* Get minimum allowed value */
+       pvr2_ctlf_get_value get_max_value;  /* Get maximum allowed value */
        pvr2_ctlf_set_value set_value;      /* Set its value */
        pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
        pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
@@ -193,9 +168,7 @@ struct pvr2_decoder_ctrl {
 
 /* Known major hardware variants, keyed from device ID */
 #define PVR2_HDW_TYPE_29XXX 0
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
 #define PVR2_HDW_TYPE_24XXX 1
-#endif
 
 typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
 #define PVR2_I2C_FUNC_CNT 128
index be1e5cc780812b1820ef21e94fea7e9058787888..88604365777c32c936bec578935ce3337ceb2dd5 100644 (file)
@@ -38,9 +38,7 @@
 
 struct usb_device_id pvr2_device_table[] = {
        [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
        [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
-#endif
        { }
 };
 
@@ -48,9 +46,7 @@ MODULE_DEVICE_TABLE(usb, pvr2_device_table);
 
 static const char *pvr2_device_names[] = {
        [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
        [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",
-#endif
 };
 
 struct pvr2_string_table {
@@ -58,14 +54,12 @@ struct pvr2_string_table {
        unsigned int cnt;
 };
 
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
 // Names of other client modules to request for 24xxx model hardware
 static const char *pvr2_client_24xxx[] = {
        "cx25840",
        "tuner",
        "wm8775",
 };
-#endif
 
 // Names of other client modules to request for 29xxx model hardware
 static const char *pvr2_client_29xxx[] = {
@@ -79,12 +73,10 @@ static struct pvr2_string_table pvr2_client_lists[] = {
                pvr2_client_29xxx,
                sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
        },
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
        [PVR2_HDW_TYPE_24XXX] = {
                pvr2_client_24xxx,
                sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
        },
-#endif
 };
 
 static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
@@ -221,14 +213,15 @@ static const struct pvr2_mpeg_ids mpeg_ids[] = {
 };
 #define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
 
+
 static const char *control_values_srate[] = {
-       [PVR2_CVAL_SRATE_48]   = "48KHz",
-       [PVR2_CVAL_SRATE_44_1] = "44.1KHz",
+       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100]   = "44.1 kHz",
+       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000]   = "48 kHz",
+       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000]   = "32 kHz",
 };
 
 
 
-
 static const char *control_values_input[] = {
        [PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
        [PVR2_CVAL_INPUT_RADIO]     = "radio",
@@ -362,6 +355,50 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
        return 0;
 }
 
+static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* If we're dealing with a 24xxx device, force the horizontal
+          maximum to be 720 no matter what, since we can't get the device
+          to work properly with any other value.  Otherwise just return
+          the normal value. */
+       *vp = cptr->info->def.type_int.max_value;
+       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
+       return 0;
+}
+
+static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* If we're dealing with a 24xxx device, force the horizontal
+          minimum to be 720 no matter what, since we can't get the device
+          to work properly with any other value.  Otherwise just return
+          the normal value. */
+       *vp = cptr->info->def.type_int.min_value;
+       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
+       return 0;
+}
+
+static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* Actual maximum depends on the video standard in effect. */
+       if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) {
+               *vp = 480;
+       } else {
+               *vp = 576;
+       }
+       return 0;
+}
+
+static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* Actual minimum depends on device type. */
+       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+               *vp = 75;
+       } else {
+               *vp = 17;
+       }
+       return 0;
+}
+
 static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
 {
        return cptr->hdw->enc_stale != 0;
@@ -719,19 +756,27 @@ static const struct pvr2_ctl_info control_defs[] = {
                .internal_id = PVR2_CID_HRES,
                .default_value = 720,
                DEFREF(res_hor),
-               DEFINT(320,720),
+               DEFINT(19,720),
+               /* Hook in check for clamp on horizontal resolution in
+                  order to avoid unsolved problem involving cx25840. */
+               .get_max_value = ctrl_hres_max_get,
+               .get_min_value = ctrl_hres_min_get,
        },{
                .desc = "Vertical capture resolution",
                .name = "resolution_ver",
                .internal_id = PVR2_CID_VRES,
                .default_value = 480,
                DEFREF(res_ver),
-               DEFINT(200,625),
+               DEFINT(17,576),
+               /* Hook in check for video standard and adjust maximum
+                  depending on the standard. */
+               .get_max_value = ctrl_vres_max_get,
+               .get_min_value = ctrl_vres_min_get,
        },{
                .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
-               .desc = "Sample rate",
+               .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+               .desc = "Audio Sampling Frequency",
                .name = "srate",
-               .default_value = PVR2_CVAL_SRATE_48,
                DEFREF(srate),
                DEFENUM(control_values_srate),
        },{
@@ -935,22 +980,18 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
        static const char *fw_files_29xxx[] = {
                "v4l-pvrusb2-29xxx-01.fw",
        };
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
        static const char *fw_files_24xxx[] = {
                "v4l-pvrusb2-24xxx-01.fw",
        };
-#endif
        static const struct pvr2_string_table fw_file_defs[] = {
                [PVR2_HDW_TYPE_29XXX] = {
                        fw_files_29xxx,
                        sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
                },
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
                [PVR2_HDW_TYPE_24XXX] = {
                        fw_files_24xxx,
                        sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
                },
-#endif
        };
        hdw->fw1_state = FW1_STATE_FAILED; // default result
 
@@ -2237,11 +2278,14 @@ static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
        }
 
        if (hdw->std_dirty ||
+           hdw->enc_stale ||
+           hdw->srate_dirty ||
+           hdw->res_ver_dirty ||
+           hdw->res_hor_dirty ||
            0) {
                /* If any of this changes, then the encoder needs to be
                   reconfigured, and we need to reset the stream. */
                stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
-               stale_subsys_mask |= hdw->subsys_stream_mask;
        }
 
        if (hdw->srate_dirty) {
index fbe6039aeb6a8a5c588c3c7f1a81b389c54f5ae0..ed3e8105292a23b807c5267e1216ab851d524821 100644 (file)
 #include "pvrusb2-audio.h"
 #include "pvrusb2-tuner.h"
 #include "pvrusb2-video-v4l.h"
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
 #include "pvrusb2-cx2584x-v4l.h"
 #include "pvrusb2-wm8775.h"
-#endif
 
 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
 
@@ -71,7 +69,6 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
                        return;
                }
        }
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
        if (id == I2C_DRIVERID_CX25840) {
                if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
                        return;
@@ -82,7 +79,6 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
                        return;
                }
        }
-#endif
        if (id == I2C_DRIVERID_SAA711X) {
                if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
                        return;
index 8a9933dec9123213ed092a04991f9e8b76b3e387..05ea17afe9037817567c710b4c06e3dae94ddc6b 100644 (file)
@@ -31,7 +31,7 @@ static void set_standard(struct pvr2_hdw *hdw)
        v4l2_std_id vs;
        vs = hdw->std_mask_cur;
        pvr2_trace(PVR2_TRACE_CHIPS,
-                  "i2c v4l2 set_standard(0x%llx)",(__u64)vs);
+                  "i2c v4l2 set_standard(0x%llx)",(long long unsigned)vs);
 
        pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
 }
index 7fca47982277a2ea68a013030a53cf0f584b3dcc..3b9012f8e380671a8595b9bf9847bcc6f2c58242 100644 (file)
@@ -185,8 +185,6 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
        }
 }
 
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
-
 /* This is a special entry point that is entered if an I2C operation is
    attempted to a wm8775 chip on model 24xxx hardware.  Autodetect of this
    part doesn't work, but we know it is really there.  So let's look for
@@ -289,8 +287,6 @@ static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
        return -EIO;
 }
 
-#endif /* CONFIG_VIDEO_PVRUSB2_24XXX */
-
 /* This is a very, very limited I2C adapter implementation.  We can only
    support what we actually know will work on the device... */
 static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
@@ -897,14 +893,12 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
                hdw->i2c_func[idx] = pvr2_i2c_basic_op;
        }
 
-#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
        // If however we're dealing with new hardware, insert some hacks in
        // the I2C transfer stack to let things work better.
        if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
                hdw->i2c_func[0x1b] = i2c_hack_wm8775;
                hdw->i2c_func[0x44] = i2c_hack_cx25840;
        }
-#endif
 
        // Configure the adapter and set up everything else related to it.
        memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
index 8f1a5afdd34e25104466a6dff2b76a952f8c22f4..e976c484c058db621d52a6e90d0ac738c590382b 100644 (file)
@@ -20,7 +20,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
index d1dda5caf4063dd4b14063e25496c4c86ab8a4a2..c294f46db9b9f421c0a7648ec3cdc9e567098fe1 100644 (file)
@@ -19,7 +19,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <asm/semaphore.h>
@@ -40,8 +39,6 @@ struct pvr2_sysfs {
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
        struct pvr2_sysfs_ctl_item *item_first;
        struct pvr2_sysfs_ctl_item *item_last;
-       struct sysfs_ops kops;
-       struct kobj_type ktype;
        struct class_device_attribute attr_v4l_minor_number;
        struct class_device_attribute attr_unit_number;
        int v4l_minor_number_created_ok;
index 0caf70b8c0de94ca873e760a56c8224085f5ed74..3608c2f81df912fa91a6bc33a7db57691d452cd9 100644 (file)
@@ -459,18 +459,26 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                ret = 0;
                switch(vf->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+                       int lmin,lmax;
+                       struct pvr2_ctrl *hcp,*vcp;
                        int h = vf->fmt.pix.height;
                        int w = vf->fmt.pix.width;
-
-                       if (h < 200) {
-                               h = 200;
-                       } else if (h > 625) {
-                               h = 625;
+                       hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
+                       vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
+
+                       lmin = pvr2_ctrl_get_min(hcp);
+                       lmax = pvr2_ctrl_get_max(hcp);
+                       if (w < lmin) {
+                               w = lmin;
+                       } else if (w > lmax) {
+                               w = lmax;
                        }
-                       if (w < 320) {
-                               w = 320;
-                       } else if (w > 720) {
-                               w = 720;
+                       lmin = pvr2_ctrl_get_min(vcp);
+                       lmax = pvr2_ctrl_get_max(vcp);
+                       if (h < lmin) {
+                               h = lmin;
+                       } else if (h > lmax) {
+                               h = lmax;
                        }
 
                        memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
@@ -479,14 +487,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        vf->fmt.pix.height = h;
 
                        if (cmd == VIDIOC_S_FMT) {
-                               pvr2_ctrl_set_value(
-                                       pvr2_hdw_get_ctrl_by_id(hdw,
-                                                               PVR2_CID_HRES),
-                                       vf->fmt.pix.width);
-                               pvr2_ctrl_set_value(
-                                       pvr2_hdw_get_ctrl_by_id(hdw,
-                                                               PVR2_CID_VRES),
-                                       vf->fmt.pix.height);
+                               pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
+                               pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
                        }
                } break;
                case V4L2_BUF_TYPE_VBI_CAPTURE:
index d4703944df9c12c39bb719b311da043da60cb1d9..53c4b5790d5c6dd8aa08bf132dee83c611f0ef27 100644 (file)
@@ -711,7 +711,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
                        case -EOVERFLOW:        errmsg = "Babble (bad cable?)"; break;
                        case -EPROTO:           errmsg = "Bit-stuff error (bad cable?)"; break;
                        case -EILSEQ:           errmsg = "CRC/Timeout (could be anything)"; break;
-                       case -ETIMEDOUT:        errmsg = "NAK (device does not respond)"; break;
+                       case -ETIME:            errmsg = "Device does not respond"; break;
                }
                PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
                /* Give up after a number of contiguous errors on the USB bus.
index 59a187272c831007de3dba1745759abeb0c04653..77bb940a1a4f4159c3a6ceafd41cd839188e5367 100644 (file)
@@ -830,7 +830,6 @@ static struct video_device saa_template =
        .owner    = THIS_MODULE,
        .name     = IF_NAME,
        .type     = VID_TYPE_TELETEXT,
-       .hardware = VID_HARDWARE_SAA5249,
        .fops     = &saa_fops,
        .release  = video_device_release,
        .minor    = -1,
index 19a8d65699f84892be0149e1cacedb48e18a0fdb..bb3fb4387f6500ff04dbadf0e003336798c41dd2 100644 (file)
@@ -713,7 +713,6 @@ static struct video_device saa_template =
        .owner          = THIS_MODULE,
        .name           = IF_NAME,
        .type           = VID_TYPE_TELETEXT,    /*| VID_TYPE_TUNER ?? */
-       .hardware       = VID_HARDWARE_SAA5249,
        .fops           = &saa_fops,
 };
 
index b59c1171727351a52beb6b77286fb977f5c27903..974179d4d3895b2dd3135b245d1e5158c4a8e213 100644 (file)
@@ -1,4 +1,6 @@
-/* saa7115 - Philips SAA7113/SAA7114/SAA7115 video decoder driver
+/* saa711x - Philips SAA711x video decoder driver
+ * This driver can work with saa7111, saa7111a, saa7113, saa7114,
+ *                          saa7115 and saa7118.
  *
  * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
  * the saa7111 driver by Dave Perks.
@@ -16,7 +18,9 @@
  * (2/17/2003)
  *
  * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
- * SAA7113 support by Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     SAA7111, SAA7113 and SAA7118 support
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -33,6 +37,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include "saa711x_regs.h"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -43,7 +48,9 @@
 #include <media/saa7115.h>
 #include <asm/div64.h>
 
-MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");
+#define VRES_60HZ      (480+16)
+
+MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
 MODULE_AUTHOR(  "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
                "Hans Verkuil, Mauro Carvalho Chehab");
 MODULE_LICENSE("GPL");
@@ -54,14 +61,14 @@ module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 static unsigned short normal_i2c[] = {
-               0x4a >> 1, 0x48 >> 1,   /* SAA7113 */
-               0x42 >> 1, 0x40 >> 1,   /* SAA7114 and SAA7115 */
+               0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
+               0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
                I2C_CLIENT_END };
 
 
 I2C_CLIENT_INSMOD;
 
-struct saa7115_state {
+struct saa711x_state {
        v4l2_std_id std;
        int input;
        int enable;
@@ -70,6 +77,8 @@ struct saa7115_state {
        int contrast;
        int hue;
        int sat;
+       int width;
+       int height;
        enum v4l2_chip_ident ident;
        u32 audclk_freq;
        u32 crystal_freq;
@@ -80,420 +89,508 @@ struct saa7115_state {
 
 /* ----------------------------------------------------------------------- */
 
-static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value)
+static inline int saa711x_write(struct i2c_client *client, u8 reg, u8 value)
 {
        return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs)
+/* Sanity routine to check if a register is present */
+static int saa711x_has_reg(const int id, const u8 reg)
 {
+       if (id == V4L2_IDENT_SAA7111)
+               return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
+                      (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
+
+       /* common for saa7113/4/5/8 */
+       if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
+           reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
+           reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
+           reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
+               return 0;
+
+       switch (id) {
+       case V4L2_IDENT_SAA7113:
+               return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
+                      reg != 0x5d && reg < 0x63;
+       case V4L2_IDENT_SAA7114:
+               return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
+                      (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
+                      reg != 0x81 && reg < 0xf0;
+       case V4L2_IDENT_SAA7115:
+               return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
+       case V4L2_IDENT_SAA7118:
+               return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
+                      (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
+                      (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
+       }
+       return 1;
+}
+
+static int saa711x_writeregs(struct i2c_client *client, const unsigned char *regs)
+{
+       struct saa711x_state *state = i2c_get_clientdata(client);
        unsigned char reg, data;
 
        while (*regs != 0x00) {
                reg = *(regs++);
                data = *(regs++);
-               if (saa7115_write(client, reg, data) < 0)
-                       return -1;
+
+               /* According with datasheets, reserved regs should be
+                  filled with 0 - seems better not to touch on they */
+               if (saa711x_has_reg(state->ident,reg)) {
+                       if (saa711x_write(client, reg, data) < 0)
+                               return -1;
+               } else {
+                       v4l_dbg(1, debug, client, "tried to access reserved reg 0x%02x\n", reg);
+               }
        }
        return 0;
 }
 
-static inline int saa7115_read(struct i2c_client *client, u8 reg)
+static inline int saa711x_read(struct i2c_client *client, u8 reg)
 {
        return i2c_smbus_read_byte_data(client, reg);
 }
 
 /* ----------------------------------------------------------------------- */
 
+/* SAA7111 initialization table */
+static const unsigned char saa7111_init[] = {
+       R_01_INC_DELAY, 0x00,           /* reserved */
+
+       /*front end */
+       R_02_INPUT_CNTL_1, 0xd0,        /* FUSE=3, GUDL=2, MODE=0 */
+       R_03_INPUT_CNTL_2, 0x23,        /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
+                                        * GAFIX=0, GAI1=256, GAI2=256 */
+       R_04_INPUT_CNTL_3, 0x00,        /* GAI1=256 */
+       R_05_INPUT_CNTL_4, 0x00,        /* GAI2=256 */
+
+       /* decoder */
+       R_06_H_SYNC_START, 0xf3,        /* HSB at  13(50Hz) /  17(60Hz)
+                                        * pixels after end of last line */
+       R_07_H_SYNC_STOP, 0xe8,         /* HSS seems to be needed to
+                                        * work with NTSC, too */
+       R_08_SYNC_CNTL, 0xc8,           /* AUFD=1, FSEL=1, EXFIL=0,
+                                        * VTRC=1, HPLL=0, VNOI=0 */
+       R_09_LUMA_CNTL, 0x01,           /* BYPS=0, PREF=0, BPSS=0,
+                                        * VBLB=0, UPTCV=0, APER=1 */
+       R_0A_LUMA_BRIGHT_CNTL, 0x80,
+       R_0B_LUMA_CONTRAST_CNTL, 0x47,  /* 0b - CONT=1.109 */
+       R_0C_CHROMA_SAT_CNTL, 0x40,
+       R_0D_CHROMA_HUE_CNTL, 0x00,
+       R_0E_CHROMA_CNTL_1, 0x01,       /* 0e - CDTO=0, CSTD=0, DCCF=0,
+                                        * FCTC=0, CHBW=1 */
+       R_0F_CHROMA_GAIN_CNTL, 0x00,    /* reserved */
+       R_10_CHROMA_CNTL_2, 0x48,       /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
+       R_11_MODE_DELAY_CNTL, 0x1c,     /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
+                                        * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
+       R_12_RT_SIGNAL_CNTL, 0x00,      /* 12 - output control 2 */
+       R_13_RT_X_PORT_OUT_CNTL, 0x00,  /* 13 - output control 3 */
+       R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
+       R_15_VGATE_START_FID_CHG, 0x00,
+       R_16_VGATE_STOP, 0x00,
+       R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
+
+       0x00, 0x00
+};
+
+/* SAA7113 init codes */
+static const unsigned char saa7113_init[] = {
+       R_01_INC_DELAY, 0x08,
+       R_02_INPUT_CNTL_1, 0xc2,
+       R_03_INPUT_CNTL_2, 0x30,
+       R_04_INPUT_CNTL_3, 0x00,
+       R_05_INPUT_CNTL_4, 0x00,
+       R_06_H_SYNC_START, 0x89,
+       R_07_H_SYNC_STOP, 0x0d,
+       R_08_SYNC_CNTL, 0x88,
+       R_09_LUMA_CNTL, 0x01,
+       R_0A_LUMA_BRIGHT_CNTL, 0x80,
+       R_0B_LUMA_CONTRAST_CNTL, 0x47,
+       R_0C_CHROMA_SAT_CNTL, 0x40,
+       R_0D_CHROMA_HUE_CNTL, 0x00,
+       R_0E_CHROMA_CNTL_1, 0x01,
+       R_0F_CHROMA_GAIN_CNTL, 0x2a,
+       R_10_CHROMA_CNTL_2, 0x08,
+       R_11_MODE_DELAY_CNTL, 0x0c,
+       R_12_RT_SIGNAL_CNTL, 0x07,
+       R_13_RT_X_PORT_OUT_CNTL, 0x00,
+       R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
+       R_15_VGATE_START_FID_CHG, 0x00,
+       R_16_VGATE_STOP, 0x00,
+       R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
+
+       0x00, 0x00
+};
+
 /* If a value differs from the Hauppauge driver values, then the comment starts with
    'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
    Hauppauge driver sets. */
 
+/* SAA7114 and SAA7115 initialization table */
 static const unsigned char saa7115_init_auto_input[] = {
                /* Front-End Part */
-       0x01, 0x48,             /* white peak control disabled */
-       0x03, 0x20,             /* was 0x30. 0x20: long vertical blanking */
-       0x04, 0x90,             /* analog gain set to 0 */
-       0x05, 0x90,             /* analog gain set to 0 */
+       R_01_INC_DELAY, 0x48,                   /* white peak control disabled */
+       R_03_INPUT_CNTL_2, 0x20,                /* was 0x30. 0x20: long vertical blanking */
+       R_04_INPUT_CNTL_3, 0x90,                /* analog gain set to 0 */
+       R_05_INPUT_CNTL_4, 0x90,                /* analog gain set to 0 */
                /* Decoder Part */
-       0x06, 0xeb,             /* horiz sync begin = -21 */
-       0x07, 0xe0,             /* horiz sync stop = -17 */
-       0x0a, 0x80,             /* was 0x88. decoder brightness, 0x80 is itu standard */
-       0x0b, 0x44,             /* was 0x48. decoder contrast, 0x44 is itu standard */
-       0x0c, 0x40,             /* was 0x47. decoder saturation, 0x40 is itu standard */
-       0x0d, 0x00,             /* chrominance hue control */
-       0x0f, 0x00,             /* chrominance gain control: use automicatic mode */
-       0x10, 0x06,             /* chrominance/luminance control: active adaptive combfilter */
-       0x11, 0x00,             /* delay control */
-       0x12, 0x9d,             /* RTS0 output control: VGATE */
-       0x13, 0x80,             /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */
-       0x14, 0x00,             /* analog/ADC/auto compatibility control */
-       0x18, 0x40,             /* raw data gain 0x00 = nominal */
-       0x19, 0x80,             /* raw data offset 0x80 = 0 LSB */
-       0x1a, 0x77,             /* color killer level control 0x77 = recommended */
-       0x1b, 0x42,             /* misc chroma control 0x42 = recommended */
-       0x1c, 0xa9,             /* combfilter control 0xA9 = recommended */
-       0x1d, 0x01,             /* combfilter control 0x01 = recommended */
+       R_06_H_SYNC_START, 0xeb,                /* horiz sync begin = -21 */
+       R_07_H_SYNC_STOP, 0xe0,                 /* horiz sync stop = -17 */
+       R_09_LUMA_CNTL, 0x53,                   /* 0x53, was 0x56 for 60hz. luminance control */
+       R_0A_LUMA_BRIGHT_CNTL, 0x80,            /* was 0x88. decoder brightness, 0x80 is itu standard */
+       R_0B_LUMA_CONTRAST_CNTL, 0x44,          /* was 0x48. decoder contrast, 0x44 is itu standard */
+       R_0C_CHROMA_SAT_CNTL, 0x40,             /* was 0x47. decoder saturation, 0x40 is itu standard */
+       R_0D_CHROMA_HUE_CNTL, 0x00,
+       R_0F_CHROMA_GAIN_CNTL, 0x00,            /* use automatic gain  */
+       R_10_CHROMA_CNTL_2, 0x06,               /* chroma: active adaptive combfilter */
+       R_11_MODE_DELAY_CNTL, 0x00,
+       R_12_RT_SIGNAL_CNTL, 0x9d,              /* RTS0 output control: VGATE */
+       R_13_RT_X_PORT_OUT_CNTL, 0x80,          /* ITU656 standard mode, RTCO output enable RTCE */
+       R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
+       R_18_RAW_DATA_GAIN_CNTL, 0x40,          /* gain 0x00 = nominal */
+       R_19_RAW_DATA_OFF_CNTL, 0x80,
+       R_1A_COLOR_KILL_LVL_CNTL, 0x77,         /* recommended value */
+       R_1B_MISC_TVVCRDET, 0x42,               /* recommended value */
+       R_1C_ENHAN_COMB_CTRL1, 0xa9,            /* recommended value */
+       R_1D_ENHAN_COMB_CTRL2, 0x01,            /* recommended value */
+
+
+       R_80_GLOBAL_CNTL_1, 0x0,                /* No tasks enabled at init */
 
                /* Power Device Control */
-       0x88, 0xd0,             /* reset device */
-       0x88, 0xf0,             /* set device programmed, all in operational mode */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,    /* reset device */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,    /* set device programmed, all in operational mode */
        0x00, 0x00
 };
 
+/* Used to reset saa7113, saa7114 and saa7115 */
 static const unsigned char saa7115_cfg_reset_scaler[] = {
-       0x87, 0x00,             /* disable I-port output */
-       0x88, 0xd0,             /* reset scaler */
-       0x88, 0xf0,             /* activate scaler */
-       0x87, 0x01,             /* enable I-port output */
+       R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00,    /* disable I-port output */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,            /* reset scaler */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,            /* activate scaler */
+       R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,    /* enable I-port output */
        0x00, 0x00
 };
 
 /* ============== SAA7715 VIDEO templates =============  */
 
-static const unsigned char saa7115_cfg_60hz_fullres_x[] = {
-       0xcc, 0xd0,             /* hsize low (output), hor. output window size = 0x2d0 = 720 */
-       0xcd, 0x02,             /* hsize hi (output) */
+static const unsigned char saa7115_cfg_60hz_video[] = {
+       R_80_GLOBAL_CNTL_1, 0x00,                       /* reset tasks */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,            /* reset scaler */
 
-       /* Why not in 60hz-Land, too? */
-       0xd0, 0x01,             /* downscale = 1 */
-       0xd8, 0x00,             /* hor lum scaling 0x0400 = 1 */
-       0xd9, 0x04,
-       0xdc, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
-       0xdd, 0x02,             /* H-scaling incr chroma */
+       R_15_VGATE_START_FID_CHG, 0x03,
+       R_16_VGATE_STOP, 0x11,
+       R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
 
-       0x00, 0x00
-};
-static const unsigned char saa7115_cfg_60hz_fullres_y[] = {
-       0xce, 0xf8,             /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */
-       0xcf, 0x00,             /* vsize hi (output) */
+       R_08_SYNC_CNTL, 0x68,                   /* 0xBO: auto detection, 0x68 = NTSC */
+       R_0E_CHROMA_CNTL_1, 0x07,               /* video autodetection is on */
 
-       /* Why not in 60hz-Land, too? */
-       0xd5, 0x40,             /* Lum contrast, nominal value = 0x40 */
-       0xd6, 0x40,             /* Chroma satur. nominal value = 0x80 */
+       R_5A_V_OFF_FOR_SLICER, 0x06,            /* standard 60hz value for ITU656 line counting */
 
-       0xe0, 0x00,             /* V-scaling incr luma low */
-       0xe1, 0x04,             /* " hi */
-       0xe2, 0x00,             /* V-scaling incr chroma low */
-       0xe3, 0x04,             /* " hi */
+       /* Task A */
+       R_90_A_TASK_HANDLING_CNTL, 0x80,
+       R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
+       R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
+       R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
 
-       0x00, 0x00
-};
+       /* hoffset low (input), 0x0002 is minimum */
+       R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
+       R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
 
-static const unsigned char saa7115_cfg_60hz_video[] = {
-       0x80, 0x00,             /* reset tasks */
-       0x88, 0xd0,             /* reset scaler */
+       /* hsize low (input), 0x02d0 = 720 */
+       R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+       R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
 
-       0x15, 0x03,             /* VGATE pulse start */
-       0x16, 0x11,             /* VGATE pulse stop */
-       0x17, 0x9c,             /* VGATE MSB and other values */
+       R_98_A_VERT_INPUT_WINDOW_START, 0x05,
+       R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
 
-       0x08, 0x68,             /* 0xBO: auto detection, 0x68 = NTSC */
-       0x0e, 0x07,             /* lots of different stuff... video autodetection is on */
+       R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
+       R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
 
-       0x5a, 0x06,             /* Vertical offset, standard 60hz value for ITU656 line counting */
+       R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
+       R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
 
-       /* Task A */
-       0x90, 0x80,             /* Task Handling Control */
-       0x91, 0x48,             /* X-port formats/config */
-       0x92, 0x40,             /* Input Ref. signal Def. */
-       0x93, 0x84,             /* I-port config */
-       0x94, 0x01,             /* hoffset low (input), 0x0002 is minimum */
-       0x95, 0x00,             /* hoffset hi (input) */
-       0x96, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
-       0x97, 0x02,             /* hsize hi (input) */
-       0x98, 0x05,             /* voffset low (input) */
-       0x99, 0x00,             /* voffset hi (input) */
-       0x9a, 0x0c,             /* vsize low (input), 0x0c = 12 */
-       0x9b, 0x00,             /* vsize hi (input) */
-       0x9c, 0xa0,             /* hsize low (output), 0x05a0 = 1440 */
-       0x9d, 0x05,             /* hsize hi (output) */
-       0x9e, 0x0c,             /* vsize low (output), 0x0c = 12 */
-       0x9f, 0x00,             /* vsize hi (output) */
+       R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
+       R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
 
        /* Task B */
-       0xc0, 0x00,             /* Task Handling Control */
-       0xc1, 0x08,             /* X-port formats/config */
-       0xc2, 0x00,             /* Input Ref. signal Def. */
-       0xc3, 0x80,             /* I-port config */
-       0xc4, 0x02,             /* hoffset low (input), 0x0002 is minimum */
-       0xc5, 0x00,             /* hoffset hi (input) */
-       0xc6, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
-       0xc7, 0x02,             /* hsize hi (input) */
-       0xc8, 0x12,             /* voffset low (input), 0x12 = 18 */
-       0xc9, 0x00,             /* voffset hi (input) */
-       0xca, 0xf8,             /* vsize low (input), 0xf8 = 248 */
-       0xcb, 0x00,             /* vsize hi (input) */
-       0xcc, 0xd0,             /* hsize low (output), 0x02d0 = 720 */
-       0xcd, 0x02,             /* hsize hi (output) */
-
-       0xf0, 0xad,             /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
-       0xf1, 0x05,             /* low bit with 0xF0 */
-       0xf5, 0xad,             /* Set pulse generator register */
-       0xf6, 0x01,
-
-       0x87, 0x00,             /* Disable I-port output */
-       0x88, 0xd0,             /* reset scaler */
-       0x80, 0x20,             /* Activate only task "B", continuous mode (was 0xA0) */
-       0x88, 0xf0,             /* activate scaler */
-       0x87, 0x01,             /* Enable I-port output */
-       0x00, 0x00
-};
+       R_C0_B_TASK_HANDLING_CNTL, 0x00,
+       R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
+       R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
+       R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
 
-static const unsigned char saa7115_cfg_50hz_fullres_x[] = {
-       0xcc, 0xd0,             /* hsize low (output), 720 same as 60hz */
-       0xcd, 0x02,             /* hsize hi (output) */
+       /* 0x0002 is minimum */
+       R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
+       R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
 
-       0xd0, 0x01,             /* down scale = 1 */
-       0xd8, 0x00,             /* hor lum scaling 0x0400 = 1 */
-       0xd9, 0x04,
-       0xdc, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
-       0xdd, 0x02,             /* H-scaling incr chroma */
+       /* 0x02d0 = 720 */
+       R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+       R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
 
-       0x00, 0x00
-};
-static const unsigned char saa7115_cfg_50hz_fullres_y[] = {
-       0xce, 0x20,             /* vsize low (output), 0x0120 = 288 */
-       0xcf, 0x01,             /* vsize hi (output) */
+       /* vwindow start 0x12 = 18 */
+       R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
+       R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+       /* vwindow length 0xf8 = 248 */
+       R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
+       R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
 
-       0xd5, 0x40,             /* Lum contrast, nominal value = 0x40 */
-       0xd6, 0x40,             /* Chroma satur. nominal value = 0x80 */
+       /* hwindow 0x02d0 = 720 */
+       R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
+       R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
 
-       0xe0, 0x00,             /* V-scaling incr luma low */
-       0xe1, 0x04,             /* " hi */
-       0xe2, 0x00,             /* V-scaling incr chroma low */
-       0xe3, 0x04,             /* " hi */
+       R_F0_LFCO_PER_LINE, 0xad,               /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
+       R_F1_P_I_PARAM_SELECT, 0x05,            /* low bit with 0xF0 */
+       R_F5_PULSGEN_LINE_LENGTH, 0xad,
+       R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
 
        0x00, 0x00
 };
 
 static const unsigned char saa7115_cfg_50hz_video[] = {
-       0x80, 0x00,             /* reset tasks */
-       0x88, 0xd0,             /* reset scaler */
+       R_80_GLOBAL_CNTL_1, 0x00,
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,    /* reset scaler */
 
-       0x15, 0x37,             /* VGATE start */
-       0x16, 0x16,             /* VGATE stop */
-       0x17, 0x99,             /* VGATE MSB and other values */
+       R_15_VGATE_START_FID_CHG, 0x37,         /* VGATE start */
+       R_16_VGATE_STOP, 0x16,
+       R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
 
-       0x08, 0x28,             /* 0x28 = PAL */
-       0x0e, 0x07,             /* chrominance control 1 */
+       R_08_SYNC_CNTL, 0x28,                   /* 0x28 = PAL */
+       R_0E_CHROMA_CNTL_1, 0x07,
 
-       0x5a, 0x03,             /* Vertical offset, standard 50hz value */
+       R_5A_V_OFF_FOR_SLICER, 0x03,            /* standard 50hz value */
 
        /* Task A */
-       0x90, 0x81,             /* Task Handling Control */
-       0x91, 0x48,             /* X-port formats/config */
-       0x92, 0x40,             /* Input Ref. signal Def. */
-       0x93, 0x84,             /* I-port config */
+       R_90_A_TASK_HANDLING_CNTL, 0x81,
+       R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
+       R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
+       R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
+
        /* This is weird: the datasheet says that you should use 2 as the minimum value, */
        /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
-       0x94, 0x00,             /* hoffset low (input), 0x0002 is minimum */
-       0x95, 0x00,             /* hoffset hi (input) */
-       0x96, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
-       0x97, 0x02,             /* hsize hi (input) */
-       0x98, 0x03,             /* voffset low (input) */
-       0x99, 0x00,             /* voffset hi (input) */
-       0x9a, 0x12,             /* vsize low (input), 0x12 = 18 */
-       0x9b, 0x00,             /* vsize hi (input) */
-       0x9c, 0xa0,             /* hsize low (output), 0x05a0 = 1440 */
-       0x9d, 0x05,             /* hsize hi (output) */
-       0x9e, 0x12,             /* vsize low (output), 0x12 = 18 */
-       0x9f, 0x00,             /* vsize hi (output) */
+       /* hoffset low (input), 0x0002 is minimum */
+       R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
+       R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
+
+       /* hsize low (input), 0x02d0 = 720 */
+       R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+       R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
+
+       R_98_A_VERT_INPUT_WINDOW_START, 0x03,
+       R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+       /* vsize 0x12 = 18 */
+       R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
+       R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
+
+       /* hsize 0x05a0 = 1440 */
+       R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
+       R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,    /* hsize hi (output) */
+       R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12,         /* vsize low (output), 0x12 = 18 */
+       R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,     /* vsize hi (output) */
 
        /* Task B */
-       0xc0, 0x00,             /* Task Handling Control */
-       0xc1, 0x08,             /* X-port formats/config */
-       0xc2, 0x00,             /* Input Ref. signal Def. */
-       0xc3, 0x80,             /* I-port config */
-       0xc4, 0x00,             /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */
-       0xc5, 0x00,             /* hoffset hi (input) */
-       0xc6, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
-       0xc7, 0x02,             /* hsize hi (input) */
-       0xc8, 0x16,             /* voffset low (input), 0x16 = 22 */
-       0xc9, 0x00,             /* voffset hi (input) */
-       0xca, 0x20,             /* vsize low (input), 0x0120 = 288 */
-       0xcb, 0x01,             /* vsize hi (input) */
-       0xcc, 0xd0,             /* hsize low (output), 0x02d0 = 720 */
-       0xcd, 0x02,             /* hsize hi (output) */
-       0xce, 0x20,             /* vsize low (output), 0x0120 = 288 */
-       0xcf, 0x01,             /* vsize hi (output) */
-
-       0xf0, 0xb0,             /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
-       0xf1, 0x05,             /* low bit with 0xF0, (was 0x05) */
-       0xf5, 0xb0,             /* Set pulse generator register */
-       0xf6, 0x01,
-
-       0x87, 0x00,             /* Disable I-port output */
-       0x88, 0xd0,             /* reset scaler (was 0xD0) */
-       0x80, 0x20,             /* Activate only task "B" */
-       0x88, 0xf0,             /* activate scaler */
-       0x87, 0x01,             /* Enable I-port output */
+       R_C0_B_TASK_HANDLING_CNTL, 0x00,
+       R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
+       R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
+       R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
+
+       /* This is weird: the datasheet says that you should use 2 as the minimum value, */
+       /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
+       /* hoffset low (input), 0x0002 is minimum. See comment above. */
+       R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
+       R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
+
+       /* hsize 0x02d0 = 720 */
+       R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+       R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
+
+       /* voffset 0x16 = 22 */
+       R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
+       R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+       /* vsize 0x0120 = 288 */
+       R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
+       R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
+
+       /* hsize 0x02d0 = 720 */
+       R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
+       R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
+
+       R_F0_LFCO_PER_LINE, 0xb0,               /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
+       R_F1_P_I_PARAM_SELECT, 0x05,            /* low bit with 0xF0, (was 0x05) */
+       R_F5_PULSGEN_LINE_LENGTH, 0xb0,
+       R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
+
        0x00, 0x00
 };
 
 /* ============== SAA7715 VIDEO templates (end) =======  */
 
 static const unsigned char saa7115_cfg_vbi_on[] = {
-       0x80, 0x00,             /* reset tasks */
-       0x88, 0xd0,             /* reset scaler */
-       0x80, 0x30,             /* Activate both tasks */
-       0x88, 0xf0,             /* activate scaler */
-       0x87, 0x01,             /* Enable I-port output */
+       R_80_GLOBAL_CNTL_1, 0x00,                       /* reset tasks */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,            /* reset scaler */
+       R_80_GLOBAL_CNTL_1, 0x30,                       /* Activate both tasks */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,            /* activate scaler */
+       R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,    /* Enable I-port output */
+
        0x00, 0x00
 };
 
 static const unsigned char saa7115_cfg_vbi_off[] = {
-       0x80, 0x00,             /* reset tasks */
-       0x88, 0xd0,             /* reset scaler */
-       0x80, 0x20,             /* Activate only task "B" */
-       0x88, 0xf0,             /* activate scaler */
-       0x87, 0x01,             /* Enable I-port output */
-       0x00, 0x00
-};
+       R_80_GLOBAL_CNTL_1, 0x00,                       /* reset tasks */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,            /* reset scaler */
+       R_80_GLOBAL_CNTL_1, 0x20,                       /* Activate only task "B" */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,            /* activate scaler */
+       R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,    /* Enable I-port output */
 
-static const unsigned char saa7113_init_auto_input[] = {
-       0x01, 0x08,     /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */
-       0x02, 0xc2,     /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */
-       0x03, 0x30,     /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */
-       0x04, 0x00,     /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */
-       0x05, 0x00,     /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */
-       0x06, 0x89,     /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */
-       0x07, 0x0d,     /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */
-       0x08, 0x88,     /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */
-       0x09, 0x01,     /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */
-       0x0a, 0x80,     /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */
-       0x0b, 0x47,     /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */
-       0x0c, 0x40,     /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */
-       0x0d, 0x00,     /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */
-       0x0e, 0x01,     /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */
-       0x0f, 0x2a,     /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */
-       0x10, 0x08,     /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */
-       0x11, 0x0c,     /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */
-       0x12, 0x07,     /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */
-       0x13, 0x00,     /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */
-       0x14, 0x00,     /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */
-       0x15, 0x00,     /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */
-       0x16, 0x00,     /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */
-       0x17, 0x00,     /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */
        0x00, 0x00
 };
 
+
 static const unsigned char saa7115_init_misc[] = {
-       0x81, 0x01,             /* reg 0x15,0x16 define blanking window */
-       0x82, 0x00,
-       0x83, 0x01,             /* I port settings */
-       0x84, 0x20,
-       0x85, 0x21,
-       0x86, 0xc5,
-       0x87, 0x01,
+       R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
+       R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
+       R_84_I_PORT_SIGNAL_DEF, 0x20,
+       R_85_I_PORT_SIGNAL_POLAR, 0x21,
+       R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
+       R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
 
        /* Task A */
-       0xa0, 0x01,             /* down scale = 1 */
-       0xa1, 0x00,             /* prescale accumulation length = 1 */
-       0xa2, 0x00,             /* dc gain and fir prefilter control */
-       0xa4, 0x80,             /* Lum Brightness, nominal value = 0x80 */
-       0xa5, 0x40,             /* Lum contrast, nominal value = 0x40 */
-       0xa6, 0x40,             /* Chroma satur. nominal value = 0x80 */
-       0xa8, 0x00,             /* hor lum scaling 0x0200 = 2 zoom */
-       0xa9, 0x02,             /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
-       0xaa, 0x00,             /* H-phase offset Luma = 0 */
-       0xac, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
-       0xad, 0x01,             /* H-scaling incr chroma */
-       0xae, 0x00,             /* H-phase offset chroma. must be offset luma / 2 */
-
-       0xb0, 0x00,             /* V-scaling incr luma low */
-       0xb1, 0x04,             /* " hi */
-       0xb2, 0x00,             /* V-scaling incr chroma low */
-       0xb3, 0x04,             /* " hi */
-       0xb4, 0x01,             /* V-scaling mode control */
-       0xb8, 0x00,             /* V-phase offset chroma 00 */
-       0xb9, 0x00,             /* V-phase offset chroma 01 */
-       0xba, 0x00,             /* V-phase offset chroma 10 */
-       0xbb, 0x00,             /* V-phase offset chroma 11 */
-       0xbc, 0x00,             /* V-phase offset luma 00 */
-       0xbd, 0x00,             /* V-phase offset luma 01 */
-       0xbe, 0x00,             /* V-phase offset luma 10 */
-       0xbf, 0x00,             /* V-phase offset luma 11 */
+       R_A0_A_HORIZ_PRESCALING, 0x01,
+       R_A1_A_ACCUMULATION_LENGTH, 0x00,
+       R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
+
+       /* Configure controls at nominal value*/
+       R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
+       R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
+       R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
+
+       /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
+       R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
+       R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
+
+       R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
+
+       /* must be horiz lum scaling / 2 */
+       R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
+       R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
+
+       /* must be offset luma / 2 */
+       R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
+
+       R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
+       R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
+
+       R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
+       R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
+
+       R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
+
+       R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
+       R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
+       R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
+       R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
+
+       R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
+       R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
+       R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
+       R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
 
        /* Task B */
-       0xd0, 0x01,             /* down scale = 1 */
-       0xd1, 0x00,             /* prescale accumulation length = 1 */
-       0xd2, 0x00,             /* dc gain and fir prefilter control */
-       0xd4, 0x80,             /* Lum Brightness, nominal value = 0x80 */
-       0xd5, 0x40,             /* Lum contrast, nominal value = 0x40 */
-       0xd6, 0x40,             /* Chroma satur. nominal value = 0x80 */
-       0xd8, 0x00,             /* hor lum scaling 0x0400 = 1 */
-       0xd9, 0x04,
-       0xda, 0x00,             /* H-phase offset Luma = 0 */
-       0xdc, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
-       0xdd, 0x02,             /* H-scaling incr chroma */
-       0xde, 0x00,             /* H-phase offset chroma. must be offset luma / 2 */
-
-       0xe0, 0x00,             /* V-scaling incr luma low */
-       0xe1, 0x04,             /* " hi */
-       0xe2, 0x00,             /* V-scaling incr chroma low */
-       0xe3, 0x04,             /* " hi */
-       0xe4, 0x01,             /* V-scaling mode control */
-       0xe8, 0x00,             /* V-phase offset chroma 00 */
-       0xe9, 0x00,             /* V-phase offset chroma 01 */
-       0xea, 0x00,             /* V-phase offset chroma 10 */
-       0xeb, 0x00,             /* V-phase offset chroma 11 */
-       0xec, 0x00,             /* V-phase offset luma 00 */
-       0xed, 0x00,             /* V-phase offset luma 01 */
-       0xee, 0x00,             /* V-phase offset luma 10 */
-       0xef, 0x00,             /* V-phase offset luma 11 */
-
-       0xf2, 0x50,             /* crystal clock = 24.576 MHz, target = 27MHz */
-       0xf3, 0x46,
-       0xf4, 0x00,
-       0xf7, 0x4b,             /* not the recommended settings! */
-       0xf8, 0x00,
-       0xf9, 0x4b,
-       0xfa, 0x00,
-       0xfb, 0x4b,
-       0xff, 0x88,             /* PLL2 lock detection settings: 71 lines 50% phase error */
+       R_D0_B_HORIZ_PRESCALING, 0x01,
+       R_D1_B_ACCUMULATION_LENGTH, 0x00,
+       R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
+
+       /* Configure controls at nominal value*/
+       R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
+       R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
+       R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
+
+       /* hor lum scaling 0x0400 = 1 */
+       R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
+       R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
+
+       R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
+
+       /* must be hor lum scaling / 2 */
+       R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
+       R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
+
+       /* must be offset luma / 2 */
+       R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
+
+       R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
+       R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
+
+       R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
+       R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
+
+       R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
+
+       R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
+       R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
+       R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
+       R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
+
+       R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
+       R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
+       R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
+       R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
+
+       R_F2_NOMINAL_PLL2_DTO, 0x50,            /* crystal clock = 24.576 MHz, target = 27MHz */
+       R_F3_PLL_INCREMENT, 0x46,
+       R_F4_PLL2_STATUS, 0x00,
+       R_F7_PULSE_A_POS_MSB, 0x4b,             /* not the recommended settings! */
+       R_F8_PULSE_B_POS, 0x00,
+       R_F9_PULSE_B_POS_MSB, 0x4b,
+       R_FA_PULSE_C_POS, 0x00,
+       R_FB_PULSE_C_POS_MSB, 0x4b,
+
+       /* PLL2 lock detection settings: 71 lines 50% phase error */
+       R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
 
        /* Turn off VBI */
-       0x40, 0x20,             /* No framing code errors allowed. */
-       0x41, 0xff,
-       0x42, 0xff,
-       0x43, 0xff,
-       0x44, 0xff,
-       0x45, 0xff,
-       0x46, 0xff,
-       0x47, 0xff,
-       0x48, 0xff,
-       0x49, 0xff,
-       0x4a, 0xff,
-       0x4b, 0xff,
-       0x4c, 0xff,
-       0x4d, 0xff,
-       0x4e, 0xff,
-       0x4f, 0xff,
-       0x50, 0xff,
-       0x51, 0xff,
-       0x52, 0xff,
-       0x53, 0xff,
-       0x54, 0xff,
-       0x55, 0xff,
-       0x56, 0xff,
-       0x57, 0xff,
-       0x58, 0x40,
-       0x59, 0x47,
-       0x5b, 0x83,
-       0x5d, 0xbd,
-       0x5e, 0x35,
-
-       0x02, 0x84,             /* input tuner -> input 4, amplifier active */
-       0x09, 0x53,             /* 0x53, was 0x56 for 60hz. luminance control */
-
-       0x80, 0x20,             /* enable task B */
-       0x88, 0xd0,
-       0x88, 0xf0,
+       R_40_SLICER_CNTL_1, 0x20,             /* No framing code errors allowed. */
+       R_41_LCR_BASE, 0xff,
+       R_41_LCR_BASE+1, 0xff,
+       R_41_LCR_BASE+2, 0xff,
+       R_41_LCR_BASE+3, 0xff,
+       R_41_LCR_BASE+4, 0xff,
+       R_41_LCR_BASE+5, 0xff,
+       R_41_LCR_BASE+6, 0xff,
+       R_41_LCR_BASE+7, 0xff,
+       R_41_LCR_BASE+8, 0xff,
+       R_41_LCR_BASE+9, 0xff,
+       R_41_LCR_BASE+10, 0xff,
+       R_41_LCR_BASE+11, 0xff,
+       R_41_LCR_BASE+12, 0xff,
+       R_41_LCR_BASE+13, 0xff,
+       R_41_LCR_BASE+14, 0xff,
+       R_41_LCR_BASE+15, 0xff,
+       R_41_LCR_BASE+16, 0xff,
+       R_41_LCR_BASE+17, 0xff,
+       R_41_LCR_BASE+18, 0xff,
+       R_41_LCR_BASE+19, 0xff,
+       R_41_LCR_BASE+20, 0xff,
+       R_41_LCR_BASE+21, 0xff,
+       R_41_LCR_BASE+22, 0xff,
+       R_58_PROGRAM_FRAMING_CODE, 0x40,
+       R_59_H_OFF_FOR_SLICER, 0x47,
+       R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
+       R_5D_DID, 0xbd,
+       R_5E_SDID, 0x35,
+
+       R_02_INPUT_CNTL_1, 0x84,                /* input tuner -> input 4, amplifier active */
+
+       R_80_GLOBAL_CNTL_1, 0x20,               /* enable task B */
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
+       R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
        0x00, 0x00
 };
 
-static int saa7115_odd_parity(u8 c)
+static int saa711x_odd_parity(u8 c)
 {
        c ^= (c >> 4);
        c ^= (c >> 2);
@@ -502,7 +599,7 @@ static int saa7115_odd_parity(u8 c)
        return c & 1;
 }
 
-static int saa7115_decode_vps(u8 * dst, u8 * p)
+static int saa711x_decode_vps(u8 * dst, u8 * p)
 {
        static const u8 biphase_tbl[] = {
                0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
@@ -549,7 +646,7 @@ static int saa7115_decode_vps(u8 * dst, u8 * p)
        return err & 0xf0;
 }
 
-static int saa7115_decode_wss(u8 * p)
+static int saa711x_decode_wss(u8 * p)
 {
        static const int wss_bits[8] = {
                0, 0, 0, 1, 0, 1, 1, 1
@@ -576,26 +673,25 @@ static int saa7115_decode_wss(u8 * p)
        return wss;
 }
 
-
-static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
+static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
        u32 acpf;
        u32 acni;
        u32 hz;
        u64 f;
        u8 acc = 0;     /* reg 0x3a, audio clock control */
 
+       /* Checks for chips that don't have audio clock (saa7111, saa7113) */
+       if (!saa711x_has_reg(state->ident,R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
+               return 0;
+
        v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
 
        /* sanity check */
        if (freq < 32000 || freq > 48000)
                return -EINVAL;
 
-       /* The saa7113 has no audio clock */
-       if (state->ident == V4L2_IDENT_SAA7113)
-               return 0;
-
        /* hz is the refresh rate times 100 */
        hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
        /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
@@ -617,22 +713,26 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
        if (state->apll)
                acc |= 0x08;
 
-       saa7115_write(client, 0x38, 0x03);
-       saa7115_write(client, 0x39, 0x10);
-       saa7115_write(client, 0x3a, acc);
-       saa7115_write(client, 0x30, acpf & 0xff);
-       saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
-       saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
-       saa7115_write(client, 0x34, acni & 0xff);
-       saa7115_write(client, 0x35, (acni >> 8) & 0xff);
-       saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
+       saa711x_write(client, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
+       saa711x_write(client, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
+       saa711x_write(client, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
+
+       saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
+       saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
+                                                       (acpf >> 8) & 0xff);
+       saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
+                                                       (acpf >> 16) & 0x03);
+
+       saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
+       saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
+       saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
        state->audclk_freq = freq;
        return 0;
 }
 
-static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
@@ -642,7 +742,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
                }
 
                state->bright = ctrl->value;
-               saa7115_write(client, 0x0a, state->bright);
+               saa711x_write(client, R_0A_LUMA_BRIGHT_CNTL, state->bright);
                break;
 
        case V4L2_CID_CONTRAST:
@@ -652,7 +752,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
                }
 
                state->contrast = ctrl->value;
-               saa7115_write(client, 0x0b, state->contrast);
+               saa711x_write(client, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
                break;
 
        case V4L2_CID_SATURATION:
@@ -662,7 +762,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
                }
 
                state->sat = ctrl->value;
-               saa7115_write(client, 0x0c, state->sat);
+               saa711x_write(client, R_0C_CHROMA_SAT_CNTL, state->sat);
                break;
 
        case V4L2_CID_HUE:
@@ -672,7 +772,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
                }
 
                state->hue = ctrl->value;
-               saa7115_write(client, 0x0d, state->hue);
+               saa711x_write(client, R_0D_CHROMA_HUE_CNTL, state->hue);
                break;
 
        default:
@@ -682,9 +782,9 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
        return 0;
 }
 
-static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
@@ -706,10 +806,115 @@ static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *c
        return 0;
 }
 
-static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+static int saa711x_set_size(struct i2c_client *client, int width, int height)
+{
+       struct saa711x_state *state = i2c_get_clientdata(client);
+       int HPSC, HFSC;
+       int VSCY;
+       int res;
+       int is_50hz = state->std & V4L2_STD_625_50;
+       int Vsrc = is_50hz ? 576 : 480;
+
+       v4l_dbg(1, debug, client, "decoder set size to %ix%i\n",width,height);
+
+       /* FIXME need better bounds checking here */
+       if ((width < 1) || (width > 1440))
+               return -EINVAL;
+       if ((height < 1) || (height > Vsrc))
+               return -EINVAL;
+
+       if (!saa711x_has_reg(state->ident,R_D0_B_HORIZ_PRESCALING)) {
+               /* Decoder only supports 720 columns and 480 or 576 lines */
+               if (width != 720)
+                       return -EINVAL;
+               if (height != Vsrc)
+                       return -EINVAL;
+       }
+
+       state->width = width;
+       state->height = height;
+
+       if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
+               return 0;
+
+       /* probably have a valid size, let's set it */
+       /* Set output width/height */
+       /* width */
+
+       saa711x_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
+                                       (u8) (width & 0xff));
+       saa711x_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
+                                       (u8) ((width >> 8) & 0xff));
+
+       /* Vertical Scaling uses height/2 */
+       res=height/2;
+
+       /* On 60Hz, it is using a higher Vertical Output Size */
+       if (!is_50hz)
+               res+=(VRES_60HZ-480)>>1;
+
+               /* height */
+       saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
+                                       (u8) (res & 0xff));
+       saa711x_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
+                                       (u8) ((res >> 8) & 0xff));
+
+       /* Scaling settings */
+       /* Hprescaler is floor(inres/outres) */
+       HPSC = (int)(720 / width);
+       /* 0 is not allowed (div. by zero) */
+       HPSC = HPSC ? HPSC : 1;
+       HFSC = (int)((1024 * 720) / (HPSC * width));
+       /* FIXME hardcodes to "Task B"
+        * write H prescaler integer */
+       saa711x_write(client, R_D0_B_HORIZ_PRESCALING,
+                               (u8) (HPSC & 0x3f));
+
+       v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
+       /* write H fine-scaling (luminance) */
+       saa711x_write(client, R_D8_B_HORIZ_LUMA_SCALING_INC,
+                               (u8) (HFSC & 0xff));
+       saa711x_write(client, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
+                               (u8) ((HFSC >> 8) & 0xff));
+       /* write H fine-scaling (chrominance)
+        * must be lum/2, so i'll just bitshift :) */
+       saa711x_write(client, R_DC_B_HORIZ_CHROMA_SCALING,
+                               (u8) ((HFSC >> 1) & 0xff));
+       saa711x_write(client, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
+                               (u8) ((HFSC >> 9) & 0xff));
+
+       VSCY = (int)((1024 * Vsrc) / height);
+       v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
+
+       /* Correct Contrast and Luminance */
+       saa711x_write(client, R_D5_B_LUMA_CONTRAST_CNTL,
+                                       (u8) (64 * 1024 / VSCY));
+       saa711x_write(client, R_D6_B_CHROMA_SATURATION_CNTL,
+                                       (u8) (64 * 1024 / VSCY));
+
+               /* write V fine-scaling (luminance) */
+       saa711x_write(client, R_E0_B_VERT_LUMA_SCALING_INC,
+                                       (u8) (VSCY & 0xff));
+       saa711x_write(client, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
+                                       (u8) ((VSCY >> 8) & 0xff));
+               /* write V fine-scaling (chrominance) */
+       saa711x_write(client, R_E2_B_VERT_CHROMA_SCALING_INC,
+                                       (u8) (VSCY & 0xff));
+       saa711x_write(client, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
+                                       (u8) ((VSCY >> 8) & 0xff));
+
+       saa711x_writeregs(client, saa7115_cfg_reset_scaler);
+
+       /* Activates task "B" */
+       saa711x_write(client, R_80_GLOBAL_CNTL_1,
+                               saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20);
+
+       return 0;
+}
+
+static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
-       int taskb = saa7115_read(client, 0x80) & 0x10;
+       struct saa711x_state *state = i2c_get_clientdata(client);
 
        /* Prevent unnecessary standard changes. During a standard
           change the I-Port is temporarily disabled. Any devices
@@ -721,17 +926,21 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
        if (std == state->std)
                return;
 
+       state->std = std;
+
        // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
        if (std & V4L2_STD_525_60) {
                v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
-               saa7115_writeregs(client, saa7115_cfg_60hz_video);
+               saa711x_writeregs(client, saa7115_cfg_60hz_video);
+               saa711x_set_size(client,720,480);
        } else {
                v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
-               saa7115_writeregs(client, saa7115_cfg_50hz_video);
+               saa711x_writeregs(client, saa7115_cfg_50hz_video);
+               saa711x_set_size(client,720,576);
        }
 
        /* Register 0E - Bits D6-D4 on NO-AUTO mode
-               (SAA7113 doesn't have auto mode)
+               (SAA7111 and SAA7113 doesn't have auto mode)
            50 Hz / 625 lines           60 Hz / 525 lines
        000 PAL BGDHI (4.43Mhz)         NTSC M (3.58MHz)
        001 NTSC 4.43 (50 Hz)           PAL 4.43 (60 Hz)
@@ -739,8 +948,9 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
        011 NTSC N (3.58MHz)            PAL M (3.58MHz)
        100 reserved                    NTSC-Japan (3.58MHz)
        */
-       if (state->ident == V4L2_IDENT_SAA7113) {
-               u8 reg = saa7115_read(client, 0x0e) & 0x8f;
+       if (state->ident == V4L2_IDENT_SAA7111 ||
+           state->ident == V4L2_IDENT_SAA7113) {
+               u8 reg = saa711x_read(client, R_0E_CHROMA_CNTL_1) & 0x8f;
 
                if (std == V4L2_STD_PAL_M) {
                        reg |= 0x30;
@@ -751,31 +961,30 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
                } else if (std == V4L2_STD_NTSC_M_JP) {
                        reg |= 0x40;
                }
-               saa7115_write(client, 0x0e, reg);
-       }
-
+               saa711x_write(client, R_0E_CHROMA_CNTL_1, reg);
+       } else {
+               /* restart task B if needed */
+               int taskb = saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10;
 
-       state->std = std;
+               if (taskb && state->ident == V4L2_IDENT_SAA7114) {
+                       saa711x_writeregs(client, saa7115_cfg_vbi_on);
+               }
 
-       /* restart task B if needed */
-       if (taskb && state->ident != V4L2_IDENT_SAA7115) {
-               saa7115_writeregs(client, saa7115_cfg_vbi_on);
+               /* switch audio mode too! */
+               saa711x_set_audio_clock_freq(client, state->audclk_freq);
        }
-
-       /* switch audio mode too! */
-       saa7115_set_audio_clock_freq(client, state->audclk_freq);
 }
 
-static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
+static v4l2_std_id saa711x_get_v4lstd(struct i2c_client *client)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
 
        return state->std;
 }
 
-static void saa7115_log_status(struct i2c_client *client)
+static void saa711x_log_status(struct i2c_client *client)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
        int reg1e, reg1f;
        int signalOk;
        int vcr;
@@ -783,7 +992,7 @@ static void saa7115_log_status(struct i2c_client *client)
        v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq);
        if (state->ident != V4L2_IDENT_SAA7115) {
                /* status for the saa7114 */
-               reg1f = saa7115_read(client, 0x1f);
+               reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);
                signalOk = (reg1f & 0xc1) == 0x81;
                v4l_info(client, "Video signal:    %s\n", signalOk ? "ok" : "bad");
                v4l_info(client, "Frequency:       %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
@@ -791,8 +1000,8 @@ static void saa7115_log_status(struct i2c_client *client)
        }
 
        /* status for the saa7115 */
-       reg1e = saa7115_read(client, 0x1e);
-       reg1f = saa7115_read(client, 0x1f);
+       reg1e = saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC);
+       reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);
 
        signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
        vcr = !(reg1f & 0x10);
@@ -819,19 +1028,27 @@ static void saa7115_log_status(struct i2c_client *client)
                        v4l_info(client, "Detected format: BW/No color\n");
                        break;
        }
+       v4l_info(client, "Width, Height:   %d, %d\n", state->width, state->height);
 }
 
 /* setup the sliced VBI lcr registers according to the sliced VBI format */
-static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt)
+static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
        int is_50hz = (state->std & V4L2_STD_625_50);
        u8 lcr[24];
        int i, x;
 
-       /* saa7113/7114 doesn't yet support VBI */
+#if 1
+       /* saa7113/7114/7118 VBI support are experimental */
+       if (!saa711x_has_reg(state->ident,R_41_LCR_BASE))
+               return;
+
+#else
+       /* SAA7113 and SAA7118 also should support VBI - Need testing */
        if (state->ident != V4L2_IDENT_SAA7115)
                return;
+#endif
 
        for (i = 0; i <= 23; i++)
                lcr[i] = 0xff;
@@ -888,14 +1105,16 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
 
        /* write the lcr registers */
        for (i = 2; i <= 23; i++) {
-               saa7115_write(client, i - 2 + 0x41, lcr[i]);
+               saa711x_write(client, i - 2 + R_41_LCR_BASE, lcr[i]);
        }
 
        /* enable/disable raw VBI capturing */
-       saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off);
+       saa711x_writeregs(client, fmt->service_set == 0 ?
+                               saa7115_cfg_vbi_on :
+                               saa7115_cfg_vbi_off);
 }
 
-static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
+static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 {
        static u16 lcr2vbi[] = {
                0, V4L2_SLICED_TELETEXT_B, 0,   /* 1 */
@@ -911,10 +1130,10 @@ static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
                return -EINVAL;
        memset(sliced, 0, sizeof(*sliced));
        /* done if using raw VBI */
-       if (saa7115_read(client, 0x80) & 0x10)
+       if (saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10)
                return 0;
        for (i = 2; i <= 23; i++) {
-               u8 v = saa7115_read(client, i - 2 + 0x41);
+               u8 v = saa711x_read(client, i - 2 + R_41_LCR_BASE);
 
                sliced->service_lines[0][i] = lcr2vbi[v >> 4];
                sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
@@ -924,114 +1143,31 @@ static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
        return 0;
 }
 
-static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
+static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
-       struct v4l2_pix_format *pix;
-       int HPSC, HFSC;
-       int VSCY, Vsrc;
-       int is_50hz = state->std & V4L2_STD_625_50;
-
        if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
-               saa7115_set_lcr(client, &fmt->fmt.sliced);
+               saa711x_set_lcr(client, &fmt->fmt.sliced);
                return 0;
        }
        if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       pix = &(fmt->fmt.pix);
-
-       v4l_dbg(1, debug, client, "decoder set size\n");
-
-       /* FIXME need better bounds checking here */
-       if ((pix->width < 1) || (pix->width > 1440))
-               return -EINVAL;
-       if ((pix->height < 1) || (pix->height > 960))
-               return -EINVAL;
-
-       /* probably have a valid size, let's set it */
-       /* Set output width/height */
-       /* width */
-       saa7115_write(client, 0xcc, (u8) (pix->width & 0xff));
-       saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff));
-       /* height */
-       saa7115_write(client, 0xce, (u8) (pix->height & 0xff));
-       saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff));
-
-       /* Scaling settings */
-       /* Hprescaler is floor(inres/outres) */
-       /* FIXME hardcoding input res */
-       if (pix->width != 720) {
-               HPSC = (int)(720 / pix->width);
-               /* 0 is not allowed (div. by zero) */
-               HPSC = HPSC ? HPSC : 1;
-               HFSC = (int)((1024 * 720) / (HPSC * pix->width));
-
-               v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
-               /* FIXME hardcodes to "Task B"
-                * write H prescaler integer */
-               saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
-
-               /* write H fine-scaling (luminance) */
-               saa7115_write(client, 0xd8, (u8) (HFSC & 0xff));
-               saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff));
-               /* write H fine-scaling (chrominance)
-                * must be lum/2, so i'll just bitshift :) */
-               saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
-               saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
-       } else {
-               if (is_50hz) {
-                       v4l_dbg(1, debug, client, "Setting full 50hz width\n");
-                       saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
-               } else {
-                       v4l_dbg(1, debug, client, "Setting full 60hz width\n");
-                       saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
-               }
-       }
-
-       Vsrc = is_50hz ? 576 : 480;
-
-       if (pix->height != Vsrc) {
-               VSCY = (int)((1024 * Vsrc) / pix->height);
-               v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
-
-               /* Correct Contrast and Luminance */
-               saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
-               saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY));
-
-               /* write V fine-scaling (luminance) */
-               saa7115_write(client, 0xe0, (u8) (VSCY & 0xff));
-               saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff));
-               /* write V fine-scaling (chrominance) */
-               saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
-               saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
-       } else {
-               if (is_50hz) {
-                       v4l_dbg(1, debug, client, "Setting full 50Hz height\n");
-                       saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
-               } else {
-                       v4l_dbg(1, debug, client, "Setting full 60hz height\n");
-                       saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
-               }
-       }
-
-       saa7115_writeregs(client, saa7115_cfg_reset_scaler);
-       return 0;
+       return saa711x_set_size(client,fmt->fmt.pix.width,fmt->fmt.pix.height);
 }
 
 /* Decode the sliced VBI data stream as created by the saa7115.
    The format is described in the saa7115 datasheet in Tables 25 and 26
    and in Figure 33.
    The current implementation uses SAV/EAV codes and not the ancillary data
-   headers. The vbi->p pointer points to the SDID byte right after the SAV
+   headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
    code. */
-static void saa7115_decode_vbi_line(struct i2c_client *client,
+static void saa711x_decode_vbi_line(struct i2c_client *client,
                                    struct v4l2_decode_vbi_line *vbi)
 {
        static const char vbi_no_data_pattern[] = {
                0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
        };
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
        u8 *p = vbi->p;
        u32 wss;
        int id1, id2;   /* the ID1 and ID2 bytes from the internal header */
@@ -1066,12 +1202,12 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
                vbi->type = V4L2_SLICED_TELETEXT_B;
                break;
        case 4:
-               if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
+               if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
                        return;
                vbi->type = V4L2_SLICED_CAPTION_525;
                break;
        case 5:
-               wss = saa7115_decode_wss(p);
+               wss = saa711x_decode_wss(p);
                if (wss == -1)
                        return;
                p[0] = wss & 0xff;
@@ -1079,7 +1215,7 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
                vbi->type = V4L2_SLICED_WSS_625;
                break;
        case 7:
-               if (saa7115_decode_vps(p, p) != 0)
+               if (saa711x_decode_vps(p, p) != 0)
                        return;
                vbi->type = V4L2_SLICED_VPS;
                break;
@@ -1090,21 +1226,21 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
 
 /* ============ SAA7115 AUDIO settings (end) ============= */
 
-static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
+static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
        int *iarg = arg;
 
        /* ioctls to allow direct access to the saa7115 registers for testing */
        switch (cmd) {
        case VIDIOC_S_FMT:
-               return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg);
+               return saa711x_set_v4lfmt(client, (struct v4l2_format *)arg);
 
        case VIDIOC_G_FMT:
-               return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
+               return saa711x_get_v4lfmt(client, (struct v4l2_format *)arg);
 
        case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-               return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
+               return saa711x_set_audio_clock_freq(client, *(u32 *)arg);
 
        case VIDIOC_G_TUNER:
        {
@@ -1113,7 +1249,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
 
                if (state->radio)
                        break;
-               status = saa7115_read(client, 0x1f);
+               status = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);
 
                v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
                vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
@@ -1121,14 +1257,14 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
        }
 
        case VIDIOC_LOG_STATUS:
-               saa7115_log_status(client);
+               saa711x_log_status(client);
                break;
 
        case VIDIOC_G_CTRL:
-               return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg);
+               return saa711x_get_v4lctrl(client, (struct v4l2_control *)arg);
 
        case VIDIOC_S_CTRL:
-               return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg);
+               return saa711x_set_v4lctrl(client, (struct v4l2_control *)arg);
 
        case VIDIOC_QUERYCTRL:
        {
@@ -1146,12 +1282,12 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
        }
 
        case VIDIOC_G_STD:
-               *(v4l2_std_id *)arg = saa7115_get_v4lstd(client);
+               *(v4l2_std_id *)arg = saa711x_get_v4lstd(client);
                break;
 
        case VIDIOC_S_STD:
                state->radio = 0;
-               saa7115_set_v4lstd(client, *(v4l2_std_id *)arg);
+               saa711x_set_v4lstd(client, *(v4l2_std_id *)arg);
                break;
 
        case AUDC_SET_RADIO:
@@ -1187,13 +1323,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                state->input = route->input;
 
                /* select mode */
-               saa7115_write(client, 0x02,
-                             (saa7115_read(client, 0x02) & 0xf0) |
+               saa711x_write(client, R_02_INPUT_CNTL_1,
+                             (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) |
                               state->input);
 
                /* bypass chrominance trap for S-Video modes */
-               saa7115_write(client, 0x09,
-                             (saa7115_read(client, 0x09) & 0x7f) |
+               saa711x_write(client, R_09_LUMA_CNTL,
+                             (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) |
                               (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
                break;
        }
@@ -1205,7 +1341,9 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
 
                if (state->enable != (cmd == VIDIOC_STREAMON)) {
                        state->enable = (cmd == VIDIOC_STREAMON);
-                       saa7115_write(client, 0x87, state->enable);
+                       saa711x_write(client,
+                               R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED,
+                               state->enable);
                }
                break;
 
@@ -1220,17 +1358,17 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
                state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
                state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
-               saa7115_set_audio_clock_freq(client, state->audclk_freq);
+               saa711x_set_audio_clock_freq(client, state->audclk_freq);
                break;
        }
 
        case VIDIOC_INT_DECODE_VBI_LINE:
-               saa7115_decode_vbi_line(client, arg);
+               saa711x_decode_vbi_line(client, arg);
                break;
 
        case VIDIOC_INT_RESET:
                v4l_dbg(1, debug, client, "decoder RESET\n");
-               saa7115_writeregs(client, saa7115_cfg_reset_scaler);
+               saa711x_writeregs(client, saa7115_cfg_reset_scaler);
                break;
 
        case VIDIOC_INT_G_VBI_DATA:
@@ -1239,25 +1377,25 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
 
                switch (data->id) {
                case V4L2_SLICED_WSS_625:
-                       if (saa7115_read(client, 0x6b) & 0xc0)
+                       if (saa711x_read(client, 0x6b) & 0xc0)
                                return -EIO;
-                       data->data[0] = saa7115_read(client, 0x6c);
-                       data->data[1] = saa7115_read(client, 0x6d);
+                       data->data[0] = saa711x_read(client, 0x6c);
+                       data->data[1] = saa711x_read(client, 0x6d);
                        return 0;
                case V4L2_SLICED_CAPTION_525:
                        if (data->field == 0) {
                                /* CC */
-                               if (saa7115_read(client, 0x66) & 0xc0)
+                               if (saa711x_read(client, 0x66) & 0xc0)
                                        return -EIO;
-                               data->data[0] = saa7115_read(client, 0x67);
-                               data->data[1] = saa7115_read(client, 0x68);
+                               data->data[0] = saa711x_read(client, 0x67);
+                               data->data[1] = saa711x_read(client, 0x68);
                                return 0;
                        }
                        /* XDS */
-                       if (saa7115_read(client, 0x66) & 0x30)
+                       if (saa711x_read(client, 0x66) & 0x30)
                                return -EIO;
-                       data->data[0] = saa7115_read(client, 0x69);
-                       data->data[1] = saa7115_read(client, 0x6a);
+                       data->data[0] = saa711x_read(client, 0x69);
+                       data->data[1] = saa711x_read(client, 0x6a);
                        return 0;
                default:
                        return -EINVAL;
@@ -1272,7 +1410,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
 
                if (reg->i2c_id != I2C_DRIVERID_SAA711X)
                        return -EINVAL;
-               reg->val = saa7115_read(client, reg->reg & 0xff);
+               reg->val = saa711x_read(client, reg->reg & 0xff);
                break;
        }
 
@@ -1284,7 +1422,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               saa7115_write(client, reg->reg & 0xff, reg->val & 0xff);
+               saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
@@ -1302,12 +1440,14 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver i2c_driver_saa7115;
+static struct i2c_driver i2c_driver_saa711x;
 
-static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
+static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
 {
        struct i2c_client *client;
-       struct saa7115_state *state;
+       struct saa711x_state *state;
+       int     i;
+       char    name[17];
        u8 chip_id;
 
        /* Check if the adapter supports the needed features */
@@ -1319,28 +1459,31 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
                return -ENOMEM;
        client->addr = address;
        client->adapter = adapter;
-       client->driver = &i2c_driver_saa7115;
+       client->driver = &i2c_driver_saa711x;
        snprintf(client->name, sizeof(client->name) - 1, "saa7115");
 
        v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1);
 
-       saa7115_write(client, 0, 5);
-       chip_id = saa7115_read(client, 0) & 0x0f;
-       if (chip_id < 3 && chip_id > 5) {
-               v4l_dbg(1, debug, client, "saa7115 not found\n");
-               kfree(client);
-               return 0;
+       for (i=0;i<0x0f;i++) {
+               saa711x_write(client, 0, i);
+               name[i] = (saa711x_read(client, 0) &0x0f) +'0';
+               if (name[i]>'9')
+                       name[i]+='a'-'9'-1;
        }
+       name[i]='\0';
+
+       saa711x_write(client, 0, 5);
+       chip_id = saa711x_read(client, 0) & 0x0f;
+
        snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id);
-       v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
+       v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, address << 1, adapter->name);
 
-       state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
        i2c_set_clientdata(client, state);
        if (state == NULL) {
                kfree(client);
                return -ENOMEM;
        }
-       state->std = V4L2_STD_NTSC;
        state->input = -1;
        state->enable = 1;
        state->radio = 0;
@@ -1349,15 +1492,25 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
        state->hue = 0;
        state->sat = 64;
        switch (chip_id) {
+       case 1:
+               state->ident = V4L2_IDENT_SAA7111;
+               break;
        case 3:
                state->ident = V4L2_IDENT_SAA7113;
                break;
        case 4:
                state->ident = V4L2_IDENT_SAA7114;
                break;
-       default:
+       case 5:
                state->ident = V4L2_IDENT_SAA7115;
                break;
+       case 8:
+               state->ident = V4L2_IDENT_SAA7118;
+               break;
+       default:
+               state->ident = V4L2_IDENT_SAA7111;
+               v4l_info(client, "WARNING: Chip is not known - Falling back to saa7111\n");
+
        }
 
        state->audclk_freq = 48000;
@@ -1365,38 +1518,39 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
        v4l_dbg(1, debug, client, "writing init values\n");
 
        /* init to 60hz/48khz */
-       if (state->ident == V4L2_IDENT_SAA7113) {
-               state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
-               saa7115_writeregs(client, saa7113_init_auto_input);
-       } else {
+       state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
+       switch (state->ident) {
+       case V4L2_IDENT_SAA7111:
+               saa711x_writeregs(client, saa7111_init);
+               break;
+       case V4L2_IDENT_SAA7113:
+               saa711x_writeregs(client, saa7113_init);
+               break;
+       default:
                state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
-               saa7115_writeregs(client, saa7115_init_auto_input);
+               saa711x_writeregs(client, saa7115_init_auto_input);
        }
-       saa7115_writeregs(client, saa7115_init_misc);
-       saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
-       saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
-       saa7115_writeregs(client, saa7115_cfg_60hz_video);
-       saa7115_set_audio_clock_freq(client, state->audclk_freq);
-       saa7115_writeregs(client, saa7115_cfg_reset_scaler);
+       saa711x_writeregs(client, saa7115_init_misc);
+       saa711x_set_v4lstd(client, V4L2_STD_NTSC);
 
        i2c_attach_client(client);
 
        v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
-               saa7115_read(client, 0x1e), saa7115_read(client, 0x1f));
+               saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC), saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC));
 
        return 0;
 }
 
-static int saa7115_probe(struct i2c_adapter *adapter)
+static int saa711x_probe(struct i2c_adapter *adapter)
 {
        if (adapter->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adapter, &addr_data, &saa7115_attach);
+               return i2c_probe(adapter, &addr_data, &saa711x_attach);
        return 0;
 }
 
-static int saa7115_detach(struct i2c_client *client)
+static int saa711x_detach(struct i2c_client *client)
 {
-       struct saa7115_state *state = i2c_get_clientdata(client);
+       struct saa711x_state *state = i2c_get_clientdata(client);
        int err;
 
        err = i2c_detach_client(client);
@@ -1412,26 +1566,26 @@ static int saa7115_detach(struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 /* i2c implementation */
-static struct i2c_driver i2c_driver_saa7115 = {
+static struct i2c_driver i2c_driver_saa711x = {
        .driver = {
                .name = "saa7115",
        },
        .id = I2C_DRIVERID_SAA711X,
-       .attach_adapter = saa7115_probe,
-       .detach_client = saa7115_detach,
-       .command = saa7115_command,
+       .attach_adapter = saa711x_probe,
+       .detach_client = saa711x_detach,
+       .command = saa711x_command,
 };
 
 
-static int __init saa7115_init_module(void)
+static int __init saa711x_init_module(void)
 {
-       return i2c_add_driver(&i2c_driver_saa7115);
+       return i2c_add_driver(&i2c_driver_saa711x);
 }
 
-static void __exit saa7115_cleanup_module(void)
+static void __exit saa711x_cleanup_module(void)
 {
-       i2c_del_driver(&i2c_driver_saa7115);
+       i2c_del_driver(&i2c_driver_saa711x);
 }
 
-module_init(saa7115_init_module);
-module_exit(saa7115_cleanup_module);
+module_init(saa711x_init_module);
+module_exit(saa711x_cleanup_module);
diff --git a/drivers/media/video/saa711x_regs.h b/drivers/media/video/saa711x_regs.h
new file mode 100644 (file)
index 0000000..4e5f2eb
--- /dev/null
@@ -0,0 +1,549 @@
+/* saa711x - Philips SAA711x video decoder register specifications
+ *
+ * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@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.
+ */
+
+#define R_00_CHIP_VERSION                             0x00
+/* Video Decoder */
+       /* Video Decoder - Frontend part */
+#define R_01_INC_DELAY                                0x01
+#define R_02_INPUT_CNTL_1                             0x02
+#define R_03_INPUT_CNTL_2                             0x03
+#define R_04_INPUT_CNTL_3                             0x04
+#define R_05_INPUT_CNTL_4                             0x05
+       /* Video Decoder - Decoder part */
+#define R_06_H_SYNC_START                             0x06
+#define R_07_H_SYNC_STOP                              0x07
+#define R_08_SYNC_CNTL                                0x08
+#define R_09_LUMA_CNTL                                0x09
+#define R_0A_LUMA_BRIGHT_CNTL                         0x0a
+#define R_0B_LUMA_CONTRAST_CNTL                       0x0b
+#define R_0C_CHROMA_SAT_CNTL                          0x0c
+#define R_0D_CHROMA_HUE_CNTL                          0x0d
+#define R_0E_CHROMA_CNTL_1                            0x0e
+#define R_0F_CHROMA_GAIN_CNTL                         0x0f
+#define R_10_CHROMA_CNTL_2                            0x10
+#define R_11_MODE_DELAY_CNTL                          0x11
+#define R_12_RT_SIGNAL_CNTL                           0x12
+#define R_13_RT_X_PORT_OUT_CNTL                       0x13
+#define R_14_ANAL_ADC_COMPAT_CNTL                     0x14
+#define R_15_VGATE_START_FID_CHG                      0x15
+#define R_16_VGATE_STOP                               0x16
+#define R_17_MISC_VGATE_CONF_AND_MSB                  0x17
+#define R_18_RAW_DATA_GAIN_CNTL                       0x18
+#define R_19_RAW_DATA_OFF_CNTL                        0x19
+#define R_1A_COLOR_KILL_LVL_CNTL                      0x1a
+#define R_1B_MISC_TVVCRDET                            0x1b
+#define R_1C_ENHAN_COMB_CTRL1                         0x1c
+#define R_1D_ENHAN_COMB_CTRL2                         0x1d
+#define R_1E_STATUS_BYTE_1_VD_DEC                     0x1e
+#define R_1F_STATUS_BYTE_2_VD_DEC                     0x1f
+
+/* Component processing and interrupt masking part */
+#define R_23_INPUT_CNTL_5                             0x23
+#define R_24_INPUT_CNTL_6                             0x24
+#define R_25_INPUT_CNTL_7                             0x25
+#define R_29_COMP_DELAY                               0x29
+#define R_2A_COMP_BRIGHT_CNTL                         0x2a
+#define R_2B_COMP_CONTRAST_CNTL                       0x2b
+#define R_2C_COMP_SAT_CNTL                            0x2c
+#define R_2D_INTERRUPT_MASK_1                         0x2d
+#define R_2E_INTERRUPT_MASK_2                         0x2e
+#define R_2F_INTERRUPT_MASK_3                         0x2f
+
+/* Audio clock generator part */
+#define R_30_AUD_MAST_CLK_CYCLES_PER_FIELD            0x30
+#define R_34_AUD_MAST_CLK_NOMINAL_INC                 0x34
+#define R_38_CLK_RATIO_AMXCLK_TO_ASCLK                0x38
+#define R_39_CLK_RATIO_ASCLK_TO_ALRCLK                0x39
+#define R_3A_AUD_CLK_GEN_BASIC_SETUP                  0x3a
+
+/* General purpose VBI data slicer part */
+#define R_40_SLICER_CNTL_1                            0x40
+#define R_41_LCR_BASE                                 0x41
+#define R_58_PROGRAM_FRAMING_CODE                     0x58
+#define R_59_H_OFF_FOR_SLICER                         0x59
+#define R_5A_V_OFF_FOR_SLICER                         0x5a
+#define R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF          0x5b
+#define R_5D_DID                                      0x5d
+#define R_5E_SDID                                     0x5e
+#define R_60_SLICER_STATUS_BYTE_0                     0x60
+#define R_61_SLICER_STATUS_BYTE_1                     0x61
+#define R_62_SLICER_STATUS_BYTE_2                     0x62
+
+/* X port, I port and the scaler part */
+       /* Task independent global settings */
+#define R_80_GLOBAL_CNTL_1                            0x80
+#define R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F    0x81
+#define R_83_X_PORT_I_O_ENA_AND_OUT_CLK               0x83
+#define R_84_I_PORT_SIGNAL_DEF                        0x84
+#define R_85_I_PORT_SIGNAL_POLAR                      0x85
+#define R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT          0x86
+#define R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED         0x87
+#define R_88_POWER_SAVE_ADC_PORT_CNTL                 0x88
+#define R_8F_STATUS_INFO_SCALER                       0x8f
+       /* Task A definition */
+               /* Basic settings and acquisition window definition */
+#define R_90_A_TASK_HANDLING_CNTL                     0x90
+#define R_91_A_X_PORT_FORMATS_AND_CONF                0x91
+#define R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL          0x92
+#define R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF         0x93
+#define R_94_A_HORIZ_INPUT_WINDOW_START               0x94
+#define R_95_A_HORIZ_INPUT_WINDOW_START_MSB           0x95
+#define R_96_A_HORIZ_INPUT_WINDOW_LENGTH              0x96
+#define R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB          0x97
+#define R_98_A_VERT_INPUT_WINDOW_START                0x98
+#define R_99_A_VERT_INPUT_WINDOW_START_MSB            0x99
+#define R_9A_A_VERT_INPUT_WINDOW_LENGTH               0x9a
+#define R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB           0x9b
+#define R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH             0x9c
+#define R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB         0x9d
+#define R_9E_A_VERT_OUTPUT_WINDOW_LENGTH              0x9e
+#define R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB          0x9f
+               /* FIR filtering and prescaling */
+#define R_A0_A_HORIZ_PRESCALING                       0xa0
+#define R_A1_A_ACCUMULATION_LENGTH                    0xa1
+#define R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER    0xa2
+#define R_A4_A_LUMA_BRIGHTNESS_CNTL                   0xa4
+#define R_A5_A_LUMA_CONTRAST_CNTL                     0xa5
+#define R_A6_A_CHROMA_SATURATION_CNTL                 0xa6
+               /* Horizontal phase scaling */
+#define R_A8_A_HORIZ_LUMA_SCALING_INC                 0xa8
+#define R_A9_A_HORIZ_LUMA_SCALING_INC_MSB             0xa9
+#define R_AA_A_HORIZ_LUMA_PHASE_OFF                   0xaa
+#define R_AC_A_HORIZ_CHROMA_SCALING_INC               0xac
+#define R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB           0xad
+#define R_AE_A_HORIZ_CHROMA_PHASE_OFF                 0xae
+#define R_AF_A_HORIZ_CHROMA_PHASE_OFF_MSB             0xaf
+               /* Vertical scaling */
+#define R_B0_A_VERT_LUMA_SCALING_INC                  0xb0
+#define R_B1_A_VERT_LUMA_SCALING_INC_MSB              0xb1
+#define R_B2_A_VERT_CHROMA_SCALING_INC                0xb2
+#define R_B3_A_VERT_CHROMA_SCALING_INC_MSB            0xb3
+#define R_B4_A_VERT_SCALING_MODE_CNTL                 0xb4
+#define R_B8_A_VERT_CHROMA_PHASE_OFF_00               0xb8
+#define R_B9_A_VERT_CHROMA_PHASE_OFF_01               0xb9
+#define R_BA_A_VERT_CHROMA_PHASE_OFF_10               0xba
+#define R_BB_A_VERT_CHROMA_PHASE_OFF_11               0xbb
+#define R_BC_A_VERT_LUMA_PHASE_OFF_00                 0xbc
+#define R_BD_A_VERT_LUMA_PHASE_OFF_01                 0xbd
+#define R_BE_A_VERT_LUMA_PHASE_OFF_10                 0xbe
+#define R_BF_A_VERT_LUMA_PHASE_OFF_11                 0xbf
+       /* Task B definition */
+               /* Basic settings and acquisition window definition */
+#define R_C0_B_TASK_HANDLING_CNTL                     0xc0
+#define R_C1_B_X_PORT_FORMATS_AND_CONF                0xc1
+#define R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION      0xc2
+#define R_C3_B_I_PORT_FORMATS_AND_CONF                0xc3
+#define R_C4_B_HORIZ_INPUT_WINDOW_START               0xc4
+#define R_C5_B_HORIZ_INPUT_WINDOW_START_MSB           0xc5
+#define R_C6_B_HORIZ_INPUT_WINDOW_LENGTH              0xc6
+#define R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB          0xc7
+#define R_C8_B_VERT_INPUT_WINDOW_START                0xc8
+#define R_C9_B_VERT_INPUT_WINDOW_START_MSB            0xc9
+#define R_CA_B_VERT_INPUT_WINDOW_LENGTH               0xca
+#define R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB           0xcb
+#define R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH             0xcc
+#define R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB         0xcd
+#define R_CE_B_VERT_OUTPUT_WINDOW_LENGTH              0xce
+#define R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB          0xcf
+               /* FIR filtering and prescaling */
+#define R_D0_B_HORIZ_PRESCALING                       0xd0
+#define R_D1_B_ACCUMULATION_LENGTH                    0xd1
+#define R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER    0xd2
+#define R_D4_B_LUMA_BRIGHTNESS_CNTL                   0xd4
+#define R_D5_B_LUMA_CONTRAST_CNTL                     0xd5
+#define R_D6_B_CHROMA_SATURATION_CNTL                 0xd6
+               /* Horizontal phase scaling */
+#define R_D8_B_HORIZ_LUMA_SCALING_INC                 0xd8
+#define R_D9_B_HORIZ_LUMA_SCALING_INC_MSB             0xd9
+#define R_DA_B_HORIZ_LUMA_PHASE_OFF                   0xda
+#define R_DC_B_HORIZ_CHROMA_SCALING                   0xdc
+#define R_DD_B_HORIZ_CHROMA_SCALING_MSB               0xdd
+#define R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA              0xde
+               /* Vertical scaling */
+#define R_E0_B_VERT_LUMA_SCALING_INC                  0xe0
+#define R_E1_B_VERT_LUMA_SCALING_INC_MSB              0xe1
+#define R_E2_B_VERT_CHROMA_SCALING_INC                0xe2
+#define R_E3_B_VERT_CHROMA_SCALING_INC_MSB            0xe3
+#define R_E4_B_VERT_SCALING_MODE_CNTL                 0xe4
+#define R_E8_B_VERT_CHROMA_PHASE_OFF_00               0xe8
+#define R_E9_B_VERT_CHROMA_PHASE_OFF_01               0xe9
+#define R_EA_B_VERT_CHROMA_PHASE_OFF_10               0xea
+#define R_EB_B_VERT_CHROMA_PHASE_OFF_11               0xeb
+#define R_EC_B_VERT_LUMA_PHASE_OFF_00                 0xec
+#define R_ED_B_VERT_LUMA_PHASE_OFF_01                 0xed
+#define R_EE_B_VERT_LUMA_PHASE_OFF_10                 0xee
+#define R_EF_B_VERT_LUMA_PHASE_OFF_11                 0xef
+
+/* second PLL (PLL2) and Pulsegenerator Programming */
+#define R_F0_LFCO_PER_LINE                            0xf0
+#define R_F1_P_I_PARAM_SELECT                         0xf1
+#define R_F2_NOMINAL_PLL2_DTO                         0xf2
+#define R_F3_PLL_INCREMENT                            0xf3
+#define R_F4_PLL2_STATUS                              0xf4
+#define R_F5_PULSGEN_LINE_LENGTH                      0xf5
+#define R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG      0xf6
+#define R_F7_PULSE_A_POS_MSB                          0xf7
+#define R_F8_PULSE_B_POS                              0xf8
+#define R_F9_PULSE_B_POS_MSB                          0xf9
+#define R_FA_PULSE_C_POS                              0xfa
+#define R_FB_PULSE_C_POS_MSB                          0xfb
+#define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES     0xff
+
+#if 0
+/* Those structs will be used in the future for debug purposes */
+struct saa711x_reg_descr {
+       u8 reg;
+       int count;
+       char *name;
+};
+
+struct saa711x_reg_descr saa711x_regs[] = {
+       /* REG COUNT NAME */
+       {R_00_CHIP_VERSION,1,
+        "Chip version"},
+
+       /* Video Decoder: R_01_INC_DELAY to R_1F_STATUS_BYTE_2_VD_DEC */
+
+       /* Video Decoder - Frontend part: R_01_INC_DELAY to R_05_INPUT_CNTL_4 */
+       {R_01_INC_DELAY,1,
+        "Increment delay"},
+       {R_02_INPUT_CNTL_1,1,
+        "Analog input control 1"},
+       {R_03_INPUT_CNTL_2,1,
+        "Analog input control 2"},
+       {R_04_INPUT_CNTL_3,1,
+        "Analog input control 3"},
+       {R_05_INPUT_CNTL_4,1,
+        "Analog input control 4"},
+
+       /* Video Decoder - Decoder part: R_06_H_SYNC_START to R_1F_STATUS_BYTE_2_VD_DEC */
+       {R_06_H_SYNC_START,1,
+        "Horizontal sync start"},
+       {R_07_H_SYNC_STOP,1,
+        "Horizontal sync stop"},
+       {R_08_SYNC_CNTL,1,
+        "Sync control"},
+       {R_09_LUMA_CNTL,1,
+        "Luminance control"},
+       {R_0A_LUMA_BRIGHT_CNTL,1,
+        "Luminance brightness control"},
+       {R_0B_LUMA_CONTRAST_CNTL,1,
+        "Luminance contrast control"},
+       {R_0C_CHROMA_SAT_CNTL,1,
+        "Chrominance saturation control"},
+       {R_0D_CHROMA_HUE_CNTL,1,
+        "Chrominance hue control"},
+       {R_0E_CHROMA_CNTL_1,1,
+        "Chrominance control 1"},
+       {R_0F_CHROMA_GAIN_CNTL,1,
+        "Chrominance gain control"},
+       {R_10_CHROMA_CNTL_2,1,
+        "Chrominance control 2"},
+       {R_11_MODE_DELAY_CNTL,1,
+        "Mode/delay control"},
+       {R_12_RT_SIGNAL_CNTL,1,
+        "RT signal control"},
+       {R_13_RT_X_PORT_OUT_CNTL,1,
+        "RT/X port output control"},
+       {R_14_ANAL_ADC_COMPAT_CNTL,1,
+        "Analog/ADC/compatibility control"},
+       {R_15_VGATE_START_FID_CHG,  1,
+        "VGATE start FID change"},
+       {R_16_VGATE_STOP,1,
+        "VGATE stop"},
+       {R_17_MISC_VGATE_CONF_AND_MSB,  1,
+        "Miscellaneous VGATE configuration and MSBs"},
+       {R_18_RAW_DATA_GAIN_CNTL,1,
+        "Raw data gain control",},
+       {R_19_RAW_DATA_OFF_CNTL,1,
+        "Raw data offset control",},
+       {R_1A_COLOR_KILL_LVL_CNTL,1,
+        "Color Killer Level Control"},
+       { R_1B_MISC_TVVCRDET, 1,
+         "MISC /TVVCRDET"},
+       { R_1C_ENHAN_COMB_CTRL1, 1,
+        "Enhanced comb ctrl1"},
+       { R_1D_ENHAN_COMB_CTRL2, 1,
+        "Enhanced comb ctrl1"},
+       {R_1E_STATUS_BYTE_1_VD_DEC,1,
+        "Status byte 1 video decoder"},
+       {R_1F_STATUS_BYTE_2_VD_DEC,1,
+        "Status byte 2 video decoder"},
+
+       /* Component processing and interrupt masking part:  0x20h to R_2F_INTERRUPT_MASK_3 */
+       /* 0x20 to 0x22 - Reserved */
+       {R_23_INPUT_CNTL_5,1,
+        "Analog input control 5"},
+       {R_24_INPUT_CNTL_6,1,
+        "Analog input control 6"},
+       {R_25_INPUT_CNTL_7,1,
+        "Analog input control 7"},
+       /* 0x26 to 0x28 - Reserved */
+       {R_29_COMP_DELAY,1,
+        "Component delay"},
+       {R_2A_COMP_BRIGHT_CNTL,1,
+        "Component brightness control"},
+       {R_2B_COMP_CONTRAST_CNTL,1,
+        "Component contrast control"},
+       {R_2C_COMP_SAT_CNTL,1,
+        "Component saturation control"},
+       {R_2D_INTERRUPT_MASK_1,1,
+        "Interrupt mask 1"},
+       {R_2E_INTERRUPT_MASK_2,1,
+        "Interrupt mask 2"},
+       {R_2F_INTERRUPT_MASK_3,1,
+        "Interrupt mask 3"},
+
+       /* Audio clock generator part: R_30_AUD_MAST_CLK_CYCLES_PER_FIELD to 0x3f */
+       {R_30_AUD_MAST_CLK_CYCLES_PER_FIELD,3,
+        "Audio master clock cycles per field"},
+       /* 0x33 - Reserved */
+       {R_34_AUD_MAST_CLK_NOMINAL_INC,3,
+        "Audio master clock nominal increment"},
+       /* 0x37 - Reserved */
+       {R_38_CLK_RATIO_AMXCLK_TO_ASCLK,1,
+        "Clock ratio AMXCLK to ASCLK"},
+       {R_39_CLK_RATIO_ASCLK_TO_ALRCLK,1,
+        "Clock ratio ASCLK to ALRCLK"},
+       {R_3A_AUD_CLK_GEN_BASIC_SETUP,1,
+        "Audio clock generator basic setup"},
+       /* 0x3b-0x3f - Reserved */
+
+       /* General purpose VBI data slicer part: R_40_SLICER_CNTL_1 to 0x7f */
+       {R_40_SLICER_CNTL_1,1,
+        "Slicer control 1"},
+       {R_41_LCR,23,
+        "R_41_LCR"},
+       {R_58_PROGRAM_FRAMING_CODE,1,
+        "Programmable framing code"},
+       {R_59_H_OFF_FOR_SLICER,1,
+        "Horizontal offset for slicer"},
+       {R_5A_V_OFF_FOR_SLICER,1,
+        "Vertical offset for slicer"},
+       {R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF,1,
+        "Field offset and MSBs for horizontal and vertical offset"},
+       {R_5D_DID,1,
+        "Header and data identification (R_5D_DID)"},
+       {R_5E_SDID,1,
+        "Sliced data identification (R_5E_SDID) code"},
+       {R_60_SLICER_STATUS_BYTE_0,1,
+        "Slicer status byte 0"},
+       {R_61_SLICER_STATUS_BYTE_1,1,
+        "Slicer status byte 1"},
+       {R_62_SLICER_STATUS_BYTE_2,1,
+        "Slicer status byte 2"},
+       /* 0x63-0x7f - Reserved */
+
+       /* X port, I port and the scaler part: R_80_GLOBAL_CNTL_1 to R_EF_B_VERT_LUMA_PHASE_OFF_11 */
+       /* Task independent global settings: R_80_GLOBAL_CNTL_1 to R_8F_STATUS_INFO_SCALER */
+       {R_80_GLOBAL_CNTL_1,1,
+        "Global control 1"},
+       {R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F,1,
+        "Vertical sync and Field ID source selection, retimed V and F signals"},
+       /* 0x82 - Reserved */
+       {R_83_X_PORT_I_O_ENA_AND_OUT_CLK,1,
+        "X port I/O enable and output clock"},
+       {R_84_I_PORT_SIGNAL_DEF,1,
+        "I port signal definitions"},
+       {R_85_I_PORT_SIGNAL_POLAR,1,
+        "I port signal polarities"},
+       {R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT,1,
+        "I port FIFO flag control and arbitration"},
+       {R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED,  1,
+        "I port I/O enable output clock and gated"},
+       {R_88_POWER_SAVE_ADC_PORT_CNTL,1,
+        "Power save/ADC port control"},
+       /* 089-0x8e - Reserved */
+       {R_8F_STATUS_INFO_SCALER,1,
+        "Status information scaler part"},
+
+       /* Task A definition: R_90_A_TASK_HANDLING_CNTL to R_BF_A_VERT_LUMA_PHASE_OFF_11 */
+       /* Task A: Basic settings and acquisition window definition */
+       {R_90_A_TASK_HANDLING_CNTL,1,
+        "Task A: Task handling control"},
+       {R_91_A_X_PORT_FORMATS_AND_CONF,1,
+        "Task A: X port formats and configuration"},
+       {R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL,1,
+        "Task A: X port input reference signal definition"},
+       {R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF,1,
+        "Task A: I port output formats and configuration"},
+       {R_94_A_HORIZ_INPUT_WINDOW_START,2,
+        "Task A: Horizontal input window start"},
+       {R_96_A_HORIZ_INPUT_WINDOW_LENGTH,2,
+        "Task A: Horizontal input window length"},
+       {R_98_A_VERT_INPUT_WINDOW_START,2,
+        "Task A: Vertical input window start"},
+       {R_9A_A_VERT_INPUT_WINDOW_LENGTH,2,
+        "Task A: Vertical input window length"},
+       {R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH,2,
+        "Task A: Horizontal output window length"},
+       {R_9E_A_VERT_OUTPUT_WINDOW_LENGTH,2,
+        "Task A: Vertical output window length"},
+
+       /* Task A: FIR filtering and prescaling */
+       {R_A0_A_HORIZ_PRESCALING,1,
+        "Task A: Horizontal prescaling"},
+       {R_A1_A_ACCUMULATION_LENGTH,1,
+        "Task A: Accumulation length"},
+       {R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER,1,
+        "Task A: Prescaler DC gain and FIR prefilter"},
+       /* 0xa3 - Reserved */
+       {R_A4_A_LUMA_BRIGHTNESS_CNTL,1,
+        "Task A: Luminance brightness control"},
+       {R_A5_A_LUMA_CONTRAST_CNTL,1,
+        "Task A: Luminance contrast control"},
+       {R_A6_A_CHROMA_SATURATION_CNTL,1,
+        "Task A: Chrominance saturation control"},
+       /* 0xa7 - Reserved */
+
+       /* Task A: Horizontal phase scaling */
+       {R_A8_A_HORIZ_LUMA_SCALING_INC,2,
+        "Task A: Horizontal luminance scaling increment"},
+       {R_AA_A_HORIZ_LUMA_PHASE_OFF,1,
+        "Task A: Horizontal luminance phase offset"},
+       /* 0xab - Reserved */
+       {R_AC_A_HORIZ_CHROMA_SCALING_INC,2,
+        "Task A: Horizontal chrominance scaling increment"},
+       {R_AE_A_HORIZ_CHROMA_PHASE_OFF,1,
+        "Task A: Horizontal chrominance phase offset"},
+       /* 0xaf - Reserved */
+
+       /* Task A: Vertical scaling */
+       {R_B0_A_VERT_LUMA_SCALING_INC,2,
+        "Task A: Vertical luminance scaling increment"},
+       {R_B2_A_VERT_CHROMA_SCALING_INC,2,
+        "Task A: Vertical chrominance scaling increment"},
+       {R_B4_A_VERT_SCALING_MODE_CNTL,1,
+        "Task A: Vertical scaling mode control"},
+       /* 0xb5-0xb7 - Reserved */
+       {R_B8_A_VERT_CHROMA_PHASE_OFF_00,1,
+        "Task A: Vertical chrominance phase offset '00'"},
+       {R_B9_A_VERT_CHROMA_PHASE_OFF_01,1,
+        "Task A: Vertical chrominance phase offset '01'"},
+       {R_BA_A_VERT_CHROMA_PHASE_OFF_10,1,
+        "Task A: Vertical chrominance phase offset '10'"},
+       {R_BB_A_VERT_CHROMA_PHASE_OFF_11,1,
+        "Task A: Vertical chrominance phase offset '11'"},
+       {R_BC_A_VERT_LUMA_PHASE_OFF_00,1,
+        "Task A: Vertical luminance phase offset '00'"},
+       {R_BD_A_VERT_LUMA_PHASE_OFF_01,1,
+        "Task A: Vertical luminance phase offset '01'"},
+       {R_BE_A_VERT_LUMA_PHASE_OFF_10,1,
+        "Task A: Vertical luminance phase offset '10'"},
+       {R_BF_A_VERT_LUMA_PHASE_OFF_11,1,
+        "Task A: Vertical luminance phase offset '11'"},
+
+       /* Task B definition: R_C0_B_TASK_HANDLING_CNTL to R_EF_B_VERT_LUMA_PHASE_OFF_11 */
+       /* Task B: Basic settings and acquisition window definition */
+       {R_C0_B_TASK_HANDLING_CNTL,1,
+        "Task B: Task handling control"},
+       {R_C1_B_X_PORT_FORMATS_AND_CONF,1,
+        "Task B: X port formats and configuration"},
+       {R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION,1,
+        "Task B: Input reference signal definition"},
+       {R_C3_B_I_PORT_FORMATS_AND_CONF,1,
+        "Task B: I port formats and configuration"},
+       {R_C4_B_HORIZ_INPUT_WINDOW_START,2,
+        "Task B: Horizontal input window start"},
+       {R_C6_B_HORIZ_INPUT_WINDOW_LENGTH,2,
+        "Task B: Horizontal input window length"},
+       {R_C8_B_VERT_INPUT_WINDOW_START,2,
+        "Task B: Vertical input window start"},
+       {R_CA_B_VERT_INPUT_WINDOW_LENGTH,2,
+        "Task B: Vertical input window length"},
+       {R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,2,
+        "Task B: Horizontal output window length"},
+       {R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,2,
+        "Task B: Vertical output window length"},
+
+       /* Task B: FIR filtering and prescaling */
+       {R_D0_B_HORIZ_PRESCALING,1,
+        "Task B: Horizontal prescaling"},
+       {R_D1_B_ACCUMULATION_LENGTH,1,
+        "Task B: Accumulation length"},
+       {R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER,1,
+        "Task B: Prescaler DC gain and FIR prefilter"},
+       /* 0xd3 - Reserved */
+       {R_D4_B_LUMA_BRIGHTNESS_CNTL,1,
+        "Task B: Luminance brightness control"},
+       {R_D5_B_LUMA_CONTRAST_CNTL,1,
+        "Task B: Luminance contrast control"},
+       {R_D6_B_CHROMA_SATURATION_CNTL,1,
+        "Task B: Chrominance saturation control"},
+       /* 0xd7 - Reserved */
+
+       /* Task B: Horizontal phase scaling */
+       {R_D8_B_HORIZ_LUMA_SCALING_INC,2,
+        "Task B: Horizontal luminance scaling increment"},
+       {R_DA_B_HORIZ_LUMA_PHASE_OFF,1,
+        "Task B: Horizontal luminance phase offset"},
+       /* 0xdb - Reserved */
+       {R_DC_B_HORIZ_CHROMA_SCALING,2,
+        "Task B: Horizontal chrominance scaling"},
+       {R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA,1,
+        "Task B: Horizontal Phase Offset Chroma"},
+       /* 0xdf - Reserved */
+
+       /* Task B: Vertical scaling */
+       {R_E0_B_VERT_LUMA_SCALING_INC,2,
+        "Task B: Vertical luminance scaling increment"},
+       {R_E2_B_VERT_CHROMA_SCALING_INC,2,
+        "Task B: Vertical chrominance scaling increment"},
+       {R_E4_B_VERT_SCALING_MODE_CNTL,1,
+        "Task B: Vertical scaling mode control"},
+       /* 0xe5-0xe7 - Reserved */
+       {R_E8_B_VERT_CHROMA_PHASE_OFF_00,1,
+        "Task B: Vertical chrominance phase offset '00'"},
+       {R_E9_B_VERT_CHROMA_PHASE_OFF_01,1,
+        "Task B: Vertical chrominance phase offset '01'"},
+       {R_EA_B_VERT_CHROMA_PHASE_OFF_10,1,
+        "Task B: Vertical chrominance phase offset '10'"},
+       {R_EB_B_VERT_CHROMA_PHASE_OFF_11,1,
+        "Task B: Vertical chrominance phase offset '11'"},
+       {R_EC_B_VERT_LUMA_PHASE_OFF_00,1,
+        "Task B: Vertical luminance phase offset '00'"},
+       {R_ED_B_VERT_LUMA_PHASE_OFF_01,1,
+        "Task B: Vertical luminance phase offset '01'"},
+       {R_EE_B_VERT_LUMA_PHASE_OFF_10,1,
+        "Task B: Vertical luminance phase offset '10'"},
+       {R_EF_B_VERT_LUMA_PHASE_OFF_11,1,
+        "Task B: Vertical luminance phase offset '11'"},
+
+       /* second PLL (PLL2) and Pulsegenerator Programming */
+       { R_F0_LFCO_PER_LINE, 1,
+         "LFCO's per line"},
+       { R_F1_P_I_PARAM_SELECT,1,
+         "P-/I- Param. Select., PLL Mode, PLL H-Src., LFCO's per line"},
+       { R_F2_NOMINAL_PLL2_DTO,1,
+        "Nominal PLL2 DTO"},
+       {R_F3_PLL_INCREMENT,1,
+        "PLL2 Increment"},
+       {R_F4_PLL2_STATUS,1,
+        "PLL2 Status"},
+       {R_F5_PULSGEN_LINE_LENGTH,1,
+        "Pulsgen. line length"},
+       {R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG,1,
+        "Pulse A Position, Pulsgen Resync., Pulsgen. H-Src., Pulsgen. line length"},
+       {R_F7_PULSE_A_POS_MSB,1,
+        "Pulse A Position"},
+       {R_F8_PULSE_B_POS,2,
+        "Pulse B Position"},
+       {R_FA_PULSE_C_POS,2,
+        "Pulse C Position"},
+       /* 0xfc to 0xfe - Reserved */
+       {R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES,1,
+        "S_PLL max. phase, error threshold, PLL2 no. of lines, threshold"},
+};
+#endif
index f5543166d1930fce988fc0c32f39abe5e57b4d08..59da79ce2efda40cf7b45758dd8928a7eb82915d 100644 (file)
@@ -41,53 +41,15 @@ config VIDEO_SAA7134_DVB
        select VIDEO_BUF_DVB
        select FW_LOADER
        select DVB_PLL
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+       select DVB_NXT200X if !DVB_FE_CUSTOMISE
+       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+       select DVB_TDA826X if !DVB_FE_CUSTOMISE
+       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB cards based on the
          Philips saa7134 chip.
 
          To compile this driver as a module, choose M here: the
          module will be called saa7134-dvb.
-
-         You must also select one or more DVB demodulators.
-         If you are unsure which you need, choose all of them.
-
-config VIDEO_SAA7134_DVB_ALL_FRONTENDS
-       bool "Build all supported frontends for saa7134 based TV cards"
-       default y
-       depends on VIDEO_SAA7134_DVB
-       select DVB_MT352
-       select DVB_TDA1004X
-       select DVB_NXT200X
-       ---help---
-         This builds saa7134-dvb with all currently supported frontend
-         demodulators.  If you wish to tweak your configuration, and
-         only include support for the hardware that you need, choose N here.
-
-         If you are unsure, choose Y.
-
-config VIDEO_SAA7134_DVB_MT352
-       bool "Zarlink MT352 DVB-T Support"
-       default y
-       depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
-       select DVB_MT352
-       ---help---
-         This adds DVB-T support for cards based on the
-         Philips saa7134 chip and the MT352 demodulator.
-
-config VIDEO_SAA7134_DVB_TDA1004X
-       bool "Phillips TDA10045H/TDA10046H DVB-T Support"
-       default y
-       depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
-       select DVB_TDA1004X
-       ---help---
-         This adds DVB-T support for cards based on the
-         Philips saa7134 chip and the TDA10045H/TDA10046H demodulator.
-
-config VIDEO_SAA7134_DVB_NXT200X
-       bool "NXT2002/NXT2004 ATSC Support"
-       default y
-       depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
-       select DVB_NXT200X
-       ---help---
-         This adds ATSC 8VSB and QAM64/256 support for cards based on the
-         Philips saa7134 chip and the NXT2002/NXT2004 demodulator.
index be7b9ee697d6ceb1aa41358f7887b35e32e5c2cb..89a1565b4256e11398ef54152314ab95ca18f57a 100644 (file)
@@ -16,8 +16,5 @@ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
 extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
-extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
-extra-cflags-$(CONFIG_DVB_TDA1004X)  += -DHAVE_TDA1004X=1
-extra-cflags-$(CONFIG_DVB_NXT200X)   += -DHAVE_NXT200X=1
 
 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
index d73cff1970ae22391ae77a6e1f1289f23119403f..a39e0136ce3ba4614b422d05e8febc1fd319c736 100644 (file)
@@ -590,6 +590,11 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
 
 static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream)
 {
+       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+       struct saa7134_dev *dev = saa7134->dev;
+
+       dev->ctl_mute = 1;
+       saa7134_tvaudio_setmute(dev);
        return 0;
 }
 
@@ -631,6 +636,9 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
        runtime->private_free = snd_card_saa7134_runtime_free;
        runtime->hw = snd_card_saa7134_capture;
 
+       dev->ctl_mute = 0;
+       saa7134_tvaudio_setmute(dev);
+
        if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
                return err;
 
index 927413aded10c120cedbfbddcf57970d48dceca4..aa1db509f3d477ec895a42c33a90b21ebe976787 100644 (file)
@@ -1911,7 +1911,7 @@ struct saa7134_board saa7134_boards[] = {
                },
        },
        [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
-               .name           = "LifeView/Typhoon FlyDVB-T Duo Cardbus",
+               .name           = "LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus",
                .audio_clock    = 0x00200000,
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .radio_type     = UNSET,
@@ -2891,6 +2891,80 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x8000,
                },
        },
+       [SAA7134_BOARD_MEDION_MD8800_QUADRO] = {
+               .name           = "Medion Md8800 Quadro",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE2,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_FLYDVBS_LR300] = {
+               /* LifeView FlyDVB-s */
+               /* Igor M. Liplianin <liplianin@tut.by> */
+               .name           = "LifeView FlyDVB-S /Acorp TV134DS",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_comp1,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_PROTEUS_2309] = {
+               .name           = "Proteus Pro 2309",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3375,7 +3449,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .driver_data  = SAA7134_BOARD_FLYDVB_TRIO,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,  /* SAA 7131E */
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
                .subvendor    = 0x1461,
                .subdevice    = 0x2c05,
                .driver_data  = SAA7134_BOARD_AVERMEDIA_777,
@@ -3421,6 +3495,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x16be,
                .subdevice    = 0x0005,
                .driver_data  = SAA7134_BOARD_MD7134_BRIDGE_2,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0300,
+               .driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x4e42,
+               .subdevice    = 0x0300,/* LR300 */
+               .driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
        },{
                .vendor = PCI_VENDOR_ID_PHILIPS,
                .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3445,6 +3531,36 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x5168,
                .subdevice    = 0x3502,  /* whats the difference to 0x3306 ?*/
                .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0007,
+               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0008,
+               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x2c05,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_777,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1489,
+               .subdevice    = 0x0502,                /* Cardbus version */
+               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0919, /* Philips Proteus PRO 2309 */
+               .subdevice    = 0x2003,
+               .driver_data  = SAA7134_BOARD_PROTEUS_2309,
        },{
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -3548,6 +3664,12 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
        case SAA7134_BOARD_FLYDVBT_LR301:
        case SAA7134_BOARD_FLYDVBTDUO:
+       case SAA7134_BOARD_PROTEUS_2309:
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               break;
+       case SAA7134_BOARD_FLYDVBS_LR300:
+               saa_writeb(SAA7134_GPIO_GPMODE3, 0x80);
+               saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x40);
                dev->has_remote = SAA7134_REMOTE_GPIO;
                break;
        case SAA7134_BOARD_MD5044:
@@ -3732,6 +3854,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
        case SAA7134_BOARD_PHILIPS_TIGER:
        case SAA7134_BOARD_TEVION_DVBT_220RF:
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+       case SAA7134_BOARD_MEDION_MD8800_QUADRO:
                /* this is a hybrid board, initialize to analog mode
                 * and configure firmware eeprom address
                 */
index be3a81fc90a2498769cb95ca2b4f306c4d71cfc8..09aa62f61af7bab0ce172f4452750fa4dc4b7944 100644 (file)
@@ -843,7 +843,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
                        latency = 0x0A;
                }
 #endif
-               if (pci_pci_problems & PCIPCI_FAIL) {
+               if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
                        printk(KERN_INFO "%s: quirk: this driver and your "
                                        "chipset may not work together"
                                        " in overlay mode.\n",dev->name);
index 279828b8f299bf45598b92af8d6e4b3f2b9d775d..b6881541e704ab0192834af210a33d2594009d2e 100644 (file)
 #include <media/v4l2-common.h>
 #include "dvb-pll.h"
 
-#ifdef HAVE_MT352
-# include "mt352.h"
-# include "mt352_priv.h" /* FIXME */
-#endif
-#ifdef HAVE_TDA1004X
-# include "tda1004x.h"
-#endif
-#ifdef HAVE_NXT200X
-# include "nxt200x.h"
-#endif
-
+#include "mt352.h"
+#include "mt352_priv.h" /* FIXME */
+#include "tda1004x.h"
+#include "nxt200x.h"
+
+#include "tda10086.h"
+#include "tda826x.h"
+#include "isl6421.h"
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
@@ -54,8 +51,6 @@ module_param(antenna_pwr, int, 0444);
 MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
 
 /* ------------------------------------------------------------------ */
-
-#ifdef HAVE_MT352
 static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
 {
        u32 ok;
@@ -185,12 +180,8 @@ static struct mt352_config avermedia_777 = {
        .demod_address = 0xf,
        .demod_init    = mt352_aver777_init,
 };
-#endif
 
 /* ------------------------------------------------------------------ */
-
-#ifdef HAVE_TDA1004X
-
 static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
@@ -969,11 +960,58 @@ static struct tda1004x_config tevion_dvbt220rf_config = {
        .request_firmware = NULL,
 };
 
-#endif
+/* ------------------------------------------------------------------ */
+
+static int md8800_dvbt_analog_mode(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       static u8 data[] = { 0x3c, 0x33, 0x68};
+       struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+       i2c_transfer(&dev->i2c_adap, &msg, 1);
+       philips_tda827xa_tuner_sleep( 0x61, fe);
+       return 0;
+}
+
+static int md8800_dvbt_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       int ret;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       static u8 tda8290_close[] = { 0x21, 0xc0};
+       static u8 tda8290_open[]  = { 0x21, 0x80};
+       struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
+       /* close tda8290 i2c bridge */
+       tda8290_msg.buf = tda8290_close;
+       ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
+       if (ret != 1)
+               return -EIO;
+       msleep(20);
+       ret = philips_tda827xa_pll_set(0x60, fe, params);
+       if (ret != 0)
+               return ret;
+       /* open tda8290 i2c bridge */
+       tda8290_msg.buf = tda8290_open;
+       i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
+       return ret;
+}
+
+static struct tda1004x_config md8800_dvbt_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .if_freq       = TDA10046_FREQ_045,
+       .request_firmware = NULL,
+};
+
+static struct tda10086_config flydvbs = {
+       .demod_address = 0x0e,
+       .invert = 0,
+};
 
 /* ------------------------------------------------------------------ */
 
-#ifdef HAVE_NXT200X
 static struct nxt200x_config avertvhda180 = {
        .demod_address    = 0x0a,
 };
@@ -991,7 +1029,6 @@ static struct nxt200x_config kworldatsc110 = {
        .demod_address    = 0x0a,
        .set_pll_input    = nxt200x_set_pll_input,
 };
-#endif
 
 /* ------------------------------------------------------------------ */
 
@@ -1009,29 +1046,26 @@ static int dvb_init(struct saa7134_dev *dev)
                            dev);
 
        switch (dev->board) {
-#ifdef HAVE_MT352
        case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
                printk("%s: pinnacle 300i dvb setup\n",dev->name);
-               dev->dvb.frontend = mt352_attach(&pinnacle_300i,
-                                                &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
                }
                break;
-
        case SAA7134_BOARD_AVERMEDIA_777:
                printk("%s: avertv 777 dvb setup\n",dev->name);
-               dev->dvb.frontend = mt352_attach(&avermedia_777,
-                                                &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs;
                }
                break;
-#endif
-#ifdef HAVE_TDA1004X
        case SAA7134_BOARD_MD7134:
-               dev->dvb.frontend = tda10046_attach(&medion_cardbus,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &medion_cardbus,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
@@ -1039,16 +1073,18 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_PHILIPS_TOUGH:
-               dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_tu1216_60_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init;
                        dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_60_set_params;
                }
                break;
        case SAA7134_BOARD_FLYDVBTDUO:
-               dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &tda827x_lifeview_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
@@ -1056,8 +1092,9 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &tda827x_lifeview_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
@@ -1065,8 +1102,9 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
-               dev->dvb.frontend = tda10046_attach(&philips_europa_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_europa_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
                        dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
@@ -1076,8 +1114,9 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-               dev->dvb.frontend = tda10046_attach(&philips_europa_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_europa_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
@@ -1085,16 +1124,18 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-               dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_tu1216_61_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init;
                        dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_61_set_params;
                }
                break;
        case SAA7134_BOARD_PHILIPS_TIGER:
-               dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_tiger_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
@@ -1102,8 +1143,9 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-               dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_tiger_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
@@ -1111,8 +1153,9 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_FLYDVBT_LR301:
-               dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &tda827x_lifeview_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
@@ -1120,16 +1163,18 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
-               dev->dvb.frontend = tda10046_attach(&lifeview_trio_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &lifeview_trio_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
                        dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
                }
                break;
        case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
-               dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &ads_tech_duo_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
@@ -1137,37 +1182,63 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
-               dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &tevion_dvbt220rf_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep;
                        dev->dvb.frontend->ops.tuner_ops.set_params = tevion_dvb220rf_tuner_set_params;
                }
                break;
        case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-               dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
-                                                   &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &ads_tech_duo_config,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
                        dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
                        dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
                }
                break;
-#endif
-#ifdef HAVE_NXT200X
+       case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+               dev->dvb.frontend = tda10046_attach(&md8800_dvbt_config,
+                                                   &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = md8800_dvbt_analog_mode;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = md8800_dvbt_pll_set;
+               }
+               break;
        case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
-               dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_tdhu2);
                }
                break;
        case SAA7134_BOARD_KWORLD_ATSC110:
-               dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+                                              &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+                                  NULL, &dvb_pll_tuv1236d);
+               }
+               break;
+       case SAA7134_BOARD_FLYDVBS_LR300:
+               dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+                                              &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d);
+                       if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+                                      &dev->i2c_adap, 0) == NULL) {
+                               printk("%s: No tda826x found!\n", __FUNCTION__);
+                       }
+                       if (dvb_attach(isl6421_attach, dev->dvb.frontend,
+                                      &dev->i2c_adap, 0x08, 0, 0) == NULL) {
+                               printk("%s: No ISL6421 found!\n", __FUNCTION__);
+                       }
                }
                break;
-#endif
        default:
                printk("%s: Huh? unknown DVB card?\n",dev->name);
                break;
index 7c595492c56b1719cc3059e03030f60573366723..f7ea857d5d73e540eda9913bab293de9450b5d7a 100644 (file)
@@ -228,6 +228,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                mask_keyup   = 0x400000;
                polling      = 50; // ms
                break;
+       case SAA7134_BOARD_PROTEUS_2309:
+               ir_codes     = ir_codes_proteus_2309;
+               mask_keycode = 0x00007F;
+               mask_keyup   = 0x000080;
+               polling      = 50; // ms
+               break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
                ir_codes     = ir_codes_videomate_tv_pvr;
index 0db53d192b2a2b1d40f975b63256066982ba1e3e..d31220d204958f16ad7d4cdb9eea829b0369706f 100644 (file)
@@ -1046,6 +1046,7 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
 }
 
 EXPORT_SYMBOL(saa_dsp_writel);
+EXPORT_SYMBOL(saa7134_tvaudio_setmute);
 
 /* ----------------------------------------------------------- */
 /*
index c04ce6152fd5373a0e2ea1410621b17ba923f8b8..7db7b970595388865d3374918b2c3d7ae0a17a34 100644 (file)
@@ -223,6 +223,9 @@ struct saa7134_format {
 #define SAA7134_BOARD_MD7134_BRIDGE_2     93
 #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
 #define SAA7134_BOARD_FLYVIDEO3000_NTSC 95
+#define SAA7134_BOARD_MEDION_MD8800_QUADRO 96
+#define SAA7134_BOARD_FLYDVBS_LR300 97
+#define SAA7134_BOARD_PROTEUS_2309 98
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
index 8dab481d384aa58b292de4dd26fd6155c8fda1ac..87ffb0e84a7a063cd34589d8705e00d1a9b1b28b 100644 (file)
@@ -480,6 +480,8 @@ static int tda9887_set_config(struct tuner *t, char *buf)
        }
        if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
                buf[1] &= ~cQSS;
+       if (t->tda9887_config & TDA9887_GATING_18)
+               buf[3] &= ~cGating_36;
        return 0;
 }
 
index abe37cf632c6845eabab734962e631e78dda5342..63db4e97ae6ce57a6003d55b0b0c6a187cc46e6e 100644 (file)
@@ -10,7 +10,7 @@
 #include <media/v4l2-common.h>
 
 static int offset = 0;
-module_param(offset, int, 0666);
+module_param(offset, int, 0664);
 MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
 
 /* ---------------------------------------------------------------------- */
@@ -331,6 +331,8 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
                        else if (params->default_top_high)
                                config |= TDA9887_TOP(params->default_top_high);
                }
+               if (params->default_pll_gating_18)
+                       config |= TDA9887_GATING_18;
                i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
        }
        tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
@@ -439,8 +441,6 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
                buffer[3] = 0xa4;
                break;
        }
-       buffer[0] = (div>>8) & 0x7f;
-       buffer[1] = div      & 0xff;
        if (params->cb_first_if_lower_freq && div < t->last_div) {
                buffer[0] = buffer[2];
                buffer[1] = buffer[3];
index 8b542599ed471c0f84c9e4247d627178d87a4fd9..8fff642fad56fa8e2579c2741d96818ea6850d94 100644 (file)
@@ -650,6 +650,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
                .count  = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
                .has_tda9887 = 1,
                .port1_invert_for_secam_lc = 1,
+               .default_pll_gating_18 = 1,
        },
 };
 
index 936e3f746fba59ca3f4f0cbf892408022ac80a23..fcaef4bf82896da5e5c20d463fca436835cc75b1 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/kthread.h>
 
 #include <media/tvaudio.h>
 #include <media/v4l2-common.h>
@@ -124,11 +125,8 @@ struct CHIPSTATE {
        int input;
 
        /* thread */
-       pid_t                tpid;
-       struct completion    texit;
-       wait_queue_head_t    wq;
+       struct task_struct   *thread;
        struct timer_list    wt;
-       int                  done;
        int                  watch_stereo;
        int                  audmode;
 };
@@ -264,28 +262,23 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
 static void chip_thread_wake(unsigned long data)
 {
        struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
-       wake_up_interruptible(&chip->wq);
+       wake_up_process(chip->thread);
 }
 
 static int chip_thread(void *data)
 {
-       DECLARE_WAITQUEUE(wait, current);
        struct CHIPSTATE *chip = data;
        struct CHIPDESC  *desc = chiplist + chip->type;
 
-       daemonize("%s", chip->c.name);
-       allow_signal(SIGTERM);
        v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
 
        for (;;) {
-               add_wait_queue(&chip->wq, &wait);
-               if (!chip->done) {
-                       set_current_state(TASK_INTERRUPTIBLE);
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (!kthread_should_stop())
                        schedule();
-               }
-               remove_wait_queue(&chip->wq, &wait);
+               set_current_state(TASK_RUNNING);
                try_to_freeze();
-               if (chip->done || signal_pending(current))
+               if (kthread_should_stop())
                        break;
                v4l_dbg(1, debug, &chip->c, "%s: thread wakeup\n", chip->c.name);
 
@@ -301,7 +294,6 @@ static int chip_thread(void *data)
        }
 
        v4l_dbg(1, debug, &chip->c, "%s: thread exiting\n", chip->c.name);
-       complete_and_exit(&chip->texit, 0);
        return 0;
 }
 
@@ -1536,19 +1528,18 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
                chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
        }
 
-       chip->tpid = -1;
+       chip->thread = NULL;
        if (desc->checkmode) {
                /* start async thread */
                init_timer(&chip->wt);
                chip->wt.function = chip_thread_wake;
                chip->wt.data     = (unsigned long)chip;
-               init_waitqueue_head(&chip->wq);
-               init_completion(&chip->texit);
-               chip->tpid = kernel_thread(chip_thread,(void *)chip,0);
-               if (chip->tpid < 0)
-                       v4l_warn(&chip->c, "%s: kernel_thread() failed\n",
+               chip->thread = kthread_run(chip_thread, chip, chip->c.name);
+               if (IS_ERR(chip->thread)) {
+                       v4l_warn(&chip->c, "%s: failed to create kthread\n",
                               chip->c.name);
-               wake_up_interruptible(&chip->wq);
+                       chip->thread = NULL;
+               }
        }
        return 0;
 }
@@ -1569,11 +1560,10 @@ static int chip_detach(struct i2c_client *client)
        struct CHIPSTATE *chip = i2c_get_clientdata(client);
 
        del_timer_sync(&chip->wt);
-       if (chip->tpid >= 0) {
+       if (chip->thread) {
                /* shutdown async thread */
-               chip->done = 1;
-               wake_up_interruptible(&chip->wq);
-               wait_for_completion(&chip->texit);
+               kthread_stop(chip->thread);
+               chip->thread = NULL;
        }
 
        i2c_detach_client(&chip->c);
index d95529e8e51376dbadeea8e89f94ab770769cf6d..cd1502ac956056f5e0e461b3b7fcdeac076d25f4 100644 (file)
@@ -605,6 +605,8 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                        tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
                        t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
                }
+       }
+       for (i = j = 0; i < 8; i++) {
                if (t_format2 & (1 << i)) {
                        tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
                        t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
index b167ffab25202106da0bc956b8304430a48634e8..bc0a4fc27b24452a828e971d906e1918aeff2a27 100644 (file)
@@ -294,7 +294,7 @@ static inline void tvp5150_selmux(struct i2c_client *c)
        if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable)
                input = 8;
 
-       switch (input) {
+       switch (decoder->route.input) {
        case TVP5150_COMPOSITE1:
                input |= 2;
                /* fall through */
@@ -308,6 +308,11 @@ static inline void tvp5150_selmux(struct i2c_client *c)
                break;
        }
 
+       tvp5150_dbg( 1, "Selecting video route: route input=%i, output=%i "
+                       "=> tvp5150 input=%i, opmode=%i\n",
+                       decoder->route.input,decoder->route.output,
+                       input, opmode );
+
        tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode);
        tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input);
 };
index 6f31ecc88843d16c7de882a8ee7e9dd28f538375..4eee8be88314104524eafcafce16a263e5400b9b 100644 (file)
@@ -222,6 +222,7 @@ static void konicawc_adjust_picture(struct uvd *uvd)
 static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev)
 {
        struct input_dev *input_dev;
+       int error;
 
        usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
        strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
@@ -242,7 +243,13 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
 
        input_dev->private = cam;
 
-       input_register_device(cam->input);
+       error = input_register_device(cam->input);
+       if (error) {
+               warn("Failed to register camera's input device, err: %d\n",
+                    error);
+               input_free_device(cam->input);
+               cam->input = NULL;
+       }
 }
 
 static void konicawc_unregister_input(struct konicawc *cam)
index 90d48e8510ba308fae6402e866b22bf14b95dbd2..08f9559a6bfa475e414f7f3b94a52039b32da74d 100644 (file)
@@ -7,6 +7,7 @@
  *                    Monroe Williams (monroe@pobox.com)
  *
  * Supports 3COM HomeConnect PC Digital WebCam
+ * Supports Compro PS39U WebCam
  *
  * 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
@@ -60,6 +61,8 @@
 /* Define these values to match your device */
 #define USB_VICAM_VENDOR_ID    0x04c1
 #define USB_VICAM_PRODUCT_ID   0x009d
+#define USB_COMPRO_VENDOR_ID   0x0602
+#define USB_COMPRO_PRODUCT_ID  0x1001
 
 #define VICAM_BYTES_PER_PIXEL   3
 #define VICAM_MAX_READ_SIZE     (512*242+128)
@@ -1254,6 +1257,7 @@ static struct video_device vicam_template = {
 /* table of devices that work with this driver */
 static struct usb_device_id vicam_table[] = {
        {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
+       {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)},
        {}                      /* Terminating entry */
 };
 
index d7c3fcbc80f7b5585d2a9463ece0f31695b566ee..1d899e2db394e62eff8f3398b005e1d37e78be3c 100644 (file)
@@ -349,6 +349,8 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        {
                struct video_buffer     *buffer = arg;
 
+               memset(buffer, 0, sizeof(*buffer));
+
                err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
                if (err < 0) {
                        dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
@@ -361,7 +363,7 @@ v4l_compat_translate_ioctl(struct inode         *inode,
                switch (fbuf2.fmt.pixelformat) {
                case V4L2_PIX_FMT_RGB332:
                        buffer->depth = 8;
-                               break;
+                       break;
                case V4L2_PIX_FMT_RGB555:
                        buffer->depth = 15;
                        break;
@@ -377,9 +379,13 @@ v4l_compat_translate_ioctl(struct inode         *inode,
                default:
                        buffer->depth = 0;
                }
-               if (0 != fbuf2.fmt.bytesperline)
+               if (fbuf2.fmt.bytesperline) {
                        buffer->bytesperline = fbuf2.fmt.bytesperline;
-               else {
+                       if (!buffer->depth && buffer->width)
+                               buffer->depth   = ((fbuf2.fmt.bytesperline<<3)
+                                                 + (buffer->width-1) )
+                                                 /buffer->width;
+               } else {
                        buffer->bytesperline =
                                (buffer->width * buffer->depth + 7) & 7;
                        buffer->bytesperline >>= 3;
index 8d972ffdaf98782b3070713900faa245d308eec5..78d28b03ec93df4e2b4eb0096aebd8589adf7fab 100644 (file)
@@ -938,6 +938,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        case VIDIOC_INT_AUDIO_CLOCK_FREQ:
        case VIDIOC_INT_I2S_CLOCK_FREQ:
        case VIDIOC_INT_S_STANDBY:
+       case VIDIOC_INT_RESET:
        {
                u32 *p=arg;
 
index 7ee8a53cd336f1702a35b2532071b1955d9af3f2..f53edf1923b7de3fa558c2adf4c42980f97ad608 100644 (file)
@@ -223,6 +223,7 @@ fail_dmxdev:
 fail_dmx:
        dvb_unregister_frontend(dvb->frontend);
 fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
        dvb_unregister_adapter(&dvb->adapter);
 fail_adapter:
        return result;
@@ -236,6 +237,7 @@ void videobuf_dvb_unregister(struct videobuf_dvb *dvb)
        dvb_dmxdev_release(&dvb->dmxdev);
        dvb_dmx_release(&dvb->demux);
        dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
        dvb_unregister_adapter(&dvb->adapter);
 }
 
index edd7b83c3464b4a2367c6391b30fcee2f9abcbe7..479a0675cf60bf8ddfc7b6a372077be03063b35a 100644 (file)
@@ -739,13 +739,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_DQBUF:
        {
                struct v4l2_buffer *p=arg;
-               if (!vfd->vidioc_qbuf)
+               if (!vfd->vidioc_dqbuf)
                        break;
                ret = check_fmt (vfd, p->type);
                if (ret)
                        break;
 
-               ret=vfd->vidioc_qbuf(file, fh, p);
+               ret=vfd->vidioc_dqbuf(file, fh, p);
                if (!ret)
                        dbgbuf(cmd,vfd,p);
                break;
@@ -836,7 +836,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-               if (index < 0 || index >= vfd->tvnormsize) {
+               if (index<0 || index >= vfd->tvnormsize) {
                        ret=-EINVAL;
                        break;
                }
@@ -1283,9 +1283,29 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_G_PARM:
        {
                struct v4l2_streamparm *p=arg;
-               if (!vfd->vidioc_g_parm)
-                       break;
-               ret=vfd->vidioc_g_parm(file, fh, p);
+               if (vfd->vidioc_g_parm) {
+                       ret=vfd->vidioc_g_parm(file, fh, p);
+               } else {
+                       struct v4l2_standard s;
+
+                       if (!vfd->tvnormsize) {
+                               printk (KERN_WARNING "%s: no TV norms defined!\n",
+                                                       vfd->name);
+                               break;
+                       }
+
+                       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+
+                       v4l2_video_std_construct(&s, vfd->tvnorms[vfd->current_norm].id,
+                                                vfd->tvnorms[vfd->current_norm].name);
+
+                       memset(p,0,sizeof(*p));
+
+                       p->parm.capture.timeperframe = s.frameperiod;
+                       ret=0;
+               }
+
                dbgarg (cmd, "type=%d\n", p->type);
                break;
        }
index 268e69fdefc6f3194fdcdc3cc2902fffbd642c3b..d1e04f7c530bbf9ee66f1e80072fb0263b1b5dab 100644 (file)
@@ -4404,7 +4404,6 @@ static struct video_device v4l_device_template = {
        .name           = "NOT SET",
        //.type         = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
        //      VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
-       .hardware       = VID_HARDWARE_VINO,
        .fops           = &vino_fops,
        .minor          = -1,
 };
index 841884af0cc03b56a992aa1084740dfa1937c3b6..e7c01d560b6460f1dd6de8ab19a87ed651556782 100644 (file)
@@ -992,7 +992,8 @@ static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
        struct vivi_fh  *fh=priv;
        struct videobuf_queue *q=&fh->vb_vidq;
        struct v4l2_requestbuffers req;
-       unsigned int i, ret;
+       unsigned int i;
+       int ret;
 
        req.type   = q->type;
        req.count  = 8;
@@ -1359,6 +1360,8 @@ static int __init vivi_init(void)
        dev->vidq.timeout.data     = (unsigned long)dev;
        init_timer(&dev->vidq.timeout);
 
+       vivi.current_norm         = tvnorms[0].id;
+
        ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);
        printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
        return ret;
index 1eca7e65d235e570fcb36ce5dcf7312b759c56ea..8ef31ed7d3f1133edfe514ba0b34445d3aaed3a6 100644 (file)
@@ -744,6 +744,6 @@ vpx3220_cleanup (void)
 module_init(vpx3220_init);
 module_exit(vpx3220_cleanup);
 
-MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video encoder driver");
+MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
 MODULE_AUTHOR("Laurent Pinchart");
 MODULE_LICENSE("GPL");
index 20f211b55ad4c4d17726c579affbfa8cccfb7e46..2912326a5aef1c6adace62d91a25bd2b8d930ea1 100644 (file)
@@ -586,15 +586,14 @@ static struct w9968cf_symbolic_list urb_errlist[] = {
        { -EFBIG,     "Too much ISO frames requested" },
        { -ENOSR,     "Buffer error (overrun)" },
        { -EPIPE,     "Specified endpoint is stalled (device not responding)"},
-       { -EOVERFLOW, "Babble (bad cable?)" },
+       { -EOVERFLOW, "Babble (too much data)" },
        { -EPROTO,    "Bit-stuff error (bad cable?)" },
        { -EILSEQ,    "CRC/Timeout" },
-       { -ETIMEDOUT, "NAK (device does not respond)" },
+       { -ETIME,     "Device does not respond to token" },
+       { -ETIMEDOUT, "Device does not respond to command" },
        { -1, NULL }
 };
 
-
-
 /****************************************************************************
  * Memory management functions                                              *
  ****************************************************************************/
index f2249ed25273bc5ded10a920e4891e587faf1c67..9f21d0ba0f0f721df3d44cad9d8b8566288964cd 100644 (file)
@@ -820,7 +820,6 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
        .getsda = zoran_i2c_getsda,
        .getscl = zoran_i2c_getscl,
        .udelay = 10,
-       .mdelay = 0,
        .timeout = 100,
 };
 
@@ -1621,10 +1620,10 @@ init_dc10_cards (void)
        dprintk(5, KERN_DEBUG "Jotti is een held!\n");
 
        /* some mainboards might not do PCI-PCI data transfer well */
-       if (pci_pci_problems & PCIPCI_FAIL) {
+       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
                dprintk(1,
                        KERN_WARNING
-                       "%s: chipset may not support reliable PCI-PCI DMA\n",
+                       "%s: chipset does not support reliable PCI-PCI DMA\n",
                        ZORAN_NAME);
        }
 
@@ -1632,7 +1631,7 @@ init_dc10_cards (void)
        for (i = 0; i < zoran_num; i++) {
                struct zoran *zr = &zoran[i];
 
-               if (pci_pci_problems & PCIPCI_NATOMA && zr->revision <= 1) {
+               if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
                        zr->jpg_buffers.need_contiguous = 1;
                        dprintk(1,
                                KERN_INFO
index 5f90db27892b9386a5b7c56f3a81e2bf6d7954ce..862a984c2155c6d8a739f54f4007f90b1a20f13b 100644 (file)
@@ -1512,6 +1512,13 @@ setup_fbuffer (struct file               *file,
        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
                return -EPERM;
 
+       /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on
+          ALi Magik (that needs very low latency while the card needs a
+          higher value always) */
+
+       if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+               return -ENXIO;
+
        /* we need a bytesperline value, even if not given */
        if (!bytesperline)
                bytesperline = width * ((fmt->depth + 7) & ~7) / 8;
index 50437383ed6297476380cc1f4ed49014a2778c9a..9240638a01342bca3ad81d7b463dc906b30764cd 100644 (file)
@@ -987,6 +987,8 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
                         VID_TYPE_SCALES;
                if (ztv->have_tuner)
                        c.type |= VID_TYPE_TUNER;
+               if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))
+                       c.type &= ~VID_TYPE_OVERLAY;
                if (ztv->have_decoder) {
                        c.channels = ztv->card->video_inputs;
                        c.audios = ztv->card->audio_inputs;
@@ -1284,6 +1286,8 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
                struct video_buffer v;
                if(!capable(CAP_SYS_ADMIN))
                        return -EPERM;
+               if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))
+                       return -ENXIO;
                if (copy_from_user(&v, arg,sizeof(v)))
                        return -EFAULT;
                DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline));
@@ -2030,7 +2034,7 @@ void release_zoran(int max)
                /* free it */
                free_irq(ztv->dev->irq,ztv);
 
-               /* unregister i2c_bus */
+               /* unregister i2c_bus */
                i2c_unregister_bus((&ztv->i2c));
 
                /* unmap and free memory */
index fef677103880b5e94a80c84bf52dcb692fbc4340..6443392bffff17402d59b2ff39f3700a7229e7fe 100644 (file)
@@ -88,7 +88,7 @@ config I2O_BUS
 
 config I2O_BLOCK
        tristate "I2O Block OSM"
-       depends on I2O
+       depends on I2O && BLOCK
        ---help---
          Include support for the I2O Block OSM. The Block OSM presents disk
          and other structured block devices to the operating system. If you
index 1ddc2fb429d5668a2f653c2c3e5d7561e5a4a92d..eaba81bf2ecad7a023d6e1ae22563ed9900bfcab 100644 (file)
@@ -390,9 +390,9 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
        }
 
        /* request is already processed by us, so return */
-       if (req->flags & REQ_SPECIAL) {
+       if (blk_special_request(req)) {
                osm_debug("REQ_SPECIAL already set!\n");
-               req->flags |= REQ_DONTPREP;
+               req->cmd_flags |= REQ_DONTPREP;
                return BLKPREP_OK;
        }
 
@@ -411,7 +411,8 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
                ireq = req->special;
 
        /* do not come back here */
-       req->flags |= REQ_DONTPREP | REQ_SPECIAL;
+       req->cmd_type = REQ_TYPE_SPECIAL;
+       req->cmd_flags |= REQ_DONTPREP;
 
        return BLKPREP_OK;
 };
index 1b58444d5aafa4d2bea4e96a18c9229357a5269d..dec41cc8993786f111ee216af84849c1fbc728b0 100644 (file)
@@ -372,12 +372,13 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
                 * Expose the ship behind i960 for initialization, or it will
                 * failed
                 */
-               i960 =
-                   pci_find_slot(c->pdev->bus->number,
+               i960 = pci_get_slot(c->pdev->bus,
                                  PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
 
-               if (i960)
+               if (i960) {
                        pci_write_config_word(i960, 0x42, 0);
+                       pci_dev_put(i960);
+               }
 
                c->promise = 1;
                c->limit_sectors = 1;
index 02776814443e24df9218fed9b703542e6d66c614..82938ad6ddbd8282752af18c91dcdf37e33b392a 100644 (file)
@@ -58,6 +58,7 @@ static int adcsync;
 static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
 {
        struct input_dev *idev = ts->idev;
+
        input_report_abs(idev, ABS_X, x);
        input_report_abs(idev, ABS_Y, y);
        input_report_abs(idev, ABS_PRESSURE, pressure);
@@ -67,6 +68,7 @@ static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x
 static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
 {
        struct input_dev *idev = ts->idev;
+
        input_report_abs(idev, ABS_PRESSURE, 0);
        input_sync(idev);
 }
@@ -189,6 +191,7 @@ static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
 static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
 {
        unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
+
        if (machine_is_collie())
                return (!(val & (UCB_TS_CR_TSPX_LOW)));
        else
@@ -291,6 +294,7 @@ static int ucb1x00_thread(void *_ts)
 static void ucb1x00_ts_irq(int idx, void *id)
 {
        struct ucb1x00_ts *ts = id;
+
        ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
        wake_up(&ts->irq_wait);
 }
@@ -372,36 +376,43 @@ static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
 static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
 {
        struct ucb1x00_ts *ts;
+       struct input_dev *idev;
+       int err;
 
        ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
-       if (!ts)
-               return -ENOMEM;
-
-       ts->idev = input_allocate_device();
-       if (!ts->idev) {
-               kfree(ts);
-               return -ENOMEM;
+       idev = input_allocate_device();
+       if (!ts || !idev) {
+               err = -ENOMEM;
+               goto fail;
        }
 
        ts->ucb = dev->ucb;
+       ts->idev = idev;
        ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
 
-       ts->idev->private = ts;
-       ts->idev->name       = "Touchscreen panel";
-       ts->idev->id.product = ts->ucb->id;
-       ts->idev->open       = ucb1x00_ts_open;
-       ts->idev->close      = ucb1x00_ts_close;
+       idev->private    = ts;
+       idev->name       = "Touchscreen panel";
+       idev->id.product = ts->ucb->id;
+       idev->open       = ucb1x00_ts_open;
+       idev->close      = ucb1x00_ts_close;
 
-       __set_bit(EV_ABS, ts->idev->evbit);
-       __set_bit(ABS_X, ts->idev->absbit);
-       __set_bit(ABS_Y, ts->idev->absbit);
-       __set_bit(ABS_PRESSURE, ts->idev->absbit);
+       __set_bit(EV_ABS, idev->evbit);
+       __set_bit(ABS_X, idev->absbit);
+       __set_bit(ABS_Y, idev->absbit);
+       __set_bit(ABS_PRESSURE, idev->absbit);
 
-       input_register_device(ts->idev);
+       err = input_register_device(idev);
+       if (err)
+               goto fail;
 
        dev->priv = ts;
 
        return 0;
+
+ fail:
+       input_free_device(idev);
+       kfree(ts);
+       return err;
 }
 
 static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
index 4a35caff5d020e0e16d0f624e648ccb8cbf5b650..b99dc507de2e4fffd7f2e19e6084cdd7b52b8694 100644 (file)
@@ -147,7 +147,6 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
        if (ret) {
                ret->i_mode = mode;
                ret->i_uid = ret->i_gid = 0;
-               ret->i_blksize = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
@@ -175,7 +174,7 @@ static struct dentry *ibmasmfs_create_file (struct super_block *sb,
        }
 
        inode->i_fop = fops;
-       inode->u.generic_ip = data;
+       inode->i_private = data;
 
        d_add(dentry, inode);
        return dentry;
@@ -244,7 +243,7 @@ static int command_file_open(struct inode *inode, struct file *file)
 {
        struct ibmasmfs_command_data *command_data;
 
-       if (!inode->u.generic_ip)
+       if (!inode->i_private)
                return -ENODEV;
 
        command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL);
@@ -252,7 +251,7 @@ static int command_file_open(struct inode *inode, struct file *file)
                return -ENOMEM;
 
        command_data->command = NULL;
-       command_data->sp = inode->u.generic_ip;
+       command_data->sp = inode->i_private;
        file->private_data = command_data;
        return 0;
 }
@@ -351,10 +350,10 @@ static int event_file_open(struct inode *inode, struct file *file)
        struct ibmasmfs_event_data *event_data;
        struct service_processor *sp; 
 
-       if (!inode->u.generic_ip)
+       if (!inode->i_private)
                return -ENODEV;
 
-       sp = inode->u.generic_ip;
+       sp = inode->i_private;
 
        event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL);
        if (!event_data)
@@ -439,14 +438,14 @@ static int r_heartbeat_file_open(struct inode *inode, struct file *file)
 {
        struct ibmasmfs_heartbeat_data *rhbeat;
 
-       if (!inode->u.generic_ip)
+       if (!inode->i_private)
                return -ENODEV;
 
        rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL);
        if (!rhbeat)
                return -ENOMEM;
 
-       rhbeat->sp = (struct service_processor *)inode->u.generic_ip;
+       rhbeat->sp = inode->i_private;
        rhbeat->active = 0;
        ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat);
        file->private_data = rhbeat;
@@ -508,7 +507,7 @@ static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf,
 
 static int remote_settings_file_open(struct inode *inode, struct file *file)
 {
-       file->private_data = inode->u.generic_ip;
+       file->private_data = inode->i_private;
        return 0;
 }
 
index 45bcf098e762c500e3777facb3a85c8f841ab385..f540bd88dc5a23aa12216079cf7ad675b2eff092 100644 (file)
@@ -21,7 +21,7 @@ config MMC_DEBUG
 
 config MMC_BLOCK
        tristate "MMC block device driver"
-       depends on MMC
+       depends on MMC && BLOCK
        default y
        help
          Say Y here to enable the MMC block device driver support.
index d2957e35cc6f2d40c6a9031c98a2a88aad3ba0ef..b1f6e03e7aa9cd216a6a12ccc9518956f0cb2fbb 100644 (file)
@@ -24,7 +24,8 @@ obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)         += omap.o
 obj-$(CONFIG_MMC_AT91RM9200)   += at91_mci.o
 
-mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
+mmc_core-y := mmc.o mmc_sysfs.o
+mmc_core-$(CONFIG_BLOCK) += mmc_queue.o
 
 ifeq ($(CONFIG_MMC_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 6b7638b84290c0e91d4bc03e2be7328ee0388c64..cb142a66098cf1d30f520207e295d13c5f7c6bdf 100644 (file)
@@ -822,6 +822,7 @@ static int at91_mci_probe(struct platform_device *pdev)
        mmc->f_min = 375000;
        mmc->f_max = 25000000;
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_BYTEBLOCK;
 
        host = mmc_priv(mmc);
        host->mmc = mmc;
@@ -850,7 +851,7 @@ static int at91_mci_probe(struct platform_device *pdev)
        /*
         * Allocate the MCI interrupt
         */
-       ret = request_irq(AT91_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+       ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
        if (ret) {
                printk(KERN_ERR "Failed to request MCI interrupt\n");
                clk_disable(mci_clk);
@@ -906,7 +907,7 @@ static int at91_mci_remove(struct platform_device *pdev)
 
        mmc_remove_host(mmc);
        at91_mci_disable();
-       free_irq(AT91_ID_MCI, host);
+       free_irq(AT91RM9200_ID_MCI, host);
        mmc_free_host(mmc);
 
        clk_disable(mci_clk);                           /* Disable the peripheral clock */
index fb6565b98f32af75a0d4a5c25547b43b87a55f7f..1b79dd271aae37ce9e9d8c8d59b98683ca4fb543 100644 (file)
@@ -956,7 +956,7 @@ static int imxmci_probe(struct platform_device *pdev)
        mmc->f_min = 150000;
        mmc->f_max = CLK_RATE/2;
        mmc->ocr_avail = MMC_VDD_32_33;
-       mmc->caps |= MMC_CAP_4_BIT_DATA;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_BYTEBLOCK;
 
        /* MMC core transfer sizes tunable parameters */
        mmc->max_hw_segs = 64;
index 74eaaee66de0e59532ba5655fddac5aaeea5ba08..5b9caa7978d34311839840243e38921255f6da4b 100644 (file)
@@ -996,7 +996,6 @@ static void mmc_read_scrs(struct mmc_host *host)
 
                mmc_set_data_timeout(&data, card, 0);
 
-               data.blksz_bits = 3;
                data.blksz = 1 << 3;
                data.blocks = 1;
                data.flags = MMC_DATA_READ;
index a0e0dad1b41944de1a59ab9b4c1c6e01c1ed42e7..db0e8ad439a5f6c8e09f873bf5734d9bc51df217 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -165,6 +166,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        do {
                struct mmc_blk_request brq;
                struct mmc_command cmd;
+               u32 readcmd, writecmd;
 
                memset(&brq, 0, sizeof(struct mmc_blk_request));
                brq.mrq.cmd = &brq.cmd;
@@ -172,7 +174,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
                brq.cmd.arg = req->sector << 9;
                brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-               brq.data.blksz_bits = md->block_bits;
                brq.data.blksz = 1 << md->block_bits;
                brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
                brq.stop.opcode = MMC_STOP_TRANSMISSION;
@@ -181,20 +182,31 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
                mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
 
-               if (rq_data_dir(req) == READ) {
-                       brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
-                       brq.data.flags |= MMC_DATA_READ;
-               } else {
-                       brq.cmd.opcode = MMC_WRITE_BLOCK;
-                       brq.data.flags |= MMC_DATA_WRITE;
+               /*
+                * If the host doesn't support multiple block writes, force
+                * block writes to single block.
+                */
+               if (rq_data_dir(req) != READ &&
+                   !(card->host->caps & MMC_CAP_MULTIWRITE))
                        brq.data.blocks = 1;
-               }
 
                if (brq.data.blocks > 1) {
                        brq.data.flags |= MMC_DATA_MULTI;
                        brq.mrq.stop = &brq.stop;
+                       readcmd = MMC_READ_MULTIPLE_BLOCK;
+                       writecmd = MMC_WRITE_MULTIPLE_BLOCK;
                } else {
                        brq.mrq.stop = NULL;
+                       readcmd = MMC_READ_SINGLE_BLOCK;
+                       writecmd = MMC_WRITE_BLOCK;
+               }
+
+               if (rq_data_dir(req) == READ) {
+                       brq.cmd.opcode = readcmd;
+                       brq.data.flags |= MMC_DATA_READ;
+               } else {
+                       brq.cmd.opcode = writecmd;
+                       brq.data.flags |= MMC_DATA_WRITE;
                }
 
                brq.data.sg = mq->sg;
@@ -219,27 +231,29 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                        goto cmd_err;
                }
 
-               do {
-                       int err;
-
-                       cmd.opcode = MMC_SEND_STATUS;
-                       cmd.arg = card->rca << 16;
-                       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-                       err = mmc_wait_for_cmd(card->host, &cmd, 5);
-                       if (err) {
-                               printk(KERN_ERR "%s: error %d requesting status\n",
-                                      req->rq_disk->disk_name, err);
-                               goto cmd_err;
-                       }
-               } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+               if (rq_data_dir(req) != READ) {
+                       do {
+                               int err;
+
+                               cmd.opcode = MMC_SEND_STATUS;
+                               cmd.arg = card->rca << 16;
+                               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+                               err = mmc_wait_for_cmd(card->host, &cmd, 5);
+                               if (err) {
+                                       printk(KERN_ERR "%s: error %d requesting status\n",
+                                              req->rq_disk->disk_name, err);
+                                       goto cmd_err;
+                               }
+                       } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
 
 #if 0
-               if (cmd.resp[0] & ~0x00000900)
-                       printk(KERN_ERR "%s: status = %08x\n",
-                              req->rq_disk->disk_name, cmd.resp[0]);
-               if (mmc_decode_status(cmd.resp))
-                       goto cmd_err;
+                       if (cmd.resp[0] & ~0x00000900)
+                               printk(KERN_ERR "%s: status = %08x\n",
+                                      req->rq_disk->disk_name, cmd.resp[0]);
+                       if (mmc_decode_status(cmd.resp))
+                               goto cmd_err;
 #endif
+               }
 
                /*
                 * A block was successfully transferred.
index 74f8cdeeff0f8501f379d01037144ecd404c6ff4..4ccdd82b680f8f22ed78e27a89a7d9c418df859a 100644 (file)
@@ -28,7 +28,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
        struct mmc_queue *mq = q->queuedata;
        int ret = BLKPREP_KILL;
 
-       if (req->flags & REQ_SPECIAL) {
+       if (blk_special_request(req)) {
                /*
                 * Special commands already have the command
                 * blocks already setup in req->special.
@@ -36,7 +36,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
                BUG_ON(!req->special);
 
                ret = BLKPREP_OK;
-       } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+       } else if (blk_fs_request(req) || blk_pc_request(req)) {
                /*
                 * Block I/O requests need translating according
                 * to the protocol.
@@ -50,7 +50,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
        }
 
        if (ret == BLKPREP_OK)
-               req->flags |= REQ_DONTPREP;
+               req->cmd_flags |= REQ_DONTPREP;
 
        return ret;
 }
index 1886562abdd40100956cc50b12962bd91bf484d3..2b5a0cc9ea56392efc4a82e040ab67fe66ce1617 100644 (file)
@@ -69,12 +69,13 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
        unsigned int datactrl, timeout, irqmask;
        unsigned long long clks;
        void __iomem *base;
+       int blksz_bits;
 
        DBG(host, "blksz %04x blks %04x flags %08x\n",
-           1 << data->blksz_bits, data->blocks, data->flags);
+           data->blksz, data->blocks, data->flags);
 
        host->data = data;
-       host->size = data->blocks << data->blksz_bits;
+       host->size = data->blksz;
        host->data_xfered = 0;
 
        mmci_init_sg(host, data);
@@ -88,7 +89,10 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
        writel(timeout, base + MMCIDATATIMER);
        writel(host->size, base + MMCIDATALENGTH);
 
-       datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4;
+       blksz_bits = ffs(data->blksz) - 1;
+       BUG_ON(1 << blksz_bits != data->blksz);
+
+       datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
        if (data->flags & MMC_DATA_READ) {
                datactrl |= MCI_DPSM_DIRECTION;
                irqmask = MCI_RXFIFOHALFFULLMASK;
@@ -145,7 +149,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
              unsigned int status)
 {
        if (status & MCI_DATABLOCKEND) {
-               host->data_xfered += 1 << data->blksz_bits;
+               host->data_xfered += data->blksz;
        }
        if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
                if (status & MCI_DATACRCFAIL)
@@ -505,6 +509,7 @@ static int mmci_probe(struct amba_device *dev, void *id)
        mmc->f_min = (host->mclk + 511) / 512;
        mmc->f_max = min(host->mclk, fmax);
        mmc->ocr_avail = plat->ocr_mask;
+       mmc->caps = MMC_CAP_MULTIWRITE;
 
        /*
         * We can do SGIO
index ddf06b32c159912f6b4213364c4f0bc294fd49d4..52c9e52e6b781126ece1830f84e329293365ed1d 100644 (file)
@@ -1034,13 +1034,14 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
        host->irq = pdev->resource[1].start;
        host->base = (void __iomem*)IO_ADDRESS(r->start);
 
-       if (minfo->wire4)
-                mmc->caps |= MMC_CAP_4_BIT_DATA;
-
        mmc->ops = &mmc_omap_ops;
        mmc->f_min = 400000;
        mmc->f_max = 24000000;
        mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_BYTEBLOCK;
+
+       if (minfo->wire4)
+                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
        /* Use scatterlist DMA to reduce per-transfer costs.
         * NOTE max_seg_size assumption that small blocks aren't
index 4e21b3b9d330e4abf9834c22951cb18f8062828d..4dab5ec392eabf450e23d351a0b39c36f63afb68 100644 (file)
@@ -4,8 +4,9 @@
  *  Copyright (C) 2005-2006 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * 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/delay.h>
@@ -1262,7 +1263,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        mmc->ops = &sdhci_ops;
        mmc->f_min = host->max_clk / 256;
        mmc->f_max = host->max_clk;
-       mmc->caps = MMC_CAP_4_BIT_DATA;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
        mmc->ocr_avail = 0;
        if (caps & SDHCI_CAN_VDD_330)
index f2453343f783bd3b7dc75ce3e8946c7c277a9eec..72a67937afe0edc83fe8289116c1e61304367b3f 100644 (file)
@@ -4,8 +4,9 @@
  *  Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * 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.
  */
 
 /*
index c351c6d1a18a11ee8ed712c77248b4337c5729d5..88c6f0b129f5eea6c6ca4f99ac4932a594b46894 100644 (file)
@@ -4,8 +4,9 @@
  *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * 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.
  *
  *
  * Warning!
@@ -1323,7 +1324,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev)
        mmc->f_min = 375000;
        mmc->f_max = 24000000;
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_4_BIT_DATA;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
        spin_lock_init(&host->lock);
 
index 249baa701cb0be7f5930e6282c944f499365119a..6072993f01e3f9debc30c0933856fea23a55190e 100644 (file)
@@ -4,8 +4,9 @@
  *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * 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.
  */
 
 #define LOCK_CODE              0xAA
index a03e862851db65bdd9783685b55e2cf4ec37ce2c..a304b34c2632f32c1713a9d337c02a4e27453bdd 100644 (file)
@@ -166,7 +166,7 @@ config MTD_CHAR
 
 config MTD_BLOCK
        tristate "Caching block device access to MTD devices"
-       depends on MTD
+       depends on MTD && BLOCK
        ---help---
          Although most flash chips have an erase size too large to be useful
          as block devices, it is possible to use MTD devices which are based
@@ -188,7 +188,7 @@ config MTD_BLOCK
 
 config MTD_BLOCK_RO
        tristate "Readonly block device access to MTD devices"
-       depends on MTD_BLOCK!=y && MTD
+       depends on MTD_BLOCK!=y && MTD && BLOCK
        help
          This allows you to mount read-only file systems (such as cramfs)
          from an MTD device, without the overhead (and danger) of the caching
@@ -199,7 +199,7 @@ config MTD_BLOCK_RO
 
 config FTL
        tristate "FTL (Flash Translation Layer) support"
-       depends on MTD
+       depends on MTD && BLOCK
        ---help---
          This provides support for the original Flash Translation Layer which
          is part of the PCMCIA specification. It uses a kind of pseudo-
@@ -215,7 +215,7 @@ config FTL
 
 config NFTL
        tristate "NFTL (NAND Flash Translation Layer) support"
-       depends on MTD
+       depends on MTD && BLOCK
        ---help---
          This provides support for the NAND Flash Translation Layer which is
          used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
@@ -238,7 +238,7 @@ config NFTL_RW
 
 config INFTL
        tristate "INFTL (Inverse NAND Flash Translation Layer) support"
-       depends on MTD
+       depends on MTD && BLOCK
        ---help---
          This provides support for the Inverse NAND Flash Translation
          Layer which is used on M-Systems' newer DiskOnChip devices. It
@@ -255,7 +255,7 @@ config INFTL
 
 config RFD_FTL
         tristate "Resident Flash Disk (Flash Translation Layer) support"
-       depends on MTD
+       depends on MTD && BLOCK
        ---help---
          This provides support for the flash translation layer known
          as the Resident Flash Disk (RFD), as used by the Embedded BIOS
index 16c02b5ccf7ec30c994a7fb5a938e4fcb2d8278b..440f6851da6997ac296be09773ada5d54a00bb4c 100644 (file)
@@ -136,7 +136,7 @@ config MTDRAM_ABS_POS
 
 config MTD_BLOCK2MTD
        tristate "MTD using block device"
-       depends on MTD
+       depends on MTD && BLOCK
        help
          This driver allows a block device to appear as an MTD. It would
          generally be used in the following cases:
index 458d3c8ae1eee3904fa34cbd414d44e6a28633b3..6baf5fe142305cfa1131a0be93a838e3e803a9a4 100644 (file)
@@ -46,7 +46,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
        nsect = req->current_nr_sectors;
        buf = req->buffer;
 
-       if (!(req->flags & REQ_CMD))
+       if (!blk_fs_request(req))
                return 0;
 
        if (block + nsect > get_capacity(req->rq_disk))
index 59c33925be62d2a90cba16c91f767718090bbd0f..b936373ab2a5f1e16754f7301b2cb0890fb9646d 100644 (file)
@@ -225,6 +225,7 @@ static struct eisa_device_id el3_eisa_ids[] = {
                { "TCM5095" },
                { "" }
 };
+MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
 
 static int el3_eisa_probe (struct device *device);
 
index af301f09d674223fe23299f02409290172c490aa..df42e28cc80f68808164a932c2ab8b8fda764c30 100644 (file)
@@ -851,6 +851,7 @@ static struct eisa_device_id vortex_eisa_ids[] = {
        { "TCM5970", CH_3C597 },
        { "" }
 };
+MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
 
 static int vortex_eisa_probe(struct device *device);
 static int vortex_eisa_remove(struct device *device);
index 5b6b05ed8f3c90553d5b9d710e39d4da54edb74d..9d34056147ad5c4c026b74e58a59ffc99cb1ec62 100644 (file)
@@ -299,7 +299,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
         *      Slow phase with lock held.
         */
 
-       disable_irq_nosync_lockdep(dev->irq);
+       disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
 
        spin_lock(&ei_local->page_lock);
 
@@ -338,7 +338,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_stop_queue(dev);
                outb_p(ENISR_ALL, e8390_base + EN0_IMR);
                spin_unlock(&ei_local->page_lock);
-               enable_irq_lockdep(dev->irq);
+               enable_irq_lockdep_irqrestore(dev->irq, &flags);
                ei_local->stat.tx_errors++;
                return 1;
        }
@@ -379,7 +379,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 
        spin_unlock(&ei_local->page_lock);
-       enable_irq_lockdep(dev->irq);
+       enable_irq_lockdep_irqrestore(dev->irq, &flags);
 
        dev_kfree_skb (skb);
        ei_local->stat.tx_bytes += send_length;
index 63154774c257be95f733aef42320439aec55cd92..ff8a8c0a26d5ce33c227ab5b75cabc63472c3649 100644 (file)
@@ -24,6 +24,9 @@ config NETDEVICES
 
          If unsure, say Y.
 
+# All the following symbols are dependent on NETDEVICES - do not repeat
+# that for each of the symbols.
+if NETDEVICES
 
 config IFB
        tristate "Intermediate Functional Block support"
@@ -2852,6 +2855,8 @@ config NETCONSOLE
        If you want to log kernel messages over the network, enable this.
        See <file:Documentation/networking/netconsole.txt> for details.
 
+endif #NETDEVICES
+
 config NETPOLL
        def_bool NETCONSOLE
 
index a075246f6f438b981282f3c57752d383caf4b77c..71a4f60f7325755f7bacd457b97c3352c7f7254b 100644 (file)
@@ -163,11 +163,7 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 #define SET_NETDEV_DEV(net, pdev)      do{} while(0)
 #endif
 
-#if LINUX_VERSION_CODE >= 0x2051c
 #define ace_sync_irq(irq)      synchronize_irq(irq)
-#else
-#define ace_sync_irq(irq)      synchronize_irq()
-#endif
 
 #ifndef offset_in_page
 #define offset_in_page(ptr)    ((unsigned long)(ptr) & ~PAGE_MASK)
index 7f7dd450226a8f853224a987302a21b2bf24acc2..b98592a8bac8034fb899c6b7f6c452be1b1bb68e 100644 (file)
@@ -145,9 +145,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Create the Extended DDP header */
        ddp = (struct ddpehdr *)skb->data;
-        ddp->deh_len = skb->len;
-        ddp->deh_hops = 1;
-        ddp->deh_pad = 0;
+        ddp->deh_len_hops = htons(skb->len + (1<<10));
         ddp->deh_sum = 0;
 
        /*
@@ -170,7 +168,6 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
         ddp->deh_sport = 72;
 
         *((__u8 *)(ddp+1)) = 22;               /* ddp type = IP */
-        *((__u16 *)ddp)=ntohs(*((__u16 *)ddp));        /* fix up length field */
 
         skb->protocol = htons(ETH_P_ATALK);     /* Protocol has changed */
 
index 95b28aa01f4fa9bcb22b9172ee53c32045dac134..3ecf2cc53a7ca2305f76b96ef754b2acb3505bce 100644 (file)
@@ -947,7 +947,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
                return -ENOMEM;
 
        dev->base_addr = AT91_VA_BASE_EMAC;
-       dev->irq = AT91_ID_EMAC;
+       dev->irq = AT91RM9200_ID_EMAC;
        SET_MODULE_OWNER(dev);
 
        /* Install the interrupt handler */
index 7fcf015021ecf9986950f22cacbb2a6432845c07..6b4edb63c4c485faaf029164bc6b32ea99c9a982 100644 (file)
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.4.44"
-#define DRV_MODULE_RELDATE     "August 10, 2006"
+#define DRV_MODULE_VERSION     "1.4.45"
+#define DRV_MODULE_RELDATE     "September 29, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -5805,6 +5805,34 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                bp->cmd_ticks_int = bp->cmd_ticks;
        }
 
+       /* Disable MSI on 5706 if AMD 8132 bridge is found.
+        *
+        * MSI is defined to be 32-bit write.  The 5706 does 64-bit MSI writes
+        * with byte enables disabled on the unused 32-bit word.  This is legal
+        * but causes problems on the AMD 8132 which will eventually stop
+        * responding after a while.
+        *
+        * AMD believes this incompatibility is unique to the 5706, and
+        * prefers to locally disable MSI rather than globally disabling it
+        * using pci_msi_quirk.
+        */
+       if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) {
+               struct pci_dev *amd_8132 = NULL;
+
+               while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
+                                                 PCI_DEVICE_ID_AMD_8132_BRIDGE,
+                                                 amd_8132))) {
+                       u8 rev;
+
+                       pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev);
+                       if (rev >= 0x10 && rev <= 0x13) {
+                               disable_msi = 1;
+                               pci_dev_put(amd_8132);
+                               break;
+                       }
+               }
+       }
+
        bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
        bp->req_line_speed = 0;
        if (bp->phy_flags & PHY_SERDES_FLAG) {
index 6a407070c2e89bb48e2bd60d0dedf71ea796fb3e..3fb354d9c5156b6e25ab617cbcded5d4e57e74d1 100644 (file)
@@ -85,6 +85,7 @@
 #define     AD_LINK_SPEED_BITMASK_10MBPS      0x2
 #define     AD_LINK_SPEED_BITMASK_100MBPS     0x4
 #define     AD_LINK_SPEED_BITMASK_1000MBPS    0x8
+#define     AD_LINK_SPEED_BITMASK_10000MBPS   0x10
 //endalloun
 
 // compare MAC addresses
@@ -99,7 +100,7 @@ static u16 __get_link_speed(struct port *port);
 static u8 __get_duplex(struct port *port);
 static inline void __initialize_port_locks(struct port *port);
 //conversions
-static void __ntohs_lacpdu(struct lacpdu *lacpdu);
+static void __htons_lacpdu(struct lacpdu *lacpdu);
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 Par);
 
 
@@ -330,7 +331,8 @@ static inline void __release_rx_machine_lock(struct port *port)
  *     0,
  *     %AD_LINK_SPEED_BITMASK_10MBPS,
  *     %AD_LINK_SPEED_BITMASK_100MBPS,
- *     %AD_LINK_SPEED_BITMASK_1000MBPS
+ *     %AD_LINK_SPEED_BITMASK_1000MBPS,
+ *     %AD_LINK_SPEED_BITMASK_10000MBPS
  */
 static u16 __get_link_speed(struct port *port)
 {
@@ -357,6 +359,10 @@ static u16 __get_link_speed(struct port *port)
                        speed = AD_LINK_SPEED_BITMASK_1000MBPS;
                        break;
 
+               case SPEED_10000:
+                       speed = AD_LINK_SPEED_BITMASK_10000MBPS;
+                       break;
+
                default:
                        speed = 0; // unknown speed value from ethtool. shouldn't happen
                        break;
@@ -414,23 +420,23 @@ static inline void __initialize_port_locks(struct port *port)
 
 //conversions
 /**
- * __ntohs_lacpdu - convert the contents of a LACPDU to host byte order
+ * __htons_lacpdu - convert the contents of a LACPDU to network byte order
  * @lacpdu: the speicifed lacpdu
  *
  * For each multi-byte field in the lacpdu, convert its content
  */
-static void __ntohs_lacpdu(struct lacpdu *lacpdu)
+static void __htons_lacpdu(struct lacpdu *lacpdu)
 {
        if (lacpdu) {
-               lacpdu->actor_system_priority =   ntohs(lacpdu->actor_system_priority);
-               lacpdu->actor_key =               ntohs(lacpdu->actor_key);
-               lacpdu->actor_port_priority =     ntohs(lacpdu->actor_port_priority);
-               lacpdu->actor_port =              ntohs(lacpdu->actor_port);
-               lacpdu->partner_system_priority = ntohs(lacpdu->partner_system_priority);
-               lacpdu->partner_key =             ntohs(lacpdu->partner_key);
-               lacpdu->partner_port_priority =   ntohs(lacpdu->partner_port_priority);
-               lacpdu->partner_port =            ntohs(lacpdu->partner_port);
-               lacpdu->collector_max_delay =     ntohs(lacpdu->collector_max_delay);
+               lacpdu->actor_system_priority =   htons(lacpdu->actor_system_priority);
+               lacpdu->actor_key =               htons(lacpdu->actor_key);
+               lacpdu->actor_port_priority =     htons(lacpdu->actor_port_priority);
+               lacpdu->actor_port =              htons(lacpdu->actor_port);
+               lacpdu->partner_system_priority = htons(lacpdu->partner_system_priority);
+               lacpdu->partner_key =             htons(lacpdu->partner_key);
+               lacpdu->partner_port_priority =   htons(lacpdu->partner_port_priority);
+               lacpdu->partner_port =            htons(lacpdu->partner_port);
+               lacpdu->collector_max_delay =     htons(lacpdu->collector_max_delay);
        }
 }
 
@@ -490,11 +496,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // record the new parameter values for the partner operational
-               port->partner_oper_port_number = lacpdu->actor_port;
-               port->partner_oper_port_priority = lacpdu->actor_port_priority;
+               port->partner_oper_port_number = ntohs(lacpdu->actor_port);
+               port->partner_oper_port_priority = ntohs(lacpdu->actor_port_priority);
                port->partner_oper_system = lacpdu->actor_system;
-               port->partner_oper_system_priority = lacpdu->actor_system_priority;
-               port->partner_oper_key = lacpdu->actor_key;
+               port->partner_oper_system_priority = ntohs(lacpdu->actor_system_priority);
+               port->partner_oper_key = ntohs(lacpdu->actor_key);
                // zero partener's lase states
                port->partner_oper_port_state = 0;
                port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_ACTIVITY);
@@ -561,11 +567,11 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if any parameter is different
-               if ((lacpdu->actor_port != port->partner_oper_port_number) ||
-                   (lacpdu->actor_port_priority != port->partner_oper_port_priority) ||
+               if ((ntohs(lacpdu->actor_port) != port->partner_oper_port_number) ||
+                   (ntohs(lacpdu->actor_port_priority) != port->partner_oper_port_priority) ||
                    MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->partner_oper_system)) ||
-                   (lacpdu->actor_system_priority != port->partner_oper_system_priority) ||
-                   (lacpdu->actor_key != port->partner_oper_key) ||
+                   (ntohs(lacpdu->actor_system_priority) != port->partner_oper_system_priority) ||
+                   (ntohs(lacpdu->actor_key) != port->partner_oper_key) ||
                    ((lacpdu->actor_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
                   ) {
                        // update the state machine Selected variable
@@ -628,11 +634,11 @@ static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if all parameters are alike
-               if (((lacpdu->partner_port == port->actor_port_number) &&
-                    (lacpdu->partner_port_priority == port->actor_port_priority) &&
+               if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
+                    (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
                     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
-                    (lacpdu->partner_system_priority == port->actor_system_priority) &&
-                    (lacpdu->partner_key == port->actor_oper_port_key) &&
+                    (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
+                    (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
                     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
                    // or this is individual link(aggregation == FALSE)
                    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
@@ -662,11 +668,11 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if any parameter is different
-               if ((lacpdu->partner_port != port->actor_port_number) ||
-                   (lacpdu->partner_port_priority != port->actor_port_priority) ||
+               if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
+                   (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
                    MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
-                   (lacpdu->partner_system_priority != port->actor_system_priority) ||
-                   (lacpdu->partner_key != port->actor_oper_port_key) ||
+                   (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
+                   (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) ||
                    ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
@@ -775,6 +781,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                case AD_LINK_SPEED_BITMASK_1000MBPS:
                        bandwidth = aggregator->num_of_ports * 1000;
                        break;
+               case AD_LINK_SPEED_BITMASK_10000MBPS:
+                       bandwidth = aggregator->num_of_ports * 10000;
+                       break;
                default:
                        bandwidth=0; // to silent the compilor ....
                }
@@ -847,7 +856,7 @@ static inline void __update_lacpdu_from_port(struct port *port)
         */
 
        /* Convert all non u8 parameters to Big Endian for transmit */
-       __ntohs_lacpdu(lacpdu);
+       __htons_lacpdu(lacpdu);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -2171,7 +2180,6 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
 
                switch (lacpdu->subtype) {
                case AD_TYPE_LACPDU:
-                       __ntohs_lacpdu(lacpdu);
                        dprintk("Received LACPDU on port %d\n", port->actor_port_number);
                        ad_rx_machine(lacpdu, port);
                        break;
index 850aae21a2fe4f48981ead85ee89e2f795e5227c..c0bbddae4ec41ef998d38f17a0a0c4ec8bd28a54 100644 (file)
@@ -96,6 +96,7 @@ static char *lacp_rate        = NULL;
 static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+static char *arp_validate = NULL;
 struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
@@ -127,6 +128,8 @@ module_param(arp_interval, int, 0);
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
 module_param_array(arp_ip_target, charp, NULL, 0);
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
+module_param(arp_validate, charp, 0);
+MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
 
 /*----------------------------- Global variables ----------------------------*/
 
@@ -170,6 +173,14 @@ struct bond_parm_tbl xmit_hashtype_tbl[] = {
 {      NULL,                   -1},
 };
 
+struct bond_parm_tbl arp_validate_tbl[] = {
+{      "none",                 BOND_ARP_VALIDATE_NONE},
+{      "active",               BOND_ARP_VALIDATE_ACTIVE},
+{      "backup",               BOND_ARP_VALIDATE_BACKUP},
+{      "all",                  BOND_ARP_VALIDATE_ALL},
+{      NULL,                   -1},
+};
+
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -638,6 +649,7 @@ verify:
        case SPEED_10:
        case SPEED_100:
        case SPEED_1000:
+       case SPEED_10000:
                break;
        default:
                return -1;
@@ -1210,10 +1222,14 @@ static int bond_compute_features(struct bonding *bond)
        unsigned long features = BOND_INTERSECT_FEATURES;
        struct slave *slave;
        struct net_device *bond_dev = bond->dev;
+       unsigned short max_hard_header_len = ETH_HLEN;
        int i;
 
-       bond_for_each_slave(bond, slave, i)
+       bond_for_each_slave(bond, slave, i) {
                features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+               if (slave->dev->hard_header_len > max_hard_header_len)
+                       max_hard_header_len = slave->dev->hard_header_len;
+       }
 
        if ((features & NETIF_F_SG) && 
            !(features & NETIF_F_ALL_CSUM))
@@ -1231,6 +1247,7 @@ static int bond_compute_features(struct bonding *bond)
 
        features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
        bond_dev->features = features;
+       bond_dev->hard_header_len = max_hard_header_len;
 
        return 0;
 }
@@ -1365,6 +1382,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        }
 
        new_slave->dev = slave_dev;
+       slave_dev->priv_flags |= IFF_BONDING;
 
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
@@ -1417,6 +1435,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        bond_compute_features(bond);
 
+       new_slave->last_arp_rx = jiffies;
+
        if (bond->params.miimon && !bond->params.use_carrier) {
                link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
@@ -1493,29 +1513,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        switch (bond->params.mode) {
        case BOND_MODE_ACTIVEBACKUP:
-               /* if we're in active-backup mode, we need one and
-                * only one active interface. The backup interfaces
-                * will have their SLAVE_INACTIVE flag set because we
-                * need them to be drop all packets. Thus, since we
-                * guarantee that curr_active_slave always point to
-                * the last usable interface, we just have to verify
-                * this interface's flag.
-                */
-               if (((!bond->curr_active_slave) ||
-                    (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
-                   (new_slave->link != BOND_LINK_DOWN)) {
-                       /* first slave or no active slave yet, and this link
-                          is OK, so make this interface the active one */
-                       bond_change_active_slave(bond, new_slave);
-                       printk(KERN_INFO DRV_NAME
-                              ": %s: first active interface up!\n",
-                              bond->dev->name);
-                       netif_carrier_on(bond->dev);
-
-               } else {
-                       dprintk("This is just a backup slave\n");
-                       bond_set_slave_inactive_flags(new_slave);
-               }
+               bond_set_slave_inactive_flags(new_slave);
+               bond_select_active_slave(bond);
                break;
        case BOND_MODE_8023AD:
                /* in 802.3ad mode, the internal mechanism
@@ -1778,7 +1777,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
        dev_set_mac_address(slave_dev, &addr);
 
        slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-                                  IFF_SLAVE_INACTIVE);
+                                  IFF_SLAVE_INACTIVE | IFF_BONDING |
+                                  IFF_SLAVE_NEEDARP);
 
        kfree(slave);
 
@@ -2252,7 +2252,7 @@ static u32 bond_glean_dev_ip(struct net_device *dev)
 {
        struct in_device *idev;
        struct in_ifaddr *ifa;
-       u32 addr = 0;
+       __be32 addr = 0;
 
        if (!dev)
                return 0;
@@ -2291,6 +2291,25 @@ static int bond_has_ip(struct bonding *bond)
        return 0;
 }
 
+static int bond_has_this_ip(struct bonding *bond, u32 ip)
+{
+       struct vlan_entry *vlan, *vlan_next;
+
+       if (ip == bond->master_ip)
+               return 1;
+
+       if (list_empty(&bond->vlan_list))
+               return 0;
+
+       list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+                                vlan_list) {
+               if (ip == vlan->vlan_ip)
+                       return 1;
+       }
+
+       return 0;
+}
+
 /*
  * We go to the (large) trouble of VLAN tagging ARP frames because
  * switches in VLAN mode (especially if ports are configured as
@@ -2429,6 +2448,93 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
        }
 }
 
+static void bond_validate_arp(struct bonding *bond, struct slave *slave, u32 sip, u32 tip)
+{
+       int i;
+       u32 *targets = bond->params.arp_targets;
+
+       targets = bond->params.arp_targets;
+       for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+               dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] "
+                       "%u.%u.%u.%u bhti(tip) %d\n",
+                      NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]),
+                      bond_has_this_ip(bond, tip));
+               if (sip == targets[i]) {
+                       if (bond_has_this_ip(bond, tip))
+                               slave->last_arp_rx = jiffies;
+                       return;
+               }
+       }
+}
+
+static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+{
+       struct arphdr *arp;
+       struct slave *slave;
+       struct bonding *bond;
+       unsigned char *arp_ptr;
+       u32 sip, tip;
+
+       if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+               goto out;
+
+       bond = dev->priv;
+       read_lock(&bond->lock);
+
+       dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
+               bond->dev->name, skb->dev ? skb->dev->name : "NULL",
+               orig_dev ? orig_dev->name : "NULL");
+
+       slave = bond_get_slave_by_dev(bond, orig_dev);
+       if (!slave || !slave_do_arp_validate(bond, slave))
+               goto out_unlock;
+
+       /* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+       if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+                                (2 * dev->addr_len) +
+                                (2 * sizeof(u32)))))
+               goto out_unlock;
+
+       arp = skb->nh.arph;
+       if (arp->ar_hln != dev->addr_len ||
+           skb->pkt_type == PACKET_OTHERHOST ||
+           skb->pkt_type == PACKET_LOOPBACK ||
+           arp->ar_hrd != htons(ARPHRD_ETHER) ||
+           arp->ar_pro != htons(ETH_P_IP) ||
+           arp->ar_pln != 4)
+               goto out_unlock;
+
+       arp_ptr = (unsigned char *)(arp + 1);
+       arp_ptr += dev->addr_len;
+       memcpy(&sip, arp_ptr, 4);
+       arp_ptr += 4 + dev->addr_len;
+       memcpy(&tip, arp_ptr, 4);
+
+       dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u"
+               " tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name,
+               slave->state, bond->params.arp_validate,
+               slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip));
+
+       /*
+        * Backup slaves won't see the ARP reply, but do come through
+        * here for each ARP probe (so we swap the sip/tip to validate
+        * the probe).  In a "redundant switch, common router" type of
+        * configuration, the ARP probe will (hopefully) travel from
+        * the active, through one switch, the router, then the other
+        * switch before reaching the backup.
+        */
+       if (slave->state == BOND_STATE_ACTIVE)
+               bond_validate_arp(bond, slave, sip, tip);
+       else
+               bond_validate_arp(bond, slave, tip, sip);
+
+out_unlock:
+       read_unlock(&bond->lock);
+out:
+       dev_kfree_skb(skb);
+       return NET_RX_SUCCESS;
+}
+
 /*
  * this function is called regularly to monitor each slave's link
  * ensuring that traffic is being sent and received when arp monitoring
@@ -2593,7 +2699,8 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
         */
        bond_for_each_slave(bond, slave, i) {
                if (slave->link != BOND_LINK_UP) {
-                       if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) {
+                       if ((jiffies - slave_last_rx(bond, slave)) <=
+                            delta_in_ticks) {
 
                                slave->link = BOND_LINK_UP;
 
@@ -2638,7 +2745,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
 
                        if ((slave != bond->curr_active_slave) &&
                            (!bond->current_arp_slave) &&
-                           (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
+                           (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) &&
                             bond_has_ip(bond))) {
                                /* a backup slave has gone down; three times
                                 * the delta allows the current slave to be
@@ -2685,7 +2792,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
                 * if it is up and needs to take over as the curr_active_slave
                 */
                if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
-           (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+           (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) &&
             bond_has_ip(bond))) &&
                    ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
 
@@ -2950,7 +3057,7 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave
        seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
        seq_printf(seq, "MII Status: %s\n",
                   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-       seq_printf(seq, "Link Failure Count: %d\n",
+       seq_printf(seq, "Link Failure Count: %u\n",
                   slave->link_failure_count);
 
        seq_printf(seq,
@@ -3210,6 +3317,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
                (event_dev ? event_dev->name : "None"),
                event);
 
+       if (!(event_dev->priv_flags & IFF_BONDING))
+               return NOTIFY_DONE;
+
        if (event_dev->flags & IFF_MASTER) {
                dprintk("IFF_MASTER\n");
                return bond_master_netdev_event(event, event_dev);
@@ -3305,6 +3415,21 @@ static void bond_unregister_lacpdu(struct bonding *bond)
        dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
 }
 
+void bond_register_arp(struct bonding *bond)
+{
+       struct packet_type *pt = &bond->arp_mon_pt;
+
+       pt->type = htons(ETH_P_ARP);
+       pt->dev = NULL; /*bond->dev;XXX*/
+       pt->func = bond_arp_rcv;
+       dev_add_pack(pt);
+}
+
+void bond_unregister_arp(struct bonding *bond)
+{
+       dev_remove_pack(&bond->arp_mon_pt);
+}
+
 /*---------------------------- Hashing Policies -----------------------------*/
 
 /*
@@ -3391,6 +3516,9 @@ static int bond_open(struct net_device *bond_dev)
                } else {
                        arp_timer->function = (void *)&bond_loadbalance_arp_mon;
                }
+               if (bond->params.arp_validate)
+                       bond_register_arp(bond);
+
                add_timer(arp_timer);
        }
 
@@ -3418,9 +3546,11 @@ static int bond_close(struct net_device *bond_dev)
                bond_unregister_lacpdu(bond);
        }
 
+       if (bond->params.arp_validate)
+               bond_unregister_arp(bond);
+
        write_lock_bh(&bond->lock);
 
-       bond_mc_list_destroy(bond);
 
        /* signal timers not to re-arm */
        bond->kill_timers = 1;
@@ -3451,8 +3581,6 @@ static int bond_close(struct net_device *bond_dev)
                break;
        }
 
-       /* Release the bonded slaves */
-       bond_release_all(bond_dev);
 
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
@@ -4179,6 +4307,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
        /* Initialize the device options */
        bond_dev->tx_queue_len = 0;
        bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
+       bond_dev->priv_flags |= IFF_BONDING;
 
        /* At first, we block adding VLANs. That's the only way to
         * prevent problems that occur when adding VLANs over an
@@ -4237,6 +4366,9 @@ static void bond_free_all(void)
        list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
                struct net_device *bond_dev = bond->dev;
 
+               bond_mc_list_destroy(bond);
+               /* Release the bonded slaves */
+               bond_release_all(bond_dev);
                unregister_netdevice(bond_dev);
                bond_deinit(bond_dev);
        }
@@ -4270,6 +4402,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
 
 static int bond_check_params(struct bond_params *params)
 {
+       int arp_validate_value;
+
        /*
         * Convert string parameters.
         */
@@ -4473,6 +4607,29 @@ static int bond_check_params(struct bond_params *params)
                arp_interval = 0;
        }
 
+       if (arp_validate) {
+               if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+                       printk(KERN_ERR DRV_NAME
+              ": arp_validate only supported in active-backup mode\n");
+                       return -EINVAL;
+               }
+               if (!arp_interval) {
+                       printk(KERN_ERR DRV_NAME
+                              ": arp_validate requires arp_interval\n");
+                       return -EINVAL;
+               }
+
+               arp_validate_value = bond_parse_parm(arp_validate,
+                                                    arp_validate_tbl);
+               if (arp_validate_value == -1) {
+                       printk(KERN_ERR DRV_NAME
+                              ": Error: invalid arp_validate \"%s\"\n",
+                              arp_validate == NULL ? "NULL" : arp_validate);
+                       return -EINVAL;
+               }
+       } else
+               arp_validate_value = 0;
+
        if (miimon) {
                printk(KERN_INFO DRV_NAME
                       ": MII link monitoring set to %d ms\n",
@@ -4481,8 +4638,10 @@ static int bond_check_params(struct bond_params *params)
                int i;
 
                printk(KERN_INFO DRV_NAME
-                      ": ARP monitoring set to %d ms with %d target(s):",
-                      arp_interval, arp_ip_count);
+                      ": ARP monitoring set to %d ms, validate %s, with %d target(s):",
+                      arp_interval,
+                      arp_validate_tbl[arp_validate_value].modename,
+                      arp_ip_count);
 
                for (i = 0; i < arp_ip_count; i++)
                        printk (" %s", arp_ip_target[i]);
@@ -4516,6 +4675,7 @@ static int bond_check_params(struct bond_params *params)
        params->xmit_policy = xmit_hashtype;
        params->miimon = miimon;
        params->arp_interval = arp_interval;
+       params->arp_validate = arp_validate_value;
        params->updelay = updelay;
        params->downdelay = downdelay;
        params->use_carrier = use_carrier;
index cfe4dc3a93a3b8c1264ee03dd4516f3aa44dfbd4..ced9ed8f995a45e00f657d085f8f2fce30a16c98 100644 (file)
@@ -51,6 +51,7 @@ extern struct bond_params bonding_defaults;
 extern struct bond_parm_tbl bond_mode_tbl[];
 extern struct bond_parm_tbl bond_lacp_tbl[];
 extern struct bond_parm_tbl xmit_hashtype_tbl[];
+extern struct bond_parm_tbl arp_validate_tbl[];
 
 static int expected_refcount = -1;
 static struct class *netdev_class;
@@ -502,6 +503,53 @@ out:
 }
 static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
 
+/*
+ * Show and set arp_validate.
+ */
+static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf)
+{
+       struct bonding *bond = to_bond(cd);
+
+       return sprintf(buf, "%s %d\n",
+                      arp_validate_tbl[bond->params.arp_validate].modename,
+                      bond->params.arp_validate) + 1;
+}
+
+static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count)
+{
+       int new_value;
+       struct bonding *bond = to_bond(cd);
+
+       new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
+       if (new_value < 0) {
+               printk(KERN_ERR DRV_NAME
+                      ": %s: Ignoring invalid arp_validate value %s\n",
+                      bond->dev->name, buf);
+               return -EINVAL;
+       }
+       if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
+               printk(KERN_ERR DRV_NAME
+                      ": %s: arp_validate only supported in active-backup mode.\n",
+                      bond->dev->name);
+               return -EINVAL;
+       }
+       printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
+              bond->dev->name, arp_validate_tbl[new_value].modename,
+              new_value);
+
+       if (!bond->params.arp_validate && new_value) {
+               bond_register_arp(bond);
+       } else if (bond->params.arp_validate && !new_value) {
+               bond_unregister_arp(bond);
+       }
+
+       bond->params.arp_validate = new_value;
+
+       return count;
+}
+
+static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+
 /*
  * Show and set the arp timer interval.  There are two tricky bits
  * here.  First, if ARP monitoring is activated, then we must disable
@@ -914,6 +962,11 @@ static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, si
                               "ARP monitoring. Disabling ARP monitoring...\n",
                               bond->dev->name);
                        bond->params.arp_interval = 0;
+                       if (bond->params.arp_validate) {
+                               bond_unregister_arp(bond);
+                               bond->params.arp_validate =
+                                       BOND_ARP_VALIDATE_NONE;
+                       }
                        /* Kill ARP timer, else it brings bond's link down */
                        if (bond->mii_timer.function) {
                                printk(KERN_INFO DRV_NAME
@@ -1093,7 +1146,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b
                             strlen(slave->dev->name)) == 0) {
                                old_active = bond->curr_active_slave;
                                new_active = slave;
-                               if (new_active && (new_active == old_active)) {
+                               if (new_active == old_active) {
                                        /* do nothing */
                                        printk(KERN_INFO DRV_NAME
                                               ": %s: %s is already the current active slave.\n",
@@ -1273,6 +1326,7 @@ static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, N
 static struct attribute *per_bond_attrs[] = {
        &class_device_attr_slaves.attr,
        &class_device_attr_mode.attr,
+       &class_device_attr_arp_validate.attr,
        &class_device_attr_arp_interval.attr,
        &class_device_attr_arp_ip_target.attr,
        &class_device_attr_downdelay.attr,
index 0bdfe2c714539dd9051d8e721914aa4a612b3b79..dc434fb6da85985def44a225789359a6b076a390 100644 (file)
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION    "3.0.3"
-#define DRV_RELDATE    "March 23, 2006"
+#define DRV_VERSION    "3.1.1"
+#define DRV_RELDATE    "September 26, 2006"
 #define DRV_NAME       "bonding"
 #define DRV_DESCRIPTION        "Ethernet Channel Bonding Driver"
 
@@ -126,6 +126,7 @@ struct bond_params {
        int xmit_policy;
        int miimon;
        int arp_interval;
+       int arp_validate;
        int use_carrier;
        int updelay;
        int downdelay;
@@ -149,8 +150,9 @@ struct slave {
        struct net_device *dev; /* first - useful for panic debug */
        struct slave *next;
        struct slave *prev;
-       s16    delay;
+       int    delay;
        u32    jiffies;
+       u32    last_arp_rx;
        s8     link;    /* one of BOND_LINK_XXXX */
        s8     state;   /* one of BOND_STATE_XXXX */
        u32    original_flags;
@@ -198,6 +200,7 @@ struct bonding {
        struct   bond_params params;
        struct   list_head vlan_list;
        struct   vlan_group *vlgrp;
+       struct   packet_type arp_mon_pt;
 };
 
 /**
@@ -228,6 +231,25 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
        return (struct bonding *)slave->dev->master->priv;
 }
 
+#define BOND_ARP_VALIDATE_NONE         0
+#define BOND_ARP_VALIDATE_ACTIVE       (1 << BOND_STATE_ACTIVE)
+#define BOND_ARP_VALIDATE_BACKUP       (1 << BOND_STATE_BACKUP)
+#define BOND_ARP_VALIDATE_ALL          (BOND_ARP_VALIDATE_ACTIVE | \
+                                        BOND_ARP_VALIDATE_BACKUP)
+
+extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave)
+{
+       return bond->params.arp_validate & (1 << slave->state);
+}
+
+extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave)
+{
+       if (slave_do_arp_validate(bond, slave))
+               return slave->last_arp_rx;
+
+       return slave->dev->last_rx;
+}
+
 static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
        struct bonding *bond = slave->dev->master->priv;
@@ -235,12 +257,14 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave)
            bond->params.mode != BOND_MODE_ALB)
                slave->state = BOND_STATE_BACKUP;
        slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
+       if (slave_do_arp_validate(bond, slave))
+               slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
 }
 
 static inline void bond_set_slave_active_flags(struct slave *slave)
 {
        slave->state = BOND_STATE_ACTIVE;
-       slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+       slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
 }
 
 static inline void bond_set_master_3ad_flags(struct bonding *bond)
@@ -284,6 +308,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
 const char *bond_mode_name(int mode);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
+void bond_register_arp(struct bonding *);
+void bond_unregister_arp(struct bonding *);
 
 #endif /* _LINUX_BONDING_H */
 
index e9361cb5f4cd44297ab0ed0fbe99f050333d9360..d0842527b3694782ebdcbde85e21e5ad95f55193 100644 (file)
@@ -110,7 +110,6 @@ static char version[] __initdata =
  *     DGRS include files
  */
 typedef unsigned char uchar;
-typedef unsigned int bool;
 #define vol volatile
 
 #include "dgrs.h"
index a170e96251f60ce59401ff1fa53519ed650e9dca..4020acb5500580d6e4a356f788ddbcdb40243b11 100644 (file)
@@ -1367,8 +1367,8 @@ struct e1000_hw_stats {
 
 /* Structure containing variables used by the shared code (e1000_hw.c) */
 struct e1000_hw {
-    uint8_t *hw_addr;
-    uint8_t *flash_address;
+    uint8_t __iomem *hw_addr;
+    uint8_t __iomem *flash_address;
     e1000_mac_type mac_type;
     e1000_phy_type phy_type;
     uint32_t phy_init_script;
index 22ac2df1aeb0c513e0d4822cafe5e938d56826c6..e17a1449ee105366dcb0caccc703216edd7ee537 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/8xx_immap.h>
 #include <asm/pgtable.h>
@@ -37,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/commproc.h>
-#include <asm/dma-mapping.h>
 
 #include "fec_8xx.h"
 
index 97db910fbc8c13d52a07d3a517079815e035f201..eea1d66c530e1e32a5a4468779b8f39588542127 100644 (file)
@@ -3789,6 +3789,12 @@ static int nv_loopback_test(struct net_device *dev)
        /* setup packet for tx */
        pkt_len = ETH_DATA_LEN;
        tx_skb = dev_alloc_skb(pkt_len);
+       if (!tx_skb) {
+               printk(KERN_ERR "dev_alloc_skb() failed during loopback test"
+                        " of %s\n", dev->name);
+               ret = 0;
+               goto out;
+       }
        pkt_data = skb_put(tx_skb, pkt_len);
        for (i = 0; i < pkt_len; i++)
                pkt_data[i] = (u8)(i & 0xff);
@@ -3853,7 +3859,7 @@ static int nv_loopback_test(struct net_device *dev)
                       tx_skb->end-tx_skb->data,
                       PCI_DMA_TODEVICE);
        dev_kfree_skb_any(tx_skb);
-
+ out:
        /* stop engines */
        nv_stop_rx(dev);
        nv_stop_tx(dev);
index 95022c005f75cb3497f269476b00657e87b4c493..92590d8fc24b4ee39b9e7bf7175132d5fa5a9002 100644 (file)
@@ -6,11 +6,10 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/phy.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/fs_enet_pd.h>
 
-#include <asm/dma-mapping.h>
-
 #ifdef CONFIG_CPM1
 #include <asm/commproc.h>
 
diff --git a/drivers/net/gt64240eth.h b/drivers/net/gt64240eth.h
deleted file mode 100644 (file)
index 0d6f486..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 Patton Electronics Company
- * Copyright (C) 2002 Momentum Computer
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             stevel@mvista.com or support@mvista.com
- *
- *  This program is free software; you can distribute 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 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.
- *
- * Ethernet driver definitions for the MIPS GT96100 Advanced
- * Communication Controller.
- *
- * Modified for the Marvellous GT64240 Retarded Communication Controller.
- */
-#ifndef _GT64240ETH_H
-#define _GT64240ETH_H
-
-#include <asm/gt64240.h>
-
-#define ETHERNET_PORTS_DIFFERENCE_OFFSETS      0x400
-
-/* Translate those weanie names from Galileo/VxWorks header files: */
-
-#define GT64240_MRR                    MAIN_ROUTING_REGISTER
-#define GT64240_CIU_ARBITER_CONFIG     COMM_UNIT_ARBITER_CONFIGURATION_REGISTER
-#define GT64240_CIU_ARBITER_CONTROL    COMM_UNIT_ARBITER_CONTROL
-#define GT64240_MAIN_LOW_CAUSE         LOW_INTERRUPT_CAUSE_REGISTER
-#define GT64240_MAIN_HIGH_CAUSE        HIGH_INTERRUPT_CAUSE_REGISTER
-#define GT64240_CPU_LOW_MASK           CPU_INTERRUPT_MASK_REGISTER_LOW
-#define GT64240_CPU_HIGH_MASK          CPU_INTERRUPT_MASK_REGISTER_HIGH
-#define GT64240_CPU_SELECT_CAUSE       CPU_SELECT_CAUSE_REGISTER
-
-#define GT64240_ETH_PHY_ADDR_REG       ETHERNET_PHY_ADDRESS_REGISTER
-#define GT64240_ETH_PORT_CONFIG        ETHERNET0_PORT_CONFIGURATION_REGISTER
-#define GT64240_ETH_PORT_CONFIG_EXT    ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER
-#define GT64240_ETH_PORT_COMMAND       ETHERNET0_PORT_COMMAND_REGISTER
-#define GT64240_ETH_PORT_STATUS        ETHERNET0_PORT_STATUS_REGISTER
-#define GT64240_ETH_IO_SIZE            ETHERNET_PORTS_DIFFERENCE_OFFSETS
-#define GT64240_ETH_SMI_REG            ETHERNET_SMI_REGISTER
-#define GT64240_ETH_MIB_COUNT_BASE     ETHERNET0_MIB_COUNTER_BASE
-#define GT64240_ETH_SDMA_CONFIG        ETHERNET0_SDMA_CONFIGURATION_REGISTER
-#define GT64240_ETH_SDMA_COMM          ETHERNET0_SDMA_COMMAND_REGISTER
-#define GT64240_ETH_INT_MASK           ETHERNET0_INTERRUPT_MASK_REGISTER
-#define GT64240_ETH_INT_CAUSE          ETHERNET0_INTERRUPT_CAUSE_REGISTER
-#define GT64240_ETH_CURR_TX_DESC_PTR0  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_TX_DESC_PTR1  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1
-#define GT64240_ETH_1ST_RX_DESC_PTR0   ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_RX_DESC_PTR0  ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_HASH_TBL_PTR       ETHERNET0_HASH_TABLE_POINTER_REGISTER
-
-/* Turn on NAPI by default */
-
-#define        GT64240_NAPI                    1
-
-/* Some 64240 settings that SHOULD eventually be setup in PROM monitor: */
-/* (Board-specific to the DSL3224 Rev A board ONLY!)                    */
-#define D3224_MPP_CTRL0_SETTING                0x66669900
-#define D3224_MPP_CTRL1_SETTING                0x00000000
-#define D3224_MPP_CTRL2_SETTING                0x00887700
-#define D3224_MPP_CTRL3_SETTING                0x00000044
-#define D3224_GPP_IO_CTRL_SETTING      0x0000e800
-#define D3224_GPP_LEVEL_CTRL_SETTING   0xf001f703
-#define D3224_GPP_VALUE_SETTING                0x00000000
-
-/* Keep the ring sizes a power of two for efficiency. */
-//-#define TX_RING_SIZE 16
-#define TX_RING_SIZE   64      /* TESTING !!! */
-#define RX_RING_SIZE   32
-#define PKT_BUF_SZ     1536    /* Size of each temporary Rx buffer. */
-
-#define RX_HASH_TABLE_SIZE 16384
-#define HASH_HOP_NUMBER 12
-
-#define NUM_INTERFACES 3
-
-#define GT64240ETH_TX_TIMEOUT HZ/4
-
-#define MIPS_GT64240_BASE 0xf4000000
-#define GT64240_ETH0_BASE (MIPS_GT64240_BASE + GT64240_ETH_PORT_CONFIG)
-#define GT64240_ETH1_BASE (GT64240_ETH0_BASE + GT64240_ETH_IO_SIZE)
-#define GT64240_ETH2_BASE (GT64240_ETH1_BASE + GT64240_ETH_IO_SIZE)
-
-#if defined(CONFIG_MIPS_DSL3224)
-#define GT64240_ETHER0_IRQ 4
-#define GT64240_ETHER1_IRQ 4
-#else
-#define GT64240_ETHER0_IRQ -1
-#define GT64240_ETHER1_IRQ -1
-#endif
-
-#define REV_GT64240  0x1
-#define REV_GT64240A 0x10
-
-#define GT64240ETH_READ(gp, offset)                                    \
-       GT_READ((gp)->port_offset + (offset))
-
-#define GT64240ETH_WRITE(gp, offset, data)                             \
-       GT_WRITE((gp)->port_offset + (offset), (data))
-
-#define GT64240ETH_SETBIT(gp, offset, bits)                            \
-       GT64240ETH_WRITE((gp), (offset),                                \
-                        GT64240ETH_READ((gp), (offset)) | (bits))
-
-#define GT64240ETH_CLRBIT(gp, offset, bits)                            \
-       GT64240ETH_WRITE((gp), (offset),                                \
-                        GT64240ETH_READ((gp), (offset)) & ~(bits))
-
-#define GT64240_READ(ofs)              GT_READ(ofs)
-#define GT64240_WRITE(ofs, data)       GT_WRITE((ofs), (data))
-
-/* Bit definitions of the SMI Reg */
-enum {
-       smirDataMask = 0xffff,
-       smirPhyAdMask = 0x1f << 16,
-       smirPhyAdBit = 16,
-       smirRegAdMask = 0x1f << 21,
-       smirRegAdBit = 21,
-       smirOpCode = 1 << 26,
-       smirReadValid = 1 << 27,
-       smirBusy = 1 << 28
-};
-
-/* Bit definitions of the Port Config Reg */
-enum pcr_bits {
-       pcrPM = 1 << 0,
-       pcrRBM = 1 << 1,
-       pcrPBF = 1 << 2,
-       pcrEN = 1 << 7,
-       pcrLPBKMask = 0x3 << 8,
-       pcrLPBKBit = 1 << 8,
-       pcrFC = 1 << 10,
-       pcrHS = 1 << 12,
-       pcrHM = 1 << 13,
-       pcrHDM = 1 << 14,
-       pcrHD = 1 << 15,
-       pcrISLMask = 0x7 << 28,
-       pcrISLBit = 28,
-       pcrACCS = 1 << 31
-};
-
-/* Bit definitions of the Port Config Extend Reg */
-enum pcxr_bits {
-       pcxrIGMP = 1,
-       pcxrSPAN = 2,
-       pcxrPAR = 4,
-       pcxrPRIOtxMask = 0x7 << 3,
-       pcxrPRIOtxBit = 3,
-       pcxrPRIOrxMask = 0x3 << 6,
-       pcxrPRIOrxBit = 6,
-       pcxrPRIOrxOverride = 1 << 8,
-       pcxrDPLXen = 1 << 9,
-       pcxrFCTLen = 1 << 10,
-       pcxrFLP = 1 << 11,
-       pcxrFCTL = 1 << 12,
-       pcxrMFLMask = 0x3 << 14,
-       pcxrMFLBit = 14,
-       pcxrMIBclrMode = 1 << 16,
-       pcxrSpeed = 1 << 18,
-       pcxrSpeeden = 1 << 19,
-       pcxrRMIIen = 1 << 20,
-       pcxrDSCPen = 1 << 21
-};
-
-/* Bit definitions of the Port Command Reg */
-enum pcmr_bits {
-       pcmrFJ = 1 << 15
-};
-
-
-/* Bit definitions of the Port Status Reg */
-enum psr_bits {
-       psrSpeed = 1,
-       psrDuplex = 2,
-       psrFctl = 4,
-       psrLink = 8,
-       psrPause = 1 << 4,
-       psrTxLow = 1 << 5,
-       psrTxHigh = 1 << 6,
-       psrTxInProg = 1 << 7
-};
-
-/* Bit definitions of the SDMA Config Reg */
-enum sdcr_bits {
-       sdcrRCMask = 0xf << 2,
-       sdcrRCBit = 2,
-       sdcrBLMR = 1 << 6,
-       sdcrBLMT = 1 << 7,
-       sdcrPOVR = 1 << 8,
-       sdcrRIFB = 1 << 9,
-       sdcrBSZMask = 0x3 << 12,
-       sdcrBSZBit = 12
-};
-
-/* Bit definitions of the SDMA Command Reg */
-enum sdcmr_bits {
-       sdcmrERD = 1 << 7,
-       sdcmrAR = 1 << 15,
-       sdcmrSTDH = 1 << 16,
-       sdcmrSTDL = 1 << 17,
-       sdcmrTXDH = 1 << 23,
-       sdcmrTXDL = 1 << 24,
-       sdcmrAT = 1 << 31
-};
-
-/* Bit definitions of the Interrupt Cause Reg */
-enum icr_bits {
-       icrRxBuffer = 1,
-       icrTxBufferHigh = 1 << 2,
-       icrTxBufferLow = 1 << 3,
-       icrTxEndHigh = 1 << 6,
-       icrTxEndLow = 1 << 7,
-       icrRxError = 1 << 8,
-       icrTxErrorHigh = 1 << 10,
-       icrTxErrorLow = 1 << 11,
-       icrRxOVR = 1 << 12,
-       icrTxUdr = 1 << 13,
-       icrRxBufferQ0 = 1 << 16,
-       icrRxBufferQ1 = 1 << 17,
-       icrRxBufferQ2 = 1 << 18,
-       icrRxBufferQ3 = 1 << 19,
-       icrRxErrorQ0 = 1 << 20,
-       icrRxErrorQ1 = 1 << 21,
-       icrRxErrorQ2 = 1 << 22,
-       icrRxErrorQ3 = 1 << 23,
-       icrMIIPhySTC = 1 << 28,
-       icrSMIdone = 1 << 29,
-       icrEtherIntSum = 1 << 31
-};
-
-
-/* The Rx and Tx descriptor lists. */
-#ifdef __LITTLE_ENDIAN
-typedef struct {
-       u32 cmdstat;
-       u16 reserved;           //-prk21aug01    u32 reserved:16;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u32 buff_ptr;
-       u32 next;
-} gt64240_td_t;
-
-typedef struct {
-       u32 cmdstat;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
-       u32 buff_ptr;
-       u32 next;
-} gt64240_rd_t;
-#elif defined(__BIG_ENDIAN)
-typedef struct {
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u16 reserved;           //-prk21aug01    u32 reserved:16;
-       u32 cmdstat;
-       u32 next;
-       u32 buff_ptr;
-} gt64240_td_t;
-
-typedef struct {
-       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u32 cmdstat;
-       u32 next;
-       u32 buff_ptr;
-} gt64240_rd_t;
-#else
-#error Either __BIG_ENDIAN or __LITTLE_ENDIAN must be defined!
-#endif
-
-
-/* Values for the Tx command-status descriptor entry. */
-enum td_cmdstat {
-       txOwn = 1 << 31,
-       txAutoMode = 1 << 30,
-       txEI = 1 << 23,
-       txGenCRC = 1 << 22,
-       txPad = 1 << 18,
-       txFirst = 1 << 17,
-       txLast = 1 << 16,
-       txErrorSummary = 1 << 15,
-       txReTxCntMask = 0x0f << 10,
-       txReTxCntBit = 10,
-       txCollision = 1 << 9,
-       txReTxLimit = 1 << 8,
-       txUnderrun = 1 << 6,
-       txLateCollision = 1 << 5
-};
-
-
-/* Values for the Rx command-status descriptor entry. */
-enum rd_cmdstat {
-       rxOwn = 1 << 31,
-       rxAutoMode = 1 << 30,
-       rxEI = 1 << 23,
-       rxFirst = 1 << 17,
-       rxLast = 1 << 16,
-       rxErrorSummary = 1 << 15,
-       rxIGMP = 1 << 14,
-       rxHashExpired = 1 << 13,
-       rxMissedFrame = 1 << 12,
-       rxFrameType = 1 << 11,
-       rxShortFrame = 1 << 8,
-       rxMaxFrameLen = 1 << 7,
-       rxOverrun = 1 << 6,
-       rxCollision = 1 << 4,
-       rxCRCError = 1
-};
-
-/* Bit fields of a Hash Table Entry */
-enum hash_table_entry {
-       hteValid = 1,
-       hteSkip = 2,
-       hteRD = 4
-};
-
-// The MIB counters
-typedef struct {
-       u32 byteReceived;
-       u32 byteSent;
-       u32 framesReceived;
-       u32 framesSent;
-       u32 totalByteReceived;
-       u32 totalFramesReceived;
-       u32 broadcastFramesReceived;
-       u32 multicastFramesReceived;
-       u32 cRCError;
-       u32 oversizeFrames;
-       u32 fragments;
-       u32 jabber;
-       u32 collision;
-       u32 lateCollision;
-       u32 frames64;
-       u32 frames65_127;
-       u32 frames128_255;
-       u32 frames256_511;
-       u32 frames512_1023;
-       u32 frames1024_MaxSize;
-       u32 macRxError;
-       u32 droppedFrames;
-       u32 outMulticastFrames;
-       u32 outBroadcastFrames;
-       u32 undersizeFrames;
-} mib_counters_t;
-
-
-struct gt64240_private {
-       gt64240_rd_t *rx_ring;
-       gt64240_td_t *tx_ring;
-       // The Rx and Tx rings must be 16-byte aligned
-       dma_addr_t rx_ring_dma;
-       dma_addr_t tx_ring_dma;
-       char *hash_table;
-       // The Hash Table must be 8-byte aligned
-       dma_addr_t hash_table_dma;
-       int hash_mode;
-
-       // The Rx buffers must be 8-byte aligned
-       char *rx_buff;
-       dma_addr_t rx_buff_dma;
-       // Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
-       // of payload must be 8-byte aligned
-       struct sk_buff *tx_skbuff[TX_RING_SIZE];
-       int rx_next_out;        /* The next free ring entry to receive */
-       int tx_next_in;         /* The next free ring entry to send */
-       int tx_next_out;        /* The last ring entry the ISR processed */
-       int tx_count;           /* current # of pkts waiting to be sent in Tx ring */
-       int intr_work_done;     /* number of Rx and Tx pkts processed in the isr */
-       int tx_full;            /* Tx ring is full */
-
-       mib_counters_t mib;
-       struct net_device_stats stats;
-
-       int io_size;
-       int port_num;           // 0 or 1
-       u32 port_offset;
-
-       int phy_addr;           // PHY address
-       u32 last_psr;           // last value of the port status register
-
-       int options;            /* User-settable misc. driver options. */
-       int drv_flags;
-       spinlock_t lock;        /* Serialise access to device */
-       struct mii_if_info mii_if;
-
-       u32 msg_enable;
-};
-
-#endif /* _GT64240ETH_H */
index e9e6d99a9add263619e2278f756b59ab29709aa4..7c8ccc09b60126a448a70c1ef4e3f77975a1f434 100644 (file)
@@ -287,6 +287,7 @@ comment "FIR device drivers"
 config USB_IRDA
        tristate "IrDA USB dongles"
        depends on IRDA && USB
+       select FW_LOADER
        ---help---
          Say Y here if you want to build support for the USB IrDA FIR Dongle
          device driver.  To compile it as a module, choose M here: the module
index 2a0d538b387fca39f69414aca82d6060ea371a0c..383cef1f5999fbe93e994ddaad893ea7a113d6f1 100644 (file)
@@ -671,10 +671,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
                         * Jean II */
                        done = 1;
                        break;
-               case -ECONNABORTED:             /* -103 */
-               case -ECONNRESET:               /* -104 */
-               case -ETIMEDOUT:                /* -110 */
-               case -ENOENT:                   /* -2 (urb unlinked by us)  */
+               case -ECONNRESET:
+               case -ENOENT:                   /* urb unlinked by us */
                default:                        /* ??? - Play safe */
                        urb->status = 0;
                        netif_wake_queue(self->netdev);
@@ -712,10 +710,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
                         * Jean II */
                        done = 1;
                        break;
-               case -ECONNABORTED:             /* -103 */
-               case -ECONNRESET:               /* -104 */
-               case -ETIMEDOUT:                /* -110 */
-               case -ENOENT:                   /* -2 (urb unlinked by us)  */
+               case -ECONNRESET:
+               case -ENOENT:                   /* urb unlinked by us */
                default:                        /* ??? - Play safe */
                        if(skb != NULL) {
                                dev_kfree_skb_any(skb);
@@ -845,14 +841,14 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
                        self->stats.rx_crc_errors++;    
                        /* Also precursor to a hot-unplug on UHCI. */
                        /* Fallthrough... */
-               case -ECONNRESET:               /* -104 */
+               case -ECONNRESET:
                        /* Random error, if I remember correctly */
                        /* uhci_cleanup_unlink() is going to kill the Rx
                         * URB just after we return. No problem, at this
                         * point the URB will be idle ;-) - Jean II */
-               case -ESHUTDOWN:                /* -108 */
+               case -ESHUTDOWN:
                        /* That's usually a hot-unplug. Submit will fail... */
-               case -ETIMEDOUT:                /* -110 */
+               case -ETIME:
                        /* Usually precursor to a hot-unplug on OHCI. */
                default:
                        self->stats.rx_errors++;
index cb62f2a9676aeb7d46395c162aed054939f93de5..7185a4ee3c1e4bf6070840964c93355bcdcad7c7 100644 (file)
@@ -110,7 +110,7 @@ static nsc_chip_t chips[] = {
        { "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, 
          nsc_ircc_probe_338, nsc_ircc_init_338 },
        /* Contributed by Steffen Pingel - IBM X40 */
-       { "PC8738x", { 0x164e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+       { "PC8738x", { 0x164e, 0x4e, 0x2e }, 0x20, 0xf4, 0xff,
          nsc_ircc_probe_39x, nsc_ircc_init_39x },
        /* Contributed by Jan Frey - IBM A30/A31 */
        { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 
index 2eff45bedc7cbc28a0f819fe44e43feece707bfe..22358ff68c4c7d2fe200a0e5517efb21600a9802 100644 (file)
@@ -2354,6 +2354,26 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
 #define PCIID_VENDOR_INTEL 0x8086
 #define PCIID_VENDOR_ALI 0x10b9
 static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = {
+       /*
+        * Subsystems needing entries:
+        * 0x10b9:0x1533 0x103c:0x0850 HP nx9010 family
+        * 0x10b9:0x1533 0x0e11:0x005a Compaq nc4000 family
+        * 0x8086:0x24cc 0x0e11:0x002a HP nx9000 family
+        */
+       {
+               /* Guessed entry */
+               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+               .device = 0x24cc,
+               .subvendor = 0x103c,
+               .subdevice = 0x08bc,
+               .sir_io = 0x02f8,
+               .fir_io = 0x0130,
+               .fir_irq = 0x05,
+               .fir_dma = 0x03,
+               .cfg_base = 0x004e,
+               .preconfigure = preconfigure_through_82801,
+               .name = "HP nx5000 family",
+       },
        {
                .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
                .device = 0x24cc,
@@ -2366,7 +2386,7 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
                .fir_dma = 0x03,
                .cfg_base = 0x004e,
                .preconfigure = preconfigure_through_82801,
-               .name = "HP nc8000",
+               .name = "HP nc8000 family",
        },
        {
                .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
@@ -2379,7 +2399,21 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __ini
                .fir_dma = 0x03,
                .cfg_base = 0x004e,
                .preconfigure = preconfigure_through_82801,
-               .name = "HP nc6000",
+               .name = "HP nc6000 family",
+       },
+       {
+               .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+               .device = 0x24cc,
+               .subvendor = 0x0e11,
+               .subdevice = 0x0860,
+               /* I assume these are the same for x1000 as for the others */
+               .sir_io = 0x02e8,
+               .fir_io = 0x02f8,
+               .fir_irq = 0x07,
+               .fir_dma = 0x03,
+               .cfg_base = 0x002e,
+               .preconfigure = preconfigure_through_82801,
+               .name = "Compaq x1000 family",
        },
        {
                /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
index d61b208b52a215d4825a72cd3929f57263c8f6d9..12103c93f7efb4622da065c77c9f184bdd76c10f 100644 (file)
@@ -149,8 +149,6 @@ enum StirFifoCtlMask {
        FIFOCTL_DIR = 0x10,
        FIFOCTL_CLR = 0x08,
        FIFOCTL_EMPTY = 0x04,
-       FIFOCTL_RXERR = 0x02,
-       FIFOCTL_TXERR = 0x01,
 };
 
 enum StirDiagMask {
@@ -615,19 +613,6 @@ static int fifo_txwait(struct stir_cb *stir, int space)
 
                pr_debug("fifo status 0x%lx count %lu\n", status, count);
 
-               /* error when receive/transmit fifo gets confused */
-               if (status & FIFOCTL_RXERR) {
-                       stir->stats.rx_fifo_errors++;
-                       stir->stats.rx_errors++;
-                       break;
-               }
-
-               if (status & FIFOCTL_TXERR) {
-                       stir->stats.tx_fifo_errors++;
-                       stir->stats.tx_errors++;
-                       break;
-               }
-
                /* is fifo receiving already, or empty */
                if (!(status & FIFOCTL_DIR)
                    || (status & FIFOCTL_EMPTY))
index 79b85f327500c4e553bccf2c69007d2e22e89468..d916e1257c471d8df1c14e172f9a25963a2c00b8 100644 (file)
@@ -1223,8 +1223,13 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase)
 
        IRDA_DEBUG(2, "%s(): len=%x\n", __FUNCTION__, len);
 
+       if ((len - 4) < 2) {
+               self->stats.rx_dropped++;
+               return FALSE;
+       }
+
        skb = dev_alloc_skb(len + 1);
-       if ((skb == NULL) || ((len - 4) < 2)) {
+       if (skb == NULL) {
                self->stats.rx_dropped++;
                return FALSE;
        }
index a82a4ba8de4fc2a6f27280a127a5997dfbd39637..c37f0bc4c7f9f7257d8f3edad087a30b5c1e347a 100644 (file)
@@ -58,7 +58,7 @@ typedef void irqreturn_t;
 
 /* PDE() introduced in 2.5.4 */
 #ifdef CONFIG_PROC_FS
-#define PDE(inode) ((inode)->u.generic_ip)
+#define PDE(inode) ((inode)->i_private)
 #endif
 
 /* irda crc16 calculation exported in 2.5.42 */
index f429b19bf620edddfeb955077504cb67c20d4e1f..4178b4b1d2df544a5b7c20fe90a0c0b02727ddcf 100644 (file)
@@ -161,15 +161,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
        return(0);
 }
 
+static struct net_device_stats loopback_stats;
+
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
-       struct net_device_stats *stats = dev->priv;
+       struct net_device_stats *stats = &loopback_stats;
        int i;
 
-       if (!stats) {
-               return NULL;
-       }
-
        memset(stats, 0, sizeof(struct net_device_stats));
 
        for_each_possible_cpu(i) {
@@ -185,19 +183,28 @@ static struct net_device_stats *get_stats(struct net_device *dev)
        return stats;
 }
 
-static u32 loopback_get_link(struct net_device *dev)
+static u32 always_on(struct net_device *dev)
 {
        return 1;
 }
 
 static const struct ethtool_ops loopback_ethtool_ops = {
-       .get_link               = loopback_get_link,
+       .get_link               = always_on,
        .get_tso                = ethtool_op_get_tso,
        .set_tso                = ethtool_op_set_tso,
+       .get_tx_csum            = always_on,
+       .get_sg                 = always_on,
+       .get_rx_csum            = always_on,
 };
 
+/*
+ * The loopback device is special. There is only one instance and
+ * it is statically allocated. Don't do this for other devices.
+ */
 struct net_device loopback_dev = {
        .name                   = "lo",
+       .get_stats              = &get_stats,
+       .priv                   = &loopback_stats,
        .mtu                    = (16 * 1024) + 20 + 20 + 12,
        .hard_start_xmit        = loopback_xmit,
        .hard_header            = eth_header,
@@ -221,16 +228,6 @@ struct net_device loopback_dev = {
 /* Setup and register the loopback device. */
 int __init loopback_init(void)
 {
-       struct net_device_stats *stats;
-
-       /* Can survive without statistics */
-       stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
-       if (stats) {
-               memset(stats, 0, sizeof(struct net_device_stats));
-               loopback_dev.priv = stats;
-               loopback_dev.get_stats = &get_stats;
-       }
-
        return register_netdev(&loopback_dev);
 };
 
index 0fa8e4d2276993984075a7e763f921470534e8b9..d663289754255015d90fc7e4cd3b3342e31084bc 100644 (file)
@@ -343,6 +343,7 @@ static struct eisa_device_id ne3210_ids[] = {
        { "NVL1801" },
        { "" },
 };
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
 
 static struct eisa_driver ne3210_eisa_driver = {
        .id_table = ne3210_ids,
index 2d1ecfdc80dbecbc5e345d4524803ecf49bba114..ecd3da151e2d2a17eca4dabf378a3cef41a341df 100644 (file)
@@ -522,7 +522,7 @@ EXPORT_SYMBOL(genphy_read_status);
 
 static int genphy_config_init(struct phy_device *phydev)
 {
-       u32 val;
+       int val;
        u32 features;
 
        /* For now, I'll claim that the generic driver supports
index 5666ed998142475420fbd3f0a5e220a98f1afb6e..0adee733b76121126c4cbfcf0cbed8f9aadbc087 100644 (file)
@@ -600,6 +600,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
                                   dev->hard_header_len);
 
+               po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
                po->chan.private = sk;
                po->chan.ops = &pppoe_chan_ops;
 
index f5dbeb27b6f082553974d8b057f2916266ed92e9..1bf23e41f5804f8f697b347f895b72920cd719aa 100644 (file)
@@ -2904,7 +2904,7 @@ static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device
 {
        u64 val64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        //address transaction
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -2953,7 +2953,7 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
        u64 val64 = 0x0;
        u64 rval64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        /* address transaction */
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -3276,7 +3276,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(void *addr, u64 busy_bit)
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit)
 {
        int ret = FAILURE, cnt = 0;
        u64 val64;
@@ -4303,11 +4303,11 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
        sp->stats.tx_errors =
                le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
        sp->stats.rx_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_drop_frms);
        sp->stats.multicast =
                le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
        sp->stats.rx_length_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_long_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_long_frms);
 
        return (&sp->stats);
 }
index 9142d91355bc9a51b2e0283b2328d0e84dab0c44..705e9a8fa30fb454b60759331910193136316bf1 100644 (file)
@@ -58,6 +58,7 @@
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
 #define BLINK_MS               250
+#define LINK_HZ                        (HZ/2)
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -605,7 +606,12 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
        if (hw->chip_id == CHIP_ID_GENESIS) {
                switch (mode) {
                case LED_MODE_OFF:
-                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       if (hw->phy_type == SK_PHY_BCOM)
+                               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       else {
+                               skge_write32(hw, SK_REG(port, TX_LED_VAL), 0);
+                               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF);
+                       }
                        skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
                        skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
                        skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
@@ -625,8 +631,14 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
                        skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
                        skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
 
-                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
-                       break;
+                       if (hw->phy_type == SK_PHY_BCOM)
+                               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+                       else {
+                               skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON);
+                               skge_write32(hw, SK_REG(port, TX_LED_VAL), 100);
+                               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
+                       }
+
                }
        } else {
                switch (mode) {
@@ -879,6 +891,9 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
        xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
        *val = xm_read16(hw, port, XM_PHY_DATA);
 
+       if (hw->phy_type == SK_PHY_XMAC)
+               goto ready;
+
        for (i = 0; i < PHY_RETRIES; i++) {
                if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
                        goto ready;
@@ -965,7 +980,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
        xm_write16(hw, port, XM_RX_CMD, 0);     /* reset RX CMD Reg */
 
        /* disable Broadcom PHY IRQ */
-       xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+       if (hw->phy_type == SK_PHY_BCOM)
+               xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
 
        xm_outhash(hw, port, XM_HSM, zero);
 }
@@ -1000,60 +1016,64 @@ static void bcom_check_link(struct skge_hw *hw, int port)
 
                if (netif_carrier_ok(dev))
                        skge_link_down(skge);
-       } else {
-               if (skge->autoneg == AUTONEG_ENABLE &&
-                   (status & PHY_ST_AN_OVER)) {
-                       u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP);
-                       u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
-
-                       if (lpa & PHY_B_AN_RF) {
-                               printk(KERN_NOTICE PFX "%s: remote fault\n",
-                                      dev->name);
-                               return;
-                       }
+               return;
+       }
 
-                       /* Check Duplex mismatch */
-                       switch (aux & PHY_B_AS_AN_RES_MSK) {
-                       case PHY_B_RES_1000FD:
-                               skge->duplex = DUPLEX_FULL;
-                               break;
-                       case PHY_B_RES_1000HD:
-                               skge->duplex = DUPLEX_HALF;
-                               break;
-                       default:
-                               printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
-                                      dev->name);
-                               return;
-                       }
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               u16 lpa, aux;
 
+               if (!(status & PHY_ST_AN_OVER))
+                       return;
 
-                       /* We are using IEEE 802.3z/D5.0 Table 37-4 */
-                       switch (aux & PHY_B_AS_PAUSE_MSK) {
-                       case PHY_B_AS_PAUSE_MSK:
-                               skge->flow_control = FLOW_MODE_SYMMETRIC;
-                               break;
-                       case PHY_B_AS_PRR:
-                               skge->flow_control = FLOW_MODE_REM_SEND;
-                               break;
-                       case PHY_B_AS_PRT:
-                               skge->flow_control = FLOW_MODE_LOC_SEND;
-                               break;
-                       default:
-                               skge->flow_control = FLOW_MODE_NONE;
-                       }
+               lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+               if (lpa & PHY_B_AN_RF) {
+                       printk(KERN_NOTICE PFX "%s: remote fault\n",
+                              dev->name);
+                       return;
+               }
 
-                       skge->speed = SPEED_1000;
+               aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+
+               /* Check Duplex mismatch */
+               switch (aux & PHY_B_AS_AN_RES_MSK) {
+               case PHY_B_RES_1000FD:
+                       skge->duplex = DUPLEX_FULL;
+                       break;
+               case PHY_B_RES_1000HD:
+                       skge->duplex = DUPLEX_HALF;
+                       break;
+               default:
+                       printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+                              dev->name);
+                       return;
                }
 
-               if (!netif_carrier_ok(dev))
-                       genesis_link_up(skge);
+
+               /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+               switch (aux & PHY_B_AS_PAUSE_MSK) {
+               case PHY_B_AS_PAUSE_MSK:
+                       skge->flow_control = FLOW_MODE_SYMMETRIC;
+                       break;
+               case PHY_B_AS_PRR:
+                       skge->flow_control = FLOW_MODE_REM_SEND;
+                       break;
+               case PHY_B_AS_PRT:
+                       skge->flow_control = FLOW_MODE_LOC_SEND;
+                       break;
+               default:
+                       skge->flow_control = FLOW_MODE_NONE;
+               }
+               skge->speed = SPEED_1000;
        }
+
+       if (!netif_carrier_ok(dev))
+               genesis_link_up(skge);
 }
 
 /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
  * Phy on for 100 or 10Mbit operation
  */
-static void bcom_phy_init(struct skge_port *skge, int jumbo)
+static void bcom_phy_init(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
@@ -1144,7 +1164,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
                     phy_pause_map[skge->flow_control] | PHY_AN_CSMA);
 
        /* Handle Jumbo frames */
-       if (jumbo) {
+       if (hw->dev[port]->mtu > ETH_DATA_LEN) {
                xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
                             PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK);
 
@@ -1157,8 +1177,154 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
 
        /* Use link status change interrupt */
        xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+}
 
-       bcom_check_link(hw, port);
+static void xm_phy_init(struct skge_port *skge)
+{
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+       u16 ctrl = 0;
+
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               if (skge->advertising & ADVERTISED_1000baseT_Half)
+                       ctrl |= PHY_X_AN_HD;
+               if (skge->advertising & ADVERTISED_1000baseT_Full)
+                       ctrl |= PHY_X_AN_FD;
+
+               switch(skge->flow_control) {
+               case FLOW_MODE_NONE:
+                       ctrl |= PHY_X_P_NO_PAUSE;
+                       break;
+               case FLOW_MODE_LOC_SEND:
+                       ctrl |= PHY_X_P_ASYM_MD;
+                       break;
+               case FLOW_MODE_SYMMETRIC:
+                       ctrl |= PHY_X_P_BOTH_MD;
+                       break;
+               }
+
+               xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl);
+
+               /* Restart Auto-negotiation */
+               ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+       } else {
+               /* Set DuplexMode in Config register */
+               if (skge->duplex == DUPLEX_FULL)
+                       ctrl |= PHY_CT_DUP_MD;
+               /*
+                * Do NOT enable Auto-negotiation here. This would hold
+                * the link down because no IDLEs are transmitted
+                */
+       }
+
+       xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
+
+       /* Poll PHY for status changes */
+       schedule_delayed_work(&skge->link_thread, LINK_HZ);
+}
+
+static void xm_check_link(struct net_device *dev)
+{
+       struct skge_port *skge = netdev_priv(dev);
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+       u16 status;
+
+       /* read twice because of latch */
+       (void) xm_phy_read(hw, port, PHY_XMAC_STAT);
+       status = xm_phy_read(hw, port, PHY_XMAC_STAT);
+
+       if ((status & PHY_ST_LSYNC) == 0) {
+               u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
+               cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+               xm_write16(hw, port, XM_MMU_CMD, cmd);
+               /* dummy read to ensure writing */
+               (void) xm_read16(hw, port, XM_MMU_CMD);
+
+               if (netif_carrier_ok(dev))
+                       skge_link_down(skge);
+               return;
+       }
+
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               u16 lpa, res;
+
+               if (!(status & PHY_ST_AN_OVER))
+                       return;
+
+               lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+               if (lpa & PHY_B_AN_RF) {
+                       printk(KERN_NOTICE PFX "%s: remote fault\n",
+                              dev->name);
+                       return;
+               }
+
+               res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
+
+               /* Check Duplex mismatch */
+               switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) {
+               case PHY_X_RS_FD:
+                       skge->duplex = DUPLEX_FULL;
+                       break;
+               case PHY_X_RS_HD:
+                       skge->duplex = DUPLEX_HALF;
+                       break;
+               default:
+                       printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+                              dev->name);
+                       return;
+               }
+
+               /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+               if (lpa & PHY_X_P_SYM_MD)
+                       skge->flow_control = FLOW_MODE_SYMMETRIC;
+               else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD)
+                       skge->flow_control = FLOW_MODE_REM_SEND;
+               else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD)
+                       skge->flow_control = FLOW_MODE_LOC_SEND;
+               else
+                       skge->flow_control = FLOW_MODE_NONE;
+
+
+               skge->speed = SPEED_1000;
+       }
+
+       if (!netif_carrier_ok(dev))
+               genesis_link_up(skge);
+}
+
+/* Poll to check for link coming up.
+ * Since internal PHY is wired to a level triggered pin, can't
+ * get an interrupt when carrier is detected.
+ */
+static void xm_link_timer(void *arg)
+{
+       struct net_device *dev = arg;
+       struct skge_port *skge = netdev_priv(arg);
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+
+       if (!netif_running(dev))
+               return;
+
+       if (netif_carrier_ok(dev)) {
+               xm_read16(hw, port, XM_ISRC);
+               if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS))
+                       goto nochange;
+       } else {
+               if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+                       goto nochange;
+               xm_read16(hw, port, XM_ISRC);
+               if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
+                       goto nochange;
+       }
+
+       mutex_lock(&hw->phy_mutex);
+       xm_check_link(dev);
+       mutex_unlock(&hw->phy_mutex);
+
+nochange:
+       schedule_delayed_work(&skge->link_thread, LINK_HZ);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -1189,20 +1355,29 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
         * namely for the 1000baseTX cards that use the XMAC's
         * GMII mode.
         */
-       /* Take external Phy out of reset */
-       r = skge_read32(hw, B2_GP_IO);
-       if (port == 0)
-               r |= GP_DIR_0|GP_IO_0;
-       else
-               r |= GP_DIR_2|GP_IO_2;
+       if (hw->phy_type != SK_PHY_XMAC) {
+               /* Take external Phy out of reset */
+               r = skge_read32(hw, B2_GP_IO);
+               if (port == 0)
+                       r |= GP_DIR_0|GP_IO_0;
+               else
+                       r |= GP_DIR_2|GP_IO_2;
 
-       skge_write32(hw, B2_GP_IO, r);
+               skge_write32(hw, B2_GP_IO, r);
 
+               /* Enable GMII interface */
+               xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+       }
 
-       /* Enable GMII interface */
-       xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
 
-       bcom_phy_init(skge, jumbo);
+       switch(hw->phy_type) {
+       case SK_PHY_XMAC:
+               xm_phy_init(skge);
+               break;
+       case SK_PHY_BCOM:
+               bcom_phy_init(skge);
+               bcom_check_link(hw, port);
+       }
 
        /* Set Station Address */
        xm_outaddr(hw, port, XM_SA, dev->dev_addr);
@@ -1335,16 +1510,18 @@ static void genesis_stop(struct skge_port *skge)
        skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
 
        /* For external PHYs there must be special handling */
-       reg = skge_read32(hw, B2_GP_IO);
-       if (port == 0) {
-               reg |= GP_DIR_0;
-               reg &= ~GP_IO_0;
-       } else {
-               reg |= GP_DIR_2;
-               reg &= ~GP_IO_2;
+       if (hw->phy_type != SK_PHY_XMAC) {
+               reg = skge_read32(hw, B2_GP_IO);
+               if (port == 0) {
+                       reg |= GP_DIR_0;
+                       reg &= ~GP_IO_0;
+               } else {
+                       reg |= GP_DIR_2;
+                       reg &= ~GP_IO_2;
+               }
+               skge_write32(hw, B2_GP_IO, reg);
+               skge_read32(hw, B2_GP_IO);
        }
-       skge_write32(hw, B2_GP_IO, reg);
-       skge_read32(hw, B2_GP_IO);
 
        xm_write16(hw, port, XM_MMU_CMD,
                        xm_read16(hw, port, XM_MMU_CMD)
@@ -1406,7 +1583,7 @@ static void genesis_link_up(struct skge_port *skge)
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
        u16 cmd;
-       u32 mode, msk;
+       u32 mode;
 
        cmd = xm_read16(hw, port, XM_MMU_CMD);
 
@@ -1454,27 +1631,24 @@ static void genesis_link_up(struct skge_port *skge)
        }
 
        xm_write32(hw, port, XM_MODE, mode);
-
-       msk = XM_DEF_MSK;
-       /* disable GP0 interrupt bit for external Phy */
-       msk |= XM_IS_INP_ASS;
-
-       xm_write16(hw, port, XM_IMSK, msk);
+       xm_write16(hw, port, XM_IMSK, XM_DEF_MSK);
        xm_read16(hw, port, XM_ISRC);
 
        /* get MMU Command Reg. */
        cmd = xm_read16(hw, port, XM_MMU_CMD);
-       if (skge->duplex == DUPLEX_FULL)
+       if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
                cmd |= XM_MMU_GMII_FD;
 
        /*
         * Workaround BCOM Errata (#10523) for all BCom Phys
         * Enable Power Management after link up
         */
-       xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
-                    xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
-                    & ~PHY_B_AC_DIS_PM);
-       xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+       if (hw->phy_type == SK_PHY_BCOM) {
+               xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+                            xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+                            & ~PHY_B_AC_DIS_PM);
+               xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+       }
 
        /* enable Rx/Tx */
        xm_write16(hw, port, XM_MMU_CMD,
@@ -2240,6 +2414,8 @@ static int skge_down(struct net_device *dev)
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
        netif_stop_queue(dev);
+       if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+               cancel_rearming_delayed_work(&skge->link_thread);
 
        skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
        if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2862,7 +3038,7 @@ static void skge_extirq(void *arg)
                if (netif_running(dev)) {
                        if (hw->chip_id != CHIP_ID_GENESIS)
                                yukon_phy_intr(skge);
-                       else
+                       else if (hw->phy_type == SK_PHY_BCOM)
                                bcom_phy_intr(skge);
                }
        }
@@ -3014,7 +3190,7 @@ static int skge_reset(struct skge_hw *hw)
 {
        u32 reg;
        u16 ctst, pci_status;
-       u8 t8, mac_cfg, pmd_type, phy_type;
+       u8 t8, mac_cfg, pmd_type;
        int i;
 
        ctst = skge_read16(hw, B0_CTST);
@@ -3038,19 +3214,22 @@ static int skge_reset(struct skge_hw *hw)
                     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
 
        hw->chip_id = skge_read8(hw, B2_CHIP_ID);
-       phy_type = skge_read8(hw, B2_E_1) & 0xf;
+       hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
        pmd_type = skge_read8(hw, B2_PMD_TYP);
        hw->copper = (pmd_type == 'T' || pmd_type == '1');
 
        switch (hw->chip_id) {
        case CHIP_ID_GENESIS:
-               switch (phy_type) {
+               switch (hw->phy_type) {
+               case SK_PHY_XMAC:
+                       hw->phy_addr = PHY_ADDR_XMAC;
+                       break;
                case SK_PHY_BCOM:
                        hw->phy_addr = PHY_ADDR_BCOM;
                        break;
                default:
                        printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
-                              pci_name(hw->pdev), phy_type);
+                              pci_name(hw->pdev), hw->phy_type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -3058,7 +3237,7 @@ static int skge_reset(struct skge_hw *hw)
        case CHIP_ID_YUKON:
        case CHIP_ID_YUKON_LITE:
        case CHIP_ID_YUKON_LP:
-               if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+               if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
                        hw->copper = 1;
 
                hw->phy_addr = PHY_ADDR_MARV;
@@ -3089,10 +3268,13 @@ static int skge_reset(struct skge_hw *hw)
        else
                hw->ram_size = t8 * 4096;
 
-       hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
+       hw->intr_mask = IS_HW_ERR | IS_PORT_1;
        if (hw->ports > 1)
                hw->intr_mask |= IS_PORT_2;
 
+       if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+               hw->intr_mask |= IS_EXT_REG;
+
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_init(hw);
        else {
@@ -3226,6 +3408,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        skge->port = port;
 
+       /* Only used for Genesis XMAC */
+       INIT_WORK(&skge->link_thread, xm_link_timer, dev);
+
        if (hw->chip_id != CHIP_ID_GENESIS) {
                dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                skge->rx_csum = 1;
index 79e09271bcf9b5e8f8d25553595b5d020e9e050c..d0b47d46cf9d23701239d7b5c6d5c7d32c477c3d 100644 (file)
@@ -934,7 +934,7 @@ enum {
        PHY_XMAC_AUNE_ADV       = 0x04,/* 16 bit r/w    Auto-Neg. Advertisement */
        PHY_XMAC_AUNE_LP        = 0x05,/* 16 bit r/o    Link Partner Abi Reg */
        PHY_XMAC_AUNE_EXP       = 0x06,/* 16 bit r/o    Auto-Neg. Expansion Reg */
-       PHY_XMAC_NEPG   = 0x07,/* 16 bit r/w    Next Page Register */
+       PHY_XMAC_NEPG           = 0x07,/* 16 bit r/w    Next Page Register */
        PHY_XMAC_NEPG_LP        = 0x08,/* 16 bit r/o    Next Page Link Partner */
 
        PHY_XMAC_EXT_STAT       = 0x0f,/* 16 bit r/o    Ext Status Register */
@@ -1097,13 +1097,36 @@ enum {
 
 /* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
 enum {
-       PHY_X_P_NO_PAUSE        = 0<<7,/* Bit  8..7:    no Pause Mode */
+       PHY_X_P_NO_PAUSE= 0<<7,/* Bit  8..7:    no Pause Mode */
        PHY_X_P_SYM_MD  = 1<<7, /* Bit  8..7:   symmetric Pause Mode */
        PHY_X_P_ASYM_MD = 2<<7,/* Bit  8..7:    asymmetric Pause Mode */
        PHY_X_P_BOTH_MD = 3<<7,/* Bit  8..7:    both Pause Mode */
 };
 
 
+/*****  PHY_XMAC_EXT_STAT      16 bit r/w      Extended Status Register *****/
+enum {
+       PHY_X_EX_FD     = 1<<15, /* Bit 15:     Device Supports Full Duplex */
+       PHY_X_EX_HD     = 1<<14, /* Bit 14:     Device Supports Half Duplex */
+};
+
+/*****  PHY_XMAC_RES_ABI       16 bit r/o      PHY Resolved Ability *****/
+enum {
+       PHY_X_RS_PAUSE  = 3<<7, /* Bit  8..7:   selected Pause Mode */
+       PHY_X_RS_HD     = 1<<6, /* Bit  6:      Half Duplex Mode selected */
+       PHY_X_RS_FD     = 1<<5, /* Bit  5:      Full Duplex Mode selected */
+       PHY_X_RS_ABLMIS = 1<<4, /* Bit  4:      duplex or pause cap mismatch */
+       PHY_X_RS_PAUMIS = 1<<3, /* Bit  3:      pause capability mismatch */
+};
+
+/* Remote Fault Bits (PHY_X_AN_RFB) encoding */
+enum {
+       X_RFB_OK        = 0<<12,/* Bit 13..12   No errors, Link OK */
+       X_RFB_LF        = 1<<12,/* Bit 13..12   Link Failure */
+       X_RFB_OFF       = 2<<12,/* Bit 13..12   Offline */
+       X_RFB_AN_ERR    = 3<<12,/* Bit 13..12   Auto-Negotiation Error */
+};
+
 /* Broadcom-Specific */
 /*****  PHY_BCOM_1000T_CTRL    16 bit r/w      1000Base-T Control Reg *****/
 enum {
@@ -2158,8 +2181,8 @@ enum {
        XM_IS_LNK_AE    = 1<<14, /* Bit 14:     Link Asynchronous Event */
        XM_IS_TX_ABORT  = 1<<13, /* Bit 13:     Transmit Abort, late Col. etc */
        XM_IS_FRC_INT   = 1<<12, /* Bit 12:     Force INT bit set in GP */
-       XM_IS_INP_ASS   = 1<<11,        /* Bit 11:      Input Asserted, GP bit 0 set */
-       XM_IS_LIPA_RC   = 1<<10,        /* Bit 10:      Link Partner requests config */
+       XM_IS_INP_ASS   = 1<<11, /* Bit 11:     Input Asserted, GP bit 0 set */
+       XM_IS_LIPA_RC   = 1<<10, /* Bit 10:     Link Partner requests config */
        XM_IS_RX_PAGE   = 1<<9, /* Bit  9:      Page Received */
        XM_IS_TX_PAGE   = 1<<8, /* Bit  8:      Next Page Loaded for Transmit */
        XM_IS_AND       = 1<<7, /* Bit  7:      Auto-Negotiation Done */
@@ -2172,9 +2195,7 @@ enum {
        XM_IS_RX_COMP   = 1<<0, /* Bit  0:      Frame Rx Complete */
 };
 
-#define XM_DEF_MSK     (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \
-                          XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \
-                          XM_IS_RXF_OV | XM_IS_TXF_UR))
+#define XM_DEF_MSK     (~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR))
 
 
 /*     XM_HW_CFG       16 bit r/w      Hardware Config Register */
@@ -2396,6 +2417,7 @@ struct skge_hw {
        u8                   chip_rev;
        u8                   copper;
        u8                   ports;
+       u8                   phy_type;
 
        u32                  ram_size;
        u32                  ram_offset;
@@ -2422,6 +2444,7 @@ struct skge_port {
 
        struct net_device_stats net_stats;
 
+       struct work_struct   link_thread;
        u8                   rx_csum;
        u8                   blink_on;
        u8                   flow_control;
index 7aa7fbac8224a385f91c8fd696daeab35d1aba58..fedd1a37bc3e71fa631ea9ebb39b97d1e0cf6e15 100644 (file)
@@ -195,6 +195,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define        SMC_IRQ_FLAGS (( \
                   machine_is_omap_h2() \
                || machine_is_omap_h3() \
+               || machine_is_omap_h4() \
                || (machine_is_omap_innovator() && !cpu_is_omap1510()) \
        ) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING)
 
@@ -379,6 +380,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
 
 #define SMC_IRQ_FLAGS          (0)
 
+#elif  defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT       1
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+#define SMC_NOWAIT             1
+
+#define SMC_inb(a, r)          readb((a) + (r))
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_inl(a, r)          readl((a) + (r))
+#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_outl(v, a, r)      writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS          (0)
+
 #else
 
 #define SMC_CAN_USE_8BIT       1
index 3fd7a4fee6658e3504fe4da58a8fa167f19c2672..e6f90427160cf162d82682a409af375eb6e4903b 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
 #include <asm/machvec.h>
 #ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
index aaf45b907a786aaa9028e60fcf6d38668653ad6d..c25ba273b74596b9727d00d695b1083229efdf36 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.65"
-#define DRV_MODULE_RELDATE     "August 07, 2006"
+#define DRV_MODULE_VERSION     "3.66"
+#define DRV_MODULE_RELDATE     "September 23, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -173,6 +173,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)},
@@ -187,6 +188,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
@@ -197,6 +199,8 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -424,6 +428,16 @@ static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
                readl(mbox);
 }
 
+static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
+{
+       return (readl(tp->regs + off + GRCMBOX_BASE));
+}
+
+static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
+{
+       writel(val, tp->regs + off + GRCMBOX_BASE);
+}
+
 #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val)
 #define tw32_mailbox_f(reg, val)       tw32_mailbox_flush(tp, (reg), (val))
 #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val)
@@ -439,6 +453,10 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
 {
        unsigned long flags;
 
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+           (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
+               return;
+
        spin_lock_irqsave(&tp->indirect_lock, flags);
        if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
                pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
@@ -460,6 +478,12 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 {
        unsigned long flags;
 
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+           (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
+               *val = 0;
+               return;
+       }
+
        spin_lock_irqsave(&tp->indirect_lock, flags);
        if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
                pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
@@ -489,6 +513,9 @@ static inline void tg3_cond_int(struct tg3 *tp)
        if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
            (tp->hw_status->status & SD_STATUS_UPDATED))
                tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+       else
+               tw32(HOSTCC_MODE, tp->coalesce_mode |
+                    (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
 }
 
 static void tg3_enable_ints(struct tg3 *tp)
@@ -654,6 +681,10 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
        unsigned int loops;
        int ret;
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
+           (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+               return 0;
+
        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE,
                     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
@@ -1004,6 +1035,24 @@ out:
                                 phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
        }
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 phy_reg;
+
+               /* adjust output voltage */
+               tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
+
+               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
+                       u32 phy_reg2;
+
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
+                                    phy_reg | MII_TG3_EPHY_SHADOW_EN);
+                       /* Enable auto-MDIX */
+                       if (!tg3_readphy(tp, 0x10, &phy_reg2))
+                               tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
+               }
+       }
+
        tg3_phy_set_wirespeed(tp);
        return 0;
 }
@@ -1117,6 +1166,15 @@ static void tg3_nvram_unlock(struct tg3 *);
 
 static void tg3_power_down_phy(struct tg3 *tp)
 {
+       if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+               return;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
+               tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                            MII_TG3_EXT_CTRL_FORCE_LED_OFF);
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+       }
+
        /* The PHY should not be powered down on some chips because
         * of bugs.
         */
@@ -1199,7 +1257,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                tg3_setup_phy(tp, 0);
        }
 
-       if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 val;
+
+               val = tr32(GRC_VCPU_EXT_CTRL);
+               tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL);
+       } else if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
                int i;
                u32 val;
 
@@ -1223,7 +1286,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                        tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
                        udelay(40);
 
-                       mac_mode = MAC_MODE_PORT_MODE_MII;
+                       if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+                               mac_mode = MAC_MODE_PORT_MODE_GMII;
+                       else
+                               mac_mode = MAC_MODE_PORT_MODE_MII;
 
                        if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
                            !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
@@ -1301,15 +1367,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
        }
 
        if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
-           !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
-               /* Turn off the PHY */
-               if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
-                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
-                                    MII_TG3_EXT_CTRL_FORCE_LED_OFF);
-                       tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
-                       tg3_power_down_phy(tp);
-               }
-       }
+           !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+               tg3_power_down_phy(tp);
 
        tg3_frob_aux_power(tp);
 
@@ -1467,6 +1526,13 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8
                break;
 
        default:
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+                       *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
+                                SPEED_10;
+                       *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
+                                 DUPLEX_HALF;
+                       break;
+               }
                *speed = SPEED_INVALID;
                *duplex = DUPLEX_INVALID;
                break;
@@ -1749,7 +1815,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 
        if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT)
                tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
-       else
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
                tg3_writephy(tp, MII_TG3_IMASK, ~0);
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
@@ -2406,24 +2472,27 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
        expected_sg_dig_ctrl |= (1 << 12);
 
        if (sg_dig_ctrl != expected_sg_dig_ctrl) {
+               if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) &&
+                   tp->serdes_counter &&
+                   ((mac_status & (MAC_STATUS_PCS_SYNCED |
+                                   MAC_STATUS_RCVD_CFG)) ==
+                    MAC_STATUS_PCS_SYNCED)) {
+                       tp->serdes_counter--;
+                       current_link_up = 1;
+                       goto out;
+               }
+restart_autoneg:
                if (workaround)
                        tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
                tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
                udelay(5);
                tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
 
-               tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+               tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
+               tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
        } else if (mac_status & (MAC_STATUS_PCS_SYNCED |
                                 MAC_STATUS_SIGNAL_DET)) {
-               int i;
-
-               /* Giver time to negotiate (~200ms) */
-               for (i = 0; i < 40000; i++) {
-                       sg_dig_status = tr32(SG_DIG_STATUS);
-                       if (sg_dig_status & (0x3))
-                               break;
-                       udelay(5);
-               }
+               sg_dig_status = tr32(SG_DIG_STATUS);
                mac_status = tr32(MAC_STATUS);
 
                if ((sg_dig_status & (1 << 1)) &&
@@ -2439,10 +2508,11 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
                        current_link_up = 1;
-                       tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+                       tp->serdes_counter = 0;
+                       tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
                } else if (!(sg_dig_status & (1 << 1))) {
-                       if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
-                               tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+                       if (tp->serdes_counter)
+                               tp->serdes_counter--;
                        else {
                                if (workaround) {
                                        u32 val = serdes_cfg;
@@ -2466,9 +2536,17 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
                                    !(mac_status & MAC_STATUS_RCVD_CFG)) {
                                        tg3_setup_flow_control(tp, 0, 0);
                                        current_link_up = 1;
-                               }
+                                       tp->tg3_flags2 |=
+                                               TG3_FLG2_PARALLEL_DETECT;
+                                       tp->serdes_counter =
+                                               SERDES_PARALLEL_DET_TIMEOUT;
+                               } else
+                                       goto restart_autoneg;
                        }
                }
+       } else {
+               tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
+               tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
        }
 
 out:
@@ -2599,14 +2677,16 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
                                    MAC_STATUS_CFG_CHANGED));
                udelay(5);
                if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
-                                        MAC_STATUS_CFG_CHANGED)) == 0)
+                                        MAC_STATUS_CFG_CHANGED |
+                                        MAC_STATUS_LNKSTATE_CHANGED)) == 0)
                        break;
        }
 
        mac_status = tr32(MAC_STATUS);
        if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
                current_link_up = 0;
-               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+               if (tp->link_config.autoneg == AUTONEG_ENABLE &&
+                   tp->serdes_counter == 0) {
                        tw32_f(MAC_MODE, (tp->mac_mode |
                                          MAC_MODE_SEND_CONFIGS));
                        udelay(1);
@@ -2711,7 +2791,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                        tg3_writephy(tp, MII_BMCR, bmcr);
 
                        tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-                       tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+                       tp->serdes_counter = SERDES_AN_TIMEOUT_5714S;
                        tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
 
                        return err;
@@ -2816,9 +2896,9 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
 
 static void tg3_serdes_parallel_detect(struct tg3 *tp)
 {
-       if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) {
+       if (tp->serdes_counter) {
                /* Give autoneg time to complete. */
-               tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+               tp->serdes_counter--;
                return;
        }
        if (!netif_carrier_ok(tp->dev) &&
@@ -3535,8 +3615,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
 
        if ((sblk->status & SD_STATUS_UPDATED) ||
            !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
-               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                            0x00000001);
+               tg3_disable_ints(tp);
                return IRQ_RETVAL(1);
        }
        return IRQ_RETVAL(0);
@@ -4644,6 +4723,44 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
        }
 }
 
+static int tg3_poll_fw(struct tg3 *tp)
+{
+       int i;
+       u32 val;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               for (i = 0; i < 400; i++) {
+                       if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
+                               return 0;
+                       udelay(10);
+               }
+               return -ENODEV;
+       }
+
+       /* Wait for firmware initialization to complete. */
+       for (i = 0; i < 100000; i++) {
+               tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+               if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+                       break;
+               udelay(10);
+       }
+
+       /* Chip might not be fitted with firmware.  Some Sun onboard
+        * parts are configured like that.  So don't signal the timeout
+        * of the above loop as an error, but do report the lack of
+        * running firmware once.
+        */
+       if (i >= 100000 &&
+           !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
+               tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
+
+               printk(KERN_INFO PFX "%s: No firmware running.\n",
+                      tp->dev->name);
+       }
+
+       return 0;
+}
+
 static void tg3_stop_fw(struct tg3 *);
 
 /* tp->lock is held. */
@@ -4651,7 +4768,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 {
        u32 val;
        void (*write_op)(struct tg3 *, u32, u32);
-       int i;
+       int err;
 
        tg3_nvram_lock(tp);
 
@@ -4688,6 +4805,12 @@ static int tg3_chip_reset(struct tg3 *tp)
                }
        }
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               tw32(VCPU_STATUS, tr32(VCPU_STATUS) | VCPU_STATUS_DRV_RESET);
+               tw32(GRC_VCPU_EXT_CTRL,
+                    tr32(GRC_VCPU_EXT_CTRL) & ~GRC_VCPU_EXT_CTRL_HALT_CPU);
+       }
+
        if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
                val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
        tw32(GRC_MISC_CFG, val);
@@ -4811,26 +4934,9 @@ static int tg3_chip_reset(struct tg3 *tp)
                tw32_f(MAC_MODE, 0);
        udelay(40);
 
-       /* Wait for firmware initialization to complete. */
-       for (i = 0; i < 100000; i++) {
-               tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
-               if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-                       break;
-               udelay(10);
-       }
-
-       /* Chip might not be fitted with firmare.  Some Sun onboard
-        * parts are configured like that.  So don't signal the timeout
-        * of the above loop as an error, but do report the lack of
-        * running firmware once.
-        */
-       if (i >= 100000 &&
-           !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
-               tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
-
-               printk(KERN_INFO PFX "%s: No firmware running.\n",
-                      tp->dev->name);
-       }
+       err = tg3_poll_fw(tp);
+       if (err)
+               return err;
 
        if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
            tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
@@ -5036,6 +5142,12 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
        BUG_ON(offset == TX_CPU_BASE &&
            (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 val = tr32(GRC_VCPU_EXT_CTRL);
+
+               tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
+               return 0;
+       }
        if (offset == RX_CPU_BASE) {
                for (i = 0; i < 10000; i++) {
                        tw32(offset + CPU_STATE, 0xffffffff);
@@ -6040,6 +6152,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                val = 1;
        else if (val > tp->rx_std_max_post)
                val = tp->rx_std_max_post;
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5906_A1)
+                       tw32(ISO_PKT_TX, (tr32(ISO_PKT_TX) & ~0x3) | 0x2);
+
+               if (val > (TG3_RX_INTERNAL_RING_SZ_5906 / 2))
+                       val = TG3_RX_INTERNAL_RING_SZ_5906 / 2;
+       }
 
        tw32(RCVBDI_STD_THRESH, val);
 
@@ -6460,7 +6579,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        if (err)
                return err;
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
                u32 tmp;
 
                /* Clear CRC stats. */
@@ -6660,12 +6780,14 @@ static void tg3_timer(unsigned long __opaque)
                                need_setup = 1;
                        }
                        if (need_setup) {
-                               tw32_f(MAC_MODE,
-                                    (tp->mac_mode &
-                                     ~MAC_MODE_PORT_MODE_MASK));
-                               udelay(40);
-                               tw32_f(MAC_MODE, tp->mac_mode);
-                               udelay(40);
+                               if (!tp->serdes_counter) {
+                                       tw32_f(MAC_MODE,
+                                            (tp->mac_mode &
+                                             ~MAC_MODE_PORT_MODE_MASK));
+                                       udelay(40);
+                                       tw32_f(MAC_MODE, tp->mac_mode);
+                                       udelay(40);
+                               }
                                tg3_setup_phy(tp, 0);
                        }
                } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
@@ -6674,13 +6796,29 @@ static void tg3_timer(unsigned long __opaque)
                tp->timer_counter = tp->timer_multiplier;
        }
 
-       /* Heartbeat is only sent once every 2 seconds.  */
+       /* Heartbeat is only sent once every 2 seconds.
+        *
+        * The heartbeat is to tell the ASF firmware that the host
+        * driver is still alive.  In the event that the OS crashes,
+        * ASF needs to reset the hardware to free up the FIFO space
+        * that may be filled with rx packets destined for the host.
+        * If the FIFO is full, ASF will no longer function properly.
+        *
+        * Unintended resets have been reported on real time kernels
+        * where the timer doesn't run on time.  Netpoll will also have
+        * same problem.
+        *
+        * The new FWCMD_NICDRV_ALIVE3 command tells the ASF firmware
+        * to check the ring condition when the heartbeat is expiring
+        * before doing the reset.  This will prevent most unintended
+        * resets.
+        */
        if (!--tp->asf_counter) {
                if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
                        u32 val;
 
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
-                                     FWCMD_NICDRV_ALIVE2);
+                                     FWCMD_NICDRV_ALIVE3);
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
                        /* 5 seconds timeout */
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
@@ -6721,8 +6859,7 @@ static int tg3_request_irq(struct tg3 *tp)
 static int tg3_test_interrupt(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
-       int err, i;
-       u32 int_mbox = 0;
+       int err, i, intr_ok = 0;
 
        if (!netif_running(dev))
                return -ENODEV;
@@ -6743,10 +6880,18 @@ static int tg3_test_interrupt(struct tg3 *tp)
               HOSTCC_MODE_NOW);
 
        for (i = 0; i < 5; i++) {
+               u32 int_mbox, misc_host_ctrl;
+
                int_mbox = tr32_mailbox(MAILBOX_INTERRUPT_0 +
                                        TG3_64BIT_REG_LOW);
-               if (int_mbox != 0)
+               misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
+
+               if ((int_mbox != 0) ||
+                   (misc_host_ctrl & MISC_HOST_CTRL_MASK_PCI_INT)) {
+                       intr_ok = 1;
                        break;
+               }
+
                msleep(10);
        }
 
@@ -6759,7 +6904,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
        if (err)
                return err;
 
-       if (int_mbox != 0)
+       if (intr_ok)
                return 0;
 
        return -EIO;
@@ -6936,9 +7081,10 @@ static int tg3_open(struct net_device *dev)
 
                if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
                        if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
-                               u32 val = tr32(0x7c04);
+                               u32 val = tr32(PCIE_TRANSACTION_CFG);
 
-                               tw32(0x7c04, val | (1 << 29));
+                               tw32(PCIE_TRANSACTION_CFG,
+                                    val | PCIE_TRANS_CFG_1SHOT_MSI);
                        }
                }
        }
@@ -7857,7 +8003,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & ~WAKE_MAGIC)
                return -EINVAL;
        if ((wol->wolopts & WAKE_MAGIC) &&
-           tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
+           tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
            !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
                return -EINVAL;
 
@@ -7893,7 +8039,8 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
                        return -EINVAL;
                return 0;
        }
-       if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) {
+       if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
+           (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
                if (value)
                        dev->features |= NETIF_F_TSO6;
                else
@@ -8147,6 +8294,8 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
 
 #define NVRAM_TEST_SIZE 0x100
 #define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_HW_SIZE 0x20
+#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
@@ -8158,12 +8307,14 @@ static int tg3_test_nvram(struct tg3 *tp)
 
        if (magic == TG3_EEPROM_MAGIC)
                size = NVRAM_TEST_SIZE;
-       else if ((magic & 0xff000000) == 0xa5000000) {
+       else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
                if ((magic & 0xe00000) == 0x200000)
                        size = NVRAM_SELFBOOT_FORMAT1_SIZE;
                else
                        return 0;
-       } else
+       } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
+               size = NVRAM_SELFBOOT_HW_SIZE;
+       else
                return -EIO;
 
        buf = kmalloc(size, GFP_KERNEL);
@@ -8182,7 +8333,8 @@ static int tg3_test_nvram(struct tg3 *tp)
                goto out;
 
        /* Selfboot format */
-       if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) {
+       if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) ==
+           TG3_EEPROM_MAGIC_FW) {
                u8 *buf8 = (u8 *) buf, csum8 = 0;
 
                for (i = 0; i < size; i++)
@@ -8197,6 +8349,51 @@ static int tg3_test_nvram(struct tg3 *tp)
                goto out;
        }
 
+       if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) ==
+           TG3_EEPROM_MAGIC_HW) {
+               u8 data[NVRAM_SELFBOOT_DATA_SIZE];
+               u8 parity[NVRAM_SELFBOOT_DATA_SIZE];
+               u8 *buf8 = (u8 *) buf;
+               int j, k;
+
+               /* Separate the parity bits and the data bytes.  */
+               for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) {
+                       if ((i == 0) || (i == 8)) {
+                               int l;
+                               u8 msk;
+
+                               for (l = 0, msk = 0x80; l < 7; l++, msk >>= 1)
+                                       parity[k++] = buf8[i] & msk;
+                               i++;
+                       }
+                       else if (i == 16) {
+                               int l;
+                               u8 msk;
+
+                               for (l = 0, msk = 0x20; l < 6; l++, msk >>= 1)
+                                       parity[k++] = buf8[i] & msk;
+                               i++;
+
+                               for (l = 0, msk = 0x80; l < 8; l++, msk >>= 1)
+                                       parity[k++] = buf8[i] & msk;
+                               i++;
+                       }
+                       data[j++] = buf8[i];
+               }
+
+               err = -EIO;
+               for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) {
+                       u8 hw8 = hweight8(data[i]);
+
+                       if ((hw8 & 0x1) && parity[i])
+                               goto out;
+                       else if (!(hw8 & 0x1) && !parity[i])
+                               goto out;
+               }
+               err = 0;
+               goto out;
+       }
+
        /* Bootstrap checksum at offset 0x10 */
        csum = calc_crc((unsigned char *) buf, 0x10);
        if(csum != cpu_to_le32(buf[0x10/4]))
@@ -8243,7 +8440,7 @@ static int tg3_test_link(struct tg3 *tp)
 /* Only test the commonly used registers */
 static int tg3_test_registers(struct tg3 *tp)
 {
-       int i, is_5705;
+       int i, is_5705, is_5750;
        u32 offset, read_mask, write_mask, val, save_val, read_val;
        static struct {
                u16 offset;
@@ -8251,6 +8448,7 @@ static int tg3_test_registers(struct tg3 *tp)
 #define TG3_FL_5705    0x1
 #define TG3_FL_NOT_5705        0x2
 #define TG3_FL_NOT_5788        0x4
+#define TG3_FL_NOT_5750        0x8
                u32 read_mask;
                u32 write_mask;
        } reg_tbl[] = {
@@ -8361,9 +8559,9 @@ static int tg3_test_registers(struct tg3 *tp)
                        0xffffffff, 0x00000000 },
 
                /* Buffer Manager Control Registers. */
-               { BUFMGR_MB_POOL_ADDR, 0x0000,
+               { BUFMGR_MB_POOL_ADDR, TG3_FL_NOT_5750,
                        0x00000000, 0x007fff80 },
-               { BUFMGR_MB_POOL_SIZE, 0x0000,
+               { BUFMGR_MB_POOL_SIZE, TG3_FL_NOT_5750,
                        0x00000000, 0x007fffff },
                { BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
                        0x00000000, 0x0000003f },
@@ -8389,10 +8587,12 @@ static int tg3_test_registers(struct tg3 *tp)
                { 0xffff, 0x0000, 0x00000000, 0x00000000 },
        };
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+       is_5705 = is_5750 = 0;
+       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
                is_5705 = 1;
-       else
-               is_5705 = 0;
+               if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
+                       is_5750 = 1;
+       }
 
        for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
                if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
@@ -8405,6 +8605,9 @@ static int tg3_test_registers(struct tg3 *tp)
                    (reg_tbl[i].flags & TG3_FL_NOT_5788))
                        continue;
 
+               if (is_5750 && (reg_tbl[i].flags & TG3_FL_NOT_5750))
+                       continue;
+
                offset = (u32) reg_tbl[i].offset;
                read_mask = reg_tbl[i].read_mask;
                write_mask = reg_tbl[i].write_mask;
@@ -8496,6 +8699,13 @@ static int tg3_test_memory(struct tg3 *tp)
                { 0x00008000, 0x02000},
                { 0x00010000, 0x0c000},
                { 0xffffffff, 0x00000}
+       }, mem_tbl_5906[] = {
+               { 0x00000200, 0x00008},
+               { 0x00004000, 0x00400},
+               { 0x00006000, 0x00400},
+               { 0x00008000, 0x01000},
+               { 0x00010000, 0x01000},
+               { 0xffffffff, 0x00000}
        };
        struct mem_entry *mem_tbl;
        int err = 0;
@@ -8505,6 +8715,8 @@ static int tg3_test_memory(struct tg3 *tp)
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
                        mem_tbl = mem_tbl_5755;
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+                       mem_tbl = mem_tbl_5906;
                else
                        mem_tbl = mem_tbl_5705;
        } else
@@ -8541,13 +8753,41 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                        return 0;
 
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                          MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
-                          MAC_MODE_PORT_MODE_GMII;
+                          MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY;
+               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+                       mac_mode |= MAC_MODE_PORT_MODE_MII;
+               else
+                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
                tw32(MAC_MODE, mac_mode);
        } else if (loopback_mode == TG3_PHY_LOOPBACK) {
-               tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
-                                          BMCR_SPEED1000);
+               u32 val;
+
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+                       u32 phytest;
+
+                       if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phytest)) {
+                               u32 phy;
+
+                               tg3_writephy(tp, MII_TG3_EPHY_TEST,
+                                            phytest | MII_TG3_EPHY_SHADOW_EN);
+                               if (!tg3_readphy(tp, 0x1b, &phy))
+                                       tg3_writephy(tp, 0x1b, phy & ~0x20);
+                               if (!tg3_readphy(tp, 0x10, &phy))
+                                       tg3_writephy(tp, 0x10, phy & ~0x4000);
+                               tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
+                       }
+               }
+               val = BMCR_LOOPBACK | BMCR_FULLDPLX;
+               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+                       val |= BMCR_SPEED100;
+               else
+                       val |= BMCR_SPEED1000;
+
+               tg3_writephy(tp, MII_BMCR, val);
                udelay(40);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+                       tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
+
                /* reset to prevent losing 1st rx packet intermittently */
                if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
                        tw32_f(MAC_RX_MODE, RX_MODE_RESET);
@@ -8555,7 +8795,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                        tw32_f(MAC_RX_MODE, tp->rx_mode);
                }
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                          MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
+                          MAC_MODE_LINK_POLARITY;
+               if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
+                       mac_mode |= MAC_MODE_PORT_MODE_MII;
+               else
+                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
                if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
                        mac_mode &= ~MAC_MODE_LINK_POLARITY;
                        tg3_writephy(tp, MII_TG3_EXT_CTRL,
@@ -8604,7 +8848,8 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
        udelay(10);
 
-       for (i = 0; i < 10; i++) {
+       /* 250 usec to allow enough time on some 10/100 Mbps devices.  */
+       for (i = 0; i < 25; i++) {
                tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
                       HOSTCC_MODE_NOW);
 
@@ -8956,7 +9201,9 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
        if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
                return;
 
-       if ((magic != TG3_EEPROM_MAGIC) && ((magic & 0xff000000) != 0xa5000000))
+       if ((magic != TG3_EEPROM_MAGIC) &&
+           ((magic & TG3_EEPROM_MAGIC_FW_MSK) != TG3_EEPROM_MAGIC_FW) &&
+           ((magic & TG3_EEPROM_MAGIC_HW_MSK) != TG3_EEPROM_MAGIC_HW))
                return;
 
        /*
@@ -9194,6 +9441,13 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
        }
 }
 
+static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+{
+       tp->nvram_jedecnum = JEDEC_ATMEL;
+       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
@@ -9230,6 +9484,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                        tg3_get_5755_nvram_info(tp);
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
                        tg3_get_5787_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+                       tg3_get_5906_nvram_info(tp);
                else
                        tg3_get_nvram_info(tp);
 
@@ -9703,6 +9959,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        /* Assume an onboard device by default.  */
        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM))
+                       tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
+               return;
+       }
+
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
                u32 nic_cfg, led_cfg;
@@ -10034,7 +10296,10 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
        }
 
 out_not_found:
-       strcpy(tp->board_part_number, "none");
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               strcpy(tp->board_part_number, "BCM95906");
+       else
+               strcpy(tp->board_part_number, "none");
 }
 
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
@@ -10236,6 +10501,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
@@ -10245,7 +10511,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                        tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
                        tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
                } else {
@@ -10262,7 +10529,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787)
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
                tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
 
        if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
@@ -10392,6 +10660,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                pci_cmd &= ~PCI_COMMAND_MEMORY;
                pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
        }
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               tp->read32_mbox = tg3_read32_mbox_5906;
+               tp->write32_mbox = tg3_write32_mbox_5906;
+               tp->write32_tx_mbox = tg3_write32_mbox_5906;
+               tp->write32_rx_mbox = tg3_write32_mbox_5906;
+       }
 
        if (tp->write32 == tg3_write_indirect_reg32 ||
            ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
@@ -10463,6 +10737,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
             (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
             (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) ||
            (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
                tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
 
@@ -10476,7 +10751,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
                        tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
-               else
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
                        tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
        }
 
@@ -10566,7 +10841,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
              tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
            (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
             (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)))
+             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
        err = tg3_phy_probe(tp);
@@ -10617,7 +10893,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         * straddle the 4GB address boundary in some cases.
         */
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                tp->dev->hard_start_xmit = tg3_start_xmit;
        else
                tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
@@ -10698,6 +10975,8 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
                else
                        tg3_nvram_unlock(tp);
        }
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               mac_offset = 0x10;
 
        /* First try to get it from MAC address mailbox. */
        tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
@@ -11181,6 +11460,12 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
                        DEFAULT_MB_MACRX_LOW_WATER_5705;
                tp->bufmgr_config.mbuf_high_water =
                        DEFAULT_MB_HIGH_WATER_5705;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+                       tp->bufmgr_config.mbuf_mac_rx_low_water =
+                               DEFAULT_MB_MACRX_LOW_WATER_5906;
+                       tp->bufmgr_config.mbuf_high_water =
+                               DEFAULT_MB_HIGH_WATER_5906;
+               }
 
                tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
                        DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780;
@@ -11224,6 +11509,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case PHY_ID_BCM5780:    return "5780";
        case PHY_ID_BCM5755:    return "5755";
        case PHY_ID_BCM5787:    return "5787";
+       case PHY_ID_BCM5756:    return "5722/5756";
+       case PHY_ID_BCM5906:    return "5906";
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
@@ -11526,7 +11813,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         */
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
                dev->features |= NETIF_F_TSO;
-               if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)
+               if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
+                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
                        dev->features |= NETIF_F_TSO6;
        }
 
index 3ecf356cfb082e17cc17875aec9eaf0c7e5b3cbb..92f53000bce69f2895dad2183ac37013de7e58cb 100644 (file)
@@ -24,6 +24,8 @@
 
 #define RX_COPY_THRESHOLD              256
 
+#define TG3_RX_INTERNAL_RING_SZ_5906   32
+
 #define RX_STD_MAX_SIZE                        1536
 #define RX_STD_MAX_SIZE_5705           512
 #define RX_JUMBO_MAX_SIZE              0xdeadbeef /* XXX */
 #define  CHIPREV_ID_5752_A0_HW          0x5000
 #define  CHIPREV_ID_5752_A0             0x6000
 #define  CHIPREV_ID_5752_A1             0x6001
+#define  CHIPREV_ID_5906_A1             0xc001
 #define  GET_ASIC_REV(CHIP_REV_ID)     ((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700                         0x07
 #define   ASIC_REV_5701                         0x00
 #define   ASIC_REV_5714                         0x09
 #define   ASIC_REV_5755                         0x0a
 #define   ASIC_REV_5787                         0x0b
+#define   ASIC_REV_5906                         0x0c
 #define  GET_CHIP_REV(CHIP_REV_ID)     ((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX               0x70
 #define   CHIPREV_5700_BX               0x71
 #define  SNDDATAI_SCTRL_FORCE_ZERO      0x00000010
 #define SNDDATAI_STATSENAB             0x00000c0c
 #define SNDDATAI_STATSINCMASK          0x00000c10
-/* 0xc14 --> 0xc80 unused */
+#define ISO_PKT_TX                     0x00000c20
+/* 0xc24 --> 0xc80 unused */
 #define SNDDATAI_COS_CNT_0             0x00000c80
 #define SNDDATAI_COS_CNT_1             0x00000c84
 #define SNDDATAI_COS_CNT_2             0x00000c88
 #define BUFMGR_MB_MACRX_LOW_WATER      0x00004414
 #define  DEFAULT_MB_MACRX_LOW_WATER      0x00000020
 #define  DEFAULT_MB_MACRX_LOW_WATER_5705  0x00000010
+#define  DEFAULT_MB_MACRX_LOW_WATER_5906  0x00000004
 #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098
 #define  DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b
 #define BUFMGR_MB_HIGH_WATER           0x00004418
 #define  DEFAULT_MB_HIGH_WATER          0x00000060
 #define  DEFAULT_MB_HIGH_WATER_5705     0x00000060
+#define  DEFAULT_MB_HIGH_WATER_5906     0x00000010
 #define  DEFAULT_MB_HIGH_WATER_JUMBO    0x0000017c
 #define  DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096
 #define BUFMGR_RX_MB_ALLOC_REQ         0x0000441c
 #define TX_CPU_STATE                   0x00005404
 #define TX_CPU_PGMCTR                  0x0000541c
 
+#define VCPU_STATUS                    0x00005100
+#define  VCPU_STATUS_INIT_DONE          0x04000000
+#define  VCPU_STATUS_DRV_RESET          0x08000000
+
 /* Mailboxes */
+#define GRCMBOX_BASE                   0x00005600
 #define GRCMBOX_INTERRUPT_0            0x00005800 /* 64-bit */
 #define GRCMBOX_INTERRUPT_1            0x00005808 /* 64-bit */
 #define GRCMBOX_INTERRUPT_2            0x00005810 /* 64-bit */
 #define GRC_EEPROM_CTRL                        0x00006840
 #define GRC_MDI_CTRL                   0x00006844
 #define GRC_SEEPROM_DELAY              0x00006848
-/* 0x684c --> 0x6c00 unused */
+/* 0x684c --> 0x6890 unused */
+#define GRC_VCPU_EXT_CTRL              0x00006890
+#define GRC_VCPU_EXT_CTRL_HALT_CPU      0x00400000
+#define GRC_VCPU_EXT_CTRL_DISABLE_WOL   0x20000000
 #define GRC_FASTBOOT_PC                        0x00006894      /* 5752, 5755, 5787 */
 
 /* 0x6c00 --> 0x7000 unused */
 #define NVRAM_WRITE1                   0x00007028
 /* 0x702c --> 0x7400 unused */
 
-/* 0x7400 --> 0x8000 unused */
+/* 0x7400 --> 0x7c00 unused */
+#define PCIE_TRANSACTION_CFG           0x00007c04
+#define PCIE_TRANS_CFG_1SHOT_MSI        0x20000000
+#define PCIE_TRANS_CFG_LOM              0x00000020
+
 
 #define TG3_EEPROM_MAGIC               0x669955aa
+#define TG3_EEPROM_MAGIC_FW            0xa5000000
+#define TG3_EEPROM_MAGIC_FW_MSK                0xff000000
+#define TG3_EEPROM_MAGIC_HW            0xabcd
+#define TG3_EEPROM_MAGIC_HW_MSK                0xffff
 
 /* 32K Window into NIC internal memory */
 #define NIC_SRAM_WIN_BASE              0x00008000
 #define  FWCMD_NICDRV_FIX_DMAR          0x00000005
 #define  FWCMD_NICDRV_FIX_DMAW          0x00000006
 #define  FWCMD_NICDRV_ALIVE2            0x0000000d
+#define  FWCMD_NICDRV_ALIVE3            0x0000000e
 #define NIC_SRAM_FW_CMD_LEN_MBOX       0x00000b7c
 #define NIC_SRAM_FW_CMD_DATA_MBOX      0x00000b80
 #define NIC_SRAM_FW_ASF_STATUS_MBOX    0x00000c00
 #define MII_TG3_DSP_RW_PORT            0x15 /* DSP coefficient read/write port */
 
 #define MII_TG3_DSP_ADDRESS            0x17 /* DSP address register */
+#define MII_TG3_EPHY_PTEST             0x17 /* 5906 PHY register */
 
 #define MII_TG3_AUX_CTRL               0x18 /* auxilliary control register */
 
 #define MII_TG3_AUX_STAT_100FULL       0x0500
 #define MII_TG3_AUX_STAT_1000HALF      0x0600
 #define MII_TG3_AUX_STAT_1000FULL      0x0700
+#define MII_TG3_AUX_STAT_100           0x0008
+#define MII_TG3_AUX_STAT_FULL          0x0001
 
 #define MII_TG3_ISTAT                  0x1a /* IRQ status register */
 #define MII_TG3_IMASK                  0x1b /* IRQ mask register */
 #define MII_TG3_INT_DUPLEXCHG          0x0008
 #define MII_TG3_INT_ANEG_PAGE_RX       0x0400
 
+#define MII_TG3_EPHY_TEST              0x1f /* 5906 PHY register */
+#define MII_TG3_EPHY_SHADOW_EN         0x80
+
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
@@ -2203,7 +2233,6 @@ struct tg3 {
 #define TG3_FLG2_PCI_EXPRESS           0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE     0x00000400
 #define TG3_FLG2_HW_AUTONEG            0x00000800
-#define TG3_FLG2_PHY_JUST_INITTED      0x00001000
 #define TG3_FLG2_PHY_SERDES            0x00002000
 #define TG3_FLG2_CAPACITIVE_COUPLING   0x00004000
 #define TG3_FLG2_FLASH                 0x00008000
@@ -2236,6 +2265,12 @@ struct tg3 {
        u16                             asf_counter;
        u16                             asf_multiplier;
 
+       /* 1 second counter for transient serdes link events */
+       u32                             serdes_counter;
+#define SERDES_AN_TIMEOUT_5704S                2
+#define SERDES_PARALLEL_DET_TIMEOUT    1
+#define SERDES_AN_TIMEOUT_5714S                1
+
        struct tg3_link_config          link_config;
        struct tg3_bufmgr_config        bufmgr_config;
 
@@ -2276,6 +2311,8 @@ struct tg3 {
 #define PHY_ID_BCM5780                 0x60008350
 #define PHY_ID_BCM5755                 0xbc050cc0
 #define PHY_ID_BCM5787                 0xbc050ce0
+#define PHY_ID_BCM5756                 0xbc050ed0
+#define PHY_ID_BCM5906                 0xdc00ac40
 #define PHY_ID_BCM8002                 0x60010140
 #define PHY_ID_INVALID                 0xffffffff
 #define PHY_ID_REV_MASK                        0x0000000f
@@ -2302,7 +2339,8 @@ struct tg3 {
         (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
         (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
         (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
-        (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM8002)
+        (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \
+        (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM8002)
 
        struct tg3_hw_stats             *hw_stats;
        dma_addr_t                      stats_mapping;
index 0d66700c6cedb3d9934a815f15c7ac2e2e327931..bfc8c3eae9a1de7123c2dba1f05932e405215c16 100644 (file)
@@ -1876,7 +1876,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
                datap[size+1]=io_word & 0xff;
        }
 
-
        size = sprintf(buffer, "\n%6s: Adapter Address   : Node Address      : Functional Addr\n", dev->name);
 
        size += sprintf(buffer + size,
@@ -1932,64 +1931,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
 #endif
 #endif
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int streamer_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-        int i;
-       struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
-       u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
-
-       switch(cmd) {
-       case IOCTL_SISR_MASK:
-               writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
-               break;
-       case IOCTL_SPIN_LOCK_TEST:
-               printk(KERN_INFO "spin_lock() called.\n");
-               spin_lock(&streamer_priv->streamer_lock);
-               spin_unlock(&streamer_priv->streamer_lock);
-               printk(KERN_INFO "spin_unlock() finished.\n");
-               break;
-       case IOCTL_PRINT_BDAS:
-               printk(KERN_INFO "bdas: RXBDA: %x RXLBDA: %x TX2FDA: %x TX2LFDA: %x\n",
-                      readw(streamer_mmio + RXBDA),
-                      readw(streamer_mmio + RXLBDA),
-                      readw(streamer_mmio + TX2FDA),
-                      readw(streamer_mmio + TX2LFDA));
-               break;
-       case IOCTL_PRINT_REGISTERS:
-               printk(KERN_INFO "registers:\n");
-               printk(KERN_INFO "SISR: %04x MISR: %04x LISR: %04x BCTL: %04x BMCTL: %04x\nmask  %04x mask  %04x\n", 
-                      readw(streamer_mmio + SISR),
-                      readw(streamer_mmio + MISR_RUM),
-                      readw(streamer_mmio + LISR),
-                      readw(streamer_mmio + BCTL),
-                      readw(streamer_mmio + BMCTL_SUM),
-                      readw(streamer_mmio + SISR_MASK),
-                      readw(streamer_mmio + MISR_MASK));
-               break;
-       case IOCTL_PRINT_RX_BUFS:
-               printk(KERN_INFO "Print rx bufs:\n");
-               for(i=0; i<STREAMER_RX_RING_SIZE; i++)
-                       printk(KERN_INFO "rx_ring %d status: 0x%x\n", i, 
-                              streamer_priv->streamer_rx_ring[i].status);
-               break;
-       case IOCTL_PRINT_TX_BUFS:
-               printk(KERN_INFO "Print tx bufs:\n");
-               for(i=0; i<STREAMER_TX_RING_SIZE; i++)
-                       printk(KERN_INFO "tx_ring %d status: 0x%x\n", i, 
-                              streamer_priv->streamer_tx_ring[i].status);
-               break;
-       case IOCTL_RX_CMD:
-               streamer_rx(dev);
-               printk(KERN_INFO "Sent rx command.\n");
-               break;
-       default:
-               printk(KERN_INFO "Bad ioctl!\n");
-       }
-       return 0;
-}
-#endif
-
 static struct pci_driver streamer_pci_driver = {
   .name     = "lanstreamer",
   .id_table = streamer_pci_tbl,
index 5557d8e1e22de6cec1b3ea0c46c65915c490bdc2..e7bb3494afc74609e53413a97c517d4bd9d37f7d 100644 (file)
 
 #include <linux/version.h>
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <asm/ioctl.h>
-#define IOCTL_PRINT_RX_BUFS   SIOCDEVPRIVATE
-#define IOCTL_PRINT_TX_BUFS   SIOCDEVPRIVATE+1
-#define IOCTL_RX_CMD          SIOCDEVPRIVATE+2
-#define IOCTL_TX_CMD          SIOCDEVPRIVATE+3
-#define IOCTL_PRINT_REGISTERS SIOCDEVPRIVATE+4
-#define IOCTL_PRINT_BDAS      SIOCDEVPRIVATE+5
-#define IOCTL_SPIN_LOCK_TEST  SIOCDEVPRIVATE+6
-#define IOCTL_SISR_MASK       SIOCDEVPRIVATE+7
-#endif
-
 /* MAX_INTR - the maximum number of times we can loop
  * inside the interrupt function before returning
  * control to the OS (maximum value is 256)
index e661d0a9cc64d5be35fc42ab81c402dd9970cea6..fb5fa7d688886afa5b4f9c2fd0f330533db29934 100644 (file)
@@ -2114,6 +2114,7 @@ static struct eisa_device_id de4x5_eisa_ids[] = {
         { "DEC4250", 0 },      /* 0 is the board name index... */
         { "" }
 };
+MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
 
 static struct eisa_driver de4x5_eisa_driver = {
         .id_table = de4x5_eisa_ids,
index de8da6dee1b0598d6d22e8bd106356d39184d0a7..bc0face01d25aa2c53f0ce95db2f0f2cf83fbca6 100644 (file)
@@ -288,11 +288,10 @@ static inline size_t iov_total(const struct iovec *iv, unsigned long count)
        return len;
 }
 
-/* Writev */
-static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
-                             unsigned long count, loff_t *pos)
+static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
+                             unsigned long count, loff_t pos)
 {
-       struct tun_struct *tun = file->private_data;
+       struct tun_struct *tun = iocb->ki_filp->private_data;
 
        if (!tun)
                return -EBADFD;
@@ -302,14 +301,6 @@ static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
        return tun_get_user(tun, (struct iovec *) iv, iov_total(iv, count));
 }
 
-/* Write */
-static ssize_t tun_chr_write(struct file * file, const char __user * buf,
-                            size_t count, loff_t *pos)
-{
-       struct iovec iv = { (void __user *) buf, count };
-       return tun_chr_writev(file, &iv, 1, pos);
-}
-
 /* Put packet to the user space buffer */
 static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
                                       struct sk_buff *skb,
@@ -343,10 +334,10 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
        return total;
 }
 
-/* Readv */
-static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
-                           unsigned long count, loff_t *pos)
+static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
+                           unsigned long count, loff_t pos)
 {
+       struct file *file = iocb->ki_filp;
        struct tun_struct *tun = file->private_data;
        DECLARE_WAITQUEUE(wait, current);
        struct sk_buff *skb;
@@ -426,14 +417,6 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
        return ret;
 }
 
-/* Read */
-static ssize_t tun_chr_read(struct file * file, char __user * buf,
-                           size_t count, loff_t *pos)
-{
-       struct iovec iv = { buf, count };
-       return tun_chr_readv(file, &iv, 1, pos);
-}
-
 static void tun_setup(struct net_device *dev)
 {
        struct tun_struct *tun = netdev_priv(dev);
@@ -764,10 +747,10 @@ static int tun_chr_close(struct inode *inode, struct file *file)
 static struct file_operations tun_fops = {
        .owner  = THIS_MODULE,
        .llseek = no_llseek,
-       .read   = tun_chr_read,
-       .readv  = tun_chr_readv,
-       .write  = tun_chr_write,
-       .writev = tun_chr_writev,
+       .read  = do_sync_read,
+       .aio_read  = tun_chr_aio_read,
+       .write = do_sync_write,
+       .aio_write = tun_chr_aio_write,
        .poll   = tun_chr_poll,
        .ioctl  = tun_chr_ioctl,
        .open   = tun_chr_open,
index 8f6f6fd8b87d3c26323b1b5a670a553afbe80586..d5c32e9caa978fe1c6e8f1e4a6359bd66245b1a8 100644 (file)
@@ -333,11 +333,7 @@ enum state_values {
 #define TYPHOON_RESET_TIMEOUT_NOSLEEP  ((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT           ((1000000 / 2) / TYPHOON_UDELAY)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
-#define typhoon_synchronize_irq(x) synchronize_irq()
-#else
 #define typhoon_synchronize_irq(x) synchronize_irq(x)
-#endif
 
 #if defined(NETIF_F_TSO)
 #define skb_tso_size(x)                (skb_shinfo(x)->gso_size)
index 54b8e492ef97dca1b16c99441f674a76767ea963..58b7efbb075015462469454e0a174805038edeb7 100644 (file)
@@ -154,7 +154,7 @@ config HDLC
          If unsure, say N.
 
 config HDLC_RAW
-       bool "Raw HDLC support"
+       tristate "Raw HDLC support"
        depends on HDLC
        help
          Generic HDLC driver supporting raw HDLC over WAN connections.
@@ -162,7 +162,7 @@ config HDLC_RAW
          If unsure, say N.
 
 config HDLC_RAW_ETH
-       bool "Raw HDLC Ethernet device support"
+       tristate "Raw HDLC Ethernet device support"
        depends on HDLC
        help
          Generic HDLC driver supporting raw HDLC Ethernet device emulation
@@ -173,7 +173,7 @@ config HDLC_RAW_ETH
          If unsure, say N.
 
 config HDLC_CISCO
-       bool "Cisco HDLC support"
+       tristate "Cisco HDLC support"
        depends on HDLC
        help
          Generic HDLC driver supporting Cisco HDLC over WAN connections.
@@ -181,7 +181,7 @@ config HDLC_CISCO
          If unsure, say N.
 
 config HDLC_FR
-       bool "Frame Relay support"
+       tristate "Frame Relay support"
        depends on HDLC
        help
          Generic HDLC driver supporting Frame Relay over WAN connections.
@@ -189,7 +189,7 @@ config HDLC_FR
          If unsure, say N.
 
 config HDLC_PPP
-       bool "Synchronous Point-to-Point Protocol (PPP) support"
+       tristate "Synchronous Point-to-Point Protocol (PPP) support"
        depends on HDLC
        help
          Generic HDLC driver supporting PPP over WAN connections.
@@ -197,7 +197,7 @@ config HDLC_PPP
          If unsure, say N.
 
 config HDLC_X25
-       bool "X.25 protocol support"
+       tristate "X.25 protocol support"
        depends on HDLC && (LAPB=m && HDLC=m || LAPB=y)
        help
          Generic HDLC driver supporting X.25 over WAN connections.
index 316ca6869d5e83542085eb937b891f9554141d27..83ec2c87ba3f34fea00937247f9e4e64bce65c67 100644 (file)
@@ -9,14 +9,13 @@ cyclomx-y                       := cycx_main.o
 cyclomx-$(CONFIG_CYCLOMX_X25)  += cycx_x25.o
 cyclomx-objs                   := $(cyclomx-y)  
 
-hdlc-y                         := hdlc_generic.o
-hdlc-$(CONFIG_HDLC_RAW)                += hdlc_raw.o
-hdlc-$(CONFIG_HDLC_RAW_ETH)    += hdlc_raw_eth.o
-hdlc-$(CONFIG_HDLC_CISCO)      += hdlc_cisco.o
-hdlc-$(CONFIG_HDLC_FR)         += hdlc_fr.o
-hdlc-$(CONFIG_HDLC_PPP)                += hdlc_ppp.o
-hdlc-$(CONFIG_HDLC_X25)                += hdlc_x25.o
-hdlc-objs                      := $(hdlc-y)
+obj-$(CONFIG_HDLC)             += hdlc.o
+obj-$(CONFIG_HDLC_RAW)         += hdlc_raw.o
+obj-$(CONFIG_HDLC_RAW_ETH)     += hdlc_raw_eth.o
+obj-$(CONFIG_HDLC_CISCO)       += hdlc_cisco.o
+obj-$(CONFIG_HDLC_FR)          += hdlc_fr.o
+obj-$(CONFIG_HDLC_PPP)         += hdlc_ppp.o   syncppp.o
+obj-$(CONFIG_HDLC_X25)         += hdlc_x25.o
 
 pc300-y                                := pc300_drv.o
 pc300-$(CONFIG_PC300_MLPPP)    += pc300_tty.o
@@ -38,10 +37,6 @@ obj-$(CONFIG_CYCLADES_SYNC)  += cycx_drv.o cyclomx.o
 obj-$(CONFIG_LAPBETHER)                += lapbether.o
 obj-$(CONFIG_SBNI)             += sbni.o
 obj-$(CONFIG_PC300)            += pc300.o
-obj-$(CONFIG_HDLC)             += hdlc.o
-ifeq ($(CONFIG_HDLC_PPP),y)
-  obj-$(CONFIG_HDLC)           += syncppp.o
-endif
 obj-$(CONFIG_N2)               += n2.o
 obj-$(CONFIG_C101)             += c101.o
 obj-$(CONFIG_WANXL)            += wanxl.o
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
new file mode 100644 (file)
index 0000000..db354e0
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Generic HDLC support routines for Linux
+ *
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * Currently supported:
+ *     * raw IP-in-HDLC
+ *     * Cisco HDLC
+ *     * Frame Relay with ANSI or CCITT LMI (both user and network side)
+ *     * PPP
+ *     * X.25
+ *
+ * Use sethdlc utility to set line parameters, protocol and PVCs
+ *
+ * How does it work:
+ * - proto->open(), close(), start(), stop() calls are serialized.
+ *   The order is: open, [ start, stop ... ] close ...
+ * - proto->start() and stop() are called with spin_lock_irq held.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/pkt_sched.h>
+#include <linux/inetdevice.h>
+#include <linux/lapb.h>
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+#include <linux/hdlc.h>
+
+
+static const char* version = "HDLC support module revision 1.20";
+
+#undef DEBUG_LINK
+
+static struct hdlc_proto *first_proto = NULL;
+
+
+static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
+               return -EINVAL;
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+
+
+static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
+{
+       return hdlc_stats(dev);
+}
+
+
+
+static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
+                   struct packet_type *p, struct net_device *orig_dev)
+{
+       struct hdlc_device_desc *desc = dev_to_desc(dev);
+       if (desc->netif_rx)
+               return desc->netif_rx(skb);
+
+       desc->stats.rx_dropped++; /* Shouldn't happen */
+       dev_kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+
+
+static inline void hdlc_proto_start(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+       if (hdlc->proto->start)
+               return hdlc->proto->start(dev);
+}
+
+
+
+static inline void hdlc_proto_stop(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+       if (hdlc->proto->stop)
+               return hdlc->proto->stop(dev);
+}
+
+
+
+static int hdlc_device_event(struct notifier_block *this, unsigned long event,
+                            void *ptr)
+{
+       struct net_device *dev = ptr;
+       hdlc_device *hdlc;
+       unsigned long flags;
+       int on;
+       if (dev->get_stats != hdlc_get_stats)
+               return NOTIFY_DONE; /* not an HDLC device */
+       if (event != NETDEV_CHANGE)
+               return NOTIFY_DONE; /* Only interrested in carrier changes */
+
+       on = netif_carrier_ok(dev);
+
+#ifdef DEBUG_LINK
+       printk(KERN_DEBUG "%s: hdlc_device_event NETDEV_CHANGE, carrier %i\n",
+              dev->name, on);
+#endif
+
+       hdlc = dev_to_hdlc(dev);
+       spin_lock_irqsave(&hdlc->state_lock, flags);
+
+       if (hdlc->carrier == on)
+               goto carrier_exit; /* no change in DCD line level */
+
+       hdlc->carrier = on;
+
+       if (!hdlc->open)
+               goto carrier_exit;
+
+       if (hdlc->carrier) {
+               printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+               hdlc_proto_start(dev);
+       } else {
+               printk(KERN_INFO "%s: Carrier lost\n", dev->name);
+               hdlc_proto_stop(dev);
+       }
+
+carrier_exit:
+       spin_unlock_irqrestore(&hdlc->state_lock, flags);
+       return NOTIFY_DONE;
+}
+
+
+
+/* Must be called by hardware driver when HDLC device is being opened */
+int hdlc_open(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+#ifdef DEBUG_LINK
+       printk(KERN_DEBUG "%s: hdlc_open() carrier %i open %i\n", dev->name,
+              hdlc->carrier, hdlc->open);
+#endif
+
+       if (hdlc->proto == NULL)
+               return -ENOSYS; /* no protocol attached */
+
+       if (hdlc->proto->open) {
+               int result = hdlc->proto->open(dev);
+               if (result)
+                       return result;
+       }
+
+       spin_lock_irq(&hdlc->state_lock);
+
+       if (hdlc->carrier) {
+               printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+               hdlc_proto_start(dev);
+       } else
+               printk(KERN_INFO "%s: No carrier\n", dev->name);
+
+       hdlc->open = 1;
+
+       spin_unlock_irq(&hdlc->state_lock);
+       return 0;
+}
+
+
+
+/* Must be called by hardware driver when HDLC device is being closed */
+void hdlc_close(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+#ifdef DEBUG_LINK
+       printk(KERN_DEBUG "%s: hdlc_close() carrier %i open %i\n", dev->name,
+              hdlc->carrier, hdlc->open);
+#endif
+
+       spin_lock_irq(&hdlc->state_lock);
+
+       hdlc->open = 0;
+       if (hdlc->carrier)
+               hdlc_proto_stop(dev);
+
+       spin_unlock_irq(&hdlc->state_lock);
+
+       if (hdlc->proto->close)
+               hdlc->proto->close(dev);
+}
+
+
+
+int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       struct hdlc_proto *proto = first_proto;
+       int result;
+
+       if (cmd != SIOCWANDEV)
+               return -EINVAL;
+
+       if (dev_to_hdlc(dev)->proto) {
+               result = dev_to_hdlc(dev)->proto->ioctl(dev, ifr);
+               if (result != -EINVAL)
+                       return result;
+       }
+
+       /* Not handled by currently attached protocol (if any) */
+
+       while (proto) {
+               if ((result = proto->ioctl(dev, ifr)) != -EINVAL)
+                       return result;
+               proto = proto->next;
+       }
+       return -EINVAL;
+}
+
+void hdlc_setup(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+
+       dev->get_stats = hdlc_get_stats;
+       dev->change_mtu = hdlc_change_mtu;
+       dev->mtu = HDLC_MAX_MTU;
+
+       dev->type = ARPHRD_RAWHDLC;
+       dev->hard_header_len = 16;
+
+       dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+
+       hdlc->carrier = 1;
+       hdlc->open = 0;
+       spin_lock_init(&hdlc->state_lock);
+}
+
+struct net_device *alloc_hdlcdev(void *priv)
+{
+       struct net_device *dev;
+       dev = alloc_netdev(sizeof(struct hdlc_device_desc) +
+                          sizeof(hdlc_device), "hdlc%d", hdlc_setup);
+       if (dev)
+               dev_to_hdlc(dev)->priv = priv;
+       return dev;
+}
+
+void unregister_hdlc_device(struct net_device *dev)
+{
+       rtnl_lock();
+       unregister_netdevice(dev);
+       detach_hdlc_protocol(dev);
+       rtnl_unlock();
+}
+
+
+
+int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
+                        int (*rx)(struct sk_buff *skb), size_t size)
+{
+       detach_hdlc_protocol(dev);
+
+       if (!try_module_get(proto->module))
+               return -ENOSYS;
+
+       if (size)
+               if ((dev_to_hdlc(dev)->state = kmalloc(size,
+                                                      GFP_KERNEL)) == NULL) {
+                       printk(KERN_WARNING "Memory squeeze on"
+                              " hdlc_proto_attach()\n");
+                       module_put(proto->module);
+                       return -ENOBUFS;
+               }
+       dev_to_hdlc(dev)->proto = proto;
+       dev_to_desc(dev)->netif_rx = rx;
+       return 0;
+}
+
+
+void detach_hdlc_protocol(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+
+       if (hdlc->proto) {
+               if (hdlc->proto->detach)
+                       hdlc->proto->detach(dev);
+               module_put(hdlc->proto->module);
+               hdlc->proto = NULL;
+       }
+       kfree(hdlc->state);
+       hdlc->state = NULL;
+}
+
+
+void register_hdlc_protocol(struct hdlc_proto *proto)
+{
+       proto->next = first_proto;
+       first_proto = proto;
+}
+
+
+void unregister_hdlc_protocol(struct hdlc_proto *proto)
+{
+       struct hdlc_proto **p = &first_proto;
+       while (*p) {
+               if (*p == proto) {
+                       *p = proto->next;
+                       return;
+               }
+               p = &((*p)->next);
+       }
+}
+
+
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("HDLC support module");
+MODULE_LICENSE("GPL v2");
+
+EXPORT_SYMBOL(hdlc_open);
+EXPORT_SYMBOL(hdlc_close);
+EXPORT_SYMBOL(hdlc_ioctl);
+EXPORT_SYMBOL(hdlc_setup);
+EXPORT_SYMBOL(alloc_hdlcdev);
+EXPORT_SYMBOL(unregister_hdlc_device);
+EXPORT_SYMBOL(register_hdlc_protocol);
+EXPORT_SYMBOL(unregister_hdlc_protocol);
+EXPORT_SYMBOL(attach_hdlc_protocol);
+EXPORT_SYMBOL(detach_hdlc_protocol);
+
+static struct packet_type hdlc_packet_type = {
+       .type = __constant_htons(ETH_P_HDLC),
+       .func = hdlc_rcv,
+};
+
+
+static struct notifier_block hdlc_notifier = {
+        .notifier_call = hdlc_device_event,
+};
+
+
+static int __init hdlc_module_init(void)
+{
+       int result;
+
+       printk(KERN_INFO "%s\n", version);
+       if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
+                return result;
+        dev_add_pack(&hdlc_packet_type);
+       return 0;
+}
+
+
+
+static void __exit hdlc_module_exit(void)
+{
+       dev_remove_pack(&hdlc_packet_type);
+       unregister_netdevice_notifier(&hdlc_notifier);
+}
+
+
+module_init(hdlc_module_init);
+module_exit(hdlc_module_exit);
index f289daba0c7b308408d84ea209054859973e5773..b0bc5ddcf1b11df483912a33160ce074c75ffa5c 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Cisco HDLC support
  *
- * Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2000 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
 #define CISCO_KEEPALIVE_REQ    2       /* Cisco keepalive request */
 
 
+struct hdlc_header {
+       u8 address;
+       u8 control;
+       u16 protocol;
+}__attribute__ ((packed));
+
+
+struct cisco_packet {
+       u32 type;               /* code */
+       u32 par1;
+       u32 par2;
+       u16 rel;                /* reliability */
+       u32 time;
+}__attribute__ ((packed));
+#define        CISCO_PACKET_LEN        18
+#define        CISCO_BIG_PACKET_LEN    20
+
+
+struct cisco_state {
+       cisco_proto settings;
+
+       struct timer_list timer;
+       unsigned long last_poll;
+       int up;
+       int request_sent;
+       u32 txseq; /* TX sequence number */
+       u32 rxseq; /* RX sequence number */
+};
+
+
+static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
+static inline struct cisco_state * state(hdlc_device *hdlc)
+{
+       return(struct cisco_state *)(hdlc->state);
+}
+
+
 static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev,
                             u16 type, void *daddr, void *saddr,
                             unsigned int len)
 {
-       hdlc_header *data;
+       struct hdlc_header *data;
 #ifdef DEBUG_HARD_HEADER
        printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name);
 #endif
 
-       skb_push(skb, sizeof(hdlc_header));
-       data = (hdlc_header*)skb->data;
+       skb_push(skb, sizeof(struct hdlc_header));
+       data = (struct hdlc_header*)skb->data;
        if (type == CISCO_KEEPALIVE)
                data->address = CISCO_MULTICAST;
        else
@@ -52,7 +91,7 @@ static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev,
        data->control = 0;
        data->protocol = htons(type);
 
-       return sizeof(hdlc_header);
+       return sizeof(struct hdlc_header);
 }
 
 
@@ -61,9 +100,10 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
                                 u32 par1, u32 par2)
 {
        struct sk_buff *skb;
-       cisco_packet *data;
+       struct cisco_packet *data;
 
-       skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet));
+       skb = dev_alloc_skb(sizeof(struct hdlc_header) +
+                           sizeof(struct cisco_packet));
        if (!skb) {
                printk(KERN_WARNING
                       "%s: Memory squeeze on cisco_keepalive_send()\n",
@@ -72,7 +112,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
        }
        skb_reserve(skb, 4);
        cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
-       data = (cisco_packet*)(skb->data + 4);
+       data = (struct cisco_packet*)(skb->data + 4);
 
        data->type = htonl(type);
        data->par1 = htonl(par1);
@@ -81,7 +121,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
        /* we will need do_div here if 1000 % HZ != 0 */
        data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ));
 
-       skb_put(skb, sizeof(cisco_packet));
+       skb_put(skb, sizeof(struct cisco_packet));
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = dev;
        skb->nh.raw = skb->data;
@@ -93,9 +133,9 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
 
 static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-       hdlc_header *data = (hdlc_header*)skb->data;
+       struct hdlc_header *data = (struct hdlc_header*)skb->data;
 
-       if (skb->len < sizeof(hdlc_header))
+       if (skb->len < sizeof(struct hdlc_header))
                return __constant_htons(ETH_P_HDLC);
 
        if (data->address != CISCO_MULTICAST &&
@@ -106,7 +146,7 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
        case __constant_htons(ETH_P_IP):
        case __constant_htons(ETH_P_IPX):
        case __constant_htons(ETH_P_IPV6):
-               skb_pull(skb, sizeof(hdlc_header));
+               skb_pull(skb, sizeof(struct hdlc_header));
                return data->protocol;
        default:
                return __constant_htons(ETH_P_HDLC);
@@ -118,12 +158,12 @@ static int cisco_rx(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       hdlc_header *data = (hdlc_header*)skb->data;
-       cisco_packet *cisco_data;
+       struct hdlc_header *data = (struct hdlc_header*)skb->data;
+       struct cisco_packet *cisco_data;
        struct in_device *in_dev;
-       u32 addr, mask;
+       __be32 addr, mask;
 
-       if (skb->len < sizeof(hdlc_header))
+       if (skb->len < sizeof(struct hdlc_header))
                goto rx_error;
 
        if (data->address != CISCO_MULTICAST &&
@@ -137,15 +177,17 @@ static int cisco_rx(struct sk_buff *skb)
                return NET_RX_SUCCESS;
 
        case CISCO_KEEPALIVE:
-               if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN &&
-                   skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
-                       printk(KERN_INFO "%s: Invalid length of Cisco "
-                              "control packet (%d bytes)\n",
-                              dev->name, skb->len);
+               if ((skb->len != sizeof(struct hdlc_header) +
+                    CISCO_PACKET_LEN) &&
+                   (skb->len != sizeof(struct hdlc_header) +
+                    CISCO_BIG_PACKET_LEN)) {
+                       printk(KERN_INFO "%s: Invalid length of Cisco control"
+                              " packet (%d bytes)\n", dev->name, skb->len);
                        goto rx_error;
                }
 
-               cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header));
+               cisco_data = (struct cisco_packet*)(skb->data + sizeof
+                                                   (struct hdlc_header));
 
                switch(ntohl (cisco_data->type)) {
                case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
@@ -178,11 +220,11 @@ static int cisco_rx(struct sk_buff *skb)
                        goto rx_error;
 
                case CISCO_KEEPALIVE_REQ:
-                       hdlc->state.cisco.rxseq = ntohl(cisco_data->par1);
-                       if (hdlc->state.cisco.request_sent &&
-                           ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) {
-                               hdlc->state.cisco.last_poll = jiffies;
-                               if (!hdlc->state.cisco.up) {
+                       state(hdlc)->rxseq = ntohl(cisco_data->par1);
+                       if (state(hdlc)->request_sent &&
+                           ntohl(cisco_data->par2) == state(hdlc)->txseq) {
+                               state(hdlc)->last_poll = jiffies;
+                               if (!state(hdlc)->up) {
                                        u32 sec, min, hrs, days;
                                        sec = ntohl(cisco_data->time) / 1000;
                                        min = sec / 60; sec -= min * 60;
@@ -193,7 +235,7 @@ static int cisco_rx(struct sk_buff *skb)
                                               dev->name, days, hrs,
                                               min, sec);
                                        netif_dormant_off(dev);
-                                       hdlc->state.cisco.up = 1;
+                                       state(hdlc)->up = 1;
                                }
                        }
 
@@ -208,7 +250,7 @@ static int cisco_rx(struct sk_buff *skb)
        return NET_RX_DROP;
 
  rx_error:
-       hdlc->stats.rx_errors++; /* Mark error */
+       dev_to_desc(dev)->stats.rx_errors++; /* Mark error */
        dev_kfree_skb_any(skb);
        return NET_RX_DROP;
 }
@@ -220,23 +262,22 @@ static void cisco_timer(unsigned long arg)
        struct net_device *dev = (struct net_device *)arg;
        hdlc_device *hdlc = dev_to_hdlc(dev);
 
-       if (hdlc->state.cisco.up &&
-           time_after(jiffies, hdlc->state.cisco.last_poll +
-                      hdlc->state.cisco.settings.timeout * HZ)) {
-               hdlc->state.cisco.up = 0;
+       if (state(hdlc)->up &&
+           time_after(jiffies, state(hdlc)->last_poll +
+                      state(hdlc)->settings.timeout * HZ)) {
+               state(hdlc)->up = 0;
                printk(KERN_INFO "%s: Link down\n", dev->name);
                netif_dormant_on(dev);
        }
 
-       cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
-                            ++hdlc->state.cisco.txseq,
-                            hdlc->state.cisco.rxseq);
-       hdlc->state.cisco.request_sent = 1;
-       hdlc->state.cisco.timer.expires = jiffies +
-               hdlc->state.cisco.settings.interval * HZ;
-       hdlc->state.cisco.timer.function = cisco_timer;
-       hdlc->state.cisco.timer.data = arg;
-       add_timer(&hdlc->state.cisco.timer);
+       cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++state(hdlc)->txseq,
+                            state(hdlc)->rxseq);
+       state(hdlc)->request_sent = 1;
+       state(hdlc)->timer.expires = jiffies +
+               state(hdlc)->settings.interval * HZ;
+       state(hdlc)->timer.function = cisco_timer;
+       state(hdlc)->timer.data = arg;
+       add_timer(&state(hdlc)->timer);
 }
 
 
@@ -244,15 +285,15 @@ static void cisco_timer(unsigned long arg)
 static void cisco_start(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       hdlc->state.cisco.up = 0;
-       hdlc->state.cisco.request_sent = 0;
-       hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
-
-       init_timer(&hdlc->state.cisco.timer);
-       hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/
-       hdlc->state.cisco.timer.function = cisco_timer;
-       hdlc->state.cisco.timer.data = (unsigned long)dev;
-       add_timer(&hdlc->state.cisco.timer);
+       state(hdlc)->up = 0;
+       state(hdlc)->request_sent = 0;
+       state(hdlc)->txseq = state(hdlc)->rxseq = 0;
+
+       init_timer(&state(hdlc)->timer);
+       state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/
+       state(hdlc)->timer.function = cisco_timer;
+       state(hdlc)->timer.data = (unsigned long)dev;
+       add_timer(&state(hdlc)->timer);
 }
 
 
@@ -260,15 +301,24 @@ static void cisco_start(struct net_device *dev)
 static void cisco_stop(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       del_timer_sync(&hdlc->state.cisco.timer);
+       del_timer_sync(&state(hdlc)->timer);
        netif_dormant_on(dev);
-       hdlc->state.cisco.up = 0;
-       hdlc->state.cisco.request_sent = 0;
+       state(hdlc)->up = 0;
+       state(hdlc)->request_sent = 0;
 }
 
 
 
-int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .start          = cisco_start,
+       .stop           = cisco_stop,
+       .type_trans     = cisco_type_trans,
+       .ioctl          = cisco_ioctl,
+       .module         = THIS_MODULE,
+};
+static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
        const size_t size = sizeof(cisco_proto);
@@ -278,12 +328,14 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_CISCO;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size))
+               if (copy_to_user(cisco_s, &state(hdlc)->settings, size))
                        return -EFAULT;
                return 0;
 
@@ -302,19 +354,15 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
                        return -EINVAL;
 
                result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
-
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memcpy(&hdlc->state.cisco.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
+               result = attach_hdlc_protocol(dev, &proto, cisco_rx,
+                                             sizeof(struct cisco_state));
+               if (result)
+                       return result;
 
-               hdlc->proto.start = cisco_start;
-               hdlc->proto.stop = cisco_stop;
-               hdlc->proto.netif_rx = cisco_rx;
-               hdlc->proto.type_trans = cisco_type_trans;
-               hdlc->proto.id = IF_PROTO_CISCO;
+               memcpy(&state(hdlc)->settings, &new_settings, size);
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = cisco_hard_header;
                dev->hard_header_cache = NULL;
@@ -327,3 +375,25 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Cisco HDLC protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index 7bb737bbdeb96cf09b1628e31b51c50c58f25372..b45ab680d2d624b52c4b44f4d1d51cb4c268de5d 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Frame Relay support
  *
- * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -52,6 +52,8 @@
 #undef DEBUG_PKT
 #undef DEBUG_ECN
 #undef DEBUG_LINK
+#undef DEBUG_PROTO
+#undef DEBUG_PVC
 
 #define FR_UI                  0x03
 #define FR_PAD                 0x00
@@ -115,13 +117,53 @@ typedef struct {
 }__attribute__ ((packed)) fr_hdr;
 
 
+typedef struct pvc_device_struct {
+       struct net_device *frad;
+       struct net_device *main;
+       struct net_device *ether;       /* bridged Ethernet interface   */
+       struct pvc_device_struct *next; /* Sorted in ascending DLCI order */
+       int dlci;
+       int open_count;
+
+       struct {
+               unsigned int new: 1;
+               unsigned int active: 1;
+               unsigned int exist: 1;
+               unsigned int deleted: 1;
+               unsigned int fecn: 1;
+               unsigned int becn: 1;
+               unsigned int bandwidth; /* Cisco LMI reporting only */
+       }state;
+}pvc_device;
+
+
+struct frad_state {
+       fr_proto settings;
+       pvc_device *first_pvc;
+       int dce_pvc_count;
+
+       struct timer_list timer;
+       unsigned long last_poll;
+       int reliable;
+       int dce_changed;
+       int request;
+       int fullrep_sent;
+       u32 last_errors; /* last errors bit list */
+       u8 n391cnt;
+       u8 txseq; /* TX sequence number */
+       u8 rxseq; /* RX sequence number */
+};
+
+
+static int fr_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
 static inline u16 q922_to_dlci(u8 *hdr)
 {
        return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4);
 }
 
 
-
 static inline void dlci_to_q922(u8 *hdr, u16 dlci)
 {
        hdr[0] = (dlci >> 2) & 0xFC;
@@ -129,10 +171,21 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci)
 }
 
 
+static inline struct frad_state * state(hdlc_device *hdlc)
+{
+       return(struct frad_state *)(hdlc->state);
+}
+
+
+static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+{
+       return dev->priv;
+}
+
 
 static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
 {
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
+       pvc_device *pvc = state(hdlc)->first_pvc;
 
        while (pvc) {
                if (pvc->dlci == dlci)
@@ -146,10 +199,10 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
 }
 
 
-static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
+static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc;
+       pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
 
        while (*pvc_p) {
                if ((*pvc_p)->dlci == dlci)
@@ -160,12 +213,15 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
        }
 
        pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC);
+#ifdef DEBUG_PVC
+       printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev);
+#endif
        if (!pvc)
                return NULL;
 
        memset(pvc, 0, sizeof(pvc_device));
        pvc->dlci = dlci;
-       pvc->master = dev;
+       pvc->frad = dev;
        pvc->next = *pvc_p;     /* Put it in the chain */
        *pvc_p = pvc;
        return pvc;
@@ -174,7 +230,7 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 
 static inline int pvc_is_used(pvc_device *pvc)
 {
-       return pvc->main != NULL || pvc->ether != NULL;
+       return pvc->main || pvc->ether;
 }
 
 
@@ -200,11 +256,14 @@ static inline void pvc_carrier(int on, pvc_device *pvc)
 
 static inline void delete_unused_pvcs(hdlc_device *hdlc)
 {
-       pvc_device **pvc_p = &hdlc->state.fr.first_pvc;
+       pvc_device **pvc_p = &state(hdlc)->first_pvc;
 
        while (*pvc_p) {
                if (!pvc_is_used(*pvc_p)) {
                        pvc_device *pvc = *pvc_p;
+#ifdef DEBUG_PVC
+                       printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc);
+#endif
                        *pvc_p = pvc->next;
                        kfree(pvc);
                        continue;
@@ -295,16 +354,16 @@ static int pvc_open(struct net_device *dev)
 {
        pvc_device *pvc = dev_to_pvc(dev);
 
-       if ((pvc->master->flags & IFF_UP) == 0)
-               return -EIO;  /* Master must be UP in order to activate PVC */
+       if ((pvc->frad->flags & IFF_UP) == 0)
+               return -EIO;  /* Frad must be UP in order to activate PVC */
 
        if (pvc->open_count++ == 0) {
-               hdlc_device *hdlc = dev_to_hdlc(pvc->master);
-               if (hdlc->state.fr.settings.lmi == LMI_NONE)
-                       pvc->state.active = netif_carrier_ok(pvc->master);
+               hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
+               if (state(hdlc)->settings.lmi == LMI_NONE)
+                       pvc->state.active = netif_carrier_ok(pvc->frad);
 
                pvc_carrier(pvc->state.active, pvc);
-               hdlc->state.fr.dce_changed = 1;
+               state(hdlc)->dce_changed = 1;
        }
        return 0;
 }
@@ -316,12 +375,12 @@ static int pvc_close(struct net_device *dev)
        pvc_device *pvc = dev_to_pvc(dev);
 
        if (--pvc->open_count == 0) {
-               hdlc_device *hdlc = dev_to_hdlc(pvc->master);
-               if (hdlc->state.fr.settings.lmi == LMI_NONE)
+               hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
+               if (state(hdlc)->settings.lmi == LMI_NONE)
                        pvc->state.active = 0;
 
-               if (hdlc->state.fr.settings.dce) {
-                       hdlc->state.fr.dce_changed = 1;
+               if (state(hdlc)->settings.dce) {
+                       state(hdlc)->dce_changed = 1;
                        pvc->state.active = 0;
                }
        }
@@ -348,7 +407,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                }
 
                info.dlci = pvc->dlci;
-               memcpy(info.master, pvc->master->name, IFNAMSIZ);
+               memcpy(info.master, pvc->frad->name, IFNAMSIZ);
                if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
                                 &info, sizeof(info)))
                        return -EFAULT;
@@ -361,7 +420,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
 {
-       return netdev_priv(dev);
+       return &dev_to_desc(dev)->stats;
 }
 
 
@@ -393,7 +452,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
                        stats->tx_packets++;
                        if (pvc->state.fecn) /* TX Congestion counter */
                                stats->tx_compressed++;
-                       skb->dev = pvc->master;
+                       skb->dev = pvc->frad;
                        dev_queue_xmit(skb);
                        return 0;
                }
@@ -419,7 +478,7 @@ static int pvc_change_mtu(struct net_device *dev, int new_mtu)
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
        printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
-              pvc->master->name,
+              pvc->frad->name,
               pvc->dlci,
               pvc->main ? pvc->main->name : "",
               pvc->main && pvc->ether ? " " : "",
@@ -438,21 +497,20 @@ static inline u8 fr_lmi_nextseq(u8 x)
 }
 
 
-
 static void fr_lmi_send(struct net_device *dev, int fullrep)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        struct sk_buff *skb;
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
-       int lmi = hdlc->state.fr.settings.lmi;
-       int dce = hdlc->state.fr.settings.dce;
+       pvc_device *pvc = state(hdlc)->first_pvc;
+       int lmi = state(hdlc)->settings.lmi;
+       int dce = state(hdlc)->settings.dce;
        int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
        int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
        u8 *data;
        int i = 0;
 
        if (dce && fullrep) {
-               len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
+               len += state(hdlc)->dce_pvc_count * (2 + stat_len);
                if (len > HDLC_MAX_MRU) {
                        printk(KERN_WARNING "%s: Too many PVCs while sending "
                               "LMI full report\n", dev->name);
@@ -486,8 +544,9 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
        data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
        data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
        data[i++] = LMI_INTEG_LEN;
-       data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
-       data[i++] = hdlc->state.fr.rxseq;
+       data[i++] = state(hdlc)->txseq =
+               fr_lmi_nextseq(state(hdlc)->txseq);
+       data[i++] = state(hdlc)->rxseq;
 
        if (dce && fullrep) {
                while (pvc) {
@@ -496,7 +555,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
                        data[i++] = stat_len;
 
                        /* LMI start/restart */
-                       if (hdlc->state.fr.reliable && !pvc->state.exist) {
+                       if (state(hdlc)->reliable && !pvc->state.exist) {
                                pvc->state.exist = pvc->state.new = 1;
                                fr_log_dlci_active(pvc);
                        }
@@ -541,15 +600,15 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
 static void fr_set_link_state(int reliable, struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
+       pvc_device *pvc = state(hdlc)->first_pvc;
 
-       hdlc->state.fr.reliable = reliable;
+       state(hdlc)->reliable = reliable;
        if (reliable) {
                netif_dormant_off(dev);
-               hdlc->state.fr.n391cnt = 0; /* Request full status */
-               hdlc->state.fr.dce_changed = 1;
+               state(hdlc)->n391cnt = 0; /* Request full status */
+               state(hdlc)->dce_changed = 1;
 
-               if (hdlc->state.fr.settings.lmi == LMI_NONE) {
+               if (state(hdlc)->settings.lmi == LMI_NONE) {
                        while (pvc) {   /* Activate all PVCs */
                                pvc_carrier(1, pvc);
                                pvc->state.exist = pvc->state.active = 1;
@@ -563,7 +622,7 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
                        pvc_carrier(0, pvc);
                        pvc->state.exist = pvc->state.active = 0;
                        pvc->state.new = 0;
-                       if (!hdlc->state.fr.settings.dce)
+                       if (!state(hdlc)->settings.dce)
                                pvc->state.bandwidth = 0;
                        pvc = pvc->next;
                }
@@ -571,7 +630,6 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
 }
 
 
-
 static void fr_timer(unsigned long arg)
 {
        struct net_device *dev = (struct net_device *)arg;
@@ -579,62 +637,61 @@ static void fr_timer(unsigned long arg)
        int i, cnt = 0, reliable;
        u32 list;
 
-       if (hdlc->state.fr.settings.dce) {
-               reliable = hdlc->state.fr.request &&
-                       time_before(jiffies, hdlc->state.fr.last_poll +
-                                   hdlc->state.fr.settings.t392 * HZ);
-               hdlc->state.fr.request = 0;
+       if (state(hdlc)->settings.dce) {
+               reliable = state(hdlc)->request &&
+                       time_before(jiffies, state(hdlc)->last_poll +
+                                   state(hdlc)->settings.t392 * HZ);
+               state(hdlc)->request = 0;
        } else {
-               hdlc->state.fr.last_errors <<= 1; /* Shift the list */
-               if (hdlc->state.fr.request) {
-                       if (hdlc->state.fr.reliable)
+               state(hdlc)->last_errors <<= 1; /* Shift the list */
+               if (state(hdlc)->request) {
+                       if (state(hdlc)->reliable)
                                printk(KERN_INFO "%s: No LMI status reply "
                                       "received\n", dev->name);
-                       hdlc->state.fr.last_errors |= 1;
+                       state(hdlc)->last_errors |= 1;
                }
 
-               list = hdlc->state.fr.last_errors;
-               for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1)
+               list = state(hdlc)->last_errors;
+               for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1)
                        cnt += (list & 1);      /* errors count */
 
-               reliable = (cnt < hdlc->state.fr.settings.n392);
+               reliable = (cnt < state(hdlc)->settings.n392);
        }
 
-       if (hdlc->state.fr.reliable != reliable) {
+       if (state(hdlc)->reliable != reliable) {
                printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
                       reliable ? "" : "un");
                fr_set_link_state(reliable, dev);
        }
 
-       if (hdlc->state.fr.settings.dce)
-               hdlc->state.fr.timer.expires = jiffies +
-                       hdlc->state.fr.settings.t392 * HZ;
+       if (state(hdlc)->settings.dce)
+               state(hdlc)->timer.expires = jiffies +
+                       state(hdlc)->settings.t392 * HZ;
        else {
-               if (hdlc->state.fr.n391cnt)
-                       hdlc->state.fr.n391cnt--;
+               if (state(hdlc)->n391cnt)
+                       state(hdlc)->n391cnt--;
 
-               fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0);
+               fr_lmi_send(dev, state(hdlc)->n391cnt == 0);
 
-               hdlc->state.fr.last_poll = jiffies;
-               hdlc->state.fr.request = 1;
-               hdlc->state.fr.timer.expires = jiffies +
-                       hdlc->state.fr.settings.t391 * HZ;
+               state(hdlc)->last_poll = jiffies;
+               state(hdlc)->request = 1;
+               state(hdlc)->timer.expires = jiffies +
+                       state(hdlc)->settings.t391 * HZ;
        }
 
-       hdlc->state.fr.timer.function = fr_timer;
-       hdlc->state.fr.timer.data = arg;
-       add_timer(&hdlc->state.fr.timer);
+       state(hdlc)->timer.function = fr_timer;
+       state(hdlc)->timer.data = arg;
+       add_timer(&state(hdlc)->timer);
 }
 
 
-
 static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        pvc_device *pvc;
        u8 rxseq, txseq;
-       int lmi = hdlc->state.fr.settings.lmi;
-       int dce = hdlc->state.fr.settings.dce;
+       int lmi = state(hdlc)->settings.lmi;
+       int dce = state(hdlc)->settings.dce;
        int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
 
        if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
@@ -645,8 +702,8 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 
        if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
                             NLPID_CCITT_ANSI_LMI)) {
-               printk(KERN_INFO "%s: Received non-LMI frame with LMI"
-                      " DLCI\n", dev->name);
+               printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
+                      dev->name);
                return 1;
        }
 
@@ -706,53 +763,53 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
        }
        i++;
 
-       hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
+       state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */
        rxseq = skb->data[i++]; /* Should confirm our sequence */
 
-       txseq = hdlc->state.fr.txseq;
+       txseq = state(hdlc)->txseq;
 
        if (dce)
-               hdlc->state.fr.last_poll = jiffies;
+               state(hdlc)->last_poll = jiffies;
 
        error = 0;
-       if (!hdlc->state.fr.reliable)
+       if (!state(hdlc)->reliable)
                error = 1;
 
-       if (rxseq == 0 || rxseq != txseq) {
-               hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */
+       if (rxseq == 0 || rxseq != txseq) { /* Ask for full report next time */
+               state(hdlc)->n391cnt = 0;
                error = 1;
        }
 
        if (dce) {
-               if (hdlc->state.fr.fullrep_sent && !error) {
+               if (state(hdlc)->fullrep_sent && !error) {
 /* Stop sending full report - the last one has been confirmed by DTE */
-                       hdlc->state.fr.fullrep_sent = 0;
-                       pvc = hdlc->state.fr.first_pvc;
+                       state(hdlc)->fullrep_sent = 0;
+                       pvc = state(hdlc)->first_pvc;
                        while (pvc) {
                                if (pvc->state.new) {
                                        pvc->state.new = 0;
 
 /* Tell DTE that new PVC is now active */
-                                       hdlc->state.fr.dce_changed = 1;
+                                       state(hdlc)->dce_changed = 1;
                                }
                                pvc = pvc->next;
                        }
                }
 
-               if (hdlc->state.fr.dce_changed) {
+               if (state(hdlc)->dce_changed) {
                        reptype = LMI_FULLREP;
-                       hdlc->state.fr.fullrep_sent = 1;
-                       hdlc->state.fr.dce_changed = 0;
+                       state(hdlc)->fullrep_sent = 1;
+                       state(hdlc)->dce_changed = 0;
                }
 
-               hdlc->state.fr.request = 1; /* got request */
+               state(hdlc)->request = 1; /* got request */
                fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
                return 0;
        }
 
        /* DTE */
 
-       hdlc->state.fr.request = 0; /* got response, no request pending */
+       state(hdlc)->request = 0; /* got response, no request pending */
 
        if (error)
                return 0;
@@ -760,7 +817,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
        if (reptype != LMI_FULLREP)
                return 0;
 
-       pvc = hdlc->state.fr.first_pvc;
+       pvc = state(hdlc)->first_pvc;
 
        while (pvc) {
                pvc->state.deleted = 1;
@@ -827,7 +884,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
                i += stat_len;
        }
 
-       pvc = hdlc->state.fr.first_pvc;
+       pvc = state(hdlc)->first_pvc;
 
        while (pvc) {
                if (pvc->state.deleted && pvc->state.exist) {
@@ -841,17 +898,16 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
        }
 
        /* Next full report after N391 polls */
-       hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391;
+       state(hdlc)->n391cnt = state(hdlc)->settings.n391;
 
        return 0;
 }
 
 
-
 static int fr_rx(struct sk_buff *skb)
 {
-       struct net_device *ndev = skb->dev;
-       hdlc_device *hdlc = dev_to_hdlc(ndev);
+       struct net_device *frad = skb->dev;
+       hdlc_device *hdlc = dev_to_hdlc(frad);
        fr_hdr *fh = (fr_hdr*)skb->data;
        u8 *data = skb->data;
        u16 dlci;
@@ -864,11 +920,11 @@ static int fr_rx(struct sk_buff *skb)
        dlci = q922_to_dlci(skb->data);
 
        if ((dlci == LMI_CCITT_ANSI_DLCI &&
-            (hdlc->state.fr.settings.lmi == LMI_ANSI ||
-             hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
+            (state(hdlc)->settings.lmi == LMI_ANSI ||
+             state(hdlc)->settings.lmi == LMI_CCITT)) ||
            (dlci == LMI_CISCO_DLCI &&
-            hdlc->state.fr.settings.lmi == LMI_CISCO)) {
-               if (fr_lmi_recv(ndev, skb))
+            state(hdlc)->settings.lmi == LMI_CISCO)) {
+               if (fr_lmi_recv(frad, skb))
                        goto rx_error;
                dev_kfree_skb_any(skb);
                return NET_RX_SUCCESS;
@@ -878,7 +934,7 @@ static int fr_rx(struct sk_buff *skb)
        if (!pvc) {
 #ifdef DEBUG_PKT
                printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
-                      ndev->name, dlci);
+                      frad->name, dlci);
 #endif
                dev_kfree_skb_any(skb);
                return NET_RX_DROP;
@@ -886,7 +942,7 @@ static int fr_rx(struct sk_buff *skb)
 
        if (pvc->state.fecn != fh->fecn) {
 #ifdef DEBUG_ECN
-               printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name,
+               printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", frad->name,
                       dlci, fh->fecn ? "N" : "FF");
 #endif
                pvc->state.fecn ^= 1;
@@ -894,7 +950,7 @@ static int fr_rx(struct sk_buff *skb)
 
        if (pvc->state.becn != fh->becn) {
 #ifdef DEBUG_ECN
-               printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name,
+               printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", frad->name,
                       dlci, fh->becn ? "N" : "FF");
 #endif
                pvc->state.becn ^= 1;
@@ -902,7 +958,7 @@ static int fr_rx(struct sk_buff *skb)
 
 
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-               hdlc->stats.rx_dropped++;
+               dev_to_desc(frad)->stats.rx_dropped++;
                return NET_RX_DROP;
        }
 
@@ -938,13 +994,13 @@ static int fr_rx(struct sk_buff *skb)
 
                default:
                        printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
-                              "PID=%x\n", ndev->name, oui, pid);
+                              "PID=%x\n", frad->name, oui, pid);
                        dev_kfree_skb_any(skb);
                        return NET_RX_DROP;
                }
        } else {
                printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
-                      "length = %i\n", ndev->name, data[3], skb->len);
+                      "length = %i\n", frad->name, data[3], skb->len);
                dev_kfree_skb_any(skb);
                return NET_RX_DROP;
        }
@@ -964,7 +1020,7 @@ static int fr_rx(struct sk_buff *skb)
        }
 
  rx_error:
-       hdlc->stats.rx_errors++; /* Mark error */
+       dev_to_desc(frad)->stats.rx_errors++; /* Mark error */
        dev_kfree_skb_any(skb);
        return NET_RX_DROP;
 }
@@ -977,44 +1033,42 @@ static void fr_start(struct net_device *dev)
 #ifdef DEBUG_LINK
        printk(KERN_DEBUG "fr_start\n");
 #endif
-       if (hdlc->state.fr.settings.lmi != LMI_NONE) {
-               hdlc->state.fr.reliable = 0;
-               hdlc->state.fr.dce_changed = 1;
-               hdlc->state.fr.request = 0;
-               hdlc->state.fr.fullrep_sent = 0;
-               hdlc->state.fr.last_errors = 0xFFFFFFFF;
-               hdlc->state.fr.n391cnt = 0;
-               hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0;
-
-               init_timer(&hdlc->state.fr.timer);
+       if (state(hdlc)->settings.lmi != LMI_NONE) {
+               state(hdlc)->reliable = 0;
+               state(hdlc)->dce_changed = 1;
+               state(hdlc)->request = 0;
+               state(hdlc)->fullrep_sent = 0;
+               state(hdlc)->last_errors = 0xFFFFFFFF;
+               state(hdlc)->n391cnt = 0;
+               state(hdlc)->txseq = state(hdlc)->rxseq = 0;
+
+               init_timer(&state(hdlc)->timer);
                /* First poll after 1 s */
-               hdlc->state.fr.timer.expires = jiffies + HZ;
-               hdlc->state.fr.timer.function = fr_timer;
-               hdlc->state.fr.timer.data = (unsigned long)dev;
-               add_timer(&hdlc->state.fr.timer);
+               state(hdlc)->timer.expires = jiffies + HZ;
+               state(hdlc)->timer.function = fr_timer;
+               state(hdlc)->timer.data = (unsigned long)dev;
+               add_timer(&state(hdlc)->timer);
        } else
                fr_set_link_state(1, dev);
 }
 
 
-
 static void fr_stop(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
        printk(KERN_DEBUG "fr_stop\n");
 #endif
-       if (hdlc->state.fr.settings.lmi != LMI_NONE)
-               del_timer_sync(&hdlc->state.fr.timer);
+       if (state(hdlc)->settings.lmi != LMI_NONE)
+               del_timer_sync(&state(hdlc)->timer);
        fr_set_link_state(0, dev);
 }
 
 
-
 static void fr_close(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
+       pvc_device *pvc = state(hdlc)->first_pvc;
 
        while (pvc) {           /* Shutdown all PVCs for this FRAD */
                if (pvc->main)
@@ -1025,7 +1079,8 @@ static void fr_close(struct net_device *dev)
        }
 }
 
-static void dlci_setup(struct net_device *dev)
+
+static void pvc_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_DLCI;
        dev->flags = IFF_POINTOPOINT;
@@ -1033,9 +1088,9 @@ static void dlci_setup(struct net_device *dev)
        dev->addr_len = 2;
 }
 
-static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
+static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 {
-       hdlc_device *hdlc = dev_to_hdlc(master);
+       hdlc_device *hdlc = dev_to_hdlc(frad);
        pvc_device *pvc = NULL;
        struct net_device *dev;
        int result, used;
@@ -1044,9 +1099,9 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
        if (type == ARPHRD_ETHER)
                prefix = "pvceth%d";
 
-       if ((pvc = add_pvc(master, dlci)) == NULL) {
+       if ((pvc = add_pvc(frad, dlci)) == NULL) {
                printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
-                      master->name);
+                      frad->name);
                return -ENOBUFS;
        }
 
@@ -1060,11 +1115,11 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
                                   "pvceth%d", ether_setup);
        else
                dev = alloc_netdev(sizeof(struct net_device_stats),
-                                  "pvc%d", dlci_setup);
+                                  "pvc%d", pvc_setup);
 
        if (!dev) {
                printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
-                      master->name);
+                      frad->name);
                delete_unused_pvcs(hdlc);
                return -ENOBUFS;
        }
@@ -1102,8 +1157,8 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
        dev->destructor = free_netdev;
        *get_dev_p(pvc, type) = dev;
        if (!used) {
-               hdlc->state.fr.dce_changed = 1;
-               hdlc->state.fr.dce_pvc_count++;
+               state(hdlc)->dce_changed = 1;
+               state(hdlc)->dce_pvc_count++;
        }
        return 0;
 }
@@ -1128,8 +1183,8 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
        *get_dev_p(pvc, type) = NULL;
 
        if (!pvc_is_used(pvc)) {
-               hdlc->state.fr.dce_pvc_count--;
-               hdlc->state.fr.dce_changed = 1;
+               state(hdlc)->dce_pvc_count--;
+               state(hdlc)->dce_changed = 1;
        }
        delete_unused_pvcs(hdlc);
        return 0;
@@ -1137,14 +1192,13 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
 
 
 
-static void fr_destroy(hdlc_device *hdlc)
+static void fr_destroy(struct net_device *frad)
 {
-       pvc_device *pvc;
-
-       pvc = hdlc->state.fr.first_pvc;
-       hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */
-       hdlc->state.fr.dce_pvc_count = 0;
-       hdlc->state.fr.dce_changed = 1;
+       hdlc_device *hdlc = dev_to_hdlc(frad);
+       pvc_device *pvc = state(hdlc)->first_pvc;
+       state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */
+       state(hdlc)->dce_pvc_count = 0;
+       state(hdlc)->dce_changed = 1;
 
        while (pvc) {
                pvc_device *next = pvc->next;
@@ -1161,8 +1215,17 @@ static void fr_destroy(hdlc_device *hdlc)
 }
 
 
+static struct hdlc_proto proto = {
+       .close          = fr_close,
+       .start          = fr_start,
+       .stop           = fr_stop,
+       .detach         = fr_destroy,
+       .ioctl          = fr_ioctl,
+       .module         = THIS_MODULE,
+};
+
 
-int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
        const size_t size = sizeof(fr_proto);
@@ -1173,12 +1236,14 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_FR;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(fr_s, &hdlc->state.fr.settings, size))
+               if (copy_to_user(fr_s, &state(hdlc)->settings, size))
                        return -EFAULT;
                return 0;
 
@@ -1213,20 +1278,16 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               if (hdlc->proto.id != IF_PROTO_FR) {
-                       hdlc_proto_detach(hdlc);
-                       hdlc->state.fr.first_pvc = NULL;
-                       hdlc->state.fr.dce_pvc_count = 0;
+               if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */
+                       result = attach_hdlc_protocol(dev, &proto, fr_rx,
+                                                     sizeof(struct frad_state));
+                       if (result)
+                               return result;
+                       state(hdlc)->first_pvc = NULL;
+                       state(hdlc)->dce_pvc_count = 0;
                }
-               memcpy(&hdlc->state.fr.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.close = fr_close;
-               hdlc->proto.start = fr_start;
-               hdlc->proto.stop = fr_stop;
-               hdlc->proto.detach = fr_destroy;
-               hdlc->proto.netif_rx = fr_rx;
-               hdlc->proto.id = IF_PROTO_FR;
+               memcpy(&state(hdlc)->settings, &new_settings, size);
+
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_FRAD;
@@ -1238,6 +1299,9 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
        case IF_PROTO_FR_DEL_PVC:
        case IF_PROTO_FR_ADD_ETH_PVC:
        case IF_PROTO_FR_DEL_ETH_PVC:
+               if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
+                       return -EINVAL;
+
                if(!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
@@ -1263,3 +1327,24 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Frame-Relay protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
deleted file mode 100644 (file)
index 04ca1f7..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Generic HDLC support routines for Linux
- *
- * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * Currently supported:
- *     * raw IP-in-HDLC
- *     * Cisco HDLC
- *     * Frame Relay with ANSI or CCITT LMI (both user and network side)
- *     * PPP
- *     * X.25
- *
- * Use sethdlc utility to set line parameters, protocol and PVCs
- *
- * How does it work:
- * - proto.open(), close(), start(), stop() calls are serialized.
- *   The order is: open, [ start, stop ... ] close ...
- * - proto.start() and stop() are called with spin_lock_irq held.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/pkt_sched.h>
-#include <linux/inetdevice.h>
-#include <linux/lapb.h>
-#include <linux/rtnetlink.h>
-#include <linux/notifier.h>
-#include <linux/hdlc.h>
-
-
-static const char* version = "HDLC support module revision 1.19";
-
-#undef DEBUG_LINK
-
-
-static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-
-
-static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
-{
-       return hdlc_stats(dev);
-}
-
-
-
-static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
-                   struct packet_type *p, struct net_device *orig_dev)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-       if (hdlc->proto.netif_rx)
-               return hdlc->proto.netif_rx(skb);
-
-       hdlc->stats.rx_dropped++; /* Shouldn't happen */
-       dev_kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-
-
-static inline void hdlc_proto_start(struct net_device *dev)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-       if (hdlc->proto.start)
-               return hdlc->proto.start(dev);
-}
-
-
-
-static inline void hdlc_proto_stop(struct net_device *dev)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-       if (hdlc->proto.stop)
-               return hdlc->proto.stop(dev);
-}
-
-
-
-static int hdlc_device_event(struct notifier_block *this, unsigned long event,
-                            void *ptr)
-{
-       struct net_device *dev = ptr;
-       hdlc_device *hdlc;
-       unsigned long flags;
-       int on;
-       if (dev->get_stats != hdlc_get_stats)
-               return NOTIFY_DONE; /* not an HDLC device */
-       if (event != NETDEV_CHANGE)
-               return NOTIFY_DONE; /* Only interrested in carrier changes */
-
-       on = netif_carrier_ok(dev);
-
-#ifdef DEBUG_LINK
-       printk(KERN_DEBUG "%s: hdlc_device_event NETDEV_CHANGE, carrier %i\n",
-              dev->name, on);
-#endif
-
-       hdlc = dev_to_hdlc(dev);
-       spin_lock_irqsave(&hdlc->state_lock, flags);
-
-       if (hdlc->carrier == on)
-               goto carrier_exit; /* no change in DCD line level */
-
-       hdlc->carrier = on;
-
-       if (!hdlc->open)
-               goto carrier_exit;
-
-       if (hdlc->carrier) {
-               printk(KERN_INFO "%s: Carrier detected\n", dev->name);
-               hdlc_proto_start(dev);
-       } else {
-               printk(KERN_INFO "%s: Carrier lost\n", dev->name);
-               hdlc_proto_stop(dev);
-       }
-
-carrier_exit:
-       spin_unlock_irqrestore(&hdlc->state_lock, flags);
-       return NOTIFY_DONE;
-}
-
-
-
-/* Must be called by hardware driver when HDLC device is being opened */
-int hdlc_open(struct net_device *dev)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-#ifdef DEBUG_LINK
-       printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n",
-              hdlc->carrier, hdlc->open);
-#endif
-
-       if (hdlc->proto.id == -1)
-               return -ENOSYS; /* no protocol attached */
-
-       if (hdlc->proto.open) {
-               int result = hdlc->proto.open(dev);
-               if (result)
-                       return result;
-       }
-
-       spin_lock_irq(&hdlc->state_lock);
-
-       if (hdlc->carrier) {
-               printk(KERN_INFO "%s: Carrier detected\n", dev->name);
-               hdlc_proto_start(dev);
-       } else
-               printk(KERN_INFO "%s: No carrier\n", dev->name);
-
-       hdlc->open = 1;
-
-       spin_unlock_irq(&hdlc->state_lock);
-       return 0;
-}
-
-
-
-/* Must be called by hardware driver when HDLC device is being closed */
-void hdlc_close(struct net_device *dev)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-#ifdef DEBUG_LINK
-       printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n",
-              hdlc->carrier, hdlc->open);
-#endif
-
-       spin_lock_irq(&hdlc->state_lock);
-
-       hdlc->open = 0;
-       if (hdlc->carrier)
-               hdlc_proto_stop(dev);
-
-       spin_unlock_irq(&hdlc->state_lock);
-
-       if (hdlc->proto.close)
-               hdlc->proto.close(dev);
-}
-
-
-
-#ifndef CONFIG_HDLC_RAW
-#define hdlc_raw_ioctl(dev, ifr)       -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_RAW_ETH
-#define hdlc_raw_eth_ioctl(dev, ifr)   -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_PPP
-#define hdlc_ppp_ioctl(dev, ifr)       -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_CISCO
-#define hdlc_cisco_ioctl(dev, ifr)     -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_FR
-#define hdlc_fr_ioctl(dev, ifr)                -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_X25
-#define hdlc_x25_ioctl(dev, ifr)       -ENOSYS
-#endif
-
-
-int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-       unsigned int proto;
-
-       if (cmd != SIOCWANDEV)
-               return -EINVAL;
-
-       switch(ifr->ifr_settings.type) {
-       case IF_PROTO_HDLC:
-       case IF_PROTO_HDLC_ETH:
-       case IF_PROTO_PPP:
-       case IF_PROTO_CISCO:
-       case IF_PROTO_FR:
-       case IF_PROTO_X25:
-               proto = ifr->ifr_settings.type;
-               break;
-
-       default:
-               proto = hdlc->proto.id;
-       }
-
-       switch(proto) {
-       case IF_PROTO_HDLC:     return hdlc_raw_ioctl(dev, ifr);
-       case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr);
-       case IF_PROTO_PPP:      return hdlc_ppp_ioctl(dev, ifr);
-       case IF_PROTO_CISCO:    return hdlc_cisco_ioctl(dev, ifr);
-       case IF_PROTO_FR:       return hdlc_fr_ioctl(dev, ifr);
-       case IF_PROTO_X25:      return hdlc_x25_ioctl(dev, ifr);
-       default:                return -EINVAL;
-       }
-}
-
-void hdlc_setup(struct net_device *dev)
-{
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-
-       dev->get_stats = hdlc_get_stats;
-       dev->change_mtu = hdlc_change_mtu;
-       dev->mtu = HDLC_MAX_MTU;
-
-       dev->type = ARPHRD_RAWHDLC;
-       dev->hard_header_len = 16;
-
-       dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-
-       hdlc->proto.id = -1;
-       hdlc->proto.detach = NULL;
-       hdlc->carrier = 1;
-       hdlc->open = 0;
-       spin_lock_init(&hdlc->state_lock);
-}
-
-struct net_device *alloc_hdlcdev(void *priv)
-{
-       struct net_device *dev;
-       dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
-       if (dev)
-               dev_to_hdlc(dev)->priv = priv;
-       return dev;
-}
-
-void unregister_hdlc_device(struct net_device *dev)
-{
-       rtnl_lock();
-       hdlc_proto_detach(dev_to_hdlc(dev));
-       unregister_netdevice(dev);
-       rtnl_unlock();
-}
-
-
-
-MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
-MODULE_DESCRIPTION("HDLC support module");
-MODULE_LICENSE("GPL v2");
-
-EXPORT_SYMBOL(hdlc_open);
-EXPORT_SYMBOL(hdlc_close);
-EXPORT_SYMBOL(hdlc_ioctl);
-EXPORT_SYMBOL(hdlc_setup);
-EXPORT_SYMBOL(alloc_hdlcdev);
-EXPORT_SYMBOL(unregister_hdlc_device);
-
-static struct packet_type hdlc_packet_type = {
-       .type = __constant_htons(ETH_P_HDLC),
-       .func = hdlc_rcv,
-};
-
-
-static struct notifier_block hdlc_notifier = {
-        .notifier_call = hdlc_device_event,
-};
-
-
-static int __init hdlc_module_init(void)
-{
-       int result;
-
-       printk(KERN_INFO "%s\n", version);
-       if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
-                return result;
-        dev_add_pack(&hdlc_packet_type);
-       return 0;
-}
-
-
-
-static void __exit hdlc_module_exit(void)
-{
-       dev_remove_pack(&hdlc_packet_type);
-       unregister_netdevice_notifier(&hdlc_notifier);
-}
-
-
-module_init(hdlc_module_init);
-module_exit(hdlc_module_exit);
index fbaab5bf71eb55b50ad8acc303dbad412d2776d9..e9f717070fde0d58bc4f1c103472510c7f9b9fff 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Point-to-point protocol support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
 #include <linux/lapb.h>
 #include <linux/rtnetlink.h>
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
+
+struct ppp_state {
+       struct ppp_device pppdev;
+       struct ppp_device *syncppp_ptr;
+       int (*old_change_mtu)(struct net_device *dev, int new_mtu);
+};
+
+static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
+static inline struct ppp_state* state(hdlc_device *hdlc)
+{
+       return(struct ppp_state *)(hdlc->state);
+}
 
 
 static int ppp_open(struct net_device *dev)
@@ -30,16 +45,16 @@ static int ppp_open(struct net_device *dev)
        void *old_ioctl;
        int result;
 
-       dev->priv = &hdlc->state.ppp.syncppp_ptr;
-       hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev;
-       hdlc->state.ppp.pppdev.dev = dev;
+       dev->priv = &state(hdlc)->syncppp_ptr;
+       state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev;
+       state(hdlc)->pppdev.dev = dev;
 
        old_ioctl = dev->do_ioctl;
-       hdlc->state.ppp.old_change_mtu = dev->change_mtu;
-       sppp_attach(&hdlc->state.ppp.pppdev);
+       state(hdlc)->old_change_mtu = dev->change_mtu;
+       sppp_attach(&state(hdlc)->pppdev);
        /* sppp_attach nukes them. We don't need syncppp's ioctl */
        dev->do_ioctl = old_ioctl;
-       hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO;
+       state(hdlc)->pppdev.sppp.pp_flags &= ~PP_CISCO;
        dev->type = ARPHRD_PPP;
        result = sppp_open(dev);
        if (result) {
@@ -59,7 +74,7 @@ static void ppp_close(struct net_device *dev)
        sppp_close(dev);
        sppp_detach(dev);
        dev->rebuild_header = NULL;
-       dev->change_mtu = hdlc->state.ppp.old_change_mtu;
+       dev->change_mtu = state(hdlc)->old_change_mtu;
        dev->mtu = HDLC_MAX_MTU;
        dev->hard_header_len = 16;
 }
@@ -73,13 +88,24 @@ static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 
 
-int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .open           = ppp_open,
+       .close          = ppp_close,
+       .type_trans     = ppp_type_trans,
+       .ioctl          = ppp_ioctl,
+       .module         = THIS_MODULE,
+};
+
+
+static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        int result;
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_PPP;
                return 0; /* return protocol only, no settable parameters */
 
@@ -96,13 +122,10 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.open = ppp_open;
-               hdlc->proto.close = ppp_close;
-               hdlc->proto.type_trans = ppp_type_trans;
-               hdlc->proto.id = IF_PROTO_PPP;
+               result = attach_hdlc_protocol(dev, &proto, NULL,
+                                             sizeof(struct ppp_state));
+               if (result)
+                       return result;
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_PPP;
@@ -113,3 +136,25 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("PPP protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index f15aa6ba77f1ee8450fd6dabb35add9d637ef94a..fe3cae5c6b9d07a267fde91d3051c950ea11e906 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * HDLC support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -24,6 +24,8 @@
 #include <linux/hdlc.h>
 
 
+static int raw_ioctl(struct net_device *dev, struct ifreq *ifr);
+
 static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
        return __constant_htons(ETH_P_IP);
@@ -31,7 +33,14 @@ static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 
 
-int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .type_trans     = raw_type_trans,
+       .ioctl          = raw_ioctl,
+       .module         = THIS_MODULE,
+};
+
+
+static int raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
        const size_t size = sizeof(raw_hdlc_proto);
@@ -41,12 +50,14 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_HDLC;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
+               if (copy_to_user(raw_s, hdlc->state, size))
                        return -EFAULT;
                return 0;
 
@@ -71,12 +82,11 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.type_trans = raw_type_trans;
-               hdlc->proto.id = IF_PROTO_HDLC;
+               result = attach_hdlc_protocol(dev, &proto, NULL,
+                                             sizeof(raw_hdlc_proto));
+               if (result)
+                       return result;
+               memcpy(hdlc->state, &new_settings, size);
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_RAWHDLC;
@@ -88,3 +98,25 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Raw HDLC protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index d1884987f94e08efbf06cc41ec68785b29a6a332..1a69a9aaa9b95fae17ffc077a1d8100dd612f414 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * HDLC Ethernet emulation support
  *
- * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2002-2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/hdlc.h>
 
+static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
 
 static int eth_tx(struct sk_buff *skb, struct net_device *dev)
 {
@@ -44,7 +45,14 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev)
 }
 
 
-int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .type_trans     = eth_type_trans,
+       .ioctl          = raw_eth_ioctl,
+       .module         = THIS_MODULE,
+};
+
+
+static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
        const size_t size = sizeof(raw_hdlc_proto);
@@ -56,12 +64,14 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_HDLC_ETH;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
+               if (copy_to_user(raw_s, hdlc->state, size))
                        return -EFAULT;
                return 0;
 
@@ -86,12 +96,11 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.type_trans = eth_type_trans;
-               hdlc->proto.id = IF_PROTO_HDLC_ETH;
+               result = attach_hdlc_protocol(dev, &proto, NULL,
+                                             sizeof(raw_hdlc_proto));
+               if (result)
+                       return result;
+               memcpy(hdlc->state, &new_settings, size);
                dev->hard_start_xmit = eth_tx;
                old_ch_mtu = dev->change_mtu;
                old_qlen = dev->tx_queue_len;
@@ -106,3 +115,25 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index a867fb411f89b90d1219e2a05801b6b6ad8a9419..e4bb9f8ad4337e1cb34bb7b9835732119877c3b3 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * X.25 support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -25,6 +25,8 @@
 
 #include <net/x25device.h>
 
+static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
+
 /* These functions are callbacks called by LAPB layer */
 
 static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
@@ -162,30 +164,39 @@ static void x25_close(struct net_device *dev)
 
 static int x25_rx(struct sk_buff *skb)
 {
-       hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+       struct hdlc_device_desc *desc = dev_to_desc(skb->dev);
 
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-               hdlc->stats.rx_dropped++;
+               desc->stats.rx_dropped++;
                return NET_RX_DROP;
        }
 
        if (lapb_data_received(skb->dev, skb) == LAPB_OK)
                return NET_RX_SUCCESS;
 
-       hdlc->stats.rx_errors++;
+       desc->stats.rx_errors++;
        dev_kfree_skb_any(skb);
        return NET_RX_DROP;
 }
 
 
+static struct hdlc_proto proto = {
+       .open           = x25_open,
+       .close          = x25_close,
+       .ioctl          = x25_ioctl,
+       .module         = THIS_MODULE,
+};
+
 
-int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        int result;
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_X25;
                return 0; /* return protocol only, no settable parameters */
 
@@ -200,14 +211,9 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.open = x25_open;
-               hdlc->proto.close = x25_close;
-               hdlc->proto.netif_rx = x25_rx;
-               hdlc->proto.type_trans = NULL;
-               hdlc->proto.id = IF_PROTO_X25;
+               if ((result = attach_hdlc_protocol(dev, &proto,
+                                                  x25_rx, 0)) != 0)
+                       return result;
                dev->hard_start_xmit = x25_xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_X25;
@@ -218,3 +224,25 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("X.25 protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index 2024b26b99e6e2728945af0c553455cb1bdaef9a..63e9fcf31fb8a1008a54a6fcdc691a228cb4cb8e 100644 (file)
 #define        _PC300_H
 
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
 #include "hd64572.h"
 #include "pc300-falc-lh.h"
 
index 56e69403d178f27ec908b4aa4c4162d8d8ad66d0..8d9b959bf15bd12eb62db63f8c58af437b91f042 100644 (file)
@@ -2016,7 +2016,6 @@ static void sca_intr(pc300_t * card)
                        pc300ch_t *chan = &card->chan[ch];
                        pc300dev_t *d = &chan->d;
                        struct net_device *dev = d->dev;
-                       hdlc_device *hdlc = dev_to_hdlc(dev);
 
                        spin_lock(&card->card_lock);
 
@@ -2049,8 +2048,8 @@ static void sca_intr(pc300_t * card)
                                                        }
                                                        cpc_net_rx(dev);
                                                        /* Discard invalid frames */
-                                                       hdlc->stats.rx_errors++;
-                                                       hdlc->stats.rx_over_errors++;
+                                                       hdlc_stats(dev)->rx_errors++;
+                                                       hdlc_stats(dev)->rx_over_errors++;
                                                        chan->rx_first_bd = 0;
                                                        chan->rx_last_bd = N_DMA_RX_BUF - 1;
                                                        rx_dma_start(card, ch);
@@ -2116,8 +2115,8 @@ static void sca_intr(pc300_t * card)
                                                                                   card->hw.cpld_reg2) &
                                                                   ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
                                                }
-                                               hdlc->stats.tx_errors++;
-                                               hdlc->stats.tx_fifo_errors++;
+                                               hdlc_stats(dev)->tx_errors++;
+                                               hdlc_stats(dev)->tx_fifo_errors++;
                                                sca_tx_intr(d);
                                        }
                                }
@@ -2534,7 +2533,6 @@ static int cpc_change_mtu(struct net_device *dev, int new_mtu)
 
 static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -2552,10 +2550,10 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                case SIOCGPC300CONF:
 #ifdef CONFIG_PC300_MLPPP
                        if (conf->proto != PC300_PROTO_MLPPP) {
-                               conf->proto = hdlc->proto.id;
+                               conf->proto = /* FIXME hdlc->proto.id */ 0;
                        }
 #else
-                       conf->proto = hdlc->proto.id;
+                       conf->proto = /* FIXME hdlc->proto.id */ 0;
 #endif
                        memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t));
                        memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t));
@@ -2588,12 +2586,12 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                                        }
                                } else {
                                        memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                                       hdlc->proto.id = conf->proto;
+                                       /* FIXME hdlc->proto.id = conf->proto; */
                                }
                        }
 #else
                        memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                       hdlc->proto.id = conf->proto;
+                       /* FIXME hdlc->proto.id = conf->proto; */
 #endif
                        return 0;
                case SIOCGPC300STATUS:
@@ -2606,7 +2604,7 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                case SIOCGPC300UTILSTATS:
                        {
                                if (!arg) {     /* clear statistics */
-                                       memset(&hdlc->stats, 0, sizeof(struct net_device_stats));
+                                       memset(hdlc_stats(dev), 0, sizeof(struct net_device_stats));
                                        if (card->hw.type == PC300_TE) {
                                                memset(&chan->falc, 0, sizeof(falc_t));
                                        }
@@ -2617,7 +2615,7 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                                        pc300stats.hw_type = card->hw.type;
                                        pc300stats.line_on = card->chan[ch].d.line_on;
                                        pc300stats.line_off = card->chan[ch].d.line_off;
-                                       memcpy(&pc300stats.gen_stats, &hdlc->stats,
+                                       memcpy(&pc300stats.gen_stats, hdlc_stats(dev),
                                               sizeof(struct net_device_stats));
                                        if (card->hw.type == PC300_TE)
                                                memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t));
@@ -3147,7 +3145,6 @@ static void cpc_closech(pc300dev_t * d)
 
 int cpc_open(struct net_device *dev)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        struct ifreq ifr;
        int result;
@@ -3156,12 +3153,14 @@ int cpc_open(struct net_device *dev)
        printk("pc300: cpc_open");
 #endif
 
+#ifdef FIXME
        if (hdlc->proto.id == IF_PROTO_PPP) {
                d->if_ptr = &hdlc->state.ppp.pppdev;
        }
+#endif
 
        result = hdlc_open(dev);
-       if (hdlc->proto.id == IF_PROTO_PPP) {
+       if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) {
                dev->priv = d;
        }
        if (result) {
@@ -3176,7 +3175,6 @@ int cpc_open(struct net_device *dev)
 
 static int cpc_close(struct net_device *dev)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -3193,7 +3191,7 @@ static int cpc_close(struct net_device *dev)
        CPC_UNLOCK(card, flags);
 
        hdlc_close(dev);
-       if (hdlc->proto.id == IF_PROTO_PPP) {
+       if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) {
                d->if_ptr = NULL;
        }
 #ifdef CONFIG_PC300_MLPPP
index c13b459a013789a62c1d7ade07739833791c9752..218f7b574ab3082012f2b4ec3a03262ffab98f9c 100644 (file)
@@ -469,7 +469,7 @@ static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb)
        struct net_device *dev = sp->pp_if;
        int len = skb->len;
        u8 *p, opt[6];
-       u32 rmagic;
+       u32 rmagic = 0;
 
        if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
                if (sp->pp_flags & PP_DEBUG)
@@ -763,7 +763,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
                {
                struct in_device *in_dev;
                struct in_ifaddr *ifa;
-               u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
+               __be32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
 #ifdef CONFIG_INET
                rcu_read_lock();
                if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
index bff04cba3fed03d77c4f82356fee11acc3ceb6df..ba737c6cebec643a6316a058a0ebc2e0f1ac7d72 100644 (file)
@@ -5868,7 +5868,7 @@ static int airo_set_essid(struct net_device *dev,
                int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE+1) {
+               if(dwrq->length > IW_ESSID_MAX_SIZE) {
                        return -E2BIG ;
                }
                /* Check if index is valid */
@@ -5880,7 +5880,7 @@ static int airo_set_essid(struct net_device *dev,
                memset(SSID_rid.ssids[index].ssid, 0,
                       sizeof(SSID_rid.ssids[index].ssid));
                memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
-               SSID_rid.ssids[index].len = dwrq->length - 1;
+               SSID_rid.ssids[index].len = dwrq->length;
        }
        SSID_rid.len = sizeof(SSID_rid);
        /* Write it to the card */
@@ -5990,7 +5990,7 @@ static int airo_set_nick(struct net_device *dev,
        struct airo_info *local = dev->priv;
 
        /* Check the size of the string */
-       if(dwrq->length > 16 + 1) {
+       if(dwrq->length > 16) {
                return -E2BIG;
        }
        readConfigRid(local, 1);
@@ -6015,7 +6015,7 @@ static int airo_get_nick(struct net_device *dev,
        readConfigRid(local, 1);
        strncpy(extra, local->config.nodeName, 16);
        extra[16] = '\0';
-       dwrq->length = strlen(extra) + 1;
+       dwrq->length = strlen(extra);
 
        return 0;
 }
@@ -6767,9 +6767,9 @@ static int airo_set_retry(struct net_device *dev,
        }
        readConfigRid(local, 1);
        if(vwrq->flags & IW_RETRY_LIMIT) {
-               if(vwrq->flags & IW_RETRY_MAX)
+               if(vwrq->flags & IW_RETRY_LONG)
                        local->config.longRetryLimit = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MIN)
+               else if (vwrq->flags & IW_RETRY_SHORT)
                        local->config.shortRetryLimit = vwrq->value;
                else {
                        /* No modifier : set both */
@@ -6805,14 +6805,14 @@ static int airo_get_retry(struct net_device *dev,
        if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
                vwrq->flags = IW_RETRY_LIFETIME;
                vwrq->value = (int)local->config.txLifetime * 1024;
-       } else if((vwrq->flags & IW_RETRY_MAX)) {
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       } else if((vwrq->flags & IW_RETRY_LONG)) {
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                vwrq->value = (int)local->config.longRetryLimit;
        } else {
                vwrq->flags = IW_RETRY_LIMIT;
                vwrq->value = (int)local->config.shortRetryLimit;
                if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
-                       vwrq->flags |= IW_RETRY_MIN;
+                       vwrq->flags |= IW_RETRY_SHORT;
        }
 
        return 0;
@@ -6990,6 +6990,7 @@ static int airo_set_power(struct net_device *dev,
                        local->config.rmode |= RXMODE_BC_MC_ADDR;
                        set_bit (FLAG_COMMIT, &local->flags);
                case IW_POWER_ON:
+                       /* This is broken, fixme ;-) */
                        break;
                default:
                        return -EINVAL;
index 995c7bea5897e9727ad66275eafd048658ec570f..0fc267d626dc0c68630b28e4953415a671eb672a 100644 (file)
@@ -1656,13 +1656,13 @@ static int atmel_set_essid(struct net_device *dev,
                priv->connect_to_any_BSS = 0;
 
                /* Check the size of the string */
-               if (dwrq->length > MAX_SSID_LENGTH + 1)
+               if (dwrq->length > MAX_SSID_LENGTH)
                         return -E2BIG;
                if (index != 0)
                        return -EINVAL;
 
-               memcpy(priv->new_SSID, extra, dwrq->length - 1);
-               priv->new_SSID_size = dwrq->length - 1;
+               memcpy(priv->new_SSID, extra, dwrq->length);
+               priv->new_SSID_size = dwrq->length;
        }
 
        return -EINPROGRESS;
@@ -2120,9 +2120,9 @@ static int atmel_set_retry(struct net_device *dev,
        struct atmel_private *priv = netdev_priv(dev);
 
        if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
-               if (vwrq->flags & IW_RETRY_MAX)
+               if (vwrq->flags & IW_RETRY_LONG)
                        priv->long_retry = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MIN)
+               else if (vwrq->flags & IW_RETRY_SHORT)
                        priv->short_retry = vwrq->value;
                else {
                        /* No modifier : set both */
@@ -2144,15 +2144,15 @@ static int atmel_get_retry(struct net_device *dev,
 
        vwrq->disabled = 0;      /* Can't be disabled */
 
-       /* Note : by default, display the min retry number */
-       if (vwrq->flags & IW_RETRY_MAX) {
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       /* Note : by default, display the short retry number */
+       if (vwrq->flags & IW_RETRY_LONG) {
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                vwrq->value = priv->long_retry;
        } else {
                vwrq->flags = IW_RETRY_LIMIT;
                vwrq->value = priv->short_retry;
                if (priv->long_retry != priv->short_retry)
-                       vwrq->flags |= IW_RETRY_MIN;
+                       vwrq->flags |= IW_RETRY_SHORT;
        }
 
        return 0;
index 6d4ea36bc5644753b8933deedb8222ca83afc957..d6a8bf09878e8716ec8a0d2c053979b841b1e450 100644 (file)
@@ -666,7 +666,6 @@ struct bcm43xx_noise_calculation {
 };
 
 struct bcm43xx_stats {
-       u8 link_quality;
        u8 noise;
        struct iw_statistics wstats;
        /* Store the last TX/RX times here for updating the leds. */
index 923275ea0789aa6e26b031a74b521b64f2ce7eb2..b9df06a06ea96105f3a033c3a54377229ee6c66e 100644 (file)
@@ -54,7 +54,7 @@ static ssize_t write_file_dummy(struct file *file, const char __user *buf,
 
 static int open_file_generic(struct inode *inode, struct file *file)
 {
-       file->private_data = inode->u.generic_ip;
+       file->private_data = inode->i_private;
        return 0;
 }
 
index cb9a3ae8463a99ddacc77b4dabed99e81be7c3dd..eb65db7393ba56dc47d6dcc4c565cbab13042078 100644 (file)
@@ -2405,9 +2405,10 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
                                   BCM43xx_UCODE_TIME) & 0x1f);
 
        if ( value16 > 0x128 ) {
-               dprintk(KERN_ERR PFX
-                       "Firmware: no support for microcode rev > 0x128\n");
-               err = -1;
+               printk(KERN_ERR PFX
+                       "Firmware: no support for microcode extracted "
+                       "from version 4.x binary drivers.\n");
+               err = -EOPNOTSUPP;
                goto err_release_fw;
        }
 
@@ -3169,8 +3170,7 @@ static void bcm43xx_periodic_work_handler(void *d)
                 * be preemtible.
                 */
                mutex_lock(&bcm->mutex);
-               netif_stop_queue(bcm->net_dev);
-               synchronize_net();
+               netif_tx_disable(bcm->net_dev);
                spin_lock_irqsave(&bcm->irq_lock, flags);
                bcm43xx_mac_suspend(bcm);
                if (bcm43xx_using_pio(bcm))
index eafd0f6626862ab5916f8ddd9906fd2e0b3c2450..52ce2a9334fb12eee4fa0d831950b04ea3128178 100644 (file)
@@ -361,7 +361,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
        if (phy->rev <= 2)
                for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
-       else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+       else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
                for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
        else
@@ -371,7 +371,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
        if (phy->rev == 2)
                for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
-       else if ((phy->rev > 2) && (phy->rev <= 7))
+       else if ((phy->rev > 2) && (phy->rev <= 8))
                for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
        
@@ -1197,7 +1197,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
 
        if (phy->rev == 1)
                bcm43xx_phy_initb5(bcm);
-       else if (phy->rev >= 2 && phy->rev <= 7)
+       else
                bcm43xx_phy_initb6(bcm);
        if (phy->rev >= 2 || phy->connected)
                bcm43xx_phy_inita(bcm);
@@ -1241,23 +1241,22 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
                bcm43xx_phy_lo_g_measure(bcm);
        } else {
                if (radio->version == 0x2050 && radio->revision == 8) {
-                       //FIXME
+                       bcm43xx_radio_write16(bcm, 0x0052,
+                                             (radio->txctl1 << 4) | radio->txctl2);
                } else {
                        bcm43xx_radio_write16(bcm, 0x0052,
                                              (bcm43xx_radio_read16(bcm, 0x0052)
                                               & 0xFFF0) | radio->txctl1);
                }
                if (phy->rev >= 6) {
-                       /*
                        bcm43xx_phy_write(bcm, 0x0036,
                                          (bcm43xx_phy_read(bcm, 0x0036)
-                                          & 0xF000) | (FIXME << 12));
-                       */
+                                          & 0xF000) | (radio->txctl2 << 12));
                }
                if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
                        bcm43xx_phy_write(bcm, 0x002E, 0x8075);
                else
-                       bcm43xx_phy_write(bcm, 0x003E, 0x807F);
+                       bcm43xx_phy_write(bcm, 0x002E, 0x807F);
                if (phy->rev < 2)
                        bcm43xx_phy_write(bcm, 0x002F, 0x0101);
                else
index 888077fc14c457b7082e706d503754efc9b46ab3..9b7b15cf656153b20d99633019b1885a1b87513c 100644 (file)
@@ -334,7 +334,7 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev,
        size_t len;
 
        mutex_lock(&bcm->mutex);
-       len = strlen(bcm->nick) + 1;
+       len = strlen(bcm->nick);
        memcpy(extra, bcm->nick, len);
        data->data.length = (__u16)len;
        data->data.flags = 1;
index c0efbfe605a5a20d3996a5f173a9e4657aac3dde..0159e4e93201cd2d7581d0d9ea2641c334948edd 100644 (file)
@@ -496,15 +496,14 @@ int bcm43xx_rx(struct bcm43xx_private *bcm,
        stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
                                              !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
                                              !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-//TODO stats.noise = 
+       stats.noise = bcm->stats.noise;
        if (is_ofdm)
                stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
        else
                stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
        stats.received_channel = radio->channel;
-//TODO stats.control = 
        stats.mask = IEEE80211_STATMASK_SIGNAL |
-//TODO              IEEE80211_STATMASK_NOISE |
+                    IEEE80211_STATMASK_NOISE |
                     IEEE80211_STATMASK_RATE |
                     IEEE80211_STATMASK_RSSI;
        if (phy->type == BCM43xx_PHYTYPE_A)
index 7a4978516eac1e6ae3824beef4083ebe26007ae7..d061fb3443ff9ea614af960986adcc44930f2794 100644 (file)
@@ -1412,9 +1412,9 @@ static int prism2_ioctl_siwretry(struct net_device *dev,
        /* what could be done, if firmware would support this.. */
 
        if (rrq->flags & IW_RETRY_LIMIT) {
-               if (rrq->flags & IW_RETRY_MAX)
+               if (rrq->flags & IW_RETRY_LONG)
                        HFA384X_RID_LONGRETRYLIMIT = rrq->value;
-               else if (rrq->flags & IW_RETRY_MIN)
+               else if (rrq->flags & IW_RETRY_SHORT)
                        HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
                else {
                        HFA384X_RID_LONGRETRYLIMIT = rrq->value;
@@ -1468,14 +1468,14 @@ static int prism2_ioctl_giwretry(struct net_device *dev,
                                rrq->value = le16_to_cpu(altretry);
                        else
                                rrq->value = local->manual_retry_count;
-               } else if ((rrq->flags & IW_RETRY_MAX)) {
-                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               } else if ((rrq->flags & IW_RETRY_LONG)) {
+                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                        rrq->value = longretry;
                } else {
                        rrq->flags = IW_RETRY_LIMIT;
                        rrq->value = shortretry;
                        if (shortretry != longretry)
-                               rrq->flags |= IW_RETRY_MIN;
+                               rrq->flags |= IW_RETRY_SHORT;
                }
        }
        return 0;
index b4d81a04c89570454fc01ecb7a0a978c9d0ea908..97937809de095c911850d914a522d4375de5c44b 100644 (file)
@@ -163,6 +163,7 @@ that only one external action is invoked at a time.
 #include <linux/firmware.h>
 #include <linux/acpi.h>
 #include <linux/ctype.h>
+#include <linux/latency.h>
 
 #include "ipw2100.h"
 
@@ -1697,6 +1698,11 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
                return 0;
        }
 
+       /* the ipw2100 hardware really doesn't want power management delays
+        * longer than 175usec
+        */
+       modify_acceptable_latency("ipw2100", 175);
+
        /* If the interrupt is enabled, turn it off... */
        spin_lock_irqsave(&priv->low_lock, flags);
        ipw2100_disable_interrupts(priv);
@@ -1849,6 +1855,8 @@ static void ipw2100_down(struct ipw2100_priv *priv)
        ipw2100_disable_interrupts(priv);
        spin_unlock_irqrestore(&priv->low_lock, flags);
 
+       modify_acceptable_latency("ipw2100", INFINITE_LATENCY);
+
 #ifdef ACPI_CSTATE_LIMIT_DEFINED
        if (priv->config & CFG_C3_DISABLED) {
                IPW_DEBUG_INFO(": Resetting C3 transitions.\n");
@@ -6534,6 +6542,7 @@ static int __init ipw2100_init(void)
 
        ret = pci_register_driver(&ipw2100_pci_driver);
 
+       set_acceptable_latency("ipw2100", INFINITE_LATENCY);
 #ifdef CONFIG_IPW2100_DEBUG
        ipw2100_debug_level = debug;
        driver_create_file(&ipw2100_pci_driver.driver,
@@ -6554,6 +6563,7 @@ static void __exit ipw2100_exit(void)
                           &driver_attr_debug_level);
 #endif
        pci_unregister_driver(&ipw2100_pci_driver);
+       remove_acceptable_latency("ipw2100");
 }
 
 module_init(ipw2100_init);
@@ -6958,7 +6968,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        }
 
        if (wrqu->essid.flags && wrqu->essid.length) {
-               length = wrqu->essid.length - 1;
+               length = wrqu->essid.length;
                essid = extra;
        }
 
@@ -7051,7 +7061,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev,
 
        struct ipw2100_priv *priv = ieee80211_priv(dev);
 
-       wrqu->data.length = strlen(priv->nick) + 1;
+       wrqu->data.length = strlen(priv->nick);
        memcpy(extra, priv->nick, wrqu->data.length);
        wrqu->data.flags = 1;   /* active */
 
@@ -7343,14 +7353,14 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
                goto done;
        }
 
-       if (wrqu->retry.flags & IW_RETRY_MIN) {
+       if (wrqu->retry.flags & IW_RETRY_SHORT) {
                err = ipw2100_set_short_retry(priv, wrqu->retry.value);
                IPW_DEBUG_WX("SET Short Retry Limit -> %d \n",
                             wrqu->retry.value);
                goto done;
        }
 
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
                err = ipw2100_set_long_retry(priv, wrqu->retry.value);
                IPW_DEBUG_WX("SET Long Retry Limit -> %d \n",
                             wrqu->retry.value);
@@ -7383,14 +7393,14 @@ static int ipw2100_wx_get_retry(struct net_device *dev,
        if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
                return -EINVAL;
 
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                wrqu->retry.value = priv->long_retry_limit;
        } else {
                wrqu->retry.flags =
                    (priv->short_retry_limit !=
                     priv->long_retry_limit) ?
-                   IW_RETRY_LIMIT | IW_RETRY_MIN : IW_RETRY_LIMIT;
+                   IW_RETRY_LIMIT | IW_RETRY_SHORT : IW_RETRY_LIMIT;
 
                wrqu->retry.value = priv->short_retry_limit;
        }
index 7358664e09088e53a2a92e1c78cbccdae96c02c9..5685d7ba55bb83c7758f3d8362dbc84a3797c89d 100644 (file)
@@ -8875,8 +8875,6 @@ static int ipw_wx_set_essid(struct net_device *dev,
         }
 
        length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE);
-       if (!extra[length - 1])
-               length--;
 
        priv->config |= CFG_STATIC_ESSID;
 
@@ -8953,7 +8951,7 @@ static int ipw_wx_get_nick(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        IPW_DEBUG_WX("Getting nick\n");
        mutex_lock(&priv->mutex);
-       wrqu->data.length = strlen(priv->nick) + 1;
+       wrqu->data.length = strlen(priv->nick);
        memcpy(extra, priv->nick, wrqu->data.length);
        wrqu->data.flags = 1;   /* active */
        mutex_unlock(&priv->mutex);
@@ -9276,9 +9274,9 @@ static int ipw_wx_set_retry(struct net_device *dev,
                return -EINVAL;
 
        mutex_lock(&priv->mutex);
-       if (wrqu->retry.flags & IW_RETRY_MIN)
+       if (wrqu->retry.flags & IW_RETRY_SHORT)
                priv->short_retry_limit = (u8) wrqu->retry.value;
-       else if (wrqu->retry.flags & IW_RETRY_MAX)
+       else if (wrqu->retry.flags & IW_RETRY_LONG)
                priv->long_retry_limit = (u8) wrqu->retry.value;
        else {
                priv->short_retry_limit = (u8) wrqu->retry.value;
@@ -9307,11 +9305,11 @@ static int ipw_wx_get_retry(struct net_device *dev,
                return -EINVAL;
        }
 
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                wrqu->retry.value = priv->long_retry_limit;
-       } else if (wrqu->retry.flags & IW_RETRY_MIN) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+       } else if (wrqu->retry.flags & IW_RETRY_SHORT) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
                wrqu->retry.value = priv->short_retry_limit;
        } else {
                wrqu->retry.flags = IW_RETRY_LIMIT;
index 1840b69e3cb5a6c5c5dfd3a04d239d50ac335442..9e19a963febc8b081839a9d9ca9216beb2942a6f 100644 (file)
@@ -3037,7 +3037,7 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
        }
 
        erq->flags = 1;
-       erq->length = strlen(essidbuf) + 1;
+       erq->length = strlen(essidbuf);
 
        return 0;
 }
@@ -3078,7 +3078,7 @@ static int orinoco_ioctl_getnick(struct net_device *dev,
        memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
        orinoco_unlock(priv, &flags);
 
-       nrq->length = strlen(nickbuf)+1;
+       nrq->length = strlen(nickbuf);
 
        return 0;
 }
@@ -3575,14 +3575,14 @@ static int orinoco_ioctl_getretry(struct net_device *dev,
                rrq->value = lifetime * 1000;   /* ??? */
        } else {
                /* By default, display the min number */
-               if ((rrq->flags & IW_RETRY_MAX)) {
-                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               if ((rrq->flags & IW_RETRY_LONG)) {
+                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                        rrq->value = long_limit;
                } else {
                        rrq->flags = IW_RETRY_LIMIT;
                        rrq->value = short_limit;
                        if(short_limit != long_limit)
-                               rrq->flags |= IW_RETRY_MIN;
+                               rrq->flags |= IW_RETRY_SHORT;
                }
        }
 
index c09fbf733b3a5ae8a8147ef63bb84f077aa161c4..286325ca3293d491f3005aa1f726ca0775645f78 100644 (file)
@@ -742,9 +742,9 @@ prism54_set_essid(struct net_device *ndev, struct iw_request_info *info,
 
        /* Check if we were asked for `any' */
        if (dwrq->flags && dwrq->length) {
-               if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1))
+               if (dwrq->length > 32)
                        return -E2BIG;
-               essid.length = dwrq->length - 1;
+               essid.length = dwrq->length;
                memcpy(essid.octets, extra, dwrq->length);
        } else
                essid.length = 0;
@@ -814,7 +814,7 @@ prism54_get_nick(struct net_device *ndev, struct iw_request_info *info,
        dwrq->length = 0;
 
        down_read(&priv->mib_sem);
-       dwrq->length = strlen(priv->nickname) + 1;
+       dwrq->length = strlen(priv->nickname);
        memcpy(extra, priv->nickname, dwrq->length);
        up_read(&priv->mib_sem);
 
@@ -992,9 +992,9 @@ prism54_set_retry(struct net_device *ndev, struct iw_request_info *info,
                return -EINVAL;
 
        if (vwrq->flags & IW_RETRY_LIMIT) {
-               if (vwrq->flags & IW_RETRY_MIN)
+               if (vwrq->flags & IW_RETRY_SHORT)
                        slimit = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MAX)
+               else if (vwrq->flags & IW_RETRY_LONG)
                        llimit = vwrq->value;
                else {
                        /* we are asked to set both */
@@ -1035,18 +1035,18 @@ prism54_get_retry(struct net_device *ndev, struct iw_request_info *info,
                    mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r);
                vwrq->value = r.u * 1024;
                vwrq->flags = IW_RETRY_LIFETIME;
-       } else if ((vwrq->flags & IW_RETRY_MAX)) {
+       } else if ((vwrq->flags & IW_RETRY_LONG)) {
                /* we are asked for the long retry limit */
                rvalue |=
                    mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r);
                vwrq->value = r.u;
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
        } else {
                /* default. get the  short retry limit */
                rvalue |=
                    mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r);
                vwrq->value = r.u;
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
        }
 
        return rvalue;
index 4574290f971fe0aeb6f39b81d83dde7684f15936..e82548ea609ac100f7310e81c8e7acdb4a946840 100644 (file)
@@ -1173,7 +1173,7 @@ static int ray_set_essid(struct net_device *dev,
                return -EOPNOTSUPP;
        } else {
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+               if(dwrq->length > IW_ESSID_MAX_SIZE) {
                        return -E2BIG;
                }
 
index ccaf28e8db0a28f529bf412b977b2546e14d266f..337c692f6fd66e98ba057cc46fc38b9a7e5fdad0 100644 (file)
@@ -1342,7 +1342,7 @@ static unsigned char *strip_make_packet(unsigned char *buffer,
         * 'broadcast hub' radio (First byte of address being 0xFF means broadcast)
         */
        if (haddr.c[0] == 0xFF) {
-               u32 brd = 0;
+               __be32 brd = 0;
                struct in_device *in_dev;
 
                rcu_read_lock();
@@ -1406,7 +1406,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
        int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0;
        int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0
            && !doreset;
-       u32 addr, brd;
+       __be32 addr, brd;
 
        /*
         * 1. If we have a packet, encapsulate it and put it in the buffer
index e0d294c12970fb7f29c68927f67a2ecc6425b390..e3ae5f60d5bea0bc537a38e84cf0182f7280d8c9 100644 (file)
@@ -1802,15 +1802,15 @@ static int wl3501_get_retry(struct net_device *dev,
                                      &retry, sizeof(retry));
        if (rc)
                goto out;
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                goto set_value;
        }
        rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_SHORT_RETRY_LIMIT,
                                  &retry, sizeof(retry));
        if (rc)
                goto out;
-       wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+       wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
 set_value:
        wrqu->retry.value = retry;
        wrqu->retry.disabled = 0;
index c52e9bcf8d02f3fc688de9d7f1c17c49b51c9288..80af9a9fcbb33cd3f54614019b8511a6b8d6f579 100644 (file)
@@ -119,7 +119,7 @@ static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
        switch(urb->status) {
                case -EILSEQ:
                case -ENODEV:
-               case -ETIMEDOUT:
+               case -ETIME:
                case -ENOENT:
                case -EPIPE:
                case -EOVERFLOW:
@@ -201,7 +201,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
        switch(urb->status) {
                case -EILSEQ:
                case -ENODEV:
-               case -ETIMEDOUT:
+               case -ETIME:
                case -ENOENT:
                case -EPIPE:
                case -EOVERFLOW:
@@ -1218,7 +1218,7 @@ static int zd1201_set_essid(struct net_device *dev,
                return -EINVAL;
        if (data->length < 1)
                data->length = 1;
-       zd->essidlen = data->length-1;
+       zd->essidlen = data->length;
        memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
        memcpy(zd->essid, essid, data->length);
        return zd1201_join(zd, zd->essid, zd->essidlen);
index 7c4e32cf0d471d2ebf0b1496e6eb520285900f18..aa661b2b76c7c3c9b358ac296ee2806cb23743b3 100644 (file)
@@ -249,7 +249,6 @@ int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_ioread16_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -260,7 +259,6 @@ int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_ioread32_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -271,7 +269,6 @@ int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_iowrite16_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -282,7 +279,6 @@ int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_iowrite32_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -294,7 +290,6 @@ int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_ioread32v_locked(chip, values, addresses, count);
        mutex_unlock(&chip->mutex);
@@ -306,7 +301,6 @@ int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_iowrite32a_locked(chip, ioreqs, count);
        mutex_unlock(&chip->mutex);
@@ -331,13 +325,22 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type)
        chip->patch_cr157 = (value >> 13) & 0x1;
        chip->patch_6m_band_edge = (value >> 21) & 0x1;
        chip->new_phy_layout = (value >> 31) & 0x1;
+       chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
+       chip->supports_tx_led = 1;
+       if (value & (1 << 24)) { /* LED scenario */
+               if (value & (1 << 29))
+                       chip->supports_tx_led = 0;
+       }
 
        dev_dbg_f(zd_chip_dev(chip),
                "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
-               "patch 6M %d new PHY %d\n",
+               "patch 6M %d new PHY %d link LED%d tx led %d\n",
                zd_rf_name(*rf_type), *rf_type,
                chip->pa_type, chip->patch_cck_gain,
-               chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout);
+               chip->patch_cr157, chip->patch_6m_band_edge,
+               chip->new_phy_layout,
+               chip->link_led == LED1 ? 1 : 2,
+               chip->supports_tx_led);
        return 0;
 error:
        *rf_type = 0;
@@ -1181,7 +1184,7 @@ static int update_pwr_int(struct zd_chip *chip, u8 channel)
        u8 value = chip->pwr_int_values[channel - 1];
        dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n",
                 channel, value);
-       return zd_iowrite32_locked(chip, value, CR31);
+       return zd_iowrite16_locked(chip, value, CR31);
 }
 
 static int update_pwr_cal(struct zd_chip *chip, u8 channel)
@@ -1189,12 +1192,12 @@ static int update_pwr_cal(struct zd_chip *chip, u8 channel)
        u8 value = chip->pwr_cal_values[channel-1];
        dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n",
                 channel, value);
-       return zd_iowrite32_locked(chip, value, CR68);
+       return zd_iowrite16_locked(chip, value, CR68);
 }
 
 static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
 {
-       struct zd_ioreq32 ioreqs[3];
+       struct zd_ioreq16 ioreqs[3];
 
        ioreqs[0].addr = CR67;
        ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1];
@@ -1206,7 +1209,7 @@ static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
        dev_dbg_f(zd_chip_dev(chip),
                "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n",
                channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value);
-       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 static int update_channel_integration_and_calibration(struct zd_chip *chip,
@@ -1218,7 +1221,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
        if (r)
                return r;
        if (chip->is_zd1211b) {
-               static const struct zd_ioreq32 ioreqs[] = {
+               static const struct zd_ioreq16 ioreqs[] = {
                        { CR69, 0x28 },
                        {},
                        { CR69, 0x2a },
@@ -1230,7 +1233,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
                r = update_pwr_cal(chip, channel);
                if (r)
                        return r;
-               r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
                if (r)
                        return r;
        }
@@ -1252,7 +1255,7 @@ static int patch_cck_gain(struct zd_chip *chip)
        if (r)
                return r;
        dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff);
-       return zd_iowrite32_locked(chip, value & 0xff, CR47);
+       return zd_iowrite16_locked(chip, value & 0xff, CR47);
 }
 
 int zd_chip_set_channel(struct zd_chip *chip, u8 channel)
@@ -1295,89 +1298,60 @@ u8 zd_chip_get_channel(struct zd_chip *chip)
        return channel;
 }
 
-static u16 led_mask(int led)
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
 {
-       switch (led) {
-       case 1:
-               return LED1;
-       case 2:
-               return LED2;
-       default:
-               return 0;
-       }
-}
-
-static int read_led_reg(struct zd_chip *chip, u16 *status)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_ioread16_locked(chip, status, CR_LED);
-}
-
-static int write_led_reg(struct zd_chip *chip, u16 status)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_iowrite16_locked(chip, status, CR_LED);
-}
+       static const zd_addr_t a[] = {
+               FW_LINK_STATUS,
+               CR_LED,
+       };
 
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status)
-{
-       int r, ret;
-       u16 mask = led_mask(led);
-       u16 reg;
+       int r;
+       u16 v[ARRAY_SIZE(a)];
+       struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
+               [0] = { FW_LINK_STATUS },
+               [1] = { CR_LED },
+       };
+       u16 other_led;
 
-       if (!mask)
-               return -EINVAL;
        mutex_lock(&chip->mutex);
-       r = read_led_reg(chip, &reg);
+       r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a));
        if (r)
-               return r;
+               goto out;
+
+       other_led = chip->link_led == LED1 ? LED2 : LED1;
+
        switch (status) {
-       case LED_STATUS:
-               return (reg & mask) ? LED_ON : LED_OFF;
        case LED_OFF:
-               reg &= ~mask;
-               ret = LED_OFF;
+               ioreqs[0].value = FW_LINK_OFF;
+               ioreqs[1].value = v[1] & ~(LED1|LED2);
                break;
-       case LED_FLIP:
-               reg ^= mask;
-               ret = (reg&mask) ? LED_ON : LED_OFF;
+       case LED_SCANNING:
+               ioreqs[0].value = FW_LINK_OFF;
+               ioreqs[1].value = v[1] & ~other_led;
+               if (get_seconds() % 3 == 0) {
+                       ioreqs[1].value &= ~chip->link_led;
+               } else {
+                       ioreqs[1].value |= chip->link_led;
+               }
                break;
-       case LED_ON:
-               reg |= mask;
-               ret = LED_ON;
+       case LED_ASSOCIATED:
+               ioreqs[0].value = FW_LINK_TX;
+               ioreqs[1].value = v[1] & ~other_led;
+               ioreqs[1].value |= chip->link_led;
                break;
        default:
-               return -EINVAL;
-       }
-       r = write_led_reg(chip, reg);
-       if (r) {
-               ret = r;
+               r = -EINVAL;
                goto out;
        }
-out:
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_chip_led_flip(struct zd_chip *chip, int led,
-       const unsigned int *phases_msecs, unsigned int count)
-{
-       int i, r;
-       enum led_status status;
 
-       r = zd_chip_led_status(chip, led, LED_STATUS);
-       if (r)
-               return r;
-       status = r;
-       for (i = 0; i < count; i++) {
-               r = zd_chip_led_status(chip, led, LED_FLIP);
-               if (r < 0)
+       if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) {
+               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               if (r)
                        goto out;
-               msleep(phases_msecs[i]);
        }
-
+       r = 0;
 out:
-       zd_chip_led_status(chip, led, status);
+       mutex_unlock(&chip->mutex);
        return r;
 }
 
@@ -1679,4 +1653,3 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip,
 
        return 0;
 }
-
index 4b12508598972a65040a44987e43531912a71003..ae59597ce4e16e5035e7910d4fc858501b347a2d 100644 (file)
 /* masks for controlling LEDs */
 #define LED1                           0x0100
 #define LED2                           0x0200
+#define LED_SW                         0x0400
 
 /* Seems to indicate that the configuration is over.
  */
 #define FW_SOFT_RESET           FW_REG(4)
 #define FW_FLASH_CHK            FW_REG(5)
 
+#define FW_LINK_OFF            0x0
+#define FW_LINK_TX             0x1
+/* 0x2 - link led on? */
+
 enum {
        CR_BASE_OFFSET                  = 0x9000,
        FW_START_OFFSET                 = 0xee00,
@@ -663,8 +668,11 @@ struct zd_chip {
        u8 pwr_int_values[E2P_CHANNEL_COUNT];
        /* SetPointOFDM in the vendor driver */
        u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
-       u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-          new_phy_layout:1, is_zd1211b:1;
+       u16 link_led;
+       unsigned int pa_type:4,
+               patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
+               new_phy_layout:1,
+               is_zd1211b:1, supports_tx_led:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -812,15 +820,12 @@ int zd_chip_lock_phy_regs(struct zd_chip *chip);
 int zd_chip_unlock_phy_regs(struct zd_chip *chip);
 
 enum led_status {
-       LED_OFF    = 0,
-       LED_ON     = 1,
-       LED_FLIP   = 2,
-       LED_STATUS = 3,
+       LED_OFF = 0,
+       LED_SCANNING = 1,
+       LED_ASSOCIATED = 2,
 };
 
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status);
-int zd_chip_led_flip(struct zd_chip *chip, int led,
-                    const unsigned int *phases_msecs, unsigned int count);
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
 
 int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
 
index 1989f1c05fbee7bea30fa93888cf611e8c4b76a6..2d12837052b03f35f49e1f4ae21aa99c831653f7 100644 (file)
 static void ieee_init(struct ieee80211_device *ieee);
 static void softmac_init(struct ieee80211softmac_device *sm);
 
+static void housekeeping_init(struct zd_mac *mac);
+static void housekeeping_enable(struct zd_mac *mac);
+static void housekeeping_disable(struct zd_mac *mac);
+
 int zd_mac_init(struct zd_mac *mac,
                struct net_device *netdev,
                struct usb_interface *intf)
@@ -46,6 +50,7 @@ int zd_mac_init(struct zd_mac *mac,
        ieee_init(ieee);
        softmac_init(ieee80211_priv(netdev));
        zd_chip_init(&mac->chip, netdev, intf);
+       housekeeping_init(mac);
        return 0;
 }
 
@@ -178,6 +183,7 @@ int zd_mac_open(struct net_device *netdev)
        if (r < 0)
                goto disable_rx;
 
+       housekeeping_enable(mac);
        ieee80211softmac_start(netdev);
        return 0;
 disable_rx:
@@ -204,6 +210,7 @@ int zd_mac_stop(struct net_device *netdev)
         */
 
        zd_chip_disable_rx(chip);
+       housekeeping_disable(mac);
        ieee80211softmac_stop(netdev);
 
        zd_chip_disable_hwint(chip);
@@ -1080,3 +1087,46 @@ void zd_dump_rx_status(const struct rx_status *status)
        }
 }
 #endif /* DEBUG */
+
+#define LINK_LED_WORK_DELAY HZ
+
+static void link_led_handler(void *p)
+{
+       struct zd_mac *mac = p;
+       struct zd_chip *chip = &mac->chip;
+       struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev);
+       int is_associated;
+       int r;
+
+       spin_lock_irq(&mac->lock);
+       is_associated = sm->associated != 0;
+       spin_unlock_irq(&mac->lock);
+
+       r = zd_chip_control_leds(chip,
+                                is_associated ? LED_ASSOCIATED : LED_SCANNING);
+       if (r)
+               dev_err(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
+
+       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+                          LINK_LED_WORK_DELAY);
+}
+
+static void housekeeping_init(struct zd_mac *mac)
+{
+       INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac);
+}
+
+static void housekeeping_enable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+                          0);
+}
+
+static void housekeeping_disable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       cancel_rearming_delayed_workqueue(zd_workqueue,
+               &mac->housekeeping.link_led_work);
+       zd_chip_control_leds(&mac->chip, LED_OFF);
+}
index 29b51fd7d4e58f484e4eeb1520b9c8526cdc2f0d..b8ea3de7924afb95a8032b32853616f15f7f6867 100644 (file)
@@ -120,6 +120,10 @@ enum mac_flags {
        MAC_FIXED_CHANNEL = 0x01,
 };
 
+struct housekeeping {
+       struct work_struct link_led_work;
+};
+
 #define ZD_MAC_STATS_BUFFER_SIZE 16
 
 struct zd_mac {
@@ -128,6 +132,7 @@ struct zd_mac {
        struct net_device *netdev;
        /* Unlocked reading possible */
        struct iw_statistics iw_stats;
+       struct housekeeping housekeeping;
        unsigned int stats_count;
        u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
        u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
index 440ef24b5fd10a445c525093bf799a65c6d348c4..af3a7b36d078c03e96dadbbe08ee6e744ff6d6b1 100644 (file)
@@ -82,7 +82,7 @@ static int iw_get_nick(struct net_device *netdev,
                       union iwreq_data *req, char *extra)
 {
        strcpy(extra, "zd1211");
-       req->data.length = strlen(extra) + 1;
+       req->data.length = strlen(extra);
        req->data.flags = 1;
        return 0;
 }
index 31027e52b04b1f17b27f17c1272a0c1c7ee105ba..5c265ad0485af0c08a46e706dfc6b16b25f6b562 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 #include <net/ieee80211.h>
 
 #include "zd_def.h"
@@ -1112,12 +1113,20 @@ static struct usb_driver driver = {
        .disconnect     = disconnect,
 };
 
+struct workqueue_struct *zd_workqueue;
+
 static int __init usb_init(void)
 {
        int r;
 
        pr_debug("usb_init()\n");
 
+       zd_workqueue = create_singlethread_workqueue(driver.name);
+       if (zd_workqueue == NULL) {
+               printk(KERN_ERR "%s: couldn't create workqueue\n", driver.name);
+               return -ENOMEM;
+       }
+
        r = usb_register(&driver);
        if (r) {
                printk(KERN_ERR "usb_register() failed. Error number %d\n", r);
@@ -1132,6 +1141,7 @@ static void __exit usb_exit(void)
 {
        pr_debug("usb_exit()\n");
        usb_deregister(&driver);
+       destroy_workqueue(zd_workqueue);
 }
 
 module_init(usb_init);
index ded39de5f72de55d0815d68ccdf8328c90f19e4f..e81a2d3cfffd2ad4dd166f0084031565aac9f524 100644 (file)
@@ -238,4 +238,6 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
 
+extern struct workqueue_struct *zd_workqueue;
+
 #endif /* _ZD_USB_H */
index 71c2da277d6e6a398b13b8041195a41f540f409d..5756401fb15bb2e13d272ef87f4ce6f3752ab8cd 100644 (file)
@@ -31,7 +31,6 @@ static struct inode * oprofilefs_get_inode(struct super_block * sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        }
@@ -110,8 +109,8 @@ static ssize_t ulong_write_file(struct file * file, char const __user * buf, siz
 
 static int default_open(struct inode * inode, struct file * filp)
 {
-       if (inode->u.generic_ip)
-               filp->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               filp->private_data = inode->i_private;
        return 0;
 }
 
@@ -158,7 +157,7 @@ int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
        if (!d)
                return -EFAULT;
 
-       d->d_inode->u.generic_ip = val;
+       d->d_inode->i_private = val;
        return 0;
 }
 
@@ -171,7 +170,7 @@ int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
        if (!d)
                return -EFAULT;
 
-       d->d_inode->u.generic_ip = val;
+       d->d_inode->i_private = val;
        return 0;
 }
 
@@ -197,7 +196,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
        if (!d)
                return -EFAULT;
 
-       d->d_inode->u.generic_ip = val;
+       d->d_inode->i_private = val;
        return 0;
 }
 
index fe800dc0be9f7fedfdf69e92ff262ebe0b51d787..43894ddec7dcfa9d4c8528703649baef60d9420b 100644 (file)
@@ -3374,6 +3374,10 @@ __setup("parport_init_mode=",parport_init_mode_setup);
 
 static int __init parport_pc_init(void)
 {
+#if defined(CONFIG_PPC_MERGE)
+       if (check_legacy_ioport(PARALLEL_BASE))
+               return -ENODEV;
+#endif
        if (parse_parport_params())
                return -EINVAL;
 
index 98b83a85c60e2d462fe92e4e39de2e6f0e977945..78c0a269a2ba3e24200b0c13e72a70c99b978141 100644 (file)
@@ -374,6 +374,7 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
        return;
 }
 
+#ifdef CONFIG_PM
 static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
 {
        struct parport_serial_private *priv = pci_get_drvdata(dev);
@@ -407,14 +408,17 @@ static int parport_serial_pci_resume(struct pci_dev *dev)
 
        return 0;
 }
+#endif
 
 static struct pci_driver parport_serial_pci_driver = {
        .name           = "parport_serial",
        .id_table       = parport_serial_pci_tbl,
        .probe          = parport_serial_pci_probe,
        .remove         = __devexit_p(parport_serial_pci_remove),
+#ifdef CONFIG_PM
        .suspend        = parport_serial_pci_suspend,
        .resume         = parport_serial_pci_resume,
+#endif
 };
 
 
index 5f7db9d2436e76141e15d50a44e9f1fc38e54378..aadaa3c8096b73ecf50428b044b0151c6f10b50d 100644 (file)
@@ -77,9 +77,12 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
  * This adds a single pci device to the global
  * device list and adds sysfs and procfs entries
  */
-void __devinit pci_bus_add_device(struct pci_dev *dev)
+int __devinit pci_bus_add_device(struct pci_dev *dev)
 {
-       device_add(&dev->dev);
+       int retval;
+       retval = device_add(&dev->dev);
+       if (retval)
+               return retval;
 
        down_write(&pci_bus_sem);
        list_add_tail(&dev->global_list, &pci_devices);
@@ -87,6 +90,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
 
        pci_proc_attach_device(dev);
        pci_create_sysfs_dev_files(dev);
+       return 0;
 }
 
 /**
@@ -104,6 +108,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
 void __devinit pci_bus_add_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
+       int retval;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                /*
@@ -112,7 +117,9 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
                 */
                if (!list_empty(&dev->global_list))
                        continue;
-               pci_bus_add_device(dev);
+               retval = pci_bus_add_device(dev);
+               if (retval)
+                       dev_err(&dev->dev, "Error adding device, continuing\n");
        }
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -129,10 +136,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
                               list_add_tail(&dev->subordinate->node,
                                               &dev->bus->children);
                               up_write(&pci_bus_sem);
-                      }
+                       }
                        pci_bus_add_devices(dev->subordinate);
-
-                       sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
+                       retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
+                                                  &dev->dev.kobj, "bridge");
+                       if (retval)
+                               dev_err(&dev->dev, "Error creating sysfs "
+                                       "bridge symlink, continuing...\n");
                }
        }
 }
index be104eced34c63ffea077e1e8d64f93cad1e56e5..7fff07e877c71982b89b672eea06b7617d89e13e 100644 (file)
@@ -150,6 +150,11 @@ struct acpiphp_attention_info
        struct module *owner;
 };
 
+struct acpiphp_ioapic {
+       struct pci_dev *dev;
+       u32 gsi_base;
+       struct list_head list;
+};
 
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID              "PNP0A03"
index ae67a8f55ba169851ad7c78bf1cdd83c7c67f047..83e8e4412de5834fff05c3558cf911d94146f48f 100644 (file)
@@ -53,6 +53,8 @@
 #include "acpiphp.h"
 
 static LIST_HEAD(bridge_list);
+static LIST_HEAD(ioapic_list);
+static DEFINE_SPINLOCK(ioapic_list_lock);
 
 #define MY_NAME "acpiphp_glue"
 
@@ -797,6 +799,7 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
        struct pci_dev *pdev;
        u32 gsi_base;
        u64 phys_addr;
+       struct acpiphp_ioapic *ioapic;
 
        /* Evaluate _STA if present */
        status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
@@ -811,41 +814,107 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
        if (get_gsi_base(handle, &gsi_base))
                return AE_OK;
 
+       ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL);
+       if (!ioapic)
+               return AE_NO_MEMORY;
+
        pdev = get_apic_pci_info(handle);
        if (!pdev)
-               return AE_OK;
+               goto exit_kfree;
 
-       if (pci_enable_device(pdev)) {
-               pci_dev_put(pdev);
-               return AE_OK;
-       }
+       if (pci_enable_device(pdev))
+               goto exit_pci_dev_put;
 
        pci_set_master(pdev);
 
-       if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) {
-               pci_disable_device(pdev);
-               pci_dev_put(pdev);
-               return AE_OK;
-       }
+       if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)"))
+               goto exit_pci_disable_device;
 
        phys_addr = pci_resource_start(pdev, 0);
-       if (acpi_register_ioapic(handle, phys_addr, gsi_base)) {
-               pci_release_region(pdev, 0);
-               pci_disable_device(pdev);
-               pci_dev_put(pdev);
+       if (acpi_register_ioapic(handle, phys_addr, gsi_base))
+               goto exit_pci_release_region;
+
+       ioapic->gsi_base = gsi_base;
+       ioapic->dev = pdev;
+       spin_lock(&ioapic_list_lock);
+       list_add_tail(&ioapic->list, &ioapic_list);
+       spin_unlock(&ioapic_list_lock);
+
+       return AE_OK;
+
+ exit_pci_release_region:
+       pci_release_region(pdev, 0);
+ exit_pci_disable_device:
+       pci_disable_device(pdev);
+ exit_pci_dev_put:
+       pci_dev_put(pdev);
+ exit_kfree:
+       kfree(ioapic);
+
+       return AE_OK;
+}
+
+static acpi_status
+ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       acpi_status status;
+       unsigned long sta;
+       acpi_handle tmp;
+       u32 gsi_base;
+       struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
+
+       /* Evaluate _STA if present */
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
+               return AE_CTRL_DEPTH;
+
+       /* Scan only PCI bus scope */
+       status = acpi_get_handle(handle, "_HID", &tmp);
+       if (ACPI_SUCCESS(status))
+               return AE_CTRL_DEPTH;
+
+       if (get_gsi_base(handle, &gsi_base))
                return AE_OK;
+
+       acpi_unregister_ioapic(handle, gsi_base);
+
+       spin_lock(&ioapic_list_lock);
+       list_for_each_entry_safe(pos, n, &ioapic_list, list) {
+               if (pos->gsi_base != gsi_base)
+                       continue;
+               ioapic = pos;
+               list_del(&ioapic->list);
+               break;
        }
+       spin_unlock(&ioapic_list_lock);
+
+       if (!ioapic)
+               return AE_OK;
+
+       pci_release_region(ioapic->dev, 0);
+       pci_disable_device(ioapic->dev);
+       pci_dev_put(ioapic->dev);
+       kfree(ioapic);
 
        return AE_OK;
 }
 
 static int acpiphp_configure_ioapics(acpi_handle handle)
 {
+       ioapic_add(handle, 0, NULL, NULL);
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
                            ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
        return 0;
 }
 
+static int acpiphp_unconfigure_ioapics(acpi_handle handle)
+{
+       ioapic_remove(handle, 0, NULL, NULL);
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                           ACPI_UINT32_MAX, ioapic_remove, NULL, NULL);
+       return 0;
+}
+
 static int power_on_slot(struct acpiphp_slot *slot)
 {
        acpi_status status;
@@ -997,7 +1066,7 @@ acpiphp_bus_add_out:
  * @handle: handle to acpi namespace
  *
  */
-int acpiphp_bus_trim(acpi_handle handle)
+static int acpiphp_bus_trim(acpi_handle handle)
 {
        struct acpi_device *device;
        int retval;
@@ -1074,10 +1143,11 @@ static int enable_device(struct acpiphp_slot *slot)
 
        pci_bus_assign_resources(bus);
        acpiphp_sanitize_bus(bus);
+       acpiphp_set_hpp_values(slot->bridge->handle, bus);
+       list_for_each_entry(func, &slot->funcs, sibling)
+               acpiphp_configure_ioapics(func->handle);
        pci_enable_bridges(bus);
        pci_bus_add_devices(bus);
-       acpiphp_set_hpp_values(slot->bridge->handle, bus);
-       acpiphp_configure_ioapics(slot->bridge->handle);
 
        /* associate pci_dev to our representation */
        list_for_each (l, &slot->funcs) {
@@ -1103,6 +1173,16 @@ static int enable_device(struct acpiphp_slot *slot)
        return retval;
 }
 
+static void disable_bridges(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               if (dev->subordinate) {
+                       disable_bridges(dev->subordinate);
+                       pci_disable_device(dev);
+               }
+       }
+}
 
 /**
  * disable_device - disable a slot
@@ -1127,6 +1207,19 @@ static int disable_device(struct acpiphp_slot *slot)
                        func->bridge = NULL;
                }
 
+               if (func->pci_dev) {
+                       pci_stop_bus_device(func->pci_dev);
+                       if (func->pci_dev->subordinate) {
+                               disable_bridges(func->pci_dev->subordinate);
+                               pci_disable_device(func->pci_dev);
+                       }
+               }
+       }
+
+       list_for_each (l, &slot->funcs) {
+               func = list_entry(l, struct acpiphp_func, sibling);
+
+               acpiphp_unconfigure_ioapics(func->handle);
                acpiphp_bus_trim(func->handle);
                /* try to remove anyway.
                 * acpiphp_bus_add might have been failed */
index 8b3da007e859abc803a9109ba046ba31e6be432c..5bab666cd67e138015657f23ef837bea332c5a6e 100644 (file)
@@ -140,7 +140,7 @@ struct ctrl_dbg {
 
 static int open(struct inode *inode, struct file *file)
 {
-       struct controller *ctrl = inode->u.generic_ip;
+       struct controller *ctrl = inode->i_private;
        struct ctrl_dbg *dbg;
        int retval = -ENOMEM;
 
index dd2b762777c4bbb72a8086401173c6e9e2707ce8..05a4f0f9018620b5f6999c701d8a73ffbb477659 100644 (file)
@@ -176,7 +176,9 @@ static void pci_rescan_slot(struct pci_dev *temp)
        struct pci_bus *bus = temp->bus;
        struct pci_dev *dev;
        int func;
+       int retval;
        u8 hdr_type;
+
        if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
                temp->hdr_type = hdr_type & 0x7f;
                if (!pci_find_slot(bus->number, temp->devfn)) {
@@ -185,8 +187,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
                                dbg("New device on %s function %x:%x\n",
                                        bus->name, temp->devfn >> 3,
                                        temp->devfn & 7);
-                               pci_bus_add_device(dev);
-                               add_slot(dev);
+                               retval = pci_bus_add_device(dev);
+                               if (retval)
+                                       dev_err(&dev->dev, "error adding "
+                                               "device, continuing.\n");
+                               else
+                                       add_slot(dev);
                        }
                }
                /* multifunction device? */
@@ -205,8 +211,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
                                        dbg("New device on %s function %x:%x\n",
                                                bus->name, temp->devfn >> 3,
                                                temp->devfn & 7);
-                                       pci_bus_add_device(dev);
-                                       add_slot(dev);
+                                       retval = pci_bus_add_device(dev);
+                                       if (retval)
+                                               dev_err(&dev->dev, "error adding "
+                                                       "device, continuing.\n");
+                                       else
+                                               add_slot(dev);
                                }
                        }
                }
index e929b7c114296c6a348af75fe921731a0f2e8220..772523dc3860f57e5bc8b2f5d4e8d89c82044c0e 100644 (file)
@@ -172,8 +172,8 @@ struct hotplug_slot {
 
 extern int pci_hp_register             (struct hotplug_slot *slot);
 extern int pci_hp_deregister           (struct hotplug_slot *slot);
-extern int pci_hp_change_slot_info     (struct hotplug_slot *slot,
-                                        struct hotplug_slot_info *info);
+extern int __must_check pci_hp_change_slot_info        (struct hotplug_slot *slot,
+                                                struct hotplug_slot_info *info);
 extern struct subsystem pci_hotplug_slots_subsys;
 
 /* PCI Setting Record (Type 0) */
index b7b378df89e3ffeb2a3fda1debb70558a02b401d..e2823ea9c4ed829ffda3298da97ac3574dc40312 100644 (file)
@@ -482,31 +482,95 @@ static int has_test_file (struct hotplug_slot *slot)
 
 static int fs_add_slot (struct hotplug_slot *slot)
 {
-       if (has_power_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+       int retval = 0;
 
-       if (has_attention_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+       if (has_power_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+               if (retval)
+                       goto exit_power;
+       }
 
-       if (has_latch_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+       if (has_attention_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_attention.attr);
+               if (retval)
+                       goto exit_attention;
+       }
 
-       if (has_adapter_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+       if (has_latch_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_latch.attr);
+               if (retval)
+                       goto exit_latch;
+       }
 
-       if (has_address_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_address.attr);
+       if (has_adapter_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_presence.attr);
+               if (retval)
+                       goto exit_adapter;
+       }
 
-       if (has_max_bus_speed_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+       if (has_address_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_address.attr);
+               if (retval)
+                       goto exit_address;
+       }
 
+       if (has_max_bus_speed_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_max_bus_speed.attr);
+               if (retval)
+                       goto exit_max_speed;
+       }
+
+       if (has_cur_bus_speed_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_cur_bus_speed.attr);
+               if (retval)
+                       goto exit_cur_speed;
+       }
+
+       if (has_test_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_test.attr);
+               if (retval)
+                       goto exit_test;
+       }
+
+       goto exit;
+
+exit_test:
        if (has_cur_bus_speed_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
 
-       if (has_test_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+exit_cur_speed:
+       if (has_max_bus_speed_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
 
-       return 0;
+exit_max_speed:
+       if (has_address_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
+
+exit_address:
+       if (has_adapter_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+exit_adapter:
+       if (has_latch_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+
+exit_latch:
+       if (has_attention_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+exit_attention:
+       if (has_power_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+exit_power:
+exit:
+       return retval;
 }
 
 static void fs_remove_slot (struct hotplug_slot *slot)
@@ -626,8 +690,11 @@ int pci_hp_deregister (struct hotplug_slot *slot)
  *
  * Returns 0 if successful, anything else for an error.
  */
-int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info)
+int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
+                                        struct hotplug_slot_info *info)
 {
+       int retval;
+
        if ((slot == NULL) || (info == NULL))
                return -ENODEV;
 
@@ -636,32 +703,60 @@ int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info
        * for the files referring to the fields that have now changed.
        */
        if ((has_power_file(slot) == 0) &&
-           (slot->info->power_status != info->power_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+           (slot->info->power_status != info->power_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_power.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_attention_file(slot) == 0) &&
-           (slot->info->attention_status != info->attention_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+           (slot->info->attention_status != info->attention_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_attention.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_latch_file(slot) == 0) &&
-           (slot->info->latch_status != info->latch_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+           (slot->info->latch_status != info->latch_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_latch.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_adapter_file(slot) == 0) &&
-           (slot->info->adapter_status != info->adapter_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+           (slot->info->adapter_status != info->adapter_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_presence.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_address_file(slot) == 0) &&
-           (slot->info->address != info->address))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_address.attr);
+           (slot->info->address != info->address)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_address.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_max_bus_speed_file(slot) == 0) &&
-           (slot->info->max_bus_speed != info->max_bus_speed))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+           (slot->info->max_bus_speed != info->max_bus_speed)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_max_bus_speed.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_cur_bus_speed_file(slot) == 0) &&
-           (slot->info->cur_bus_speed != info->cur_bus_speed))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+           (slot->info->cur_bus_speed != info->cur_bus_speed)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_cur_bus_speed.attr);
+               if (retval)
+                       return retval;
+       }
 
        memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
 
index 33d19876835626a6be7e4aa226aa459c3a5c9860..41290a106bd8c4661fd1f1204c213a5db64c32ef 100644 (file)
@@ -762,14 +762,14 @@ int pciehp_enable_slot(struct slot *p_slot)
        if (rc || !getstatus) {
                info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
                mutex_unlock(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        if (MRL_SENS(p_slot->ctrl->ctrlcap)) {  
                rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
                if (rc || getstatus) {
                        info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -ENODEV;
                }
        }
        
@@ -778,7 +778,7 @@ int pciehp_enable_slot(struct slot *p_slot)
                if (rc || getstatus) {
                        info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -EINVAL;
                }
        }
        mutex_unlock(&p_slot->ctrl->crit_sect);
@@ -813,7 +813,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                if (ret || !getstatus) {
                        info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -ENODEV;
                }
        }
 
@@ -822,7 +822,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                if (ret || getstatus) {
                        info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -ENODEV;
                }
        }
 
@@ -831,7 +831,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                if (ret || !getstatus) {
                        info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -EINVAL;
                }
        }
 
index 8ad446605f756fe3afad4feaea3d9e7c82cd0a1a..2b9e10e38613327bee8c6767609c2522892d12f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PCI Hot Plug Controller Skeleton Driver - 0.2
+ * PCI Hot Plug Controller Skeleton Driver - 0.3
  *
  * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2001,2003 IBM Corp.
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * This driver is to be used as a skeleton driver to be show how to interface
+ * This driver is to be used as a skeleton driver to show how to interface
  * with the pci hotplug core easily.
  *
  * Send feedback to <greg@kroah.com>
@@ -58,8 +58,6 @@ static LIST_HEAD(slot_list);
 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
 
-
-
 /* local variables */
 static int debug;
 static int num_slots;
@@ -109,7 +107,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
        return retval;
 }
 
-
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
@@ -342,7 +339,7 @@ static int __init pcihp_skel_init(void)
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
        /*
         * Do specific initialization stuff for your driver here
-        * Like initializing your controller hardware (if any) and
+        * like initializing your controller hardware (if any) and
         * determining the number of slots you have in the system
         * right now.
         */
index 7208b95c6ee779585ff056bcdaeb091140f44961..c7103ac5cd06b76da2c0ec60381003601bd98bc1 100644 (file)
@@ -173,7 +173,7 @@ struct controller {
 #define msg_button_cancel      "PCI slot #%s - action canceled due to button press.\n"
 
 /* sysfs functions for the hotplug controller info */
-extern void shpchp_create_ctrl_files   (struct controller *ctrl);
+extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
 
 extern int     shpchp_sysfs_enable_slot(struct slot *slot);
 extern int     shpchp_sysfs_disable_slot(struct slot *slot);
index a14e7de1984621cd9281751df06cc0624fee5d87..235c18a22393d04e0ba86ec5f511d086149f6d75 100644 (file)
@@ -449,10 +449,14 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ctrl->speed = PCI_SPEED_33MHz;
        }
 
-       shpchp_create_ctrl_files(ctrl);
+       rc = shpchp_create_ctrl_files(ctrl);
+       if (rc)
+               goto err_cleanup_slots;
 
        return 0;
 
+err_cleanup_slots:
+       cleanup_slots(ctrl);
 err_out_release_ctlr:
        ctrl->hpc_ops->release_ctlr(ctrl);
 err_out_free_ctrl:
index 620e1139e607c763dfaa69ff25413c971de82310..29fa9d26adae28b0e49e0a39e16796439f1c4b4f 100644 (file)
@@ -91,9 +91,9 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-void shpchp_create_ctrl_files (struct controller *ctrl)
+int __must_check shpchp_create_ctrl_files (struct controller *ctrl)
 {
-       device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+       return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
 }
 
 void shpchp_remove_ctrl_files(struct controller *ctrl)
index a83c1f5735d69bc05418e5963dbbcbc975a06a11..27a057409eca1d53d37ca41d3d2fa4a6844de868 100644 (file)
@@ -45,16 +45,10 @@ msi_register(struct msi_ops *ops)
        return 0;
 }
 
-static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
-{
-       memset(p, 0, sizeof(struct msi_desc));
-}
-
 static int msi_cache_init(void)
 {
-       msi_cachep = kmem_cache_create("msi_cache",
-                       sizeof(struct msi_desc),
-                       0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL);
+       msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
+                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
        if (!msi_cachep)
                return -ENOMEM;
 
@@ -402,11 +396,10 @@ static struct msi_desc* alloc_msi_entry(void)
 {
        struct msi_desc *entry;
 
-       entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
+       entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL);
        if (!entry)
                return NULL;
 
-       memset(entry, 0, sizeof(struct msi_desc));
        entry->link.tail = entry->link.head = 0;        /* single message */
        entry->dev = NULL;
 
@@ -900,6 +893,33 @@ static int msix_capability_init(struct pci_dev *dev,
        return 0;
 }
 
+/**
+ * pci_msi_supported - check whether MSI may be enabled on device
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ *
+ * MSI must be globally enabled and supported by the device and its root
+ * bus. But, the root bus is not easy to find since some architectures
+ * have virtual busses on top of the PCI hierarchy (for instance the
+ * hypertransport bus), while the actual bus where MSI must be supported
+ * is below. So we test the MSI flag on all parent busses and assume
+ * that no quirk will ever set the NO_MSI flag on a non-root bus.
+ **/
+static
+int pci_msi_supported(struct pci_dev * dev)
+{
+       struct pci_bus *bus;
+
+       if (!pci_msi_enable || !dev || dev->no_msi)
+               return -EINVAL;
+
+       /* check MSI flags of all parent busses */
+       for (bus = dev->bus; bus; bus = bus->parent)
+               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+                       return -EINVAL;
+
+       return 0;
+}
+
 /**
  * pci_enable_msi - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -912,19 +932,11 @@ static int msix_capability_init(struct pci_dev *dev,
  **/
 int pci_enable_msi(struct pci_dev* dev)
 {
-       struct pci_bus *bus;
-       int pos, temp, status = -EINVAL;
+       int pos, temp, status;
        u16 control;
 
-       if (!pci_msi_enable || !dev)
-               return status;
-
-       if (dev->no_msi)
-               return status;
-
-       for (bus = dev->bus; bus; bus = bus->parent)
-               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
-                       return -EINVAL;
+       if (pci_msi_supported(dev) < 0)
+               return -EINVAL;
 
        temp = dev->irq;
 
@@ -1134,22 +1146,14 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
  **/
 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 {
-       struct pci_bus *bus;
        int status, pos, nr_entries, free_vectors;
        int i, j, temp;
        u16 control;
        unsigned long flags;
 
-       if (!pci_msi_enable || !dev || !entries)
+       if (!entries || pci_msi_supported(dev) < 0)
                return -EINVAL;
 
-       if (dev->no_msi)
-               return -EINVAL;
-
-       for (bus = dev->bus; bus; bus = bus->parent)
-               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
-                       return -EINVAL;
-
        status = msi_init();
        if (status < 0)
                return status;
index d8ace1f90dd2a13f864bb2f87b649377c11d4c14..b1c0c707d96ccc6e713042b1d67167609199c723 100644 (file)
@@ -56,6 +56,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
                subdevice=PCI_ANY_ID, class=0, class_mask=0;
        unsigned long driver_data=0;
        int fields=0;
+       int retval = 0;
 
        fields = sscanf(buf, "%x %x %x %x %x %x %lux",
                        &vendor, &device, &subvendor, &subdevice,
@@ -82,10 +83,12 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
        spin_unlock(&pdrv->dynids.lock);
 
        if (get_driver(&pdrv->driver)) {
-               driver_attach(&pdrv->driver);
+               retval = driver_attach(&pdrv->driver);
                put_driver(&pdrv->driver);
        }
 
+       if (retval)
+               return retval;
        return count;
 }
 static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
@@ -418,7 +421,11 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
        drv->driver.bus = &pci_bus_type;
        drv->driver.owner = owner;
        drv->driver.kobj.ktype = &pci_driver_kobj_type;
-       drv->driver.multithread_probe = pci_multithread_probe;
+
+       if (pci_multithread_probe)
+               drv->driver.multithread_probe = pci_multithread_probe;
+       else
+               drv->driver.multithread_probe = drv->multithread_probe;
 
        spin_lock_init(&drv->dynids.lock);
        INIT_LIST_HEAD(&drv->dynids.list);
index fdefa7dcd15675758f31c3ce3ababd69368433d4..a1d2e979b17fdd1e431297b78c88fbf926da99ac 100644 (file)
@@ -117,6 +117,7 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
+       int retval = 0;
 
        /* this can crash the machine when done on the "wrong" device */
        if (!capable(CAP_SYS_ADMIN))
@@ -126,11 +127,53 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
                pci_disable_device(pdev);
 
        if (*buf == '1')
-               pci_enable_device(pdev);
+               retval = pci_enable_device(pdev);
 
+       if (retval)
+               return retval;
        return count;
 }
 
+static ssize_t
+msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       if (!pdev->subordinate)
+               return 0;
+
+       return sprintf (buf, "%u\n",
+                       !(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
+}
+
+static ssize_t
+msi_bus_store(struct device *dev, struct device_attribute *attr,
+             const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       /* bad things may happen if the no_msi flag is changed
+        * while some drivers are loaded */
+       if (!capable(CAP_SYS_ADMIN))
+               return count;
+
+       if (!pdev->subordinate)
+               return count;
+
+       if (*buf == '0') {
+               pdev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+               dev_warn(&pdev->dev, "forced subordinate bus to not support MSI,"
+                        " bad things could happen.\n");
+       }
+
+       if (*buf == '1') {
+               pdev->subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI;
+               dev_warn(&pdev->dev, "forced subordinate bus to support MSI,"
+                        " bad things could happen.\n");
+       }
+
+       return count;
+}
 
 struct device_attribute pci_dev_attrs[] = {
        __ATTR_RO(resource),
@@ -145,6 +188,7 @@ struct device_attribute pci_dev_attrs[] = {
        __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
        __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
                broken_parity_status_show,broken_parity_status_store),
+       __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
        __ATTR_NULL,
 };
 
@@ -384,16 +428,39 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
        return pci_mmap_page_range(pdev, vma, mmap_type, 0);
 }
 
+/**
+ * pci_remove_resource_files - cleanup resource files
+ * @dev: dev to cleanup
+ *
+ * If we created resource files for @dev, remove them from sysfs and
+ * free their resources.
+ */
+static void
+pci_remove_resource_files(struct pci_dev *pdev)
+{
+       int i;
+
+       for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+               struct bin_attribute *res_attr;
+
+               res_attr = pdev->res_attr[i];
+               if (res_attr) {
+                       sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
+                       kfree(res_attr);
+               }
+       }
+}
+
 /**
  * pci_create_resource_files - create resource files in sysfs for @dev
  * @dev: dev in question
  *
  * Walk the resources in @dev creating files for each resource available.
  */
-static void
-pci_create_resource_files(struct pci_dev *pdev)
+static int pci_create_resource_files(struct pci_dev *pdev)
 {
        int i;
+       int retval;
 
        /* Expose the PCI resources from this device as files */
        for (i = 0; i < PCI_ROM_RESOURCE; i++) {
@@ -416,35 +483,19 @@ pci_create_resource_files(struct pci_dev *pdev)
                        res_attr->size = pci_resource_len(pdev, i);
                        res_attr->mmap = pci_mmap_resource;
                        res_attr->private = &pdev->resource[i];
-                       sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
-               }
-       }
-}
-
-/**
- * pci_remove_resource_files - cleanup resource files
- * @dev: dev to cleanup
- *
- * If we created resource files for @dev, remove them from sysfs and
- * free their resources.
- */
-static void
-pci_remove_resource_files(struct pci_dev *pdev)
-{
-       int i;
-
-       for (i = 0; i < PCI_ROM_RESOURCE; i++) {
-               struct bin_attribute *res_attr;
-
-               res_attr = pdev->res_attr[i];
-               if (res_attr) {
-                       sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
-                       kfree(res_attr);
+                       retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
+                       if (retval) {
+                               pci_remove_resource_files(pdev);
+                               return retval;
+                       }
+               } else {
+                       return -ENOMEM;
                }
        }
+       return 0;
 }
 #else /* !HAVE_PCI_MMAP */
-static inline void pci_create_resource_files(struct pci_dev *dev) { return; }
+static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; }
 static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
 #endif /* HAVE_PCI_MMAP */
 
@@ -529,22 +580,27 @@ static struct bin_attribute pcie_config_attr = {
        .write = pci_write_config,
 };
 
-int pci_create_sysfs_dev_files (struct pci_dev *pdev)
+int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
+       struct bin_attribute *rom_attr = NULL;
+       int retval;
+
        if (!sysfs_initialized)
                return -EACCES;
 
        if (pdev->cfg_size < 4096)
-               sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
        else
-               sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+       if (retval)
+               goto err;
 
-       pci_create_resource_files(pdev);
+       retval = pci_create_resource_files(pdev);
+       if (retval)
+               goto err_bin_file;
 
        /* If the device has a ROM, try to expose it in sysfs. */
        if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
-               struct bin_attribute *rom_attr;
-               
                rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
                if (rom_attr) {
                        pdev->rom_attr = rom_attr;
@@ -554,13 +610,28 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
                        rom_attr->attr.owner = THIS_MODULE;
                        rom_attr->read = pci_read_rom;
                        rom_attr->write = pci_write_rom;
-                       sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
+                       retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
+                       if (retval)
+                               goto err_rom;
+               } else {
+                       retval = -ENOMEM;
+                       goto err_bin_file;
                }
        }
        /* add platform-specific attributes */
        pcibios_add_platform_entries(pdev);
-       
+
        return 0;
+
+err_rom:
+       kfree(rom_attr);
+err_bin_file:
+       if (pdev->cfg_size < 4096)
+               sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+       else
+               sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+err:
+       return retval;
 }
 
 /**
@@ -589,10 +660,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 static int __init pci_sysfs_init(void)
 {
        struct pci_dev *pdev = NULL;
-       
+       int retval;
+
        sysfs_initialized = 1;
-       for_each_pci_dev(pdev)
-               pci_create_sysfs_dev_files(pdev);
+       for_each_pci_dev(pdev) {
+               retval = pci_create_sysfs_dev_files(pdev);
+               if (retval)
+                       return retval;
+       }
 
        return 0;
 }
index 590f4e6f505d35328f4b0f706a31c7e9319d3ed7..a544997399b307a7efa50b7854dd7b6e63340487 100644 (file)
@@ -445,6 +445,51 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
 
 EXPORT_SYMBOL(pci_choose_state);
 
+static int pci_save_pcie_state(struct pci_dev *dev)
+{
+       int pos, i = 0;
+       struct pci_cap_saved_state *save_state;
+       u16 *cap;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (pos <= 0)
+               return 0;
+
+       save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+       if (!save_state) {
+               dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
+               return -ENOMEM;
+       }
+       cap = (u16 *)&save_state->data[0];
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
+       pci_add_saved_cap(dev, save_state);
+       return 0;
+}
+
+static void pci_restore_pcie_state(struct pci_dev *dev)
+{
+       int i = 0, pos;
+       struct pci_cap_saved_state *save_state;
+       u16 *cap;
+
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!save_state || pos <= 0)
+               return;
+       cap = (u16 *)&save_state->data[0];
+
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
+       pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
+       pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
+       pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
+       pci_remove_saved_cap(save_state);
+       kfree(save_state);
+}
+
 /**
  * pci_save_state - save the PCI configuration space of a device before suspending
  * @dev: - PCI device that we're dealing with
@@ -460,6 +505,8 @@ pci_save_state(struct pci_dev *dev)
                return i;
        if ((i = pci_save_msix_state(dev)) != 0)
                return i;
+       if ((i = pci_save_pcie_state(dev)) != 0)
+               return i;
        return 0;
 }
 
@@ -473,6 +520,9 @@ pci_restore_state(struct pci_dev *dev)
        int i;
        int val;
 
+       /* PCI Express register must be restored first */
+       pci_restore_pcie_state(dev);
+
        /*
         * The Base Address register should be programmed before the command
         * register(s)
index 08d58fc78ee1cafc522702fd26618e4b43d66a4f..6bf327db5c5e70fd39d62f060ca8d5cbd95da1de 100644 (file)
@@ -42,7 +42,7 @@ extern void pci_remove_legacy_files(struct pci_bus *bus);
 /* Lock for read/write access to pci device and bus lists */
 extern struct rw_semaphore pci_bus_sem;
 
-#ifdef CONFIG_X86_IO_APIC
+#ifdef CONFIG_PCI_MSI
 extern int pci_msi_quirk;
 #else
 #define pci_msi_quirk 0
index 1012db8b8b2c4b6d093d93bc2e65053fba3e71d3..0ad92a8ad8b1a831007dc58cd47554a7be0ac68a 100644 (file)
@@ -34,3 +34,4 @@ config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
           
          When in doubt, say N.
 
+source "drivers/pci/pcie/aer/Kconfig"
index 984fa87283e3a3f7e0b3228cf36d53a8147d56dd..e00fb99acf44434934d05db3dc33959eeebd5650 100644 (file)
@@ -5,3 +5,6 @@
 pcieportdrv-y                  := portdrv_core.o portdrv_pci.o portdrv_bus.o
 
 obj-$(CONFIG_PCIEPORTBUS)      += pcieportdrv.o
+
+# Build PCI Express AER if needed
+obj-$(CONFIG_PCIEAER)          += aer/
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
new file mode 100644 (file)
index 0000000..3f37a60
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# PCI Express Root Port Device AER Configuration
+#
+
+config PCIEAER
+       boolean "Root Port Advanced Error Reporting support"
+       depends on PCIEPORTBUS && ACPI
+       default y
+       help
+         This enables PCI Express Root Port Advanced Error Reporting
+         (AER) driver support. Error reporting messages sent to Root
+         Port will be handled by PCI Express AER driver.
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
new file mode 100644 (file)
index 0000000..15a4f40
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for PCI-Express Root Port Advanced Error Reporting Driver
+#
+
+obj-$(CONFIG_PCIEAER) += aerdriver.o
+
+aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
+
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
new file mode 100644 (file)
index 0000000..0d4ac02
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This file implements the AER root port service driver. The driver will
+ * register an irq handler. When root port triggers an AER interrupt, the irq
+ * handler will collect root port status and schedule a work.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pcieport_if.h>
+
+#include "aerdrv.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0"
+#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
+#define DRIVER_DESC "Root Port Advanced Error Reporting Driver"
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+static int __devinit aer_probe (struct pcie_device *dev,
+       const struct pcie_port_service_id *id );
+static void aer_remove(struct pcie_device *dev);
+static int aer_suspend(struct pcie_device *dev, pm_message_t state)
+{return 0;}
+static int aer_resume(struct pcie_device *dev) {return 0;}
+static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
+       enum pci_channel_state error);
+static void aer_error_resume(struct pci_dev *dev);
+static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
+
+/*
+ * PCI Express bus's AER Root service driver data structure
+ */
+static struct pcie_port_service_id aer_id[] = {
+       {
+       .vendor         = PCI_ANY_ID,
+       .device         = PCI_ANY_ID,
+       .port_type      = PCIE_RC_PORT,
+       .service_type   = PCIE_PORT_SERVICE_AER,
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_error_handlers aer_error_handlers = {
+       .error_detected = aer_error_detected,
+       .resume = aer_error_resume,
+};
+
+static struct pcie_port_service_driver aerdrv = {
+       .name           = "aer",
+       .id_table       = &aer_id[0],
+
+       .probe          = aer_probe,
+       .remove         = aer_remove,
+
+       .suspend        = aer_suspend,
+       .resume         = aer_resume,
+
+       .err_handler    = &aer_error_handlers,
+
+       .reset_link     = aer_root_reset,
+};
+
+/**
+ * aer_irq - Root Port's ISR
+ * @irq: IRQ assigned to Root Port
+ * @context: pointer to Root Port data structure
+ * @r: pointer struct pt_regs
+ *
+ * Invoked when Root Port detects AER messages.
+ **/
+static irqreturn_t aer_irq(int irq, void *context, struct pt_regs * r)
+{
+       unsigned int status, id;
+       struct pcie_device *pdev = (struct pcie_device *)context;
+       struct aer_rpc *rpc = get_service_data(pdev);
+       int next_prod_idx;
+       unsigned long flags;
+       int pos;
+
+       pos = pci_find_aer_capability(pdev->port);
+       /*
+        * Must lock access to Root Error Status Reg, Root Error ID Reg,
+        * and Root error producer/consumer index
+        */
+       spin_lock_irqsave(&rpc->e_lock, flags);
+
+       /* Read error status */
+       pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
+       if (!(status & ROOT_ERR_STATUS_MASKS)) {
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return IRQ_NONE;
+       }
+
+       /* Read error source and clear error status */
+       pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id);
+       pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
+
+       /* Store error source for later DPC handler */
+       next_prod_idx = rpc->prod_idx + 1;
+       if (next_prod_idx == AER_ERROR_SOURCES_MAX)
+               next_prod_idx = 0;
+       if (next_prod_idx == rpc->cons_idx) {
+               /*
+                * Error Storm Condition - possibly the same error occurred.
+                * Drop the error.
+                */
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return IRQ_HANDLED;
+       }
+       rpc->e_sources[rpc->prod_idx].status =  status;
+       rpc->e_sources[rpc->prod_idx].id = id;
+       rpc->prod_idx = next_prod_idx;
+       spin_unlock_irqrestore(&rpc->e_lock, flags);
+
+       /*  Invoke DPC handler */
+       schedule_work(&rpc->dpc_handler);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * aer_alloc_rpc - allocate Root Port data structure
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when Root Port's AER service is loaded.
+ **/
+static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
+{
+       struct aer_rpc *rpc;
+
+       if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
+               GFP_KERNEL)))
+               return NULL;
+
+       memset(rpc, 0, sizeof(struct aer_rpc));
+       /*
+        * Initialize Root lock access, e_lock, to Root Error Status Reg,
+        * Root Error ID Reg, and Root error producer/consumer index.
+        */
+       rpc->e_lock = SPIN_LOCK_UNLOCKED;
+
+       rpc->rpd = dev;
+       INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev);
+       rpc->prod_idx = rpc->cons_idx = 0;
+       mutex_init(&rpc->rpc_mutex);
+       init_waitqueue_head(&rpc->wait_release);
+
+       /* Use PCIE bus function to store rpc into PCIE device */
+       set_service_data(dev, rpc);
+
+       return rpc;
+}
+
+/**
+ * aer_remove - clean up resources
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when PCI Express bus unloads or AER probe fails.
+ **/
+static void aer_remove(struct pcie_device *dev)
+{
+       struct aer_rpc *rpc = get_service_data(dev);
+
+       if (rpc) {
+               /* If register interrupt service, it must be free. */
+               if (rpc->isr)
+                       free_irq(dev->irq, dev);
+
+               wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+
+               aer_delete_rootport(rpc);
+               set_service_data(dev, NULL);
+       }
+}
+
+/**
+ * aer_probe - initialize resources
+ * @dev: pointer to the pcie_dev data structure
+ * @id: pointer to the service id data structure
+ *
+ * Invoked when PCI Express bus loads AER service driver.
+ **/
+static int __devinit aer_probe (struct pcie_device *dev,
+                               const struct pcie_port_service_id *id )
+{
+       int status;
+       struct aer_rpc *rpc;
+       struct device *device = &dev->device;
+
+       /* Init */
+       if ((status = aer_init(dev)))
+               return status;
+
+       /* Alloc rpc data structure */
+       if (!(rpc = aer_alloc_rpc(dev))) {
+               printk(KERN_DEBUG "%s: Alloc rpc fails on PCIE device[%s]\n",
+                       __FUNCTION__, device->bus_id);
+               aer_remove(dev);
+               return -ENOMEM;
+       }
+
+       /* Request IRQ ISR */
+       if ((status = request_irq(dev->irq, aer_irq, SA_SHIRQ, "aerdrv",
+                               dev))) {
+               printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
+                       __FUNCTION__, device->bus_id);
+               aer_remove(dev);
+               return status;
+       }
+
+       rpc->isr = 1;
+
+       aer_enable_rootport(rpc);
+
+       return status;
+}
+
+/**
+ * aer_root_reset - reset link on Root Port
+ * @dev: pointer to Root Port's pci_dev data structure
+ *
+ * Invoked by Port Bus driver when performing link reset at Root Port.
+ **/
+static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
+{
+       u16 p2p_ctrl;
+       u32 status;
+       int pos;
+
+       pos = pci_find_aer_capability(dev);
+
+       /* Disable Root's interrupt in response to error messages */
+       pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
+
+       /* Assert Secondary Bus Reset */
+       pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl);
+       p2p_ctrl |= PCI_CB_BRIDGE_CTL_CB_RESET;
+       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
+
+       /* De-assert Secondary Bus Reset */
+       p2p_ctrl &= ~PCI_CB_BRIDGE_CTL_CB_RESET;
+       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
+
+       /*
+        * System software must wait for at least 100ms from the end
+        * of a reset of one or more device before it is permitted
+        * to issue Configuration Requests to those devices.
+        */
+       msleep(200);
+       printk(KERN_DEBUG "Complete link reset at Root[%s]\n", dev->dev.bus_id);
+
+       /* Enable Root Port's interrupt in response to error messages */
+       pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
+       pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
+       pci_write_config_dword(dev,
+               pos + PCI_ERR_ROOT_COMMAND,
+               ROOT_PORT_INTR_ON_MESG_MASK);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * aer_error_detected - update severity status
+ * @dev: pointer to Root Port's pci_dev data structure
+ * @error: error severity being notified by port bus
+ *
+ * Invoked by Port Bus driver during error recovery.
+ **/
+static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
+                       enum pci_channel_state error)
+{
+       /* Root Port has no impact. Always recovers. */
+       return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+/**
+ * aer_error_resume - clean up corresponding error status bits
+ * @dev: pointer to Root Port's pci_dev data structure
+ *
+ * Invoked by Port Bus driver during nonfatal recovery.
+ **/
+static void aer_error_resume(struct pci_dev *dev)
+{
+       int pos;
+       u32 status, mask;
+       u16 reg16;
+
+       /* Clean up Root device status */
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+       pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
+
+       /* Clean AER Root Error Status */
+       pos = pci_find_aer_capability(dev);
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+       if (dev->error_state == pci_channel_io_normal)
+               status &= ~mask; /* Clear corresponding nonfatal bits */
+       else
+               status &= mask; /* Clear corresponding fatal bits */
+       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+}
+
+/**
+ * aer_service_init - register AER root service driver
+ *
+ * Invoked when AER root service driver is loaded.
+ **/
+static int __init aer_service_init(void)
+{
+       return pcie_port_service_register(&aerdrv);
+}
+
+/**
+ * aer_service_exit - unregister AER root service driver
+ *
+ * Invoked when AER root service driver is unloaded.
+ **/
+static void __exit aer_service_exit(void)
+{
+       pcie_port_service_unregister(&aerdrv);
+}
+
+module_init(aer_service_init);
+module_exit(aer_service_exit);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
new file mode 100644 (file)
index 0000000..daf0cad
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#ifndef _AERDRV_H_
+#define _AERDRV_H_
+
+#include <linux/pcieport_if.h>
+#include <linux/aer.h>
+
+#define AER_NONFATAL                   0
+#define AER_FATAL                      1
+#define AER_CORRECTABLE                        2
+#define AER_UNCORRECTABLE              4
+#define AER_ERROR_MASK                 0x001fffff
+#define AER_ERROR(d)                   (d & AER_ERROR_MASK)
+
+#define OSC_METHOD_RUN_SUCCESS         0
+#define OSC_METHOD_NOT_SUPPORTED       1
+#define OSC_METHOD_RUN_FAILURE         2
+
+/* Root Error Status Register Bits */
+#define ROOT_ERR_STATUS_MASKS                  0x0f
+
+#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE|   \
+                                       PCI_EXP_RTCTL_SENFEE|   \
+                                       PCI_EXP_RTCTL_SEFEE)
+#define ROOT_PORT_INTR_ON_MESG_MASK    (PCI_ERR_ROOT_CMD_COR_EN|       \
+                                       PCI_ERR_ROOT_CMD_NONFATAL_EN|   \
+                                       PCI_ERR_ROOT_CMD_FATAL_EN)
+#define ERR_COR_ID(d)                  (d & 0xffff)
+#define ERR_UNCOR_ID(d)                        (d >> 16)
+
+#define AER_SUCCESS                    0
+#define AER_UNSUCCESS                  1
+#define AER_ERROR_SOURCES_MAX          100
+
+#define AER_LOG_TLP_MASKS              (PCI_ERR_UNC_POISON_TLP|        \
+                                       PCI_ERR_UNC_ECRC|               \
+                                       PCI_ERR_UNC_UNSUP|              \
+                                       PCI_ERR_UNC_COMP_ABORT|         \
+                                       PCI_ERR_UNC_UNX_COMP|           \
+                                       PCI_ERR_UNC_MALF_TLP)
+
+/* AER Error Info Flags */
+#define AER_TLP_HEADER_VALID_FLAG      0x00000001
+#define AER_MULTI_ERROR_VALID_FLAG     0x00000002
+
+#define ERR_CORRECTABLE_ERROR_MASK     0x000031c1
+#define ERR_UNCORRECTABLE_ERROR_MASK   0x001ff010
+
+struct header_log_regs {
+       unsigned int dw0;
+       unsigned int dw1;
+       unsigned int dw2;
+       unsigned int dw3;
+};
+
+struct aer_err_info {
+       int severity;                   /* 0:NONFATAL | 1:FATAL | 2:COR */
+       int flags;
+       unsigned int status;            /* COR/UNCOR Error Status */
+       struct header_log_regs tlp;     /* TLP Header */
+};
+
+struct aer_err_source {
+       unsigned int status;
+       unsigned int id;
+};
+
+struct aer_rpc {
+       struct pcie_device *rpd;        /* Root Port device */
+       struct work_struct dpc_handler;
+       struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
+       unsigned short prod_idx;        /* Error Producer Index */
+       unsigned short cons_idx;        /* Error Consumer Index */
+       int isr;
+       spinlock_t e_lock;              /*
+                                        * Lock access to Error Status/ID Regs
+                                        * and error producer/consumer index
+                                        */
+       struct mutex rpc_mutex;         /*
+                                        * only one thread could do
+                                        * recovery on the same
+                                        * root port hierachy
+                                        */
+       wait_queue_head_t wait_release;
+};
+
+struct aer_broadcast_data {
+       enum pci_channel_state state;
+       enum pci_ers_result result;
+};
+
+static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
+               enum pci_ers_result new)
+{
+       switch (orig) {
+       case PCI_ERS_RESULT_CAN_RECOVER:
+       case PCI_ERS_RESULT_RECOVERED:
+               orig = new;
+               break;
+       case PCI_ERS_RESULT_DISCONNECT:
+               if (new == PCI_ERS_RESULT_NEED_RESET)
+                       orig = new;
+               break;
+       default:
+               break;
+       }
+
+       return orig;
+}
+
+extern struct bus_type pcie_port_bus_type;
+extern void aer_enable_rootport(struct aer_rpc *rpc);
+extern void aer_delete_rootport(struct aer_rpc *rpc);
+extern int aer_init(struct pcie_device *dev);
+extern void aer_isr(void *context);
+extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
+extern int aer_osc_setup(struct pci_dev *dev);
+
+#endif //_AERDRV_H_
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
new file mode 100644 (file)
index 0000000..fa68e89
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Access ACPI _OSC method
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <linux/delay.h>
+#include "aerdrv.h"
+
+/**
+ * aer_osc_setup - run ACPI _OSC method
+ *
+ * Return:
+ *     Zero if success. Nonzero for otherwise.
+ *
+ * Invoked when PCIE bus loads AER service driver. To avoid conflict with
+ * BIOS AER support requires BIOS to yield AER control to OS native driver.
+ **/
+int aer_osc_setup(struct pci_dev *dev)
+{
+       int retval = OSC_METHOD_RUN_SUCCESS;
+       acpi_status status;
+       acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
+       struct pci_dev *pdev = dev;
+       struct pci_bus *parent;
+
+       while (!handle) {
+               if (!pdev || !pdev->bus->parent)
+                       break;
+               parent = pdev->bus->parent;
+               if (!parent->self)
+                       /* Parent must be a host bridge */
+                       handle = acpi_get_pci_rootbridge_handle(
+                                       pci_domain_nr(parent),
+                                       parent->number);
+               else
+                       handle = DEVICE_ACPI_HANDLE(
+                                       &(parent->self->dev));
+               pdev = parent->self;
+       }
+
+       if (!handle)
+               return OSC_METHOD_NOT_SUPPORTED;
+
+       pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+       status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
+               OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+       if (ACPI_FAILURE(status)) {
+               if (status == AE_SUPPORT)
+                       retval = OSC_METHOD_NOT_SUPPORTED;
+               else
+                       retval = OSC_METHOD_RUN_FAILURE;
+       }
+
+       return retval;
+}
+
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
new file mode 100644 (file)
index 0000000..1c7e660
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv_core.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This file implements the core part of PCI-Express AER. When an pci-express
+ * error is delivered, an error message will be collected and printed to
+ * console, then, an error recovery procedure will be executed by following
+ * the pci error recovery rules.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <linux/delay.h>
+#include "aerdrv.h"
+
+static int forceload;
+module_param(forceload, bool, 0);
+
+#define PCI_CFG_SPACE_SIZE     (0x100)
+int pci_find_aer_capability(struct pci_dev *dev)
+{
+       int pos;
+       u32 reg32 = 0;
+
+       /* Check if it's a pci-express device */
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return 0;
+
+       /* Check if it supports pci-express AER */
+       pos = PCI_CFG_SPACE_SIZE;
+       while (pos) {
+               if (pci_read_config_dword(dev, pos, &reg32))
+                       return 0;
+
+               /* some broken boards return ~0 */
+               if (reg32 == 0xffffffff)
+                       return 0;
+
+               if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
+                       break;
+
+               pos = reg32 >> 20;
+       }
+
+       return pos;
+}
+
+int pci_enable_pcie_error_reporting(struct pci_dev *dev)
+{
+       u16 reg16 = 0;
+       int pos;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
+       reg16 = reg16 |
+               PCI_EXP_DEVCTL_CERE |
+               PCI_EXP_DEVCTL_NFERE |
+               PCI_EXP_DEVCTL_FERE |
+               PCI_EXP_DEVCTL_URRE;
+       pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
+                       reg16);
+       return 0;
+}
+
+int pci_disable_pcie_error_reporting(struct pci_dev *dev)
+{
+       u16 reg16 = 0;
+       int pos;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
+       reg16 = reg16 & ~(PCI_EXP_DEVCTL_CERE |
+                       PCI_EXP_DEVCTL_NFERE |
+                       PCI_EXP_DEVCTL_FERE |
+                       PCI_EXP_DEVCTL_URRE);
+       pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
+                       reg16);
+       return 0;
+}
+
+int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+{
+       int pos;
+       u32 status, mask;
+
+       pos = pci_find_aer_capability(dev);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+       if (dev->error_state == pci_channel_io_normal)
+               status &= ~mask; /* Clear corresponding nonfatal bits */
+       else
+               status &= mask; /* Clear corresponding fatal bits */
+       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+
+       return 0;
+}
+
+static int find_device_iter(struct device *device, void *data)
+{
+       struct pci_dev *dev;
+       u16 id = *(unsigned long *)data;
+       u8 secondary, subordinate, d_bus = id >> 8;
+
+       if (device->bus == &pci_bus_type) {
+               dev = to_pci_dev(device);
+               if (id == ((dev->bus->number << 8) | dev->devfn)) {
+                       /*
+                        * Device ID match
+                        */
+                       *(unsigned long*)data = (unsigned long)device;
+                       return 1;
+               }
+
+               /*
+                * If device is P2P, check if it is an upstream?
+                */
+               if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+                       pci_read_config_byte(dev, PCI_SECONDARY_BUS,
+                               &secondary);
+                       pci_read_config_byte(dev, PCI_SUBORDINATE_BUS,
+                               &subordinate);
+                       if (d_bus >= secondary && d_bus <= subordinate) {
+                               *(unsigned long*)data = (unsigned long)device;
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * find_source_device - search through device hierarchy for source device
+ * @p_dev: pointer to Root Port pci_dev data structure
+ * @id: device ID of agent who sends an error message to this Root Port
+ *
+ * Invoked when error is detected at the Root Port.
+ **/
+static struct device* find_source_device(struct pci_dev *parent, u16 id)
+{
+       struct pci_dev *dev = parent;
+       struct device *device;
+       unsigned long device_addr;
+       int status;
+
+       /* Is Root Port an agent that sends error message? */
+       if (id == ((dev->bus->number << 8) | dev->devfn))
+               return &dev->dev;
+
+       do {
+               device_addr = id;
+               if ((status = device_for_each_child(&dev->dev,
+                       &device_addr, find_device_iter))) {
+                       device = (struct device*)device_addr;
+                       dev = to_pci_dev(device);
+                       if (id == ((dev->bus->number << 8) | dev->devfn))
+                               return device;
+               }
+       }while (status);
+
+       return NULL;
+}
+
+static void report_error_detected(struct pci_dev *dev, void *data)
+{
+       pci_ers_result_t vote;
+       struct pci_error_handlers *err_handler;
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
+
+       dev->error_state = result_data->state;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->error_detected) {
+               if (result_data->state == pci_channel_io_frozen &&
+                       !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
+                       /*
+                        * In case of fatal recovery, if one of down-
+                        * stream device has no driver. We might be
+                        * unable to recover because a later insmod
+                        * of a driver for this device is unaware of
+                        * its hw state.
+                        */
+                       printk(KERN_DEBUG "Device ID[%s] has %s\n",
+                                       dev->dev.bus_id, (dev->driver) ?
+                                       "no AER-aware driver" : "no driver");
+               }
+               return;
+       }
+
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->error_detected(dev, result_data->state);
+       result_data->result = merge_result(result_data->result, vote);
+       return;
+}
+
+static void report_mmio_enabled(struct pci_dev *dev, void *data)
+{
+       pci_ers_result_t vote;
+       struct pci_error_handlers *err_handler;
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->mmio_enabled)
+               return;
+
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->mmio_enabled(dev);
+       result_data->result = merge_result(result_data->result, vote);
+       return;
+}
+
+static void report_slot_reset(struct pci_dev *dev, void *data)
+{
+       pci_ers_result_t vote;
+       struct pci_error_handlers *err_handler;
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->slot_reset)
+               return;
+
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->slot_reset(dev);
+       result_data->result = merge_result(result_data->result, vote);
+       return;
+}
+
+static void report_resume(struct pci_dev *dev, void *data)
+{
+       struct pci_error_handlers *err_handler;
+
+       dev->error_state = pci_channel_io_normal;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->slot_reset)
+               return;
+
+       err_handler = dev->driver->err_handler;
+       err_handler->resume(dev);
+       return;
+}
+
+/**
+ * broadcast_error_message - handle message broadcast to downstream drivers
+ * @device: pointer to from where in a hierarchy message is broadcasted down
+ * @api: callback to be broadcasted
+ * @state: error state
+ *
+ * Invoked during error recovery process. Once being invoked, the content
+ * of error severity will be broadcasted to all downstream drivers in a
+ * hierarchy in question.
+ **/
+static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
+       enum pci_channel_state state,
+       char *error_mesg,
+       void (*cb)(struct pci_dev *, void *))
+{
+       struct aer_broadcast_data result_data;
+
+       printk(KERN_DEBUG "Broadcast %s message\n", error_mesg);
+       result_data.state = state;
+       if (cb == report_error_detected)
+               result_data.result = PCI_ERS_RESULT_CAN_RECOVER;
+       else
+               result_data.result = PCI_ERS_RESULT_RECOVERED;
+
+       if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+               /*
+                * If the error is reported by a bridge, we think this error
+                * is related to the downstream link of the bridge, so we
+                * do error recovery on all subordinates of the bridge instead
+                * of the bridge and clear the error status of the bridge.
+                */
+               if (cb == report_error_detected)
+                       dev->error_state = state;
+               pci_walk_bus(dev->subordinate, cb, &result_data);
+               if (cb == report_resume) {
+                       pci_cleanup_aer_uncorrect_error_status(dev);
+                       dev->error_state = pci_channel_io_normal;
+               }
+       }
+       else {
+               /*
+                * If the error is reported by an end point, we think this
+                * error is related to the upstream link of the end point.
+                */
+               pci_walk_bus(dev->bus, cb, &result_data);
+       }
+
+       return result_data.result;
+}
+
+struct find_aer_service_data {
+       struct pcie_port_service_driver *aer_driver;
+       int is_downstream;
+};
+
+static int find_aer_service_iter(struct device *device, void *data)
+{
+       struct device_driver *driver;
+       struct pcie_port_service_driver *service_driver;
+       struct pcie_device *pcie_dev;
+       struct find_aer_service_data *result;
+
+       result = (struct find_aer_service_data *) data;
+
+       if (device->bus == &pcie_port_bus_type) {
+               pcie_dev = to_pcie_device(device);
+               if (pcie_dev->id.port_type == PCIE_SW_DOWNSTREAM_PORT)
+                       result->is_downstream = 1;
+
+               driver = device->driver;
+               if (driver) {
+                       service_driver = to_service_driver(driver);
+                       if (service_driver->id_table->service_type ==
+                                       PCIE_PORT_SERVICE_AER) {
+                               result->aer_driver = service_driver;
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void find_aer_service(struct pci_dev *dev,
+               struct find_aer_service_data *data)
+{
+       int retval;
+       retval = device_for_each_child(&dev->dev, data, find_aer_service_iter);
+}
+
+static pci_ers_result_t reset_link(struct pcie_device *aerdev,
+               struct pci_dev *dev)
+{
+       struct pci_dev *udev;
+       pci_ers_result_t status;
+       struct find_aer_service_data data;
+
+       if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)
+               udev = dev;
+       else
+               udev= dev->bus->self;
+
+       data.is_downstream = 0;
+       data.aer_driver = NULL;
+       find_aer_service(udev, &data);
+
+       /*
+        * Use the aer driver of the error agent firstly.
+        * If it hasn't the aer driver, use the root port's
+        */
+       if (!data.aer_driver || !data.aer_driver->reset_link) {
+               if (data.is_downstream &&
+                       aerdev->device.driver &&
+                       to_service_driver(aerdev->device.driver)->reset_link) {
+                       data.aer_driver =
+                               to_service_driver(aerdev->device.driver);
+               } else {
+                       printk(KERN_DEBUG "No link-reset support to Device ID"
+                               "[%s]\n",
+                               dev->dev.bus_id);
+                       return PCI_ERS_RESULT_DISCONNECT;
+               }
+       }
+
+       status = data.aer_driver->reset_link(udev);
+       if (status != PCI_ERS_RESULT_RECOVERED) {
+               printk(KERN_DEBUG "Link reset at upstream Device ID"
+                       "[%s] failed\n",
+                       udev->dev.bus_id);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       return status;
+}
+
+/**
+ * do_recovery - handle nonfatal/fatal error recovery process
+ * @aerdev: pointer to a pcie_device data structure of root port
+ * @dev: pointer to a pci_dev data structure of agent detecting an error
+ * @severity: error severity type
+ *
+ * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
+ * error detected message to all downstream drivers within a hierarchy in
+ * question and return the returned code.
+ **/
+static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
+               struct pci_dev *dev,
+               int severity)
+{
+       pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
+       enum pci_channel_state state;
+
+       if (severity == AER_FATAL)
+               state = pci_channel_io_frozen;
+       else
+               state = pci_channel_io_normal;
+
+       status = broadcast_error_message(dev,
+                       state,
+                       "error_detected",
+                       report_error_detected);
+
+       if (severity == AER_FATAL) {
+               result = reset_link(aerdev, dev);
+               if (result != PCI_ERS_RESULT_RECOVERED) {
+                       /* TODO: Should panic here? */
+                       return result;
+               }
+       }
+
+       if (status == PCI_ERS_RESULT_CAN_RECOVER)
+               status = broadcast_error_message(dev,
+                               state,
+                               "mmio_enabled",
+                               report_mmio_enabled);
+
+       if (status == PCI_ERS_RESULT_NEED_RESET) {
+               /*
+                * TODO: Should call platform-specific
+                * functions to reset slot before calling
+                * drivers' slot_reset callbacks?
+                */
+               status = broadcast_error_message(dev,
+                               state,
+                               "slot_reset",
+                               report_slot_reset);
+       }
+
+       if (status == PCI_ERS_RESULT_RECOVERED)
+               broadcast_error_message(dev,
+                               state,
+                               "resume",
+                               report_resume);
+
+       return status;
+}
+
+/**
+ * handle_error_source - handle logging error into an event log
+ * @aerdev: pointer to pcie_device data structure of the root port
+ * @dev: pointer to pci_dev data structure of error source device
+ * @info: comprehensive error information
+ *
+ * Invoked when an error being detected by Root Port.
+ **/
+static void handle_error_source(struct pcie_device * aerdev,
+       struct pci_dev *dev,
+       struct aer_err_info info)
+{
+       pci_ers_result_t status = 0;
+       int pos;
+
+       if (info.severity == AER_CORRECTABLE) {
+               /*
+                * Correctable error does not need software intevention.
+                * No need to go through error recovery process.
+                */
+               pos = pci_find_aer_capability(dev);
+               if (pos)
+                       pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
+                                       info.status);
+       } else {
+               status = do_recovery(aerdev, dev, info.severity);
+               if (status == PCI_ERS_RESULT_RECOVERED) {
+                       printk(KERN_DEBUG "AER driver successfully recovered\n");
+               } else {
+                       /* TODO: Should kernel panic here? */
+                       printk(KERN_DEBUG "AER driver didn't recover\n");
+               }
+       }
+}
+
+/**
+ * aer_enable_rootport - enable Root Port's interrupts when receiving messages
+ * @rpc: pointer to a Root Port data structure
+ *
+ * Invoked when PCIE bus loads AER service driver.
+ **/
+void aer_enable_rootport(struct aer_rpc *rpc)
+{
+       struct pci_dev *pdev = rpc->rpd->port;
+       int pos, aer_pos;
+       u16 reg16;
+       u32 reg32;
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       /* Clear PCIE Capability's Device Status */
+       pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
+       pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
+
+       /* Disable system error generation in response to error messages */
+       pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, &reg16);
+       reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
+       pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
+
+       aer_pos = pci_find_aer_capability(pdev);
+       /* Clear error status */
+       pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
+       pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
+       pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
+       pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
+       pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
+       pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
+
+       /* Enable Root Port device reporting error itself */
+       pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, &reg16);
+       reg16 = reg16 |
+               PCI_EXP_DEVCTL_CERE |
+               PCI_EXP_DEVCTL_NFERE |
+               PCI_EXP_DEVCTL_FERE |
+               PCI_EXP_DEVCTL_URRE;
+       pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL,
+               reg16);
+
+       /* Enable Root Port's interrupt in response to error messages */
+       pci_write_config_dword(pdev,
+               aer_pos + PCI_ERR_ROOT_COMMAND,
+               ROOT_PORT_INTR_ON_MESG_MASK);
+}
+
+/**
+ * disable_root_aer - disable Root Port's interrupts when receiving messages
+ * @rpc: pointer to a Root Port data structure
+ *
+ * Invoked when PCIE bus unloads AER service driver.
+ **/
+static void disable_root_aer(struct aer_rpc *rpc)
+{
+       struct pci_dev *pdev = rpc->rpd->port;
+       u32 reg32;
+       int pos;
+
+       pos = pci_find_aer_capability(pdev);
+       /* Disable Root's interrupt in response to error messages */
+       pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
+
+       /* Clear Root's error status reg */
+       pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
+       pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
+}
+
+/**
+ * get_e_source - retrieve an error source
+ * @rpc: pointer to the root port which holds an error
+ *
+ * Invoked by DPC handler to consume an error.
+ **/
+static struct aer_err_source* get_e_source(struct aer_rpc *rpc)
+{
+       struct aer_err_source *e_source;
+       unsigned long flags;
+
+       /* Lock access to Root error producer/consumer index */
+       spin_lock_irqsave(&rpc->e_lock, flags);
+       if (rpc->prod_idx == rpc->cons_idx) {
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return NULL;
+       }
+       e_source = &rpc->e_sources[rpc->cons_idx];
+       rpc->cons_idx++;
+       if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
+               rpc->cons_idx = 0;
+       spin_unlock_irqrestore(&rpc->e_lock, flags);
+
+       return e_source;
+}
+
+static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
+{
+       int pos;
+
+       pos = pci_find_aer_capability(dev);
+
+       /* The device might not support AER */
+       if (!pos)
+               return AER_SUCCESS;
+
+       if (info->severity == AER_CORRECTABLE) {
+               pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
+                       &info->status);
+               if (!(info->status & ERR_CORRECTABLE_ERROR_MASK))
+                       return AER_UNSUCCESS;
+       } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
+               info->severity == AER_NONFATAL) {
+
+               /* Link is still healthy for IO reads */
+               pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+                       &info->status);
+               if (!(info->status & ERR_UNCORRECTABLE_ERROR_MASK))
+                       return AER_UNSUCCESS;
+
+               if (info->status & AER_LOG_TLP_MASKS) {
+                       info->flags |= AER_TLP_HEADER_VALID_FLAG;
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
+               }
+       }
+
+       return AER_SUCCESS;
+}
+
+/**
+ * aer_isr_one_error - consume an error detected by root port
+ * @p_device: pointer to error root port service device
+ * @e_src: pointer to an error source
+ **/
+static void aer_isr_one_error(struct pcie_device *p_device,
+               struct aer_err_source *e_src)
+{
+       struct device *s_device;
+       struct aer_err_info e_info = {0, 0, 0,};
+       int i;
+       u16 id;
+
+       /*
+        * There is a possibility that both correctable error and
+        * uncorrectable error being logged. Report correctable error first.
+        */
+       for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) {
+               if (i > 4)
+                       break;
+               if (!(e_src->status & i))
+                       continue;
+
+               /* Init comprehensive error information */
+               if (i & PCI_ERR_ROOT_COR_RCV) {
+                       id = ERR_COR_ID(e_src->id);
+                       e_info.severity = AER_CORRECTABLE;
+               } else {
+                       id = ERR_UNCOR_ID(e_src->id);
+                       e_info.severity = ((e_src->status >> 6) & 1);
+               }
+               if (e_src->status &
+                       (PCI_ERR_ROOT_MULTI_COR_RCV |
+                        PCI_ERR_ROOT_MULTI_UNCOR_RCV))
+                       e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
+               if (!(s_device = find_source_device(p_device->port, id))) {
+                       printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
+                               __FUNCTION__, id);
+                       continue;
+               }
+               if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
+                               AER_SUCCESS) {
+                       aer_print_error(to_pci_dev(s_device), &e_info);
+                       handle_error_source(p_device,
+                               to_pci_dev(s_device),
+                               e_info);
+               }
+       }
+}
+
+/**
+ * aer_isr - consume errors detected by root port
+ * @context: pointer to a private data of pcie device
+ *
+ * Invoked, as DPC, when root port records new detected error
+ **/
+void aer_isr(void *context)
+{
+       struct pcie_device *p_device = (struct pcie_device *) context;
+       struct aer_rpc *rpc = get_service_data(p_device);
+       struct aer_err_source *e_src;
+
+       mutex_lock(&rpc->rpc_mutex);
+       e_src = get_e_source(rpc);
+       while (e_src) {
+               aer_isr_one_error(p_device, e_src);
+               e_src = get_e_source(rpc);
+       }
+       mutex_unlock(&rpc->rpc_mutex);
+
+       wake_up(&rpc->wait_release);
+}
+
+/**
+ * aer_delete_rootport - disable root port aer and delete service data
+ * @rpc: pointer to a root port device being deleted
+ *
+ * Invoked when AER service unloaded on a specific Root Port
+ **/
+void aer_delete_rootport(struct aer_rpc *rpc)
+{
+       /* Disable root port AER itself */
+       disable_root_aer(rpc);
+
+       kfree(rpc);
+}
+
+/**
+ * aer_init - provide AER initialization
+ * @dev: pointer to AER pcie device
+ *
+ * Invoked when AER service driver is loaded.
+ **/
+int aer_init(struct pcie_device *dev)
+{
+       int status;
+
+       /* Run _OSC Method */
+       status = aer_osc_setup(dev->port);
+
+       if(status != OSC_METHOD_RUN_SUCCESS) {
+               printk(KERN_DEBUG "%s: AER service init fails - %s\n",
+               __FUNCTION__,
+               (status == OSC_METHOD_NOT_SUPPORTED) ?
+                       "No ACPI _OSC support" : "Run ACPI _OSC fails");
+
+               if (!forceload)
+                       return status;
+       }
+
+       return AER_SUCCESS;
+}
+
+EXPORT_SYMBOL_GPL(pci_find_aer_capability);
+EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
+EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
+EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
new file mode 100644 (file)
index 0000000..3933d4f
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv_errprint.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Format error messages and print them to console.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+
+#include "aerdrv.h"
+
+#define AER_AGENT_RECEIVER             0
+#define AER_AGENT_REQUESTER            1
+#define AER_AGENT_COMPLETER            2
+#define AER_AGENT_TRANSMITTER          3
+
+#define AER_AGENT_REQUESTER_MASK       (PCI_ERR_UNC_COMP_TIME| \
+                                       PCI_ERR_UNC_UNSUP)
+
+#define AER_AGENT_COMPLETER_MASK       PCI_ERR_UNC_COMP_ABORT
+
+#define AER_AGENT_TRANSMITTER_MASK(t, e) (e & (PCI_ERR_COR_REP_ROLL| \
+       ((t == AER_CORRECTABLE) ? PCI_ERR_COR_REP_TIMER: 0)))
+
+#define AER_GET_AGENT(t, e)                                            \
+       ((e & AER_AGENT_COMPLETER_MASK) ? AER_AGENT_COMPLETER :         \
+       (e & AER_AGENT_REQUESTER_MASK) ? AER_AGENT_REQUESTER :          \
+       (AER_AGENT_TRANSMITTER_MASK(t, e)) ? AER_AGENT_TRANSMITTER :    \
+       AER_AGENT_RECEIVER)
+
+#define AER_PHYSICAL_LAYER_ERROR_MASK  PCI_ERR_COR_RCVR
+#define AER_DATA_LINK_LAYER_ERROR_MASK(t, e)   \
+               (PCI_ERR_UNC_DLP|               \
+               PCI_ERR_COR_BAD_TLP|            \
+               PCI_ERR_COR_BAD_DLLP|           \
+               PCI_ERR_COR_REP_ROLL|           \
+               ((t == AER_CORRECTABLE) ?       \
+               PCI_ERR_COR_REP_TIMER: 0))
+
+#define AER_PHYSICAL_LAYER_ERROR       0
+#define AER_DATA_LINK_LAYER_ERROR      1
+#define AER_TRANSACTION_LAYER_ERROR    2
+
+#define AER_GET_LAYER_ERROR(t, e)                              \
+       ((e & AER_PHYSICAL_LAYER_ERROR_MASK) ?                  \
+       AER_PHYSICAL_LAYER_ERROR :                              \
+       (e & AER_DATA_LINK_LAYER_ERROR_MASK(t, e)) ?            \
+               AER_DATA_LINK_LAYER_ERROR :                     \
+               AER_TRANSACTION_LAYER_ERROR)
+
+/*
+ * AER error strings
+ */
+static char* aer_error_severity_string[] = {
+       "Uncorrected (Non-Fatal)",
+       "Uncorrected (Fatal)",
+       "Corrected"
+};
+
+static char* aer_error_layer[] = {
+       "Physical Layer",
+       "Data Link Layer",
+       "Transaction Layer"
+};
+static char* aer_correctable_error_string[] = {
+       "Receiver Error        ",       /* Bit Position 0       */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Bad TLP               ",       /* Bit Position 6       */
+       "Bad DLLP              ",       /* Bit Position 7       */
+       "RELAY_NUM Rollover    ",       /* Bit Position 8       */
+       NULL,
+       NULL,
+       NULL,
+       "Replay Timer Timeout  ",       /* Bit Position 12      */
+       "Advisory Non-Fatal    ",       /* Bit Position 13      */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+static char* aer_uncorrectable_error_string[] = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Data Link Protocol    ",       /* Bit Position 4       */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Poisoned TLP          ",       /* Bit Position 12      */
+       "Flow Control Protocol ",       /* Bit Position 13      */
+       "Completion Timeout    ",       /* Bit Position 14      */
+       "Completer Abort       ",       /* Bit Position 15      */
+       "Unexpected Completion ",       /* Bit Position 16      */
+       "Receiver Overflow     ",       /* Bit Position 17      */
+       "Malformed TLP         ",       /* Bit Position 18      */
+       "ECRC                  ",       /* Bit Position 19      */
+       "Unsupported Request   ",       /* Bit Position 20      */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+static char* aer_agent_string[] = {
+       "Receiver ID",
+       "Requester ID",
+       "Completer ID",
+       "Transmitter ID"
+};
+
+static char * aer_get_error_source_name(int severity,
+                       unsigned int status,
+                       char errmsg_buff[])
+{
+       int i;
+       char * errmsg = NULL;
+
+       for (i = 0; i < 32; i++) {
+               if (!(status & (1 << i)))
+                       continue;
+
+               if (severity == AER_CORRECTABLE)
+                       errmsg = aer_correctable_error_string[i];
+               else
+                       errmsg = aer_uncorrectable_error_string[i];
+
+               if (!errmsg) {
+                       sprintf(errmsg_buff, "Unknown Error Bit %2d  ", i);
+                       errmsg = errmsg_buff;
+               }
+
+               break;
+       }
+
+       return errmsg;
+}
+
+static DEFINE_SPINLOCK(logbuf_lock);
+static char errmsg_buff[100];
+void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
+{
+       char * errmsg;
+       int err_layer, agent;
+       char * loglevel;
+
+       if (info->severity == AER_CORRECTABLE)
+               loglevel = KERN_WARNING;
+       else
+               loglevel = KERN_ERR;
+
+       printk("%s+------ PCI-Express Device Error ------+\n", loglevel);
+       printk("%sError Severity\t\t: %s\n", loglevel,
+               aer_error_severity_string[info->severity]);
+
+       if ( info->status == 0) {
+               printk("%sPCIE Bus Error type\t: (Unaccessible)\n", loglevel);
+               printk("%sUnaccessible Received\t: %s\n", loglevel,
+                       info->flags & AER_MULTI_ERROR_VALID_FLAG ?
+                               "Multiple" : "First");
+               printk("%sUnregistered Agent ID\t: %04x\n", loglevel,
+                       (dev->bus->number << 8) | dev->devfn);
+       } else {
+               err_layer = AER_GET_LAYER_ERROR(info->severity, info->status);
+               printk("%sPCIE Bus Error type\t: %s\n", loglevel,
+                       aer_error_layer[err_layer]);
+
+               spin_lock(&logbuf_lock);
+               errmsg = aer_get_error_source_name(info->severity,
+                               info->status,
+                               errmsg_buff);
+               printk("%s%s\t: %s\n", loglevel, errmsg,
+                       info->flags & AER_MULTI_ERROR_VALID_FLAG ?
+                               "Multiple" : "First");
+               spin_unlock(&logbuf_lock);
+
+               agent = AER_GET_AGENT(info->severity, info->status);
+               printk("%s%s\t\t: %04x\n", loglevel,
+                       aer_agent_string[agent],
+                       (dev->bus->number << 8) | dev->devfn);
+
+               printk("%sVendorID=%04xh, DeviceID=%04xh,"
+                       " Bus=%02xh, Device=%02xh, Function=%02xh\n",
+                       loglevel,
+                       dev->vendor,
+                       dev->device,
+                       dev->bus->number,
+                       PCI_SLOT(dev->devfn),
+                       PCI_FUNC(dev->devfn));
+
+               if (info->flags & AER_TLP_HEADER_VALID_FLAG) {
+                       unsigned char *tlp = (unsigned char *) &info->tlp;
+                       printk("%sTLB Header:\n", loglevel);
+                       printk("%s%02x%02x%02x%02x %02x%02x%02x%02x"
+                               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
+                               loglevel,
+                               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+                               *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
+                               *(tlp + 11), *(tlp + 10), *(tlp + 9),
+                               *(tlp + 8), *(tlp + 15), *(tlp + 14),
+                               *(tlp + 13), *(tlp + 12));
+               }
+       }
+}
+
index 1d317d22ee892f0dd17efc2b4814c9a9e642a4a1..67fcd176babdb8182242d9d038f5b665364654d6 100644 (file)
@@ -39,7 +39,7 @@ extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state);
 extern int pcie_port_device_resume(struct pci_dev *dev);
 #endif
 extern void pcie_port_device_remove(struct pci_dev *dev);
-extern void pcie_port_bus_register(void);
+extern int pcie_port_bus_register(void);
 extern void pcie_port_bus_unregister(void);
 
 #endif /* _PORTDRV_H_ */
index 3e84b501e6a419ea2b7e28452983c36a8a127bff..3f0976868eda656c9a2441caae804c96f9cc3fac 100644 (file)
@@ -24,6 +24,7 @@ struct bus_type pcie_port_bus_type = {
        .suspend        = pcie_port_bus_suspend,
        .resume         = pcie_port_bus_resume, 
 };
+EXPORT_SYMBOL_GPL(pcie_port_bus_type);
 
 static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
 {
index 55c66226786887e27640285d6167980c2df155aa..bd6615b4d40eb7546521a41898b39bd3a0da47d1 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
  */
 
+#include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -339,8 +340,7 @@ static int suspend_iter(struct device *dev, void *data)
 
 int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
 {
-       device_for_each_child(&dev->dev, &state, suspend_iter);
-       return 0;
+       return device_for_each_child(&dev->dev, &state, suspend_iter);
 }
 
 static int resume_iter(struct device *dev, void *data)
@@ -358,8 +358,7 @@ static int resume_iter(struct device *dev, void *data)
 
 int pcie_port_device_resume(struct pci_dev *dev)
 {
-       device_for_each_child(&dev->dev, NULL, resume_iter);
-       return 0;
+       return device_for_each_child(&dev->dev, NULL, resume_iter);
 }
 #endif
 
@@ -402,9 +401,9 @@ void pcie_port_device_remove(struct pci_dev *dev)
                pci_disable_msi(dev);
 }
 
-void pcie_port_bus_register(void)
+int __must_check pcie_port_bus_register(void)
 {
-       bus_register(&pcie_port_bus_type);
+       return bus_register(&pcie_port_bus_type);
 }
 
 void pcie_port_bus_unregister(void)
index 478d0d28f7ad1e6b573e5e3c3a26f37b9dc1e557..037690e08f5f023a0e012806efbe9627b2450c7c 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/pcieport_if.h>
+#include <linux/aer.h>
 
 #include "portdrv.h"
+#include "aer/aerdrv.h"
 
 /*
  * Version Information
@@ -30,6 +32,43 @@ MODULE_LICENSE("GPL");
 /* global data */
 static const char device_name[] = "pcieport-driver";
 
+static int pcie_portdrv_save_config(struct pci_dev *dev)
+{
+       return pci_save_state(dev);
+}
+
+#ifdef CONFIG_PM
+static int pcie_portdrv_restore_config(struct pci_dev *dev)
+{
+       int retval;
+
+       pci_restore_state(dev);
+       retval = pci_enable_device(dev);
+       if (retval)
+               return retval;
+       pci_set_master(dev);
+       return 0;
+}
+
+static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       int ret = pcie_port_device_suspend(dev, state);
+
+       if (!ret)
+               ret = pcie_portdrv_save_config(dev);
+       return ret;
+}
+
+static int pcie_portdrv_resume(struct pci_dev *dev)
+{
+       pcie_portdrv_restore_config(dev);
+       return pcie_port_device_resume(dev);
+}
+#else
+#define pcie_portdrv_suspend NULL
+#define pcie_portdrv_resume NULL
+#endif
+
 /*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
@@ -61,6 +100,10 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
                return -ENOMEM;
        }
 
+       pcie_portdrv_save_config(dev);
+
+       pci_enable_pcie_error_reporting(dev);
+
        return 0;
 }
 
@@ -70,39 +113,151 @@ static void pcie_portdrv_remove (struct pci_dev *dev)
        kfree(pci_get_drvdata(dev));
 }
 
-#ifdef CONFIG_PM
-static int pcie_portdrv_save_config(struct pci_dev *dev)
+static int error_detected_iter(struct device *device, void *data)
 {
-       return pci_save_state(dev);
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+       struct aer_broadcast_data *result_data;
+       pci_ers_result_t status;
+
+       result_data = (struct aer_broadcast_data *) data;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (!driver ||
+                       !driver->err_handler ||
+                       !driver->err_handler->error_detected)
+                       return 0;
+
+               pcie_device = to_pcie_device(device);
+
+               /* Forward error detected message to service drivers */
+               status = driver->err_handler->error_detected(
+                       pcie_device->port,
+                       result_data->state);
+               result_data->result =
+                       merge_result(result_data->result, status);
+       }
+
+       return 0;
 }
 
-static int pcie_portdrv_restore_config(struct pci_dev *dev)
+static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
+                                       enum pci_channel_state error)
 {
+       struct aer_broadcast_data result_data =
+                       {error, PCI_ERS_RESULT_CAN_RECOVER};
        int retval;
 
-       pci_restore_state(dev);
-       retval = pci_enable_device(dev);
-       if (retval)
-               return retval;
-       pci_set_master(dev);
+       /* can not fail */
+       retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
+
+       return result_data.result;
+}
+
+static int mmio_enabled_iter(struct device *device, void *data)
+{
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+       pci_ers_result_t status, *result;
+
+       result = (pci_ers_result_t *) data;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (driver &&
+                       driver->err_handler &&
+                       driver->err_handler->mmio_enabled) {
+                       pcie_device = to_pcie_device(device);
+
+                       /* Forward error message to service drivers */
+                       status = driver->err_handler->mmio_enabled(
+                                       pcie_device->port);
+                       *result = merge_result(*result, status);
+               }
+       }
+
        return 0;
 }
 
-static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
+static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
 {
-       int ret = pcie_port_device_suspend(dev, state);
+       pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
+       int retval;
 
-       if (!ret)
-               ret = pcie_portdrv_save_config(dev);
-       return ret;
+       /* get true return value from &status */
+       retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
+       return status;
 }
 
-static int pcie_portdrv_resume (struct pci_dev *dev)
+static int slot_reset_iter(struct device *device, void *data)
 {
-       pcie_portdrv_restore_config(dev);
-       return pcie_port_device_resume(dev);
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+       pci_ers_result_t status, *result;
+
+       result = (pci_ers_result_t *) data;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (driver &&
+                       driver->err_handler &&
+                       driver->err_handler->slot_reset) {
+                       pcie_device = to_pcie_device(device);
+
+                       /* Forward error message to service drivers */
+                       status = driver->err_handler->slot_reset(
+                                       pcie_device->port);
+                       *result = merge_result(*result, status);
+               }
+       }
+
+       return 0;
+}
+
+static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
+{
+       pci_ers_result_t status;
+       int retval;
+
+       /* If fatal, restore cfg space for possible link reset at upstream */
+       if (dev->error_state == pci_channel_io_frozen) {
+               pcie_portdrv_restore_config(dev);
+               pci_enable_pcie_error_reporting(dev);
+       }
+
+       /* get true return value from &status */
+       retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
+
+       return status;
+}
+
+static int resume_iter(struct device *device, void *data)
+{
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (driver &&
+                       driver->err_handler &&
+                       driver->err_handler->resume) {
+                       pcie_device = to_pcie_device(device);
+
+                       /* Forward error message to service drivers */
+                       driver->err_handler->resume(pcie_device->port);
+               }
+       }
+
+       return 0;
+}
+
+static void pcie_portdrv_err_resume(struct pci_dev *dev)
+{
+       int retval;
+       /* nothing to do with error value, if it ever happens */
+       retval = device_for_each_child(&dev->dev, NULL, resume_iter);
 }
-#endif
 
 /*
  * LINUX Device Driver Model
@@ -114,6 +269,13 @@ static const struct pci_device_id port_pci_ids[] = { {
 };
 MODULE_DEVICE_TABLE(pci, port_pci_ids);
 
+static struct pci_error_handlers pcie_portdrv_err_handler = {
+               .error_detected = pcie_portdrv_error_detected,
+               .mmio_enabled = pcie_portdrv_mmio_enabled,
+               .slot_reset = pcie_portdrv_slot_reset,
+               .resume = pcie_portdrv_err_resume,
+};
+
 static struct pci_driver pcie_portdrv = {
        .name           = (char *)device_name,
        .id_table       = &port_pci_ids[0],
@@ -121,20 +283,25 @@ static struct pci_driver pcie_portdrv = {
        .probe          = pcie_portdrv_probe,
        .remove         = pcie_portdrv_remove,
 
-#ifdef CONFIG_PM
        .suspend        = pcie_portdrv_suspend,
        .resume         = pcie_portdrv_resume,
-#endif /* PM */
+
+       .err_handler    = &pcie_portdrv_err_handler,
 };
 
 static int __init pcie_portdrv_init(void)
 {
-       int retval = 0;
+       int retval;
 
-       pcie_port_bus_register();
+       retval = pcie_port_bus_register();
+       if (retval) {
+               printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
+               goto out;
+       }
        retval = pci_register_driver(&pcie_portdrv);
        if (retval)
                pcie_port_bus_unregister();
+ out:
        return retval;
 }
 
index c5a58d1c6c1c14f266d5d45d8f980e9531f37db0..a3b0a5eb5054fefcc0e76e72b838fac1146fd310 100644 (file)
@@ -339,6 +339,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 {
        struct pci_bus *child;
        int i;
+       int retval;
 
        /*
         * Allocate a new bus, and inherit stuff from the parent..
@@ -356,8 +357,13 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 
        child->class_dev.class = &pcibus_class;
        sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
-       class_device_register(&child->class_dev);
-       class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity);
+       retval = class_device_register(&child->class_dev);
+       if (retval)
+               goto error_register;
+       retval = class_device_create_file(&child->class_dev,
+                                         &class_device_attr_cpuaffinity);
+       if (retval)
+               goto error_file_create;
 
        /*
         * Set up the primary, secondary and subordinate
@@ -375,6 +381,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
        bridge->subordinate = child;
 
        return child;
+
+error_file_create:
+       class_device_unregister(&child->class_dev);
+error_register:
+       kfree(child);
+       return NULL;
 }
 
 struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
index def78a2a7c156a2b7ef40041ca7a2558a8ac0a6b..23b599d6a9d540db8b2727533f74ffcd7e72f06d 100644 (file)
@@ -93,8 +93,21 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev)
                pci_pci_problems |= PCIPCI_FAIL;
        }
 }
+
+static void __devinit quirk_nopciamd(struct pci_dev *dev)
+{
+       u8 rev;
+       pci_read_config_byte(dev, 0x08, &rev);
+       if (rev == 0x13) {
+               /* Erratum 24 */
+               printk(KERN_INFO "Chipset erratum: Disabling direct PCI/AGP transfers.\n");
+               pci_pci_problems |= PCIAGP_FAIL;
+       }
+}
+
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5597,          quirk_nopcipci );
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_496,           quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_8151_0,       quirk_nopciamd );
 
 /*
  *     Triton requires workarounds to be used by the drivers
@@ -555,7 +568,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,  PCI_DEVICE_ID_VIA_8237,         quirk_via_vt
  * is currently marked NoFix
  *
  * We have multiple reports of hangs with this chipset that went away with
- * noapic specified. For the moment we assume its the errata. We may be wrong
+ * noapic specified. For the moment we assume it's the erratum. We may be wrong
  * of course. However the advice is demonstrably good even if so..
  */
 static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
@@ -564,7 +577,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 
        pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
        if (rev >= 0x02) {
-               printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
+               printk(KERN_WARNING "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
                printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
        }
 }
@@ -577,8 +590,6 @@ static void __init quirk_ioapic_rmw(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_ANY_ID,                     quirk_ioapic_rmw );
 
-int pci_msi_quirk;
-
 #define AMD8131_revA0        0x01
 #define AMD8131_revB0        0x11
 #define AMD8131_MISC         0x40
@@ -587,12 +598,6 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
 { 
         unsigned char revid, tmp;
         
-       if (dev->subordinate) {
-               printk(KERN_WARNING "PCI: MSI quirk detected. "
-                      "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n");
-               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
-       }
-
         if (nr_ioapics == 0) 
                 return;
 
@@ -605,13 +610,6 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
         }
 } 
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
-
-static void __init quirk_svw_msi(struct pci_dev *dev)
-{
-       pci_msi_quirk = 1;
-       printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi );
 #endif /* CONFIG_X86_IO_APIC */
 
 
@@ -1690,6 +1688,95 @@ static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
                        quirk_nvidia_ck804_pcie_aer_ext_cap);
 
+#ifdef CONFIG_PCI_MSI
+/* To disable MSI globally */
+int pci_msi_quirk;
+
+/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely
+ * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
+ * some other busses controlled by the chipset even if Linux is not aware of it.
+ * Instead of setting the flag on all busses in the machine, simply disable MSI
+ * globally.
+ */
+static void __init quirk_svw_msi(struct pci_dev *dev)
+{
+       pci_msi_quirk = 1;
+       printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi);
+
+/* Disable MSI on chipsets that are known to not support it */
+static void __devinit quirk_disable_msi(struct pci_dev *dev)
+{
+       if (dev->subordinate) {
+               printk(KERN_WARNING "PCI: MSI quirk detected. "
+                      "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n",
+                      pci_name(dev));
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
+
+/* Go through the list of Hypertransport capabilities and
+ * return 1 if a HT MSI capability is found and enabled */
+static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
+{
+       u8 pos;
+       int ttl;
+       for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48;
+            pos && ttl;
+            pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) {
+               u32 cap_hdr;
+               /* MSI mapping section according to Hypertransport spec */
+               if (pci_read_config_dword(dev, pos, &cap_hdr) == 0
+                   && (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) {
+                       printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n",
+                              pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled");
+                       return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */
+               }
+       }
+       return 0;
+}
+
+/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */
+static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
+{
+       if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
+               printk(KERN_WARNING "PCI: MSI quirk detected. "
+                      "MSI disabled on chipset %s.\n",
+                      pci_name(dev));
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
+                       quirk_msi_ht_cap);
+
+/* The nVidia CK804 chipset may have 2 HT MSI mappings.
+ * MSI are supported if the MSI capability set in any of these mappings.
+ */
+static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
+{
+       struct pci_dev *pdev;
+
+       if (!dev->subordinate)
+               return;
+
+       /* check HT MSI cap on this chipset and the root one.
+        * a single one having MSI is enough to be sure that MSI are supported.
+        */
+       pdev = pci_find_slot(dev->bus->number, 0);
+       if (dev->subordinate && !msi_ht_cap_enabled(dev)
+           && !msi_ht_cap_enabled(pdev)) {
+               printk(KERN_WARNING "PCI: MSI quirk detected. "
+                      "MSI disabled on chipset %s.\n",
+                      pci_name(dev));
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
+                       quirk_nvidia_ck804_msi_ht_cap);
+#endif /* CONFIG_PCI_MSI */
+
 EXPORT_SYMBOL(pcie_mch_quirk);
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pci_fixup_device);
index 99ffbd478b29c5ffd74d4593ddab6625b2b7fc9d..430281b2e9212400af4b8bf3dd9aa1fa72c41855 100644 (file)
@@ -16,8 +16,11 @@ static void pci_free_resources(struct pci_dev *dev)
        }
 }
 
-static void pci_destroy_dev(struct pci_dev *dev)
+static void pci_stop_dev(struct pci_dev *dev)
 {
+       if (!dev->global_list.next)
+               return;
+
        if (!list_empty(&dev->global_list)) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
@@ -27,6 +30,11 @@ static void pci_destroy_dev(struct pci_dev *dev)
                dev->global_list.next = dev->global_list.prev = NULL;
                up_write(&pci_bus_sem);
        }
+}
+
+static void pci_destroy_dev(struct pci_dev *dev)
+{
+       pci_stop_dev(dev);
 
        /* Remove the device from the device lists, and prevent any further
         * list accesses from this device */
@@ -119,5 +127,32 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
        }
 }
 
+static void pci_stop_bus_devices(struct pci_bus *bus)
+{
+       struct list_head *l, *n;
+
+       list_for_each_safe(l, n, &bus->devices) {
+               struct pci_dev *dev = pci_dev_b(l);
+               pci_stop_bus_device(dev);
+       }
+}
+
+/**
+ * pci_stop_bus_device - stop a PCI device and any children
+ * @dev: the device to stop
+ *
+ * Stop a PCI device (detach the driver, remove from the global list
+ * and so on). This also stop any subordinate buses and children in a
+ * depth-first manner.
+ */
+void pci_stop_bus_device(struct pci_dev *dev)
+{
+       if (dev->subordinate)
+               pci_stop_bus_devices(dev->subordinate);
+
+       pci_stop_dev(dev);
+}
+
 EXPORT_SYMBOL(pci_remove_bus_device);
 EXPORT_SYMBOL(pci_remove_behind_bridge);
+EXPORT_SYMBOL_GPL(pci_stop_bus_device);
index 47c1071ad84ea06b057faac42e6ea60aeb87c5fe..54404917be9a5ebbaaa77d694d118eba1298a7d3 100644 (file)
@@ -55,12 +55,19 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
        list_for_each_entry(dev, &bus->devices, bus_list) {
                u16 class = dev->class >> 8;
 
-               /* Don't touch classless devices or host bridges or ioapics.  */
+               /* Don't touch classless devices or host bridges. */
                if (class == PCI_CLASS_NOT_DEFINED ||
-                   class == PCI_CLASS_BRIDGE_HOST ||
-                   class == PCI_CLASS_SYSTEM_PIC)
+                   class == PCI_CLASS_BRIDGE_HOST)
                        continue;
 
+               /* Don't touch ioapics if it has the assigned resources. */
+               if (class == PCI_CLASS_SYSTEM_PIC) {
+                       res = &dev->resource[0];
+                       if (res[0].start || res[1].start || res[2].start ||
+                           res[3].start || res[4].start || res[5].start)
+                               continue;
+               }
+
                pdev_sort_resources(dev, &head);
        }
 
index 3f6d51d11374063b0f3e0c86de1d75e23c1f3b34..2d7effe7990d9c67136a44617e31bed2290a7026 100644 (file)
@@ -138,7 +138,7 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void
 
        cs_dbg(s, 3, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);
 
-       dev = pci_find_slot(s->cb_dev->subordinate->number, 0);
+       dev = pci_get_slot(s->cb_dev->subordinate, 0);
        if (!dev)
                goto fail;
 
@@ -152,6 +152,9 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void
        }
 
        res = dev->resource + space - 1;
+
+       pci_dev_put(dev);
+
        if (!res->flags)
                goto fail;
 
index 420e10aec0ae451c52961cceb9c2e3ca4f5de306..01be47e72730b5fa847ac9e8245fa2e9d9cda23d 100644 (file)
@@ -67,6 +67,7 @@ struct omap_cf_socket {
        struct platform_device  *pdev;
        unsigned long           phys_cf;
        u_int                   irq;
+       struct resource         iomem;
 };
 
 #define        POLL_INTERVAL           (2 * HZ)
@@ -112,16 +113,14 @@ static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp)
        if (!sp)
                return -EINVAL;
 
-       /* FIXME power management should probably be board-specific:
-        *  - 3VCARD vs XVCARD (OSK only handles 3VCARD)
-        *  - POWERON (switched on/off by set_socket)
-        */
+       /* NOTE CF is always 3VCARD */
        if (omap_cf_present()) {
                struct omap_cf_socket   *cf;
 
                *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
                cf = container_of(s, struct omap_cf_socket, socket);
-               s->irq.AssignedIRQ = cf->irq;
+               s->irq.AssignedIRQ = 0;
+               s->pci_irq = cf->irq;
        } else
                *sp = 0;
        return 0;
@@ -132,7 +131,7 @@ omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
 {
        u16             control;
 
-       /* FIXME some non-OSK boards will support power switching */
+       /* REVISIT some non-OSK boards may support power switching */
        switch (s->Vcc) {
        case 0:
        case 33:
@@ -204,7 +203,7 @@ static struct pccard_operations omap_cf_ops = {
  * "what chipselect is used".  Boards could want more.
  */
 
-static int __init omap_cf_probe(struct device *dev)
+static int __devinit omap_cf_probe(struct device *dev)
 {
        unsigned                seg;
        struct omap_cf_socket   *cf;
@@ -253,6 +252,9 @@ static int __init omap_cf_probe(struct device *dev)
        default:
                goto  fail1;
        }
+       cf->iomem.start = cf->phys_cf;
+       cf->iomem.end = cf->iomem.end + SZ_8K - 1;
+       cf->iomem.flags = IORESOURCE_MEM;
 
        /* pcmcia layer only remaps "real" memory */
        cf->socket.io_offset = (unsigned long)
@@ -296,6 +298,7 @@ static int __init omap_cf_probe(struct device *dev)
        cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
                                | SS_CAP_MEM_ALIGN;
        cf->socket.map_size = SZ_2K;
+       cf->socket.io[0].res = &cf->iomem;
 
        status = pcmcia_register_socket(&cf->socket);
        if (status < 0)
@@ -334,15 +337,15 @@ static struct device_driver omap_cf_driver = {
        .bus            = &platform_bus_type,
        .probe          = omap_cf_probe,
        .remove         = __devexit_p(omap_cf_remove),
-       .suspend        = pcmcia_socket_dev_suspend,
-       .resume         = pcmcia_socket_dev_resume,
+       .suspend        = pcmcia_socket_dev_suspend,
+       .resume         = pcmcia_socket_dev_resume,
 };
 
 static int __init omap_cf_init(void)
 {
        if (cpu_is_omap16xx())
-               driver_register(&omap_cf_driver);
-       return 0;
+               return driver_register(&omap_cf_driver);
+       return -ENODEV;
 }
 
 static void __exit omap_cf_exit(void)
index 551f58e298106060b5708cb288d04c8c7da39043..81a6c83d89a644bb9400aef1ee2470f0a536784d 100644 (file)
@@ -526,6 +526,10 @@ static int __init pnpbios_init(void)
 {
        int ret;
 
+#if defined(CONFIG_PPC_MERGE)
+       if (check_legacy_ioport(PNPBIOS_BASE))
+               return -ENODEV;
+#endif
        if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table)) {
                printk(KERN_INFO "PnPBIOS: Disabled\n");
                return -ENODEV;
@@ -575,6 +579,10 @@ subsys_initcall(pnpbios_init);
 
 static int __init pnpbios_thread_init(void)
 {
+#if defined(CONFIG_PPC_MERGE)
+       if (check_legacy_ioport(PNPBIOS_BASE))
+               return 0;
+#endif
        if (pnpbios_disabled)
                return 0;
 #ifdef CONFIG_HOTPLUG
index 7ff1d88094b683b16827ea20b61804223ac5e85e..fc766a7a611ee0a88327561f93f2996431c9bdb4 100644 (file)
@@ -27,7 +27,7 @@ config RTC_HCTOSYS
        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 fschk runs.
+         in order to avoid unnecessary fsck runs.
 
 config RTC_HCTOSYS_DEVICE
        string "The RTC to read the time from"
@@ -37,6 +37,13 @@ config RTC_HCTOSYS_DEVICE
          The RTC device that will be used as the source for
          the system time, usually rtc0.
 
+config RTC_DEBUG
+       bool "RTC debug support"
+       depends on RTC_CLASS = y
+       help
+         Say yes here to enable debugging support in the RTC framework
+         and individual RTC drivers.
+
 comment "RTC interfaces"
        depends on RTC_CLASS
 
@@ -45,8 +52,8 @@ config RTC_INTF_SYSFS
        depends on RTC_CLASS && SYSFS
        default RTC_CLASS
        help
-         Say yes here if you want to use your RTC using the sysfs
-         interface, /sys/class/rtc/rtcX .
+         Say yes here if you want to use your RTCs using sysfs interfaces,
+         /sys/class/rtc/rtc0 through /sys/.../rtcN.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-sysfs.
@@ -56,8 +63,9 @@ config RTC_INTF_PROC
        depends on RTC_CLASS && PROC_FS
        default RTC_CLASS
        help
-         Say yes here if you want to use your RTC using the proc
-         interface, /proc/driver/rtc .
+         Say yes here if you want to use your first RTC through the proc
+         interface, /proc/driver/rtc.  Other RTCs will not be available
+         through that API.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-proc.
@@ -67,8 +75,11 @@ config RTC_INTF_DEV
        depends on RTC_CLASS
        default RTC_CLASS
        help
-         Say yes here if you want to use your RTC using the dev
-         interface, /dev/rtc .
+         Say yes here if you want to use your RTCs using the /dev
+         interfaces, which "udev" sets up as /dev/rtc0 through
+         /dev/rtcN.  You may want to set up a symbolic link so one
+         of these can be accessed as /dev/rtc, which is a name
+         expected by "hwclock" and some other programs.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-dev.
@@ -78,7 +89,8 @@ config RTC_INTF_DEV_UIE_EMUL
        depends on RTC_INTF_DEV
        help
          Provides an emulation for RTC_UIE if the underlaying rtc chip
-         driver did not provide RTC_UIE ioctls.
+         driver does not expose RTC_UIE ioctls.  Those requests generate
+         once-per-second update interrupts, used for synchronization.
 
 comment "RTC drivers"
        depends on RTC_CLASS
@@ -238,6 +250,16 @@ config RTC_DRV_SA1100
          To compile this driver as a module, choose M here: the
          module will be called rtc-sa1100.
 
+config RTC_DRV_SH
+       tristate "SuperH On-Chip RTC"
+       depends on RTC_CLASS && SUPERH
+       help
+         Say Y here to enable support for the on-chip RTC found in
+         most SuperH processors.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rtc-sh.
+
 config RTC_DRV_VR41XX
        tristate "NEC VR41XX"
        depends on RTC_CLASS && CPU_VR41XX
index bbcfb09d81d90398460a5316ce80817c67af186f..3ba5ff6e68004700162f2e05c75fe02e438ff0b9 100644 (file)
@@ -2,6 +2,10 @@
 # Makefile for RTC class/drivers.
 #
 
+ifeq ($(CONFIG_RTC_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
 obj-$(CONFIG_RTC_LIB)          += rtc-lib.o
 obj-$(CONFIG_RTC_HCTOSYS)      += hctosys.o
 obj-$(CONFIG_RTC_CLASS)                += rtc-core.o
@@ -31,3 +35,4 @@ obj-$(CONFIG_RTC_DRV_PL031)   += rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_AT91)     += rtc-at91.o
+obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
index 1cb61a761cb284cc6dd590e6ebd8062f6271d246..7a0d8ee2de9c9aa95f973b86dec3d5955d348798 100644 (file)
@@ -39,7 +39,7 @@ static void rtc_device_release(struct class_device *class_dev)
  * Returns the pointer to the new struct class device.
  */
 struct rtc_device *rtc_device_register(const char *name, struct device *dev,
-                                       struct rtc_class_ops *ops,
+                                       const struct rtc_class_ops *ops,
                                        struct module *owner)
 {
        struct rtc_device *rtc;
@@ -142,9 +142,9 @@ static void __exit rtc_exit(void)
        class_destroy(rtc_class);
 }
 
-module_init(rtc_init);
+subsys_initcall(rtc_init);
 module_exit(rtc_exit);
 
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>");
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
 MODULE_DESCRIPTION("RTC class support");
 MODULE_LICENSE("GPL");
index dfd0ce86f6a0d82e445752653e667899959d22cd..c0714da44920287fc1be7ad76d2cacccc0bd927c 100644 (file)
@@ -267,7 +267,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id,
        return IRQ_NONE;                /* not handled */
 }
 
-static struct rtc_class_ops at91_rtc_ops = {
+static const struct rtc_class_ops at91_rtc_ops = {
        .ioctl          = at91_rtc_ioctl,
        .read_time      = at91_rtc_readtime,
        .set_time       = at91_rtc_settime,
@@ -307,6 +307,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
                return PTR_ERR(rtc);
        }
        platform_set_drvdata(pdev, rtc);
+       device_init_wakeup(&pdev->dev, 1);
 
        printk(KERN_INFO "AT91 Real Time Clock driver.\n");
        return 0;
@@ -327,6 +328,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev)
 
        rtc_device_unregister(rtc);
        platform_set_drvdata(pdev, NULL);
+       device_init_wakeup(&pdev->dev, 0);
 
        return 0;
 }
@@ -336,6 +338,7 @@ static int __devexit 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)
 {
@@ -349,6 +352,18 @@ static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
        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...
+        */
+       at91_rtc_imr = at91_sys_read(AT91_RTC_IMR)
+                       & (AT91_RTC_ALARM|AT91_RTC_SECEV);
+       if (at91_rtc_imr) {
+               if (device_may_wakeup(&pdev->dev))
+                       enable_irq_wake(AT91_ID_SYS);
+               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);
@@ -367,6 +382,13 @@ static int at91_rtc_resume(struct platform_device *pdev)
        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);
index 61a58259c93fe04ed5a502435763a921f3d57cc5..583789c66cdb9d2404157f0cda029c9e8dfc7c60 100644 (file)
@@ -24,7 +24,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
        int err;
        struct rtc_device *rtc = container_of(inode->i_cdev,
                                        struct rtc_device, char_dev);
-       struct rtc_class_ops *ops = rtc->ops;
+       const struct rtc_class_ops *ops = rtc->ops;
 
        /* We keep the lock as long as the device is in use
         * and return immediately if busy
@@ -209,7 +209,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
        int err = 0;
        struct class_device *class_dev = file->private_data;
        struct rtc_device *rtc = to_rtc_device(class_dev);
-       struct rtc_class_ops *ops = rtc->ops;
+       const struct rtc_class_ops *ops = rtc->ops;
        struct rtc_time tm;
        struct rtc_wkalrm alarm;
        void __user *uarg = (void __user *) arg;
@@ -406,7 +406,6 @@ static int rtc_dev_add_device(struct class_device *class_dev,
        rtc->char_dev.owner = rtc->owner;
 
        if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) {
-               cdev_del(&rtc->char_dev);
                dev_err(class_dev->dev,
                        "failed to add char device %d:%d\n",
                        MAJOR(rtc_devt), rtc->id);
@@ -496,7 +495,7 @@ static void __exit rtc_dev_exit(void)
        unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
 }
 
-module_init(rtc_dev_init);
+subsys_initcall(rtc_dev_init);
 module_exit(rtc_dev_exit);
 
 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
index e8afb9384786a605a0881d153474f4ca0554c2ac..cc5032b6f42ac45c9aba4f0ff896b17585a6c813 100644 (file)
@@ -178,7 +178,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
        return 0;
 }
 
-static struct rtc_class_ops ds13xx_rtc_ops = {
+static const struct rtc_class_ops ds13xx_rtc_ops = {
        .read_time      = ds1307_get_time,
        .set_time       = ds1307_set_time,
 };
index 209001495474f9f88b74cbee8bb410fd7b868523..9647188fee2c66c4c172bce9923b919a2a17eef5 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define RTC_REG_SIZE           0x2000
 #define RTC_OFFSET             0x1ff0
@@ -250,7 +250,7 @@ static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
        return 0;
 }
 
-static struct rtc_class_ops ds1553_rtc_ops = {
+static const struct rtc_class_ops ds1553_rtc_ops = {
        .read_time      = ds1553_rtc_read_time,
        .set_time       = ds1553_rtc_set_time,
        .read_alarm     = ds1553_rtc_read_alarm,
@@ -357,9 +357,13 @@ static int __init ds1553_rtc_probe(struct platform_device *pdev)
        pdata->rtc = rtc;
        pdata->last_jiffies = jiffies;
        platform_set_drvdata(pdev, pdata);
-       sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+       ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+       if (ret)
+               goto out;
        return 0;
  out:
+       if (pdata->rtc)
+               rtc_device_unregister(pdata->rtc);
        if (pdata->irq >= 0)
                free_irq(pdata->irq, pdev);
        if (ioaddr)
index 9be81fd4737c20c11cbcc4c2e466a41331c01434..9c68ec99afa5776ad23d039efd693b02ef2d4890 100644 (file)
@@ -156,7 +156,7 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c
 }
 static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
 
-static struct rtc_class_ops ds1672_rtc_ops = {
+static const struct rtc_class_ops ds1672_rtc_ops = {
        .read_time      = ds1672_rtc_read_time,
        .set_time       = ds1672_rtc_set_time,
        .set_mmss       = ds1672_rtc_set_mmss,
index 8e47e5a06d2a48c336cd4cd44e6b4e86a16670fe..6273a3d240a2afd2f4a57179d38219f6259797a1 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define RTC_REG_SIZE           0x800
 #define RTC_OFFSET             0x7f8
@@ -116,7 +116,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
        return 0;
 }
 
-static struct rtc_class_ops ds1742_rtc_ops = {
+static const struct rtc_class_ops ds1742_rtc_ops = {
        .read_time      = ds1742_rtc_read_time,
        .set_time       = ds1742_rtc_set_time,
 };
@@ -196,7 +196,7 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev)
                writeb(sec, ioaddr + RTC_SECONDS);
                writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
        }
-       if (readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)
+       if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG))
                dev_warn(&pdev->dev, "voltage-low detected.\n");
 
        rtc = rtc_device_register(pdev->name, &pdev->dev,
@@ -208,9 +208,13 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev)
        pdata->rtc = rtc;
        pdata->last_jiffies = jiffies;
        platform_set_drvdata(pdev, pdata);
-       sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+       ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+       if (ret)
+               goto out;
        return 0;
  out:
+       if (pdata->rtc)
+               rtc_device_unregister(pdata->rtc);
        if (ioaddr)
                iounmap(ioaddr);
        if (pdata->baseaddr)
index e1a1169e46649f4be8c8917f5a1a9b6cc7230615..ef4f147f3c0c30b0a16b46908f545f3ac6001eb1 100644 (file)
@@ -73,7 +73,7 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
        return 0;
 }
 
-static struct rtc_class_ops ep93xx_rtc_ops = {
+static const struct rtc_class_ops ep93xx_rtc_ops = {
        .read_time      = ep93xx_rtc_read_time,
        .set_time       = ep93xx_rtc_set_time,
        .set_mmss       = ep93xx_rtc_set_mmss,
index f324d0a635d4743c9268e4f914fcd51a8069af17..1c743641b73b294c0e365b4ca27a93ff14015bbd 100644 (file)
@@ -390,7 +390,7 @@ static int isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm);
 }
 
-static struct rtc_class_ops isl1208_rtc_ops = {
+static const struct rtc_class_ops isl1208_rtc_ops = {
        .proc           = isl1208_rtc_proc,
        .read_time      = isl1208_rtc_read_time,
        .set_time       = isl1208_rtc_set_time,
index 9812120f3a7c825c783a7c15635279740ced383d..ba795a4db1e97289829c3c69dbee613fa2720a25 100644 (file)
@@ -94,12 +94,12 @@ EXPORT_SYMBOL(rtc_time_to_tm);
 int rtc_valid_tm(struct rtc_time *tm)
 {
        if (tm->tm_year < 70
-               || tm->tm_mon >= 12
+               || ((unsigned)tm->tm_mon) >= 12
                || tm->tm_mday < 1
                || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900)
-               || tm->tm_hour >= 24
-               || tm->tm_min >= 60
-               || tm->tm_sec >= 60)
+               || ((unsigned)tm->tm_hour) >= 24
+               || ((unsigned)tm->tm_min) >= 60
+               || ((unsigned)tm->tm_sec) >= 60)
                return -EINVAL;
 
        return 0;
index 8c0d1a6739adb23012a1c92bf9a102898b9a94cf..8ff4a1221f59a4a1aaa549451b659cab8f7d4c6a 100644 (file)
@@ -138,7 +138,7 @@ static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
        return 0;
 }
 
-static struct rtc_class_ops m48t86_rtc_ops = {
+static const struct rtc_class_ops m48t86_rtc_ops = {
        .read_time      = m48t86_rtc_read_time,
        .set_time       = m48t86_rtc_set_time,
        .proc           = m48t86_rtc_proc,
index 2c9739562b5c284a740d2e004ab776abeaf0039a..9eeef964663ac84597f7d1ab1d754e1df302063c 100644 (file)
@@ -207,7 +207,7 @@ static int max6902_set_time(struct device *dev, struct rtc_time *tm)
        return max6902_set_datetime(dev, tm);
 }
 
-static struct rtc_class_ops max6902_rtc_ops = {
+static const struct rtc_class_ops max6902_rtc_ops = {
        .read_time      = max6902_read_time,
        .set_time       = max6902_set_time,
 };
index ba9a583b7b6817ff073b4c70a5a93910fdc89fe0..a760cf69af90de24bb80782fbdbf3a393d08777c 100644 (file)
@@ -95,7 +95,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
        tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
        tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR])
-               + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0);
+               + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 0 : 100);
 
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -135,7 +135,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 
        /* year and century */
        buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
-       if (tm->tm_year / 100)
+       if (tm->tm_year < 100)
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;
 
        buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
@@ -227,7 +227,7 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
        return pcf8563_set_datetime(to_i2c_client(dev), tm);
 }
 
-static struct rtc_class_ops pcf8563_rtc_ops = {
+static const struct rtc_class_ops pcf8563_rtc_ops = {
        .read_time      = pcf8563_rtc_read_time,
        .set_time       = pcf8563_rtc_set_time,
 };
index b235a30cb6610b67c12f82447ecdb534d5b91e51..5875ebb8c79d9c3070c025860a8a5b1cf428fbec 100644 (file)
@@ -273,7 +273,7 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
        return ret;
 }
 
-static struct rtc_class_ops pcf8583_rtc_ops = {
+static const struct rtc_class_ops pcf8583_rtc_ops = {
        .read_time      = pcf8583_rtc_read_time,
        .set_time       = pcf8583_rtc_set_time,
 };
index d6d1c5726b0ee87347e9532a1da267c6cb1c79e3..739d1a6e14eb9054d717bda6eef4f8266d3213fd 100644 (file)
@@ -128,7 +128,7 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        return 0;
 }
 
-static struct rtc_class_ops pl031_ops = {
+static const struct rtc_class_ops pl031_ops = {
        .open = pl031_open,
        .release = pl031_release,
        .ioctl = pl031_ioctl,
index cef5f5a3bbf9298233e25a2da7ba9dcc464133b2..d51d8f20e634e020428b834febb6852731303310 100644 (file)
@@ -23,7 +23,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
 {
        int err;
        struct class_device *class_dev = seq->private;
-       struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
+       const struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
        struct rtc_wkalrm alrm;
        struct rtc_time tm;
 
@@ -61,7 +61,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
                        seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);
                else
                        seq_printf(seq, "**-");
-               if ((unsigned int)alrm.time.tm_mday <= 31)
+               if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31)
                        seq_printf(seq, "%02d\n", alrm.time.tm_mday);
                else
                        seq_printf(seq, "**\n");
@@ -156,7 +156,7 @@ static void __exit rtc_proc_exit(void)
        class_interface_unregister(&rtc_proc_interface);
 }
 
-module_init(rtc_proc_init);
+subsys_initcall(rtc_proc_init);
 module_exit(rtc_proc_exit);
 
 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
index 0964d1dba92519e6fe3ab799f2c04bb4ae26db40..f50f3fc353cd64be4845c8dcc90bfd6eeb7cc877 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/workqueue.h>
 #include <linux/spi/spi.h>
 
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define RS5C348_REG_SECS       0
 #define RS5C348_REG_MINS       1
@@ -140,7 +140,7 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
        return 0;
 }
 
-static struct rtc_class_ops rs5c348_rtc_ops = {
+static const struct rtc_class_ops rs5c348_rtc_ops = {
        .read_time      = rs5c348_rtc_read_time,
        .set_time       = rs5c348_rtc_set_time,
 };
@@ -175,8 +175,15 @@ static int __devinit rs5c348_probe(struct spi_device *spi)
                goto kfree_exit;
        if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) {
                u8 buf[2];
+               struct rtc_time tm;
                if (ret & RS5C348_BIT_VDET)
                        dev_warn(&spi->dev, "voltage-low detected.\n");
+               if (ret & RS5C348_BIT_XSTP)
+                       dev_warn(&spi->dev, "oscillator-stop detected.\n");
+               rtc_time_to_tm(0, &tm); /* 1970/1/1 */
+               ret = rs5c348_rtc_set_time(&spi->dev, &tm);
+               if (ret < 0)
+                       goto kfree_exit;
                buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2);
                buf[1] = 0;
                ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
index 7553d797603fd86d78a266d578765e439ea5aced..bbdad099471d43b65d33ec05161f1f88e01b0dac 100644 (file)
@@ -160,7 +160,7 @@ static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
        return 0;
 }
 
-static struct rtc_class_ops rs5c372_rtc_ops = {
+static const struct rtc_class_ops rs5c372_rtc_ops = {
        .proc           = rs5c372_rtc_proc,
        .read_time      = rs5c372_rtc_read_time,
        .set_time       = rs5c372_rtc_set_time,
index 2c7de79c83b9baa352769e7626bc06b27c8abb60..625dad2eeb4f4fa2b8f787ce805bf44c67eccf56 100644 (file)
@@ -386,7 +386,7 @@ static void s3c_rtc_release(struct device *dev)
        free_irq(s3c_rtc_tickno, rtc_dev);
 }
 
-static struct rtc_class_ops s3c_rtcops = {
+static const struct rtc_class_ops s3c_rtcops = {
        .open           = s3c_rtc_open,
        .release        = s3c_rtc_release,
        .ioctl          = s3c_rtc_ioctl,
index ee4b61ee67b03de09faa6296137dd0c3f925d495..439c41aea31c9d091bcfe66f326d2ba3afdd2679 100644 (file)
@@ -303,7 +303,7 @@ static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
        return 0;
 }
 
-static struct rtc_class_ops sa1100_rtc_ops = {
+static const struct rtc_class_ops sa1100_rtc_ops = {
        .open = sa1100_rtc_open,
        .read_callback = sa1100_rtc_read_callback,
        .release = sa1100_rtc_release,
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
new file mode 100644 (file)
index 0000000..d2ce0c8
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * SuperH On-Chip RTC Support
+ *
+ * Copyright (C) 2006  Paul Mundt
+ *
+ * Based on the old arch/sh/kernel/cpu/rtc.c by:
+ *
+ *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ *
+ * 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/bcd.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CPU_SH3
+#define rtc_reg_size           sizeof(u16)
+#define RTC_BIT_INVERTED       0       /* No bug on SH7708, SH7709A */
+#elif defined(CONFIG_CPU_SH4)
+#define rtc_reg_size           sizeof(u32)
+#define RTC_BIT_INVERTED       0x40    /* bug on SH7750, SH7750S */
+#endif
+
+#define RTC_REG(r)     ((r) * rtc_reg_size)
+
+#define R64CNT         RTC_REG(0)
+#define RSECCNT        RTC_REG(1)
+#define RMINCNT        RTC_REG(2)
+#define RHRCNT         RTC_REG(3)
+#define RWKCNT         RTC_REG(4)
+#define RDAYCNT        RTC_REG(5)
+#define RMONCNT        RTC_REG(6)
+#define RYRCNT         RTC_REG(7)
+#define RSECAR         RTC_REG(8)
+#define RMINAR         RTC_REG(9)
+#define RHRAR          RTC_REG(10)
+#define RWKAR          RTC_REG(11)
+#define RDAYAR         RTC_REG(12)
+#define RMONAR         RTC_REG(13)
+#define RCR1           RTC_REG(14)
+#define RCR2           RTC_REG(15)
+
+/* RCR1 Bits */
+#define RCR1_CF                0x80    /* Carry Flag             */
+#define RCR1_CIE       0x10    /* Carry Interrupt Enable */
+#define RCR1_AIE       0x08    /* Alarm Interrupt Enable */
+#define RCR1_AF                0x01    /* Alarm Flag             */
+
+/* RCR2 Bits */
+#define RCR2_PEF       0x80    /* PEriodic interrupt Flag */
+#define RCR2_PESMASK   0x70    /* Periodic interrupt Set  */
+#define RCR2_RTCEN     0x08    /* ENable RTC              */
+#define RCR2_ADJ       0x04    /* ADJustment (30-second)  */
+#define RCR2_RESET     0x02    /* Reset bit               */
+#define RCR2_START     0x01    /* Start bit               */
+
+struct sh_rtc {
+       void __iomem *regbase;
+       unsigned long regsize;
+       struct resource *res;
+       unsigned int alarm_irq, periodic_irq, carry_irq;
+       struct rtc_device *rtc_dev;
+       spinlock_t lock;
+};
+
+static irqreturn_t sh_rtc_interrupt(int irq, void *id, struct pt_regs *regs)
+{
+       struct platform_device *pdev = id;
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned int tmp, events = 0;
+
+       spin_lock(&rtc->lock);
+
+       tmp = readb(rtc->regbase + RCR1);
+
+       if (tmp & RCR1_AF)
+               events |= RTC_AF | RTC_IRQF;
+
+       tmp &= ~(RCR1_CF | RCR1_AF);
+
+       writeb(tmp, rtc->regbase + RCR1);
+
+       rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
+
+       spin_unlock(&rtc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t sh_rtc_periodic(int irq, void *id, struct pt_regs *regs)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(id);
+
+       spin_lock(&rtc->lock);
+
+       rtc_update_irq(&rtc->rtc_dev->class_dev, 1, RTC_PF | RTC_IRQF);
+
+       spin_unlock(&rtc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+
+       spin_lock_irq(&rtc->lock);
+
+       tmp = readb(rtc->regbase + RCR2);
+
+       if (enable) {
+               tmp &= ~RCR2_PESMASK;
+               tmp |= RCR2_PEF | (2 << 4);
+       } else
+               tmp &= ~(RCR2_PESMASK | RCR2_PEF);
+
+       writeb(tmp, rtc->regbase + RCR2);
+
+       spin_unlock_irq(&rtc->lock);
+}
+
+static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+
+       spin_lock_irq(&rtc->lock);
+
+       tmp = readb(rtc->regbase + RCR1);
+
+       if (enable)
+               tmp |= RCR1_AIE;
+       else
+               tmp &= ~RCR1_AIE;
+
+       writeb(tmp, rtc->regbase + RCR1);
+
+       spin_unlock_irq(&rtc->lock);
+}
+
+static int sh_rtc_open(struct device *dev)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+       int ret;
+
+       tmp = readb(rtc->regbase + RCR1);
+       tmp &= ~RCR1_CF;
+       tmp |= RCR1_CIE;
+       writeb(tmp, rtc->regbase + RCR1);
+
+       ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, SA_INTERRUPT,
+                         "sh-rtc period", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
+                       ret, rtc->periodic_irq);
+               return ret;
+       }
+
+       ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, SA_INTERRUPT,
+                         "sh-rtc carry", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
+                       ret, rtc->carry_irq);
+               free_irq(rtc->periodic_irq, dev);
+               goto err_bad_carry;
+       }
+
+       ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, SA_INTERRUPT,
+                         "sh-rtc alarm", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
+                       ret, rtc->alarm_irq);
+               goto err_bad_alarm;
+       }
+
+       return 0;
+
+err_bad_alarm:
+       free_irq(rtc->carry_irq, dev);
+err_bad_carry:
+       free_irq(rtc->periodic_irq, dev);
+
+       return ret;
+}
+
+static void sh_rtc_release(struct device *dev)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+
+       sh_rtc_setpie(dev, 0);
+
+       free_irq(rtc->periodic_irq, dev);
+       free_irq(rtc->carry_irq, dev);
+       free_irq(rtc->alarm_irq, dev);
+}
+
+static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+
+       tmp = readb(rtc->regbase + RCR1);
+       seq_printf(seq, "alarm_IRQ\t: %s\n",
+                  (tmp & RCR1_AIE) ? "yes" : "no");
+       seq_printf(seq, "carry_IRQ\t: %s\n",
+                  (tmp & RCR1_CIE) ? "yes" : "no");
+
+       tmp = readb(rtc->regbase + RCR2);
+       seq_printf(seq, "periodic_IRQ\t: %s\n",
+                  (tmp & RCR2_PEF) ? "yes" : "no");
+
+       return 0;
+}
+
+static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       unsigned int ret = -ENOIOCTLCMD;
+
+       switch (cmd) {
+       case RTC_PIE_OFF:
+       case RTC_PIE_ON:
+               sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
+               ret = 0;
+               break;
+       case RTC_AIE_OFF:
+       case RTC_AIE_ON:
+               sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
+               ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned int sec128, sec2, yr, yr100, cf_bit;
+
+       do {
+               unsigned int tmp;
+
+               spin_lock_irq(&rtc->lock);
+
+               tmp = readb(rtc->regbase + RCR1);
+               tmp &= ~RCR1_CF; /* Clear CF-bit */
+               tmp |= RCR1_CIE;
+               writeb(tmp, rtc->regbase + RCR1);
+
+               sec128 = readb(rtc->regbase + R64CNT);
+
+               tm->tm_sec      = BCD2BIN(readb(rtc->regbase + RSECCNT));
+               tm->tm_min      = BCD2BIN(readb(rtc->regbase + RMINCNT));
+               tm->tm_hour     = BCD2BIN(readb(rtc->regbase + RHRCNT));
+               tm->tm_wday     = BCD2BIN(readb(rtc->regbase + RWKCNT));
+               tm->tm_mday     = BCD2BIN(readb(rtc->regbase + RDAYCNT));
+               tm->tm_mon      = BCD2BIN(readb(rtc->regbase + RMONCNT));
+
+#if defined(CONFIG_CPU_SH4)
+               yr  = readw(rtc->regbase + RYRCNT);
+               yr100 = BCD2BIN(yr >> 8);
+               yr &= 0xff;
+#else
+               yr  = readb(rtc->regbase + RYRCNT);
+               yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
+#endif
+
+               tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
+
+               sec2 = readb(rtc->regbase + R64CNT);
+               cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;
+
+               spin_unlock_irq(&rtc->lock);
+       } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
+
+#if RTC_BIT_INVERTED != 0
+       if ((sec128 & RTC_BIT_INVERTED))
+               tm->tm_sec--;
+#endif
+
+       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,
+               tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+       if (rtc_valid_tm(tm) < 0)
+               dev_err(dev, "invalid date\n");
+
+       return 0;
+}
+
+static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned int tmp;
+       int year;
+
+       spin_lock_irq(&rtc->lock);
+
+       /* Reset pre-scaler & stop RTC */
+       tmp = readb(rtc->regbase + RCR2);
+       tmp |= RCR2_RESET;
+       writeb(tmp, rtc->regbase + RCR2);
+
+       writeb(BIN2BCD(tm->tm_sec),  rtc->regbase + RSECCNT);
+       writeb(BIN2BCD(tm->tm_min),  rtc->regbase + RMINCNT);
+       writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
+       writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
+       writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
+       writeb(BIN2BCD(tm->tm_mon),  rtc->regbase + RMONCNT);
+
+#ifdef CONFIG_CPU_SH3
+       year = tm->tm_year % 100;
+       writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
+#else
+       year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
+               BIN2BCD(tm->tm_year % 100);
+       writew(year, rtc->regbase + RYRCNT);
+#endif
+
+       /* Start RTC */
+       tmp = readb(rtc->regbase + RCR2);
+       tmp &= ~RCR2_RESET;
+       tmp |= RCR2_RTCEN | RCR2_START;
+       writeb(tmp, rtc->regbase + RCR2);
+
+       spin_unlock_irq(&rtc->lock);
+
+       return 0;
+}
+
+static struct rtc_class_ops sh_rtc_ops = {
+       .open           = sh_rtc_open,
+       .release        = sh_rtc_release,
+       .ioctl          = sh_rtc_ioctl,
+       .read_time      = sh_rtc_read_time,
+       .set_time       = sh_rtc_set_time,
+       .proc           = sh_rtc_proc,
+};
+
+static int __devinit sh_rtc_probe(struct platform_device *pdev)
+{
+       struct sh_rtc *rtc;
+       struct resource *res;
+       int ret = -ENOENT;
+
+       rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
+       if (unlikely(!rtc))
+               return -ENOMEM;
+
+       spin_lock_init(&rtc->lock);
+
+       rtc->periodic_irq = platform_get_irq(pdev, 0);
+       if (unlikely(rtc->periodic_irq < 0)) {
+               dev_err(&pdev->dev, "No IRQ for period\n");
+               goto err_badres;
+       }
+
+       rtc->carry_irq = platform_get_irq(pdev, 1);
+       if (unlikely(rtc->carry_irq < 0)) {
+               dev_err(&pdev->dev, "No IRQ for carry\n");
+               goto err_badres;
+       }
+
+       rtc->alarm_irq = platform_get_irq(pdev, 2);
+       if (unlikely(rtc->alarm_irq < 0)) {
+               dev_err(&pdev->dev, "No IRQ for alarm\n");
+               goto err_badres;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (unlikely(res == NULL)) {
+               dev_err(&pdev->dev, "No IO resource\n");
+               goto err_badres;
+       }
+
+       rtc->regsize = res->end - res->start + 1;
+
+       rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name);
+       if (unlikely(!rtc->res)) {
+               ret = -EBUSY;
+               goto err_badres;
+       }
+
+       rtc->regbase = (void __iomem *)rtc->res->start;
+       if (unlikely(!rtc->regbase)) {
+               ret = -EINVAL;
+               goto err_badmap;
+       }
+
+       rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
+                                          &sh_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc->rtc_dev);
+               goto err_badmap;
+       }
+
+       platform_set_drvdata(pdev, rtc);
+
+       return 0;
+
+err_badmap:
+       release_resource(rtc->res);
+err_badres:
+       kfree(rtc);
+
+       return ret;
+}
+
+static int __devexit sh_rtc_remove(struct platform_device *pdev)
+{
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+
+       if (likely(rtc->rtc_dev))
+               rtc_device_unregister(rtc->rtc_dev);
+
+       sh_rtc_setpie(&pdev->dev, 0);
+       sh_rtc_setaie(&pdev->dev, 0);
+
+       release_resource(rtc->res);
+
+       platform_set_drvdata(pdev, NULL);
+
+       kfree(rtc);
+
+       return 0;
+}
+static struct platform_driver sh_rtc_platform_driver = {
+       .driver         = {
+               .name   = "sh-rtc",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = sh_rtc_probe,
+       .remove         = __devexit_p(sh_rtc_remove),
+};
+
+static int __init sh_rtc_init(void)
+{
+       return platform_driver_register(&sh_rtc_platform_driver);
+}
+
+static void __exit sh_rtc_exit(void)
+{
+       platform_driver_unregister(&sh_rtc_platform_driver);
+}
+
+module_init(sh_rtc_init);
+module_exit(sh_rtc_exit);
+
+MODULE_DESCRIPTION("SuperH on-chip RTC driver");
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_LICENSE("GPL");
index 7c1f3d2e53c4d3eeff9354dcbf168aacd874380f..6f8370e88a76bb90321f4e8172fe7bdd163c4122 100644 (file)
@@ -116,7 +116,7 @@ static void __exit rtc_sysfs_exit(void)
        class_interface_unregister(&rtc_sysfs_interface);
 }
 
-module_init(rtc_sysfs_init);
+subsys_init(rtc_sysfs_init);
 module_exit(rtc_sysfs_exit);
 
 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
index e1fa5fe7901f900167b448997cb4f4373a85e892..bc4bd24508a2d4beb23458c3b6ee3a86b7e41e26 100644 (file)
@@ -75,7 +75,7 @@ static int test_rtc_ioctl(struct device *dev, unsigned int cmd,
        }
 }
 
-static struct rtc_class_ops test_rtc_ops = {
+static const struct rtc_class_ops test_rtc_ops = {
        .proc = test_rtc_proc,
        .read_time = test_rtc_read_time,
        .set_time = test_rtc_set_time,
index a40f400acff6b814401228ba550f54e92aeddfda..09b714f1cdc39f9dedb4cad38b5b036677a0d9dd 100644 (file)
@@ -149,7 +149,7 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt)
        return 0;
 }
 
-static struct rtc_class_ops v3020_rtc_ops = {
+static const struct rtc_class_ops v3020_rtc_ops = {
        .read_time      = v3020_read_time,
        .set_time       = v3020_set_time,
 };
@@ -169,9 +169,6 @@ static int rtc_probe(struct platform_device *pdev)
        if (pdev->resource[0].flags != IORESOURCE_MEM)
                return -EBUSY;
 
-       if (pdev == NULL)
-               return -EBUSY;
-
        chip = kzalloc(sizeof *chip, GFP_KERNEL);
        if (!chip)
                return -ENOMEM;
index 596764fd29f5a320cfeb89a4fb0823cac3972720..58e5ed0aa12702fc9798f03eb915f262d7f92a8c 100644 (file)
@@ -296,7 +296,7 @@ static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *reg
        return IRQ_HANDLED;
 }
 
-static struct rtc_class_ops vr41xx_rtc_ops = {
+static const struct rtc_class_ops vr41xx_rtc_ops = {
        .release        = vr41xx_rtc_release,
        .ioctl          = vr41xx_rtc_ioctl,
        .read_time      = vr41xx_rtc_read_time,
index 788b6d1f8f2fd282cac69e6b8a5c0e9a3698c9f2..522c69753bbfb3843b6dccf1c4f922b43e45a666 100644 (file)
@@ -460,7 +460,7 @@ static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
        return 0;
 }
 
-static struct rtc_class_ops x1205_rtc_ops = {
+static const struct rtc_class_ops x1205_rtc_ops = {
        .proc           = x1205_rtc_proc,
        .read_time      = x1205_rtc_read_time,
        .set_time       = x1205_rtc_set_time,
index 929d6fff6152a642b929d8854e515d3f8152bc1d..b250c53545033cba2a019ee4e5973bf1bac04551 100644 (file)
@@ -1,4 +1,4 @@
-if S390
+if S390 && BLOCK
 
 comment "S/390 block device drivers"
        depends on S390
index 23fa0b289173e84098c48411ac10287db517e8e1..222a8a71a5e8b439dd11df7e31ee389270a1dab9 100644 (file)
@@ -63,44 +63,26 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
  * and function code cmd.
  * In case of an exception return 3. Otherwise return result of bitwise OR of
  * resulting condition code and DIAG return code. */
-static __inline__ int
-dia250(void *iob, int cmd)
+static inline int dia250(void *iob, int cmd)
 {
+       register unsigned long reg0 asm ("0") = (unsigned long) iob;
        typedef union {
                struct dasd_diag_init_io init_io;
                struct dasd_diag_rw_io rw_io;
        } addr_type;
        int rc;
 
-       __asm__ __volatile__(
-#ifdef CONFIG_64BIT
-               "       lghi    %0,3\n"
-               "       lgr     0,%3\n"
-               "       diag    0,%2,0x250\n"
-               "0:     ipm     %0\n"
-               "       srl     %0,28\n"
-               "       or      %0,1\n"
-               "1:\n"
-               ".section __ex_table,\"a\"\n"
-               "       .align 8\n"
-               "       .quad  0b,1b\n"
-               ".previous\n"
-#else
-               "       lhi     %0,3\n"
-               "       lr      0,%3\n"
+       rc = 3;
+       asm volatile(
                "       diag    0,%2,0x250\n"
                "0:     ipm     %0\n"
                "       srl     %0,28\n"
                "       or      %0,1\n"
                "1:\n"
-               ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
-               "       .long 0b,1b\n"
-               ".previous\n"
-#endif
-               : "=&d" (rc), "=m" (*(addr_type *) iob)
-               : "d" (cmd), "d" (iob), "m" (*(addr_type *) iob)
-               : "0", "1", "cc");
+               EX_TABLE(0b,1b)
+               : "+d" (rc), "=m" (*(addr_type *) iob)
+               : "d" (cmd), "d" (reg0), "m" (*(addr_type *) iob)
+               : "1", "cc");
        return rc;
 }
 
@@ -547,7 +529,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
        }
        cqr->retries = DIAG_MAX_RETRIES;
        cqr->buildclk = get_clock();
-       if (req->flags & REQ_FAILFAST)
+       if (req->cmd_flags & REQ_FAILFAST)
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->device = device;
        cqr->expires = DIAG_TIMEOUT;
index b7a7fac3f7c3a05ae3448e5d172db199578a4dc6..5ecea3e4fdefd3a5bdaa8ef0cebc0711dc91028f 100644 (file)
@@ -1266,7 +1266,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
                        recid++;
                }
        }
-       if (req->flags & REQ_FAILFAST)
+       if (req->cmd_flags & REQ_FAILFAST)
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->device = device;
        cqr->expires = 5 * 60 * HZ;     /* 5 minutes */
index e85015be109bb918366a62c83fec616512a6bb30..80926c5482281293644f52e06888060e804a9f2a 100644 (file)
@@ -344,7 +344,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
                        recid++;
                }
        }
-       if (req->flags & REQ_FAILFAST)
+       if (req->cmd_flags & REQ_FAILFAST)
                set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->device = device;
        cqr->expires = 5 * 60 * HZ;     /* 5 minutes */
index cab2c736683a089672f5d5283926353d5d66605b..a04d9120cef0111970cb4980235781a0f76a8a2c 100644 (file)
@@ -89,28 +89,15 @@ MODULE_LICENSE("GPL");
  */
 static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
 {
-       int cc;
+       int cc = 2;     /* return unused cc 2 if pgin traps */
 
-       __asm__ __volatile__ (
-               "   lhi   %0,2\n"  /* return unused cc 2 if pgin traps */
-               "   .insn rre,0xb22e0000,%1,%2\n"  /* pgin %1,%2 */
-                "0: ipm   %0\n"
-               "   srl   %0,28\n"
+       asm volatile(
+               "       .insn   rre,0xb22e0000,%1,%2\n"  /* pgin %1,%2 */
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
                "1:\n"
-#ifndef CONFIG_64BIT
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-               "   .long  0b,1b\n"
-               ".previous"
-#else
-                ".section __ex_table,\"a\"\n"
-                "   .align 8\n"
-                "   .quad 0b,1b\n"
-                ".previous"
-#endif
-               : "=&d" (cc) 
-               : "a" (__pa(page_addr)), "a" (xpage_index) 
-               : "cc" );
+               EX_TABLE(0b,1b)
+               : "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
        if (cc == 3)
                return -ENXIO;
        if (cc == 2) {
@@ -137,28 +124,15 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
  */
 static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
 {
-       int cc;
+       int cc = 2;     /* return unused cc 2 if pgin traps */
 
-       __asm__ __volatile__ (
-               "   lhi   %0,2\n"  /* return unused cc 2 if pgout traps */
-               "   .insn rre,0xb22f0000,%1,%2\n"  /* pgout %1,%2 */
-                "0: ipm   %0\n"
-               "   srl   %0,28\n"
+       asm volatile(
+               "       .insn   rre,0xb22f0000,%1,%2\n"  /* pgout %1,%2 */
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
                "1:\n"
-#ifndef CONFIG_64BIT
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-               "   .long  0b,1b\n"
-               ".previous"
-#else
-                ".section __ex_table,\"a\"\n"
-                "   .align 8\n"
-                "   .quad 0b,1b\n"
-                ".previous"
-#endif
-               : "=&d" (cc) 
-               : "a" (__pa(page_addr)), "a" (xpage_index) 
-               : "cc" );
+               EX_TABLE(0b,1b)
+               : "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
        if (cc == 3)
                return -ENXIO;
        if (cc == 2) {
index ef004d089712bc8a0420e204fc3d597fbfb05343..b4557fa30858038103825a70ae43402062dce96d 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
-#include <asm/cpcmd.h>
 #include <asm/ebcdic.h>
 #include <asm/idals.h>
 
index 985d1613baaa59235d5c6a6edcb76e91f5fa9b0c..31e335751d6d5a3788aee3676c2cfb5e4d123a18 100644 (file)
@@ -100,13 +100,12 @@ service_call(sclp_cmdw_t command, void *sccb)
 {
        int cc;
 
-       __asm__ __volatile__(
-               "   .insn rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=&d" (cc)
-               : "d" (command), "a" (__pa(sccb))
-               : "cc", "memory" );
+       asm volatile(
+               "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+               : "cc", "memory");
        if (cc == 3)
                return -EIO;
        if (cc == 2)
@@ -360,16 +359,6 @@ sclp_interrupt_handler(struct pt_regs *regs, __u16 code)
        sclp_process_queue();
 }
 
-/* Return current Time-Of-Day clock. */
-static inline u64
-sclp_get_clock(void)
-{
-       u64 result;
-
-       asm volatile ("STCK 0(%1)" : "=m" (result) : "a" (&(result)) : "cc");
-       return result;
-}
-
 /* Convert interval in jiffies to TOD ticks. */
 static inline u64
 sclp_tod_from_jiffies(unsigned long jiffies)
@@ -382,7 +371,6 @@ sclp_tod_from_jiffies(unsigned long jiffies)
 void
 sclp_sync_wait(void)
 {
-       unsigned long psw_mask;
        unsigned long flags;
        unsigned long cr0, cr0_sync;
        u64 timeout;
@@ -392,7 +380,7 @@ sclp_sync_wait(void)
        timeout = 0;
        if (timer_pending(&sclp_request_timer)) {
                /* Get timeout TOD value */
-               timeout = sclp_get_clock() +
+               timeout = get_clock() +
                          sclp_tod_from_jiffies(sclp_request_timer.expires -
                                                jiffies);
        }
@@ -406,13 +394,12 @@ sclp_sync_wait(void)
        cr0_sync |= 0x00000200;
        cr0_sync &= 0xFFFFF3AC;
        __ctl_load(cr0_sync, 0, 0);
-       asm volatile ("STOSM 0(%1),0x01"
-                     : "=m" (psw_mask) : "a" (&psw_mask) : "memory");
+       __raw_local_irq_stosm(0x01);
        /* Loop until driver state indicates finished request */
        while (sclp_running_state != sclp_running_state_idle) {
                /* Check for expired request timer */
                if (timer_pending(&sclp_request_timer) &&
-                   sclp_get_clock() > timeout &&
+                   get_clock() > timeout &&
                    del_timer(&sclp_request_timer))
                        sclp_request_timer.function(sclp_request_timer.data);
                barrier();
index 29718042c6c9a669da34d828e046fb636a6f64d1..06e2eeec8473dca2e3ff3c79ae5fab78014eac0c 100644 (file)
@@ -698,7 +698,6 @@ tty3270_alloc_view(void)
        if (!tp->freemem_pages)
                goto out_tp;
        INIT_LIST_HEAD(&tp->freemem);
-       init_timer(&tp->timer);
        for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
                tp->freemem_pages[pages] = (void *)
                        __get_free_pages(GFP_KERNEL|GFP_DMA, 0);
index 807320a41fa40f5ab1ed0b426e9831d2bb109b97..4b868f72fe89efd4a3befcf73bfdd5ef85e34ac2 100644 (file)
@@ -54,48 +54,20 @@ enum vmwdt_func {
 static int __diag288(enum vmwdt_func func, unsigned int timeout,
                            char *cmd, size_t len)
 {
-       register unsigned long __func asm("2");
-       register unsigned long __timeout asm("3");
-       register unsigned long __cmdp asm("4");
-       register unsigned long __cmdl asm("5");
+       register unsigned long __func asm("2") = func;
+       register unsigned long __timeout asm("3") = timeout;
+       register unsigned long __cmdp asm("4") = virt_to_phys(cmd);
+       register unsigned long __cmdl asm("5") = len;
        int err;
 
-       __func = func;
-       __timeout = timeout;
-       __cmdp = virt_to_phys(cmd);
-       __cmdl = len;
-       err = 0;
-       asm volatile (
-#ifdef CONFIG_64BIT
-                      "diag %2,%4,0x288\n"
-               "1:     \n"
-               ".section .fixup,\"ax\"\n"
-               "2:     lghi %0,%1\n"
-               "       jg 1b\n"
-               ".previous\n"
-               ".section __ex_table,\"a\"\n"
-               "       .align 8\n"
-               "       .quad 1b,2b\n"
-               ".previous\n"
-#else
-                      "diag %2,%4,0x288\n"
-               "1:     \n"
-               ".section .fixup,\"ax\"\n"
-               "2:     lhi %0,%1\n"
-               "       bras 1,3f\n"
-               "       .long 1b\n"
-               "3:     l 1,0(1)\n"
-               "       br 1\n"
-               ".previous\n"
-               ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
-               "       .long 1b,2b\n"
-               ".previous\n"
-#endif
-               : "+&d"(err)
-               : "i"(-EINVAL), "d"(__func), "d"(__timeout),
-                 "d"(__cmdp), "d"(__cmdl)
-               : "1", "cc");
+       err = -EINVAL;
+       asm volatile(
+               "       diag    %1,%3,0x288\n"
+               "0:     la      %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "=d" (err) : "d"(__func), "d"(__timeout),
+                 "d"(__cmdp), "d"(__cmdl), "0" (-EINVAL) : "1", "cc");
        return err;
 }
 
index 438db483035d033a85013e184fcef818a75dcfd2..1398367b5f68ef14f3591f9daf53e582475557b9 100644 (file)
@@ -42,18 +42,15 @@ diag210(struct diag210 * addr)
        spin_lock_irqsave(&diag210_lock, flags);
        diag210_tmp = *addr;
 
-       asm volatile (
-               "   lhi   %0,-1\n"
-               "   sam31\n"
-               "   diag  %1,0,0x210\n"
-               "0: ipm   %0\n"
-               "   srl   %0,28\n"
-               "1: sam64\n"
-               ".section __ex_table,\"a\"\n"
-               "    .align 8\n"
-               "    .quad 0b,1b\n"
-               ".previous"
-               : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory" );
+       asm volatile(
+               "       lhi     %0,-1\n"
+               "       sam31\n"
+               "       diag    %1,0,0x210\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:     sam64\n"
+               EX_TABLE(0b,1b)
+               : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
 
        *addr = diag210_tmp;
        spin_unlock_irqrestore(&diag210_lock, flags);
@@ -66,17 +63,14 @@ diag210(struct diag210 * addr)
 {
        int ccode;
 
-       asm volatile (
-               "   lhi   %0,-1\n"
-               "   diag  %1,0,0x210\n"
-               "0: ipm   %0\n"
-               "   srl   %0,28\n"
+       asm volatile(
+               "       lhi     %0,-1\n"
+               "       diag    %1,0,0x210\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
                "1:\n"
-               ".section __ex_table,\"a\"\n"
-               "    .align 4\n"
-               "    .long 0b,1b\n"
-               ".previous"
-               : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory" );
+               EX_TABLE(0b,1b)
+               : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
 
        return ccode;
 }
index 95a9462f9a911ccc74faea8b9a39235f4b6cebc3..ad6d829400691826659cf3de58ff35f0fa8eed98 100644 (file)
@@ -25,106 +25,74 @@ struct tpi_info {
 static inline int stsch(struct subchannel_id schid,
                            volatile struct schib *addr)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   stsch 0(%2)\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid), "a" (addr), "m" (*addr)
-               : "cc", "1" );
+       asm volatile(
+               "       stsch   0(%2)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
 static inline int stsch_err(struct subchannel_id schid,
                                volatile struct schib *addr)
 {
-       int ccode;
+       register struct subchannel_id reg1 asm ("1") = schid;
+       int ccode = -EIO;
 
-       __asm__ __volatile__(
-               "    lhi  %0,%3\n"
-               "    lr   1,%1\n"
-               "    stsch 0(%2)\n"
-               "0:  ipm  %0\n"
-               "    srl  %0,28\n"
+       asm volatile(
+               "       stsch   0(%2)\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
                "1:\n"
-#ifdef CONFIG_64BIT
-               ".section __ex_table,\"a\"\n"
-               "   .align 8\n"
-               "   .quad 0b,1b\n"
-               ".previous"
-#else
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-               "   .long 0b,1b\n"
-               ".previous"
-#endif
-               : "=&d" (ccode)
-               : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
-               : "cc", "1" );
+               EX_TABLE(0b,1b)
+               : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
 static inline int msch(struct subchannel_id schid,
                           volatile struct schib *addr)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   msch  0(%2)\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid), "a" (addr), "m" (*addr)
-               : "cc", "1" );
+       asm volatile(
+               "       msch    0(%2)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
 static inline int msch_err(struct subchannel_id schid,
                               volatile struct schib *addr)
 {
-       int ccode;
+       register struct subchannel_id reg1 asm ("1") = schid;
+       int ccode = -EIO;
 
-       __asm__ __volatile__(
-               "    lhi  %0,%3\n"
-               "    lr   1,%1\n"
-               "    msch 0(%2)\n"
-               "0:  ipm  %0\n"
-               "    srl  %0,28\n"
+       asm volatile(
+               "       msch    0(%2)\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
                "1:\n"
-#ifdef CONFIG_64BIT
-               ".section __ex_table,\"a\"\n"
-               "   .align 8\n"
-               "   .quad 0b,1b\n"
-               ".previous"
-#else
-               ".section __ex_table,\"a\"\n"
-               "   .align 4\n"
-               "   .long 0b,1b\n"
-               ".previous"
-#endif
-               : "=&d" (ccode)
-               : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
-               : "cc", "1" );
+               EX_TABLE(0b,1b)
+               : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
 static inline int tsch(struct subchannel_id schid,
                           volatile struct irb *addr)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   tsch  0(%2)\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid), "a" (addr), "m" (*addr)
-               : "cc", "1" );
+       asm volatile(
+               "       tsch    0(%2)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
@@ -132,89 +100,77 @@ static inline int tpi( volatile struct tpi_info *addr)
 {
        int ccode;
 
-       __asm__ __volatile__(
-               "   tpi   0(%1)\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "a" (addr), "m" (*addr)
-               : "cc", "1" );
+       asm volatile(
+               "       tpi     0(%1)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
 static inline int ssch(struct subchannel_id schid,
                           volatile struct orb *addr)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   ssch  0(%2)\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid), "a" (addr), "m" (*addr)
-               : "cc", "1" );
+       asm volatile(
+               "       ssch    0(%2)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
 static inline int rsch(struct subchannel_id schid)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   rsch\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid)
-               : "cc", "1" );
+       asm volatile(
+               "       rsch\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1) : "cc");
        return ccode;
 }
 
 static inline int csch(struct subchannel_id schid)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   csch\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid)
-               : "cc", "1" );
+       asm volatile(
+               "       csch\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1) : "cc");
        return ccode;
 }
 
 static inline int hsch(struct subchannel_id schid)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   hsch\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid)
-               : "cc", "1" );
+       asm volatile(
+               "       hsch\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1) : "cc");
        return ccode;
 }
 
 static inline int xsch(struct subchannel_id schid)
 {
+       register struct subchannel_id reg1 asm ("1") = schid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   .insn rre,0xb2760000,%1,0\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (schid)
-               : "cc", "1" );
+       asm volatile(
+               "       .insn   rre,0xb2760000,%1,0\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1) : "cc");
        return ccode;
 }
 
@@ -223,41 +179,27 @@ static inline int chsc(void *chsc_area)
        typedef struct { char _[4096]; } addr_type;
        int cc;
 
-       __asm__ __volatile__ (
-               ".insn  rre,0xb25f0000,%2,0     \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
+       asm volatile(
+               "       .insn   rre,0xb25f0000,%2,0\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
                : "=d" (cc), "=m" (*(addr_type *) chsc_area)
                : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
-               : "cc" );
-
+               : "cc");
        return cc;
 }
 
-static inline int iac( void)
-{
-       int ccode;
-
-       __asm__ __volatile__(
-               "   iac   1\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode) : : "cc", "1" );
-       return ccode;
-}
-
 static inline int rchp(int chpid)
 {
+       register unsigned int reg1 asm ("1") = chpid;
        int ccode;
 
-       __asm__ __volatile__(
-               "   lr    1,%1\n"
-               "   rchp\n"
-               "   ipm   %0\n"
-               "   srl   %0,28"
-               : "=d" (ccode)
-               : "d" (chpid)
-               : "cc", "1" );
+       asm volatile(
+               "       lr      1,%1\n"
+               "       rchp\n"
+               "       ipm     %0\n"
+               "       srl     %0,28"
+               : "=d" (ccode) : "d" (reg1) : "cc");
        return ccode;
 }
 
index 124569362f0220caaf9634ec36d8aeb725b63519..49bb9e371c327e50266ebd4caf42662fd3b54d03 100644 (file)
@@ -274,12 +274,11 @@ do_sqbs(unsigned long sch, unsigned char state, int queue,
        register unsigned long _sch asm ("1") = sch;
        unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
 
-       asm volatile (
-              " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
-              : "+d" (_ccq), "+d" (_queuestart)
-              : "d" ((unsigned long)state), "d" (_sch)
-              : "memory", "cc"
-       );
+       asm volatile(
+              "        .insn   rsy,0xeb000000008A,%1,0,0(%2)"
+              : "+d" (_ccq), "+d" (_queuestart)
+              : "d" ((unsigned long)state), "d" (_sch)
+              : "memory", "cc");
        *count = _ccq & 0xff;
        *start = _queuestart & 0xff;
 
@@ -299,12 +298,11 @@ do_eqbs(unsigned long sch, unsigned char *state, int queue,
        unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
        unsigned long _state = 0;
 
-       asm volatile (
-             " .insn rrf,0xB99c0000,%1,%2,0,0  \n\t"
-             : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
-             : "d" (_sch)
-             : "memory", "cc"
-       );
+       asm volatile(
+               "       .insn   rrf,0xB99c0000,%1,%2,0,0"
+               : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+               : "d" (_sch)
+               : "memory", "cc" );
        *count = _ccq & 0xff;
        *start = _queuestart & 0xff;
        *state = _state & 0xff;
@@ -319,69 +317,35 @@ do_eqbs(unsigned long sch, unsigned char *state, int queue,
 static inline int
 do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
 {
+       register unsigned long reg0 asm ("0") = 2;
+       register struct subchannel_id reg1 asm ("1") = schid;
+       register unsigned long reg2 asm ("2") = mask1;
+       register unsigned long reg3 asm ("3") = mask2;
        int cc;
 
-#ifndef CONFIG_64BIT
-       asm volatile (
-               "lhi    0,2     \n\t"
-               "lr     1,%1    \n\t"
-               "lr     2,%2    \n\t"
-               "lr     3,%3    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
+       asm volatile(
+               "       siga    0\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
                : "=d" (cc)
-               : "d" (schid), "d" (mask1), "d" (mask2)
-               : "cc", "0", "1", "2", "3"
-               );
-#else /* CONFIG_64BIT */
-       asm volatile (
-               "lghi   0,2     \n\t"
-               "llgfr  1,%1    \n\t"
-               "llgfr  2,%2    \n\t"
-               "llgfr  3,%3    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               : "=d" (cc)
-               : "d" (schid), "d" (mask1), "d" (mask2)
-               : "cc", "0", "1", "2", "3"
-               );
-#endif /* CONFIG_64BIT */
+               : "d" (reg0), "d" (reg1), "d" (reg2), "d" (reg3) : "cc");
        return cc;
 }
 
 static inline int
 do_siga_input(struct subchannel_id schid, unsigned int mask)
 {
+       register unsigned long reg0 asm ("0") = 1;
+       register struct subchannel_id reg1 asm ("1") = schid;
+       register unsigned long reg2 asm ("2") = mask;
        int cc;
 
-#ifndef CONFIG_64BIT
-       asm volatile (
-               "lhi    0,1     \n\t"
-               "lr     1,%1    \n\t"
-               "lr     2,%2    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               : "=d" (cc)
-               : "d" (schid), "d" (mask)
-               : "cc", "0", "1", "2", "memory"
-               );
-#else /* CONFIG_64BIT */
-       asm volatile (
-               "lghi   0,1     \n\t"
-               "llgfr  1,%1    \n\t"
-               "llgfr  2,%2    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
+       asm volatile(
+               "       siga    0\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
                : "=d" (cc)
-               : "d" (schid), "d" (mask)
-               : "cc", "0", "1", "2", "memory"
-               );
-#endif /* CONFIG_64BIT */
-       
+               : "d" (reg0), "d" (reg1), "d" (reg2) : "cc", "memory");
        return cc;
 }
 
@@ -389,93 +353,35 @@ static inline int
 do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
               unsigned int fc)
 {
+       register unsigned long __fc asm("0") = fc;
+       register unsigned long __schid asm("1") = schid;
+       register unsigned long __mask asm("2") = mask;
        int cc;
-       __u32 busy_bit;
-
-#ifndef CONFIG_64BIT
-       asm volatile (
-               "lhi    0,0     \n\t"
-               "lr     1,%2    \n\t"
-               "lr     2,%3    \n\t"
-               "siga   0       \n\t"
-               "0:"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               "srl    0,31    \n\t"
-               "lr     %1,0    \n\t"
-               "1:     \n\t"
-               ".section .fixup,\"ax\"\n\t"
-               "2:     \n\t"
-               "lhi    %0,%4   \n\t"
-               "bras   1,3f    \n\t"
-               ".long 1b       \n\t"
-               "3:     \n\t"
-               "l      1,0(1)  \n\t"
-               "br     1       \n\t"
-               ".previous      \n\t"
-               ".section __ex_table,\"a\"\n\t"
-               ".align 4       \n\t"
-               ".long  0b,2b   \n\t"
-               ".previous      \n\t"
-               : "=d" (cc), "=d" (busy_bit)
-               : "d" (schid), "d" (mask),
-               "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
-               : "cc", "0", "1", "2", "memory"
-               );
-#else /* CONFIG_64BIT */
-       asm volatile (
-               "llgfr  0,%5    \n\t"
-                "lgr    1,%2    \n\t"
-               "llgfr  2,%3    \n\t"
-               "siga   0       \n\t"
-               "0:"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               "srl    0,31    \n\t"
-               "llgfr  %1,0    \n\t"
-               "1:     \n\t"
-               ".section .fixup,\"ax\"\n\t"
-               "lghi   %0,%4   \n\t"
-               "jg     1b      \n\t"
-               ".previous\n\t"
-               ".section __ex_table,\"a\"\n\t"
-               ".align 8       \n\t"
-               ".quad  0b,1b   \n\t"
-               ".previous      \n\t"
-               : "=d" (cc), "=d" (busy_bit)
-               : "d" (schid), "d" (mask),
-               "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
-               : "cc", "0", "1", "2", "memory"
-               );
-#endif /* CONFIG_64BIT */
-       
-       (*bb) = busy_bit;
+
+       asm volatile(
+               "       siga    0\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "=d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask)
+               : "0" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
+               : "cc", "memory");
+       (*bb) = ((unsigned int) __fc) >> 31;
        return cc;
 }
 
 static inline unsigned long
 do_clear_global_summary(void)
 {
-
-       unsigned long time;
-
-#ifndef CONFIG_64BIT
-       asm volatile (
-               "lhi    1,3     \n\t"
-               ".insn  rre,0xb2650000,2,0      \n\t"
-               "lr     %0,3    \n\t"
-               : "=d" (time) : : "cc", "1", "2", "3"
-               );
-#else /* CONFIG_64BIT */
-       asm volatile (
-               "lghi   1,3     \n\t"
-               ".insn  rre,0xb2650000,2,0      \n\t"
-               "lgr    %0,3    \n\t"
-               : "=d" (time) : : "cc", "1", "2", "3"
-               );
-#endif /* CONFIG_64BIT */
-       
-       return time;
+       register unsigned long __fn asm("1") = 3;
+       register unsigned long __tmp asm("2");
+       register unsigned long __time asm("3");
+
+       asm volatile(
+               "       .insn   rre,0xb2650000,2,0"
+               : "+d" (__fn), "=d" (__tmp), "=d" (__time));
+       return __time;
 }
        
 /*
index 821dde86e240c611a32a3cf6c576db73f39c182f..809dd8d7f47ab034510e88ccf06dfcb39ddf3e15 100644 (file)
@@ -534,19 +534,15 @@ iucv_add_handler (handler *new)
  *
  * Returns: return code from CP's IUCV call
  */
-static __inline__ ulong
-b2f0(__u32 code, void *parm)
+static inline ulong b2f0(__u32 code, void *parm)
 {
+       register unsigned long reg0 asm ("0");
+       register unsigned long reg1 asm ("1");
        iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
 
-       asm volatile (
-               "LRA   1,0(%1)\n\t"
-               "LR    0,%0\n\t"
-               ".long 0xb2f01000"
-               :
-               : "d" (code), "a" (parm)
-               : "0", "1"
-               );
+       reg0 = code;
+       reg1 = virt_to_phys(parm);
+       asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
 
        iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
 
@@ -1248,6 +1244,8 @@ iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
 static int
 iucv_query_generic(int want_maxconn)
 {
+       register unsigned long reg0 asm ("0");
+       register unsigned long reg1 asm ("1");
        iparml_purge *parm = (iparml_purge *)grab_param();
        int bufsize, maxconn;
        int ccode;
@@ -1256,18 +1254,15 @@ iucv_query_generic(int want_maxconn)
         * Call b2f0 and store R0 (max buffer size),
         * R1 (max connections) and CC.
         */
-       asm volatile (
-               "LRA   1,0(%4)\n\t"
-               "LR    0,%3\n\t"
-               ".long 0xb2f01000\n\t"
-               "IPM   %0\n\t"
-               "SRL   %0,28\n\t"
-               "ST    0,%1\n\t"
-               "ST    1,%2\n\t"
-               : "=d" (ccode), "=m" (bufsize), "=m" (maxconn)
-               : "d" (QUERY), "a" (parm)
-               : "0", "1", "cc"
-               );
+       reg0 = QUERY;
+       reg1 = virt_to_phys(parm);
+       asm volatile(
+               "       .long   0xb2f01000\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
+               : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
+       bufsize = reg0;
+       maxconn = reg1;
        release_param(parm);
 
        if (ccode)
index 5613b4564fa2967f3b78a37fff49c87e621301be..8364d5475ac7fa5a8d2898f3a65d4d70a57b3066 100644 (file)
@@ -8067,7 +8067,7 @@ qeth_arp_constructor(struct neighbour *neigh)
        neigh->parms = neigh_parms_clone(parms);
        rcu_read_unlock();
 
-       neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
+       neigh->type = inet_addr_type(*(__be32 *) neigh->primary_key);
        neigh->nud_state = NUD_NOARP;
        neigh->ops = arp_direct_ops;
        neigh->output = neigh->ops->queue_xmit;
index a914129a4da9862ba3f58d2269b14a58df7e3271..479364d0332a062c2424fbf16728464fb3c29b7a 100644 (file)
@@ -253,11 +253,12 @@ s390_revalidate_registers(struct mci *mci)
                kill_task = 1;
 
 #ifndef CONFIG_64BIT
-       asm volatile("ld 0,0(%0)\n"
-                    "ld 2,8(%0)\n"
-                    "ld 4,16(%0)\n"
-                    "ld 6,24(%0)"
-                    : : "a" (&S390_lowcore.floating_pt_save_area));
+       asm volatile(
+               "       ld      0,0(%0)\n"
+               "       ld      2,8(%0)\n"
+               "       ld      4,16(%0)\n"
+               "       ld      6,24(%0)"
+               : : "a" (&S390_lowcore.floating_pt_save_area));
 #endif
 
        if (MACHINE_HAS_IEEE) {
@@ -274,37 +275,36 @@ s390_revalidate_registers(struct mci *mci)
                         * Floating point control register can't be restored.
                         * Task will be terminated.
                         */
-                       asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
+                       asm volatile("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
                        kill_task = 1;
 
-               }
-               else
-                       asm volatile (
-                               "lfpc 0(%0)"
-                               : : "a" (fpt_creg_save_area));
-
-               asm volatile("ld  0,0(%0)\n"
-                            "ld  1,8(%0)\n"
-                            "ld  2,16(%0)\n"
-                            "ld  3,24(%0)\n"
-                            "ld  4,32(%0)\n"
-                            "ld  5,40(%0)\n"
-                            "ld  6,48(%0)\n"
-                            "ld  7,56(%0)\n"
-                            "ld  8,64(%0)\n"
-                            "ld  9,72(%0)\n"
-                            "ld 10,80(%0)\n"
-                            "ld 11,88(%0)\n"
-                            "ld 12,96(%0)\n"
-                            "ld 13,104(%0)\n"
-                            "ld 14,112(%0)\n"
-                            "ld 15,120(%0)\n"
-                            : : "a" (fpt_save_area));
+               } else
+                       asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
+
+               asm volatile(
+                       "       ld      0,0(%0)\n"
+                       "       ld      1,8(%0)\n"
+                       "       ld      2,16(%0)\n"
+                       "       ld      3,24(%0)\n"
+                       "       ld      4,32(%0)\n"
+                       "       ld      5,40(%0)\n"
+                       "       ld      6,48(%0)\n"
+                       "       ld      7,56(%0)\n"
+                       "       ld      8,64(%0)\n"
+                       "       ld      9,72(%0)\n"
+                       "       ld      10,80(%0)\n"
+                       "       ld      11,88(%0)\n"
+                       "       ld      12,96(%0)\n"
+                       "       ld      13,104(%0)\n"
+                       "       ld      14,112(%0)\n"
+                       "       ld      15,120(%0)\n"
+                       : : "a" (fpt_save_area));
        }
 
        /* Revalidate access registers */
-       asm volatile("lam 0,15,0(%0)"
-                    : : "a" (&S390_lowcore.access_regs_save_area));
+       asm volatile(
+               "       lam     0,15,0(%0)"
+               : : "a" (&S390_lowcore.access_regs_save_area));
        if (!mci->ar)
                /*
                 * Access registers have unknown contents.
@@ -321,11 +321,13 @@ s390_revalidate_registers(struct mci *mci)
                s390_handle_damage("invalid control registers.");
        else
 #ifdef CONFIG_64BIT
-               asm volatile("lctlg 0,15,0(%0)"
-                            : : "a" (&S390_lowcore.cregs_save_area));
+               asm volatile(
+                       "       lctlg   0,15,0(%0)"
+                       : : "a" (&S390_lowcore.cregs_save_area));
 #else
-               asm volatile("lctl 0,15,0(%0)"
-                            : : "a" (&S390_lowcore.cregs_save_area));
+               asm volatile(
+                       "       lctl    0,15,0(%0)"
+                       : : "a" (&S390_lowcore.cregs_save_area));
 #endif
 
        /*
@@ -339,20 +341,23 @@ s390_revalidate_registers(struct mci *mci)
         * old contents (should be zero) otherwise set it to zero.
         */
        if (!mci->pr)
-               asm volatile("sr 0,0\n"
-                            "sckpf"
-                            : : : "0", "cc");
+               asm volatile(
+                       "       sr      0,0\n"
+                       "       sckpf"
+                       : : : "0", "cc");
        else
                asm volatile(
-                       "l 0,0(%0)\n"
-                       "sckpf"
-                       : : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
+                       "       l       0,0(%0)\n"
+                       "       sckpf"
+                       : : "a" (&S390_lowcore.tod_progreg_save_area)
+                       : "0", "cc");
 #endif
 
        /* Revalidate clock comparator register */
-       asm volatile ("stck 0(%1)\n"
-                     "sckc 0(%1)"
-                     : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+       asm volatile(
+               "       stck    0(%1)\n"
+               "       sckc    0(%1)"
+               : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
 
        /* Check if old PSW is valid */
        if (!mci->wp)
index 7cafa34e4c7f5b17a0aa1e8cfe19b4c97057af2e..4d2bc7981324b4fc5abe939fbcca0f26895e0c91 100644 (file)
@@ -301,7 +301,7 @@ zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt,
                       int use_timer)
 {
        int ret;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
 
        scpnt->SCp.ptr = (void *) &wait;  /* silent re-use */
        scpnt->scsi_done = zfcp_scsi_command_sync_handler;
index 657a3ab75399426b23f7028a925b37d2860fdd97..15ce40a7053a6dfae5ccfcc20fc69b507483106b 100644 (file)
@@ -1939,7 +1939,7 @@ NCR_700_abort(struct scsi_cmnd * SCp)
 STATIC int
 NCR_700_bus_reset(struct scsi_cmnd * SCp)
 {
-       DECLARE_COMPLETION(complete);
+       DECLARE_COMPLETION_ONSTACK(complete);
        struct NCR_700_Host_Parameters *hostdata = 
                (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
 
index 9792e5af5252c4a6378490667fe64f5318c64dac..d6d1d5613c8aa9e6a207204cdd0127112a548761 100644 (file)
@@ -237,10 +237,7 @@ enum BusLogic_BIOS_DiskGeometryTranslation {
   Define a Boolean data type.
 */
 
-typedef enum {
-       false,
-       true
-} PACKED boolean;
+typedef bool boolean;
 
 /*
   Define a 10^18 Statistics Byte Counter data type.
index c4dfcc91dddaa07ea474037fd60f9245ae962d98..dab082002e6fe572f10e9e46f4cafecba2f3dbc7 100644 (file)
@@ -3,11 +3,13 @@ menu "SCSI device support"
 config RAID_ATTRS
        tristate "RAID Transport Class"
        default n
+       depends on BLOCK
        ---help---
          Provides RAID
 
 config SCSI
        tristate "SCSI device support"
+       depends on BLOCK
        ---help---
          If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
          any other SCSI device under Linux, say Y and make sure that you know
index 0e4a7ebe300a07d1bb51686cbc804436b639ae2f..6b35ed8301e0dac3211968409505bc2f4f63fbb2 100644 (file)
@@ -681,6 +681,7 @@ static struct eisa_device_id aha1740_ids[] = {
        { "ADP0400" },          /* 1744  */
        { "" }
 };
+MODULE_DEVICE_TABLE(eisa, aha1740_ids);
 
 static struct eisa_driver aha1740_driver = {
        .id_table = aha1740_ids,
index 867cbe23579b6310f583187c4b927494f4edb54b..1ac119733bac3b2ceef4fea3a228931037366664 100644 (file)
@@ -132,7 +132,8 @@ static struct eisa_device_id aic7770_ids[] = {
        { "ADP7770", 5 }, /* AIC7770 generic */
        { "" }
 };
-  
+MODULE_DEVICE_TABLE(eisa, aic7770_ids);
+
 static struct eisa_driver aic7770_driver = {
        .id_table       = aic7770_ids,
        .driver = {
index c7eeaced324afe4954a1fa79b06716dce5bf5d70..1faa008b5b817047d16c0f976523ba746105ab9a 100644 (file)
@@ -646,7 +646,7 @@ ahd_linux_dev_reset(struct scsi_cmnd *cmd)
        struct  ahd_initiator_tinfo *tinfo;
        struct  ahd_tmode_tstate *tstate;
        unsigned long flags;
-       DECLARE_COMPLETION(done);
+       DECLARE_COMPLETION_ONSTACK(done);
 
        reset_scb = NULL;
        paused = FALSE;
@@ -2251,7 +2251,7 @@ done:
        if (paused)
                ahd_unpause(ahd);
        if (wait) {
-               DECLARE_COMPLETION(done);
+               DECLARE_COMPLETION_ONSTACK(done);
 
                ahd->platform_data->eh_done = &done;
                ahd_unlock(ahd, &flags);
index 64c8b88a429fa1d11228138babe693518db30edb..339b85cb61cdbefb4a5bb9af77da7caf9f03b4ed 100644 (file)
@@ -2335,7 +2335,7 @@ done:
        if (paused)
                ahc_unpause(ahc);
        if (wait) {
-               DECLARE_COMPLETION(done);
+               DECLARE_COMPLETION_ONSTACK(done);
 
                ahc->platform_data->eh_done = &done;
                ahc_unlock(ahc, &flags);
index 5dcef48d414faeaf9ce636c093e924a719d9eea0..10353379a0741e5f4f4f784ad230c4cba6249192 100644 (file)
@@ -2862,7 +2862,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
       aic_dev->r_total++;
       ptr = aic_dev->r_bins;
     }
-    if(cmd->device->simple_tags && cmd->request->flags & REQ_HARDBARRIER)
+    if(cmd->device->simple_tags && cmd->request->cmd_flags & REQ_HARDBARRIER)
     {
       aic_dev->barrier_total++;
       if(scb->tag_action == MSG_ORDERED_Q_TAG)
@@ -10158,7 +10158,7 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
     /* We always force TEST_UNIT_READY to untagged */
     if (cmd->cmnd[0] != TEST_UNIT_READY && sdptr->simple_tags)
     {
-      if (req->flags & REQ_HARDBARRIER)
+      if (req->cmd_flags & REQ_HARDBARRIER)
       {
        if(sdptr->ordered_tags)
        {
index 43afd476e606adad053fb3a1ff8d94dccb5b1cb8..0f3eb22b979a1b8345dcf75e6d3bd83c09580c6e 100644 (file)
@@ -724,7 +724,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
                    int timeout, u32 *info)
 {
     Scsi_Cmnd *scp;
-    DECLARE_COMPLETION(wait);
+    DECLARE_COMPLETION_ONSTACK(wait);
     int rval;
 
     scp = kmalloc(sizeof(*scp), GFP_KERNEL);
@@ -764,7 +764,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
 {
     Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE);
     unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0;
-    DECLARE_COMPLETION(wait);
+    DECLARE_COMPLETION_ONSTACK(wait);
     int rval;
 
     if (!scp)
index 94d1de55607f2dc00a05605259b0d8e864937062..1427a41e844104149a7e71c4a3e639f01711718b 100644 (file)
@@ -344,7 +344,7 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
        pc->buffer = buf;
        pc->c[0] = REQUEST_SENSE;
        pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE;
-       rq->flags = REQ_SENSE;
+       rq->cmd_type = REQ_TYPE_SENSE;
        pc->timeout = jiffies + WAIT_READY;
        /* NOTE! Save the failed packet command in "rq->buffer" */
        rq->buffer = (void *) failed_command->special;
@@ -398,12 +398,12 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
        int errors = rq->errors;
        unsigned long flags;
 
-       if (!(rq->flags & (REQ_SPECIAL|REQ_SENSE))) {
+       if (!blk_special_request(rq) && !blk_sense_request(rq)) {
                ide_end_request(drive, uptodate, nrsecs);
                return 0;
        }
        ide_end_drive_cmd (drive, 0, 0);
-       if (rq->flags & REQ_SENSE) {
+       if (blk_sense_request(rq)) {
                idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
                if (log) {
                        printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
@@ -708,11 +708,11 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
 static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
 {
 #if IDESCSI_DEBUG_LOG
-       printk (KERN_INFO "rq_status: %d, dev: %s, cmd: %x, errors: %d\n",rq->rq_status, rq->rq_disk->disk_name,rq->cmd[0],rq->errors);
+       printk (KERN_INFO "dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name,rq->cmd[0],rq->errors);
        printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
 #endif /* IDESCSI_DEBUG_LOG */
 
-       if (rq->flags & (REQ_SPECIAL|REQ_SENSE)) {
+       if (blk_sense_request(rq) || blk_special_request(rq)) {
                return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special);
        }
        blk_dump_rq_flags(rq, "ide-scsi: unsup command");
@@ -938,7 +938,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
 
        ide_init_drive_cmd (rq);
        rq->special = (char *) pc;
-       rq->flags = REQ_SPECIAL;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
        spin_unlock_irq(host->host_lock);
        rq->rq_disk = scsi->disk;
        (void) ide_do_drive_cmd (drive, rq, ide_end);
@@ -992,7 +992,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
                 */
                printk (KERN_ERR "ide-scsi: cmd aborted!\n");
 
-               if (scsi->pc->rq->flags & REQ_SENSE)
+               if (blk_sense_request(scsi->pc->rq))
                        kfree(scsi->pc->buffer);
                kfree(scsi->pc->rq);
                kfree(scsi->pc);
@@ -1042,7 +1042,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
        /* kill current request */
        blkdev_dequeue_request(req);
        end_that_request_last(req, 0);
-       if (req->flags & REQ_SENSE)
+       if (blk_sense_request(req))
                kfree(scsi->pc->buffer);
        kfree(scsi->pc);
        scsi->pc = NULL;
index 7f9e89bcac7eacc4feae3b9a9bc6df846244a1c6..e46e79355b776ec98a407962694a8e3756414571 100644 (file)
@@ -126,7 +126,7 @@ static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd)
        enum task_attribute ta = TASK_ATTR_SIMPLE;
        if (cmd->request && blk_rq_tagged(cmd->request)) {
                if (cmd->device->ordered_tags &&
-                   (cmd->request->flags & REQ_HARDBARRIER))
+                   (cmd->request->cmd_flags & REQ_HARDBARRIER))
                        ta = TASK_ATTR_HOQ;
        }
        return ta;
index 0bd9c60e6455b879b831c4b7a64854422213ee8c..aa60a5f1fbc3b5b639cf0123900b0ba862a36518 100644 (file)
@@ -67,7 +67,6 @@ static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
 
 static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
 {
-       SCpnt->request->rq_status = RQ_SCSI_DONE;
        PLND(("Detect done %08lx\n", (long)SCpnt))
        if (atomic_dec_and_test (&fcss))
                up(&fc_sem);
@@ -166,7 +165,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
                
                SCpnt->cmd_len = COMMAND_SIZE(INQUIRY);
        
-               SCpnt->request->rq_status = RQ_SCSI_BUSY;
+               SCpnt->request->cmd_flags &= ~REQ_STARTED;
                
                SCpnt->done = pluto_detect_done;
                SCpnt->request_bufflen = 256;
@@ -178,7 +177,8 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
        for (retry = 0; retry < 5; retry++) {
                for (i = 0; i < fcscount; i++) {
                        if (!fcs[i].fc) break;
-                       if (fcs[i].cmd.request->rq_status != RQ_SCSI_DONE) {
+                       if (!(fcs[i].cmd.request->cmd_flags & REQ_STARTED)) {
+                               fcs[i].cmd.request->cmd_flags |= REQ_STARTED;
                                disable_irq(fcs[i].fc->irq);
                                PLND(("queuecommand %d %d\n", retry, i))
                                fcp_scsi_queuecommand (&(fcs[i].cmd), 
index 8953991462d78f3d9600ea6445ed08820e133ec4..332151e2a0189eb57a529eb4461afc218811a492 100644 (file)
@@ -813,7 +813,7 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
        uint16_t data;
        unsigned char *handle;
        int result, i;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
        struct timer_list timer;
 
        ha = (struct scsi_qla_host *)(CMD_HOST(cmd)->hostdata);
@@ -2406,7 +2406,7 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb)
        uint16_t *optr, *iptr;
        uint16_t __iomem *mptr;
        uint16_t data;
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
        struct timer_list timer;
 
        ENTER("qla1280_mailbox_command");
index 7a054f9d1ee38230a7b59344e3e791d217f46d79..da95bce907dd3a23257637510bb12e3613bc6a6c 100644 (file)
@@ -592,12 +592,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
        return rtn;
 }
 
-
-/*
- * Per-CPU I/O completion queue.
- */
-static DEFINE_PER_CPU(struct list_head, scsi_done_q);
-
 /**
  * scsi_req_abort_cmd -- Request command recovery for the specified command
  * cmd: pointer to the SCSI command of interest
@@ -1065,7 +1059,7 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
 
        spin_lock_irqsave(&sdev->list_lock, flags);
        list_for_each_entry(scmd, &sdev->cmd_list, list) {
-               if (scmd->request && scmd->request->rq_status != RQ_INACTIVE) {
+               if (scmd->request) {
                        /*
                         * If we are unable to remove the timer, it means
                         * that the command has already timed out or
@@ -1102,7 +1096,7 @@ MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
 
 static int __init init_scsi(void)
 {
-       int error, i;
+       int error;
 
        error = scsi_init_queue();
        if (error)
@@ -1123,9 +1117,6 @@ static int __init init_scsi(void)
        if (error)
                goto cleanup_sysctl;
 
-       for_each_possible_cpu(i)
-               INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
-
        scsi_netlink_init();
 
        printk(KERN_NOTICE "SCSI subsystem initialized\n");
index d6743b959a72b151f1d6ade6d70b6d3b70c44d92..71084728eb42322462af7a6f0980d627af54e725 100644 (file)
@@ -82,7 +82,7 @@ static void scsi_unprep_request(struct request *req)
 {
        struct scsi_cmnd *cmd = req->special;
 
-       req->flags &= ~REQ_DONTPREP;
+       req->cmd_flags &= ~REQ_DONTPREP;
        req->special = NULL;
 
        scsi_put_command(cmd);
@@ -196,7 +196,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
        req->sense_len = 0;
        req->retries = retries;
        req->timeout = timeout;
-       req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
+       req->cmd_type = REQ_TYPE_BLOCK_PC;
+       req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT;
 
        /*
         * head injection *required* here otherwise quiesce won't work
@@ -397,7 +398,8 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
        req = blk_get_request(sdev->request_queue, write, gfp);
        if (!req)
                goto free_sense;
-       req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+       req->cmd_type = REQ_TYPE_BLOCK_PC;
+       req->cmd_flags |= REQ_QUIET;
 
        if (use_sg)
                err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
@@ -933,7 +935,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                        break;
                                }
                        }
-                       if (!(req->flags & REQ_QUIET)) {
+                       if (!(req->cmd_flags & REQ_QUIET)) {
                                scmd_printk(KERN_INFO, cmd,
                                            "Device not ready: ");
                                scsi_print_sense_hdr("", &sshdr);
@@ -941,7 +943,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                        scsi_end_request(cmd, 0, this_count, 1);
                        return;
                case VOLUME_OVERFLOW:
-                       if (!(req->flags & REQ_QUIET)) {
+                       if (!(req->cmd_flags & REQ_QUIET)) {
                                scmd_printk(KERN_INFO, cmd,
                                            "Volume overflow, CDB: ");
                                __scsi_print_command(cmd->cmnd);
@@ -963,7 +965,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                return;
        }
        if (result) {
-               if (!(req->flags & REQ_QUIET)) {
+               if (!(req->cmd_flags & REQ_QUIET)) {
                        scmd_printk(KERN_INFO, cmd,
                                    "SCSI error: return code = 0x%08x\n",
                                    result);
@@ -995,7 +997,7 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
        /*
         * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer
         */
-       if ((req->flags & REQ_BLOCK_PC) && !req->bio) {
+       if (blk_pc_request(req) && !req->bio) {
                cmd->request_bufflen = req->data_len;
                cmd->request_buffer = req->data;
                req->buffer = req->data;
@@ -1139,13 +1141,12 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
         * these two cases differently.  We differentiate by looking
         * at request->cmd, as this tells us the real story.
         */
-       if (req->flags & REQ_SPECIAL && req->special) {
+       if (blk_special_request(req) && req->special)
                cmd = req->special;
-       } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
-
-               if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
-                       if(specials_only == SDEV_QUIESCE ||
-                                       specials_only == SDEV_BLOCK)
+       else if (blk_pc_request(req) || blk_fs_request(req)) {
+               if (unlikely(specials_only) && !(req->cmd_flags & REQ_PREEMPT)){
+                       if (specials_only == SDEV_QUIESCE ||
+                           specials_only == SDEV_BLOCK)
                                goto defer;
                        
                        sdev_printk(KERN_ERR, sdev,
@@ -1153,7 +1154,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                        goto kill;
                }
                        
-                       
                /*
                 * Now try and find a command block that we can use.
                 */
@@ -1184,7 +1184,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
         * lock.  We hope REQ_STARTED prevents anything untoward from
         * happening now.
         */
-       if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+       if (blk_fs_request(req) || blk_pc_request(req)) {
                int ret;
 
                /*
@@ -1216,7 +1216,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                /*
                 * Initialize the actual SCSI command for this request.
                 */
-               if (req->flags & REQ_BLOCK_PC) {
+               if (blk_pc_request(req)) {
                        scsi_setup_blk_pc_cmnd(cmd);
                } else if (req->rq_disk) {
                        struct scsi_driver *drv;
@@ -1233,7 +1233,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
        /*
         * The request is now prepped, no need to come back here
         */
-       req->flags |= REQ_DONTPREP;
+       req->cmd_flags |= REQ_DONTPREP;
        return BLKPREP_OK;
 
  defer:
@@ -1454,8 +1454,9 @@ static void scsi_request_fn(struct request_queue *q)
                if (unlikely(cmd == NULL)) {
                        printk(KERN_CRIT "impossible request in %s.\n"
                                         "please mail a stack trace to "
-                                        "linux-scsi@vger.kernel.org",
+                                        "linux-scsi@vger.kernel.org\n",
                                         __FUNCTION__);
+                       blk_dump_rq_flags(req, "foo");
                        BUG();
                }
                spin_lock(shost->host_lock);
index 638cff41d436777fa85afc31dfd6213f227b2637..10bc99c911faf55744dc226f04b4fe84fc210800 100644 (file)
@@ -443,8 +443,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                SCpnt->cmnd[0] = READ_6;
                SCpnt->sc_data_direction = DMA_FROM_DEVICE;
        } else {
-               printk(KERN_ERR "sd: Unknown command %lx\n", rq->flags);
-/* overkill    panic("Unknown sd command %lx\n", rq->flags); */
+               printk(KERN_ERR "sd: Unknown command %x\n", rq->cmd_flags);
                return 0;
        }
 
@@ -840,7 +839,7 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector)
 static void sd_prepare_flush(request_queue_t *q, struct request *rq)
 {
        memset(rq->cmd, 0, sizeof(rq->cmd));
-       rq->flags |= REQ_BLOCK_PC;
+       rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->timeout = SD_TIMEOUT;
        rq->cmd[0] = SYNCHRONIZE_CACHE;
        rq->cmd_len = 10;
index b27e85428daab7a59decef0a2ba3e170afb0bca2..551baccec5230c57ec2fb3bcdf714d7969fe1fab 100644 (file)
@@ -282,6 +282,7 @@ static struct eisa_device_id sim710_eisa_ids[] = {
        { "HWP0C80" },
        { "" }
 };
+MODULE_DEVICE_TABLE(eisa, sim710_eisa_ids);
 
 static __init int
 sim710_eisa_probe(struct device *dev)
index 2f8073b73bf30d1d5924498ec899c8984c0549ff..7f9bcef6adfa941cfa07cc3301a57b62177cd7ca 100644 (file)
@@ -2017,7 +2017,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done
                                                  != cmd))
                {
-                       if(cmd->request->flags & REQ_CMD) {
+                       if(blk_fs_request(cmd->request)) {
                                sun3scsi_dma_setup(d, count,
                                                   rq_data_dir(cmd->request));
                                sun3_dma_setup_done = cmd;
index 837173415d4c8442ae7bb036be84452b7c1d615e..44a99aeb818046355a17a4fbb9b94b34506878f7 100644 (file)
@@ -524,7 +524,7 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
 static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd,
                                    int write_flag)
 {
-       if(cmd->request->flags & REQ_CMD)
+       if(blk_fs_request(cmd->request))
                return wanted;
        else
                return 0;
index 008a82ab8521e9142bc4845e0f03298a7645ca75..f5742b84b27aa28bf4b6ed0e16f23a4c20cc1745 100644 (file)
@@ -458,7 +458,7 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
 static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd,
                                    int write_flag)
 {
-       if(cmd->request->flags & REQ_CMD)
+       if(blk_fs_request(cmd->request))
                return wanted;
        else
                return 0;
index 32af3650e8b44bace902d939d58f4e57403c1e2b..ef8cc8a70c6092e018a7e34b98a7c66426140bec 100644 (file)
@@ -35,6 +35,7 @@ struct serial_card_type {
 struct serial_card_info {
        unsigned int    num_ports;
        int             ports[MAX_PORTS];
+       void __iomem *vaddr;
 };
 
 static int __devinit
@@ -44,7 +45,6 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
        struct serial_card_type *type = id->data;
        struct uart_port port;
        unsigned long bus_addr;
-       unsigned char __iomem *virt_addr;
        unsigned int i;
 
        info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
@@ -55,8 +55,8 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
        info->num_ports = type->num_ports;
 
        bus_addr = ecard_resource_start(ec, type->type);
-       virt_addr = ioremap(bus_addr, ecard_resource_len(ec, type->type));
-       if (!virt_addr) {
+       info->vaddr = ioremap(bus_addr, ecard_resource_len(ec, type->type));
+       if (!info->vaddr) {
                kfree(info);
                return -ENOMEM;
        }
@@ -72,7 +72,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
        port.dev        = &ec->dev;
 
        for (i = 0; i < info->num_ports; i ++) {
-               port.membase = virt_addr + type->offset[i];
+               port.membase = info->vaddr + type->offset[i];
                port.mapbase = bus_addr + type->offset[i];
 
                info->ports[i] = serial8250_register_port(&port);
@@ -92,6 +92,7 @@ static void __devexit serial_card_remove(struct expansion_card *ec)
                if (info->ports[i] > 0)
                        serial8250_unregister_port(info->ports[i]);
 
+       iounmap(info->vaddr);
        kfree(info);
 }
 
index 913c71cc056939b0295a78c1a6f3a644fb9aa2b3..1ebe6b585d2d57d3c44b4d52bcceebb3b5fdfd78 100644 (file)
@@ -64,6 +64,7 @@ serial_init_chip(struct parisc_device *dev)
        err = serial8250_register_port(&port);
        if (err < 0) {
                printk(KERN_WARNING "serial8250_register_port returned error %d\n", err);
+               iounmap(port.membase);
                return err;
        }
         
index 5b48ac22c9c5964b62b93500831f1656a1b84e1a..d926272a40db59ed23a956078e90b58a640f0e84 100644 (file)
@@ -295,7 +295,7 @@ config SERIAL_AMBA_PL011_CONSOLE
          Even if you say Y here, the currently visible framebuffer console
          (/dev/tty0) will still be used as the system console by default, but
          you can alter that using a kernel command line option such as
-         "console=ttyAM0". (Try "man bootparam" or see the documentation of
+         "console=ttyAMA0". (Try "man bootparam" or see the documentation of
          your boot loader (lilo or loadlin) about how to pass options to the
          kernel at boot time.)
 
@@ -642,12 +642,17 @@ config V850E_UART_CONSOLE
        select SERIAL_CORE_CONSOLE
 
 config SERIAL_SH_SCI
-       tristate "SH SCI(F) serial port support"
+       tristate "SuperH SCI(F) serial port support"
        depends on SUPERH || H8300
        select SERIAL_CORE
 
+config SERIAL_SH_SCI_NR_UARTS
+       int "Maximum number of SCI(F) serial ports"
+       depends on SERIAL_SH_SCI
+       default "2"
+
 config SERIAL_SH_SCI_CONSOLE
-       bool "Support for console on SH SCI(F)"
+       bool "Support for console on SuperH SCI(F)"
        depends on SERIAL_SH_SCI=y
        select SERIAL_CORE_CONSOLE
 
index 54c6b2adf7b73c57a2023768a8e11b6cc545bd9e..bf4bf103e5a0aff82476cc45a399d6b1b1f35aff 100644 (file)
@@ -139,7 +139,7 @@ static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
                 * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21.
                 *  We need to drive the pin manually.
                 */
-               if (port->mapbase == AT91_BASE_US0) {
+               if (port->mapbase == AT91RM9200_BASE_US0) {
                        if (mctrl & TIOCM_RTS)
                                at91_set_gpio_value(AT91_PIN_PA21, 0);
                        else
index 576ca1eaa2b68119acedf4fc4ea33ee2a3209a3f..5ec4716c99bf30e5bd16bb271e45aa1f38207343 100644 (file)
@@ -2685,6 +2685,7 @@ static int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
        if (soft) {
                free_irq(control->ic_irq, soft);
                if (soft->is_ioc4_serial_addr) {
+                       iounmap(soft->is_ioc4_serial_addr);
                        release_region((unsigned long)
                             soft->is_ioc4_serial_addr,
                                sizeof(struct ioc4_serial));
@@ -2887,6 +2888,8 @@ out4:
 out3:
        kfree(control);
 out2:
+       if (serial)
+               iounmap(serial);
        release_region(tmp_addr1, sizeof(struct ioc4_serial));
 out1:
 
index 5ff269fb604c051212449d18a1270e2da174c855..dbf13c03a1bbceac17df1de52d1608f8812ceac0 100644 (file)
@@ -1229,13 +1229,27 @@ static int __init ip22zilog_init(void)
 static void __exit ip22zilog_exit(void)
 {
        int i;
+       struct uart_ip22zilog_port *up;
 
        for (i = 0; i < NUM_CHANNELS; i++) {
-               struct uart_ip22zilog_port *up = &ip22zilog_port_table[i];
+               up = &ip22zilog_port_table[i];
 
                uart_remove_one_port(&ip22zilog_reg, &up->port);
        }
 
+       /* Free IO mem */
+       up = &ip22zilog_port_table[0];
+       for (i = 0; i < NUM_IP22ZILOG; i++) {
+               if (up[(i * 2) + 0].port.mapbase) {
+                  iounmap((void*)up[(i * 2) + 0].port.mapbase);
+                  up[(i * 2) + 0].port.mapbase = 0;
+               }
+               if (up[(i * 2) + 1].port.mapbase) {
+                       iounmap((void*)up[(i * 2) + 1].port.mapbase);
+                       up[(i * 2) + 1].port.mapbase = 0;
+               }
+       }
+
        uart_unregister_driver(&ip22zilog_reg);
 }
 
index 7708e5dd3656967882ae990d1984e33b361301b3..dbad0e31e005864cb02c72b9f293ecbc11e906d5 100644 (file)
@@ -338,14 +338,23 @@ mpc52xx_uart_release_port(struct uart_port *port)
 static int
 mpc52xx_uart_request_port(struct uart_port *port)
 {
+       int err;
+
        if (port->flags & UPF_IOREMAP) /* Need to remap ? */
                port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
 
        if (!port->membase)
                return -EINVAL;
 
-       return request_mem_region(port->mapbase, MPC52xx_PSC_SIZE,
+       err = request_mem_region(port->mapbase, MPC52xx_PSC_SIZE,
                        "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
+
+       if (err && (port->flags & UPF_IOREMAP)) {
+               iounmap(port->membase);
+               port->membase = NULL;
+       }
+
+       return err;
 }
 
 static void
index 63d2a66e563bac3823fbb699b11ecabce44cdbb3..704243c9f78a44c2d58f560d1cd4301aaafeb138 100644 (file)
@@ -1893,6 +1893,10 @@ mpsc_drv_map_regs(struct mpsc_port_info *pi, struct platform_device *pd)
        }
        else {
                mpsc_resource_err("SDMA base");
+               if (pi->mpsc_base) {
+                       iounmap(pi->mpsc_base);
+                       pi->mpsc_base = NULL;
+               }
                return -ENOMEM;
        }
 
@@ -1905,6 +1909,14 @@ mpsc_drv_map_regs(struct mpsc_port_info *pi, struct platform_device *pd)
        }
        else {
                mpsc_resource_err("BRG base");
+               if (pi->mpsc_base) {
+                       iounmap(pi->mpsc_base);
+                       pi->mpsc_base = NULL;
+               }
+               if (pi->sdma_base) {
+                       iounmap(pi->sdma_base);
+                       pi->sdma_base = NULL;
+               }
                return -ENOMEM;
        }
 
index 4a1c9983f38f8e38a78e47f761b996da129c6969..aa819d3f8ee51344d58b2939c39f396d4698a058 100644 (file)
@@ -521,6 +521,8 @@ static void __exit mux_exit(void)
 
        for (i = 0; i < port_cnt; i++) {
                uart_remove_one_port(&mux_driver, &mux_ports[i]);
+               if (mux_ports[i].membase)
+                       iounmap(mux_ports[i].membase);
        }
 
        uart_unregister_driver(&mux_driver);
index cbede06cac27915d92664b1019b5a859adfdbb62..f336ba6778dd6bdbbffe4fd2a9f37a930021544d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
  *
- *  Copyright (C) 2002, 2003, 2004  Paul Mundt
+ *  Copyright (C) 2002 - 2006  Paul Mundt
  *
  * based off of the old drivers/char/sh-sci.c by:
  *
 
 #undef DEBUG
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/sysrq.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/console.h>
-#include <linux/bitops.h>
-#include <linux/generic_serial.h>
+#include <linux/platform_device.h>
 
 #ifdef CONFIG_CPU_FREQ
 #include <linux/notifier.h>
 #include <linux/cpufreq.h>
 #endif
 
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
 #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
 #include <asm/clock.h>
-#endif
-
-#ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
+#include <asm/kgdb.h>
 #endif
 
+#include <asm/sci.h>
+
 #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
 
 #include "sh-sci.h"
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
+struct sci_port {
+       struct uart_port        port;
+
+       /* Port type */
+       unsigned int            type;
+
+       /* Port IRQs: ERI, RXI, TXI, BRI (optional) */
+       unsigned int            irqs[SCIx_NR_IRQS]; 
+
+       /* Port pin configuration */
+       void                    (*init_pins)(struct uart_port *port,
+                                            unsigned int cflag);
 
-static int kgdb_get_char(struct sci_port *port);
-static void kgdb_put_char(struct sci_port *port, char c);
-static void kgdb_handle_error(struct sci_port *port);
+       /* Port enable callback */
+       void                    (*enable)(struct uart_port *port);
+
+       /* Port disable callback */
+       void                    (*disable)(struct uart_port *port);
+
+       /* Break timer */
+       struct timer_list       break_timer;
+       int                     break_flag;
+};
+
+#ifdef CONFIG_SH_KGDB
 static struct sci_port *kgdb_sci_port;
-#endif /* CONFIG_SH_KGDB */
+#endif
 
 #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-static struct sci_port *serial_console_port = 0;
-#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
+static struct sci_port *serial_console_port;
+#endif
 
 /* Function prototypes */
 static void sci_stop_tx(struct uart_port *port);
-static void sci_start_tx(struct uart_port *port);
-static void sci_start_rx(struct uart_port *port, unsigned int tty_start);
-static void sci_stop_rx(struct uart_port *port);
-static int sci_request_irq(struct sci_port *port);
-static void sci_free_irq(struct sci_port *port);
-
-static struct sci_port sci_ports[];
-static struct uart_driver sci_uart_driver;
 
-#define SCI_NPORTS sci_uart_driver.nr
+#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
 
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+static struct sci_port sci_ports[SCI_NPORTS];
+static struct uart_driver sci_uart_driver;
 
-static void handle_error(struct uart_port *port)
-{                              /* Clear error flags */
+#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && \
+    defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+static inline void handle_error(struct uart_port *port)
+{
+       /* Clear error flags */
        sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
 }
 
@@ -106,8 +111,8 @@ static int get_char(struct uart_port *port)
        unsigned short status;
        int c;
 
-       local_irq_save(flags);
-        do {
+       spin_lock_irqsave(&port->lock, flags);
+       do {
                status = sci_in(port, SCxSR);
                if (status & SCxSR_ERRORS(port)) {
                        handle_error(port);
@@ -117,38 +122,19 @@ static int get_char(struct uart_port *port)
        c = sci_in(port, SCxRDR);
        sci_in(port, SCxSR);            /* Dummy read */
        sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
-       local_irq_restore(flags);
+       spin_unlock_irqrestore(&port->lock, flags);
 
        return c;
 }
-
-/* Taken from sh-stub.c of GDB 4.18 */
-static const char hexchars[] = "0123456789abcdef";
-
-static __inline__ char highhex(int  x)
-{
-       return hexchars[(x >> 4) & 0xf];
-}
-
-static __inline__ char lowhex(int  x)
-{
-       return hexchars[x & 0xf];
-}
-
 #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
 
-/*
- * Send the packet in buffer.  The host gets one chance to read it.
- * This routine does not wait for a positive acknowledge.
- */
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || defined(CONFIG_SH_KGDB)
 static void put_char(struct uart_port *port, char c)
 {
        unsigned long flags;
        unsigned short status;
 
-       local_irq_save(flags);
+       spin_lock_irqsave(&port->lock, flags);
 
        do {
                status = sci_in(port, SCxSR);
@@ -158,9 +144,11 @@ static void put_char(struct uart_port *port, char c)
        sci_in(port, SCxSR);            /* Dummy read */
        sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
 
-       local_irq_restore(flags);
+       spin_unlock_irqrestore(&port->lock, flags);
 }
+#endif
 
+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
 static void put_string(struct sci_port *sci_port, const char *buffer, int count)
 {
        struct uart_port *port = &sci_port->port;
@@ -213,96 +201,28 @@ static void put_string(struct sci_port *sci_port, const char *buffer, int count)
 }
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
-
 #ifdef CONFIG_SH_KGDB
-
-/* Is the SCI ready, ie is there a char waiting? */
-static int kgdb_is_char_ready(struct sci_port *port)
-{
-        unsigned short status = sci_in(port, SCxSR);
-
-        if (status & (SCxSR_ERRORS(port) | SCxSR_BRK(port)))
-                kgdb_handle_error(port);
-
-        return (status & SCxSR_RDxF(port));
-}
-
-/* Write a char */
-static void kgdb_put_char(struct sci_port *port, char c)
-{
-        unsigned short status;
-
-        do
-                status = sci_in(port, SCxSR);
-        while (!(status & SCxSR_TDxE(port)));
-
-        sci_out(port, SCxTDR, c);
-        sci_in(port, SCxSR);    /* Dummy read */
-        sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
-}
-
-/* Get a char if there is one, else ret -1 */
-static int kgdb_get_char(struct sci_port *port)
-{
-        int c;
-
-        if (kgdb_is_char_ready(port) == 0)
-                c = -1;
-        else {
-                c = sci_in(port, SCxRDR);
-                sci_in(port, SCxSR);    /* Dummy read */
-                sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
-        }
-
-        return c;
-}
-
-/* Called from kgdbstub.c to get a character, i.e. is blocking */
 static int kgdb_sci_getchar(void)
 {
-        volatile int c;
+        int c;
 
         /* Keep trying to read a character, this could be neater */
-        while ((c = kgdb_get_char(kgdb_sci_port)) < 0);
+        while ((c = get_char(kgdb_sci_port)) < 0)
+               cpu_relax();
 
         return c;
 }
 
-/* Called from kgdbstub.c to put a character, just a wrapper */
-static void kgdb_sci_putchar(int c)
-{
-
-        kgdb_put_char(kgdb_sci_port, c);
-}
-
-/* Clear any errors on the SCI */
-static void kgdb_handle_error(struct sci_port *port)
+static inline void kgdb_sci_putchar(int c)
 {
-        sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));  /* Clear error flags */
+        put_char(kgdb_sci_port, c);
 }
-
-/* Breakpoint if there's a break sent on the serial port */
-static void kgdb_break_interrupt(int irq, void *ptr, struct pt_regs *regs)
-{
-        struct sci_port *port = ptr;
-        unsigned short status = sci_in(port, SCxSR);
-
-        if (status & SCxSR_BRK(port)) {
-
-                /* Break into the debugger if a break is detected */
-                BREAKPOINT();
-
-                /* Clear */
-                sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
-        }
-}
-
 #endif /* CONFIG_SH_KGDB */
 
 #if defined(__H8300S__)
 enum { sci_disable, sci_enable };
 
-static void h8300_sci_enable(struct uart_port* port, unsigned int ctrl)
+static void h8300_sci_config(struct uart_port* port, unsigned int ctrl)
 {
        volatile unsigned char *mstpcrl=(volatile unsigned char *)MSTPCRL;
        int ch = (port->mapbase  - SMR0) >> 3;
@@ -314,32 +234,66 @@ static void h8300_sci_enable(struct uart_port* port, unsigned int ctrl)
                *mstpcrl &= ~mask;
        }
 }
+
+static inline void h8300_sci_enable(struct uart_port *port)
+{
+       h8300_sci_config(port, sci_enable);
+}
+
+static inline void h8300_sci_disable(struct uart_port *port)
+{
+       h8300_sci_config(port, sci_disable);
+}
 #endif
 
-#if defined(SCI_ONLY) || defined(SCI_AND_SCIF)
-#if defined(__H8300H__) || defined(__H8300S__)
+#if defined(SCI_ONLY) || defined(SCI_AND_SCIF) && \
+    defined(__H8300H__) || defined(__H8300S__)
 static void sci_init_pins_sci(struct uart_port* port, unsigned int cflag)
 {
        int ch = (port->mapbase - SMR0) >> 3;
 
        /* set DDR regs */
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,h8300_sci_pins[ch].rx,H8300_GPIO_INPUT);
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,h8300_sci_pins[ch].tx,H8300_GPIO_OUTPUT);
+       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
+                      h8300_sci_pins[ch].rx,
+                      H8300_GPIO_INPUT);
+       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
+                      h8300_sci_pins[ch].tx,
+                      H8300_GPIO_OUTPUT);
+
        /* tx mark output*/
        H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
 }
+#else
+#define sci_init_pins_sci NULL
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
+{
+       unsigned int fcr_val = 0;
+
+       if (cflag & CRTSCTS)
+               fcr_val |= SCFCR_MCE;
+
+       sci_out(port, SCFCR, fcr_val);
+}
+#else
+#define sci_init_pins_irda NULL
 #endif
+
+#ifdef SCI_ONLY
+#define sci_init_pins_scif NULL
 #endif
 
 #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
 /* SH7300 doesn't use RTS/CTS */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
        sci_out(port, SCFCR, 0);
 }
 #elif defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7707, SH7709, SH7709A, SH7729 */
+/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
        unsigned int fcr_val = 0;
@@ -366,20 +320,7 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 
        sci_out(port, SCFCR, fcr_val);
 }
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
-{
-       unsigned int fcr_val = 0;
-
-       if (cflag & CRTSCTS)
-               fcr_val |= SCFCR_MCE;
-
-       sci_out(port, SCFCR, fcr_val);
-}
-#endif
 #else
-
 /* For SH7750 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
@@ -388,7 +329,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
        if (cflag & CRTSCTS) {
                fcr_val |= SCFCR_MCE;
        } else {
-#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#ifdef CONFIG_CPU_SUBTYPE_SH7343
+               /* Nothing */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
                ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
 #else
                ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
@@ -396,10 +339,41 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
        }
        sci_out(port, SCFCR, fcr_val);
 }
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+static inline int scif_txroom(struct uart_port *port)
+{
+       return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
+}
+
+static inline int scif_rxroom(struct uart_port *port)
+{
+       return sci_in(port, SCRFDR) & 0x7f;
+}
+#else
+static inline int scif_txroom(struct uart_port *port)
+{
+       return SCIF_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
+}
 
+static inline int scif_rxroom(struct uart_port *port)
+{
+       return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+}
 #endif
 #endif /* SCIF_ONLY || SCI_AND_SCIF */
 
+static inline int sci_txroom(struct uart_port *port)
+{
+       return ((sci_in(port, SCxSR) & SCI_TDRE) != 0);
+}
+
+static inline int sci_rxroom(struct uart_port *port)
+{
+       return ((sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0);
+}
+
 /* ********************************************************************** *
  *                   the interrupt related routines                       *
  * ********************************************************************** */
@@ -408,14 +382,12 @@ static void sci_transmit_chars(struct uart_port *port)
 {
        struct circ_buf *xmit = &port->info->xmit;
        unsigned int stopped = uart_tx_stopped(port);
-       unsigned long flags;
        unsigned short status;
        unsigned short ctrl;
-       int count, txroom;
+       int count;
 
        status = sci_in(port, SCxSR);
        if (!(status & SCxSR_TDxE(port))) {
-               local_irq_save(flags);
                ctrl = sci_in(port, SCSCR);
                if (uart_circ_empty(xmit)) {
                        ctrl &= ~SCI_CTRL_FLAGS_TIE;
@@ -423,25 +395,15 @@ static void sci_transmit_chars(struct uart_port *port)
                        ctrl |= SCI_CTRL_FLAGS_TIE;
                }
                sci_out(port, SCSCR, ctrl);
-               local_irq_restore(flags);
                return;
        }
 
-#if !defined(SCI_ONLY)
-       if (port->type == PORT_SCIF) {
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
-               txroom = SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
-#else
-               txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8);
-#endif
-       } else {
-               txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
-       }
-#else
-       txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
+#ifndef SCI_ONLY
+       if (port->type == PORT_SCIF)
+               count = scif_txroom(port);
+       else
 #endif
-
-       count = txroom;
+               count = sci_txroom(port);
 
        do {
                unsigned char c;
@@ -468,7 +430,6 @@ static void sci_transmit_chars(struct uart_port *port)
        if (uart_circ_empty(xmit)) {
                sci_stop_tx(port);
        } else {
-               local_irq_save(flags);
                ctrl = sci_in(port, SCSCR);
 
 #if !defined(SCI_ONLY)
@@ -480,7 +441,6 @@ static void sci_transmit_chars(struct uart_port *port)
 
                ctrl |= SCI_CTRL_FLAGS_TIE;
                sci_out(port, SCSCR, ctrl);
-               local_irq_restore(flags);
        }
 }
 
@@ -490,6 +450,7 @@ static void sci_transmit_chars(struct uart_port *port)
 static inline void sci_receive_chars(struct uart_port *port,
                                     struct pt_regs *regs)
 {
+       struct sci_port *sci_port = (struct sci_port *)port;
        struct tty_struct *tty = port->info->tty;
        int i, count, copied = 0;
        unsigned short status;
@@ -501,18 +462,11 @@ static inline void sci_receive_chars(struct uart_port *port,
 
        while (1) {
 #if !defined(SCI_ONLY)
-               if (port->type == PORT_SCIF) {
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
-                       count = sci_in(port, SCRFDR) & 0x7f;
-#else
-                       count = sci_in(port, SCFDR)&SCIF_RFDC_MASK ;
-#endif
-               } else {
-                       count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
-               }
-#else
-               count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
+               if (port->type == PORT_SCIF)
+                       count = scif_rxroom(port);
+               else
 #endif
+                       count = sci_rxroom(port);
 
                /* Don't copy more bytes than there is room for in the buffer */
                count = tty_buffer_request_room(tty, count);
@@ -523,11 +477,10 @@ static inline void sci_receive_chars(struct uart_port *port,
 
                if (port->type == PORT_SCI) {
                        char c = sci_in(port, SCxRDR);
-                       if(((struct sci_port *)port)->break_flag
-                           || uart_handle_sysrq_char(port, c, regs)) {
+                       if (uart_handle_sysrq_char(port, c, regs) || sci_port->break_flag)
                                count = 0;
-                       else {
-                           tty_insert_flip_char(tty, c, TTY_NORMAL);
+                       else {
+                               tty_insert_flip_char(tty, c, TTY_NORMAL);
                        }
                } else {
                        for (i=0; i<count; i++) {
@@ -535,15 +488,17 @@ static inline void sci_receive_chars(struct uart_port *port,
                                status = sci_in(port, SCxSR);
 #if defined(CONFIG_CPU_SH3)
                                /* Skip "chars" during break */
-                               if (((struct sci_port *)port)->break_flag) {
+                               if (sci_port->break_flag) {
                                        if ((c == 0) &&
                                            (status & SCxSR_FER(port))) {
                                                count--; i--;
                                                continue;
                                        }
+
                                        /* Nonzero => end-of-break */
                                        pr_debug("scif: debounce<%02x>\n", c);
-                                       ((struct sci_port *)port)->break_flag = 0;
+                                       sci_port->break_flag = 0;
+
                                        if (STEPFN(c)) {
                                                count--; i--;
                                                continue;
@@ -600,15 +555,17 @@ static void sci_schedule_break_timer(struct sci_port *port)
 /* Ensure that two consecutive samples find the break over. */
 static void sci_break_timer(unsigned long data)
 {
-    struct sci_port * port = (struct sci_port *)data;
-       if(sci_rxd_in(&port->port) == 0) {
+       struct sci_port *port = (struct sci_port *)data;
+
+       if (sci_rxd_in(&port->port) == 0) {
                port->break_flag = 1;
-           sci_schedule_break_timer(port);
-       } else if(port->break_flag == 1){
+               sci_schedule_break_timer(port);
+       } else if (port->break_flag == 1) {
                /* break is over. */
                port->break_flag = 2;
-           sci_schedule_break_timer(port);
-       } else port->break_flag = 0;
+               sci_schedule_break_timer(port);
+       } else
+               port->break_flag = 0;
 }
 
 static inline int sci_handle_errors(struct uart_port *port)
@@ -617,40 +574,41 @@ static inline int sci_handle_errors(struct uart_port *port)
        unsigned short status = sci_in(port, SCxSR);
        struct tty_struct *tty = port->info->tty;
 
-       if (status&SCxSR_ORER(port)) {
+       if (status & SCxSR_ORER(port)) {
                /* overrun error */
-               if(tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+               if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
                        copied++;
                pr_debug("sci: overrun error\n");
        }
 
-       if (status&SCxSR_FER(port)) {
+       if (status & SCxSR_FER(port)) {
                if (sci_rxd_in(port) == 0) {
                        /* Notify of BREAK */
-                       struct sci_port * sci_port = (struct sci_port *)port;
-                       if(!sci_port->break_flag) {
-                               sci_port->break_flag = 1;
-                               sci_schedule_break_timer((struct sci_port *)port);
+                       struct sci_port *sci_port = (struct sci_port *)port;
+
+                       if (!sci_port->break_flag) {
+                               sci_port->break_flag = 1;
+                               sci_schedule_break_timer(sci_port);
+
                                /* Do sysrq handling. */
-                               if(uart_handle_break(port))
+                               if (uart_handle_break(port))
                                        return 0;
                                pr_debug("sci: BREAK detected\n");
-                               if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+                               if (tty_insert_flip_char(tty, 0, TTY_BREAK))
                                        copied++;
                        }
-               }
-               else {
+               } else {
                        /* frame error */
-                       if(tty_insert_flip_char(tty, 0, TTY_FRAME))
+                       if (tty_insert_flip_char(tty, 0, TTY_FRAME))
                                copied++;
                        pr_debug("sci: frame error\n");
                }
        }
 
-       if (status&SCxSR_PER(port)) {
-               if(tty_insert_flip_char(tty, 0, TTY_PARITY))
-                       copied++;
+       if (status & SCxSR_PER(port)) {
                /* parity error */
+               if (tty_insert_flip_char(tty, 0, TTY_PARITY))
+                       copied++;
                pr_debug("sci: parity error\n");
        }
 
@@ -673,7 +631,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
                s->break_flag = 1;
 #endif
                /* Notify of BREAK */
-               if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+               if (tty_insert_flip_char(tty, 0, TTY_BREAK))
                        copied++;
                pr_debug("sci: BREAK detected\n");
        }
@@ -682,7 +640,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
        /* XXX: Handle SCIF overrun error */
        if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
                sci_out(port, SCLSR, 0);
-               if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
+               if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
                        copied++;
                        pr_debug("sci: overrun error\n");
                }
@@ -691,13 +649,12 @@ static inline int sci_handle_breaks(struct uart_port *port)
 
        if (copied)
                tty_flip_buffer_push(tty);
+
        return copied;
 }
 
-static irqreturn_t sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sci_rx_interrupt(int irq, void *port, struct pt_regs *regs)
 {
-       struct uart_port *port = ptr;
-
        /* I think sci_receive_chars has to be called irrespective
         * of whether the I_IXOFF is set, otherwise, how is the interrupt
         * to be disabled?
@@ -711,7 +668,9 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs)
 {
        struct uart_port *port = ptr;
 
+       spin_lock_irq(&port->lock);
        sci_transmit_chars(port);
+       spin_unlock_irq(&port->lock);
 
        return IRQ_HANDLED;
 }
@@ -755,6 +714,12 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs)
 
        /* Handle BREAKs */
        sci_handle_breaks(port);
+
+#ifdef CONFIG_SH_KGDB
+       /* Break into the debugger if a break is detected */
+       BREAKPOINT();
+#endif
+
        sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
 
        return IRQ_HANDLED;
@@ -769,16 +734,16 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs)
         scr_status = sci_in(port,SCSCR);
 
        /* Tx Interrupt */
-        if ((ssr_status&0x0020) && (scr_status&0x0080))
+        if ((ssr_status & 0x0020) && (scr_status & 0x0080))
                 sci_tx_interrupt(irq, ptr, regs);
        /* Rx Interrupt */
-        if ((ssr_status&0x0002) && (scr_status&0x0040))
+        if ((ssr_status & 0x0002) && (scr_status & 0x0040))
                 sci_rx_interrupt(irq, ptr, regs);
        /* Error Interrupt */
-        if ((ssr_status&0x0080) && (scr_status&0x0400))
+        if ((ssr_status & 0x0080) && (scr_status & 0x0400))
                 sci_er_interrupt(irq, ptr, regs);
        /* Break Interrupt */
-        if ((ssr_status&0x0010) && (scr_status&0x0200))
+        if ((ssr_status & 0x0010) && (scr_status & 0x0200))
                 sci_br_interrupt(irq, ptr, regs);
 
        return IRQ_HANDLED;
@@ -789,7 +754,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs)
  * Here we define a transistion notifier so that we can update all of our
  * ports' baud rate when the peripheral clock changes.
  */
-static int sci_notifier(struct notifier_block *self, unsigned long phase, void *p)
+static int sci_notifier(struct notifier_block *self,
+                       unsigned long phase, void *p)
 {
        struct cpufreq_freqs *freqs = p;
        int i;
@@ -816,8 +782,9 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void *
                        clk_put(clk);
                }
 
-               printk("%s: got a postchange notification for cpu %d (old %d, new %d)\n",
-                               __FUNCTION__, freqs->cpu, freqs->old, freqs->new);
+               printk(KERN_INFO "%s: got a postchange notification "
+                      "for cpu %d (old %d, new %d)\n",
+                      __FUNCTION__, freqs->cpu, freqs->old, freqs->new);
        }
 
        return NOTIFY_OK;
@@ -841,8 +808,9 @@ static int sci_request_irq(struct sci_port *port)
                        printk(KERN_ERR "sci: Cannot allocate irq.(IRQ=0)\n");
                        return -ENODEV;
                }
-               if (request_irq(port->irqs[0], sci_mpxed_interrupt, IRQF_DISABLED,
-                               "sci", port)) {
+
+               if (request_irq(port->irqs[0], sci_mpxed_interrupt,
+                               SA_INTERRUPT, "sci", port)) {
                        printk(KERN_ERR "sci: Cannot allocate irq.\n");
                        return -ENODEV;
                }
@@ -850,8 +818,8 @@ static int sci_request_irq(struct sci_port *port)
                for (i = 0; i < ARRAY_SIZE(handlers); i++) {
                        if (!port->irqs[i])
                                continue;
-                       if (request_irq(port->irqs[i], handlers[i], IRQF_DISABLED,
-                                       desc[i], port)) {
+                       if (request_irq(port->irqs[i], handlers[i],
+                                       SA_INTERRUPT, desc[i], port)) {
                                printk(KERN_ERR "sci: Cannot allocate irq.\n");
                                return -ENODEV;
                        }
@@ -903,50 +871,42 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
 
 static void sci_start_tx(struct uart_port *port)
 {
-       struct sci_port *s = &sci_ports[port->line];
+       unsigned short ctrl;
 
-       disable_irq(s->irqs[SCIx_TXI_IRQ]);
-       sci_transmit_chars(port);
-       enable_irq(s->irqs[SCIx_TXI_IRQ]);
+       /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
+       ctrl = sci_in(port, SCSCR);
+       ctrl |= SCI_CTRL_FLAGS_TIE;
+       sci_out(port, SCSCR, ctrl);
 }
 
 static void sci_stop_tx(struct uart_port *port)
 {
-       unsigned long flags;
        unsigned short ctrl;
 
        /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
-       local_irq_save(flags);
        ctrl = sci_in(port, SCSCR);
        ctrl &= ~SCI_CTRL_FLAGS_TIE;
        sci_out(port, SCSCR, ctrl);
-       local_irq_restore(flags);
 }
 
 static void sci_start_rx(struct uart_port *port, unsigned int tty_start)
 {
-       unsigned long flags;
        unsigned short ctrl;
 
        /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
-       local_irq_save(flags);
        ctrl = sci_in(port, SCSCR);
        ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
        sci_out(port, SCSCR, ctrl);
-       local_irq_restore(flags);
 }
 
 static void sci_stop_rx(struct uart_port *port)
 {
-       unsigned long flags;
        unsigned short ctrl;
 
        /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
-       local_irq_save(flags);
        ctrl = sci_in(port, SCSCR);
        ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
        sci_out(port, SCSCR, ctrl);
-       local_irq_restore(flags);
 }
 
 static void sci_enable_ms(struct uart_port *port)
@@ -963,9 +923,8 @@ static int sci_startup(struct uart_port *port)
 {
        struct sci_port *s = &sci_ports[port->line];
 
-#if defined(__H8300S__)
-       h8300_sci_enable(port, sci_enable);
-#endif
+       if (s->enable)
+               s->enable(port);
 
        sci_request_irq(s);
        sci_start_tx(port);
@@ -982,9 +941,8 @@ static void sci_shutdown(struct uart_port *port)
        sci_stop_tx(port);
        sci_free_irq(s);
 
-#if defined(__H8300S__)
-       h8300_sci_enable(port, sci_disable);
-#endif
+       if (s->disable)
+               s->disable(port);
 }
 
 static void sci_set_termios(struct uart_port *port, struct termios *termios,
@@ -997,6 +955,23 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
 
+       switch (baud) {
+               case 0:
+                       t = -1;
+                       break;
+               default:
+               {
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+                       struct clk *clk = clk_get("module_clk");
+                       t = SCBRR_VALUE(baud, clk_get_rate(clk));
+                       clk_put(clk);
+#else
+                       t = SCBRR_VALUE(baud);
+#endif
+               }
+                       break;
+       }
+
        spin_lock_irqsave(&port->lock, flags);
 
        do {
@@ -1006,9 +981,8 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
        sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
 
 #if !defined(SCI_ONLY)
-       if (port->type == PORT_SCIF) {
+       if (port->type == PORT_SCIF)
                sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
-       }
 #endif
 
        smr_val = sci_in(port, SCSMR) & 3;
@@ -1025,23 +999,6 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
 
        sci_out(port, SCSMR, smr_val);
 
-       switch (baud) {
-               case 0:
-                       t = -1;
-                       break;
-               default:
-               {
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
-                       struct clk *clk = clk_get("module_clk");
-                       t = SCBRR_VALUE(baud, clk_get_rate(clk));
-                       clk_put(clk);
-#else
-                       t = SCBRR_VALUE(baud);
-#endif
-               }
-                       break;
-       }
-
        if (t > 0) {
                if(t >= 256) {
                        sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
@@ -1092,11 +1049,23 @@ static void sci_config_port(struct uart_port *port, int flags)
 
        port->type = s->type;
 
+       switch (port->type) {
+       case PORT_SCI:
+               s->init_pins = sci_init_pins_sci;
+               break;
+       case PORT_SCIF:
+               s->init_pins = sci_init_pins_scif;
+               break;
+       case PORT_IRDA:
+               s->init_pins = sci_init_pins_irda;
+               break;
+       }
+
 #if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
        if (port->mapbase == 0)
                port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF");
 
-       port->membase = (void *)port->mapbase;
+       port->membase = (void __iomem *)port->mapbase;
 #endif
 }
 
@@ -1132,412 +1101,61 @@ static struct uart_ops sci_uart_ops = {
        .verify_port    = sci_verify_port,
 };
 
-static struct sci_port sci_ports[] = {
-#if defined(CONFIG_CPU_SUBTYPE_SH7708)
-       {
-               .port   = {
-                       .membase        = (void *)0xfffffe80,
-                       .mapbase        = 0xfffffe80,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = SCI_IRQS,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-       {
-               .port   = {
-                       .membase        = (void *)SCIF0,
-                       .mapbase        = SCIF0,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 55,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH3_IRDA_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)SCIF2,
-                       .mapbase        = SCIF2,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 59,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH3_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-       {
-               .port   = {
-                       .membase        = (void *)0xfffffe80,
-                       .mapbase        = 0xfffffe80,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = SCI_IRQS,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xa4000150,
-                       .mapbase        = 0xa4000150,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 59,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH3_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xa4000140,
-                       .mapbase        = 0xa4000140,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 55,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_IRDA,
-               .irqs           = SH3_IRDA_IRQS,
-               .init_pins      = sci_init_pins_irda,
-       }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
-       {
-               .port   = {
-                       .membase        = (void *)0xA4430000,
-                       .mapbase        = 0xA4430000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7300_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH73180_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe80000,
-                       .mapbase        = 0xffe80000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH4_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = SCI_IRQS,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xffe80000,
-                       .mapbase        = 0xffe80000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH4_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-       {
-               .port   = {
-                       .membase        = (void *)0xfe600000,
-                       .mapbase        = 0xfe600000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 55,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7760_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xfe610000,
-                       .mapbase        = 0xfe610000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 75,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7760_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xfe620000,
-                       .mapbase        = 0xfe620000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 79,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7760_SCIF2_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 26,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = STB1_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xffe80000,
-                       .mapbase        = 0xffe80000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH4_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-       {
-               .port   = {
-                       .iotype         = UPIO_MEM,
-                       .irq            = 42,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH5_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffffb0,
-                       .mapbase        = 0x00ffffb0,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 54,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8300H_SCI_IRQS0,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffffb8,
-                       .mapbase        = 0x00ffffb8,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 58,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8300H_SCI_IRQS1,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffffc0,
-                       .mapbase        = 0x00ffffc0,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 62,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8300H_SCI_IRQS2,
-               .init_pins      = sci_init_pins_sci,
-       },
-#elif defined(CONFIG_H8S2678)
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffff78,
-                       .mapbase        = 0x00ffff78,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 90,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8S_SCI_IRQS0,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffff80,
-                       .mapbase        = 0x00ffff80,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 94,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8S_SCI_IRQS1,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffff88,
-                       .mapbase        = 0x00ffff88,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 98,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8S_SCI_IRQS2,
-               .init_pins      = sci_init_pins_sci,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-       {
-               .port   = {
-                       .membase        = (void *)0xff923000,
-                       .mapbase        = 0xff923000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 61,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7770_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xff924000,
-                       .mapbase        = 0xff924000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 62,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7770_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xff925000,
-                       .mapbase        = 0xff925000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 63,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7770_SCIF2_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7780_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xffe10000,
-                       .mapbase        = 0xffe10000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 79,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7780_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
+static void __init sci_init_ports(void)
+{
+       static int first = 1;
+       int i;
+
+       if (!first)
+               return;
+
+       first = 0;
+
+       for (i = 0; i < SCI_NPORTS; i++) {
+               sci_ports[i].port.ops           = &sci_uart_ops;
+               sci_ports[i].port.iotype        = UPIO_MEM;
+               sci_ports[i].port.line          = i;
+               sci_ports[i].port.fifosize      = 1;
+
+#if defined(__H8300H__) || defined(__H8300S__)
+#ifdef __H8300S__
+               sci_ports[i].enable     = h8300_sci_enable;
+               sci_ports[i].disable    = h8300_sci_disable;
+#endif
+               sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK;
+#elif defined(CONFIG_SUPERH64)
+               sci_ports[i].port.uartclk = current_cpu_data.module_clock * 16;
 #else
-#error "CPU subtype not defined"
+               /*
+                * XXX: We should use a proper SCI/SCIF clock
+                */
+               {
+                       struct clk *clk = clk_get("module_clk");
+                       sci_ports[i].port.uartclk = clk_get_rate(clk) * 16;
+                       clk_put(clk);
+               }
 #endif
-};
+
+               sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i];
+               sci_ports[i].break_timer.function = sci_break_timer;
+
+               init_timer(&sci_ports[i].break_timer);
+       }
+}
+
+int __init early_sci_setup(struct uart_port *port)
+{
+       if (unlikely(port->line > SCI_NPORTS))
+               return -ENODEV;
+
+       sci_init_ports();
+
+       sci_ports[port->line].port.membase      = port->membase;
+       sci_ports[port->line].port.mapbase      = port->mapbase;
+       sci_ports[port->line].port.type         = port->type;
+
+       return 0;
+}
 
 #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
 /*
@@ -1559,34 +1177,38 @@ static int __init serial_console_setup(struct console *co, char *options)
        int flow = 'n';
        int ret;
 
+       /*
+        * Check whether an invalid uart number has been specified, and
+        * if so, search for the first available port that does have
+        * console support.
+        */
+       if (co->index >= SCI_NPORTS)
+               co->index = 0;
+
        serial_console_port = &sci_ports[co->index];
        port = &serial_console_port->port;
-       port->type = serial_console_port->type;
-
-#ifdef CONFIG_SUPERH64
-       /* This is especially needed on sh64 to remap the SCIF */
-       sci_config_port(port, 0);
-#endif
 
        /*
-        * We need to set the initial uartclk here, since otherwise it will
-        * only ever be setup at sci_init() time.
+        * Also need to check port->type, we don't actually have any
+        * UPIO_PORT ports, but uart_report_port() handily misreports
+        * it anyways if we don't have a port available by the time this is
+        * called.
         */
-#if defined(__H8300H__) || defined(__H8300S__)
-       port->uartclk = CONFIG_CPU_CLOCK;
+       if (!port->type)
+               return -ENODEV;
+       if (!port->membase || !port->mapbase)
+               return -ENODEV;
+
+       spin_lock_init(&port->lock);
+
+       port->type = serial_console_port->type;
+
+       if (port->flags & UPF_IOREMAP)
+               sci_config_port(port, 0);
+
+       if (serial_console_port->enable)
+               serial_console_port->enable(port);
 
-#if defined(__H8300S__)
-       h8300_sci_enable(port, sci_enable);
-#endif
-#elif defined(CONFIG_SUPERH64)
-       port->uartclk = current_cpu_data.module_clock * 16;
-#else
-       {
-               struct clk *clk = clk_get("module_clk");
-               port->uartclk = clk_get_rate(clk) * 16;
-               clk_put(clk);
-       }
-#endif
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
@@ -1604,17 +1226,17 @@ static struct console serial_console = {
        .device         = uart_console_device,
        .write          = serial_console_write,
        .setup          = serial_console_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER, 
        .index          = -1,
        .data           = &sci_uart_driver,
 };
 
 static int __init sci_console_init(void)
 {
+       sci_init_ports();
        register_console(&serial_console);
        return 0;
 }
-
 console_initcall(sci_console_init);
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
@@ -1649,6 +1271,8 @@ int __init kgdb_console_setup(struct console *co, char *options)
        int parity = 'n';
        int flow = 'n';
 
+       spin_lock_init(&port->lock);
+
        if (co->index != kgdb_portnum)
                co->index = kgdb_portnum;
 
@@ -1677,10 +1301,10 @@ static struct console kgdb_console = {
 /* Register the KGDB console so we get messages (d'oh!) */
 static int __init kgdb_console_init(void)
 {
+       sci_init_ports();
        register_console(&kgdb_console);
        return 0;
 }
-
 console_initcall(kgdb_console_init);
 #endif /* CONFIG_SH_KGDB_CONSOLE */
 
@@ -1701,60 +1325,132 @@ static struct uart_driver sci_uart_driver = {
        .dev_name       = "ttySC",
        .major          = SCI_MAJOR,
        .minor          = SCI_MINOR_START,
+       .nr             = SCI_NPORTS,
        .cons           = SCI_CONSOLE,
 };
 
-static int __init sci_init(void)
+/*
+ * Register a set of serial devices attached to a platform device.  The
+ * list is terminated with a zero flags entry, which means we expect
+ * all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need
+ * remapping (such as sh64) should also set UPF_IOREMAP.
+ */
+static int __devinit sci_probe(struct platform_device *dev)
 {
-       int chan, ret;
+       struct plat_sci_port *p = dev->dev.platform_data;
+       int i;
 
-       printk("%s", banner);
+       for (i = 0; p && p->flags != 0 && i < SCI_NPORTS; p++, i++) {
+               struct sci_port *sciport = &sci_ports[i];
 
-       sci_uart_driver.nr = ARRAY_SIZE(sci_ports);
+               sciport->port.mapbase   = p->mapbase;
 
-       ret = uart_register_driver(&sci_uart_driver);
-       if (ret == 0) {
-               for (chan = 0; chan < SCI_NPORTS; chan++) {
-                       struct sci_port *sciport = &sci_ports[chan];
+               /*
+                * For the simple (and majority of) cases where we don't need
+                * to do any remapping, just cast the cookie directly.
+                */
+               if (p->mapbase && !p->membase && !(p->flags & UPF_IOREMAP))
+                       p->membase = (void __iomem *)p->mapbase;
 
-#if defined(__H8300H__) || defined(__H8300S__)
-                       sciport->port.uartclk = CONFIG_CPU_CLOCK;
-#elif defined(CONFIG_SUPERH64)
-                       sciport->port.uartclk = current_cpu_data.module_clock * 16;
-#else
-                       struct clk *clk = clk_get("module_clk");
-                       sciport->port.uartclk = clk_get_rate(clk) * 16;
-                       clk_put(clk);
-#endif
-                       uart_add_one_port(&sci_uart_driver, &sciport->port);
-                       sciport->break_timer.data = (unsigned long)sciport;
-                       sciport->break_timer.function = sci_break_timer;
-                       init_timer(&sciport->break_timer);
-               }
+               sciport->port.membase   = p->membase;
+
+               sciport->port.irq       = p->irqs[SCIx_TXI_IRQ];
+               sciport->port.flags     = p->flags;
+               sciport->port.dev       = &dev->dev;
+
+               sciport->type           = sciport->port.type = p->type;
+
+               memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs));
+
+               uart_add_one_port(&sci_uart_driver, &sciport->port);
        }
 
 #ifdef CONFIG_CPU_FREQ
        cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
-       printk("sci: CPU frequency notifier registered\n");
+       dev_info(&dev->dev, "sci: CPU frequency notifier registered\n");
 #endif
 
 #ifdef CONFIG_SH_STANDARD_BIOS
        sh_bios_gdb_detach();
 #endif
 
-       return ret;
+       return 0;
 }
 
-static void __exit sci_exit(void)
+static int __devexit sci_remove(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < SCI_NPORTS; i++)
+               uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port);
+
+       return 0;
+}
+
+static int sci_suspend(struct platform_device *dev, pm_message_t state)
 {
-       int chan;
+       int i;
+
+       for (i = 0; i < SCI_NPORTS; i++) {
+               struct sci_port *p = &sci_ports[i];
+
+               if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev)
+                       uart_suspend_port(&sci_uart_driver, &p->port);
+       }
 
-       for (chan = 0; chan < SCI_NPORTS; chan++)
-               uart_remove_one_port(&sci_uart_driver, &sci_ports[chan].port);
+       return 0;
+}
 
+static int sci_resume(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < SCI_NPORTS; i++) {
+               struct sci_port *p = &sci_ports[i];
+
+               if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev)
+                       uart_resume_port(&sci_uart_driver, &p->port);
+       }
+
+       return 0;
+}
+
+static struct platform_driver sci_driver = {
+       .probe          = sci_probe,
+       .remove         = __devexit_p(sci_remove),
+       .suspend        = sci_suspend,
+       .resume         = sci_resume,
+       .driver         = {
+               .name   = "sh-sci",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init sci_init(void)
+{
+       int ret;
+
+       printk(banner);
+
+       sci_init_ports();
+
+       ret = uart_register_driver(&sci_uart_driver);
+       if (likely(ret == 0)) {
+               ret = platform_driver_register(&sci_driver);
+               if (unlikely(ret))
+                       uart_unregister_driver(&sci_uart_driver);
+       }
+
+       return ret;
+}
+
+static void __exit sci_exit(void)
+{
+       platform_driver_unregister(&sci_driver);
        uart_unregister_driver(&sci_uart_driver);
 }
 
 module_init(sci_init);
 module_exit(sci_exit);
 
+MODULE_LICENSE("GPL");
index ab320fa3237c7f29ac29f6077c802574f70aeaca..28643c4dc850178e15d6d1970682065de6e8e552 100644 (file)
@@ -10,7 +10,9 @@
  *  Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
  *  Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
  */
+#include <linux/config.h>
 #include <linux/serial_core.h>
+#include <asm/io.h>
 
 #if defined(__H8300H__) || defined(__H8300S__)
 #include <asm/gpio.h>
 #endif
 #endif
 
-/* Offsets into the sci_port->irqs array */
-#define SCIx_ERI_IRQ 0
-#define SCIx_RXI_IRQ 1
-#define SCIx_TXI_IRQ 2
-
-/*                     ERI, RXI, TXI, BRI */
-#define SCI_IRQS      { 23,  24,  25,   0 }
-#define SH3_SCIF_IRQS { 56,  57,  59,  58 }
-#define SH3_IRDA_IRQS { 52,  53,  55,  54 }
-#define SH4_SCIF_IRQS { 40,  41,  43,  42 }
-#define STB1_SCIF1_IRQS {23, 24,  26,  25 }
-#define SH7760_SCIF0_IRQS { 52, 53, 55, 54 }
-#define SH7760_SCIF1_IRQS { 72, 73, 75, 74 }
-#define SH7760_SCIF2_IRQS { 76, 77, 79, 78 }
-#define SH7300_SCIF0_IRQS {80,  80,  80,  80 }
-#define SH73180_SCIF_IRQS {80,  81,  83,  82 }
-#define H8300H_SCI_IRQS0 {52, 53, 54,   0 }
-#define H8300H_SCI_IRQS1 {56, 57, 58,   0 }
-#define H8300H_SCI_IRQS2 {60, 61, 62,   0 }
-#define H8S_SCI_IRQS0 {88, 89, 90,   0 }
-#define H8S_SCI_IRQS1 {92, 93, 94,   0 }
-#define H8S_SCI_IRQS2 {96, 97, 98,   0 }
-#define SH5_SCIF_IRQS {39, 40, 42,   0 }
-#define        SH7770_SCIF0_IRQS {61, 61, 61, 61 }
-#define        SH7770_SCIF1_IRQS {62, 62, 62, 62 }
-#define        SH7770_SCIF2_IRQS {63, 63, 63, 63 }
-#define        SH7780_SCIF0_IRQS {40, 41, 43, 42 }
-#define        SH7780_SCIF1_IRQS {76, 77, 79, 78 }
-
 #if defined(CONFIG_CPU_SUBTYPE_SH7708)
 # define SCSPTR 0xffffff7c /* 8 bit */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCI_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706)
 # define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */
 # define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCPDR  0xA4050136        /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+# define SCSPTR0 0xA4400000      /* 16 bit SCIF */
+# define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
+# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH73180)
 # define SCPDR  0xA4050138        /* 16 bit SCIF */
 # define SCSPTR2 SCPDR
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port)  0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+# define SCSPTR0 0xffe00010    /* 16 bit SCIF */
+# define SCSPTR1 0xffe10010    /* 16 bit SCIF */
+# define SCSPTR2 0xffe20010    /* 16 bit SCIF */
+# define SCSPTR3 0xffe30010    /* 16 bit SCIF */
+# define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */
+# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define SCSPTR0       0xffe00024      /* 16 bit SCIF */
 # define SCSPTR1       0xffe10024      /* 16 bit SCIF */
-# define SCIF_OPER     0x0001          /* Overrun error bit */
+# define SCIF_ORER     0x0001          /* Overrun error bit */
 # define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #else
  */
 #define SCI_EVENT_WRITE_WAKEUP 0
 
-struct sci_port {
-       struct uart_port port;
-       int type;
-       unsigned char irqs[4]; /* ERI, RXI, TXI, BRI */
-       void (*init_pins)(struct uart_port *port, unsigned int cflag);
-       int break_flag;
-       struct timer_list break_timer;
-};
-
 #define SCI_IN(size, offset)                                   \
   unsigned int addr = port->mapbase + (offset);                        \
   if ((size) == 8) {                                           \
@@ -336,7 +313,9 @@ struct sci_port {
   }
 
 #ifdef CONFIG_CPU_SH3
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define SCIF_FNS(name, scif_offset, scif_size) \
   CPU_SCIF_FNS(name, scif_offset, scif_size)
 #else
@@ -362,7 +341,9 @@ struct sci_port {
   CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
 #endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710)
 SCIF_FNS(SCSMR,  0x00, 16)
 SCIF_FNS(SCBRR,  0x04,  8)
 SCIF_FNS(SCSCR,  0x08, 16)
@@ -447,7 +428,9 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inb(SCSPTR)&0x01 ? 1 : 0; /* SCI */
        return 1;
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706)
 static inline int sci_rxd_in(struct uart_port *port)
 {
        if (port->mapbase == 0xfffffe80)
@@ -467,6 +450,13 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
        return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == SCSPTR0)
+               return ctrl_inw(SCSPTR0 + 0x10) & 0x01 ? 1 : 0;
+       return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
       defined(CONFIG_CPU_SUBTYPE_SH7751) || \
       defined(CONFIG_CPU_SUBTYPE_SH4_202)
@@ -504,6 +494,19 @@ static inline int sci_rxd_in(struct uart_port *port)
 {
        return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xffe00000)
+               return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe10000)
+               return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe20000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe30000)
+               return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+       return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 static inline int sci_rxd_in(struct uart_port *port)
 {
@@ -587,4 +590,3 @@ static inline int sci_rxd_in(struct uart_port *port)
 #else /* Generic SH */
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif
-
index d3a5aeee73a34b33bb4736b751a2aacab8ec5e8a..9b3b9aaa6b909efd4a7bc61e111a01cd8b6a373b 100644 (file)
@@ -1499,6 +1499,9 @@ static int __devexit su_remove(struct of_device *dev)
                uart_remove_one_port(&sunsu_reg, &up->port);
        }
 
+       if (up->port.membase)
+               of_iounmap(up->port.membase, up->reg_size);
+
        dev_set_drvdata(&dev->dev, NULL);
 
        return 0;
index d34f336d53d80db4fdebd4016e8f9dedb077c770..0da3ebfff82dc55cc4750640ae7f92530f63562d 100644 (file)
@@ -1270,7 +1270,7 @@ static void __init sunzilog_register_serio(struct uart_sunzilog_port *up)
 }
 #endif
 
-static void __init sunzilog_init_hw(struct uart_sunzilog_port *up)
+static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
 {
        struct zilog_channel __iomem *channel;
        unsigned long flags;
index 005043197527142749965cce1d75fde169773c4c..f9b1719b9a372d562da3d65d959123ba1e1243fc 100644 (file)
@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI
        default y if PXA27x
        default y if ARCH_EP93XX
        default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
+       default y if ARCH_PNX4008
        # PPC:
        default y if STB03xxx
        default y if PPC_MPC52xx
index 4710eb02ed640b7b572c223e2792759e2ff0a76d..97d57cfc343b628fb81f78820c2ad6cea9e5b958 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ISP116X_HCD) += host/
 obj-$(CONFIG_USB_OHCI_HCD)     += host/
 obj-$(CONFIG_USB_UHCI_HCD)     += host/
 obj-$(CONFIG_USB_SL811_HCD)    += host/
+obj-$(CONFIG_USB_U132_HCD)     += host/
 obj-$(CONFIG_ETRAX_USB_HOST)   += host/
 obj-$(CONFIG_USB_OHCI_AT91)    += host/
 
@@ -23,6 +24,7 @@ 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_HID)          += input/
@@ -31,8 +33,8 @@ obj-$(CONFIG_USB_KBTAB)               += input/
 obj-$(CONFIG_USB_MOUSE)                += input/
 obj-$(CONFIG_USB_MTOUCH)       += input/
 obj-$(CONFIG_USB_POWERMATE)    += input/
+obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/
 obj-$(CONFIG_USB_WACOM)                += input/
-obj-$(CONFIG_USB_ACECAD)       += input/
 obj-$(CONFIG_USB_XPAD)         += input/
 
 obj-$(CONFIG_USB_CATC)         += net/
@@ -47,22 +49,24 @@ obj-$(CONFIG_USB_MICROTEK)  += image/
 
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
+obj-$(CONFIG_USB_ADUTUX)       += misc/
+obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
 obj-$(CONFIG_USB_AUERSWALD)    += misc/
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
 obj-$(CONFIG_USB_CYTHERM)      += misc/
 obj-$(CONFIG_USB_EMI26)                += misc/
 obj-$(CONFIG_USB_EMI62)                += misc/
+obj-$(CONFIG_USB_FTDI_ELAN)    += misc/
 obj-$(CONFIG_USB_IDMOUSE)      += misc/
 obj-$(CONFIG_USB_LCD)          += misc/
 obj-$(CONFIG_USB_LD)           += misc/
 obj-$(CONFIG_USB_LED)          += misc/
 obj-$(CONFIG_USB_LEGOTOWER)    += misc/
+obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
 obj-$(CONFIG_USB_RIO500)       += misc/
+obj-$(CONFIG_USB_SISUSBVGA)    += misc/
 obj-$(CONFIG_USB_TEST)         += misc/
 obj-$(CONFIG_USB_USS720)       += misc/
-obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
-obj-$(CONFIG_USB_SISUSBVGA)    += misc/
-obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
 
 obj-$(CONFIG_USB_ATM)          += atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)   += atm/
index b38990adf1cdaf7d15b1a3249350e840461bac6a..465961a26e4a9131af4fe96671fe42eac202c16f 100644 (file)
@@ -1621,26 +1621,32 @@ static int claim_interface(struct usb_device *usb_dev,
        return ret;
 }
 
-static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+static struct attribute *attrs[] = {
+       &dev_attr_stat_status.attr,
+       &dev_attr_stat_mflags.attr,
+       &dev_attr_stat_human_status.attr,
+       &dev_attr_stat_delin.attr,
+       &dev_attr_stat_vidcpe.attr,
+       &dev_attr_stat_usrate.attr,
+       &dev_attr_stat_dsrate.attr,
+       &dev_attr_stat_usattenuation.attr,
+       &dev_attr_stat_dsattenuation.attr,
+       &dev_attr_stat_usmargin.attr,
+       &dev_attr_stat_dsmargin.attr,
+       &dev_attr_stat_txflow.attr,
+       &dev_attr_stat_rxflow.attr,
+       &dev_attr_stat_uscorr.attr,
+       &dev_attr_stat_dscorr.attr,
+       &dev_attr_stat_usunc.attr,
+       &dev_attr_stat_dsunc.attr,
+};
+static struct attribute_group attr_grp = {
+       .attrs = attrs,
+};
+
+static int create_fs_entries(struct usb_interface *intf)
 {
-       /* sysfs interface */
-       device_create_file(&intf->dev, &dev_attr_stat_status);
-       device_create_file(&intf->dev, &dev_attr_stat_mflags);
-       device_create_file(&intf->dev, &dev_attr_stat_human_status);
-       device_create_file(&intf->dev, &dev_attr_stat_delin);
-       device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
-       device_create_file(&intf->dev, &dev_attr_stat_usrate);
-       device_create_file(&intf->dev, &dev_attr_stat_dsrate);
-       device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
-       device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
-       device_create_file(&intf->dev, &dev_attr_stat_usmargin);
-       device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
-       device_create_file(&intf->dev, &dev_attr_stat_txflow);
-       device_create_file(&intf->dev, &dev_attr_stat_rxflow);
-       device_create_file(&intf->dev, &dev_attr_stat_uscorr);
-       device_create_file(&intf->dev, &dev_attr_stat_dscorr);
-       device_create_file(&intf->dev, &dev_attr_stat_usunc);
-       device_create_file(&intf->dev, &dev_attr_stat_dsunc);
+       return sysfs_create_group(&intf->dev.kobj, &attr_grp);
 }
 
 static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
@@ -1708,37 +1714,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
                return ret;
        }
 
-       create_fs_entries(sc, intf);
+       ret = create_fs_entries(intf);
+       if (ret) {
+               uea_stop(sc);
+               kfree(sc);
+               return ret;
+       }
        return 0;
 }
 
-static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+static void destroy_fs_entries(struct usb_interface *intf)
 {
-       /* sysfs interface */
-       device_remove_file(&intf->dev, &dev_attr_stat_status);
-       device_remove_file(&intf->dev, &dev_attr_stat_mflags);
-       device_remove_file(&intf->dev, &dev_attr_stat_human_status);
-       device_remove_file(&intf->dev, &dev_attr_stat_delin);
-       device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
-       device_remove_file(&intf->dev, &dev_attr_stat_usrate);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
-       device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
-       device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
-       device_remove_file(&intf->dev, &dev_attr_stat_txflow);
-       device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
-       device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
-       device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
-       device_remove_file(&intf->dev, &dev_attr_stat_usunc);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+       sysfs_remove_group(&intf->dev.kobj, &attr_grp);
 }
 
 static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
 {
        struct uea_softc *sc = usbatm->driver_data;
 
-       destroy_fs_entries(sc, intf);
+       destroy_fs_entries(intf);
        uea_stop(sc);
        kfree(sc);
 }
index 48dee4b8d8e50a8b6064fb5b2e98b29fc2293e91..9cac11ca1bb73f83cada5a12f77bf4f6ebb4fc11 100644 (file)
@@ -813,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product)
        return 0;
 }
 
-static struct file_operations usblp_fops = {
+static const struct file_operations usblp_fops = {
        .owner =        THIS_MODULE,
        .read =         usblp_read,
        .write =        usblp_write,
@@ -927,7 +927,9 @@ static int usblp_probe(struct usb_interface *intf,
 
        /* Retrieve and store the device ID string. */
        usblp_cache_device_id_string(usblp);
-       device_create_file(&intf->dev, &dev_attr_ieee1284_id);
+       retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id);
+       if (retval)
+               goto abort_intfdata;
 
 #ifdef DEBUG
        usblp_check_status(usblp, 0);
@@ -1021,18 +1023,13 @@ static int usblp_select_alts(struct usblp *usblp)
                for (e = 0; e < ifd->desc.bNumEndpoints; e++) {
                        epd = &ifd->endpoint[e].desc;
 
-                       if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
-                           USB_ENDPOINT_XFER_BULK)
-                               continue;
-
-                       if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
+                       if (usb_endpoint_is_bulk_out(epd))
                                if (!epwrite)
                                        epwrite = epd;
 
-                       } else {
+                       if (usb_endpoint_is_bulk_in(epd))
                                if (!epread)
                                        epread = epd;
-                       }
                }
 
                /* Ignore buggy hardware without the right endpoints. */
index ec510922af63a1fac195a022b1347ff4d2624c78..34e9bac319b4e5af731727e5da58907f28612a61 100644 (file)
@@ -4,7 +4,7 @@
 
 usbcore-objs   := usb.o hub.o hcd.o urb.o message.o driver.o \
                        config.o file.o buffer.o sysfs.o endpoint.o \
-                       devio.o notify.o
+                       devio.o notify.o generic.o
 
 ifeq ($(CONFIG_PCI),y)
        usbcore-objs    += hcd-pci.o
index f4f4ef0f377ae001c2aee0d24bec14dc91a46442..840442a25b6183844979b3c2f5fc58d3607fb7ac 100644 (file)
@@ -104,7 +104,7 @@ void *hcd_buffer_alloc (
        dma_addr_t              *dma
 )
 {
-       struct usb_hcd          *hcd = bus->hcpriv;
+       struct usb_hcd          *hcd = bus_to_hcd(bus);
        int                     i;
 
        /* some USB hosts just use PIO */
@@ -127,7 +127,7 @@ void hcd_buffer_free (
        dma_addr_t              dma
 )
 {
-       struct usb_hcd          *hcd = bus->hcpriv;
+       struct usb_hcd          *hcd = bus_to_hcd(bus);
        int                     i;
 
        if (!addr)
index 4c9e63e665b6988f54f4feca6566a4d6444c231e..bfb3731d42db816531a4cacd69d692ff04727827 100644 (file)
@@ -475,7 +475,9 @@ int usb_get_configuration(struct usb_device *dev)
                if (result < 0) {
                        dev_err(ddev, "unable to read config index %d "
                            "descriptor/%s\n", cfgno, "start");
-                       goto err;
+                       dev_err(ddev, "chopping to %d config(s)\n", cfgno);
+                       dev->descriptor.bNumConfigurations = cfgno;
+                       break;
                } else if (result < 4) {
                        dev_err(ddev, "config index %d descriptor too short "
                            "(expected %i, got %i)\n", cfgno,
index c0f37343a276ce551705065625f923ec13f7f629..3538c2fdadfe5752fc650cc858fd2ab76de32ff5 100644 (file)
@@ -593,7 +593,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
 /* Kernel lock for "lastev" protection */
 static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
 {
-       struct usb_device_status *st = (struct usb_device_status *)file->private_data;
+       struct usb_device_status *st = file->private_data;
        unsigned int mask = 0;
 
        lock_kernel();
@@ -603,7 +603,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
                        unlock_kernel();
                        return POLLIN;
                }
-               
+
                /* we may have dropped BKL - need to check for having lost the race */
                if (file->private_data) {
                        kfree(st);
@@ -667,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
        return ret;
 }
 
-struct file_operations usbfs_devices_fops = {
+const struct file_operations usbfs_devices_fops = {
        .llseek =       usb_device_lseek,
        .read =         usb_device_read,
        .poll =         usb_device_poll,
index 218621b9958e4af20972900bc19038d940fbe78a..a94c63bef632c5151e985073f2cf6457f30a0ad4 100644 (file)
@@ -59,6 +59,9 @@
 #define USB_DEVICE_MAX                 USB_MAXBUS * 128
 static struct class *usb_device_class;
 
+/* Mutual exclusion for removal, open, and release */
+DEFINE_MUTEX(usbfs_mutex);
+
 struct async {
        struct list_head asynclist;
        struct dev_state *ps;
@@ -87,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
 
 #define        MAX_USBFS_BUFFER_SIZE   16384
 
-static inline int connected (struct usb_device *dev)
+static inline int connected (struct dev_state *ps)
 {
-       return dev->state != USB_STATE_NOTATTACHED;
+       return (!list_empty(&ps->list) &&
+                       ps->dev->state != USB_STATE_NOTATTACHED);
 }
 
 static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
@@ -118,7 +122,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
 
 static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
+       struct dev_state *ps = file->private_data;
        struct usb_device *dev = ps->dev;
        ssize_t ret = 0;
        unsigned len;
@@ -127,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
 
        pos = *ppos;
        usb_lock_device(dev);
-       if (!connected(dev)) {
+       if (!connected(ps)) {
                ret = -ENODEV;
                goto err;
        } else if (pos < 0) {
@@ -301,7 +305,7 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
 
 static void async_completed(struct urb *urb, struct pt_regs *regs)
 {
-        struct async *as = (struct async *)urb->context;
+        struct async *as = urb->context;
         struct dev_state *ps = as->ps;
        struct siginfo sinfo;
 
@@ -541,25 +545,25 @@ static int usbdev_open(struct inode *inode, struct file *file)
        struct dev_state *ps;
        int ret;
 
-       /* 
-        * no locking necessary here, as chrdev_open has the kernel lock
-        * (still acquire the kernel lock for safety)
-        */
+       /* Protect against simultaneous removal or release */
+       mutex_lock(&usbfs_mutex);
+
        ret = -ENOMEM;
        if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
-               goto out_nolock;
+               goto out;
 
-       lock_kernel();
        ret = -ENOENT;
        /* check if we are called from a real node or usbfs */
        if (imajor(inode) == USB_DEVICE_MAJOR)
                dev = usbdev_lookup_minor(iminor(inode));
        if (!dev)
-               dev = inode->u.generic_ip;
-       if (!dev) {
-               kfree(ps);
+               dev = inode->i_private;
+       if (!dev)
                goto out;
-       }
+       ret = usb_autoresume_device(dev, 1);
+       if (ret)
+               goto out;
+
        usb_get_dev(dev);
        ret = 0;
        ps->dev = dev;
@@ -579,30 +583,36 @@ static int usbdev_open(struct inode *inode, struct file *file)
        list_add_tail(&ps->list, &dev->filelist);
        file->private_data = ps;
  out:
-       unlock_kernel();
- out_nolock:
-        return ret;
+       if (ret)
+               kfree(ps);
+       mutex_unlock(&usbfs_mutex);
+       return ret;
 }
 
 static int usbdev_release(struct inode *inode, struct file *file)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
+       struct dev_state *ps = file->private_data;
        struct usb_device *dev = ps->dev;
        unsigned int ifnum;
 
        usb_lock_device(dev);
+
+       /* Protect against simultaneous open */
+       mutex_lock(&usbfs_mutex);
        list_del_init(&ps->list);
+       mutex_unlock(&usbfs_mutex);
+
        for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
                        ifnum++) {
                if (test_bit(ifnum, &ps->ifclaimed))
                        releaseintf(ps, ifnum);
        }
        destroy_all_async(ps);
+       usb_autosuspend_device(dev, 1);
        usb_unlock_device(dev);
        usb_put_dev(dev);
-       ps->dev = NULL;
        kfree(ps);
-        return 0;
+       return 0;
 }
 
 static int proc_control(struct dev_state *ps, void __user *arg)
@@ -1322,7 +1332,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
                }
        }
 
-       if (!connected(ps->dev)) {
+       if (!connected(ps)) {
                kfree(buf);
                return -ENODEV;
        }
@@ -1349,7 +1359,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
        /* let kernel drivers try to (re)bind to the interface */
        case USBDEVFS_CONNECT:
                usb_unlock_device(ps->dev);
-               bus_rescan_devices(intf->dev.bus);
+               retval = bus_rescan_devices(intf->dev.bus);
                usb_lock_device(ps->dev);
                break;
 
@@ -1413,7 +1423,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
  */
 static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
+       struct dev_state *ps = file->private_data;
        struct usb_device *dev = ps->dev;
        void __user *p = (void __user *)arg;
        int ret = -ENOTTY;
@@ -1421,7 +1431,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        if (!(file->f_mode & FMODE_WRITE))
                return -EPERM;
        usb_lock_device(dev);
-       if (!connected(dev)) {
+       if (!connected(ps)) {
                usb_unlock_device(dev);
                return -ENODEV;
        }
@@ -1556,18 +1566,18 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 /* No kernel lock - fine */
 static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
-        unsigned int mask = 0;
+       struct dev_state *ps = file->private_data;
+       unsigned int mask = 0;
 
        poll_wait(file, &ps->wait, wait);
        if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
                mask |= POLLOUT | POLLWRNORM;
-       if (!connected(ps->dev))
+       if (!connected(ps))
                mask |= POLLERR | POLLHUP;
        return mask;
 }
 
-struct file_operations usbfs_device_file_operations = {
+const struct file_operations usbfs_device_file_operations = {
        .llseek =       usbdev_lseek,
        .read =         usbdev_read,
        .poll =         usbdev_poll,
index ec8906501415b38cac0298e52194874ff58a1c2f..113e484c763eb23093bb0ffa08f28a12f8b8bff0 100644 (file)
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
- * generic USB things that the real drivers can use..
+ * matching, probing, releasing, suspending and resuming for
+ * real drivers.
  *
  */
 
 #include <linux/device.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 #include "hcd.h"
 #include "usb.h"
 
@@ -34,38 +36,6 @@ struct usb_dynid {
        struct usb_device_id id;
 };
 
-
-static int generic_probe(struct device *dev)
-{
-       return 0;
-}
-static int generic_remove(struct device *dev)
-{
-       struct usb_device *udev = to_usb_device(dev);
-
-       /* if this is only an unbind, not a physical disconnect, then
-        * unconfigure the device */
-       if (udev->state == USB_STATE_CONFIGURED)
-               usb_set_configuration(udev, 0);
-
-       /* in case the call failed or the device was suspended */
-       if (udev->state >= USB_STATE_CONFIGURED)
-               usb_disable_device(udev, 0);
-       return 0;
-}
-
-struct device_driver usb_generic_driver = {
-       .owner = THIS_MODULE,
-       .name = "usb",
-       .bus = &usb_bus_type,
-       .probe = generic_probe,
-       .remove = generic_remove,
-};
-
-/* Fun hack to determine if the struct device is a
- * usb device or a usb interface. */
-int usb_generic_driver_data;
-
 #ifdef CONFIG_HOTPLUG
 
 /*
@@ -80,6 +50,7 @@ static ssize_t store_new_id(struct device_driver *driver,
        u32 idVendor = 0;
        u32 idProduct = 0;
        int fields = 0;
+       int retval = 0;
 
        fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
        if (fields < 2)
@@ -99,10 +70,12 @@ static ssize_t store_new_id(struct device_driver *driver,
        spin_unlock(&usb_drv->dynids.lock);
 
        if (get_driver(driver)) {
-               driver_attach(driver);
+               retval = driver_attach(driver);
                put_driver(driver);
        }
 
+       if (retval)
+               return retval;
        return count;
 }
 static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
@@ -115,7 +88,7 @@ static int usb_create_newid_file(struct usb_driver *usb_drv)
                goto exit;
 
        if (usb_drv->probe != NULL)
-               error = sysfs_create_file(&usb_drv->driver.kobj,
+               error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj,
                                          &driver_attr_new_id.attr);
 exit:
        return error;
@@ -127,7 +100,7 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv)
                return;
 
        if (usb_drv->probe != NULL)
-               sysfs_remove_file(&usb_drv->driver.kobj,
+               sysfs_remove_file(&usb_drv->drvwrap.driver.kobj,
                                  &driver_attr_new_id.attr);
 }
 
@@ -174,21 +147,57 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in
 }
 
 
-/* called from driver core with usb_bus_type.subsys writelock */
+/* called from driver core with dev locked */
+static int usb_probe_device(struct device *dev)
+{
+       struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+       struct usb_device *udev;
+       int error = -ENODEV;
+
+       dev_dbg(dev, "%s\n", __FUNCTION__);
+
+       if (!is_usb_device(dev))        /* Sanity check */
+               return error;
+
+       udev = to_usb_device(dev);
+
+       /* TODO: Add real matching code */
+
+       /* The device should always appear to be in use
+        * unless the driver suports autosuspend.
+        */
+       udev->pm_usage_cnt = !(udriver->supports_autosuspend);
+
+       error = udriver->probe(udev);
+       return error;
+}
+
+/* called from driver core with dev locked */
+static int usb_unbind_device(struct device *dev)
+{
+       struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+
+       udriver->disconnect(to_usb_device(dev));
+       return 0;
+}
+
+
+/* called from driver core with dev locked */
 static int usb_probe_interface(struct device *dev)
 {
-       struct usb_interface * intf = to_usb_interface(dev);
-       struct usb_driver * driver = to_usb_driver(dev->driver);
+       struct usb_driver *driver = to_usb_driver(dev->driver);
+       struct usb_interface *intf;
+       struct usb_device *udev;
        const struct usb_device_id *id;
        int error = -ENODEV;
 
        dev_dbg(dev, "%s\n", __FUNCTION__);
 
-       if (!driver->probe)
+       if (is_usb_device(dev))         /* Sanity check */
                return error;
-       /* FIXME we'd much prefer to just resume it ... */
-       if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
-               return -EHOSTUNREACH;
+
+       intf = to_usb_interface(dev);
+       udev = interface_to_usbdev(intf);
 
        id = usb_match_id(intf, driver->id_table);
        if (!id)
@@ -196,48 +205,165 @@ static int usb_probe_interface(struct device *dev)
        if (id) {
                dev_dbg(dev, "%s - got id\n", __FUNCTION__);
 
+               error = usb_autoresume_device(udev, 1);
+               if (error)
+                       return error;
+
                /* Interface "power state" doesn't correspond to any hardware
                 * state whatsoever.  We use it to record when it's bound to
                 * a driver that may start I/0:  it's not frozen/quiesced.
                 */
                mark_active(intf);
                intf->condition = USB_INTERFACE_BINDING;
+
+               /* The interface should always appear to be in use
+                * unless the driver suports autosuspend.
+                */
+               intf->pm_usage_cnt = !(driver->supports_autosuspend);
+
                error = driver->probe(intf, id);
                if (error) {
                        mark_quiesced(intf);
+                       intf->needs_remote_wakeup = 0;
                        intf->condition = USB_INTERFACE_UNBOUND;
                } else
                        intf->condition = USB_INTERFACE_BOUND;
+
+               usb_autosuspend_device(udev, 1);
        }
 
        return error;
 }
 
-/* called from driver core with usb_bus_type.subsys writelock */
+/* called from driver core with dev locked */
 static int usb_unbind_interface(struct device *dev)
 {
+       struct usb_driver *driver = to_usb_driver(dev->driver);
        struct usb_interface *intf = to_usb_interface(dev);
-       struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+       struct usb_device *udev;
+       int error;
 
        intf->condition = USB_INTERFACE_UNBINDING;
 
+       /* Autoresume for set_interface call below */
+       udev = interface_to_usbdev(intf);
+       error = usb_autoresume_device(udev, 1);
+
        /* release all urbs for this interface */
        usb_disable_interface(interface_to_usbdev(intf), intf);
 
-       if (driver && driver->disconnect)
-               driver->disconnect(intf);
+       driver->disconnect(intf);
 
        /* reset other interface state */
        usb_set_interface(interface_to_usbdev(intf),
                        intf->altsetting[0].desc.bInterfaceNumber,
                        0);
        usb_set_intfdata(intf, NULL);
+
        intf->condition = USB_INTERFACE_UNBOUND;
        mark_quiesced(intf);
+       intf->needs_remote_wakeup = 0;
+
+       if (!error)
+               usb_autosuspend_device(udev, 1);
 
        return 0;
 }
 
+/**
+ * usb_driver_claim_interface - bind a driver to an interface
+ * @driver: the driver to be bound
+ * @iface: the interface to which it will be bound; must be in the
+ *     usb device's active configuration
+ * @priv: driver data associated with that interface
+ *
+ * This is used by usb device drivers that need to claim more than one
+ * interface on a device when probing (audio and acm are current examples).
+ * No device driver should directly modify internal usb_interface or
+ * usb_device structure members.
+ *
+ * Few drivers should need to use this routine, since the most natural
+ * way to bind to an interface is to return the private data from
+ * the driver's probe() method.
+ *
+ * Callers must own the device lock and the driver model's usb_bus_type.subsys
+ * writelock.  So driver probe() entries don't need extra locking,
+ * but other call contexts may need to explicitly claim those locks.
+ */
+int usb_driver_claim_interface(struct usb_driver *driver,
+                               struct usb_interface *iface, void* priv)
+{
+       struct device *dev = &iface->dev;
+       struct usb_device *udev = interface_to_usbdev(iface);
+       int retval = 0;
+
+       if (dev->driver)
+               return -EBUSY;
+
+       dev->driver = &driver->drvwrap.driver;
+       usb_set_intfdata(iface, priv);
+
+       usb_pm_lock(udev);
+       iface->condition = USB_INTERFACE_BOUND;
+       mark_active(iface);
+       iface->pm_usage_cnt = !(driver->supports_autosuspend);
+       usb_pm_unlock(udev);
+
+       /* if interface was already added, bind now; else let
+        * the future device_add() bind it, bypassing probe()
+        */
+       if (device_is_registered(dev))
+               retval = device_bind_driver(dev);
+
+       return retval;
+}
+EXPORT_SYMBOL(usb_driver_claim_interface);
+
+/**
+ * usb_driver_release_interface - unbind a driver from an interface
+ * @driver: the driver to be unbound
+ * @iface: the interface from which it will be unbound
+ *
+ * This can be used by drivers to release an interface without waiting
+ * for their disconnect() methods to be called.  In typical cases this
+ * also causes the driver disconnect() method to be called.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ * Callers must own the device lock and the driver model's usb_bus_type.subsys
+ * writelock.  So driver disconnect() entries don't need extra locking,
+ * but other call contexts may need to explicitly claim those locks.
+ */
+void usb_driver_release_interface(struct usb_driver *driver,
+                                       struct usb_interface *iface)
+{
+       struct device *dev = &iface->dev;
+       struct usb_device *udev = interface_to_usbdev(iface);
+
+       /* this should never happen, don't release something that's not ours */
+       if (!dev->driver || dev->driver != &driver->drvwrap.driver)
+               return;
+
+       /* don't release from within disconnect() */
+       if (iface->condition != USB_INTERFACE_BOUND)
+               return;
+
+       /* don't release if the interface hasn't been added yet */
+       if (device_is_registered(dev)) {
+               iface->condition = USB_INTERFACE_UNBINDING;
+               device_release_driver(dev);
+       }
+
+       dev->driver = NULL;
+       usb_set_intfdata(iface, NULL);
+
+       usb_pm_lock(udev);
+       iface->condition = USB_INTERFACE_UNBOUND;
+       mark_quiesced(iface);
+       iface->needs_remote_wakeup = 0;
+       usb_pm_unlock(udev);
+}
+EXPORT_SYMBOL(usb_driver_release_interface);
+
 /* returns 0 if no match, 1 if match */
 static int usb_match_one_id(struct usb_interface *interface,
                            const struct usb_device_id *id)
@@ -380,36 +506,224 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
 
 int usb_device_match(struct device *dev, struct device_driver *drv)
+{
+       /* devices and interfaces are handled separately */
+       if (is_usb_device(dev)) {
+
+               /* interface drivers never match devices */
+               if (!is_usb_device_driver(drv))
+                       return 0;
+
+               /* TODO: Add real matching code */
+               return 1;
+
+       } else {
+               struct usb_interface *intf;
+               struct usb_driver *usb_drv;
+               const struct usb_device_id *id;
+
+               /* device drivers never match interfaces */
+               if (is_usb_device_driver(drv))
+                       return 0;
+
+               intf = to_usb_interface(dev);
+               usb_drv = to_usb_driver(drv);
+
+               id = usb_match_id(intf, usb_drv->id_table);
+               if (id)
+                       return 1;
+
+               id = usb_match_dynamic_id(intf, usb_drv);
+               if (id)
+                       return 1;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * This sends an uevent to userspace, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ * We're called either from khubd (the typical case) or from root hub
+ * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
+ * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
+ * device (and this configuration!) are still present.
+ */
+static int usb_uevent(struct device *dev, char **envp, int num_envp,
+                     char *buffer, int buffer_size)
 {
        struct usb_interface *intf;
-       struct usb_driver *usb_drv;
-       const struct usb_device_id *id;
+       struct usb_device *usb_dev;
+       struct usb_host_interface *alt;
+       int i = 0;
+       int length = 0;
 
-       /* check for generic driver, which we don't match any device with */
-       if (drv == &usb_generic_driver)
-               return 0;
+       if (!dev)
+               return -ENODEV;
 
-       intf = to_usb_interface(dev);
-       usb_drv = to_usb_driver(drv);
+       /* driver is often null here; dev_dbg() would oops */
+       pr_debug ("usb %s: uevent\n", dev->bus_id);
 
-       id = usb_match_id(intf, usb_drv->id_table);
-       if (id)
-               return 1;
+       if (is_usb_device(dev)) {
+               usb_dev = to_usb_device(dev);
+               alt = NULL;
+       } else {
+               intf = to_usb_interface(dev);
+               usb_dev = interface_to_usbdev(intf);
+               alt = intf->cur_altsetting;
+       }
+
+       if (usb_dev->devnum < 0) {
+               pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+               return -ENODEV;
+       }
+       if (!usb_dev->bus) {
+               pr_debug ("usb %s: bus removed?\n", dev->bus_id);
+               return -ENODEV;
+       }
+
+#ifdef CONFIG_USB_DEVICEFS
+       /* If this is available, userspace programs can directly read
+        * all the device descriptors we don't tell them about.  Or
+        * even act as usermode drivers.
+        *
+        * FIXME reduce hardwired intelligence here
+        */
+       if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "DEVICE=/proc/bus/usb/%03d/%03d",
+                          usb_dev->bus->busnum, usb_dev->devnum))
+               return -ENOMEM;
+#endif
+
+       /* per-device configurations are common */
+       if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "PRODUCT=%x/%x/%x",
+                          le16_to_cpu(usb_dev->descriptor.idVendor),
+                          le16_to_cpu(usb_dev->descriptor.idProduct),
+                          le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+               return -ENOMEM;
+
+       /* class-based driver binding models */
+       if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "TYPE=%d/%d/%d",
+                          usb_dev->descriptor.bDeviceClass,
+                          usb_dev->descriptor.bDeviceSubClass,
+                          usb_dev->descriptor.bDeviceProtocol))
+               return -ENOMEM;
+
+       if (!is_usb_device(dev)) {
+
+               if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "INTERFACE=%d/%d/%d",
+                          alt->desc.bInterfaceClass,
+                          alt->desc.bInterfaceSubClass,
+                          alt->desc.bInterfaceProtocol))
+                       return -ENOMEM;
+
+               if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+                          le16_to_cpu(usb_dev->descriptor.idVendor),
+                          le16_to_cpu(usb_dev->descriptor.idProduct),
+                          le16_to_cpu(usb_dev->descriptor.bcdDevice),
+                          usb_dev->descriptor.bDeviceClass,
+                          usb_dev->descriptor.bDeviceSubClass,
+                          usb_dev->descriptor.bDeviceProtocol,
+                          alt->desc.bInterfaceClass,
+                          alt->desc.bInterfaceSubClass,
+                          alt->desc.bInterfaceProtocol))
+                       return -ENOMEM;
+       }
+
+       envp[i] = NULL;
 
-       id = usb_match_dynamic_id(intf, usb_drv);
-       if (id)
-               return 1;
        return 0;
 }
 
+#else
+
+static int usb_uevent(struct device *dev, char **envp,
+                       int num_envp, char *buffer, int buffer_size)
+{
+       return -ENODEV;
+}
+
+#endif /* CONFIG_HOTPLUG */
+
+/**
+ * usb_register_device_driver - register a USB device (not interface) driver
+ * @new_udriver: USB operations for the device driver
+ * @owner: module owner of this driver.
+ *
+ * Registers a USB device driver with the USB core.  The list of
+ * unattached devices will be rescanned whenever a new driver is
+ * added, allowing the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ */
+int usb_register_device_driver(struct usb_device_driver *new_udriver,
+               struct module *owner)
+{
+       int retval = 0;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       new_udriver->drvwrap.for_devices = 1;
+       new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
+       new_udriver->drvwrap.driver.bus = &usb_bus_type;
+       new_udriver->drvwrap.driver.probe = usb_probe_device;
+       new_udriver->drvwrap.driver.remove = usb_unbind_device;
+       new_udriver->drvwrap.driver.owner = owner;
+
+       retval = driver_register(&new_udriver->drvwrap.driver);
+
+       if (!retval) {
+               pr_info("%s: registered new device driver %s\n",
+                       usbcore_name, new_udriver->name);
+               usbfs_update_special();
+       } else {
+               printk(KERN_ERR "%s: error %d registering device "
+                       "       driver %s\n",
+                       usbcore_name, retval, new_udriver->name);
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(usb_register_device_driver);
+
+/**
+ * usb_deregister_device_driver - unregister a USB device (not interface) driver
+ * @udriver: USB operations of the device driver to unregister
+ * Context: must be able to sleep
+ *
+ * Unlinks the specified driver from the internal USB driver list.
+ */
+void usb_deregister_device_driver(struct usb_device_driver *udriver)
+{
+       pr_info("%s: deregistering device driver %s\n",
+                       usbcore_name, udriver->name);
+
+       driver_unregister(&udriver->drvwrap.driver);
+       usbfs_update_special();
+}
+EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
+
 /**
- * usb_register_driver - register a USB driver
- * @new_driver: USB operations for the driver
+ * usb_register_driver - register a USB interface driver
+ * @new_driver: USB operations for the interface driver
  * @owner: module owner of this driver.
  *
- * Registers a USB driver with the USB core.  The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
+ * Registers a USB interface driver with the USB core.  The list of
+ * unattached interfaces will be rescanned whenever a new driver is
+ * added, allowing the new driver to attach to any recognized interfaces.
  * Returns a negative error code on failure and 0 on success.
  *
  * NOTE: if you want your driver to use the USB major number, you must call
@@ -423,23 +737,25 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
        if (usb_disabled())
                return -ENODEV;
 
-       new_driver->driver.name = (char *)new_driver->name;
-       new_driver->driver.bus = &usb_bus_type;
-       new_driver->driver.probe = usb_probe_interface;
-       new_driver->driver.remove = usb_unbind_interface;
-       new_driver->driver.owner = owner;
+       new_driver->drvwrap.for_devices = 0;
+       new_driver->drvwrap.driver.name = (char *) new_driver->name;
+       new_driver->drvwrap.driver.bus = &usb_bus_type;
+       new_driver->drvwrap.driver.probe = usb_probe_interface;
+       new_driver->drvwrap.driver.remove = usb_unbind_interface;
+       new_driver->drvwrap.driver.owner = owner;
        spin_lock_init(&new_driver->dynids.lock);
        INIT_LIST_HEAD(&new_driver->dynids.list);
 
-       retval = driver_register(&new_driver->driver);
+       retval = driver_register(&new_driver->drvwrap.driver);
 
        if (!retval) {
-               pr_info("%s: registered new driver %s\n",
+               pr_info("%s: registered new interface driver %s\n",
                        usbcore_name, new_driver->name);
                usbfs_update_special();
                usb_create_newid_file(new_driver);
        } else {
-               printk(KERN_ERR "%s: error %d registering driver %s\n",
+               printk(KERN_ERR "%s: error %d registering interface "
+                       "       driver %s\n",
                        usbcore_name, retval, new_driver->name);
        }
 
@@ -448,8 +764,8 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
 EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
 
 /**
- * usb_deregister - unregister a USB driver
- * @driver: USB operations of the driver to unregister
+ * usb_deregister - unregister a USB interface driver
+ * @driver: USB operations of the interface driver to unregister
  * Context: must be able to sleep
  *
  * Unlinks the specified driver from the internal USB driver list.
@@ -460,12 +776,554 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
  */
 void usb_deregister(struct usb_driver *driver)
 {
-       pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+       pr_info("%s: deregistering interface driver %s\n",
+                       usbcore_name, driver->name);
 
        usb_remove_newid_file(driver);
        usb_free_dynids(driver);
-       driver_unregister(&driver->driver);
+       driver_unregister(&driver->drvwrap.driver);
 
        usbfs_update_special();
 }
 EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+
+#ifdef CONFIG_PM
+
+/* Caller has locked udev's pm_mutex */
+static int suspend_device(struct usb_device *udev, pm_message_t msg)
+{
+       struct usb_device_driver        *udriver;
+       int                             status = 0;
+
+       if (udev->state == USB_STATE_NOTATTACHED ||
+                       udev->state == USB_STATE_SUSPENDED)
+               goto done;
+
+       /* For devices that don't have a driver, we do a standard suspend. */
+       if (udev->dev.driver == NULL) {
+               udev->do_remote_wakeup = 0;
+               status = usb_port_suspend(udev);
+               goto done;
+       }
+
+       udriver = to_usb_device_driver(udev->dev.driver);
+       status = udriver->suspend(udev, msg);
+
+done:
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               udev->dev.power.power_state.event = msg.event;
+       return status;
+}
+
+/* Caller has locked udev's pm_mutex */
+static int resume_device(struct usb_device *udev)
+{
+       struct usb_device_driver        *udriver;
+       int                             status = 0;
+
+       if (udev->state == USB_STATE_NOTATTACHED ||
+                       udev->state != USB_STATE_SUSPENDED)
+               goto done;
+
+       /* Can't resume it if it doesn't have a driver. */
+       if (udev->dev.driver == NULL) {
+               status = -ENOTCONN;
+               goto done;
+       }
+
+       udriver = to_usb_device_driver(udev->dev.driver);
+       status = udriver->resume(udev);
+
+done:
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               udev->dev.power.power_state.event = PM_EVENT_ON;
+       return status;
+}
+
+/* Caller has locked intf's usb_device's pm mutex */
+static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+{
+       struct usb_driver       *driver;
+       int                     status = 0;
+
+       /* with no hardware, USB interfaces only use FREEZE and ON states */
+       if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+                       !is_active(intf))
+               goto done;
+
+       if (intf->condition == USB_INTERFACE_UNBOUND)   /* This can't happen */
+               goto done;
+       driver = to_usb_driver(intf->dev.driver);
+
+       if (driver->suspend && driver->resume) {
+               status = driver->suspend(intf, msg);
+               if (status == 0)
+                       mark_quiesced(intf);
+               else if (!interface_to_usbdev(intf)->auto_pm)
+                       dev_err(&intf->dev, "%s error %d\n",
+                                       "suspend", status);
+       } else {
+               // FIXME else if there's no suspend method, disconnect...
+               // Not possible if auto_pm is set...
+               dev_warn(&intf->dev, "no suspend for driver %s?\n",
+                               driver->name);
+               mark_quiesced(intf);
+       }
+
+done:
+       // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               intf->dev.power.power_state.event = msg.event;
+       return status;
+}
+
+/* Caller has locked intf's usb_device's pm_mutex */
+static int resume_interface(struct usb_interface *intf)
+{
+       struct usb_driver       *driver;
+       int                     status = 0;
+
+       if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+                       is_active(intf))
+               goto done;
+
+       /* Don't let autoresume interfere with unbinding */
+       if (intf->condition == USB_INTERFACE_UNBINDING)
+               goto done;
+
+       /* Can't resume it if it doesn't have a driver. */
+       if (intf->condition == USB_INTERFACE_UNBOUND) {
+               status = -ENOTCONN;
+               goto done;
+       }
+       driver = to_usb_driver(intf->dev.driver);
+
+       if (driver->resume) {
+               status = driver->resume(intf);
+               if (status)
+                       dev_err(&intf->dev, "%s error %d\n",
+                                       "resume", status);
+               else
+                       mark_active(intf);
+       } else {
+               dev_warn(&intf->dev, "no resume for driver %s?\n",
+                               driver->name);
+               mark_active(intf);
+       }
+
+done:
+       // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               intf->dev.power.power_state.event = PM_EVENT_ON;
+       return status;
+}
+
+/**
+ * usb_suspend_both - suspend a USB device and its interfaces
+ * @udev: the usb_device to suspend
+ * @msg: Power Management message describing this state transition
+ *
+ * This is the central routine for suspending USB devices.  It calls the
+ * suspend methods for all the interface drivers in @udev and then calls
+ * the suspend method for @udev itself.  If an error occurs at any stage,
+ * all the interfaces which were suspended are resumed so that they remain
+ * in the same state as the device.
+ *
+ * If an autosuspend is in progress (@udev->auto_pm is set), the routine
+ * checks first to make sure that neither the device itself or any of its
+ * active interfaces is in use (pm_usage_cnt is greater than 0).  If they
+ * are, the autosuspend fails.
+ *
+ * If the suspend succeeds, the routine recursively queues an autosuspend
+ * request for @udev's parent device, thereby propagating the change up
+ * the device tree.  If all of the parent's children are now suspended,
+ * the parent will autosuspend in turn.
+ *
+ * The suspend method calls are subject to mutual exclusion under control
+ * of @udev's pm_mutex.  Many of these calls are also under the protection
+ * of @udev's device lock (including all requests originating outside the
+ * USB subsystem), but autosuspend requests generated by a child device or
+ * interface driver may not be.  Usbcore will insure that the method calls
+ * do not arrive during bind, unbind, or reset operations.  However, drivers
+ * must be prepared to handle suspend calls arriving at unpredictable times.
+ * The only way to block such calls is to do an autoresume (preventing
+ * autosuspends) while holding @udev's device lock (preventing outside
+ * suspends).
+ *
+ * The caller must hold @udev->pm_mutex.
+ *
+ * This routine can run only in process context.
+ */
+int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+{
+       int                     status = 0;
+       int                     i = 0;
+       struct usb_interface    *intf;
+       struct usb_device       *parent = udev->parent;
+
+       cancel_delayed_work(&udev->autosuspend);
+       if (udev->state == USB_STATE_NOTATTACHED)
+               return 0;
+       if (udev->state == USB_STATE_SUSPENDED)
+               return 0;
+
+       udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+
+       /* For autosuspend, fail fast if anything is in use.
+        * Also fail if any interfaces require remote wakeup but it
+        * isn't available. */
+       if (udev->auto_pm) {
+               if (udev->pm_usage_cnt > 0)
+                       return -EBUSY;
+               if (udev->actconfig) {
+                       for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                               intf = udev->actconfig->interface[i];
+                               if (!is_active(intf))
+                                       continue;
+                               if (intf->pm_usage_cnt > 0)
+                                       return -EBUSY;
+                               if (intf->needs_remote_wakeup &&
+                                               !udev->do_remote_wakeup) {
+                                       dev_dbg(&udev->dev,
+       "remote wakeup needed for autosuspend\n");
+                                       return -EOPNOTSUPP;
+                               }
+                       }
+                       i = 0;
+               }
+       }
+
+       /* Suspend all the interfaces and then udev itself */
+       if (udev->actconfig) {
+               for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                       intf = udev->actconfig->interface[i];
+                       status = suspend_interface(intf, msg);
+                       if (status != 0)
+                               break;
+               }
+       }
+       if (status == 0)
+               status = suspend_device(udev, msg);
+
+       /* If the suspend failed, resume interfaces that did get suspended */
+       if (status != 0) {
+               while (--i >= 0) {
+                       intf = udev->actconfig->interface[i];
+                       resume_interface(intf);
+               }
+
+       /* If the suspend succeeded, propagate it up the tree */
+       } else if (parent)
+               usb_autosuspend_device(parent, 0);
+
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       return status;
+}
+
+/**
+ * usb_resume_both - resume a USB device and its interfaces
+ * @udev: the usb_device to resume
+ *
+ * This is the central routine for resuming USB devices.  It calls the
+ * the resume method for @udev and then calls the resume methods for all
+ * the interface drivers in @udev.
+ *
+ * Before starting the resume, the routine calls itself recursively for
+ * the parent device of @udev, thereby propagating the change up the device
+ * tree and assuring that @udev will be able to resume.  If the parent is
+ * unable to resume successfully, the routine fails.
+ *
+ * The resume method calls are subject to mutual exclusion under control
+ * of @udev's pm_mutex.  Many of these calls are also under the protection
+ * of @udev's device lock (including all requests originating outside the
+ * USB subsystem), but autoresume requests generated by a child device or
+ * interface driver may not be.  Usbcore will insure that the method calls
+ * do not arrive during bind, unbind, or reset operations.  However, drivers
+ * must be prepared to handle resume calls arriving at unpredictable times.
+ * The only way to block such calls is to do an autoresume (preventing
+ * other autoresumes) while holding @udev's device lock (preventing outside
+ * resumes).
+ *
+ * The caller must hold @udev->pm_mutex.
+ *
+ * This routine can run only in process context.
+ */
+int usb_resume_both(struct usb_device *udev)
+{
+       int                     status = 0;
+       int                     i;
+       struct usb_interface    *intf;
+       struct usb_device       *parent = udev->parent;
+
+       cancel_delayed_work(&udev->autosuspend);
+       if (udev->state == USB_STATE_NOTATTACHED)
+               return -ENODEV;
+
+       /* Propagate the resume up the tree, if necessary */
+       if (udev->state == USB_STATE_SUSPENDED) {
+               if (parent) {
+                       usb_pm_lock(parent);
+                       parent->auto_pm = 1;
+                       status = usb_resume_both(parent);
+               } else {
+
+                       /* We can't progagate beyond the USB subsystem,
+                        * so if a root hub's controller is suspended
+                        * then we're stuck. */
+                       if (udev->dev.parent->power.power_state.event !=
+                                       PM_EVENT_ON)
+                               status = -EHOSTUNREACH;
+               }
+               if (status == 0)
+                       status = resume_device(udev);
+               if (parent)
+                       usb_pm_unlock(parent);
+       } else {
+
+               /* Needed only for setting udev->dev.power.power_state.event
+                * and for possible debugging message. */
+               status = resume_device(udev);
+       }
+
+       /* Now the parent won't suspend until we are finished */
+
+       if (status == 0 && udev->actconfig) {
+               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                       intf = udev->actconfig->interface[i];
+                       resume_interface(intf);
+               }
+       }
+
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       return status;
+}
+
+#ifdef CONFIG_USB_SUSPEND
+
+/**
+ * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+ * @udev: the usb_device to autosuspend
+ * @dec_usage_cnt: flag to decrement @udev's PM-usage counter
+ *
+ * This routine should be called when a core subsystem is finished using
+ * @udev and wants to allow it to autosuspend.  Examples would be when
+ * @udev's device file in usbfs is closed or after a configuration change.
+ *
+ * @dec_usage_cnt should be 1 if the subsystem previously incremented
+ * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
+ * otherwise it should be 0.
+ *
+ * If the usage counter for @udev or any of its active interfaces is greater
+ * than 0, the autosuspend request will not be queued.  (If an interface
+ * driver does not support autosuspend then its usage counter is permanently
+ * positive.)  Likewise, if an interface driver requires remote-wakeup
+ * capability during autosuspend but remote wakeup is disabled, the
+ * autosuspend will fail.
+ *
+ * Often the caller will hold @udev's device lock, but this is not
+ * necessary.
+ *
+ * This routine can run only in process context.
+ */
+void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+{
+       usb_pm_lock(udev);
+       udev->pm_usage_cnt -= dec_usage_cnt;
+       if (udev->pm_usage_cnt <= 0)
+               queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+                               USB_AUTOSUSPEND_DELAY);
+       usb_pm_unlock(udev);
+       // dev_dbg(&udev->dev, "%s: cnt %d\n",
+       //              __FUNCTION__, udev->pm_usage_cnt);
+}
+
+/**
+ * usb_autoresume_device - immediately autoresume a USB device and its interfaces
+ * @udev: the usb_device to autoresume
+ * @inc_usage_cnt: flag to increment @udev's PM-usage counter
+ *
+ * This routine should be called when a core subsystem wants to use @udev
+ * and needs to guarantee that it is not suspended.  In addition, the
+ * caller can prevent @udev from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * Examples would be when @udev's device file in usbfs is opened (autosuspend
+ * should be prevented until the file is closed) or when a remote-wakeup
+ * request is received (later autosuspends should not be prevented).
+ *
+ * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
+ * autosuspends.  This prevention will persist until the usage counter is
+ * decremented again (such as by passing 1 to usb_autosuspend_device).
+ * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
+ * Regardless, if the autoresume fails then the usage counter is not
+ * incremented.
+ *
+ * Often the caller will hold @udev's device lock, but this is not
+ * necessary (and attempting it might cause deadlock).
+ *
+ * This routine can run only in process context.
+ */
+int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+{
+       int     status;
+
+       usb_pm_lock(udev);
+       udev->pm_usage_cnt += inc_usage_cnt;
+       udev->auto_pm = 1;
+       status = usb_resume_both(udev);
+       if (status != 0)
+               udev->pm_usage_cnt -= inc_usage_cnt;
+       usb_pm_unlock(udev);
+       // dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
+       //              __FUNCTION__, status, udev->pm_usage_cnt);
+       return status;
+}
+
+/**
+ * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
+ * @intf: the usb_interface whose counter should be decremented
+ *
+ * This routine should be called by an interface driver when it is
+ * finished using @intf and wants to allow it to autosuspend.  A typical
+ * example would be a character-device driver when its device file is
+ * closed.
+ *
+ * The routine decrements @intf's usage counter.  When the counter reaches
+ * 0, a delayed autosuspend request for @intf's device is queued.  When
+ * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all
+ * the other usage counters for the sibling interfaces and @intf's
+ * usb_device, the device and all its interfaces will be autosuspended.
+ *
+ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+ * core will not change its value other than the increment and decrement
+ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+ * may use this simple counter-oriented discipline or may set the value
+ * any way it likes.
+ *
+ * If the driver has set @intf->needs_remote_wakeup then autosuspend will
+ * take place only if the device's remote-wakeup facility is enabled.
+ *
+ * Suspend method calls queued by this routine can arrive at any time
+ * while @intf is resumed and its usage counter is equal to 0.  They are
+ * not protected by the usb_device's lock but only by its pm_mutex.
+ * Drivers must provide their own synchronization.
+ *
+ * This routine can run only in process context.
+ */
+void usb_autopm_put_interface(struct usb_interface *intf)
+{
+       struct usb_device       *udev = interface_to_usbdev(intf);
+
+       usb_pm_lock(udev);
+       if (intf->condition != USB_INTERFACE_UNBOUND &&
+                       --intf->pm_usage_cnt <= 0) {
+               queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+                               USB_AUTOSUSPEND_DELAY);
+       }
+       usb_pm_unlock(udev);
+       // dev_dbg(&intf->dev, "%s: cnt %d\n",
+       //              __FUNCTION__, intf->pm_usage_cnt);
+}
+EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+
+/**
+ * usb_autopm_get_interface - increment a USB interface's PM-usage counter
+ * @intf: the usb_interface whose counter should be incremented
+ *
+ * This routine should be called by an interface driver when it wants to
+ * use @intf and needs to guarantee that it is not suspended.  In addition,
+ * the routine prevents @intf from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * This prevention will persist until usb_autopm_put_interface() is called
+ * or @intf is unbound.  A typical example would be a character-device
+ * driver when its device file is opened.
+ *
+ * The routine increments @intf's usage counter.  So long as the counter
+ * is greater than 0, autosuspend will not be allowed for @intf or its
+ * usb_device.  When the driver is finished using @intf it should call
+ * usb_autopm_put_interface() to decrement the usage counter and queue
+ * a delayed autosuspend request (if the counter is <= 0).
+ *
+ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+ * core will not change its value other than the increment and decrement
+ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+ * may use this simple counter-oriented discipline or may set the value
+ * any way it likes.
+ *
+ * Resume method calls generated by this routine can arrive at any time
+ * while @intf is suspended.  They are not protected by the usb_device's
+ * lock but only by its pm_mutex.  Drivers must provide their own
+ * synchronization.
+ *
+ * This routine can run only in process context.
+ */
+int usb_autopm_get_interface(struct usb_interface *intf)
+{
+       struct usb_device       *udev = interface_to_usbdev(intf);
+       int                     status;
+
+       usb_pm_lock(udev);
+       if (intf->condition == USB_INTERFACE_UNBOUND)
+               status = -ENODEV;
+       else {
+               ++intf->pm_usage_cnt;
+               udev->auto_pm = 1;
+               status = usb_resume_both(udev);
+               if (status != 0)
+                       --intf->pm_usage_cnt;
+       }
+       usb_pm_unlock(udev);
+       // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+       //              __FUNCTION__, status, intf->pm_usage_cnt);
+       return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+
+#endif /* CONFIG_USB_SUSPEND */
+
+static int usb_suspend(struct device *dev, pm_message_t message)
+{
+       int     status;
+
+       if (is_usb_device(dev)) {
+               struct usb_device *udev = to_usb_device(dev);
+
+               usb_pm_lock(udev);
+               udev->auto_pm = 0;
+               status = usb_suspend_both(udev, message);
+               usb_pm_unlock(udev);
+       } else
+               status = 0;
+       return status;
+}
+
+static int usb_resume(struct device *dev)
+{
+       int     status;
+
+       if (is_usb_device(dev)) {
+               struct usb_device *udev = to_usb_device(dev);
+
+               usb_pm_lock(udev);
+               udev->auto_pm = 0;
+               status = usb_resume_both(udev);
+               usb_pm_unlock(udev);
+
+               /* Rebind drivers that had no suspend method? */
+       } else
+               status = 0;
+       return status;
+}
+
+#endif /* CONFIG_PM */
+
+struct bus_type usb_bus_type = {
+       .name =         "usb",
+       .match =        usb_device_match,
+       .uevent =       usb_uevent,
+#ifdef CONFIG_PM
+       .suspend =      usb_suspend,
+       .resume =       usb_resume,
+#endif
+};
index 247b5a4913a8079491f0104bfe5eaeaf972d8fd1..3ebb90149e93ef7319ae529c22da546032172730 100644 (file)
@@ -207,9 +207,9 @@ static void ep_device_release(struct device *dev)
        kfree(ep_dev);
 }
 
-void usb_create_ep_files(struct device *parent,
-                        struct usb_host_endpoint *endpoint,
-                        struct usb_device *udev)
+int usb_create_ep_files(struct device *parent,
+                       struct usb_host_endpoint *endpoint,
+                       struct usb_device *udev)
 {
        char name[8];
        struct ep_device *ep_dev;
@@ -242,19 +242,33 @@ void usb_create_ep_files(struct device *parent,
        retval = device_register(&ep_dev->dev);
        if (retval)
                goto error;
-       sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+       retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+       if (retval)
+               goto error_group;
 
        endpoint->ep_dev = ep_dev;
 
        /* create the symlink to the old-style "ep_XX" directory */
        sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
-       sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name);
-
+       retval = sysfs_create_link(&parent->kobj,
+                                  &endpoint->ep_dev->dev.kobj, name);
+       if (retval)
+               goto error_link;
 exit:
-       return;
+       return retval;
+
+error_link:
+       sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+
+error_group:
+       device_unregister(&ep_dev->dev);
+       endpoint->ep_dev = NULL;
+       destroy_endpoint_class();
+       return retval;
 error:
        kfree(ep_dev);
-       return;
+       destroy_endpoint_class();
+       return retval;
 }
 
 void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
index 8de4f8c99d61f3a7cb01696bde29202ed814b160..c376c655c5defc8f6a0693430c29663f6b4e2a44 100644 (file)
@@ -55,7 +55,7 @@ static int usb_open(struct inode * inode, struct file * file)
        return err;
 }
 
-static struct file_operations usb_fops = {
+static const struct file_operations usb_fops = {
        .owner =        THIS_MODULE,
        .open =         usb_open,
 };
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
new file mode 100644 (file)
index 0000000..16332cc
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * drivers/usb/generic.c - generic driver for USB devices (not interfaces)
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * based on drivers/usb/usb.c which had the following copyrights:
+ *     (C) Copyright Linus Torvalds 1999
+ *     (C) Copyright Johannes Erdfelt 1999-2001
+ *     (C) Copyright Andreas Gal 1999
+ *     (C) Copyright Gregory P. Smith 1999
+ *     (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ *     (C) Copyright Randy Dunlap 2000
+ *     (C) Copyright David Brownell 2000-2004
+ *     (C) Copyright Yggdrasil Computing, Inc. 2000
+ *             (usb_device_id matching changes by Adam J. Richter)
+ *     (C) Copyright Greg Kroah-Hartman 2002-2003
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/usb.h>
+#include "usb.h"
+
+static inline const char *plural(int n)
+{
+       return (n == 1 ? "" : "s");
+}
+
+static int choose_configuration(struct usb_device *udev)
+{
+       int i;
+       int num_configs;
+       int insufficient_power = 0;
+       struct usb_host_config *c, *best;
+
+       best = NULL;
+       c = udev->config;
+       num_configs = udev->descriptor.bNumConfigurations;
+       for (i = 0; i < num_configs; (i++, c++)) {
+               struct usb_interface_descriptor *desc = NULL;
+
+               /* It's possible that a config has no interfaces! */
+               if (c->desc.bNumInterfaces > 0)
+                       desc = &c->intf_cache[0]->altsetting->desc;
+
+               /*
+                * HP's USB bus-powered keyboard has only one configuration
+                * and it claims to be self-powered; other devices may have
+                * similar errors in their descriptors.  If the next test
+                * were allowed to execute, such configurations would always
+                * be rejected and the devices would not work as expected.
+                * In the meantime, we run the risk of selecting a config
+                * that requires external power at a time when that power
+                * isn't available.  It seems to be the lesser of two evils.
+                *
+                * Bugzilla #6448 reports a device that appears to crash
+                * when it receives a GET_DEVICE_STATUS request!  We don't
+                * have any other way to tell whether a device is self-powered,
+                * but since we don't use that information anywhere but here,
+                * the call has been removed.
+                *
+                * Maybe the GET_DEVICE_STATUS call and the test below can
+                * be reinstated when device firmwares become more reliable.
+                * Don't hold your breath.
+                */
+#if 0
+               /* Rule out self-powered configs for a bus-powered device */
+               if (bus_powered && (c->desc.bmAttributes &
+                                       USB_CONFIG_ATT_SELFPOWER))
+                       continue;
+#endif
+
+               /*
+                * The next test may not be as effective as it should be.
+                * Some hubs have errors in their descriptor, claiming
+                * to be self-powered when they are really bus-powered.
+                * We will overestimate the amount of current such hubs
+                * make available for each port.
+                *
+                * This is a fairly benign sort of failure.  It won't
+                * cause us to reject configurations that we should have
+                * accepted.
+                */
+
+               /* Rule out configs that draw too much bus current */
+               if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+                       insufficient_power++;
+                       continue;
+               }
+
+               /* If the first config's first interface is COMM/2/0xff
+                * (MSFT RNDIS), rule it out unless Linux has host-side
+                * RNDIS support. */
+               if (i == 0 && desc
+                               && desc->bInterfaceClass == USB_CLASS_COMM
+                               && desc->bInterfaceSubClass == 2
+                               && desc->bInterfaceProtocol == 0xff) {
+#ifndef CONFIG_USB_NET_RNDIS_HOST
+                       continue;
+#else
+                       best = c;
+#endif
+               }
+
+               /* From the remaining configs, choose the first one whose
+                * first interface is for a non-vendor-specific class.
+                * Reason: Linux is more likely to have a class driver
+                * than a vendor-specific driver. */
+               else if (udev->descriptor.bDeviceClass !=
+                                               USB_CLASS_VENDOR_SPEC &&
+                               (!desc || desc->bInterfaceClass !=
+                                               USB_CLASS_VENDOR_SPEC)) {
+                       best = c;
+                       break;
+               }
+
+               /* If all the remaining configs are vendor-specific,
+                * choose the first one. */
+               else if (!best)
+                       best = c;
+       }
+
+       if (insufficient_power > 0)
+               dev_info(&udev->dev, "rejected %d configuration%s "
+                       "due to insufficient available bus power\n",
+                       insufficient_power, plural(insufficient_power));
+
+       if (best) {
+               i = best->desc.bConfigurationValue;
+               dev_info(&udev->dev,
+                       "configuration #%d chosen from %d choice%s\n",
+                       i, num_configs, plural(num_configs));
+       } else {
+               i = -1;
+               dev_warn(&udev->dev,
+                       "no configuration chosen from %d choice%s\n",
+                       num_configs, plural(num_configs));
+       }
+       return i;
+}
+
+static int generic_probe(struct usb_device *udev)
+{
+       int err, c;
+
+       /* put device-specific files into sysfs */
+       usb_create_sysfs_dev_files(udev);
+
+       /* Choose and set the configuration.  This registers the interfaces
+        * with the driver core and lets interface drivers bind to them.
+        */
+       c = choose_configuration(udev);
+       if (c >= 0) {
+               err = usb_set_configuration(udev, c);
+               if (err) {
+                       dev_err(&udev->dev, "can't set config #%d, error %d\n",
+                                       c, err);
+                       /* This need not be fatal.  The user can try to
+                        * set other configurations. */
+               }
+       }
+
+       /* USB device state == configured ... usable */
+       usb_notify_add_device(udev);
+
+       return 0;
+}
+
+static void generic_disconnect(struct usb_device *udev)
+{
+       usb_notify_remove_device(udev);
+
+       /* if this is only an unbind, not a physical disconnect, then
+        * unconfigure the device */
+       if (udev->actconfig)
+               usb_set_configuration(udev, 0);
+
+       usb_remove_sysfs_dev_files(udev);
+}
+
+#ifdef CONFIG_PM
+
+static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+{
+       /* USB devices enter SUSPEND state through their hubs, but can be
+        * marked for FREEZE as soon as their children are already idled.
+        * But those semantics are useless, so we equate the two (sigh).
+        */
+       return usb_port_suspend(udev);
+}
+
+static int generic_resume(struct usb_device *udev)
+{
+       return usb_port_resume(udev);
+}
+
+#endif /* CONFIG_PM */
+
+struct usb_device_driver usb_generic_driver = {
+       .name = "usb",
+       .probe = generic_probe,
+       .disconnect = generic_disconnect,
+#ifdef CONFIG_PM
+       .suspend = generic_suspend,
+       .resume = generic_resume,
+#endif
+       .supports_autosuspend = 1,
+};
index fa36391fedd39676b7c9621fcb39539079f50d02..edf4300a3f7a75d748776ab3fe3d69fbf1a6f66d 100644 (file)
@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
 
 #endif /* CONFIG_PM */
 
+/**
+ * usb_hcd_pci_shutdown - shutdown host controller
+ * @dev: USB Host Controller being shutdown
+ */
+void usb_hcd_pci_shutdown (struct pci_dev *dev)
+{
+       struct usb_hcd          *hcd;
+
+       hcd = pci_get_drvdata(dev);
+       if (!hcd)
+               return;
+
+       if (hcd->driver->shutdown)
+               hcd->driver->shutdown(hcd);
+}
+EXPORT_SYMBOL (usb_hcd_pci_shutdown);
 
index fb4d058bbde00d006deb8d4f50ce7496fbcf1384..37f9f5e7425d1b5e1a518302fa36cad686989c25 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/mutex.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
+#include <linux/platform_device.h>
 
 #include <linux/usb.h>
 
@@ -344,7 +345,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
        struct usb_ctrlrequest *cmd;
        u16             typeReq, wValue, wIndex, wLength;
        u8              *ubuf = urb->transfer_buffer;
-       u8              tbuf [sizeof (struct usb_hub_descriptor)];
+       u8              tbuf [sizeof (struct usb_hub_descriptor)]
+               __attribute__((aligned(4)));
        const u8        *bufp = tbuf;
        int             len = 0;
        int             patch_wakeup = 0;
@@ -632,31 +634,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
 
 /*-------------------------------------------------------------------------*/
 
-/* Asynchronous unlinks of root-hub control URBs are legal, but they
- * don't do anything.  Status URB unlinks must be made in process context
- * with interrupts enabled.
+/* Unlinks of root-hub control URBs are legal, but they don't do anything
+ * since these URBs always execute synchronously.
  */
 static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
-       if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
-               if (in_interrupt())
-                       return 0;               /* nothing to do */
-
-               spin_lock_irq(&urb->lock);      /* from usb_kill_urb */
-               ++urb->reject;
-               spin_unlock_irq(&urb->lock);
-
-               wait_event(usb_kill_urb_queue,
-                               atomic_read(&urb->use_count) == 0);
+       unsigned long   flags;
 
-               spin_lock_irq(&urb->lock);
-               --urb->reject;
-               spin_unlock_irq(&urb->lock);
+       if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
+               ;       /* Do nothing */
 
        } else {                                /* Status URB */
                if (!hcd->uses_new_polling)
-                       del_timer_sync (&hcd->rh_timer);
-               local_irq_disable ();
+                       del_timer (&hcd->rh_timer);
+               local_irq_save (flags);
                spin_lock (&hcd_root_hub_lock);
                if (urb == hcd->status_urb) {
                        hcd->status_urb = NULL;
@@ -666,7 +657,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
                spin_unlock (&hcd_root_hub_lock);
                if (urb)
                        usb_hcd_giveback_urb (hcd, urb, NULL);
-               local_irq_enable ();
+               local_irq_restore (flags);
        }
 
        return 0;
@@ -674,31 +665,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 
 /*-------------------------------------------------------------------------*/
 
-/* exported only within usbcore */
-struct usb_bus *usb_bus_get(struct usb_bus *bus)
-{
-       if (bus)
-               kref_get(&bus->kref);
-       return bus;
-}
-
-static void usb_host_release(struct kref *kref)
-{
-       struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
-
-       if (bus->release)
-               bus->release(bus);
-}
-
-/* exported only within usbcore */
-void usb_bus_put(struct usb_bus *bus)
-{
-       if (bus)
-               kref_put(&bus->kref, usb_host_release);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static struct class *usb_host_class;
 
 int usb_host_init(void)
@@ -730,39 +696,12 @@ static void usb_bus_init (struct usb_bus *bus)
        bus->devnum_next = 1;
 
        bus->root_hub = NULL;
-       bus->hcpriv = NULL;
        bus->busnum = -1;
        bus->bandwidth_allocated = 0;
        bus->bandwidth_int_reqs  = 0;
        bus->bandwidth_isoc_reqs = 0;
 
        INIT_LIST_HEAD (&bus->bus_list);
-
-       kref_init(&bus->kref);
-}
-
-/**
- * usb_alloc_bus - creates a new USB host controller structure
- * @op: pointer to a struct usb_operations that this bus structure should use
- * Context: !in_interrupt()
- *
- * Creates a USB host controller bus structure with the specified 
- * usb_operations and initializes all the necessary internal objects.
- *
- * If no memory is available, NULL is returned.
- *
- * The caller should call usb_put_bus() when it is finished with the structure.
- */
-struct usb_bus *usb_alloc_bus (struct usb_operations *op)
-{
-       struct usb_bus *bus;
-
-       bus = kzalloc (sizeof *bus, GFP_KERNEL);
-       if (!bus)
-               return NULL;
-       usb_bus_init (bus);
-       bus->op = op;
-       return bus;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -897,8 +836,7 @@ void usb_enable_root_hub_irq (struct usb_bus *bus)
        struct usb_hcd *hcd;
 
        hcd = container_of (bus, struct usb_hcd, self);
-       if (hcd->driver->hub_irq_enable && !hcd->poll_rh &&
-                       hcd->state != HC_STATE_HALT)
+       if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
                hcd->driver->hub_irq_enable (hcd);
 }
 
@@ -1112,10 +1050,10 @@ static void urb_unlink (struct urb *urb)
  * expects usb_submit_urb() to have sanity checked and conditioned all
  * inputs in the urb
  */
-static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
        int                     status;
-       struct usb_hcd          *hcd = urb->dev->bus->hcpriv;
+       struct usb_hcd          *hcd = bus_to_hcd(urb->dev->bus);
        struct usb_host_endpoint *ep;
        unsigned long           flags;
 
@@ -1186,7 +1124,7 @@ doit:
        /* lower level hcd code should use *_dma exclusively,
         * unless it uses pio or talks to another transport.
         */
-       if (hcd->self.controller->dma_mask) {
+       if (hcd->self.uses_dma) {
                if (usb_pipecontrol (urb->pipe)
                        && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                        urb->setup_dma = dma_map_single (
@@ -1221,9 +1159,10 @@ done:
 /*-------------------------------------------------------------------------*/
 
 /* called in any context */
-static int hcd_get_frame_number (struct usb_device *udev)
+int usb_hcd_get_frame_number (struct usb_device *udev)
 {
-       struct usb_hcd  *hcd = (struct usb_hcd *)udev->bus->hcpriv;
+       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
+
        if (!HC_IS_RUNNING (hcd->state))
                return -ESHUTDOWN;
        return hcd->driver->get_frame_number (hcd);
@@ -1263,7 +1202,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
  * caller guarantees urb won't be recycled till both unlink()
  * and the urb's completion function return
  */
-static int hcd_unlink_urb (struct urb *urb, int status)
+int usb_hcd_unlink_urb (struct urb *urb, int status)
 {
        struct usb_host_endpoint        *ep;
        struct usb_hcd                  *hcd = NULL;
@@ -1296,7 +1235,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
        spin_lock (&hcd_data_lock);
 
        sys = &urb->dev->dev;
-       hcd = urb->dev->bus->hcpriv;
+       hcd = bus_to_hcd(urb->dev->bus);
        if (hcd == NULL) {
                retval = -ENODEV;
                goto done;
@@ -1354,41 +1293,33 @@ done:
 /*-------------------------------------------------------------------------*/
 
 /* disables the endpoint: cancels any pending urbs, then synchronizes with
- * the hcd to make sure all endpoint state is gone from hardware. use for
+ * the hcd to make sure all endpoint state is gone from hardware, and then
+ * waits until the endpoint's queue is completely drained. use for
  * set_configuration, set_interface, driver removal, physical disconnect.
  *
  * example:  a qh stored in ep->hcpriv, holding state related to endpoint
  * type, maxpacket size, toggle, halt status, and scheduling.
  */
-static void
-hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+void usb_hcd_endpoint_disable (struct usb_device *udev,
+               struct usb_host_endpoint *ep)
 {
        struct usb_hcd          *hcd;
        struct urb              *urb;
 
-       hcd = udev->bus->hcpriv;
+       hcd = bus_to_hcd(udev->bus);
 
        WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
                        udev->state != USB_STATE_NOTATTACHED);
 
        local_irq_disable ();
 
-       /* FIXME move most of this into message.c as part of its
-        * endpoint disable logic
-        */
-
        /* ep is already gone from udev->ep_{in,out}[]; no more submits */
 rescan:
        spin_lock (&hcd_data_lock);
        list_for_each_entry (urb, &ep->urb_list, urb_list) {
                int     tmp;
 
-               /* another cpu may be in hcd, spinning on hcd_data_lock
-                * to giveback() this urb.  the races here should be
-                * small, but a full fix needs a new "can't submit"
-                * urb state.
-                * FIXME urb->reject should allow that...
-                */
+               /* the urb may already have been unlinked */
                if (urb->status != -EINPROGRESS)
                        continue;
                usb_get_urb (urb);
@@ -1430,6 +1361,30 @@ rescan:
        might_sleep ();
        if (hcd->driver->endpoint_disable)
                hcd->driver->endpoint_disable (hcd, ep);
+
+       /* Wait until the endpoint queue is completely empty.  Most HCDs
+        * will have done this already in their endpoint_disable method,
+        * but some might not.  And there could be root-hub control URBs
+        * still pending since they aren't affected by the HCDs'
+        * endpoint_disable methods.
+        */
+       while (!list_empty (&ep->urb_list)) {
+               spin_lock_irq (&hcd_data_lock);
+
+               /* The list may have changed while we acquired the spinlock */
+               urb = NULL;
+               if (!list_empty (&ep->urb_list)) {
+                       urb = list_entry (ep->urb_list.prev, struct urb,
+                                       urb_list);
+                       usb_get_urb (urb);
+               }
+               spin_unlock_irq (&hcd_data_lock);
+
+               if (urb) {
+                       usb_kill_urb (urb);
+                       usb_put_urb (urb);
+               }
+       }
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1476,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus)
        return status;
 }
 
-/*
- * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
- * @hcd: host controller for this root hub
- *
- * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
- * that the HCD's root hub polling is deactivated; and that the root's hub
- * driver is suspended.  HCDs may call this to autosuspend when their root
- * hub's downstream ports are all inactive:  unpowered, disconnected,
- * disabled, or suspended.
- *
- * The HCD will autoresume on device connect change detection (using SRP
- * or a D+/D- pullup).  The HCD also autoresumes on remote wakeup signaling
- * from any ports that are suspended (if that is enabled).  In most cases,
- * overcurrent signaling (on powered ports) will also start autoresume.
- *
- * Always called with IRQs blocked.
- */
-void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
-{
-       struct urb      *urb;
-
-       spin_lock (&hcd_root_hub_lock);
-       usb_suspend_root_hub (hcd->self.root_hub);
-
-       /* force status urb to complete/unlink while suspended */
-       if (hcd->status_urb) {
-               urb = hcd->status_urb;
-               urb->status = -ECONNRESET;
-               urb->hcpriv = NULL;
-               urb->actual_length = 0;
-
-               del_timer (&hcd->rh_timer);
-               hcd->poll_pending = 0;
-               hcd->status_urb = NULL;
-       } else
-               urb = NULL;
-       spin_unlock (&hcd_root_hub_lock);
-       hcd->state = HC_STATE_SUSPENDED;
-
-       if (urb)
-               usb_hcd_giveback_urb (hcd, urb, NULL);
-}
-EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
-
 /**
  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
  * @hcd: host controller for this root hub
@@ -1583,20 +1494,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
- */
-static struct usb_operations usb_hcd_operations = {
-       .get_frame_number =     hcd_get_frame_number,
-       .submit_urb =           hcd_submit_urb,
-       .unlink_urb =           hcd_unlink_urb,
-       .buffer_alloc =         hcd_buffer_alloc,
-       .buffer_free =          hcd_buffer_free,
-       .disable =              hcd_endpoint_disable,
-};
-
-/*-------------------------------------------------------------------------*/
-
 /**
  * usb_hcd_giveback_urb - return URB from HCD to device driver
  * @hcd: host controller returning the URB
@@ -1617,8 +1514,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
        at_root_hub = (urb->dev == hcd->self.root_hub);
        urb_unlink (urb);
 
-       /* lower level hcd code should use *_dma exclusively */
-       if (hcd->self.controller->dma_mask && !at_root_hub) {
+       /* lower level hcd code should use *_dma exclusively if the
+        * host controller does DMA */
+       if (hcd->self.uses_dma && !at_root_hub) {
                if (usb_pipecontrol (urb->pipe)
                        && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                        dma_unmap_single (hcd->self.controller, urb->setup_dma,
@@ -1704,14 +1602,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
 
 /*-------------------------------------------------------------------------*/
 
-static void hcd_release (struct usb_bus *bus)
-{
-       struct usb_hcd *hcd;
-
-       hcd = container_of(bus, struct usb_hcd, self);
-       kfree(hcd);
-}
-
 /**
  * usb_create_hcd - create and initialize an HCD structure
  * @driver: HC driver that will use this hcd
@@ -1736,13 +1626,12 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
                return NULL;
        }
        dev_set_drvdata(dev, hcd);
+       kref_init(&hcd->kref);
 
        usb_bus_init(&hcd->self);
-       hcd->self.op = &usb_hcd_operations;
-       hcd->self.hcpriv = hcd;
-       hcd->self.release = &hcd_release;
        hcd->self.controller = dev;
        hcd->self.bus_name = bus_name;
+       hcd->self.uses_dma = (dev->dma_mask != NULL);
 
        init_timer(&hcd->rh_timer);
        hcd->rh_timer.function = rh_timer_func;
@@ -1756,10 +1645,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 }
 EXPORT_SYMBOL (usb_create_hcd);
 
+static void hcd_release (struct kref *kref)
+{
+       struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
+
+       kfree(hcd);
+}
+
+struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
+{
+       if (hcd)
+               kref_get (&hcd->kref);
+       return hcd;
+}
+EXPORT_SYMBOL (usb_get_hcd);
+
 void usb_put_hcd (struct usb_hcd *hcd)
 {
-       dev_set_drvdata(hcd->self.controller, NULL);
-       usb_bus_put(&hcd->self);
+       if (hcd)
+               kref_put (&hcd->kref, hcd_release);
 }
 EXPORT_SYMBOL (usb_put_hcd);
 
@@ -1915,6 +1819,16 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL (usb_remove_hcd);
 
+void
+usb_hcd_platform_shutdown(struct platform_device* dev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+       if (hcd->driver->shutdown)
+               hcd->driver->shutdown(hcd);
+}
+EXPORT_SYMBOL (usb_hcd_platform_shutdown);
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_USB_MON)
index 7022aafb2ae8bedf9460d5c433fcea9329814251..676877c15f8187731e833bab4750407ce1c0bdd2 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
-struct usb_hcd {       /* usb_bus.hcpriv points to this */
+struct usb_hcd {
 
        /*
         * housekeeping
         */
        struct usb_bus          self;           /* hcd is-a bus */
+       struct kref             kref;           /* reference counter */
 
        const char              *product_desc;  /* product/vendor string */
        char                    irq_descr[24];  /* driver + bus # */
@@ -85,6 +86,7 @@ struct usb_hcd {      /* usb_bus.hcpriv points to this */
        unsigned                uses_new_polling:1;
        unsigned                poll_rh:1;      /* poll for rh status? */
        unsigned                poll_pending:1; /* status has changed? */
+       unsigned                wireless:1;     /* Wireless USB HCD */
 
        int                     irq;            /* irq allocated */
        void __iomem            *regs;          /* device memory/io */
@@ -128,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
        return &hcd->self;
 }
 
-
-// urb.hcpriv is really hardware-specific
+static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
+{
+       return container_of(bus, struct usb_hcd, self);
+}
 
 struct hcd_timeout {   /* timeouts we allocate */
        struct list_head        timeout_list;
@@ -138,28 +142,6 @@ struct hcd_timeout {       /* timeouts we allocate */
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * FIXME usb_operations should vanish or become hc_driver,
- * when usb_bus and usb_hcd become the same thing.
- */
-
-struct usb_operations {
-       int (*get_frame_number) (struct usb_device *usb_dev);
-       int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
-       int (*unlink_urb) (struct urb *urb, int status);
-
-       /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
-       void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
-                       gfp_t mem_flags,
-                       dma_addr_t *dma);
-       void (*buffer_free)(struct usb_bus *bus, size_t size,
-                       void *addr, dma_addr_t dma);
-
-       void (*disable)(struct usb_device *udev,
-                       struct usb_host_endpoint *ep);
-};
-
-/* each driver provides one of these, and hardware init support */
 
 struct pt_regs;
 
@@ -192,6 +174,9 @@ struct hc_driver {
        /* cleanly make HCD stop writing memory and doing I/O */
        void    (*stop) (struct usb_hcd *hcd);
 
+       /* shutdown HCD */
+       void    (*shutdown) (struct usb_hcd *hcd);
+
        /* return current frame number */
        int     (*get_frame_number) (struct usb_hcd *hcd);
 
@@ -218,15 +203,25 @@ struct hc_driver {
                /* Needed only if port-change IRQs are level-triggered */
 };
 
-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
+extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
+extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
+               struct pt_regs *regs);
+extern void usb_hcd_endpoint_disable (struct usb_device *udev,
+               struct usb_host_endpoint *ep);
+extern int usb_hcd_get_frame_number (struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
                struct device *dev, char *bus_name);
+extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
 extern void usb_put_hcd (struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
                unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 
+struct platform_device;
+extern void usb_hcd_platform_shutdown(struct platform_device* dev);
+
 #ifdef CONFIG_PCI
 struct pci_dev;
 struct pci_device_id;
@@ -239,6 +234,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
 extern int usb_hcd_pci_resume (struct pci_dev *dev);
 #endif /* CONFIG_PM */
 
+extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
+
 #endif /* CONFIG_PCI */
 
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */
@@ -352,8 +349,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
 
 /*-------------------------------------------------------------------------*/
 
-extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-
 extern void usb_set_device_state(struct usb_device *udev,
                enum usb_device_state new_state);
 
@@ -365,9 +360,6 @@ extern struct list_head usb_bus_list;
 extern struct mutex usb_bus_list_lock;
 extern wait_queue_head_t usb_kill_urb_queue;
 
-extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
-extern void usb_bus_put (struct usb_bus *bus);
-
 extern void usb_enable_root_hub_irq (struct usb_bus *bus);
 
 extern int usb_find_interface_driver (struct usb_device *dev,
@@ -376,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev,
 #define usb_endpoint_out(ep_dir)       (!((ep_dir) & USB_DIR_IN))
 
 #ifdef CONFIG_PM
-extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power (struct usb_device *rhdev);
 extern int hcd_bus_suspend (struct usb_bus *bus);
 extern int hcd_bus_resume (struct usb_bus *bus);
 #else
-static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
-{
-       return;
-}
-
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
        return;
index 26c8cb5f3e6722467379204762fb5d8a89b938a0..7676690a0386aedc56242def77c874825714b13b 100644 (file)
@@ -293,7 +293,7 @@ void usb_kick_khubd(struct usb_device *hdev)
 /* completion function, fires on port status changes and various faults */
 static void hub_irq(struct urb *urb, struct pt_regs *regs)
 {
-       struct usb_hub *hub = (struct usb_hub *)urb->context;
+       struct usb_hub *hub = urb->context;
        int status;
        int i;
        unsigned long bits;
@@ -311,7 +311,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
                        goto resubmit;
                hub->error = urb->status;
                /* FALL THROUGH */
-       
+
        /* let khubd handle things */
        case 0:                 /* we got data:  port status changed */
                bits = 0;
@@ -452,18 +452,14 @@ static void hub_power_on(struct usb_hub *hub)
        msleep(max(pgood_delay, (unsigned) 100));
 }
 
-static inline void __hub_quiesce(struct usb_hub *hub)
+static void hub_quiesce(struct usb_hub *hub)
 {
        /* (nonblocking) khubd and related activity won't re-trigger */
        hub->quiescing = 1;
        hub->activating = 0;
        hub->resume_root_hub = 0;
-}
 
-static void hub_quiesce(struct usb_hub *hub)
-{
        /* (blocking) stop khubd and related activity */
-       __hub_quiesce(hub);
        usb_kill_urb(hub->urb);
        if (hub->has_indicators)
                cancel_delayed_work(&hub->leds);
@@ -868,13 +864,8 @@ descriptor_error:
 
        endpoint = &desc->endpoint[0].desc;
 
-       /* Output endpoint? Curiouser and curiouser.. */
-       if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-               goto descriptor_error;
-
-       /* If it's not an interrupt endpoint, we'd better punt! */
-       if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                       != USB_ENDPOINT_XFER_INT)
+       /* If it's not an interrupt in endpoint, we'd better punt! */
+       if (!usb_endpoint_is_int_in(endpoint))
                goto descriptor_error;
 
        /* We found a hub */
@@ -1022,26 +1013,29 @@ void usb_set_device_state(struct usb_device *udev,
        if (udev->state == USB_STATE_NOTATTACHED)
                ;       /* do nothing */
        else if (new_state != USB_STATE_NOTATTACHED) {
-               udev->state = new_state;
 
                /* root hub wakeup capabilities are managed out-of-band
                 * and may involve silicon errata ... ignore them here.
                 */
                if (udev->parent) {
-                       if (new_state == USB_STATE_CONFIGURED)
+                       if (udev->state == USB_STATE_SUSPENDED
+                                       || new_state == USB_STATE_SUSPENDED)
+                               ;       /* No change to wakeup settings */
+                       else if (new_state == USB_STATE_CONFIGURED)
                                device_init_wakeup(&udev->dev,
                                        (udev->actconfig->desc.bmAttributes
                                         & USB_CONFIG_ATT_WAKEUP));
-                       else if (new_state != USB_STATE_SUSPENDED)
+                       else
                                device_init_wakeup(&udev->dev, 0);
                }
+               udev->state = new_state;
        } else
                recursively_mark_NOTATTACHED(udev);
        spin_unlock_irqrestore(&device_state_lock, flags);
 }
 
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM
 
 /**
  * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
@@ -1059,6 +1053,12 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
        unsigned long flags;
 
        dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+
+       /* Make sure no potential wakeup events get lost,
+        * by forcing the root hub to be resumed.
+        */
+       rhdev->dev.power.prev_state.event = PM_EVENT_ON;
+
        spin_lock_irqsave(&device_state_lock, flags);
        hub = hdev_to_hub(rhdev);
        for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
@@ -1072,7 +1072,7 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
 }
 EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
 
-#endif
+#endif /* CONFIG_PM */
 
 static void choose_address(struct usb_device *udev)
 {
@@ -1148,144 +1148,28 @@ void usb_disconnect(struct usb_device **pdev)
         * cleaning up all state associated with the current configuration
         * so that the hardware is now fully quiesced.
         */
+       dev_dbg (&udev->dev, "unregistering device\n");
        usb_disable_device(udev, 0);
 
-       usb_notify_remove_device(udev);
+       usb_unlock_device(udev);
 
-       /* Free the device number, remove the /proc/bus/usb entry and
-        * the sysfs attributes, and delete the parent's children[]
+       /* Unregister the device.  The device driver is responsible
+        * for removing the device files from usbfs and sysfs and for
+        * de-configuring the device.
+        */
+       device_del(&udev->dev);
+
+       /* Free the device number and delete the parent's children[]
         * (or root_hub) pointer.
         */
-       dev_dbg (&udev->dev, "unregistering device\n");
        release_address(udev);
-       usb_remove_sysfs_dev_files(udev);
 
        /* Avoid races with recursively_mark_NOTATTACHED() */
        spin_lock_irq(&device_state_lock);
        *pdev = NULL;
        spin_unlock_irq(&device_state_lock);
 
-       usb_unlock_device(udev);
-
-       device_unregister(&udev->dev);
-}
-
-static inline const char *plural(int n)
-{
-       return (n == 1 ? "" : "s");
-}
-
-static int choose_configuration(struct usb_device *udev)
-{
-       int i;
-       int num_configs;
-       int insufficient_power = 0;
-       struct usb_host_config *c, *best;
-
-       best = NULL;
-       c = udev->config;
-       num_configs = udev->descriptor.bNumConfigurations;
-       for (i = 0; i < num_configs; (i++, c++)) {
-               struct usb_interface_descriptor *desc = NULL;
-
-               /* It's possible that a config has no interfaces! */
-               if (c->desc.bNumInterfaces > 0)
-                       desc = &c->intf_cache[0]->altsetting->desc;
-
-               /*
-                * HP's USB bus-powered keyboard has only one configuration
-                * and it claims to be self-powered; other devices may have
-                * similar errors in their descriptors.  If the next test
-                * were allowed to execute, such configurations would always
-                * be rejected and the devices would not work as expected.
-                * In the meantime, we run the risk of selecting a config
-                * that requires external power at a time when that power
-                * isn't available.  It seems to be the lesser of two evils.
-                *
-                * Bugzilla #6448 reports a device that appears to crash
-                * when it receives a GET_DEVICE_STATUS request!  We don't
-                * have any other way to tell whether a device is self-powered,
-                * but since we don't use that information anywhere but here,
-                * the call has been removed.
-                *
-                * Maybe the GET_DEVICE_STATUS call and the test below can
-                * be reinstated when device firmwares become more reliable.
-                * Don't hold your breath.
-                */
-#if 0
-               /* Rule out self-powered configs for a bus-powered device */
-               if (bus_powered && (c->desc.bmAttributes &
-                                       USB_CONFIG_ATT_SELFPOWER))
-                       continue;
-#endif
-
-               /*
-                * The next test may not be as effective as it should be.
-                * Some hubs have errors in their descriptor, claiming
-                * to be self-powered when they are really bus-powered.
-                * We will overestimate the amount of current such hubs
-                * make available for each port.
-                *
-                * This is a fairly benign sort of failure.  It won't
-                * cause us to reject configurations that we should have
-                * accepted.
-                */
-
-               /* Rule out configs that draw too much bus current */
-               if (c->desc.bMaxPower * 2 > udev->bus_mA) {
-                       insufficient_power++;
-                       continue;
-               }
-
-               /* If the first config's first interface is COMM/2/0xff
-                * (MSFT RNDIS), rule it out unless Linux has host-side
-                * RNDIS support. */
-               if (i == 0 && desc
-                               && desc->bInterfaceClass == USB_CLASS_COMM
-                               && desc->bInterfaceSubClass == 2
-                               && desc->bInterfaceProtocol == 0xff) {
-#ifndef CONFIG_USB_NET_RNDIS_HOST
-                       continue;
-#else
-                       best = c;
-#endif
-               }
-
-               /* From the remaining configs, choose the first one whose
-                * first interface is for a non-vendor-specific class.
-                * Reason: Linux is more likely to have a class driver
-                * than a vendor-specific driver. */
-               else if (udev->descriptor.bDeviceClass !=
-                                               USB_CLASS_VENDOR_SPEC &&
-                               (!desc || desc->bInterfaceClass !=
-                                               USB_CLASS_VENDOR_SPEC)) {
-                       best = c;
-                       break;
-               }
-
-               /* If all the remaining configs are vendor-specific,
-                * choose the first one. */
-               else if (!best)
-                       best = c;
-       }
-
-       if (insufficient_power > 0)
-               dev_info(&udev->dev, "rejected %d configuration%s "
-                       "due to insufficient available bus power\n",
-                       insufficient_power, plural(insufficient_power));
-
-       if (best) {
-               i = best->desc.bConfigurationValue;
-               dev_info(&udev->dev,
-                       "configuration #%d chosen from %d choice%s\n",
-                       i, num_configs, plural(num_configs));
-       } else {
-               i = -1;
-               dev_warn(&udev->dev,
-                       "no configuration chosen from %d choice%s\n",
-                       num_configs, plural(num_configs));
-       }
-       return i;
+       put_device(&udev->dev);
 }
 
 #ifdef DEBUG
@@ -1328,7 +1212,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 int usb_new_device(struct usb_device *udev)
 {
        int err;
-       int c;
 
        err = usb_get_configuration(udev);
        if (err < 0) {
@@ -1371,8 +1254,7 @@ int usb_new_device(struct usb_device *udev)
                                        USB_DT_OTG, (void **) &desc) == 0) {
                        if (desc->bmAttributes & USB_OTG_HNP) {
                                unsigned                port1 = udev->portnum;
-                               struct usb_device       *root = udev->parent;
-                               
+
                                dev_info(&udev->dev,
                                        "Dual-Role OTG device on %sHNP port\n",
                                        (port1 == bus->otg_port)
@@ -1407,9 +1289,9 @@ int usb_new_device(struct usb_device *udev)
                 * (Includes HNP test device.)
                 */
                if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-                       static int __usb_suspend_device(struct usb_device *,
+                       static int __usb_port_suspend(struct usb_device *,
                                                int port1);
-                       err = __usb_suspend_device(udev, udev->bus->otg_port);
+                       err = __usb_port_suspend(udev, udev->bus->otg_port);
                        if (err < 0)
                                dev_dbg(&udev->dev, "HNP fail, %d\n", err);
                }
@@ -1418,34 +1300,15 @@ int usb_new_device(struct usb_device *udev)
        }
 #endif
 
-       /* put device-specific files into sysfs */
+       /* Register the device.  The device driver is responsible
+        * for adding the device files to usbfs and sysfs and for
+        * configuring the device.
+        */
        err = device_add (&udev->dev);
        if (err) {
                dev_err(&udev->dev, "can't device_add, error %d\n", err);
                goto fail;
        }
-       usb_create_sysfs_dev_files (udev);
-
-       usb_lock_device(udev);
-
-       /* choose and set the configuration. that registers the interfaces
-        * with the driver core, and lets usb device drivers bind to them.
-        */
-       c = choose_configuration(udev);
-       if (c >= 0) {
-               err = usb_set_configuration(udev, c);
-               if (err) {
-                       dev_err(&udev->dev, "can't set config #%d, error %d\n",
-                                       c, err);
-                       /* This need not be fatal.  The user can try to
-                        * set other configurations. */
-               }
-       }
-
-       /* USB device state == configured ... usable */
-       usb_notify_add_device(udev);
-
-       usb_unlock_device(udev);
 
        return 0;
 
@@ -1472,6 +1335,18 @@ static int hub_port_status(struct usb_hub *hub, int port1,
        return ret;
 }
 
+
+/* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+static unsigned hub_is_wusb(struct usb_hub *hub)
+{
+       struct usb_hcd *hcd;
+       if (hub->hdev->parent != NULL)  /* not a root hub? */
+               return 0;
+       hcd = container_of(hub->hdev->bus, struct usb_hcd, self);
+       return hcd->wireless;
+}
+
+
 #define PORT_RESET_TRIES       5
 #define SET_ADDRESS_TRIES      2
 #define GET_DESCRIPTOR_TRIES   2
@@ -1512,7 +1387,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                /* if we`ve finished resetting, then break out of the loop */
                if (!(portstatus & USB_PORT_STAT_RESET) &&
                    (portstatus & USB_PORT_STAT_ENABLE)) {
-                       if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+                       if (hub_is_wusb(hub))
+                               udev->speed = USB_SPEED_VARIABLE;
+                       else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
                                udev->speed = USB_SPEED_HIGH;
                        else if (portstatus & USB_PORT_STAT_LOW_SPEED)
                                udev->speed = USB_SPEED_LOW;
@@ -1607,6 +1484,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
        kick_khubd(hub);
 }
 
+#ifdef CONFIG_PM
 
 #ifdef CONFIG_USB_SUSPEND
 
@@ -1633,7 +1511,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
         * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
         * we don't explicitly enable it here.
         */
-       if (device_may_wakeup(&udev->dev)) {
+       if (udev->do_remote_wakeup) {
                status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
                                USB_DEVICE_REMOTE_WAKEUP, 0,
@@ -1659,7 +1537,8 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
                                USB_CTRL_SET_TIMEOUT);
        } else {
                /* device has up to 10 msec to fully suspend */
-               dev_dbg(&udev->dev, "usb suspend\n");
+               dev_dbg(&udev->dev, "usb %ssuspend\n",
+                               udev->auto_pm ? "auto-" : "");
                usb_set_device_state(udev, USB_STATE_SUSPENDED);
                msleep(10);
        }
@@ -1684,7 +1563,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
  * the root hub for their bus goes into global suspend ... so we don't
  * (falsely) update the device power state to say it suspended.
  */
-static int __usb_suspend_device (struct usb_device *udev, int port1)
+static int __usb_port_suspend (struct usb_device *udev, int port1)
 {
        int     status = 0;
 
@@ -1692,49 +1571,29 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
        if (port1 < 0)
                return port1;
 
-       if (udev->state == USB_STATE_SUSPENDED
-                       || udev->state == USB_STATE_NOTATTACHED) {
-               return 0;
-       }
-
-       /* all interfaces must already be suspended */
-       if (udev->actconfig) {
-               int     i;
-
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       struct usb_interface    *intf;
-
-                       intf = udev->actconfig->interface[i];
-                       if (is_active(intf)) {
-                               dev_dbg(&intf->dev, "nyet suspended\n");
-                               return -EBUSY;
-                       }
-               }
-       }
-
-       /* we only change a device's upstream USB link.
-        * root hubs have no upstream USB link.
+       /* we change the device's upstream USB link,
+        * but root hubs have no upstream USB link.
         */
        if (udev->parent)
                status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
                                udev);
-
-       if (status == 0)
-               udev->dev.power.power_state = PMSG_SUSPEND;
+       else {
+               dev_dbg(&udev->dev, "usb %ssuspend\n",
+                               udev->auto_pm ? "auto-" : "");
+               usb_set_device_state(udev, USB_STATE_SUSPENDED);
+       }
        return status;
 }
 
-#endif
-
 /*
- * usb_suspend_device - suspend a usb device
+ * usb_port_suspend - suspend a usb device's upstream port
  * @udev: device that's no longer in active use
  * Context: must be able to sleep; device not locked; pm locks held
  *
  * Suspends a USB device that isn't in active use, conserving power.
  * Devices may wake out of a suspend, if anything important happens,
  * using the remote wakeup mechanism.  They may also be taken out of
- * suspend by the host, using usb_resume_device().  It's also routine
+ * suspend by the host, using usb_port_resume().  It's also routine
  * to disconnect devices while they are suspended.
  *
  * This only affects the USB hardware for a device; its interfaces
@@ -1746,17 +1605,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_suspend_device(struct usb_device *udev)
+int usb_port_suspend(struct usb_device *udev)
 {
-#ifdef CONFIG_USB_SUSPEND
-       if (udev->state == USB_STATE_NOTATTACHED)
-               return -ENODEV;
-       return __usb_suspend_device(udev, udev->portnum);
-#else
-       /* NOTE:  udev->state unchanged, it's not lying ... */
-       udev->dev.power.power_state = PMSG_SUSPEND;
-       return 0;
-#endif
+       return __usb_port_suspend(udev, udev->portnum);
 }
 
 /*
@@ -1767,7 +1618,7 @@ int usb_suspend_device(struct usb_device *udev)
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
  */
-static int finish_device_resume(struct usb_device *udev)
+static int finish_port_resume(struct usb_device *udev)
 {
        int     status;
        u16     devstatus;
@@ -1783,7 +1634,6 @@ static int finish_device_resume(struct usb_device *udev)
        usb_set_device_state(udev, udev->actconfig
                        ? USB_STATE_CONFIGURED
                        : USB_STATE_ADDRESS);
-       udev->dev.power.power_state = PMSG_ON;
 
        /* 10.5.4.5 says be sure devices in the tree are still there.
         * For now let's assume the device didn't go crazy on resume,
@@ -1798,9 +1648,6 @@ static int finish_device_resume(struct usb_device *udev)
                        "gone after usb resume? status %d\n",
                        status);
        else if (udev->actconfig) {
-               unsigned        i;
-               int             (*resume)(struct device *);
-
                le16_to_cpus(&devstatus);
                if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
                                && udev->parent) {
@@ -1811,24 +1658,9 @@ static int finish_device_resume(struct usb_device *udev)
                                        USB_DEVICE_REMOTE_WAKEUP, 0,
                                        NULL, 0,
                                        USB_CTRL_SET_TIMEOUT);
-                       if (status) {
+                       if (status)
                                dev_dbg(&udev->dev, "disable remote "
                                        "wakeup, status %d\n", status);
-                               status = 0;
-                       }
-               }
-
-               /* resume interface drivers; if this is a hub, it
-                * may have a child resume event to deal with soon
-                */
-               resume = udev->dev.bus->resume;
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       struct device *dev =
-                                       &udev->actconfig->interface[i]->dev;
-
-                       down(&dev->sem);
-                       (void) resume(dev);
-                       up(&dev->sem);
                }
                status = 0;
 
@@ -1839,8 +1671,6 @@ static int finish_device_resume(struct usb_device *udev)
        return status;
 }
 
-#ifdef CONFIG_USB_SUSPEND
-
 static int
 hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 {
@@ -1848,6 +1678,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 
        // dev_dbg(hub->intfdev, "resume port %d\n", port1);
 
+       set_bit(port1, hub->busy_bits);
+
        /* see 7.1.7.7; affects power usage, but not budgeting */
        status = clear_port_feature(hub->hdev,
                        port1, USB_PORT_FEAT_SUSPEND);
@@ -1861,7 +1693,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 
                /* drive resume for at least 20 msec */
                if (udev)
-                       dev_dbg(&udev->dev, "RESUME\n");
+                       dev_dbg(&udev->dev, "usb %sresume\n",
+                                       udev->auto_pm ? "auto-" : "");
                msleep(25);
 
 #define LIVE_FLAGS     ( USB_PORT_STAT_POWER \
@@ -1891,19 +1724,21 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
                        /* TRSMRCY = 10 msec */
                        msleep(10);
                        if (udev)
-                               status = finish_device_resume(udev);
+                               status = finish_port_resume(udev);
                }
        }
        if (status < 0)
                hub_port_logical_disconnect(hub, port1);
 
+       clear_bit(port1, hub->busy_bits);
+       if (!hub->hdev->parent && !hub->busy_bits[0])
+               usb_enable_root_hub_irq(hub->hdev->bus);
+
        return status;
 }
 
-#endif
-
 /*
- * usb_resume_device - re-activate a suspended usb device
+ * usb_port_resume - re-activate a suspended usb device's upstream port
  * @udev: device to re-activate
  * Context: must be able to sleep; device not locked; pm locks held
  *
@@ -1915,36 +1750,24 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_resume_device(struct usb_device *udev)
+int usb_port_resume(struct usb_device *udev)
 {
        int     status;
 
-       if (udev->state == USB_STATE_NOTATTACHED)
-               return -ENODEV;
-
-       /* selective resume of one downstream hub-to-device port */
+       /* we change the device's upstream USB link,
+        * but root hubs have no upstream USB link.
+        */
        if (udev->parent) {
-#ifdef CONFIG_USB_SUSPEND
-               if (udev->state == USB_STATE_SUSPENDED) {
-                       // NOTE swsusp may bork us, device state being wrong...
-                       // NOTE this fails if parent is also suspended...
-                       status = hub_port_resume(hdev_to_hub(udev->parent),
-                                       udev->portnum, udev);
-               } else
-#endif
-                       status = 0;
-       } else
-               status = finish_device_resume(udev);
-       if (status < 0)
-               dev_dbg(&udev->dev, "can't resume, status %d\n",
-                       status);
-
-       /* rebind drivers that had no suspend() */
-       if (status == 0) {
-               usb_unlock_device(udev);
-               bus_rescan_devices(&usb_bus_type);
-               usb_lock_device(udev);
+               // NOTE this fails if parent is also suspended...
+               status = hub_port_resume(hdev_to_hub(udev->parent),
+                               udev->portnum, udev);
+       } else {
+               dev_dbg(&udev->dev, "usb %sresume\n",
+                               udev->auto_pm ? "auto-" : "");
+               status = finish_port_resume(udev);
        }
+       if (status < 0)
+               dev_dbg(&udev->dev, "can't resume, status %d\n", status);
        return status;
 }
 
@@ -1952,23 +1775,60 @@ static int remote_wakeup(struct usb_device *udev)
 {
        int     status = 0;
 
-#ifdef CONFIG_USB_SUSPEND
+       /* All this just to avoid sending a port-resume message
+        * to the parent hub! */
 
-       /* don't repeat RESUME sequence if this device
-        * was already woken up by some other task
-        */
        usb_lock_device(udev);
+       usb_pm_lock(udev);
        if (udev->state == USB_STATE_SUSPENDED) {
-               dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+               dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
                /* TRSMRCY = 10 msec */
                msleep(10);
-               status = finish_device_resume(udev);
+               status = finish_port_resume(udev);
+               if (status == 0)
+                       udev->dev.power.power_state.event = PM_EVENT_ON;
        }
+       usb_pm_unlock(udev);
+
+       if (status == 0)
+               usb_autoresume_device(udev, 0);
        usb_unlock_device(udev);
-#endif
        return status;
 }
 
+#else  /* CONFIG_USB_SUSPEND */
+
+/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
+
+int usb_port_suspend(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int
+finish_port_resume(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int
+hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+{
+       return 0;
+}
+
+int usb_port_resume(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int remote_wakeup(struct usb_device *udev)
+{
+       return 0;
+}
+
+#endif
+
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
        struct usb_hub          *hub = usb_get_intfdata (intf);
@@ -1980,13 +1840,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
                struct usb_device       *udev;
 
                udev = hdev->children [port1-1];
-               if (udev && (udev->dev.power.power_state.event
-                                       == PM_EVENT_ON
+               if (udev && msg.event == PM_EVENT_SUSPEND &&
 #ifdef CONFIG_USB_SUSPEND
-                               || udev->state != USB_STATE_SUSPENDED
+                               udev->state != USB_STATE_SUSPENDED
+#else
+                               udev->dev.power.power_state.event
+                                       == PM_EVENT_ON
 #endif
-                               )) {
-                       dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+                               ) {
+                       if (!hdev->auto_pm)
+                               dev_dbg(&intf->dev, "port %d nyet suspended\n",
+                                               port1);
                        return -EBUSY;
                }
        }
@@ -2035,66 +1899,22 @@ static int hub_resume(struct usb_interface *intf)
                }
        }
 
+       /* tell khubd to look for changes on this hub */
        hub_activate(hub);
-
-       /* REVISIT:  this recursion probably shouldn't exist.  Remove
-        * this code sometime, after retesting with different root and
-        * external hubs.
-        */
-#ifdef CONFIG_USB_SUSPEND
-       {
-       unsigned                port1;
-
-       for (port1 = 1; port1 <= hdev->maxchild; port1++) {
-               struct usb_device       *udev;
-               u16                     portstat, portchange;
-
-               udev = hdev->children [port1-1];
-               status = hub_port_status(hub, port1, &portstat, &portchange);
-               if (status == 0) {
-                       if (portchange & USB_PORT_STAT_C_SUSPEND) {
-                               clear_port_feature(hdev, port1,
-                                       USB_PORT_FEAT_C_SUSPEND);
-                               portchange &= ~USB_PORT_STAT_C_SUSPEND;
-                       }
-
-                       /* let khubd handle disconnects etc */
-                       if (portchange)
-                               continue;
-               }
-
-               if (!udev || status < 0)
-                       continue;
-               usb_lock_device(udev);
-               if (portstat & USB_PORT_STAT_SUSPEND)
-                       status = hub_port_resume(hub, port1, udev);
-               else {
-                       status = finish_device_resume(udev);
-                       if (status < 0) {
-                               dev_dbg(&intf->dev, "resume port %d --> %d\n",
-                                       port1, status);
-                               hub_port_logical_disconnect(hub, port1);
-                       }
-               }
-               usb_unlock_device(udev);
-       }
-       }
-#endif
        return 0;
 }
 
-void usb_suspend_root_hub(struct usb_device *hdev)
-{
-       struct usb_hub *hub = hdev_to_hub(hdev);
+#else  /* CONFIG_PM */
 
-       /* This also makes any led blinker stop retriggering.  We're called
-        * from irq, so the blinker might still be scheduled.  Caller promises
-        * that the root hub status URB will be canceled.
-        */
-       __hub_quiesce(hub);
-       mark_quiesced(to_usb_interface(hub->intfdev));
+static inline int remote_wakeup(struct usb_device *udev)
+{
+       return 0;
 }
 
+#define hub_suspend NULL
+#define hub_resume NULL
+#endif
+
 void usb_resume_root_hub(struct usb_device *hdev)
 {
        struct usb_hub *hub = hdev_to_hub(hdev);
@@ -2214,6 +2034,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        int                     i, j, retval;
        unsigned                delay = HUB_SHORT_RESET_TIME;
        enum usb_device_speed   oldspeed = udev->speed;
+       char                    *speed, *type;
 
        /* root hub ports have a slightly longer reset period
         * (from USB 2.0 spec, section 7.1.7.5)
@@ -2246,8 +2067,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
   
        /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
         * it's fixed size except for full speed devices.
+        * For Wireless USB devices, ep0 max packet is always 512 (tho
+        * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
         */
        switch (udev->speed) {
+       case USB_SPEED_VARIABLE:        /* fixed at 512 */
+               udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512);
+               break;
        case USB_SPEED_HIGH:            /* fixed at 64 */
                udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
                break;
@@ -2265,17 +2091,21 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                goto fail;
        }
  
+       type = "";
+       switch (udev->speed) {
+       case USB_SPEED_LOW:     speed = "low";  break;
+       case USB_SPEED_FULL:    speed = "full"; break;
+       case USB_SPEED_HIGH:    speed = "high"; break;
+       case USB_SPEED_VARIABLE:
+                               speed = "variable";
+                               type = "Wireless ";
+                               break;
+       default:                speed = "?";    break;
+       }
        dev_info (&udev->dev,
-                       "%s %s speed USB device using %s and address %d\n",
-                       (udev->config) ? "reset" : "new",
-                       ({ char *speed; switch (udev->speed) {
-                       case USB_SPEED_LOW:     speed = "low";  break;
-                       case USB_SPEED_FULL:    speed = "full"; break;
-                       case USB_SPEED_HIGH:    speed = "high"; break;
-                       default:                speed = "?";    break;
-                       }; speed;}),
-                       udev->bus->controller->driver->name,
-                       udev->devnum);
+                 "%s %s speed %sUSB device using %s and address %d\n",
+                 (udev->config) ? "reset" : "new", speed, type,
+                 udev->bus->controller->driver->name, udev->devnum);
 
        /* Set up TT records, if needed  */
        if (hdev->tt) {
@@ -2317,6 +2147,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                         * down tremendously by NAKing the unexpectedly
                         * early status stage.  Also, retry on all errors;
                         * some devices are flakey.
+                        * 255 is for WUSB devices, we actually need to use 512.
+                        * WUSB1.0[4.8.1].
                         */
                        for (j = 0; j < 3; ++j) {
                                buf->bMaxPacketSize0 = 0;
@@ -2326,7 +2158,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                                        buf, GET_DESCRIPTOR_BUFSIZE,
                                        (i ? USB_CTRL_GET_TIMEOUT : 1000));
                                switch (buf->bMaxPacketSize0) {
-                               case 8: case 16: case 32: case 64:
+                               case 8: case 16: case 32: case 64: case 255:
                                        if (buf->bDescriptorType ==
                                                        USB_DT_DEVICE) {
                                                r = 0;
@@ -2400,7 +2232,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        if (retval)
                goto fail;
 
-       i = udev->descriptor.bMaxPacketSize0;
+       i = udev->descriptor.bMaxPacketSize0 == 0xff?
+           512 : udev->descriptor.bMaxPacketSize0;
        if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
                if (udev->speed != USB_SPEED_FULL ||
                                !(i == 8 || i == 16 || i == 32 || i == 64)) {
@@ -2585,6 +2418,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                usb_set_device_state(udev, USB_STATE_POWERED);
                udev->speed = USB_SPEED_UNKNOWN;
                udev->bus_mA = hub->mA_per_port;
+               udev->level = hdev->level + 1;
 
                /* set the address */
                choose_address(udev);
@@ -2736,17 +2570,6 @@ static void hub_events(void)
                usb_get_intf(intf);
                spin_unlock_irq(&hub_event_lock);
 
-               /* Is this is a root hub wanting to reactivate the downstream
-                * ports?  If so, be sure the interface resumes even if its
-                * stub "device" node was never suspended.
-                */
-               if (i) {
-                       dpm_runtime_resume(&hdev->dev);
-                       dpm_runtime_resume(&intf->dev);
-                       usb_put_intf(intf);
-                       continue;
-               }
-
                /* Lock the device, then check to see if we were
                 * disconnected while waiting for the lock to succeed. */
                if (locktree(hdev) < 0) {
@@ -2763,6 +2586,13 @@ static void hub_events(void)
                        goto loop;
                }
 
+               /* Is this is a root hub wanting to reactivate the downstream
+                * ports?  If so, be sure the interface resumes even if its
+                * stub "device" node was never suspended.
+                */
+               if (i)
+                       usb_autoresume_device(hdev, 0);
+
                /* If this is an inactive or suspended hub, do nothing */
                if (hub->quiescing)
                        goto loop;
@@ -2900,7 +2730,7 @@ static void hub_events(void)
 
                /* If this is a root hub, tell the HCD it's okay to
                 * re-enable port-change interrupts now. */
-               if (!hdev->parent)
+               if (!hdev->parent && !hub->busy_bits[0])
                        usb_enable_root_hub_irq(hdev->bus);
 
 loop:
@@ -3075,6 +2905,9 @@ int usb_reset_device(struct usb_device *udev)
                        break;
        }
        clear_bit(port1, parent_hub->busy_bits);
+       if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+               usb_enable_root_hub_irq(parent_hdev->bus);
+
        if (ret < 0)
                goto re_enumerate;
  
@@ -3128,6 +2961,7 @@ re_enumerate:
        hub_port_logical_disconnect(parent_hub, port1);
        return -ENODEV;
 }
+EXPORT_SYMBOL(usb_reset_device);
 
 /**
  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
@@ -3163,6 +2997,9 @@ int usb_reset_composite_device(struct usb_device *udev,
                return -EINVAL;
        }
 
+       /* Prevent autosuspend during the reset */
+       usb_autoresume_device(udev, 1);
+
        if (iface && iface->condition != USB_INTERFACE_BINDING)
                iface = NULL;
 
@@ -3204,5 +3041,7 @@ int usb_reset_composite_device(struct usb_device *udev,
                }
        }
 
+       usb_autosuspend_device(udev, 1);
        return ret;
 }
+EXPORT_SYMBOL(usb_reset_composite_device);
index 29d5f45a8456369f39dd1ed79d8853b40a5cefa7..0f8e82a4d48067da7d547344e41e30b28c123b55 100644 (file)
@@ -212,7 +212,8 @@ struct usb_hub {
        unsigned long           event_bits[1];  /* status change bitmask */
        unsigned long           change_bits[1]; /* ports with logical connect
                                                        status change */
-       unsigned long           busy_bits[1];   /* ports being reset */
+       unsigned long           busy_bits[1];   /* ports being reset or
+                                                       resumed */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif
index 3182c2224ba24f79c428242e431eaff03bbeba51..7c77c2d8d30073d3fcba0eda4c908f07f637b3e1 100644 (file)
@@ -44,7 +44,7 @@
 #include "hcd.h"
 
 static struct super_operations usbfs_ops;
-static struct file_operations default_file_operations;
+static const struct file_operations default_file_operations;
 static struct vfsmount *usbfs_mount;
 static int usbfs_mount_count;  /* = 0 */
 static int ignore_mount = 0;
@@ -249,7 +249,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
@@ -264,7 +263,7 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
                        inode->i_fop = &simple_dir_operations;
 
                        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        break;
                }
        }
@@ -296,7 +295,7 @@ static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
        res = usbfs_mknod (dir, dentry, mode, 0);
        if (!res)
-               dir->i_nlink++;
+               inc_nlink(dir);
        return res;
 }
 
@@ -333,7 +332,7 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
        mutex_lock(&inode->i_mutex);
-       dentry->d_inode->i_nlink--;
+       drop_nlink(dentry->d_inode);
        dput(dentry);
        mutex_unlock(&inode->i_mutex);
        d_delete(dentry);
@@ -348,10 +347,11 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
        mutex_lock(&inode->i_mutex);
        dentry_unhash(dentry);
        if (usbfs_empty(dentry)) {
-               dentry->d_inode->i_nlink -= 2;
+               drop_nlink(dentry->d_inode);
+               drop_nlink(dentry->d_inode);
                dput(dentry);
                inode->i_flags |= S_DEAD;
-               dir->i_nlink--;
+               drop_nlink(dir);
                error = 0;
        }
        mutex_unlock(&inode->i_mutex);
@@ -402,13 +402,13 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
 
 static int default_open (struct inode *inode, struct file *file)
 {
-       if (inode->u.generic_ip)
-               file->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               file->private_data = inode->i_private;
 
        return 0;
 }
 
-static struct file_operations default_file_operations = {
+static const struct file_operations default_file_operations = {
        .read =         default_read_file,
        .write =        default_write_file,
        .open =         default_open,
@@ -495,7 +495,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
 
 static struct dentry *fs_create_file (const char *name, mode_t mode,
                                      struct dentry *parent, void *data,
-                                     struct file_operations *fops,
+                                     const struct file_operations *fops,
                                      uid_t uid, gid_t gid)
 {
        struct dentry *dentry;
@@ -509,7 +509,7 @@ static struct dentry *fs_create_file (const char *name, mode_t mode,
        } else {
                if (dentry->d_inode) {
                        if (data)
-                               dentry->d_inode->u.generic_ip = data;
+                               dentry->d_inode->i_private = data;
                        if (fops)
                                dentry->d_inode->i_fop = fops;
                        dentry->d_inode->i_uid = uid;
index 4cc8d3e67db795f54f5f8dcc1d5a393c391796eb..85b1cd18336f03c63b875c2431f87942eb43c007 100644 (file)
@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
 }
 
 
-static void timeout_kill(unsigned long data)
-{
-       struct urb      *urb = (struct urb *) data;
-
-       usb_unlink_urb(urb);
-}
-
-// Starts urb and waits for completion or timeout
-// note that this call is NOT interruptible, while
-// many device driver i/o requests should be interruptible
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+/*
+ * Starts urb and waits for completion or timeout. Note that this call
+ * is NOT interruptible. Many device driver i/o requests should be
+ * interruptible and therefore these drivers should implement their
+ * own interruptible routines.
+ */
+static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
 { 
-       struct completion       done;
-       struct timer_list       timer;
-       int                     status;
+       struct completion done;
+       unsigned long expire;
+       int status;
 
        init_completion(&done);         
        urb->context = &done;
        urb->actual_length = 0;
        status = usb_submit_urb(urb, GFP_NOIO);
-
-       if (status == 0) {
-               if (timeout > 0) {
-                       init_timer(&timer);
-                       timer.expires = jiffies + msecs_to_jiffies(timeout);
-                       timer.data = (unsigned long)urb;
-                       timer.function = timeout_kill;
-                       /* grr.  timeout _should_ include submit delays. */
-                       add_timer(&timer);
-               }
-               wait_for_completion(&done);
+       if (unlikely(status))
+               goto out;
+
+       expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+       if (!wait_for_completion_timeout(&done, expire)) {
+
+               dev_dbg(&urb->dev->dev,
+                       "%s timed out on ep%d%s len=%d/%d\n",
+                       current->comm,
+                       usb_pipeendpoint(urb->pipe),
+                       usb_pipein(urb->pipe) ? "in" : "out",
+                       urb->actual_length,
+                       urb->transfer_buffer_length);
+
+               usb_kill_urb(urb);
+               status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
+       } else
                status = urb->status;
-               /* note:  HCDs return ETIMEDOUT for other reasons too */
-               if (status == -ECONNRESET) {
-                       dev_dbg(&urb->dev->dev,
-                               "%s timed out on ep%d%s len=%d/%d\n",
-                               current->comm,
-                               usb_pipeendpoint(urb->pipe),
-                               usb_pipein(urb->pipe) ? "in" : "out",
-                               urb->actual_length,
-                               urb->transfer_buffer_length
-                               );
-                       if (urb->actual_length > 0)
-                               status = 0;
-                       else
-                               status = -ETIMEDOUT;
-               }
-               if (timeout > 0)
-                       del_timer_sync(&timer);
-       }
-
+out:
        if (actual_length)
                *actual_length = urb->actual_length;
+
        usb_free_urb(urb);
        return status;
 }
@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io)
 
 static void sg_complete (struct urb *urb, struct pt_regs *regs)
 {
-       struct usb_sg_request   *io = (struct usb_sg_request *) urb->context;
+       struct usb_sg_request   *io = urb->context;
 
        spin_lock (&io->lock);
 
@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
                ep = dev->ep_in[epnum];
                dev->ep_in[epnum] = NULL;
        }
-       if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
-               dev->bus->op->disable(dev, ep);
+       if (ep && dev->bus)
+               usb_hcd_endpoint_disable(dev, ep);
 }
 
 /**
@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        if (cp && configuration == 0)
                dev_warn(&dev->dev, "config 0 descriptor??\n");
 
-       if (dev->state == USB_STATE_SUSPENDED)
-               return -EHOSTUNREACH;
-
        /* Allocate memory for new interfaces before doing anything else,
         * so that if we run out then nothing will have changed. */
        n = nintf = 0;
@@ -1418,6 +1400,11 @@ free_interfaces:
                                        configuration, -i);
        }
 
+       /* Wake up the device so we can send it the Set-Config request */
+       ret = usb_autoresume_device(dev, 1);
+       if (ret)
+               goto free_interfaces;
+
        /* if it's already configured, clear out old state first.
         * getting rid of old interfaces means unbinding their drivers.
         */
@@ -1437,6 +1424,7 @@ free_interfaces:
        dev->actconfig = cp;
        if (!cp) {
                usb_set_device_state(dev, USB_STATE_ADDRESS);
+               usb_autosuspend_device(dev, 1);
                goto free_interfaces;
        }
        usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1505,8 +1493,68 @@ free_interfaces:
                usb_create_sysfs_intf_files (intf);
        }
 
+       usb_autosuspend_device(dev, 1);
+       return 0;
+}
+
+struct set_config_request {
+       struct usb_device       *udev;
+       int                     config;
+       struct work_struct      work;
+};
+
+/* Worker routine for usb_driver_set_configuration() */
+static void driver_set_config_work(void *_req)
+{
+       struct set_config_request *req = _req;
+
+       usb_lock_device(req->udev);
+       usb_set_configuration(req->udev, req->config);
+       usb_unlock_device(req->udev);
+       usb_put_dev(req->udev);
+       kfree(req);
+}
+
+/**
+ * usb_driver_set_configuration - Provide a way for drivers to change device configurations
+ * @udev: the device whose configuration is being updated
+ * @config: the configuration being chosen.
+ * Context: In process context, must be able to sleep
+ *
+ * Device interface drivers are not allowed to change device configurations.
+ * This is because changing configurations will destroy the interface the
+ * driver is bound to and create new ones; it would be like a floppy-disk
+ * driver telling the computer to replace the floppy-disk drive with a
+ * tape drive!
+ *
+ * Still, in certain specialized circumstances the need may arise.  This
+ * routine gets around the normal restrictions by using a work thread to
+ * submit the change-config request.
+ *
+ * Returns 0 if the request was succesfully queued, error code otherwise.
+ * The caller has no way to know whether the queued request will eventually
+ * succeed.
+ */
+int usb_driver_set_configuration(struct usb_device *udev, int config)
+{
+       struct set_config_request *req;
+
+       req = kmalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+       req->udev = udev;
+       req->config = config;
+       INIT_WORK(&req->work, driver_set_config_work, req);
+
+       usb_get_dev(udev);
+       if (!schedule_work(&req->work)) {
+               usb_put_dev(udev);
+               kfree(req);
+               return -EINVAL;
+       }
        return 0;
 }
+EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
 
 // synchronous request completion model
 EXPORT_SYMBOL(usb_control_msg);
index b042676af0a5b11b70b1fa9e422aba2de4f2a551..6b36897ca151998ab28f07c12f0e9baef9e372fe 100644 (file)
@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev)
 
 void usb_notify_remove_device(struct usb_device *udev)
 {
+       /* Protect against simultaneous usbfs open */
+       mutex_lock(&usbfs_mutex);
        blocking_notifier_call_chain(&usb_notifier_list,
                        USB_DEVICE_REMOVE, udev);
+       mutex_unlock(&usbfs_mutex);
 }
 
 void usb_notify_add_bus(struct usb_bus *ubus)
index dec973affb0f5b2639d9bbaeb237726c0bbd9d56..55d8f575206d6b1dcbfb0338e48a79b735a7ef9d 100644 (file)
@@ -60,7 +60,7 @@ static ssize_t
 set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
-       struct usb_device       *udev = udev = to_usb_device (dev);
+       struct usb_device       *udev = to_usb_device (dev);
        int                     config, value;
 
        if (sscanf (buf, "%u", &config) != 1 || config > 255)
@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n")
 
 static struct attribute *dev_attrs[] = {
        /* current configuration's attributes */
+       &dev_attr_configuration.attr,
        &dev_attr_bNumInterfaces.attr,
        &dev_attr_bConfigurationValue.attr,
        &dev_attr_bmAttributes.attr,
@@ -209,20 +210,40 @@ static struct attribute_group dev_attr_grp = {
        .attrs = dev_attrs,
 };
 
-void usb_create_sysfs_dev_files (struct usb_device *udev)
+int usb_create_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
+       int retval;
 
-       sysfs_create_group(&dev->kobj, &dev_attr_grp);
+       retval = sysfs_create_group(&dev->kobj, &dev_attr_grp);
+       if (retval)
+               return retval;
 
-       if (udev->manufacturer)
-               device_create_file (dev, &dev_attr_manufacturer);
-       if (udev->product)
-               device_create_file (dev, &dev_attr_product);
-       if (udev->serial)
-               device_create_file (dev, &dev_attr_serial);
-       device_create_file (dev, &dev_attr_configuration);
-       usb_create_ep_files(dev, &udev->ep0, udev);
+       if (udev->manufacturer) {
+               retval = device_create_file (dev, &dev_attr_manufacturer);
+               if (retval)
+                       goto error;
+       }
+       if (udev->product) {
+               retval = device_create_file (dev, &dev_attr_product);
+               if (retval)
+                       goto error;
+       }
+       if (udev->serial) {
+               retval = device_create_file (dev, &dev_attr_serial);
+               if (retval)
+                       goto error;
+       }
+       retval = usb_create_ep_files(dev, &udev->ep0, udev);
+       if (retval)
+               goto error;
+       return 0;
+error:
+       usb_remove_ep_files(&udev->ep0);
+       device_remove_file(dev, &dev_attr_manufacturer);
+       device_remove_file(dev, &dev_attr_product);
+       device_remove_file(dev, &dev_attr_serial);
+       return retval;
 }
 
 void usb_remove_sysfs_dev_files (struct usb_device *udev)
@@ -238,7 +259,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
                device_remove_file(dev, &dev_attr_product);
        if (udev->serial)
                device_remove_file(dev, &dev_attr_serial);
-       device_remove_file (dev, &dev_attr_configuration);
 }
 
 /* Interface fields */
@@ -340,18 +360,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
                usb_remove_ep_files(&iface_desc->endpoint[i]);
 }
 
-void usb_create_sysfs_intf_files (struct usb_interface *intf)
+int usb_create_sysfs_intf_files(struct usb_interface *intf)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_host_interface *alt = intf->cur_altsetting;
+       int retval;
 
-       sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+       retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+       if (retval)
+               goto error;
 
        if (alt->string == NULL)
                alt->string = usb_cache_string(udev, alt->desc.iInterface);
        if (alt->string)
-               device_create_file(&intf->dev, &dev_attr_interface);
+               retval = device_create_file(&intf->dev, &dev_attr_interface);
        usb_create_intf_ep_files(intf, udev);
+       return 0;
+error:
+       if (alt->string)
+               device_remove_file(&intf->dev, &dev_attr_interface);
+       sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+       usb_remove_intf_ep_files(intf);
+       return retval;
 }
 
 void usb_remove_sysfs_intf_files (struct usb_interface *intf)
index 9864988377c74c11c052336a2065be1bdf8c54c7..9801d08edacf8db26056175116d28df45af985ed 100644 (file)
@@ -57,7 +57,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
 {
        struct urb *urb;
 
-       urb = (struct urb *)kmalloc(sizeof(struct urb) + 
+       urb = kmalloc(sizeof(struct urb) +
                iso_packets * sizeof(struct usb_iso_packet_descriptor),
                mem_flags);
        if (!urb) {
@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
        int                     pipe, temp, max;
        struct usb_device       *dev;
-       struct usb_operations   *op;
        int                     is_out;
 
        if (!urb || urb->hcpriv || !urb->complete)
@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
        if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
                        || dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
-       if (!(op = dev->bus->op) || !op->submit_urb)
-               return -ENODEV;
 
        urb->status = -EINPROGRESS;
        urb->actual_length = 0;
@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
                urb->interval = temp;
        }
 
-       return op->submit_urb (urb, mem_flags);
+       return usb_hcd_submit_urb (urb, mem_flags);
 }
 
 /*-------------------------------------------------------------------*/
@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb)
 {
        if (!urb)
                return -EINVAL;
-       if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
+       if (!(urb->dev && urb->dev->bus))
                return -ENODEV;
-       return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
+       return usb_hcd_unlink_urb(urb, -ECONNRESET);
 }
 
 /**
@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb)
 void usb_kill_urb(struct urb *urb)
 {
        might_sleep();
-       if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
+       if (!(urb && urb->dev && urb->dev->bus))
                return;
        spin_lock_irq(&urb->lock);
        ++urb->reject;
        spin_unlock_irq(&urb->lock);
 
-       urb->dev->bus->op->unlink_urb(urb, -ENOENT);
+       usb_hcd_unlink_urb(urb, -ENOENT);
        wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 
        spin_lock_irq(&urb->lock);
index 184c24660a4c572b89fd4175d24314dd1fcb8f6c..e4df9edf1bc02bcfaa65f96f74730cb37f1e65bd 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include <asm/io.h>
 #include <asm/scatterlist.h>
@@ -47,6 +48,8 @@ const char *usbcore_name = "usbcore";
 
 static int nousb;      /* Disable USB when built into kernel image */
 
+struct workqueue_struct *ksuspend_usb_wq;      /* For autosuspend */
+
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -67,7 +70,8 @@ static int nousb;     /* Disable USB when built into kernel image */
  * Don't call this function unless you are bound to one of the interfaces
  * on this device or you have locked the device!
  */
-struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
+struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
+                                     unsigned ifnum)
 {
        struct usb_host_config *config = dev->actconfig;
        int i;
@@ -100,8 +104,8 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
  * Don't call this function unless you are bound to the intf interface
  * or you have locked the device!
  */
-struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
-               unsigned int altnum)
+struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf,
+                                                   unsigned int altnum)
 {
        int i;
 
@@ -112,87 +116,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
        return NULL;
 }
 
-/**
- * usb_driver_claim_interface - bind a driver to an interface
- * @driver: the driver to be bound
- * @iface: the interface to which it will be bound; must be in the
- *     usb device's active configuration
- * @priv: driver data associated with that interface
- *
- * This is used by usb device drivers that need to claim more than one
- * interface on a device when probing (audio and acm are current examples).
- * No device driver should directly modify internal usb_interface or
- * usb_device structure members.
- *
- * Few drivers should need to use this routine, since the most natural
- * way to bind to an interface is to return the private data from
- * the driver's probe() method.
- *
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver probe() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
- */
-int usb_driver_claim_interface(struct usb_driver *driver,
-                               struct usb_interface *iface, void* priv)
-{
-       struct device *dev = &iface->dev;
-
-       if (dev->driver)
-               return -EBUSY;
-
-       dev->driver = &driver->driver;
-       usb_set_intfdata(iface, priv);
-       iface->condition = USB_INTERFACE_BOUND;
-       mark_active(iface);
-
-       /* if interface was already added, bind now; else let
-        * the future device_add() bind it, bypassing probe()
-        */
-       if (device_is_registered(dev))
-               device_bind_driver(dev);
-
-       return 0;
-}
-
-/**
- * usb_driver_release_interface - unbind a driver from an interface
- * @driver: the driver to be unbound
- * @iface: the interface from which it will be unbound
- *
- * This can be used by drivers to release an interface without waiting
- * for their disconnect() methods to be called.  In typical cases this
- * also causes the driver disconnect() method to be called.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver disconnect() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
- */
-void usb_driver_release_interface(struct usb_driver *driver,
-                                       struct usb_interface *iface)
-{
-       struct device *dev = &iface->dev;
-
-       /* this should never happen, don't release something that's not ours */
-       if (!dev->driver || dev->driver != &driver->driver)
-               return;
-
-       /* don't release from within disconnect() */
-       if (iface->condition != USB_INTERFACE_BOUND)
-               return;
-
-       /* don't release if the interface hasn't been added yet */
-       if (device_is_registered(dev)) {
-               iface->condition = USB_INTERFACE_UNBINDING;
-               device_release_driver(dev);
-       }
-
-       dev->driver = NULL;
-       usb_set_intfdata(iface, NULL);
-       iface->condition = USB_INTERFACE_UNBOUND;
-       mark_quiesced(iface);
-}
-
 struct find_interface_arg {
        int minor;
        struct usb_interface *interface;
@@ -204,7 +127,7 @@ static int __find_interface(struct device * dev, void * data)
        struct usb_interface *intf;
 
        /* can't look at usb devices, only interfaces */
-       if (dev->driver == &usb_generic_driver)
+       if (is_usb_device(dev))
                return 0;
 
        intf = to_usb_interface(dev);
@@ -227,147 +150,82 @@ static int __find_interface(struct device * dev, void * data)
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
        struct find_interface_arg argb;
+       int retval;
 
        argb.minor = minor;
        argb.interface = NULL;
-       driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
+       /* eat the error, it will be in argb.interface */
+       retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
+                                       __find_interface);
        return argb.interface;
 }
 
-#ifdef CONFIG_HOTPLUG
-
-/*
- * This sends an uevent to userspace, typically helping to load driver
- * or other modules, configure the device, and more.  Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+/**
+ * usb_release_dev - free a usb device structure when all users of it are finished.
+ * @dev: device that's been disconnected
  *
- * We're called either from khubd (the typical case) or from root hub
- * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
- * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
- * device (and this configuration!) are still present.
+ * Will be called only by the device core when all users of this usb device are
+ * done.
  */
-static int usb_uevent(struct device *dev, char **envp, int num_envp,
-                     char *buffer, int buffer_size)
+static void usb_release_dev(struct device *dev)
 {
-       struct usb_interface *intf;
-       struct usb_device *usb_dev;
-       struct usb_host_interface *alt;
-       int i = 0;
-       int length = 0;
-
-       if (!dev)
-               return -ENODEV;
-
-       /* driver is often null here; dev_dbg() would oops */
-       pr_debug ("usb %s: uevent\n", dev->bus_id);
-
-       /* Must check driver_data here, as on remove driver is always NULL */
-       if ((dev->driver == &usb_generic_driver) || 
-           (dev->driver_data == &usb_generic_driver_data))
-               return 0;
-
-       intf = to_usb_interface(dev);
-       usb_dev = interface_to_usbdev (intf);
-       alt = intf->cur_altsetting;
+       struct usb_device *udev;
 
-       if (usb_dev->devnum < 0) {
-               pr_debug ("usb %s: already deleted?\n", dev->bus_id);
-               return -ENODEV;
-       }
-       if (!usb_dev->bus) {
-               pr_debug ("usb %s: bus removed?\n", dev->bus_id);
-               return -ENODEV;
-       }
+       udev = to_usb_device(dev);
 
-#ifdef CONFIG_USB_DEVICEFS
-       /* If this is available, userspace programs can directly read
-        * all the device descriptors we don't tell them about.  Or
-        * even act as usermode drivers.
-        *
-        * FIXME reduce hardwired intelligence here
-        */
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "DEVICE=/proc/bus/usb/%03d/%03d",
-                          usb_dev->bus->busnum, usb_dev->devnum))
-               return -ENOMEM;
+#ifdef CONFIG_USB_SUSPEND
+       cancel_delayed_work(&udev->autosuspend);
+       flush_workqueue(ksuspend_usb_wq);
 #endif
+       usb_destroy_configuration(udev);
+       usb_put_hcd(bus_to_hcd(udev->bus));
+       kfree(udev->product);
+       kfree(udev->manufacturer);
+       kfree(udev->serial);
+       kfree(udev);
+}
 
-       /* per-device configurations are common */
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "PRODUCT=%x/%x/%x",
-                          le16_to_cpu(usb_dev->descriptor.idVendor),
-                          le16_to_cpu(usb_dev->descriptor.idProduct),
-                          le16_to_cpu(usb_dev->descriptor.bcdDevice)))
-               return -ENOMEM;
+#ifdef CONFIG_PM
 
-       /* class-based driver binding models */
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "TYPE=%d/%d/%d",
-                          usb_dev->descriptor.bDeviceClass,
-                          usb_dev->descriptor.bDeviceSubClass,
-                          usb_dev->descriptor.bDeviceProtocol))
+static int ksuspend_usb_init(void)
+{
+       ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
+       if (!ksuspend_usb_wq)
                return -ENOMEM;
+       return 0;
+}
 
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "INTERFACE=%d/%d/%d",
-                          alt->desc.bInterfaceClass,
-                          alt->desc.bInterfaceSubClass,
-                          alt->desc.bInterfaceProtocol))
-               return -ENOMEM;
+static void ksuspend_usb_cleanup(void)
+{
+       destroy_workqueue(ksuspend_usb_wq);
+}
 
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-                          le16_to_cpu(usb_dev->descriptor.idVendor),
-                          le16_to_cpu(usb_dev->descriptor.idProduct),
-                          le16_to_cpu(usb_dev->descriptor.bcdDevice),
-                          usb_dev->descriptor.bDeviceClass,
-                          usb_dev->descriptor.bDeviceSubClass,
-                          usb_dev->descriptor.bDeviceProtocol,
-                          alt->desc.bInterfaceClass,
-                          alt->desc.bInterfaceSubClass,
-                          alt->desc.bInterfaceProtocol))
-               return -ENOMEM;
+#else
 
-       envp[i] = NULL;
+#define ksuspend_usb_init()    0
+#define ksuspend_usb_cleanup() do {} while (0)
 
-       return 0;
-}
+#endif
 
-#else
+#ifdef CONFIG_USB_SUSPEND
 
-static int usb_uevent(struct device *dev, char **envp,
-                       int num_envp, char *buffer, int buffer_size)
+/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+static void usb_autosuspend_work(void *_udev)
 {
-       return -ENODEV;
-}
+       struct usb_device       *udev = _udev;
 
-#endif /* CONFIG_HOTPLUG */
+       usb_pm_lock(udev);
+       udev->auto_pm = 1;
+       usb_suspend_both(udev, PMSG_SUSPEND);
+       usb_pm_unlock(udev);
+}
 
-/**
- * usb_release_dev - free a usb device structure when all users of it are finished.
- * @dev: device that's been disconnected
- *
- * Will be called only by the device core when all users of this usb device are
- * done.
- */
-static void usb_release_dev(struct device *dev)
-{
-       struct usb_device *udev;
+#else
 
-       udev = to_usb_device(dev);
+static void usb_autosuspend_work(void *_udev)
+{}
 
-       usb_destroy_configuration(udev);
-       usb_bus_put(udev->bus);
-       kfree(udev->product);
-       kfree(udev->manufacturer);
-       kfree(udev->serial);
-       kfree(udev);
-}
+#endif
 
 /**
  * usb_alloc_dev - usb device constructor (usbcore-internal)
@@ -390,8 +248,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        if (!dev)
                return NULL;
 
-       bus = usb_bus_get(bus);
-       if (!bus) {
+       if (!usb_get_hcd(bus_to_hcd(bus))) {
                kfree(dev);
                return NULL;
        }
@@ -399,11 +256,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        device_initialize(&dev->dev);
        dev->dev.bus = &usb_bus_type;
        dev->dev.dma_mask = bus->controller->dma_mask;
-       dev->dev.driver_data = &usb_generic_driver_data;
-       dev->dev.driver = &usb_generic_driver;
        dev->dev.release = usb_release_dev;
        dev->state = USB_STATE_ATTACHED;
 
+       /* This magic assignment distinguishes devices from interfaces */
+       dev->dev.platform_data = &usb_generic_driver;
+
        INIT_LIST_HEAD(&dev->ep0.urb_list);
        dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
        dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
@@ -444,6 +302,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        dev->parent = parent;
        INIT_LIST_HEAD(&dev->filelist);
 
+#ifdef CONFIG_PM
+       mutex_init(&dev->pm_mutex);
+       INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev);
+#endif
        return dev;
 }
 
@@ -549,7 +411,7 @@ void usb_put_intf(struct usb_interface *intf)
  * case the driver already owns the device lock.)
  */
 int usb_lock_device_for_reset(struct usb_device *udev,
-               struct usb_interface *iface)
+                             const struct usb_interface *iface)
 {
        unsigned long jiffies_expire = jiffies + HZ;
 
@@ -672,7 +534,139 @@ exit:
  */
 int usb_get_current_frame_number(struct usb_device *dev)
 {
-       return dev->bus->op->get_frame_number (dev);
+       return usb_hcd_get_frame_number (dev);
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
 }
 
 /*-------------------------------------------------------------------*/
@@ -737,9 +731,9 @@ void *usb_buffer_alloc (
        dma_addr_t *dma
 )
 {
-       if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc)
+       if (!dev || !dev->bus)
                return NULL;
-       return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma);
+       return hcd_buffer_alloc (dev->bus, size, mem_flags, dma);
 }
 
 /**
@@ -760,9 +754,11 @@ void usb_buffer_free (
        dma_addr_t dma
 )
 {
-       if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free)
-               return;
-       dev->bus->op->buffer_free (dev->bus, size, addr, dma);
+       if (!dev || !dev->bus)
+               return;
+       if (!addr)
+               return;
+       hcd_buffer_free (dev->bus, size, addr, dma);
 }
 
 /**
@@ -911,8 +907,8 @@ void usb_buffer_unmap (struct urb *urb)
  *
  * Reverse the effect of this call with usb_buffer_unmap_sg().
  */
-int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int nents)
+int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+                     struct scatterlist *sg, int nents)
 {
        struct usb_bus          *bus;
        struct device           *controller;
@@ -946,8 +942,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
  * Use this when you are re-using a scatterlist's data buffers for
  * another USB request.
  */
-void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents)
+void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+                          struct scatterlist *sg, int n_hw_ents)
 {
        struct usb_bus          *bus;
        struct device           *controller;
@@ -972,8 +968,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
  *
  * Reverses the effect of usb_buffer_map_sg().
  */
-void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents)
+void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+                        struct scatterlist *sg, int n_hw_ents)
 {
        struct usb_bus          *bus;
        struct device           *controller;
@@ -988,116 +984,6 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
                        usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 
-static int verify_suspended(struct device *dev, void *unused)
-{
-       if (dev->driver == NULL)
-               return 0;
-       return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
-}
-
-static int usb_generic_suspend(struct device *dev, pm_message_t message)
-{
-       struct usb_interface    *intf;
-       struct usb_driver       *driver;
-       int                     status;
-
-       /* USB devices enter SUSPEND state through their hubs, but can be
-        * marked for FREEZE as soon as their children are already idled.
-        * But those semantics are useless, so we equate the two (sigh).
-        */
-       if (dev->driver == &usb_generic_driver) {
-               if (dev->power.power_state.event == message.event)
-                       return 0;
-               /* we need to rule out bogus requests through sysfs */
-               status = device_for_each_child(dev, NULL, verify_suspended);
-               if (status)
-                       return status;
-               return usb_suspend_device (to_usb_device(dev));
-       }
-
-       if ((dev->driver == NULL) ||
-           (dev->driver_data == &usb_generic_driver_data))
-               return 0;
-
-       intf = to_usb_interface(dev);
-       driver = to_usb_driver(dev->driver);
-
-       /* with no hardware, USB interfaces only use FREEZE and ON states */
-       if (!is_active(intf))
-               return 0;
-
-       if (driver->suspend && driver->resume) {
-               status = driver->suspend(intf, message);
-               if (status)
-                       dev_err(dev, "%s error %d\n", "suspend", status);
-               else
-                       mark_quiesced(intf);
-       } else {
-               // FIXME else if there's no suspend method, disconnect...
-               dev_warn(dev, "no suspend for driver %s?\n", driver->name);
-               mark_quiesced(intf);
-               status = 0;
-       }
-       return status;
-}
-
-static int usb_generic_resume(struct device *dev)
-{
-       struct usb_interface    *intf;
-       struct usb_driver       *driver;
-       struct usb_device       *udev;
-       int                     status;
-
-       if (dev->power.power_state.event == PM_EVENT_ON)
-               return 0;
-
-       /* mark things as "on" immediately, no matter what errors crop up */
-       dev->power.power_state.event = PM_EVENT_ON;
-
-       /* devices resume through their hubs */
-       if (dev->driver == &usb_generic_driver) {
-               udev = to_usb_device(dev);
-               if (udev->state == USB_STATE_NOTATTACHED)
-                       return 0;
-               return usb_resume_device (to_usb_device(dev));
-       }
-
-       if ((dev->driver == NULL) ||
-           (dev->driver_data == &usb_generic_driver_data)) {
-               dev->power.power_state.event = PM_EVENT_FREEZE;
-               return 0;
-       }
-
-       intf = to_usb_interface(dev);
-       driver = to_usb_driver(dev->driver);
-
-       udev = interface_to_usbdev(intf);
-       if (udev->state == USB_STATE_NOTATTACHED)
-               return 0;
-
-       /* if driver was suspended, it has a resume method;
-        * however, sysfs can wrongly mark things as suspended
-        * (on the "no suspend method" FIXME path above)
-        */
-       if (driver->resume) {
-               status = driver->resume(intf);
-               if (status) {
-                       dev_err(dev, "%s error %d\n", "resume", status);
-                       mark_quiesced(intf);
-               }
-       } else
-               dev_warn(dev, "no resume for driver %s?\n", driver->name);
-       return 0;
-}
-
-struct bus_type usb_bus_type = {
-       .name =         "usb",
-       .match =        usb_device_match,
-       .uevent =       usb_uevent,
-       .suspend =      usb_generic_suspend,
-       .resume =       usb_generic_resume,
-};
-
 /* format to disable USB on kernel command line is: nousb */
 __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
 
@@ -1120,9 +1006,12 @@ static int __init usb_init(void)
                return 0;
        }
 
+       retval = ksuspend_usb_init();
+       if (retval)
+               goto out;
        retval = bus_register(&usb_bus_type);
        if (retval) 
-               goto out;
+               goto bus_register_failed;
        retval = usb_host_init();
        if (retval)
                goto host_init_failed;
@@ -1141,7 +1030,7 @@ static int __init usb_init(void)
        retval = usb_hub_init();
        if (retval)
                goto hub_init_failed;
-       retval = driver_register(&usb_generic_driver);
+       retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
        if (!retval)
                goto out;
 
@@ -1158,6 +1047,8 @@ major_init_failed:
        usb_host_cleanup();
 host_init_failed:
        bus_unregister(&usb_bus_type);
+bus_register_failed:
+       ksuspend_usb_cleanup();
 out:
        return retval;
 }
@@ -1171,7 +1062,7 @@ static void __exit usb_exit(void)
        if (nousb)
                return;
 
-       driver_unregister(&usb_generic_driver);
+       usb_deregister_device_driver(&usb_generic_driver);
        usb_major_cleanup();
        usbfs_cleanup();
        usb_deregister(&usbfs_driver);
@@ -1179,6 +1070,7 @@ static void __exit usb_exit(void)
        usb_hub_cleanup();
        usb_host_cleanup();
        bus_unregister(&usb_bus_type);
+       ksuspend_usb_cleanup();
 }
 
 subsys_initcall(usb_init);
@@ -1201,20 +1093,27 @@ EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
 
 EXPORT_SYMBOL(usb_lock_device_for_reset);
 
-EXPORT_SYMBOL(usb_driver_claim_interface);
-EXPORT_SYMBOL(usb_driver_release_interface);
 EXPORT_SYMBOL(usb_find_interface);
 EXPORT_SYMBOL(usb_ifnum_to_if);
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
 
-EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_reset_composite_device);
-
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
 
 EXPORT_SYMBOL(usb_find_device);
 EXPORT_SYMBOL(usb_get_current_frame_number);
 
+EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
+
 EXPORT_SYMBOL (usb_buffer_alloc);
 EXPORT_SYMBOL (usb_buffer_free);
 
index 49f69236b4201614b5a8329f7d7d12ec0309d5d5..f69df137ec0ec91aac813342ee3a3e0e564a6fae 100644 (file)
@@ -1,10 +1,10 @@
 /* Functions local to drivers/usb/core/ */
 
-extern void usb_create_sysfs_dev_files (struct usb_device *dev);
+extern int usb_create_sysfs_dev_files (struct usb_device *dev);
 extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
-extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
+extern int usb_create_sysfs_intf_files (struct usb_interface *intf);
 extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
+extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
                                struct usb_device *udev);
 extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 
@@ -20,7 +20,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_kick_khubd(struct usb_device *dev);
-extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
 
 extern int  usb_hub_init(void);
@@ -30,28 +29,91 @@ extern void usb_major_cleanup(void);
 extern int usb_host_init(void);
 extern void usb_host_cleanup(void);
 
-extern int usb_suspend_device(struct usb_device *dev);
-extern int usb_resume_device(struct usb_device *dev);
+#ifdef CONFIG_PM
 
-extern struct device_driver usb_generic_driver;
-extern int usb_generic_driver_data;
-extern int usb_device_match(struct device *dev, struct device_driver *drv);
+extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
+extern int usb_resume_both(struct usb_device *udev);
+extern int usb_port_suspend(struct usb_device *dev);
+extern int usb_port_resume(struct usb_device *dev);
+
+static inline void usb_pm_lock(struct usb_device *udev)
+{
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+}
+
+static inline void usb_pm_unlock(struct usb_device *udev)
+{
+       mutex_unlock(&udev->pm_mutex);
+}
+
+#else
+
+#define usb_suspend_both(udev, msg)    0
+static inline int usb_resume_both(struct usb_device *udev)
+{
+       return 0;
+}
+#define usb_port_suspend(dev)          0
+#define usb_port_resume(dev)           0
+static inline void usb_pm_lock(struct usb_device *udev) {}
+static inline void usb_pm_unlock(struct usb_device *udev) {}
+
+#endif
+
+#ifdef CONFIG_USB_SUSPEND
+
+#define USB_AUTOSUSPEND_DELAY  (HZ*2)
+
+extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
+extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+
+#else
+
+#define usb_autosuspend_device(udev, dec_busy_cnt)     do {} while (0)
+static inline int usb_autoresume_device(struct usb_device *udev,
+               int inc_busy_cnt)
+{
+       return 0;
+}
+
+#endif
+
+extern struct workqueue_struct *ksuspend_usb_wq;
+extern struct bus_type usb_bus_type;
+extern struct usb_device_driver usb_generic_driver;
+
+/* Here's how we tell apart devices and interfaces.  Luckily there's
+ * no such thing as a platform USB device, so we can steal the use
+ * of the platform_data field. */
+
+static inline int is_usb_device(const struct device *dev)
+{
+       return dev->platform_data == &usb_generic_driver;
+}
+
+/* Do the same for device drivers and interface drivers. */
+
+static inline int is_usb_device_driver(struct device_driver *drv)
+{
+       return container_of(drv, struct usbdrv_wrap, driver)->
+                       for_devices;
+}
 
 /* Interfaces and their "power state" are owned by usbcore */
 
 static inline void mark_active(struct usb_interface *f)
 {
-       f->dev.power.power_state.event = PM_EVENT_ON;
+       f->is_active = 1;
 }
 
 static inline void mark_quiesced(struct usb_interface *f)
 {
-       f->dev.power.power_state.event = PM_EVENT_FREEZE;
+       f->is_active = 0;
 }
 
-static inline int is_active(struct usb_interface *f)
+static inline int is_active(const struct usb_interface *f)
 {
-       return f->dev.power.power_state.event == PM_EVENT_ON;
+       return f->is_active;
 }
 
 
@@ -59,9 +121,10 @@ static inline int is_active(struct usb_interface *f)
 extern const char *usbcore_name;
 
 /* usbfs stuff */
+extern struct mutex usbfs_mutex;
 extern struct usb_driver usbfs_driver;
-extern struct file_operations usbfs_devices_fops;
-extern struct file_operations usbfs_device_file_operations;
+extern const struct file_operations usbfs_devices_fops;
+extern const struct file_operations usbfs_device_file_operations;
 extern void usbfs_conn_disc_event(void);
 
 extern int usbdev_init(void);
index 1a32d96774b42d61ce0e33abe3b38b8c350fde10..8e5dd6f29d0bc18ed7c5b7ac453f67475cd1125d 100644 (file)
@@ -26,7 +26,7 @@ config USB_GADGET
           you need a low level bus controller driver, and some software
           talking to it.  Peripheral controllers are often discrete silicon,
           or are integrated with the CPU in a microcontroller.  The more
-          familiar host side controllers have names like like "EHCI", "OHCI",
+          familiar host side controllers have names like "EHCI", "OHCI",
           or "UHCI", and are usually integrated into southbridges on PC
           motherboards.
 
@@ -404,6 +404,20 @@ config USB_G_SERIAL
          which includes instructions and a "driver info file" needed to
          make MS-Windows work with this driver.
 
+config USB_MIDI_GADGET
+       tristate "MIDI Gadget (EXPERIMENTAL)"
+       depends on SND && EXPERIMENTAL
+       select SND_RAWMIDI
+       help
+         The MIDI Gadget acts as a USB Audio device, with one MIDI
+         input and one MIDI output. These MIDI jacks appear as
+         a sound "card" in the ALSA sound system. Other MIDI
+         connections can then be made on the gadget system, using
+         ALSA's aconnect utility etc.
+
+         Say "y" to link the driver statically, or "m" to build a
+         dynamically linked module called "g_midi".
+
 
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
index 5a28e61392ec4807ef0e0a63516b4d1cc59e3b51..e71e086a1cfaf4e881ff63c34c25b4145a09c166 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_AT91)                += at91_udc.o
 g_zero-objs                    := zero.o usbstring.o config.o epautoconf.o
 g_ether-objs                   := ether.o usbstring.o config.o epautoconf.o
 g_serial-objs                  := serial.o usbstring.o config.o epautoconf.o
+g_midi-objs                    := gmidi.o usbstring.o config.o epautoconf.o
 gadgetfs-objs                  := inode.o
 g_file_storage-objs            := file_storage.o usbstring.o config.o \
                                        epautoconf.o
@@ -28,4 +29,5 @@ obj-$(CONFIG_USB_ETH)         += g_ether.o
 obj-$(CONFIG_USB_GADGETFS)     += gadgetfs.o
 obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)     += g_serial.o
+obj-$(CONFIG_USB_MIDI_GADGET)  += g_midi.o
 
index cfebca05ead57ca87188b40d93f08ec0c04160b1..77beba485a8430e343eddffdd7f91e223ef7a712 100644 (file)
@@ -247,7 +247,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
        return single_open(file, proc_udc_show, PDE(inode)->data);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -1658,7 +1658,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) {
+       if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) {
                DBG("someone's using UDC memory\n");
                return -EBUSY;
        }
@@ -1720,7 +1720,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
 fail1:
        device_unregister(&udc->gadget.dev);
 fail0:
-       release_mem_region(AT91_BASE_UDP, SZ_16K);
+       release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
        DBG("%s probe failed, %d\n", driver_name, retval);
        return retval;
 }
@@ -1742,7 +1742,7 @@ static int __devexit at91udc_remove(struct platform_device *pdev)
                free_irq(udc->board.vbus_pin, udc);
        free_irq(udc->udp_irq, udc);
        device_unregister(&udc->gadget.dev);
-       release_mem_region(AT91_BASE_UDP, SZ_16K);
+       release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
 
        clk_put(udc->iclk);
        clk_put(udc->fclk);
index 7d1c22c34957bfa94ebc5dfe067a6b98ffa86e28..4d2946e540cf9462538db8b51274fd5a40621ffe 100644 (file)
@@ -816,15 +816,14 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
        dum->gadget.dev.driver = &driver->driver;
        dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
                        driver->driver.name);
-       if ((retval = driver->bind (&dum->gadget)) != 0) {
-               dum->driver = NULL;
-               dum->gadget.dev.driver = NULL;
-               return retval;
-       }
+       if ((retval = driver->bind (&dum->gadget)) != 0)
+               goto err_bind_gadget;
 
        driver->driver.bus = dum->gadget.dev.parent->bus;
-       driver_register (&driver->driver);
-       device_bind_driver (&dum->gadget.dev);
+       if ((retval = driver_register (&driver->driver)) != 0)
+               goto err_register;
+       if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
+               goto err_bind_driver;
 
        /* khubd will enumerate this in a while */
        spin_lock_irq (&dum->lock);
@@ -834,6 +833,19 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
 
        usb_hcd_poll_rh_status (dummy_to_hcd (dum));
        return 0;
+
+err_bind_driver:
+       driver_unregister (&driver->driver);
+err_register:
+       driver->unbind (&dum->gadget);
+       spin_lock_irq (&dum->lock);
+       dum->pullup = 0;
+       set_link_state (dum);
+       spin_unlock_irq (&dum->lock);
+err_bind_gadget:
+       dum->driver = NULL;
+       dum->gadget.dev.driver = NULL;
+       return retval;
 }
 EXPORT_SYMBOL (usb_gadget_register_driver);
 
@@ -889,11 +901,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);
 static void
 dummy_gadget_release (struct device *dev)
 {
-#if 0          /* usb_bus_put isn't EXPORTed! */
        struct dummy    *dum = gadget_dev_to_dummy (dev);
 
-       usb_bus_put (&dummy_to_hcd (dum)->self);
-#endif
+       usb_put_hcd (dummy_to_hcd (dum));
 }
 
 static int dummy_udc_probe (struct platform_device *pdev)
@@ -915,12 +925,12 @@ static int dummy_udc_probe (struct platform_device *pdev)
        if (rc < 0)
                return rc;
 
-#if 0          /* usb_bus_get isn't EXPORTed! */
-       usb_bus_get (&dummy_to_hcd (dum)->self);
-#endif
+       usb_get_hcd (dummy_to_hcd (dum));
 
        platform_set_drvdata (pdev, dum);
-       device_create_file (&dum->gadget.dev, &dev_attr_function);
+       rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
+       if (rc < 0)
+               device_unregister (&dum->gadget.dev);
        return rc;
 }
 
@@ -1868,8 +1878,7 @@ static int dummy_start (struct usb_hcd *hcd)
 #endif
 
        /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
-       device_create_file (dummy_dev(dum), &dev_attr_urbs);
-       return 0;
+       return device_create_file (dummy_dev(dum), &dev_attr_urbs);
 }
 
 static void dummy_stop (struct usb_hcd *hcd)
index 30299c620d97302e3dd73900568fc803c150911b..366dc0a9e52c291e8057970eca7b3de8644e53ce 100644 (file)
@@ -262,7 +262,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_MUSBHDRC
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 #define DEV_CONFIG_CDC
 #endif
 
@@ -2014,7 +2014,7 @@ rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
 static int rndis_control_ack (struct net_device *net)
 {
        struct eth_dev          *dev = netdev_priv(net);
-       u32                     length;
+       int                     length;
        struct usb_request      *resp = dev->stat_req;
 
        /* in case RNDIS calls this after disconnect */
@@ -2230,6 +2230,9 @@ eth_bind (struct usb_gadget *gadget)
        if (gadget_is_pxa (gadget)) {
                /* pxa doesn't support altsettings */
                cdc = 0;
+       } else if (gadget_is_musbhdrc(gadget)) {
+               /* reduce tx dma overhead by avoiding special cases */
+               zlp = 0;
        } else if (gadget_is_sh(gadget)) {
                /* sh doesn't support multiple interfaces or configs */
                cdc = 0;
@@ -2564,7 +2567,7 @@ static struct usb_gadget_driver eth_driver = {
 
        .function       = (char *) driver_desc,
        .bind           = eth_bind,
-       .unbind         = __exit_p(eth_unbind),
+       .unbind         = eth_unbind,
 
        .setup          = eth_setup,
        .disconnect     = eth_disconnect,
index 8d7f1e84cd7b048eadc36df840c383ff7c7bfab8..c83d3b6c68f2121dd574ff92fd3c30a4b9670791 100644 (file)
@@ -567,6 +567,7 @@ struct lun {
        unsigned int    ro : 1;
        unsigned int    prevent_medium_removal : 1;
        unsigned int    registered : 1;
+       unsigned int    info_valid : 1;
 
        u32             sense_data;
        u32             sense_data_info;
@@ -1656,6 +1657,7 @@ static int do_read(struct fsg_dev *fsg)
                        curlun->sense_data =
                                        SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
                        curlun->sense_data_info = file_offset >> 9;
+                       curlun->info_valid = 1;
                        bh->inreq->length = 0;
                        bh->state = BUF_STATE_FULL;
                        break;
@@ -1691,6 +1693,7 @@ static int do_read(struct fsg_dev *fsg)
                if (nread < amount) {
                        curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
                        curlun->sense_data_info = file_offset >> 9;
+                       curlun->info_valid = 1;
                        break;
                }
 
@@ -1785,6 +1788,7 @@ static int do_write(struct fsg_dev *fsg)
                                curlun->sense_data =
                                        SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
                                curlun->sense_data_info = usb_offset >> 9;
+                               curlun->info_valid = 1;
                                continue;
                        }
                        amount -= (amount & 511);
@@ -1827,6 +1831,7 @@ static int do_write(struct fsg_dev *fsg)
                        if (bh->outreq->status != 0) {
                                curlun->sense_data = SS_COMMUNICATION_FAILURE;
                                curlun->sense_data_info = file_offset >> 9;
+                               curlun->info_valid = 1;
                                break;
                        }
 
@@ -1868,6 +1873,7 @@ static int do_write(struct fsg_dev *fsg)
                        if (nwritten < amount) {
                                curlun->sense_data = SS_WRITE_ERROR;
                                curlun->sense_data_info = file_offset >> 9;
+                               curlun->info_valid = 1;
                                break;
                        }
 
@@ -2010,6 +2016,7 @@ static int do_verify(struct fsg_dev *fsg)
                        curlun->sense_data =
                                        SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
                        curlun->sense_data_info = file_offset >> 9;
+                       curlun->info_valid = 1;
                        break;
                }
 
@@ -2036,6 +2043,7 @@ static int do_verify(struct fsg_dev *fsg)
                if (nread == 0) {
                        curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
                        curlun->sense_data_info = file_offset >> 9;
+                       curlun->info_valid = 1;
                        break;
                }
                file_offset += nread;
@@ -2079,6 +2087,7 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
        struct lun      *curlun = fsg->curlun;
        u8              *buf = (u8 *) bh->buf;
        u32             sd, sdinfo;
+       int             valid;
 
        /*
         * From the SCSI-2 spec., section 7.9 (Unit attention condition):
@@ -2106,15 +2115,18 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
                fsg->bad_lun_okay = 1;
                sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
                sdinfo = 0;
+               valid = 0;
        } else {
                sd = curlun->sense_data;
                sdinfo = curlun->sense_data_info;
+               valid = curlun->info_valid << 7;
                curlun->sense_data = SS_NO_SENSE;
                curlun->sense_data_info = 0;
+               curlun->info_valid = 0;
        }
 
        memset(buf, 0, 18);
-       buf[0] = 0x80 | 0x70;                   // Valid, current error
+       buf[0] = valid | 0x70;                  // Valid, current error
        buf[2] = SK(sd);
        put_be32(&buf[3], sdinfo);              // Sense information
        buf[7] = 18 - 8;                        // Additional sense length
@@ -2703,6 +2715,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
                if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
                        curlun->sense_data = SS_NO_SENSE;
                        curlun->sense_data_info = 0;
+                       curlun->info_valid = 0;
                }
        } else {
                fsg->curlun = curlun = NULL;
@@ -3332,6 +3345,7 @@ static void handle_exception(struct fsg_dev *fsg)
                        curlun->sense_data = curlun->unit_attention_data =
                                        SS_NO_SENSE;
                        curlun->sense_data_info = 0;
+                       curlun->info_valid = 0;
                }
                fsg->state = FSG_STATE_IDLE;
        }
@@ -3873,21 +3887,26 @@ static int __init fsg_bind(struct usb_gadget *gadget)
        for (i = 0; i < fsg->nluns; ++i) {
                curlun = &fsg->luns[i];
                curlun->ro = mod_data.ro[i];
+               curlun->dev.release = lun_release;
                curlun->dev.parent = &gadget->dev;
                curlun->dev.driver = &fsg_driver.driver;
                dev_set_drvdata(&curlun->dev, fsg);
                snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
                                "%s-lun%d", gadget->dev.bus_id, i);
 
-               if ((rc = device_register(&curlun->dev)) != 0)
+               if ((rc = device_register(&curlun->dev)) != 0) {
                        INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-               else {
-                       curlun->registered = 1;
-                       curlun->dev.release = lun_release;
-                       device_create_file(&curlun->dev, &dev_attr_ro);
-                       device_create_file(&curlun->dev, &dev_attr_file);
-                       kref_get(&fsg->ref);
+                       goto out;
+               }
+               if ((rc = device_create_file(&curlun->dev,
+                                       &dev_attr_ro)) != 0 ||
+                               (rc = device_create_file(&curlun->dev,
+                                       &dev_attr_file)) != 0) {
+                       device_unregister(&curlun->dev);
+                       goto out;
                }
+               curlun->registered = 1;
+               kref_get(&fsg->ref);
 
                if (mod_data.file[i] && *mod_data.file[i]) {
                        if ((rc = open_backing_file(curlun,
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
new file mode 100644 (file)
index 0000000..b68cecd
--- /dev/null
@@ -0,0 +1,1337 @@
+/*
+ * gmidi.c -- USB MIDI Gadget Driver
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This code is based in part on:
+ *
+ * Gadget Zero driver, Copyright (C) 2003-2004 David Brownell.
+ * USB Audio driver, Copyright (C) 2002 by Takashi Iwai.
+ * USB MIDI driver, Copyright (C) 2002-2005 Clemens Ladisch.
+ *
+ * Refer to the USB Device Class Definition for MIDI Devices:
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#define DEBUG 1
+// #define VERBOSE
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/midi.h>
+
+#include "gadget_chips.h"
+
+MODULE_AUTHOR("Ben Williamson");
+MODULE_LICENSE("GPL v2");
+
+#define DRIVER_VERSION "25 Jul 2006"
+
+static const char shortname[] = "g_midi";
+static const char longname[] = "MIDI Gadget";
+
+static int index = SNDRV_DEFAULT_IDX1;
+static char *id = SNDRV_DEFAULT_STR1;
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter.");
+
+/* Some systems will want different product identifers published in the
+ * device descriptor, either numbers or strings or both.  These string
+ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort idVendor;
+module_param(idVendor, ushort, S_IRUGO);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort idProduct;
+module_param(idProduct, ushort, S_IRUGO);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort bcdDevice;
+module_param(bcdDevice, ushort, S_IRUGO);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *iManufacturer;
+module_param(iManufacturer, charp, S_IRUGO);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *iProduct;
+module_param(iProduct, charp, S_IRUGO);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
+
+/*
+ * this version autoconfigures as much as possible,
+ * which is reasonable for most "bulk-only" drivers.
+ */
+static const char *EP_IN_NAME;
+static const char *EP_OUT_NAME;
+
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+/* This is a gadget, and the IN/OUT naming is from the host's perspective.
+   USB -> OUT endpoint -> rawmidi
+   USB <- IN endpoint  <- rawmidi */
+struct gmidi_in_port {
+       struct gmidi_device* dev;
+       int active;
+       uint8_t cable;          /* cable number << 4 */
+       uint8_t state;
+#define STATE_UNKNOWN  0
+#define STATE_1PARAM   1
+#define STATE_2PARAM_1 2
+#define STATE_2PARAM_2 3
+#define STATE_SYSEX_0  4
+#define STATE_SYSEX_1  5
+#define STATE_SYSEX_2  6
+       uint8_t data[2];
+};
+
+struct gmidi_device {
+       spinlock_t              lock;
+       struct usb_gadget       *gadget;
+       struct usb_request      *req;           /* for control responses */
+       u8                      config;
+       struct usb_ep           *in_ep, *out_ep;
+       struct snd_card         *card;
+       struct snd_rawmidi      *rmidi;
+       struct snd_rawmidi_substream *in_substream;
+       struct snd_rawmidi_substream *out_substream;
+
+       /* For the moment we only support one port in
+          each direction, but in_port is kept as a
+          separate struct so we can have more later. */
+       struct gmidi_in_port    in_port;
+       unsigned long           out_triggered;
+       struct tasklet_struct   tasklet;
+};
+
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
+
+
+#define xprintk(d,level,fmt,args...) \
+       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+       xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+       do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+       do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+       xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+       xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+       xprintk(dev , KERN_INFO , fmt , ## args)
+
+
+static unsigned buflen = 256;
+static unsigned qlen = 32;
+
+module_param(buflen, uint, S_IRUGO);
+module_param(qlen, uint, S_IRUGO);
+
+
+/* Thanks to Grey Innovation for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+#define DRIVER_VENDOR_NUM      0x17b3          /* Grey Innovation */
+#define DRIVER_PRODUCT_NUM     0x0004          /* Linux-USB "MIDI Gadget" */
+
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full)
+ * configuration descriptors are built on demand.
+ */
+
+#define STRING_MANUFACTURER    25
+#define STRING_PRODUCT         42
+#define STRING_SERIAL          101
+#define STRING_MIDI_GADGET     250
+
+/* We only have the one configuration, it's number 1. */
+#define        GMIDI_CONFIG            1
+
+/* We have two interfaces- AudioControl and MIDIStreaming */
+#define GMIDI_AC_INTERFACE     0
+#define GMIDI_MS_INTERFACE     1
+#define GMIDI_NUM_INTERFACES   2
+
+DECLARE_USB_AC_HEADER_DESCRIPTOR(1);
+DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
+DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
+
+/* B.1  Device Descriptor */
+static struct usb_device_descriptor device_desc = {
+       .bLength =              USB_DT_DEVICE_SIZE,
+       .bDescriptorType =      USB_DT_DEVICE,
+       .bcdUSB =               __constant_cpu_to_le16(0x0200),
+       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
+       .idVendor =             __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
+       .idProduct =            __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+       .iManufacturer =        STRING_MANUFACTURER,
+       .iProduct =             STRING_PRODUCT,
+       .bNumConfigurations =   1,
+};
+
+/* B.2  Configuration Descriptor */
+static struct usb_config_descriptor config_desc = {
+       .bLength =              USB_DT_CONFIG_SIZE,
+       .bDescriptorType =      USB_DT_CONFIG,
+       /* compute wTotalLength on the fly */
+       .bNumInterfaces =       GMIDI_NUM_INTERFACES,
+       .bConfigurationValue =  GMIDI_CONFIG,
+       .iConfiguration =       STRING_MIDI_GADGET,
+       /*
+        * FIXME: When embedding this driver in a device,
+        * these need to be set to reflect the actual
+        * power properties of the device. Is it selfpowered?
+        */
+       .bmAttributes =         USB_CONFIG_ATT_ONE,
+       .bMaxPower =            1,
+};
+
+/* B.3.1  Standard AC Interface Descriptor */
+static const struct usb_interface_descriptor ac_interface_desc = {
+       .bLength =              USB_DT_INTERFACE_SIZE,
+       .bDescriptorType =      USB_DT_INTERFACE,
+       .bInterfaceNumber =     GMIDI_AC_INTERFACE,
+       .bNumEndpoints =        0,
+       .bInterfaceClass =      USB_CLASS_AUDIO,
+       .bInterfaceSubClass =   USB_SUBCLASS_AUDIOCONTROL,
+       .iInterface =           STRING_MIDI_GADGET,
+};
+
+/* B.3.2  Class-Specific AC Interface Descriptor */
+static const struct usb_ac_header_descriptor_1 ac_header_desc = {
+       .bLength =              USB_DT_AC_HEADER_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_HEADER,
+       .bcdADC =               __constant_cpu_to_le16(0x0100),
+       .wTotalLength =         USB_DT_AC_HEADER_SIZE(1),
+       .bInCollection =        1,
+       .baInterfaceNr = {
+               [0] =           GMIDI_MS_INTERFACE,
+       }
+};
+
+/* B.4.1  Standard MS Interface Descriptor */
+static const struct usb_interface_descriptor ms_interface_desc = {
+       .bLength =              USB_DT_INTERFACE_SIZE,
+       .bDescriptorType =      USB_DT_INTERFACE,
+       .bInterfaceNumber =     GMIDI_MS_INTERFACE,
+       .bNumEndpoints =        2,
+       .bInterfaceClass =      USB_CLASS_AUDIO,
+       .bInterfaceSubClass =   USB_SUBCLASS_MIDISTREAMING,
+       .iInterface =           STRING_MIDI_GADGET,
+};
+
+/* B.4.2  Class-Specific MS Interface Descriptor */
+static const struct usb_ms_header_descriptor ms_header_desc = {
+       .bLength =              USB_DT_MS_HEADER_SIZE,
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_HEADER,
+       .bcdMSC =               __constant_cpu_to_le16(0x0100),
+       .wTotalLength =         USB_DT_MS_HEADER_SIZE
+                               + 2*USB_DT_MIDI_IN_SIZE
+                               + 2*USB_DT_MIDI_OUT_SIZE(1),
+};
+
+#define JACK_IN_EMB    1
+#define JACK_IN_EXT    2
+#define JACK_OUT_EMB   3
+#define JACK_OUT_EXT   4
+
+/* B.4.3  MIDI IN Jack Descriptors */
+static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
+       .bLength =              USB_DT_MIDI_IN_SIZE,
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_IN_JACK,
+       .bJackType =            USB_MS_EMBEDDED,
+       .bJackID =              JACK_IN_EMB,
+};
+
+static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = {
+       .bLength =              USB_DT_MIDI_IN_SIZE,
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_IN_JACK,
+       .bJackType =            USB_MS_EXTERNAL,
+       .bJackID =              JACK_IN_EXT,
+};
+
+/* B.4.4  MIDI OUT Jack Descriptors */
+static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = {
+       .bLength =              USB_DT_MIDI_OUT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK,
+       .bJackType =            USB_MS_EMBEDDED,
+       .bJackID =              JACK_OUT_EMB,
+       .bNrInputPins =         1,
+       .pins = {
+               [0] = {
+                       .baSourceID =   JACK_IN_EXT,
+                       .baSourcePin =  1,
+               }
+       }
+};
+
+static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = {
+       .bLength =              USB_DT_MIDI_OUT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK,
+       .bJackType =            USB_MS_EXTERNAL,
+       .bJackID =              JACK_OUT_EXT,
+       .bNrInputPins =         1,
+       .pins = {
+               [0] = {
+                       .baSourceID =   JACK_IN_EMB,
+                       .baSourcePin =  1,
+               }
+       }
+};
+
+/* B.5.1  Standard Bulk OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor bulk_out_desc = {
+       .bLength =              USB_DT_ENDPOINT_AUDIO_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     USB_DIR_OUT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+};
+
+/* B.5.2  Class-specific MS Bulk OUT Endpoint Descriptor */
+static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = {
+       .bLength =              USB_DT_MS_ENDPOINT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_ENDPOINT,
+       .bDescriptorSubtype =   USB_MS_GENERAL,
+       .bNumEmbMIDIJack =      1,
+       .baAssocJackID = {
+               [0] =           JACK_IN_EMB,
+       }
+};
+
+/* B.6.1  Standard Bulk IN Endpoint Descriptor */
+static struct usb_endpoint_descriptor bulk_in_desc = {
+       .bLength =              USB_DT_ENDPOINT_AUDIO_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     USB_DIR_IN,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+};
+
+/* B.6.2  Class-specific MS Bulk IN Endpoint Descriptor */
+static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = {
+       .bLength =              USB_DT_MS_ENDPOINT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_ENDPOINT,
+       .bDescriptorSubtype =   USB_MS_GENERAL,
+       .bNumEmbMIDIJack =      1,
+       .baAssocJackID = {
+               [0] =           JACK_OUT_EMB,
+       }
+};
+
+static const struct usb_descriptor_header *gmidi_function [] = {
+       (struct usb_descriptor_header *)&ac_interface_desc,
+       (struct usb_descriptor_header *)&ac_header_desc,
+       (struct usb_descriptor_header *)&ms_interface_desc,
+
+       (struct usb_descriptor_header *)&ms_header_desc,
+       (struct usb_descriptor_header *)&jack_in_emb_desc,
+       (struct usb_descriptor_header *)&jack_in_ext_desc,
+       (struct usb_descriptor_header *)&jack_out_emb_desc,
+       (struct usb_descriptor_header *)&jack_out_ext_desc,
+       /* If you add more jacks, update ms_header_desc.wTotalLength */
+
+       (struct usb_descriptor_header *)&bulk_out_desc,
+       (struct usb_descriptor_header *)&ms_out_desc,
+       (struct usb_descriptor_header *)&bulk_in_desc,
+       (struct usb_descriptor_header *)&ms_in_desc,
+       NULL,
+};
+
+static char manufacturer[50];
+static char product_desc[40] = "MIDI Gadget";
+static char serial_number[20];
+
+/* static strings, in UTF-8 */
+static struct usb_string strings [] = {
+       { STRING_MANUFACTURER, manufacturer, },
+       { STRING_PRODUCT, product_desc, },
+       { STRING_SERIAL, serial_number, },
+       { STRING_MIDI_GADGET, longname, },
+       {  }                    /* end of list */
+};
+
+static struct usb_gadget_strings stringtab = {
+       .language       = 0x0409,       /* en-us */
+       .strings        = strings,
+};
+
+static int config_buf(struct usb_gadget *gadget,
+               u8 *buf, u8 type, unsigned index)
+{
+       int len;
+
+       /* only one configuration */
+       if (index != 0) {
+               return -EINVAL;
+       }
+       len = usb_gadget_config_buf(&config_desc,
+                       buf, USB_BUFSIZ, gmidi_function);
+       if (len < 0) {
+               return len;
+       }
+       ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
+       return len;
+}
+
+static struct usb_request* alloc_ep_req(struct usb_ep *ep, unsigned length)
+{
+       struct usb_request      *req;
+
+       req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+       if (req) {
+               req->length = length;
+               req->buf = kmalloc(length, GFP_ATOMIC);
+               if (!req->buf) {
+                       usb_ep_free_request(ep, req);
+                       req = NULL;
+               }
+       }
+       return req;
+}
+
+static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+       kfree(req->buf);
+       usb_ep_free_request(ep, req);
+}
+
+static const uint8_t gmidi_cin_length[] = {
+       0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
+};
+
+/*
+ * Receives a chunk of MIDI data.
+ */
+static void gmidi_read_data(struct usb_ep *ep, int cable,
+                                  uint8_t* data, int length)
+{
+       struct gmidi_device *dev = ep->driver_data;
+       /* cable is ignored, because for now we only have one. */
+
+       if (!dev->out_substream) {
+               /* Nobody is listening - throw it on the floor. */
+               return;
+       }
+       if (!test_bit(dev->out_substream->number, &dev->out_triggered)) {
+               return;
+       }
+       snd_rawmidi_receive(dev->out_substream, data, length);
+}
+
+static void gmidi_handle_out_data(struct usb_ep *ep, struct usb_request *req)
+{
+       unsigned i;
+       u8 *buf = req->buf;
+
+       for (i = 0; i + 3 < req->actual; i += 4) {
+               if (buf[i] != 0) {
+                       int cable = buf[i] >> 4;
+                       int length = gmidi_cin_length[buf[i] & 0x0f];
+                       gmidi_read_data(ep, cable, &buf[i + 1], length);
+               }
+       }
+}
+
+static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct gmidi_device *dev = ep->driver_data;
+       int status = req->status;
+
+       switch (status) {
+       case 0:                         /* normal completion */
+               if (ep == dev->out_ep) {
+                       /* we received stuff.
+                          req is queued again, below */
+                       gmidi_handle_out_data(ep, req);
+               } else if (ep == dev->in_ep) {
+                       /* our transmit completed.
+                          see if there's more to go.
+                          gmidi_transmit eats req, don't queue it again. */
+                       gmidi_transmit(dev, req);
+                       return;
+               }
+               break;
+
+       /* this endpoint is normally active while we're configured */
+       case -ECONNABORTED:             /* hardware forced ep reset */
+       case -ECONNRESET:               /* request dequeued */
+       case -ESHUTDOWN:                /* disconnect from host */
+               VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
+                               req->actual, req->length);
+               if (ep == dev->out_ep) {
+                       gmidi_handle_out_data(ep, req);
+               }
+               free_ep_req(ep, req);
+               return;
+
+       case -EOVERFLOW:                /* buffer overrun on read means that
+                                        * we didn't provide a big enough
+                                        * buffer.
+                                        */
+       default:
+               DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
+                               status, req->actual, req->length);
+               break;
+       case -EREMOTEIO:                /* short read */
+               break;
+       }
+
+       status = usb_ep_queue(ep, req, GFP_ATOMIC);
+       if (status) {
+               ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n",
+                               ep->name, req->length, status);
+               usb_ep_set_halt(ep);
+               /* FIXME recover later ... somehow */
+       }
+}
+
+static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags)
+{
+       int err = 0;
+       struct usb_request *req;
+       struct usb_ep* ep;
+       unsigned i;
+
+       err = usb_ep_enable(dev->in_ep, &bulk_in_desc);
+       if (err) {
+               ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err);
+               goto fail;
+       }
+       dev->in_ep->driver_data = dev;
+
+       err = usb_ep_enable(dev->out_ep, &bulk_out_desc);
+       if (err) {
+               ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err);
+               goto fail;
+       }
+       dev->out_ep->driver_data = dev;
+
+       /* allocate a bunch of read buffers and queue them all at once. */
+       ep = dev->out_ep;
+       for (i = 0; i < qlen && err == 0; i++) {
+               req = alloc_ep_req(ep, buflen);
+               if (req) {
+                       req->complete = gmidi_complete;
+                       err = usb_ep_queue(ep, req, GFP_ATOMIC);
+                       if (err) {
+                               DBG(dev, "%s queue req: %d\n", ep->name, err);
+                       }
+               } else {
+                       err = -ENOMEM;
+               }
+       }
+fail:
+       /* caller is responsible for cleanup on error */
+       return err;
+}
+
+
+static void gmidi_reset_config(struct gmidi_device *dev)
+{
+       if (dev->config == 0) {
+               return;
+       }
+
+       DBG(dev, "reset config\n");
+
+       /* just disable endpoints, forcing completion of pending i/o.
+        * all our completion handlers free their requests in this case.
+        */
+       usb_ep_disable(dev->in_ep);
+       usb_ep_disable(dev->out_ep);
+       dev->config = 0;
+}
+
+/* change our operational config.  this code must agree with the code
+ * that returns config descriptors, and altsetting code.
+ *
+ * it's also responsible for power management interactions. some
+ * configurations might not work with our current power sources.
+ *
+ * note that some device controller hardware will constrain what this
+ * code can do, perhaps by disallowing more than one configuration or
+ * by limiting configuration choices (like the pxa2xx).
+ */
+static int
+gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
+{
+       int result = 0;
+       struct usb_gadget *gadget = dev->gadget;
+
+#if 0
+       /* FIXME */
+       /* Hacking this bit out fixes a bug where on receipt of two
+          USB_REQ_SET_CONFIGURATION messages, we end up with no
+          buffered OUT requests waiting for data. This is clearly
+          hiding a bug elsewhere, because if the config didn't
+          change then we really shouldn't do anything. */
+       /* Having said that, when we do "change" from config 1
+          to config 1, we at least gmidi_reset_config() which
+          clears out any requests on endpoints, so it's not like
+          we leak or anything. */
+       if (number == dev->config) {
+               return 0;
+       }
+#endif
+
+       if (gadget_is_sa1100(gadget) && dev->config) {
+               /* tx fifo is full, but we can't clear it...*/
+               INFO(dev, "can't change configurations\n");
+               return -ESPIPE;
+       }
+       gmidi_reset_config(dev);
+
+       switch (number) {
+       case GMIDI_CONFIG:
+               result = set_gmidi_config(dev, gfp_flags);
+               break;
+       default:
+               result = -EINVAL;
+               /* FALL THROUGH */
+       case 0:
+               return result;
+       }
+
+       if (!result && (!dev->in_ep || !dev->out_ep)) {
+               result = -ENODEV;
+       }
+       if (result) {
+               gmidi_reset_config(dev);
+       } else {
+               char *speed;
+
+               switch (gadget->speed) {
+               case USB_SPEED_LOW:     speed = "low"; break;
+               case USB_SPEED_FULL:    speed = "full"; break;
+               case USB_SPEED_HIGH:    speed = "high"; break;
+               default:                speed = "?"; break;
+               }
+
+               dev->config = number;
+               INFO(dev, "%s speed\n", speed);
+       }
+       return result;
+}
+
+
+static void gmidi_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       if (req->status || req->actual != req->length) {
+               DBG((struct gmidi_device *) ep->driver_data,
+                               "setup complete --> %d, %d/%d\n",
+                               req->status, req->actual, req->length);
+       }
+}
+
+/*
+ * The setup() callback implements all the ep0 functionality that's
+ * not handled lower down, in hardware or the hardware driver (like
+ * device and endpoint feature flags, and their status).  It's all
+ * housekeeping for the gadget function we're implementing.  Most of
+ * the work is in config-specific setup.
+ */
+static int gmidi_setup(struct usb_gadget *gadget,
+                       const struct usb_ctrlrequest *ctrl)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+       struct usb_request *req = dev->req;
+       int value = -EOPNOTSUPP;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
+       u16 w_value = le16_to_cpu(ctrl->wValue);
+       u16 w_length = le16_to_cpu(ctrl->wLength);
+
+       /* usually this stores reply data in the pre-allocated ep0 buffer,
+        * but config change events will reconfigure hardware.
+        */
+       req->zero = 0;
+       switch (ctrl->bRequest) {
+
+       case USB_REQ_GET_DESCRIPTOR:
+               if (ctrl->bRequestType != USB_DIR_IN) {
+                       goto unknown;
+               }
+               switch (w_value >> 8) {
+
+               case USB_DT_DEVICE:
+                       value = min(w_length, (u16) sizeof(device_desc));
+                       memcpy(req->buf, &device_desc, value);
+                       break;
+               case USB_DT_CONFIG:
+                       value = config_buf(gadget, req->buf,
+                                       w_value >> 8,
+                                       w_value & 0xff);
+                       if (value >= 0) {
+                               value = min(w_length, (u16)value);
+                       }
+                       break;
+
+               case USB_DT_STRING:
+                       /* wIndex == language code.
+                        * this driver only handles one language, you can
+                        * add string tables for other languages, using
+                        * any UTF-8 characters
+                        */
+                       value = usb_gadget_get_string(&stringtab,
+                                       w_value & 0xff, req->buf);
+                       if (value >= 0) {
+                               value = min(w_length, (u16)value);
+                       }
+                       break;
+               }
+               break;
+
+       /* currently two configs, two speeds */
+       case USB_REQ_SET_CONFIGURATION:
+               if (ctrl->bRequestType != 0) {
+                       goto unknown;
+               }
+               if (gadget->a_hnp_support) {
+                       DBG(dev, "HNP available\n");
+               } else if (gadget->a_alt_hnp_support) {
+                       DBG(dev, "HNP needs a different root port\n");
+               } else {
+                       VDBG(dev, "HNP inactive\n");
+               }
+               spin_lock(&dev->lock);
+               value = gmidi_set_config(dev, w_value, GFP_ATOMIC);
+               spin_unlock(&dev->lock);
+               break;
+       case USB_REQ_GET_CONFIGURATION:
+               if (ctrl->bRequestType != USB_DIR_IN) {
+                       goto unknown;
+               }
+               *(u8 *)req->buf = dev->config;
+               value = min(w_length, (u16)1);
+               break;
+
+       /* until we add altsetting support, or other interfaces,
+        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
+        * and already killed pending endpoint I/O.
+        */
+       case USB_REQ_SET_INTERFACE:
+               if (ctrl->bRequestType != USB_RECIP_INTERFACE) {
+                       goto unknown;
+               }
+               spin_lock(&dev->lock);
+               if (dev->config && w_index < GMIDI_NUM_INTERFACES
+                       && w_value == 0)
+               {
+                       u8 config = dev->config;
+
+                       /* resets interface configuration, forgets about
+                        * previous transaction state (queued bufs, etc)
+                        * and re-inits endpoint state (toggle etc)
+                        * no response queued, just zero status == success.
+                        * if we had more than one interface we couldn't
+                        * use this "reset the config" shortcut.
+                        */
+                       gmidi_reset_config(dev);
+                       gmidi_set_config(dev, config, GFP_ATOMIC);
+                       value = 0;
+               }
+               spin_unlock(&dev->lock);
+               break;
+       case USB_REQ_GET_INTERFACE:
+               if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) {
+                       goto unknown;
+               }
+               if (!dev->config) {
+                       break;
+               }
+               if (w_index >= GMIDI_NUM_INTERFACES) {
+                       value = -EDOM;
+                       break;
+               }
+               *(u8 *)req->buf = 0;
+               value = min(w_length, (u16)1);
+               break;
+
+       default:
+unknown:
+               VDBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n",
+                       ctrl->bRequestType, ctrl->bRequest,
+                       w_value, w_index, w_length);
+       }
+
+       /* respond with data transfer before status phase? */
+       if (value >= 0) {
+               req->length = value;
+               req->zero = value < w_length;
+               value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+               if (value < 0) {
+                       DBG(dev, "ep_queue --> %d\n", value);
+                       req->status = 0;
+                       gmidi_setup_complete(gadget->ep0, req);
+               }
+       }
+
+       /* device either stalls (value < 0) or reports success */
+       return value;
+}
+
+static void gmidi_disconnect(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       gmidi_reset_config(dev);
+
+       /* a more significant application might have some non-usb
+        * activities to quiesce here, saving resources like power
+        * or pushing the notification up a network stack.
+        */
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       /* next we may get setup() calls to enumerate new connections;
+        * or an unbind() during shutdown (including removing module).
+        */
+}
+
+static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+       struct snd_card* card;
+
+       DBG(dev, "unbind\n");
+
+       card = dev->card;
+       dev->card = NULL;
+       if (card) {
+               snd_card_free(card);
+       }
+
+       /* we've already been disconnected ... no i/o is active */
+       if (dev->req) {
+               dev->req->length = USB_BUFSIZ;
+               free_ep_req(gadget->ep0, dev->req);
+       }
+       kfree(dev);
+       set_gadget_data(gadget, NULL);
+}
+
+static int gmidi_snd_free(struct snd_device *device)
+{
+       return 0;
+}
+
+static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0,
+                                       uint8_t p1, uint8_t p2, uint8_t p3)
+{
+       unsigned length = req->length;
+
+       uint8_t* buf = (uint8_t*)req->buf + length;
+       buf[0] = p0;
+       buf[1] = p1;
+       buf[2] = p2;
+       buf[3] = p3;
+       req->length = length + 4;
+}
+
+/*
+ * Converts MIDI commands to USB MIDI packets.
+ */
+static void gmidi_transmit_byte(struct usb_request* req,
+                               struct gmidi_in_port* port, uint8_t b)
+{
+       uint8_t p0 = port->cable;
+
+       if (b >= 0xf8) {
+               gmidi_transmit_packet(req, p0 | 0x0f, b, 0, 0);
+       } else if (b >= 0xf0) {
+               switch (b) {
+               case 0xf0:
+                       port->data[0] = b;
+                       port->state = STATE_SYSEX_1;
+                       break;
+               case 0xf1:
+               case 0xf3:
+                       port->data[0] = b;
+                       port->state = STATE_1PARAM;
+                       break;
+               case 0xf2:
+                       port->data[0] = b;
+                       port->state = STATE_2PARAM_1;
+                       break;
+               case 0xf4:
+               case 0xf5:
+                       port->state = STATE_UNKNOWN;
+                       break;
+               case 0xf6:
+                       gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0);
+                       port->state = STATE_UNKNOWN;
+                       break;
+               case 0xf7:
+                       switch (port->state) {
+                       case STATE_SYSEX_0:
+                               gmidi_transmit_packet(req,
+                                       p0 | 0x05, 0xf7, 0, 0);
+                               break;
+                       case STATE_SYSEX_1:
+                               gmidi_transmit_packet(req,
+                                       p0 | 0x06, port->data[0], 0xf7, 0);
+                               break;
+                       case STATE_SYSEX_2:
+                               gmidi_transmit_packet(req,
+                                       p0 | 0x07, port->data[0],
+                                       port->data[1], 0xf7);
+                               break;
+                       }
+                       port->state = STATE_UNKNOWN;
+                       break;
+               }
+       } else if (b >= 0x80) {
+               port->data[0] = b;
+               if (b >= 0xc0 && b <= 0xdf)
+                       port->state = STATE_1PARAM;
+               else
+                       port->state = STATE_2PARAM_1;
+       } else { /* b < 0x80 */
+               switch (port->state) {
+               case STATE_1PARAM:
+                       if (port->data[0] < 0xf0) {
+                               p0 |= port->data[0] >> 4;
+                       } else {
+                               p0 |= 0x02;
+                               port->state = STATE_UNKNOWN;
+                       }
+                       gmidi_transmit_packet(req, p0, port->data[0], b, 0);
+                       break;
+               case STATE_2PARAM_1:
+                       port->data[1] = b;
+                       port->state = STATE_2PARAM_2;
+                       break;
+               case STATE_2PARAM_2:
+                       if (port->data[0] < 0xf0) {
+                               p0 |= port->data[0] >> 4;
+                               port->state = STATE_2PARAM_1;
+                       } else {
+                               p0 |= 0x03;
+                               port->state = STATE_UNKNOWN;
+                       }
+                       gmidi_transmit_packet(req,
+                               p0, port->data[0], port->data[1], b);
+                       break;
+               case STATE_SYSEX_0:
+                       port->data[0] = b;
+                       port->state = STATE_SYSEX_1;
+                       break;
+               case STATE_SYSEX_1:
+                       port->data[1] = b;
+                       port->state = STATE_SYSEX_2;
+                       break;
+               case STATE_SYSEX_2:
+                       gmidi_transmit_packet(req,
+                               p0 | 0x04, port->data[0], port->data[1], b);
+                       port->state = STATE_SYSEX_0;
+                       break;
+               }
+       }
+}
+
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req)
+{
+       struct usb_ep* ep = dev->in_ep;
+       struct gmidi_in_port* port = &dev->in_port;
+
+       if (!ep) {
+               return;
+       }
+       if (!req) {
+               req = alloc_ep_req(ep, buflen);
+       }
+       if (!req) {
+               ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n");
+               return;
+       }
+       req->length = 0;
+       req->complete = gmidi_complete;
+
+       if (port->active) {
+               while (req->length + 3 < buflen) {
+                       uint8_t b;
+                       if (snd_rawmidi_transmit(dev->in_substream, &b, 1)
+                               != 1)
+                       {
+                               port->active = 0;
+                               break;
+                       }
+                       gmidi_transmit_byte(req, port, b);
+               }
+       }
+       if (req->length > 0) {
+               usb_ep_queue(ep, req, GFP_ATOMIC);
+       } else {
+               free_ep_req(ep, req);
+       }
+}
+
+static void gmidi_in_tasklet(unsigned long data)
+{
+       struct gmidi_device* dev = (struct gmidi_device*)data;
+
+       gmidi_transmit(dev, NULL);
+}
+
+static int gmidi_in_open(struct snd_rawmidi_substream *substream)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_in_open\n");
+       dev->in_substream = substream;
+       dev->in_port.state = STATE_UNKNOWN;
+       return 0;
+}
+
+static int gmidi_in_close(struct snd_rawmidi_substream *substream)
+{
+       VDBG(dev, "gmidi_in_close\n");
+       return 0;
+}
+
+static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_in_trigger %d\n", up);
+       dev->in_port.active = up;
+       if (up) {
+               tasklet_hi_schedule(&dev->tasklet);
+       }
+}
+
+static int gmidi_out_open(struct snd_rawmidi_substream *substream)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_out_open\n");
+       dev->out_substream = substream;
+       return 0;
+}
+
+static int gmidi_out_close(struct snd_rawmidi_substream *substream)
+{
+       VDBG(dev, "gmidi_out_close\n");
+       return 0;
+}
+
+static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_out_trigger %d\n", up);
+       if (up) {
+               set_bit(substream->number, &dev->out_triggered);
+       } else {
+               clear_bit(substream->number, &dev->out_triggered);
+       }
+}
+
+static struct snd_rawmidi_ops gmidi_in_ops = {
+       .open = gmidi_in_open,
+       .close = gmidi_in_close,
+       .trigger = gmidi_in_trigger,
+};
+
+static struct snd_rawmidi_ops gmidi_out_ops = {
+       .open = gmidi_out_open,
+       .close = gmidi_out_close,
+       .trigger = gmidi_out_trigger
+};
+
+/* register as a sound "card" */
+static int gmidi_register_card(struct gmidi_device *dev)
+{
+       struct snd_card *card;
+       struct snd_rawmidi *rmidi;
+       int err;
+       int out_ports = 1;
+       int in_ports = 1;
+       static struct snd_device_ops ops = {
+               .dev_free = gmidi_snd_free,
+       };
+
+       card = snd_card_new(index, id, THIS_MODULE, 0);
+       if (!card) {
+               ERROR(dev, "snd_card_new failed\n");
+               err = -ENOMEM;
+               goto fail;
+       }
+       dev->card = card;
+
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops);
+       if (err < 0) {
+               ERROR(dev, "snd_device_new failed: error %d\n", err);
+               goto fail;
+       }
+
+       strcpy(card->driver, longname);
+       strcpy(card->longname, longname);
+       strcpy(card->shortname, shortname);
+
+       /* Set up rawmidi */
+       dev->in_port.dev = dev;
+       dev->in_port.active = 0;
+       snd_component_add(card, "MIDI");
+       err = snd_rawmidi_new(card, "USB MIDI Gadget", 0,
+                             out_ports, in_ports, &rmidi);
+       if (err < 0) {
+               ERROR(dev, "snd_rawmidi_new failed: error %d\n", err);
+               goto fail;
+       }
+       dev->rmidi = rmidi;
+       strcpy(rmidi->name, card->shortname);
+       rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                           SNDRV_RAWMIDI_INFO_INPUT |
+                           SNDRV_RAWMIDI_INFO_DUPLEX;
+       rmidi->private_data = dev;
+
+       /* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
+          It's an upside-down world being a gadget. */
+       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops);
+       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops);
+
+       snd_card_set_dev(card, &dev->gadget->dev);
+
+       /* register it - we're ready to go */
+       err = snd_card_register(card);
+       if (err < 0) {
+               ERROR(dev, "snd_card_register failed\n");
+               goto fail;
+       }
+
+       VDBG(dev, "gmidi_register_card finished ok\n");
+       return 0;
+
+fail:
+       if (dev->card) {
+               snd_card_free(dev->card);
+               dev->card = NULL;
+       }
+       return err;
+}
+
+/*
+ * Creates an output endpoint, and initializes output ports.
+ */
+static int __devinit gmidi_bind(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev;
+       struct usb_ep *in_ep, *out_ep;
+       int gcnum, err = 0;
+
+       /* support optional vendor/distro customization */
+       if (idVendor) {
+               if (!idProduct) {
+                       printk(KERN_ERR "idVendor needs idProduct!\n");
+                       return -ENODEV;
+               }
+               device_desc.idVendor = cpu_to_le16(idVendor);
+               device_desc.idProduct = cpu_to_le16(idProduct);
+               if (bcdDevice) {
+                       device_desc.bcdDevice = cpu_to_le16(bcdDevice);
+               }
+       }
+       if (iManufacturer) {
+               strlcpy(manufacturer, iManufacturer, sizeof(manufacturer));
+       } else {
+               snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+                       system_utsname.sysname, system_utsname.release,
+                       gadget->name);
+       }
+       if (iProduct) {
+               strlcpy(product_desc, iProduct, sizeof(product_desc));
+       }
+       if (iSerialNumber) {
+               device_desc.iSerialNumber = STRING_SERIAL,
+               strlcpy(serial_number, iSerialNumber, sizeof(serial_number));
+       }
+
+       /* Bulk-only drivers like this one SHOULD be able to
+        * autoconfigure on any sane usb controller driver,
+        * but there may also be important quirks to address.
+        */
+       usb_ep_autoconfig_reset(gadget);
+       in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);
+       if (!in_ep) {
+autoconf_fail:
+               printk(KERN_ERR "%s: can't autoconfigure on %s\n",
+                       shortname, gadget->name);
+               return -ENODEV;
+       }
+       EP_IN_NAME = in_ep->name;
+       in_ep->driver_data = in_ep;     /* claim */
+
+       out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc);
+       if (!out_ep) {
+               goto autoconf_fail;
+       }
+       EP_OUT_NAME = out_ep->name;
+       out_ep->driver_data = out_ep;   /* claim */
+
+       gcnum = usb_gadget_controller_number(gadget);
+       if (gcnum >= 0) {
+               device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+       } else {
+               /* gmidi is so simple (no altsettings) that
+                * it SHOULD NOT have problems with bulk-capable hardware.
+                * so warn about unrecognized controllers, don't panic.
+                */
+               printk(KERN_WARNING "%s: controller '%s' not recognized\n",
+                       shortname, gadget->name);
+               device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+       }
+
+
+       /* ok, we made sense of the hardware ... */
+       dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+       if (!dev) {
+               return -ENOMEM;
+       }
+       spin_lock_init(&dev->lock);
+       dev->gadget = gadget;
+       dev->in_ep = in_ep;
+       dev->out_ep = out_ep;
+       set_gadget_data(gadget, dev);
+       tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
+
+       /* preallocate control response and buffer */
+       dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+       if (!dev->req) {
+               err = -ENOMEM;
+               goto fail;
+       }
+       dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
+                               &dev->req->dma, GFP_KERNEL);
+       if (!dev->req->buf) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       dev->req->complete = gmidi_setup_complete;
+
+       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+
+       gadget->ep0->driver_data = dev;
+
+       INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
+       INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
+               EP_OUT_NAME, EP_IN_NAME);
+
+       /* register as an ALSA sound card */
+       err = gmidi_register_card(dev);
+       if (err < 0) {
+               goto fail;
+       }
+
+       VDBG(dev, "gmidi_bind finished ok\n");
+       return 0;
+
+fail:
+       gmidi_unbind(gadget);
+       return err;
+}
+
+
+static void gmidi_suspend(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+
+       if (gadget->speed == USB_SPEED_UNKNOWN) {
+               return;
+       }
+
+       DBG(dev, "suspend\n");
+}
+
+static void gmidi_resume(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+
+       DBG(dev, "resume\n");
+}
+
+
+static struct usb_gadget_driver gmidi_driver = {
+       .speed          = USB_SPEED_FULL,
+       .function       = (char *)longname,
+       .bind           = gmidi_bind,
+       .unbind         = __exit_p(gmidi_unbind),
+
+       .setup          = gmidi_setup,
+       .disconnect     = gmidi_disconnect,
+
+       .suspend        = gmidi_suspend,
+       .resume         = gmidi_resume,
+
+       .driver         = {
+               .name           = (char *)shortname,
+               .owner          = THIS_MODULE,
+       },
+};
+
+static int __init gmidi_init(void)
+{
+       return usb_gadget_register_driver(&gmidi_driver);
+}
+module_init(gmidi_init);
+
+static void __exit gmidi_cleanup(void)
+{
+       usb_gadget_unregister_driver(&gmidi_driver);
+}
+module_exit(gmidi_cleanup);
+
index 3bdc5e3ba2346a588d518339de3bc31f5834520d..86924f9cdd7e0c5e57845e4f4a41d63a188414b2 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/compiler.h>
 #include <asm/uaccess.h>
 #include <linux/slab.h>
+#include <linux/poll.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -222,7 +223,6 @@ static void put_ep (struct ep_data *data)
        /* needs no more cleanup */
        BUG_ON (!list_empty (&data->epfiles));
        BUG_ON (waitqueue_active (&data->wait));
-       BUG_ON (down_trylock (&data->lock) != 0);
        kfree (data);
 }
 
@@ -342,7 +342,7 @@ fail:
 static ssize_t
 ep_io (struct ep_data *epdata, void *buf, unsigned len)
 {
-       DECLARE_COMPLETION (done);
+       DECLARE_COMPLETION_ONSTACK (done);
        int value;
 
        spin_lock_irq (&epdata->dev->lock);
@@ -477,6 +477,10 @@ static int
 ep_release (struct inode *inode, struct file *fd)
 {
        struct ep_data          *data = fd->private_data;
+       int value;
+
+       if ((value = down_interruptible(&data->lock)) < 0)
+               return value;
 
        /* clean up if this can be reopened */
        if (data->state != STATE_EP_UNBOUND) {
@@ -485,6 +489,7 @@ ep_release (struct inode *inode, struct file *fd)
                data->hs_desc.bDescriptorType = 0;
                usb_ep_disable(data->ep);
        }
+       up (&data->lock);
        put_ep (data);
        return 0;
 }
@@ -528,7 +533,8 @@ struct kiocb_priv {
        struct usb_request      *req;
        struct ep_data          *epdata;
        void                    *buf;
-       char __user             *ubuf;          /* NULL for writes */
+       const struct iovec      *iv;
+       unsigned long           nr_segs;
        unsigned                actual;
 };
 
@@ -556,17 +562,32 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 static ssize_t ep_aio_read_retry(struct kiocb *iocb)
 {
        struct kiocb_priv       *priv = iocb->private;
-       ssize_t                 status = priv->actual;
-
-       /* we "retry" to get the right mm context for this: */
-       status = copy_to_user(priv->ubuf, priv->buf, priv->actual);
-       if (unlikely(0 != status))
-               status = -EFAULT;
-       else
-               status = priv->actual;
-       kfree(priv->buf);
-       kfree(priv);
-       return status;
+       ssize_t                 len, total;
+       int                     i;
+
+       /* we "retry" to get the right mm context for this: */
+
+       /* copy stuff into user buffers */
+       total = priv->actual;
+       len = 0;
+       for (i=0; i < priv->nr_segs; i++) {
+               ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
+
+               if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
+                       if (len == 0)
+                               len = -EFAULT;
+                       break;
+               }
+
+               total -= this;
+               len += this;
+               if (total == 0)
+                       break;
+       }
+       kfree(priv->buf);
+       kfree(priv);
+       aio_put_req(iocb);
+       return len;
 }
 
 static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
@@ -579,7 +600,7 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
        spin_lock(&epdata->dev->lock);
        priv->req = NULL;
        priv->epdata = NULL;
-       if (priv->ubuf == NULL
+       if (priv->iv == NULL
                        || unlikely(req->actual == 0)
                        || unlikely(kiocbIsCancelled(iocb))) {
                kfree(req->buf);
@@ -614,7 +635,8 @@ ep_aio_rwtail(
        char            *buf,
        size_t          len,
        struct ep_data  *epdata,
-       char __user     *ubuf
+       const struct iovec *iv,
+       unsigned long   nr_segs
 )
 {
        struct kiocb_priv       *priv;
@@ -629,7 +651,8 @@ fail:
                return value;
        }
        iocb->private = priv;
-       priv->ubuf = ubuf;
+       priv->iv = iv;
+       priv->nr_segs = nr_segs;
 
        value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
        if (unlikely(value < 0)) {
@@ -669,47 +692,59 @@ fail:
                kfree(priv);
                put_ep(epdata);
        } else
-               value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED);
+               value = (iv ? -EIOCBRETRY : -EIOCBQUEUED);
        return value;
 }
 
 static ssize_t
-ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
+ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t o)
 {
        struct ep_data          *epdata = iocb->ki_filp->private_data;
        char                    *buf;
 
        if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN))
                return -EINVAL;
-       buf = kmalloc(len, GFP_KERNEL);
+
+       buf = kmalloc(iocb->ki_left, GFP_KERNEL);
        if (unlikely(!buf))
                return -ENOMEM;
+
        iocb->ki_retry = ep_aio_read_retry;
-       return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
+       return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
 }
 
 static ssize_t
-ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
+ep_aio_write(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t o)
 {
        struct ep_data          *epdata = iocb->ki_filp->private_data;
        char                    *buf;
+       size_t                  len = 0;
+       int                     i = 0;
 
        if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN)))
                return -EINVAL;
-       buf = kmalloc(len, GFP_KERNEL);
+
+       buf = kmalloc(iocb->ki_left, GFP_KERNEL);
        if (unlikely(!buf))
                return -ENOMEM;
-       if (unlikely(copy_from_user(buf, ubuf, len) != 0)) {
-               kfree(buf);
-               return -EFAULT;
+
+       for (i=0; i < nr_segs; i++) {
+               if (unlikely(copy_from_user(&buf[len], iov[i].iov_base,
+                               iov[i].iov_len) != 0)) {
+                       kfree(buf);
+                       return -EFAULT;
+               }
+               len += iov[i].iov_len;
        }
-       return ep_aio_rwtail(iocb, buf, len, epdata, NULL);
+       return ep_aio_rwtail(iocb, buf, len, epdata, NULL, 0);
 }
 
 /*----------------------------------------------------------------------*/
 
 /* used after endpoint configuration */
-static struct file_operations ep_io_operations = {
+static const struct file_operations ep_io_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
@@ -741,7 +776,7 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        struct ep_data          *data = fd->private_data;
        struct usb_ep           *ep;
        u32                     tag;
-       int                     value;
+       int                     value, length = len;
 
        if ((value = down_interruptible (&data->lock)) < 0)
                return value;
@@ -792,7 +827,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                        goto fail0;
                }
        }
-       value = len;
 
        spin_lock_irq (&data->dev->lock);
        if (data->dev->state == STATE_DEV_UNBOUND) {
@@ -822,8 +856,10 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                                data->name);
                data->state = STATE_EP_DEFER_ENABLE;
        }
-       if (value == 0)
+       if (value == 0) {
                fd->f_op = &ep_io_operations;
+               value = length;
+       }
 gone:
        spin_unlock_irq (&data->dev->lock);
        if (value < 0) {
@@ -844,7 +880,7 @@ fail1:
 static int
 ep_open (struct inode *inode, struct file *fd)
 {
-       struct ep_data          *data = inode->u.generic_ip;
+       struct ep_data          *data = inode->i_private;
        int                     value = -EBUSY;
 
        if (down_interruptible (&data->lock) != 0)
@@ -867,7 +903,7 @@ ep_open (struct inode *inode, struct file *fd)
 }
 
 /* used before endpoint configuration */
-static struct file_operations ep_config_operations = {
+static const struct file_operations ep_config_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
@@ -1009,7 +1045,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                        else {
                                len = min (len, (size_t)dev->req->actual);
 // FIXME don't call this with the spinlock held ...
-                               if (copy_to_user (buf, &dev->req->buf, len))
+                               if (copy_to_user (buf, dev->req->buf, len))
                                        retval = -EFAULT;
                                clean_req (dev->gadget->ep0, dev->req);
                                /* NOTE userspace can't yet choose to stall */
@@ -1229,6 +1265,35 @@ dev_release (struct inode *inode, struct file *fd)
        return 0;
 }
 
+static unsigned int
+ep0_poll (struct file *fd, poll_table *wait)
+{
+       struct dev_data         *dev = fd->private_data;
+       int                     mask = 0;
+
+       poll_wait(fd, &dev->wait, wait);
+
+       spin_lock_irq (&dev->lock);
+
+       /* report fd mode change before acting on it */
+       if (dev->setup_abort) {
+               dev->setup_abort = 0;
+               mask = POLLHUP;
+               goto out;
+       }
+
+       if (dev->state == STATE_SETUP) {
+               if (dev->setup_in || dev->setup_can_stall)
+                       mask = POLLOUT;
+       } else {
+               if (dev->ev_next != 0)
+                       mask = POLLIN;
+       }
+out:
+       spin_unlock_irq(&dev->lock);
+       return mask;
+}
+
 static int dev_ioctl (struct inode *inode, struct file *fd,
                unsigned code, unsigned long value)
 {
@@ -1241,14 +1306,14 @@ static int dev_ioctl (struct inode *inode, struct file *fd,
 }
 
 /* used after device configuration */
-static struct file_operations ep0_io_operations = {
+static const struct file_operations ep0_io_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
        .read =         ep0_read,
        .write =        ep0_write,
        .fasync =       ep0_fasync,
-       // .poll =      ep0_poll,
+       .poll =         ep0_poll,
        .ioctl =        dev_ioctl,
        .release =      dev_release,
 };
@@ -1696,16 +1761,17 @@ gadgetfs_disconnect (struct usb_gadget *gadget)
 {
        struct dev_data         *dev = get_gadget_data (gadget);
 
+       spin_lock (&dev->lock);
        if (dev->state == STATE_UNCONNECTED) {
                DBG (dev, "already unconnected\n");
-               return;
+               goto exit;
        }
        dev->state = STATE_UNCONNECTED;
 
        INFO (dev, "disconnected\n");
-       spin_lock (&dev->lock);
        next_event (dev, GADGETFS_DISCONNECT);
        ep0_readable (dev);
+exit:
        spin_unlock (&dev->lock);
 }
 
@@ -1909,7 +1975,7 @@ fail:
 static int
 dev_open (struct inode *inode, struct file *fd)
 {
-       struct dev_data         *dev = inode->u.generic_ip;
+       struct dev_data         *dev = inode->i_private;
        int                     value = -EBUSY;
 
        if (dev->state == STATE_DEV_DISABLED) {
@@ -1922,7 +1988,7 @@ dev_open (struct inode *inode, struct file *fd)
        return value;
 }
 
-static struct file_operations dev_init_operations = {
+static const struct file_operations dev_init_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
@@ -1966,11 +2032,10 @@ gadgetfs_make_inode (struct super_block *sb,
                inode->i_mode = mode;
                inode->i_uid = default_uid;
                inode->i_gid = default_gid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime
                                = CURRENT_TIME;
-               inode->u.generic_ip = data;
+               inode->i_private = data;
                inode->i_fop = fops;
        }
        return inode;
index 09243239d948cf4c034515c89838b41b769b7817..3bda37f9a35f7d54ebf254de672bc44d44e1027d 100644 (file)
@@ -2,7 +2,7 @@
  * Driver for the PLX NET2280 USB device controller.
  * Specs and errata are available from <http://www.plxtech.com>.
  *
- * PLX Technology Inc. (formerly NetChip Technology) supported the 
+ * PLX Technology Inc. (formerly NetChip Technology) supported the
  * development of this driver.
  *
  *
@@ -26,7 +26,8 @@
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
+ *     with 2282 chip
  *
  * 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
@@ -85,7 +86,7 @@ static const char driver_name [] = "net2280";
 static const char driver_desc [] = DRIVER_DESC;
 
 static const char ep0name [] = "ep0";
-static const char *ep_name [] = {
+static const char *const ep_name [] = {
        ep0name,
        "ep-a", "ep-b", "ep-c", "ep-d",
        "ep-e", "ep-f",
@@ -225,7 +226,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
        if (!ep->is_in)
                writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
        else if (dev->pdev->device != 0x2280) {
-               /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
+               /* Added for 2282, Don't use nak packets on an in endpoint,
+                * this was ignored on 2280
+                */
                writel ((1 << CLEAR_NAK_OUT_PACKETS)
                        | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
        }
@@ -288,7 +291,7 @@ static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
        return -ETIMEDOUT;
 }
 
-static struct usb_ep_ops net2280_ep_ops;
+static const struct usb_ep_ops net2280_ep_ops;
 
 static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
 {
@@ -449,34 +452,15 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
 
 /*-------------------------------------------------------------------------*/
 
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
+/*
+ * dma-coherent memory allocation (for dma-capable endpoints)
  *
- * other platforms need more care, with 2.5 having a moderately general
- * solution (which falls down for allocations smaller than one page)
- * that improves significantly on the 2.4 PCI allocators by removing
- * the restriction that memory never be freed in_interrupt().
+ * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
+ * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
+ * respect to calls with irqs disabled:  alloc is safe, free is not.
+ * We currently work around (b), but not (a).
  */
-#if    defined(CONFIG_X86)
-#define USE_KMALLOC
-
-#elif  defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
 
-#elif  defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
-#define USE_KMALLOC
-
-/* FIXME there are other cases, including an x86-64 one ...  */
-#endif
-
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
 static void *
 net2280_alloc_buffer (
        struct usb_ep           *_ep,
@@ -493,43 +477,71 @@ net2280_alloc_buffer (
                return NULL;
        *dma = DMA_ADDR_INVALID;
 
-#if    defined(USE_KMALLOC)
-       retval = kmalloc(bytes, gfp_flags);
-       if (retval)
-               *dma = virt_to_phys(retval);
-#else
-       if (ep->dma) {
-               /* the main problem with this call is that it wastes memory
-                * on typical 1/N page allocations: it allocates 1-N pages.
-                */
-#warning Using dma_alloc_coherent even with buffers smaller than a page.
+       if (ep->dma)
                retval = dma_alloc_coherent(&ep->dev->pdev->dev,
                                bytes, dma, gfp_flags);
-       else
+       else
                retval = kmalloc(bytes, gfp_flags);
-#endif
        return retval;
 }
 
+static DEFINE_SPINLOCK(buflock);
+static LIST_HEAD(buffers);
+
+struct free_record {
+       struct list_head        list;
+       struct device           *dev;
+       unsigned                bytes;
+       dma_addr_t              dma;
+};
+
+static void do_free(unsigned long ignored)
+{
+       spin_lock_irq(&buflock);
+       while (!list_empty(&buffers)) {
+               struct free_record      *buf;
+
+               buf = list_entry(buffers.next, struct free_record, list);
+               list_del(&buf->list);
+               spin_unlock_irq(&buflock);
+
+               dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
+
+               spin_lock_irq(&buflock);
+       }
+       spin_unlock_irq(&buflock);
+}
+
+static DECLARE_TASKLET(deferred_free, do_free, 0);
+
 static void
 net2280_free_buffer (
        struct usb_ep *_ep,
-       void *buf,
+       void *address,
        dma_addr_t dma,
        unsigned bytes
 ) {
        /* free memory into the right allocator */
-#ifndef        USE_KMALLOC
        if (dma != DMA_ADDR_INVALID) {
                struct net2280_ep       *ep;
+               struct free_record      *buf = address;
+               unsigned long           flags;
 
                ep = container_of(_ep, struct net2280_ep, ep);
                if (!_ep)
                        return;
-               dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
+
+               ep = container_of (_ep, struct net2280_ep, ep);
+               buf->dev = &ep->dev->pdev->dev;
+               buf->bytes = bytes;
+               buf->dma = dma;
+
+               spin_lock_irqsave(&buflock, flags);
+               list_add_tail(&buf->list, &buffers);
+               tasklet_schedule(&deferred_free);
+               spin_unlock_irqrestore(&buflock, flags);
        } else
-#endif
-               kfree (buf);
+               kfree (address);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -737,7 +749,8 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
         */
        if (ep->is_in)
                dmacount |= (1 << DMA_DIRECTION);
-       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
+       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
+                       || ep->dev->pdev->device != 0x2280)
                dmacount |= (1 << END_OF_CHAIN);
 
        req->valid = valid;
@@ -812,7 +825,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
 
        /* previous OUT packet might have been short */
        if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-                               & (1 << NAK_OUT_PACKETS)) != 0) {
+                               & (1 << NAK_OUT_PACKETS)) != 0) {
                writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
                        &ep->regs->ep_stat);
 
@@ -1373,7 +1386,7 @@ net2280_fifo_flush (struct usb_ep *_ep)
        (void) readl (&ep->regs->ep_rsp);
 }
 
-static struct usb_ep_ops net2280_ep_ops = {
+static const struct usb_ep_ops net2280_ep_ops = {
        .enable         = net2280_enable,
        .disable        = net2280_disable,
 
@@ -1631,7 +1644,7 @@ show_registers (struct device *_dev, struct device_attribute *attr, char *buf)
        }
 
        /* Indexed Registers */
-               // none yet 
+               // none yet
 
        /* Statistics */
        t = scnprintf (next, size, "\nirqs:  ");
@@ -1691,11 +1704,11 @@ show_queues (struct device *_dev, struct device_attribute *attr, char *buf)
                                ({ char *val;
                                 switch (d->bmAttributes & 0x03) {
                                 case USB_ENDPOINT_XFER_BULK:
-                                       val = "bulk"; break;
+                                       val = "bulk"; break;
                                 case USB_ENDPOINT_XFER_INT:
-                                       val = "intr"; break;
+                                       val = "intr"; break;
                                 default:
-                                       val = "iso"; break;
+                                       val = "iso"; break;
                                 }; val; }),
                                le16_to_cpu (d->wMaxPacketSize) & 0x1fff,
                                ep->dma ? "dma" : "pio", ep->fifo_size
@@ -1808,8 +1821,8 @@ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
  * net2280_set_fifo_mode - change allocation of fifo buffers
  * @gadget: access to the net2280 device that will be updated
  * @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
- *     1 for two 2kB buffers (ep-a and ep-b only);
- *     2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
+ *     1 for two 2kB buffers (ep-a and ep-b only);
+ *     2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
  *
  * returns zero on success, else negative errno.  when this succeeds,
  * the contents of gadget->ep_list may have changed.
@@ -2241,7 +2254,8 @@ static void handle_ep_small (struct net2280_ep *ep)
                                req->td->dmacount = 0;
                                t = readl (&ep->regs->ep_avail);
                                dma_done (ep, req, count,
-                                       (ep->out_overflow || t) ? -EOVERFLOW : 0);
+                                       (ep->out_overflow || t)
+                                               ? -EOVERFLOW : 0);
                        }
 
                        /* also flush to prevent erratum 0106 trouble */
@@ -2411,7 +2425,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        , &ep->regs->ep_stat);
                u.raw [0] = readl (&dev->usb->setup0123);
                u.raw [1] = readl (&dev->usb->setup4567);
-               
+
                cpu_to_le32s (&u.raw [0]);
                cpu_to_le32s (&u.raw [1]);
 
@@ -2578,14 +2592,16 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 
        /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
         * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
-        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 
+        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
         * only indicates a change in the reset state).
         */
        if (stat & tmp) {
                writel (tmp, &dev->regs->irqstat1);
-               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 
-                               ((readl (&dev->usb->usbstat) & mask) == 0))
-                               || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 
+               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT))
+                                       && ((readl (&dev->usb->usbstat) & mask)
+                                                       == 0))
+                               || ((readl (&dev->usb->usbctl)
+                                       & (1 << VBUS_PIN)) == 0)
                            ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
                        DEBUG (dev, "disconnect %s\n",
                                        dev->driver->driver.name);
@@ -2852,7 +2868,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* now all the pci goodies ... */
        if (pci_enable_device (pdev) < 0) {
-               retval = -ENODEV;
+               retval = -ENODEV;
                goto done;
        }
        dev->enabled = 1;
@@ -2870,6 +2886,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
        }
        dev->region = 1;
 
+       /* FIXME provide firmware download interface to put
+        * 8051 code into the chip, e.g. to turn on PCI PM.
+        */
+
        base = ioremap_nocache (resource, len);
        if (base == NULL) {
                DEBUG (dev, "can't map memory\n");
@@ -2984,16 +3004,16 @@ static void net2280_shutdown (struct pci_dev *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static struct pci_device_id pci_ids [] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
+static const struct pci_device_id pci_ids [] = { {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
        .vendor =       0x17cc,
        .device =       0x2280,
        .subvendor =    PCI_ANY_ID,
        .subdevice =    PCI_ANY_ID,
 }, {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
        .vendor =       0x17cc,
        .device =       0x2282,
        .subvendor =    PCI_ANY_ID,
index 2de9748ee6734c7763a2e4618f9769c91d36bce2..8c18df86983330a8e29118546a680d208a90d74d 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/platform_device.h>
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/dma-mapping.h>
 
 #include <asm/byteorder.h>
@@ -2437,7 +2437,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
        return single_open(file, proc_udc_show, NULL);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -2869,7 +2869,7 @@ cleanup0:
 
 static int __exit omap_udc_remove(struct platform_device *pdev)
 {
-       DECLARE_COMPLETION(done);
+       DECLARE_COMPLETION_ONSTACK(done);
 
        if (!udc)
                return -ENODEV;
index fff027d30a09d2e564f842baa4eba11a90a80ad2..f1adcf8b202307f4d6bf0c1b4d373541ccc4ab14 100644 (file)
@@ -150,6 +150,39 @@ MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
 static void pxa2xx_ep_fifo_flush (struct usb_ep *ep);
 static void nuke (struct pxa2xx_ep *, int status);
 
+/* one GPIO should be used to detect VBUS from the host */
+static int is_vbus_present(void)
+{
+       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
+
+       if (mach->gpio_vbus)
+               return pxa_gpio_get(mach->gpio_vbus);
+       if (mach->udc_is_connected)
+               return mach->udc_is_connected();
+       return 1;
+}
+
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+static void pullup_off(void)
+{
+       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
+
+       if (mach->gpio_pullup)
+               pxa_gpio_set(mach->gpio_pullup, 0);
+       else if (mach->udc_command)
+               mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+static void pullup_on(void)
+{
+       struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
+
+       if (mach->gpio_pullup)
+               pxa_gpio_set(mach->gpio_pullup, 1);
+       else if (mach->udc_command)
+               mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
 static void pio_irq_enable(int bEndpointAddress)
 {
         bEndpointAddress &= 0xf;
@@ -1721,6 +1754,16 @@ lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
 
 #endif
 
+static irqreturn_t
+udc_vbus_irq(int irq, void *_dev, struct pt_regs *r)
+{
+       struct pxa2xx_udc       *dev = _dev;
+       int                     vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+
+       pxa2xx_udc_vbus_session(&dev->gadget, vbus);
+       return IRQ_HANDLED;
+}
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -2438,7 +2481,7 @@ static struct pxa2xx_udc memory = {
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
        struct pxa2xx_udc *dev = &memory;
-       int retval, out_dma = 1;
+       int retval, out_dma = 1, vbus_irq;
        u32 chiprev;
 
        /* insist on Intel/ARM/XScale */
@@ -2502,6 +2545,16 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        /* other non-static parts of init */
        dev->dev = &pdev->dev;
        dev->mach = pdev->dev.platform_data;
+       if (dev->mach->gpio_vbus) {
+               vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR);
+               pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR)
+                               | GPIO_IN);
+               set_irq_type(vbus_irq, IRQT_BOTHEDGE);
+       } else
+               vbus_irq = 0;
+       if (dev->mach->gpio_pullup)
+               pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR)
+                               | GPIO_OUT | GPIO_DFLT_LOW);
 
        init_timer(&dev->timer);
        dev->timer.function = udc_watchdog;
@@ -2557,8 +2610,19 @@ lubbock_fail0:
                HEX_DISPLAY(dev->stats.irqs);
                LUB_DISC_BLNK_LED &= 0xff;
 #endif
-       }
+       } else
 #endif
+       if (vbus_irq) {
+               retval = request_irq(vbus_irq, udc_vbus_irq,
+                               SA_INTERRUPT | SA_SAMPLE_RANDOM,
+                               driver_name, dev);
+               if (retval != 0) {
+                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                               driver_name, vbus_irq, retval);
+                       free_irq(IRQ_USB, dev);
+                       return -EBUSY;
+               }
+       }
        create_proc_files();
 
        return 0;
@@ -2587,6 +2651,8 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
                free_irq(LUBBOCK_USB_IRQ, dev);
        }
 #endif
+       if (dev->mach->gpio_vbus)
+               free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev);
        platform_set_drvdata(pdev, NULL);
        the_controller = NULL;
        return 0;
index 19a883f7d1b8f610c8c9c3a0cba195aeacc88836..8e598c8bf4e388da20c6672b3a0f54a95e296e6e 100644 (file)
@@ -177,27 +177,19 @@ struct pxa2xx_udc {
 
 static struct pxa2xx_udc *the_controller;
 
-/* one GPIO should be used to detect VBUS from the host */
-static inline int is_vbus_present(void)
+static inline int pxa_gpio_get(unsigned gpio)
 {
-       if (!the_controller->mach->udc_is_connected)
-               return 1;
-       return the_controller->mach->udc_is_connected();
+       return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
 }
 
-/* one GPIO should control a D+ pullup, so host sees this device (or not) */
-static inline void pullup_off(void)
+static inline void pxa_gpio_set(unsigned gpio, int is_on)
 {
-       if (!the_controller->mach->udc_command)
-               return;
-       the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
-}
+       int mask = GPIO_bit(gpio);
 
-static inline void pullup_on(void)
-{
-       if (!the_controller->mach->udc_command)
-               return;
-       the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+       if (is_on)
+               GPSR(gpio) = mask;
+       else
+               GPCR(gpio) = mask;
 }
 
 /*-------------------------------------------------------------------------*/
index e762aa19ab0a1c9fef4a87a105b0221b95e3ddad..b893e3118e1be480e9b4d8bbd739152efd718141 100644 (file)
@@ -1120,12 +1120,15 @@ static int gs_send(struct gs_dev *dev)
 gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
                        list_del(&req_entry->re_entry);
                        req->length = len;
+                       spin_unlock_irqrestore(&dev->dev_lock, flags);
                        if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
                                printk(KERN_ERR
                                "gs_send: cannot queue read request, ret=%d\n",
                                        ret);
+                               spin_lock_irqsave(&dev->dev_lock, flags);
                                break;
                        }
+                       spin_lock_irqsave(&dev->dev_lock, flags);
                } else {
                        break;
                }
index b93d71d28db7a04a011735318973181e953eedbf..cf10cbc98f8089885ab3174ceb09e56c369aa543 100644 (file)
@@ -83,6 +83,7 @@ config USB_OHCI_HCD
        tristate "OHCI HCD support"
        depends on USB && USB_ARCH_HAS_OHCI
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
+       select I2C if ARCH_PNX4008
        ---help---
          The Open Host Controller Interface (OHCI) is a standard for accessing
          USB 1.1 host controller hardware.  It does more in hardware than Intel's
@@ -141,6 +142,34 @@ config USB_UHCI_HCD
          To compile this driver as a module, choose M here: the
          module will be called uhci-hcd.
 
+config USB_U132_HCD
+       tristate "Elan U132 Adapter Host Controller"
+       depends on USB && USB_FTDI_ELAN
+       default M
+       help
+         The U132 adapter is a USB to CardBus adapter specifically designed
+         for PC cards that contain an OHCI host controller. Typical PC cards
+         are the Orange Mobile 3G Option GlobeTrotter Fusion card. The U132
+         adapter will *NOT* work with PC cards that do not contain an OHCI
+         controller.
+
+         For those PC cards that contain multiple OHCI controllers only ther
+         first one is used.
+
+         The driver consists of two modules, the "ftdi-elan" module is a
+         USB client driver that interfaces to the FTDI chip within ELAN's
+         USB-to-PCMCIA adapter, and this "u132-hcd" module is a USB host
+         controller driver that talks to the OHCI controller within the
+         CardBus cards that are inserted in the U132 adapter.
+
+         This driver has been tested with a CardBus OHCI USB adapter, and
+         worked with a USB PEN Drive inserted into the first USB port of
+         the PCCARD. A rather pointless thing to do, but useful for testing.
+
+         It is safe to say M here.
+
+         See also <http://www.elandigitalsystems.com/support/ufaq/u132linux.php>
+
 config USB_SL811_HCD
        tristate "SL811HS HCD support"
        depends on USB
index e3020f4b17be9a4ea8572768d234ac9301da33f3..a2e58c86849fc597972e4cb675eb9a813dff12f8 100644 (file)
@@ -14,4 +14,5 @@ obj-$(CONFIG_USB_OHCI_HCD)    += ohci-hcd.o
 obj-$(CONFIG_USB_UHCI_HCD)     += uhci-hcd.o
 obj-$(CONFIG_USB_SL811_HCD)    += sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)     += sl811_cs.o
+obj-$(CONFIG_USB_U132_HCD)     += u132-hcd.o
 obj-$(CONFIG_ETRAX_ARCH_V10)   += hc_crisv10.o
index 26ed757d22a66139ea500eaddc1130f4eeb2baf4..5d1b12aad7766acc39d338c9200dfc4ca6b86601 100644 (file)
@@ -200,6 +200,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
        .reset = ehci_init,
        .start = ehci_run,
        .stop = ehci_stop,
+       .shutdown = ehci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -268,6 +269,7 @@ MODULE_ALIAS("au1xxx-ehci");
 static struct platform_driver ehci_hcd_au1xxx_driver = {
        .probe = ehci_hcd_au1xxx_drv_probe,
        .remove = ehci_hcd_au1xxx_drv_remove,
+       .shutdown = usb_hcd_platform_shutdown,
        /*.suspend      = ehci_hcd_au1xxx_drv_suspend, */
        /*.resume       = ehci_hcd_au1xxx_drv_resume, */
        .driver = {
index 65ac9fef3a7c1dfc382ef2c8aaf5a089fdb7a7ad..23b95b2bfe1572e7788a6422e4a09f3a60261d2e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001-2002 by David Brownell
- * 
+ *
  * 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
@@ -65,7 +65,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
                for (i = 0; i < HCS_N_PORTS (params); i++) {
                        // FIXME MIPS won't readb() ...
                        byte = readb (&ehci->caps->portroute[(i>>1)]);
-                       sprintf(tmp, "%d ", 
+                       sprintf(tmp, "%d ",
                                ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
                        strcat(buf, tmp);
                }
@@ -141,12 +141,12 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 }
 
 static void __attribute__((__unused__))
-dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) 
+dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
        ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
                label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
        ehci_dbg (ehci,
-               "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", 
+               "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
                le32_to_cpu(itd->hw_transaction[0]),
                le32_to_cpu(itd->hw_transaction[1]),
                le32_to_cpu(itd->hw_transaction[2]),
@@ -156,7 +156,7 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
                le32_to_cpu(itd->hw_transaction[6]),
                le32_to_cpu(itd->hw_transaction[7]));
        ehci_dbg (ehci,
-               "  buf:   %08x %08x %08x %08x %08x %08x %08x\n", 
+               "  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
                le32_to_cpu(itd->hw_bufp[0]),
                le32_to_cpu(itd->hw_bufp[1]),
                le32_to_cpu(itd->hw_bufp[2]),
@@ -171,12 +171,12 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 }
 
 static void __attribute__((__unused__))
-dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) 
+dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
        ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
                label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
        ehci_dbg (ehci,
-               "  addr %08x sched %04x result %08x buf %08x %08x\n", 
+               "  addr %08x sched %04x result %08x buf %08x %08x\n",
                le32_to_cpu(sitd->hw_fullspeed_ep),
                le32_to_cpu(sitd->hw_uframe),
                le32_to_cpu(sitd->hw_results),
@@ -451,7 +451,7 @@ show_async (struct class_device *class_dev, char *buf)
        *buf = 0;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ehci = hcd_to_ehci (hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -497,7 +497,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        seen_count = 0;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ehci = hcd_to_ehci (hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -634,7 +634,7 @@ show_registers (struct class_device *class_dev, char *buf)
        static char             label [] = "";
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ehci = hcd_to_ehci (hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -754,9 +754,7 @@ show_registers (struct class_device *class_dev, char *buf)
        }
 
        if (ehci->reclaim) {
-               temp = scnprintf (next, size, "reclaim qh %p%s\n",
-                               ehci->reclaim,
-                               ehci->reclaim_ready ? " ready" : "");
+               temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim);
                size -= temp;
                next += temp;
        }
@@ -785,10 +783,11 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
        struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
+       int retval;
 
-       class_device_create_file(cldev, &class_device_attr_async);
-       class_device_create_file(cldev, &class_device_attr_periodic);
-       class_device_create_file(cldev, &class_device_attr_registers);
+       retval = class_device_create_file(cldev, &class_device_attr_async);
+       retval = class_device_create_file(cldev, &class_device_attr_periodic);
+       retval = class_device_create_file(cldev, &class_device_attr_registers);
 }
 
 static inline void remove_debug_files (struct ehci_hcd *ehci)
index d030516edfb9f6077003d7b553ee3d52a0805580..1a915e982c1c49a9c671d2769f23fad04f6909a1 100644 (file)
@@ -285,6 +285,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
        .resume = ehci_bus_resume,
 #endif
        .stop = ehci_stop,
+       .shutdown = ehci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -329,6 +330,7 @@ MODULE_ALIAS("fsl-ehci");
 static struct platform_driver ehci_fsl_driver = {
        .probe = ehci_fsl_drv_probe,
        .remove = ehci_fsl_drv_remove,
+       .shutdown = usb_hcd_platform_shutdown,
        .driver = {
                   .name = "fsl-ehci",
                   },
index d63177a8eaea330b41e6465f740efa4d7b3ba3c7..5ac918591131a5a11e08d75bc87a7d1d40363aec 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2000-2004 by David Brownell
- * 
+ *
  * 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
@@ -70,7 +70,7 @@
  * 2002-08-06  Handling for bulk and interrupt transfers is mostly shared;
  *     only scheduling is different, no arbitrary limitations.
  * 2002-07-25  Sanity check PCI reads, mostly for better cardbus support,
- *     clean up HC run state handshaking.
+ *     clean up HC run state handshaking.
  * 2002-05-24  Preliminary FS/LS interrupts, using scheduling shortcuts
  * 2002-05-11  Clear TT errors for FS/LS ctrl/bulk.  Fill in some other
  *     missing pieces:  enabling 64bit dma, handoff from BIOS/SMM.
@@ -111,7 +111,7 @@ static const char   hcd_name [] = "ehci_hcd";
 #define        EHCI_TUNE_MULT_TT       1
 #define        EHCI_TUNE_FLS           2       /* (small) 256 frame schedule */
 
-#define EHCI_IAA_JIFFIES       (HZ/100)        /* arbitrary; ~10 msec */
+#define EHCI_IAA_MSECS         10              /* arbitrary */
 #define EHCI_IO_JIFFIES                (HZ/10)         /* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES     (HZ/20)         /* async idle timeout */
 #define EHCI_SHRINK_JIFFIES    (HZ/200)        /* async qh unlink delay */
@@ -254,6 +254,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
 
 /*-------------------------------------------------------------------------*/
 
+static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs);
 static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
 
 #include "ehci-hub.c"
@@ -263,28 +264,39 @@ static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_watchdog (unsigned long param)
+static void ehci_iaa_watchdog (unsigned long param)
 {
        struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
        unsigned long           flags;
+       u32                     status;
 
        spin_lock_irqsave (&ehci->lock, flags);
+       WARN_ON(!ehci->reclaim);
 
-       /* lost IAA irqs wedge things badly; seen with a vt8235 */
+       /* lost IAA irqs wedge things badly; seen first with a vt8235 */
        if (ehci->reclaim) {
-               u32             status = readl (&ehci->regs->status);
-
+               status = readl (&ehci->regs->status);
                if (status & STS_IAA) {
                        ehci_vdbg (ehci, "lost IAA\n");
                        COUNT (ehci->stats.lost_iaa);
                        writel (STS_IAA, &ehci->regs->status);
-                       ehci->reclaim_ready = 1;
+                       end_unlink_async (ehci, NULL);
                }
        }
 
-       /* stop async processing after it's idled a bit */
+       spin_unlock_irqrestore (&ehci->lock, flags);
+}
+
+static void ehci_watchdog (unsigned long param)
+{
+       struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
+       unsigned long           flags;
+
+       spin_lock_irqsave (&ehci->lock, flags);
+
+       /* stop async processing after it's idled a bit */
        if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
-               start_unlink_async (ehci, ehci->async);
+               start_unlink_async (ehci, ehci->async);
 
        /* ehci could run by timer, without IRQs ... */
        ehci_work (ehci, NULL);
@@ -292,21 +304,20 @@ static void ehci_watchdog (unsigned long param)
        spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
-/* Reboot notifiers kick in for silicon on any bus (not just pci, etc).
+/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
  * This forcibly disables dma and IRQs, helping kexec and other cases
  * where the next system software may expect clean state.
  */
-static int
-ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
+static void
+ehci_shutdown (struct usb_hcd *hcd)
 {
-       struct ehci_hcd         *ehci;
+       struct ehci_hcd *ehci;
 
-       ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+       ehci = hcd_to_ehci (hcd);
        (void) ehci_halt (ehci);
 
        /* make BIOS/etc use companion controller during reboot */
        writel (0, &ehci->regs->configured_flag);
-       return 0;
 }
 
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -334,8 +345,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
 static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        timer_action_done (ehci, TIMER_IO_WATCHDOG);
-       if (ehci->reclaim_ready)
-               end_unlink_async (ehci, regs);
 
        /* another CPU may drop ehci->lock during a schedule scan while
         * it reports urb completions.  this flag guards against bogus
@@ -370,6 +379,7 @@ static void ehci_stop (struct usb_hcd *hcd)
 
        /* no more interrupts ... */
        del_timer_sync (&ehci->watchdog);
+       del_timer_sync (&ehci->iaa_watchdog);
 
        spin_lock_irq(&ehci->lock);
        if (HC_IS_RUNNING (hcd->state))
@@ -381,7 +391,6 @@ static void ehci_stop (struct usb_hcd *hcd)
 
        /* let companion controllers work when we aren't */
        writel (0, &ehci->regs->configured_flag);
-       unregister_reboot_notifier (&ehci->reboot_notifier);
 
        remove_debug_files (ehci);
 
@@ -417,6 +426,10 @@ static int ehci_init(struct usb_hcd *hcd)
        ehci->watchdog.function = ehci_watchdog;
        ehci->watchdog.data = (unsigned long) ehci;
 
+       init_timer(&ehci->iaa_watchdog);
+       ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+       ehci->iaa_watchdog.data = (unsigned long) ehci;
+
        /*
         * hw default: 1K periodic list heads, one per frame.
         * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -427,13 +440,12 @@ static int ehci_init(struct usb_hcd *hcd)
 
        /* controllers may cache some of the periodic schedule ... */
        hcc_params = readl(&ehci->caps->hcc_params);
-       if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
+       if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
                ehci->i_thresh = 8;
        else                                    // N microframes cached
                ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
        ehci->reclaim = NULL;
-       ehci->reclaim_ready = 0;
        ehci->next_uframe = -1;
 
        /*
@@ -483,9 +495,6 @@ static int ehci_init(struct usb_hcd *hcd)
        }
        ehci->command = temp;
 
-       ehci->reboot_notifier.notifier_call = ehci_reboot;
-       register_reboot_notifier(&ehci->reboot_notifier);
-
        return 0;
 }
 
@@ -499,7 +508,6 @@ static int ehci_run (struct usb_hcd *hcd)
 
        /* EHCI spec section 4.1 */
        if ((retval = ehci_reset(ehci)) != 0) {
-               unregister_reboot_notifier(&ehci->reboot_notifier);
                ehci_mem_cleanup(ehci);
                return retval;
        }
@@ -611,7 +619,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
        /* complete the unlinking of some qh [4.15.2.3] */
        if (status & STS_IAA) {
                COUNT (ehci->stats.reclaim);
-               ehci->reclaim_ready = 1;
+               end_unlink_async (ehci, regs);
                bh = 1;
        }
 
@@ -715,10 +723,14 @@ static int ehci_urb_enqueue (
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       /* if we need to use IAA and it's busy, defer */
-       if (qh->qh_state == QH_STATE_LINKED
-                       && ehci->reclaim
-                       && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+       // BUG_ON(qh->qh_state != QH_STATE_LINKED);
+
+       /* failfast */
+       if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+               end_unlink_async (ehci, NULL);
+
+       /* defer till later if busy */
+       else if (ehci->reclaim) {
                struct ehci_qh          *last;
 
                for (last = ehci->reclaim;
@@ -728,12 +740,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
                qh->qh_state = QH_STATE_UNLINK_WAIT;
                last->reclaim = qh;
 
-       /* bypass IAA if the hc can't care */
-       } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
-               end_unlink_async (ehci, NULL);
-
-       /* something else might have unlinked the qh by now */
-       if (qh->qh_state == QH_STATE_LINKED)
+       /* start IAA cycle */
+       } else
                start_unlink_async (ehci, qh);
 }
 
@@ -755,7 +763,19 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
                qh = (struct ehci_qh *) urb->hcpriv;
                if (!qh)
                        break;
-               unlink_async (ehci, qh);
+               switch (qh->qh_state) {
+               case QH_STATE_LINKED:
+               case QH_STATE_COMPLETING:
+                       unlink_async (ehci, qh);
+                       break;
+               case QH_STATE_UNLINK:
+               case QH_STATE_UNLINK_WAIT:
+                       /* already started */
+                       break;
+               case QH_STATE_IDLE:
+                       WARN_ON(1);
+                       break;
+               }
                break;
 
        case PIPE_INTERRUPT:
@@ -847,6 +867,7 @@ rescan:
                unlink_async (ehci, qh);
                /* FALL THROUGH */
        case QH_STATE_UNLINK:           /* wait for hw to finish? */
+       case QH_STATE_UNLINK_WAIT:
 idle_timeout:
                spin_unlock_irqrestore (&ehci->lock, flags);
                schedule_timeout_uninterruptible(1);
index d03e3cad5ca8a90a2cf7319a2f92891b481a1784..b2ee13c58517cc9182fccc533c7c5ca4aff0c77a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 by David Brownell
- * 
+ *
  * 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
@@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        }
        ehci->command = readl (&ehci->regs->command);
        if (ehci->reclaim)
-               ehci->reclaim_ready = 1;
+               end_unlink_async (ehci, NULL);
        ehci_work(ehci, NULL);
 
        /* suspend any active/unsuspended ports, maybe allow wakeup */
@@ -103,10 +103,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 
        /* re-init operational registers in case we lost power */
        if (readl (&ehci->regs->intr_enable) == 0) {
-               /* at least some APM implementations will try to deliver
+               /* at least some APM implementations will try to deliver
                 * IRQs right away, so delay them until we're ready.
-                */
-               intr_enable = 1;
+                */
+               intr_enable = 1;
                writel (0, &ehci->regs->segment);
                writel (ehci->periodic_dma, &ehci->regs->frame_list);
                writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
@@ -232,7 +232,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
                buf [1] = 0;
                retval++;
        }
-       
+
        /* no hub change reports (bit 0) for now (power, ...) */
 
        /* port N changes (bit N)? */
@@ -304,7 +304,7 @@ ehci_hub_descriptor (
 
 /*-------------------------------------------------------------------------*/
 
-#define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+#define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
 static int ehci_hub_control (
        struct usb_hcd  *hcd,
index 766061e0260a5e96d6258149bc6f7f8a31f71ee9..a8ba2e1497a4fb6d9f7b46bc6068b0cc6fd56371 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001 by David Brownell
- * 
+ *
  * 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
@@ -25,7 +25,7 @@
  *     - data used only by the HCD ... kmalloc is fine
  *     - async and periodic schedules, shared by HC and HCD ... these
  *       need to use dma_pool or dma_alloc_coherent
- *     - driver buffers, read/written by HC ... single shot DMA mapped 
+ *     - driver buffers, read/written by HC ... single shot DMA mapped
  *
  * There's also PCI "register" data, which is memory mapped.
  * No memory seen by this driver is pageable.
@@ -119,7 +119,7 @@ static inline void qh_put (struct ehci_qh *qh)
 
 /*-------------------------------------------------------------------------*/
 
-/* The queue heads and transfer descriptors are managed from pools tied 
+/* The queue heads and transfer descriptors are managed from pools tied
  * to each of the "per device" structures.
  * This is the initialisation and cleanup code.
  */
@@ -165,7 +165,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        int i;
 
        /* QTDs for control/bulk/intr transfers */
-       ehci->qtd_pool = dma_pool_create ("ehci_qtd", 
+       ehci->qtd_pool = dma_pool_create ("ehci_qtd",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_qtd),
                        32 /* byte alignment (for hw parts) */,
@@ -175,7 +175,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        }
 
        /* QHs for control/bulk/intr transfers */
-       ehci->qh_pool = dma_pool_create ("ehci_qh", 
+       ehci->qh_pool = dma_pool_create ("ehci_qh",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_qh),
                        32 /* byte alignment (for hw parts) */,
@@ -189,7 +189,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        }
 
        /* ITD for high speed ISO transfers */
-       ehci->itd_pool = dma_pool_create ("ehci_itd", 
+       ehci->itd_pool = dma_pool_create ("ehci_itd",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_itd),
                        32 /* byte alignment (for hw parts) */,
@@ -199,7 +199,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        }
 
        /* SITD for full/low speed split ISO transfers */
-       ehci->sitd_pool = dma_pool_create ("ehci_sitd", 
+       ehci->sitd_pool = dma_pool_create ("ehci_sitd",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_sitd),
                        32 /* byte alignment (for hw parts) */,
index 6967ab71e28281d8330395e14d3bf55af9a9ea84..08d0472d4f57f4201e430a625f18702fccdfdc10 100644 (file)
@@ -303,7 +303,7 @@ restart:
        /* emptying the schedule aborts any urbs */
        spin_lock_irq(&ehci->lock);
        if (ehci->reclaim)
-               ehci->reclaim_ready = 1;
+               end_unlink_async (ehci, NULL);
        ehci_work(ehci, NULL);
        spin_unlock_irq(&ehci->lock);
 
@@ -338,6 +338,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .resume =               ehci_pci_resume,
 #endif
        .stop =                 ehci_stop,
+       .shutdown =             ehci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -384,4 +385,5 @@ static struct pci_driver ehci_pci_driver = {
        .suspend =      usb_hcd_pci_suspend,
        .resume =       usb_hcd_pci_resume,
 #endif
+       .shutdown =     usb_hcd_pci_shutdown,
 };
index e469221e7ec392088fd1274e278175e29644f7a8..7fc25b6bd7d249f487e4d2adf8a4ecc150613733 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 by David Brownell
- * 
+ *
  * 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
@@ -31,7 +31,7 @@
  * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
  * interrupts) needs careful scheduling.  Performance improvements can be
  * an ongoing challenge.  That's in "ehci-sched.c".
- * 
+ *
  * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
  * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
  * (b) special fields in qh entries or (c) split iso entries.  TTs will
@@ -199,7 +199,7 @@ static void qtd_copy_status (
                                && ((token & QTD_STS_MMF) != 0
                                        || QTD_CERR(token) == 0)
                                && (!ehci_is_TDI(ehci)
-                                       || urb->dev->tt->hub !=
+                                       || urb->dev->tt->hub !=
                                           ehci_to_hcd(ehci)->self.root_hub)) {
 #ifdef DEBUG
                        struct usb_device *tt = urb->dev->tt->hub;
@@ -364,7 +364,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
                         */
                        if (likely (urb->status == -EINPROGRESS))
                                continue;
-                       
+
                        /* issue status after short control reads */
                        if (unlikely (do_status != 0)
                                        && QTD_PID (token) == 0 /* OUT */) {
@@ -388,7 +388,7 @@ halt:
                                wmb ();
                        }
                }
+
                /* remove it from the queue */
                spin_lock (&urb->lock);
                qtd_copy_status (ehci, urb, qtd->length, token);
@@ -518,7 +518,7 @@ qh_urb_transaction (
                /* for zero length DATA stages, STATUS is always IN */
                if (len == 0)
                        token |= (1 /* "in" */ << 8);
-       } 
+       }
 
        /*
         * data transfer stage:  buffer setup
@@ -759,7 +759,7 @@ qh_make (
                }
                break;
        default:
-               dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
+               dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
 done:
                qh_put (qh);
                return NULL;
@@ -967,17 +967,16 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
        struct ehci_qh          *qh = ehci->reclaim;
        struct ehci_qh          *next;
 
-       timer_action_done (ehci, TIMER_IAA_WATCHDOG);
+       iaa_watchdog_done (ehci);
 
        // qh->hw_next = cpu_to_le32 (qh->qh_dma);
        qh->qh_state = QH_STATE_IDLE;
        qh->qh_next.qh = NULL;
-       qh_put (qh);                    // refcount from reclaim 
+       qh_put (qh);                    // refcount from reclaim
 
        /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
        next = qh->reclaim;
        ehci->reclaim = next;
-       ehci->reclaim_ready = 0;
        qh->reclaim = NULL;
 
        qh_completions (ehci, qh, regs);
@@ -1031,7 +1030,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        timer_action_done (ehci, TIMER_ASYNC_OFF);
                }
                return;
-       } 
+       }
 
        qh->qh_state = QH_STATE_UNLINK;
        ehci->reclaim = qh = qh_get (qh);
@@ -1046,17 +1045,16 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
                /* if (unlikely (qh->reclaim != 0))
-                *      this will recurse, probably not much
+                *      this will recurse, probably not much
                 */
                end_unlink_async (ehci, NULL);
                return;
        }
 
-       ehci->reclaim_ready = 0;
        cmd |= CMD_IAAD;
        writel (cmd, &ehci->regs->command);
        (void) readl (&ehci->regs->command);
-       timer_action (ehci, TIMER_IAA_WATCHDOG);
+       iaa_watchdog_start (ehci);
 }
 
 /*-------------------------------------------------------------------------*/
index 4859900bd1351df16b10746b37977dbc217d03cd..e5e9c653c90725ea99d54e5c40c4d3dd0753f01f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2001-2004 by David Brownell
  * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers
- * 
+ *
  * 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
@@ -613,7 +613,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 /*-------------------------------------------------------------------------*/
 
 static int check_period (
-       struct ehci_hcd *ehci, 
+       struct ehci_hcd *ehci,
        unsigned        frame,
        unsigned        uframe,
        unsigned        period,
@@ -629,7 +629,7 @@ static int check_period (
 
        /*
         * 80% periodic == 100 usec/uframe available
-        * convert "usecs we need" to "max already claimed" 
+        * convert "usecs we need" to "max already claimed"
         */
        usecs = 100 - usecs;
 
@@ -659,14 +659,14 @@ static int check_period (
 }
 
 static int check_intr_schedule (
-       struct ehci_hcd         *ehci, 
+       struct ehci_hcd         *ehci,
        unsigned                frame,
        unsigned                uframe,
        const struct ehci_qh    *qh,
        __le32                  *c_maskp
 )
 {
-       int             retval = -ENOSPC;
+       int             retval = -ENOSPC;
        u8              mask = 0;
 
        if (qh->c_usecs && uframe >= 6)         /* FSTN territory? */
@@ -701,7 +701,7 @@ static int check_intr_schedule (
        /* Make sure this tt's buffer is also available for CSPLITs.
         * We pessimize a bit; probably the typical full speed case
         * doesn't need the second CSPLIT.
-        * 
+        *
         * NOTE:  both SPLIT and CSPLIT could be checked in just
         * one smart pass...
         */
@@ -728,7 +728,7 @@ done:
  */
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       int             status;
+       int             status;
        unsigned        uframe;
        __le32          c_mask;
        unsigned        frame;          /* 0..(qh->period - 1), or NO_FRAME */
@@ -784,7 +784,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
                ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
        /* stuff into the periodic schedule */
-       status = qh_link_periodic (ehci, qh);
+       status = qh_link_periodic (ehci, qh);
 done:
        return status;
 }
@@ -1681,7 +1681,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
                status = -ESHUTDOWN;
        else
                status = iso_stream_schedule (ehci, urb, stream);
-       if (likely (status == 0))
+       if (likely (status == 0))
                itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
        spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -1738,7 +1738,7 @@ sitd_sched_init (
                if (packet->buf1 != (buf & ~(u64)0x0fff))
                        packet->cross = 1;
 
-               /* OUT uses multiple start-splits */ 
+               /* OUT uses multiple start-splits */
                if (stream->bEndpointAddress & USB_DIR_IN)
                        continue;
                length = (length + 187) / 188;
@@ -1925,7 +1925,7 @@ sitd_link_urb (
 /*-------------------------------------------------------------------------*/
 
 #define        SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
-                               | SITD_STS_XACT | SITD_STS_MMF)
+                               | SITD_STS_XACT | SITD_STS_MMF)
 
 static unsigned
 sitd_complete (
@@ -2043,7 +2043,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
                status = -ESHUTDOWN;
        else
                status = iso_stream_schedule (ehci, urb, stream);
-       if (status == 0)
+       if (status == 0)
                sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
        spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -2226,5 +2226,5 @@ restart:
                        now_uframe++;
                        now_uframe %= mod;
                }
-       } 
+       }
 }
index 679c1cdcc9154d286235cbe99c7451cf26751e65..6aac39f50e0734d35e33f2fb3cfd5c6e2fcec627 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001-2002 by David Brownell
- * 
+ *
  * 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
@@ -58,7 +58,6 @@ struct ehci_hcd {                     /* one per controller */
        /* async schedule support */
        struct ehci_qh          *async;
        struct ehci_qh          *reclaim;
-       unsigned                reclaim_ready : 1;
        unsigned                scanning : 1;
 
        /* periodic schedule support */
@@ -81,8 +80,8 @@ struct ehci_hcd {                     /* one per controller */
        struct dma_pool         *itd_pool;      /* itd per iso urb */
        struct dma_pool         *sitd_pool;     /* sitd per split iso urb */
 
+       struct timer_list       iaa_watchdog;
        struct timer_list       watchdog;
-       struct notifier_block   reboot_notifier;
        unsigned long           actions;
        unsigned                stamp;
        unsigned long           next_statechange;
@@ -104,7 +103,7 @@ struct ehci_hcd {                   /* one per controller */
 #endif
 };
 
-/* convert between an HCD pointer and the corresponding EHCI_HCD */ 
+/* convert between an HCD pointer and the corresponding EHCI_HCD */
 static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd)
 {
        return (struct ehci_hcd *) (hcd->hcd_priv);
@@ -115,9 +114,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
 }
 
 
+static inline void
+iaa_watchdog_start (struct ehci_hcd *ehci)
+{
+       WARN_ON(timer_pending(&ehci->iaa_watchdog));
+       mod_timer (&ehci->iaa_watchdog,
+                       jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
+}
+
+static inline void iaa_watchdog_done (struct ehci_hcd *ehci)
+{
+       del_timer (&ehci->iaa_watchdog);
+}
+
 enum ehci_timer_action {
        TIMER_IO_WATCHDOG,
-       TIMER_IAA_WATCHDOG,
        TIMER_ASYNC_SHRINK,
        TIMER_ASYNC_OFF,
 };
@@ -135,9 +146,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
                unsigned long t;
 
                switch (action) {
-               case TIMER_IAA_WATCHDOG:
-                       t = EHCI_IAA_JIFFIES;
-                       break;
                case TIMER_IO_WATCHDOG:
                        t = EHCI_IO_JIFFIES;
                        break;
@@ -154,8 +162,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
                // async queue SHRINK often precedes IAA.  while it's ready
                // to go OFF neither can matter, and afterwards the IO
                // watchdog stops unless there's still periodic traffic.
-               if (action != TIMER_IAA_WATCHDOG
-                               && t > ehci->watchdog.expires
+               if (time_before_eq(t, ehci->watchdog.expires)
                                && timer_pending (&ehci->watchdog))
                        return;
                mod_timer (&ehci->watchdog, t);
@@ -179,8 +186,8 @@ struct ehci_caps {
 #define HCS_INDICATOR(p)       ((p)&(1 << 16)) /* true: has port indicators */
 #define HCS_N_CC(p)            (((p)>>12)&0xf) /* bits 15:12, #companion HCs */
 #define HCS_N_PCC(p)           (((p)>>8)&0xf)  /* bits 11:8, ports per CC */
-#define HCS_PORTROUTED(p)      ((p)&(1 << 7))  /* true: port routing */ 
-#define HCS_PPC(p)             ((p)&(1 << 4))  /* true: port power control */ 
+#define HCS_PORTROUTED(p)      ((p)&(1 << 7))  /* true: port routing */
+#define HCS_PPC(p)             ((p)&(1 << 4))  /* true: port power control */
 #define HCS_N_PORTS(p)         (((p)>>0)&0xf)  /* bits 3:0, ports on HC */
 
        u32             hcc_params;      /* HCCPARAMS - offset 0x8 */
@@ -205,7 +212,7 @@ struct ehci_regs {
 #define CMD_LRESET     (1<<7)          /* partial reset (no ports, etc) */
 #define CMD_IAAD       (1<<6)          /* "doorbell" interrupt async advance */
 #define CMD_ASE                (1<<5)          /* async schedule enable */
-#define CMD_PSE        (1<<4)          /* periodic schedule enable */
+#define CMD_PSE                (1<<4)          /* periodic schedule enable */
 /* 3:2 is periodic frame list size */
 #define CMD_RESET      (1<<1)          /* reset HC not bus */
 #define CMD_RUN                (1<<0)          /* start/stop HC */
@@ -231,9 +238,9 @@ struct ehci_regs {
        /* FRINDEX: offset 0x0C */
        u32             frame_index;    /* current microframe number */
        /* CTRLDSSEGMENT: offset 0x10 */
-       u32             segment;        /* address bits 63:32 if needed */
+       u32             segment;        /* address bits 63:32 if needed */
        /* PERIODICLISTBASE: offset 0x14 */
-       u32             frame_list;     /* points to periodic list */
+       u32             frame_list;     /* points to periodic list */
        /* ASYNCLISTADDR: offset 0x18 */
        u32             async_next;     /* address of next async queue head */
 
@@ -302,7 +309,7 @@ struct ehci_dbg_port {
 
 /*
  * EHCI Specification 0.95 Section 3.5
- * QTD: describe data transfer components (buffer, direction, ...) 
+ * QTD: describe data transfer components (buffer, direction, ...)
  * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
  *
  * These are associated only with "QH" (Queue Head) structures,
@@ -312,7 +319,7 @@ struct ehci_qtd {
        /* first part defined by EHCI spec */
        __le32                  hw_next;          /* see EHCI 3.5.1 */
        __le32                  hw_alt_next;      /* see EHCI 3.5.2 */
-       __le32                  hw_token;         /* see EHCI 3.5.3 */       
+       __le32                  hw_token;         /* see EHCI 3.5.3 */
 #define        QTD_TOGGLE      (1 << 31)       /* data toggle */
 #define        QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
 #define        QTD_IOC         (1 << 15)       /* interrupt on complete */
@@ -349,8 +356,8 @@ struct ehci_qtd {
 /* values for that type tag */
 #define Q_TYPE_ITD     __constant_cpu_to_le32 (0 << 1)
 #define Q_TYPE_QH      __constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD    __constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN    __constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_SITD    __constant_cpu_to_le32 (2 << 1)
+#define Q_TYPE_FSTN    __constant_cpu_to_le32 (3 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
 #define        QH_NEXT(dma)    (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
@@ -367,7 +374,7 @@ struct ehci_qtd {
  * For entries in the async schedule, the type tag always says "qh".
  */
 union ehci_shadow {
-       struct ehci_qh          *qh;            /* Q_TYPE_QH */
+       struct ehci_qh          *qh;            /* Q_TYPE_QH */
        struct ehci_itd         *itd;           /* Q_TYPE_ITD */
        struct ehci_sitd        *sitd;          /* Q_TYPE_SITD */
        struct ehci_fstn        *fstn;          /* Q_TYPE_FSTN */
@@ -397,7 +404,7 @@ struct ehci_qh {
 #define        QH_HUBPORT      0x3f800000
 #define        QH_MULT         0xc0000000
        __le32                  hw_current;      /* qtd list - see EHCI 3.6.4 */
-       
+
        /* qtd overlay (hardware parts of a struct ehci_qtd) */
        __le32                  hw_qtd_next;
        __le32                  hw_alt_next;
@@ -472,7 +479,7 @@ struct ehci_iso_stream {
        struct list_head        td_list;        /* queued itds/sitds */
        struct list_head        free_list;      /* list of unused itds/sitds */
        struct usb_device       *udev;
-       struct usb_host_endpoint *ep;
+       struct usb_host_endpoint *ep;
 
        /* output of (re)scheduling */
        unsigned long           start;          /* jiffies */
@@ -492,8 +499,8 @@ struct ehci_iso_stream {
        unsigned                bandwidth;
 
        /* This is used to initialize iTD's hw_bufp fields */
-       __le32                  buf0;           
-       __le32                  buf1;           
+       __le32                  buf0;
+       __le32                  buf1;
        __le32                  buf2;
 
        /* this is used to initialize sITD's tt info */
@@ -521,7 +528,7 @@ struct ehci_itd {
 
 #define ITD_ACTIVE     __constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
 
-       __le32                  hw_bufp [7];    /* see EHCI 3.3.3 */ 
+       __le32                  hw_bufp [7];    /* see EHCI 3.3.3 */
        __le32                  hw_bufp_hi [7]; /* Appendix B */
 
        /* the rest is HCD-private */
@@ -542,7 +549,7 @@ struct ehci_itd {
 /*-------------------------------------------------------------------------*/
 
 /*
- * EHCI Specification 0.95 Section 3.4 
+ * EHCI Specification 0.95 Section 3.4
  * siTD, aka split-transaction isochronous Transfer Descriptor
  *       ... describe full speed iso xfers through TT in hubs
  * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
index 5147ed4a66626f5a75a89b6da80f14b90a51b7cc..a72e041df8e7256b800c08226493ea46df82b32b 100644 (file)
@@ -1204,10 +1204,10 @@ static int isp116x_show_dbg(struct seq_file *s, void *unused)
 
 static int isp116x_open_seq(struct inode *inode, struct file *file)
 {
-       return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
+       return single_open(file, isp116x_show_dbg, inode->i_private);
 }
 
-static struct file_operations isp116x_debug_fops = {
+static const struct file_operations isp116x_debug_fops = {
        .open = isp116x_open_seq,
        .read = seq_read,
        .llseek = seq_lseek,
index a1b7c3813d3a955321d08961b0a5fc98faecbff4..b91e2edd9c5c1415ebecfe7aa056cddcb15c4fc6 100644 (file)
@@ -233,7 +233,7 @@ static const int cc_to_error[16] = {
        /* Bit Stuff  */ -EPROTO,
        /* Data Togg  */ -EILSEQ,
        /* Stall      */ -EPIPE,
-       /* DevNotResp */ -ETIMEDOUT,
+       /* DevNotResp */ -ETIME,
        /* PIDCheck   */ -EPROTO,
        /* UnExpPID   */ -EPROTO,
        /* DataOver   */ -EOVERFLOW,
index 85cc059705a645e947eae76f13be929048f8eef4..b466581beb4a777499e4ae1e5934471368cea3bd 100644 (file)
@@ -193,7 +193,7 @@ ohci_at91_start (struct usb_hcd *hcd)
        if ((ret = ohci_init(ohci)) < 0)
                return ret;
 
-       root->maxchild = board->ports;
+       ohci->num_ports = board->ports;
 
        if ((ret = ohci_run(ohci)) < 0) {
                err("can't start %s", hcd->self.bus_name);
@@ -221,6 +221,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
         */
        .start =                ohci_at91_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -239,7 +240,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -296,6 +297,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
        if (!clocked) {
                clk_enable(iclk);
                clk_enable(fclk);
+               clocked = 1;
        }
 
        return 0;
@@ -310,6 +312,7 @@ MODULE_ALIAS("at91_ohci");
 static struct platform_driver ohci_hcd_at91_driver = {
        .probe          = ohci_hcd_at91_drv_probe,
        .remove         = ohci_hcd_at91_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        .suspend        = ohci_hcd_at91_drv_suspend,
        .resume         = ohci_hcd_at91_drv_resume,
        .driver         = {
index f7a975d5db097757965b758baf14612c86b72f62..24e23c5783d85da4d5f05d01eec90d7752fed83d 100644 (file)
@@ -268,11 +268,8 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         * basic lifecycle operations
         */
        .start =                ohci_au1xxx_start,
-#ifdef CONFIG_PM
-       /* suspend:             ohci_au1xxx_suspend,  -- tbd */
-       /* resume:              ohci_au1xxx_resume,   -- tbd */
-#endif /*CONFIG_PM*/
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -291,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -338,6 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
 static struct platform_driver ohci_hcd_au1xxx_driver = {
        .probe          = ohci_hcd_au1xxx_drv_probe,
        .remove         = ohci_hcd_au1xxx_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        /*.suspend      = ohci_hcd_au1xxx_drv_suspend, */
        /*.resume       = ohci_hcd_au1xxx_drv_resume, */
        .driver         = {
index 7bfffcbbd226ec5a6089e775a2116825027b5988..8293c1d4be3f3049e0fb531cff33966436803541 100644 (file)
@@ -477,7 +477,7 @@ show_async (struct class_device *class_dev, char *buf)
        unsigned long           flags;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ohci = hcd_to_ohci(hcd);
 
        /* display control and bulk lists together, for simplicity */
@@ -510,7 +510,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        seen_count = 0;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ohci = hcd_to_ohci(hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -607,7 +607,7 @@ show_registers (struct class_device *class_dev, char *buf)
        u32                     rdata;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ohci = hcd_to_ohci(hcd);
        regs = ohci->regs;
        next = buf;
@@ -667,6 +667,11 @@ show_registers (struct class_device *class_dev, char *buf)
        size -= temp;
        next += temp;
 
+       temp = scnprintf (next, size, "hub poll timer %s\n",
+                       ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
+       size -= temp;
+       next += temp;
+
        /* roothub */
        ohci_dump_roothub (ohci, 1, &next, &size);
 
@@ -680,10 +685,11 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 static inline void create_debug_files (struct ohci_hcd *ohci)
 {
        struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
+       int retval;
 
-       class_device_create_file(cldev, &class_device_attr_async);
-       class_device_create_file(cldev, &class_device_attr_periodic);
-       class_device_create_file(cldev, &class_device_attr_registers);
+       retval = class_device_create_file(cldev, &class_device_attr_async);
+       retval = class_device_create_file(cldev, &class_device_attr_periodic);
+       retval = class_device_create_file(cldev, &class_device_attr_registers);
        ohci_dbg (ohci, "created debug files\n");
 }
 
index 6531c4d26527208eb6dac426a93d59ef36939546..1bf5e7a4e73551749803a85aed745e0b47898763 100644 (file)
@@ -128,12 +128,14 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
        .flags                  = HCD_USB11 | HCD_MEMORY,
        .start                  = ohci_ep93xx_start,
        .stop                   = ohci_stop,
+       .shutdown               = ohci_shutdown,
        .urb_enqueue            = ohci_urb_enqueue,
        .urb_dequeue            = ohci_urb_dequeue,
        .endpoint_disable       = ohci_endpoint_disable,
        .get_frame_number       = ohci_get_frame,
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
+       .hub_irq_enable         = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend            = ohci_bus_suspend,
        .bus_resume             = ohci_bus_resume,
@@ -202,6 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_ep93xx_driver = {
        .probe          = ohci_hcd_ep93xx_drv_probe,
        .remove         = ohci_hcd_ep93xx_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        .suspend        = ohci_hcd_ep93xx_drv_suspend,
        .resume         = ohci_hcd_ep93xx_drv_resume,
index 94d8cf4b36c19cf1472ae3c64d5874d143fd60fa..d1d68c4022519bf8aedcdb075193ded74c07dc44 100644 (file)
@@ -88,7 +88,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/dma-mapping.h> 
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
 
 #include "../core/hcd.h"
 
-#define DRIVER_VERSION "2005 April 22"
+#define DRIVER_VERSION "2006 August 04"
 #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
 #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
 
 #undef OHCI_VERBOSE_DEBUG      /* not always helpful */
 
 /* For initializing controller (mask in an HCFS mode too) */
-#define        OHCI_CONTROL_INIT       OHCI_CTRL_CBSR
+#define        OHCI_CONTROL_INIT       OHCI_CTRL_CBSR
 #define        OHCI_INTR_INIT \
-       (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
+               (OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \
+               | OHCI_INTR_RD | OHCI_INTR_WDH)
 
 #ifdef __hppa__
 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
 
 static const char      hcd_name [] = "ohci_hcd";
 
+#define        STATECHANGE_DELAY       msecs_to_jiffies(300)
+
 #include "ohci.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
 static void ohci_stop (struct usb_hcd *hcd);
-static int ohci_reboot (struct notifier_block *, unsigned long , void *);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -416,21 +418,20 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
        ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 }
 
-/* reboot notifier forcibly disables IRQs and DMA, helping kexec and
+/* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and
  * other cases where the next software may expect clean state from the
  * "firmware".  this is bus-neutral, unlike shutdown() methods.
  */
-static int
-ohci_reboot (struct notifier_block *block, unsigned long code, void *null)
+static void
+ohci_shutdown (struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci;
 
-       ohci = container_of (block, struct ohci_hcd, reboot_notifier);
+       ohci = hcd_to_ohci (hcd);
        ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
        ohci_usb_reset (ohci);
        /* flush the writes */
        (void) ohci_readl (ohci, &ohci->regs->control);
-       return 0;
 }
 
 /*-------------------------------------------------------------------------*
@@ -446,7 +447,6 @@ static int ohci_init (struct ohci_hcd *ohci)
 
        disable (ohci);
        ohci->regs = hcd->regs;
-       ohci->next_statechange = jiffies;
 
        /* REVISIT this BIOS handshake is now moved into PCI "quirks", and
         * was never needed for most non-PCI systems ... remove the code?
@@ -502,7 +502,6 @@ static int ohci_init (struct ohci_hcd *ohci)
        if ((ret = ohci_mem_init (ohci)) < 0)
                ohci_stop (hcd);
        else {
-               register_reboot_notifier (&ohci->reboot_notifier);
                create_debug_files (ohci);
        }
 
@@ -637,10 +636,14 @@ retry:
                return -EOVERFLOW;
        }
 
-       /* start controller operations */
+       /* use rhsc irqs after khubd is fully initialized */
+       hcd->poll_rh = 1;
+       hcd->uses_new_polling = 1;
+
+       /* start controller operations */
        ohci->hc_control &= OHCI_CTRL_RWC;
-       ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
-       ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+       ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+       ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
        hcd->state = HC_STATE_RUNNING;
 
        /* wake on ConnectStatusChange, matching external hubs */
@@ -648,7 +651,7 @@ retry:
 
        /* Choose the interrupts we care about now, others later on demand */
        mask = OHCI_INTR_INIT;
-       ohci_writel (ohci, mask, &ohci->regs->intrstatus);
+       ohci_writel (ohci, ~0, &ohci->regs->intrstatus);
        ohci_writel (ohci, mask, &ohci->regs->intrenable);
 
        /* handle root hub init quirks ... */
@@ -672,6 +675,7 @@ retry:
        // flush those writes
        (void) ohci_readl (ohci, &ohci->regs->control);
 
+       ohci->next_statechange = jiffies + STATECHANGE_DELAY;
        spin_unlock_irq (&ohci->lock);
 
        // POTPGT delay is bits 24-31, in 2 ms units.
@@ -709,7 +713,14 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
        /* interrupt for some other device? */
        } else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
                return IRQ_NOTMINE;
-       } 
+       }
+
+       if (ints & OHCI_INTR_RHSC) {
+               ohci_vdbg (ohci, "rhsc\n");
+               ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+               ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrstatus);
+               usb_hcd_poll_rh_status(hcd);
+       }
 
        if (ints & OHCI_INTR_UE) {
                disable (ohci);
@@ -723,13 +734,18 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
        if (ints & OHCI_INTR_RD) {
                ohci_vdbg (ohci, "resume detect\n");
                ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
-               if (hcd->state != HC_STATE_QUIESCING)
+               hcd->poll_rh = 1;
+               if (ohci->autostop) {
+                       spin_lock (&ohci->lock);
+                       ohci_rh_resume (ohci);
+                       spin_unlock (&ohci->lock);
+               } else
                        usb_hcd_resume_root_hub(hcd);
        }
 
        if (ints & OHCI_INTR_WDH) {
                if (HC_IS_RUNNING(hcd->state))
-                       ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);  
+                       ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
                spin_lock (&ohci->lock);
                dl_done_list (ohci, ptregs);
                spin_unlock (&ohci->lock);
@@ -775,9 +791,10 @@ static void ohci_stop (struct usb_hcd *hcd)
 
        ohci_usb_reset (ohci);
        ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       
+       free_irq(hcd->irq, hcd);
+       hcd->irq = -1;
+
        remove_debug_files (ohci);
-       unregister_reboot_notifier (&ohci->reboot_notifier);
        ohci_mem_cleanup (ohci);
        if (ohci->hcca) {
                dma_free_coherent (hcd->self.controller, 
@@ -917,6 +934,10 @@ MODULE_LICENSE ("GPL");
 #include "ohci-at91.c"
 #endif
 
+#ifdef CONFIG_ARCH_PNX4008
+#include "ohci-pnx4008.c"
+#endif
+
 #if !(defined(CONFIG_PCI) \
       || defined(CONFIG_SA1111) \
       || defined(CONFIG_ARCH_S3C2410) \
@@ -928,6 +949,7 @@ MODULE_LICENSE ("GPL");
       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
       || defined (CONFIG_ARCH_AT91RM9200) \
       || defined (CONFIG_ARCH_AT91SAM9261) \
+      || defined (CONFIG_ARCH_PNX4008) \
        )
 #error "missing bus glue for ohci-hcd"
 #endif
index 5b0a23fd798bb46294885432878e4c6429a660ed..ec75774abeac581eabb0a57b6de6fb30e4594a92 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_PM
+/* hcd->hub_irq_enable() */
+static void ohci_rhsc_enable (struct usb_hcd *hcd)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+
+       ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+}
 
 #define OHCI_SCHED_ENABLES \
        (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
 static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
 static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
-static int ohci_restart (struct ohci_hcd *ohci);
 
-static int ohci_bus_suspend (struct usb_hcd *hcd)
+static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
+__releases(ohci->lock)
+__acquires(ohci->lock)
 {
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
        int                     status = 0;
-       unsigned long           flags;
-
-       spin_lock_irqsave (&ohci->lock, flags);
-
-       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
-               spin_unlock_irqrestore (&ohci->lock, flags);
-               return -ESHUTDOWN;
-       }
 
        ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
        switch (ohci->hc_control & OHCI_CTRL_HCFS) {
@@ -72,15 +70,16 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
                ohci_dbg (ohci, "needs reinit!\n");
                goto done;
        case OHCI_USB_SUSPEND:
-               ohci_dbg (ohci, "already suspended\n");
-               goto done;
+               if (!ohci->autostop) {
+                       ohci_dbg (ohci, "already suspended\n");
+                       goto done;
+               }
        }
-       ohci_dbg (ohci, "suspend root hub\n");
+       ohci_dbg (ohci, "%s root hub\n",
+                       autostop ? "auto-stop" : "suspend");
 
        /* First stop any processing */
-       if (ohci->hc_control & OHCI_SCHED_ENABLES) {
-               int             limit;
-
+       if (!autostop && (ohci->hc_control & OHCI_SCHED_ENABLES)) {
                ohci->hc_control &= ~OHCI_SCHED_ENABLES;
                ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
                ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
@@ -90,27 +89,22 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
                 * then the last WDH could take 6+ msec
                 */
                ohci_dbg (ohci, "stopping schedules ...\n");
-               limit = 2000;
-               while (limit > 0) {
-                       udelay (250);
-                       limit =- 250;
-                       if (ohci_readl (ohci, &ohci->regs->intrstatus)
-                                       & OHCI_INTR_SF)
-                               break;
-               }
-               dl_done_list (ohci, NULL);
-               mdelay (7);
+               ohci->autostop = 0;
+               spin_unlock_irq (&ohci->lock);
+               msleep (8);
+               spin_lock_irq (&ohci->lock);
        }
        dl_done_list (ohci, NULL);
        finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
-       ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
-                       &ohci->regs->intrstatus);
 
        /* maybe resume can wake root hub */
-       if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev))
+       if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
+                       autostop)
                ohci->hc_control |= OHCI_CTRL_RWE;
-       else
+       else {
+               ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
                ohci->hc_control &= ~OHCI_CTRL_RWE;
+       }
 
        /* Suspend hub ... this is the "global (to this bus) suspend" mode,
         * which doesn't imply ports will first be individually suspended.
@@ -121,13 +115,12 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
        (void) ohci_readl (ohci, &ohci->regs->control);
 
        /* no resumes until devices finish suspending */
-       ohci->next_statechange = jiffies + msecs_to_jiffies (5);
+       if (!autostop) {
+               ohci->next_statechange = jiffies + msecs_to_jiffies (5);
+               ohci->autostop = 0;
+       }
 
 done:
-       /* external suspend vs self autosuspend ... same effect */
-       if (status == 0)
-               usb_hcd_suspend_root_hub(hcd);
-       spin_unlock_irqrestore (&ohci->lock, flags);
        return status;
 }
 
@@ -139,25 +132,19 @@ static inline struct ed *find_head (struct ed *ed)
        return ed;
 }
 
+static int ohci_restart (struct ohci_hcd *ohci);
+
 /* caller has locked the root hub */
-static int ohci_bus_resume (struct usb_hcd *hcd)
+static int ohci_rh_resume (struct ohci_hcd *ohci)
+__releases(ohci->lock)
+__acquires(ohci->lock)
 {
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+       struct usb_hcd          *hcd = ohci_to_hcd (ohci);
        u32                     temp, enables;
        int                     status = -EINPROGRESS;
-       unsigned long           flags;
-
-       if (time_before (jiffies, ohci->next_statechange))
-               msleep(5);
-
-       spin_lock_irqsave (&ohci->lock, flags);
-
-       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
-               spin_unlock_irqrestore (&ohci->lock, flags);
-               return -ESHUTDOWN;
-       }
-
+       int                     autostopped = ohci->autostop;
 
+       ohci->autostop = 0;
        ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
 
        if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
@@ -177,7 +164,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
                ohci->hc_control |= OHCI_USB_RESUME;
                ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
                (void) ohci_readl (ohci, &ohci->regs->control);
-               ohci_dbg (ohci, "resume root hub\n");
+               ohci_dbg (ohci, "%s root hub\n",
+                               autostopped ? "auto-start" : "resume");
                break;
        case OHCI_USB_RESUME:
                /* HCFS changes sometime after INTR_RD */
@@ -192,16 +180,24 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
                ohci_dbg (ohci, "lost power\n");
                status = -EBUSY;
        }
-       spin_unlock_irqrestore (&ohci->lock, flags);
+#ifdef CONFIG_PM
        if (status == -EBUSY) {
-               (void) ohci_init (ohci);
-               return ohci_restart (ohci);
+               if (!autostopped) {
+                       spin_unlock_irq (&ohci->lock);
+                       (void) ohci_init (ohci);
+                       status = ohci_restart (ohci);
+                       spin_lock_irq (&ohci->lock);
+               }
+               return status;
        }
+#endif
        if (status != -EINPROGRESS)
                return status;
+       if (autostopped)
+               goto skip_resume;
+       spin_unlock_irq (&ohci->lock);
 
        temp = ohci->num_ports;
-       enables = 0;
        while (temp--) {
                u32 stat = ohci_readl (ohci,
                                       &ohci->regs->roothub.portstatus [temp]);
@@ -234,17 +230,21 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        /* Sometimes PCI D3 suspend trashes frame timings ... */
        periodic_reinit (ohci);
 
+       /* the following code is executed with ohci->lock held and
+        * irqs disabled if and only if autostopped is true
+        */
+
+skip_resume:
        /* interrupts might have been disabled */
        ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
        if (ohci->ed_rm_list)
                ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
-       ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
-                       &ohci->regs->intrstatus);
 
        /* Then re-enable operations */
        ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
        (void) ohci_readl (ohci, &ohci->regs->control);
-       msleep (3);
+       if (!autostopped)
+               msleep (3);
 
        temp = ohci->hc_control;
        temp &= OHCI_CTRL_RWC;
@@ -254,10 +254,14 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        (void) ohci_readl (ohci, &ohci->regs->control);
 
        /* TRSMRCY */
-       msleep (10);
+       if (!autostopped) {
+               msleep (10);
+               spin_lock_irq (&ohci->lock);
+       }
+       /* now ohci->lock is always held and irqs are always disabled */
 
-       /* keep it alive for ~5x suspend + resume costs */
-       ohci->next_statechange = jiffies + msecs_to_jiffies (250);
+       /* keep it alive for more than ~5x suspend + resume costs */
+       ohci->next_statechange = jiffies + STATECHANGE_DELAY;
 
        /* maybe turn schedules back on */
        enables = 0;
@@ -291,6 +295,45 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        return 0;
 }
 
+#ifdef CONFIG_PM
+
+static int ohci_bus_suspend (struct usb_hcd *hcd)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+       int                     rc;
+
+       spin_lock_irq (&ohci->lock);
+
+       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+               rc = -ESHUTDOWN;
+       else
+               rc = ohci_rh_suspend (ohci, 0);
+       spin_unlock_irq (&ohci->lock);
+       return rc;
+}
+
+static int ohci_bus_resume (struct usb_hcd *hcd)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+       int                     rc;
+
+       if (time_before (jiffies, ohci->next_statechange))
+               msleep(5);
+
+       spin_lock_irq (&ohci->lock);
+
+       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+               rc = -ESHUTDOWN;
+       else
+               rc = ohci_rh_resume (ohci);
+       spin_unlock_irq (&ohci->lock);
+
+       /* poll until we know a device is connected or we autostop */
+       if (rc == 0)
+               usb_hcd_poll_rh_status(hcd);
+       return rc;
+}
+
 #endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
@@ -302,20 +345,11 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        int             i, changed = 0, length = 1;
-       int             can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
+       int             any_connected = 0, rhsc_enabled = 1;
        unsigned long   flags;
 
        spin_lock_irqsave (&ohci->lock, flags);
 
-       /* handle autosuspended root:  finish resuming before
-        * letting khubd or root hub timer see state changes.
-        */
-       if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
-                    || !HC_IS_RUNNING(hcd->state))) {
-               can_suspend = 0;
-               goto done;
-       }
-
        /* undocumented erratum seen on at least rev D */
        if ((ohci->flags & OHCI_QUIRK_AMD756)
                        && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
@@ -339,6 +373,9 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
        for (i = 0; i < ohci->num_ports; i++) {
                u32     status = roothub_portstatus (ohci, i);
 
+               /* can't autostop if ports are connected */
+               any_connected |= (status & RH_PS_CCS);
+
                if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
                                | RH_PS_OCIC | RH_PS_PRSC)) {
                        changed = 1;
@@ -346,39 +383,72 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                            buf [0] |= 1 << (i + 1);
                        else
                            buf [1] |= 1 << (i - 7);
-                       continue;
                }
-
-               /* can suspend if no ports are enabled; or if all all
-                * enabled ports are suspended AND remote wakeup is on.
-                */
-               if (!(status & RH_PS_CCS))
-                       continue;
-               if ((status & RH_PS_PSS) && can_suspend)
-                       continue;
-               can_suspend = 0;
        }
-done:
-       spin_unlock_irqrestore (&ohci->lock, flags);
 
-#ifdef CONFIG_PM
-       /* save power by suspending idle root hubs;
-        * INTR_RD wakes us when there's work
+       /* NOTE:  vendors didn't always make the same implementation
+        * choices for RHSC.  Sometimes it triggers on an edge (like
+        * setting and maybe clearing a port status change bit); and
+        * it's level-triggered on other silicon, active until khubd
+        * clears all active port status change bits.  If it's still
+        * set (level-triggered) we must disable it and rely on
+        * polling until khubd re-enables it.
         */
-       if (can_suspend
-                       && !changed
-                       && !ohci->ed_rm_list
-                       && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
-                                       & ohci->hc_control)
-                               == OHCI_USB_OPER
-                       && time_after (jiffies, ohci->next_statechange)
-                       && usb_trylock_device (hcd->self.root_hub) == 0
-                       ) {
-               ohci_vdbg (ohci, "autosuspend\n");
-               (void) ohci_bus_suspend (hcd);
-               usb_unlock_device (hcd->self.root_hub);
+       if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
+               ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
+               (void) ohci_readl (ohci, &ohci->regs->intrdisable);
+               rhsc_enabled = 0;
        }
-#endif
+       hcd->poll_rh = 1;
+
+       /* carry out appropriate state changes */
+       switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+
+       case OHCI_USB_OPER:
+               /* keep on polling until we know a device is connected
+                * and RHSC is enabled */
+               if (!ohci->autostop) {
+                       if (any_connected) {
+                               if (rhsc_enabled)
+                                       hcd->poll_rh = 0;
+                       } else {
+                               ohci->autostop = 1;
+                               ohci->next_statechange = jiffies + HZ;
+                       }
+
+               /* if no devices have been attached for one second, autostop */
+               } else {
+                       if (changed || any_connected) {
+                               ohci->autostop = 0;
+                               ohci->next_statechange = jiffies +
+                                               STATECHANGE_DELAY;
+                       } else if (time_after_eq (jiffies,
+                                               ohci->next_statechange)
+                                       && !ohci->ed_rm_list
+                                       && !(ohci->hc_control &
+                                               OHCI_SCHED_ENABLES)) {
+                               ohci_rh_suspend (ohci, 1);
+                       }
+               }
+               break;
+
+       /* if there is a port change, autostart or ask to be resumed */
+       case OHCI_USB_SUSPEND:
+       case OHCI_USB_RESUME:
+               if (changed) {
+                       if (ohci->autostop)
+                               ohci_rh_resume (ohci);
+                       else
+                               usb_hcd_resume_root_hub (hcd);
+               } else {
+                       /* everything is idle, no need for polling */
+                       hcd->poll_rh = 0;
+               }
+               break;
+       }
+
+done:
+       spin_unlock_irqrestore (&ohci->lock, flags);
 
        return changed ? length : 0;
 }
@@ -550,9 +620,6 @@ static int ohci_hub_control (
                        break;
                case USB_PORT_FEAT_SUSPEND:
                        temp = RH_PS_POCI;
-                       if ((ohci->hc_control & OHCI_CTRL_HCFS)
-                                       != OHCI_USB_OPER)
-                               usb_hcd_resume_root_hub(hcd);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        temp = RH_PS_PSSC;
index 5602da9bd52c9446e6706544f7acb11a57672aea..e121d97ed91caf7e3a7d3c3d9616f9baa5a19093 100644 (file)
@@ -173,11 +173,8 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         * basic lifecycle operations
         */
        .start =                ohci_lh7a404_start,
-#ifdef CONFIG_PM
-       /* suspend:             ohci_lh7a404_suspend,  -- tbd */
-       /* resume:              ohci_lh7a404_resume,   -- tbd */
-#endif /*CONFIG_PM*/
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -196,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -244,6 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev)
 static struct platform_driver ohci_hcd_lh7a404_driver = {
        .probe          = ohci_hcd_lh7a404_drv_probe,
        .remove         = ohci_hcd_lh7a404_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        /*.suspend      = ohci_hcd_lh7a404_drv_suspend, */
        /*.resume       = ohci_hcd_lh7a404_drv_resume, */
        .driver         = {
index bfbe328a47885671f833c3e84f6b9c26f4f6854f..d976614eebd3b33055bf8b2dd7f327187c55f43b 100644 (file)
@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
        ohci->next_statechange = jiffies;
        spin_lock_init (&ohci->lock);
        INIT_LIST_HEAD (&ohci->pending);
-       ohci->reboot_notifier.notifier_call = ohci_reboot;
 }
 
 /*-------------------------------------------------------------------------*/
index c4c4babd4767f52bd12ed0a67586021a471f1b43..9c02177de50a85a15836301d87993c31e5b41438 100644 (file)
@@ -4,7 +4,7 @@
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
  * (C) Copyright 2000-2005 David Brownell
  * (C) Copyright 2002 Hewlett-Packard Company
- * 
+ *
  * OMAP Bus Glue
  *
  * Modified for OMAP by Tony Lindgren <tony@atomide.com>
@@ -66,15 +66,20 @@ extern int usb_disabled(void);
 extern int ocpi_enable(void);
 
 static struct clk *usb_host_ck;
+static struct clk *usb_dc_ck;
+static int host_enabled;
+static int host_initialized;
 
 static void omap_ohci_clock_power(int on)
 {
        if (on) {
+               clk_enable(usb_dc_ck);
                clk_enable(usb_host_ck);
                /* guesstimate for T5 == 1x 32K clock + APLL lock time */
                udelay(100);
        } else {
                clk_disable(usb_host_ck);
+               clk_disable(usb_dc_ck);
        }
 }
 
@@ -87,14 +92,14 @@ static int omap_ohci_transceiver_power(int on)
        if (on) {
                if (machine_is_omap_innovator() && cpu_is_omap1510())
                        fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
-                               | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
+                               | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
                               INNOVATOR_FPGA_CAM_USB_CONTROL);
                else if (machine_is_omap_osk())
                        tps65010_set_gpio_out_value(GPIO1, LOW);
        } else {
                if (machine_is_omap_innovator() && cpu_is_omap1510())
                        fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
-                               & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
+                               & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
                               INNOVATOR_FPGA_CAM_USB_CONTROL);
                else if (machine_is_omap_osk())
                        tps65010_set_gpio_out_value(GPIO1, HIGH);
@@ -103,6 +108,7 @@ static int omap_ohci_transceiver_power(int on)
        return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP15XX
 /*
  * OMAP-1510 specific Local Bus clock on/off
  */
@@ -121,8 +127,8 @@ static int omap_1510_local_bus_power(int on)
 /*
  * OMAP-1510 specific Local Bus initialization
  * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
- *       See also arch/mach-omap/memory.h for __virt_to_dma() and 
- *       __dma_to_virt() which need to match with the physical 
+ *       See also arch/mach-omap/memory.h for __virt_to_dma() and
+ *       __dma_to_virt() which need to match with the physical
  *       Local Bus address below.
  */
 static int omap_1510_local_bus_init(void)
@@ -130,7 +136,7 @@ static int omap_1510_local_bus_init(void)
        unsigned int tlb;
        unsigned long lbaddr, physaddr;
 
-       omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
+       omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
               OMAP1510_LB_CLOCK_DIV);
 
        /* Configure the Local Bus MMU table */
@@ -138,7 +144,7 @@ static int omap_1510_local_bus_init(void)
                lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
                physaddr = tlb * 0x00100000 + PHYS_OFFSET;
                omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
-               omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
+               omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
                       OMAP1510_LB_MMU_CAM_L);
                omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
                omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
@@ -152,6 +158,10 @@ static int omap_1510_local_bus_init(void)
 
        return 0;
 }
+#else
+#define omap_1510_local_bus_power(x)   {}
+#define omap_1510_local_bus_init()     {}
+#endif
 
 #ifdef CONFIG_USB_OTG
 
@@ -173,13 +183,14 @@ static void start_hnp(struct ohci_hcd *ohci)
 
 /*-------------------------------------------------------------------------*/
 
-static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
+static int ohci_omap_init(struct usb_hcd *hcd)
 {
-       struct omap_usb_config  *config = pdev->dev.platform_data;
+       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
+       struct omap_usb_config  *config = hcd->self.controller->platform_data;
        int                     need_transceiver = (config->otg != 0);
        int                     ret;
 
-       dev_dbg(&pdev->dev, "starting USB Controller\n");
+       dev_dbg(hcd->self.controller, "starting USB Controller\n");
 
        if (config->otg) {
                ohci_to_hcd(ohci)->self.otg_port = config->otg;
@@ -200,7 +211,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
                if (ohci->transceiver) {
                        int     status = otg_set_host(ohci->transceiver,
                                                &ohci_to_hcd(ohci)->self);
-                       dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
+                       dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
                                        ohci->transceiver->label, status);
                        if (status) {
                                if (ohci->transceiver)
@@ -208,7 +219,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
                                return status;
                        }
                } else {
-                       dev_err(&pdev->dev, "can't find transceiver\n");
+                       dev_err(hcd->self.controller, "can't find transceiver\n");
                        return -ENODEV;
                }
        }
@@ -247,6 +258,10 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
                }
                ohci_writel(ohci, rh, &ohci->regs->roothub.a);
                distrust_firmware = 0;
+       } else if (machine_is_nokia770()) {
+               /* We require a self-powered hub, which should have
+                * plenty of power. */
+               ohci_to_hcd(ohci)->power_budget = 0;
        }
 
        /* FIXME khubd hub requests should manage power switching */
@@ -260,21 +275,15 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
        return 0;
 }
 
-static void omap_stop_hc(struct platform_device *pdev)
+static void ohci_omap_stop(struct usb_hcd *hcd)
 {
-       dev_dbg(&pdev->dev, "stopping USB Controller\n");
+       dev_dbg(hcd->self.controller, "stopping USB Controller\n");
        omap_ohci_clock_power(0);
 }
 
 
 /*-------------------------------------------------------------------------*/
 
-void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
 /**
  * usb_hcd_omap_probe - initialize OMAP-based HCDs
  * Context: !in_interrupt()
@@ -283,7 +292,7 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-int usb_hcd_omap_probe (const struct hc_driver *driver,
+static int usb_hcd_omap_probe (const struct hc_driver *driver,
                          struct platform_device *pdev)
 {
        int retval, irq;
@@ -291,12 +300,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
        struct ohci_hcd *ohci;
 
        if (pdev->num_resources != 2) {
-               printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
+               printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
                       pdev->num_resources);
                return -ENODEV;
        }
 
-       if (pdev->resource[0].flags != IORESOURCE_MEM 
+       if (pdev->resource[0].flags != IORESOURCE_MEM
                        || pdev->resource[1].flags != IORESOURCE_IRQ) {
                printk(KERN_ERR "hcd probe: invalid resource type\n");
                return -ENODEV;
@@ -306,6 +315,17 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
        if (IS_ERR(usb_host_ck))
                return PTR_ERR(usb_host_ck);
 
+       if (!cpu_is_omap1510())
+               usb_dc_ck = clk_get(0, "usb_dc_ck");
+       else
+               usb_dc_ck = clk_get(0, "lb_ck");
+
+       if (IS_ERR(usb_dc_ck)) {
+               clk_put(usb_host_ck);
+               return PTR_ERR(usb_dc_ck);
+       }
+
+
        hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
        if (!hcd) {
                retval = -ENOMEM;
@@ -325,9 +345,8 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
        ohci = hcd_to_ohci(hcd);
        ohci_hcd_init(ohci);
 
-       retval = omap_start_hc(ohci, pdev);
-       if (retval < 0)
-               goto err2;
+       host_initialized = 0;
+       host_enabled = 1;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -335,15 +354,21 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
                goto err2;
        }
        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
-       if (retval == 0)
-               return retval;
+       if (retval)
+               goto err2;
+
+       host_initialized = 1;
+
+       if (!host_enabled)
+               omap_ohci_clock_power(0);
 
-       omap_stop_hc(pdev);
+       return 0;
 err2:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err1:
        usb_put_hcd(hcd);
 err0:
+       clk_put(usb_dc_ck);
        clk_put(usb_host_ck);
        return retval;
 }
@@ -359,31 +384,41 @@ err0:
  * Reverses the effect of usb_hcd_omap_probe(), first invoking
  * the HCD's stop() method.  It is always called from a thread
  * context, normally "rmmod", "apmd", or something similar.
- *
  */
-void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
+static inline void
+usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+
        usb_remove_hcd(hcd);
+       if (ohci->transceiver) {
+               (void) otg_set_host(ohci->transceiver, 0);
+               put_device(ohci->transceiver->dev);
+       }
        if (machine_is_omap_osk())
                omap_free_gpio(9);
-       omap_stop_hc(pdev);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
+       clk_put(usb_dc_ck);
        clk_put(usb_host_ck);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 ohci_omap_start (struct usb_hcd *hcd)
 {
        struct omap_usb_config *config;
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        int             ret;
 
+       if (!host_enabled)
+               return 0;
        config = hcd->self.controller->platform_data;
-       if (config->otg || config->rwc)
+       if (config->otg || config->rwc) {
+               ohci->hc_control = OHCI_CTRL_RWC;
                writel(OHCI_CTRL_RWC, &ohci->regs->control);
+       }
 
        if ((ret = ohci_run (ohci)) < 0) {
                dev_err(hcd->self.controller, "can't start\n");
@@ -409,8 +444,10 @@ static const struct hc_driver ohci_omap_hc_driver = {
        /*
         * basic lifecycle operations
         */
+       .reset =                ohci_omap_init,
        .start =                ohci_omap_start,
-       .stop =                 ohci_stop,
+       .stop =                 ohci_omap_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -429,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -446,13 +484,8 @@ static int ohci_hcd_omap_drv_probe(struct platform_device *dev)
 static int ohci_hcd_omap_drv_remove(struct platform_device *dev)
 {
        struct usb_hcd          *hcd = platform_get_drvdata(dev);
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
 
        usb_hcd_omap_remove(hcd, dev);
-       if (ohci->transceiver) {
-               (void) otg_set_host(ohci->transceiver, 0);
-               put_device(ohci->transceiver->dev);
-       }
        platform_set_drvdata(dev, NULL);
 
        return 0;
@@ -472,7 +505,7 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
 
        omap_ohci_clock_power(0);
        ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-       dev->power.power_state = PMSG_SUSPEND;
+       dev->dev.power.power_state = PMSG_SUSPEND;
        return 0;
 }
 
@@ -485,8 +518,8 @@ static int ohci_omap_resume(struct platform_device *dev)
        ohci->next_statechange = jiffies;
 
        omap_ohci_clock_power(1);
-       dev->power.power_state = PMSG_ON;
-       usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+       dev->dev.power.power_state = PMSG_ON;
+       usb_hcd_resume_root_hub(platform_get_drvdata(dev));
        return 0;
 }
 
@@ -500,6 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev)
 static struct platform_driver ohci_hcd_omap_driver = {
        .probe          = ohci_hcd_omap_drv_probe,
        .remove         = ohci_hcd_omap_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        .suspend        = ohci_omap_suspend,
        .resume         = ohci_omap_resume,
index 37e122812b6797ee7a934a0fecd3cd0eaab1406b..874418552789154ee73a72064e6265c299d1edbe 100644 (file)
@@ -73,13 +73,14 @@ ohci_pci_start (struct usb_hcd *hcd)
                else if (pdev->vendor == PCI_VENDOR_ID_NS) {
                        struct pci_dev  *b;
 
-                       b  = pci_find_slot (pdev->bus->number,
+                       b  = pci_get_slot (pdev->bus,
                                        PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
                        if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
                                        && b->vendor == PCI_VENDOR_ID_NS) {
                                ohci->flags |= OHCI_QUIRK_SUPERIO;
                                ohci_dbg (ohci, "Using NSC SuperIO setup\n");
                        }
+                       pci_dev_put(b);
                }
 
                /* Check for Compaq's ZFMicro chipset, which needs short 
@@ -176,11 +177,14 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .reset =                ohci_pci_reset,
        .start =                ohci_pci_start,
+       .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
+
 #ifdef CONFIG_PM
+       /* these suspend/resume entries are for upstream PCI glue ONLY */
        .suspend =              ohci_pci_suspend,
        .resume =               ohci_pci_resume,
 #endif
-       .stop =                 ohci_stop,
 
        /*
         * managing i/o requests and associated device resources
@@ -199,6 +203,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -229,6 +234,8 @@ static struct pci_driver ohci_pci_driver = {
        .suspend =      usb_hcd_pci_suspend,
        .resume =       usb_hcd_pci_resume,
 #endif
+
+       .shutdown =     usb_hcd_pci_shutdown,
 };
 
  
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
new file mode 100644 (file)
index 0000000..82cb22f
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * drivers/usb/host/ohci-pnx4008.c
+ *
+ * driver for Philips PNX4008 USB Host
+ *
+ * Authors: Dmitry Chigirev <source@mvista.com>
+ *         Vitaly Wool <vitalywool@gmail.com>
+ *
+ * register initialization is based on code examples provided by Philips
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * NOTE: This driver does not have suspend/resume functionality
+ * This driver is intended for engineering development purposes only
+ *
+ * 2005-2006 (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/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+
+#define USB_CTRL       IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
+
+/* USB_CTRL bit defines */
+#define USB_SLAVE_HCLK_EN      (1 << 24)
+#define USB_HOST_NEED_CLK_EN   (1 << 21)
+
+#define USB_OTG_CLK_CTRL       IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4)
+#define USB_OTG_CLK_STAT       IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8)
+
+/* USB_OTG_CLK_CTRL bit defines */
+#define AHB_M_CLOCK_ON         (1 << 4)
+#define OTG_CLOCK_ON           (1 << 3)
+#define I2C_CLOCK_ON           (1 << 2)
+#define DEV_CLOCK_ON           (1 << 1)
+#define HOST_CLOCK_ON          (1 << 0)
+
+#define USB_OTG_STAT_CONTROL   IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110)
+
+/* USB_OTG_STAT_CONTROL bit defines */
+#define TRANSPARENT_I2C_EN     (1 << 7)
+#define HOST_EN                        (1 << 0)
+
+/* ISP1301 USB transceiver I2C registers */
+#define        ISP1301_MODE_CONTROL_1          0x04    /* u8 read, set, +1 clear */
+
+#define        MC1_SPEED_REG           (1 << 0)
+#define        MC1_SUSPEND_REG         (1 << 1)
+#define        MC1_DAT_SE0             (1 << 2)
+#define        MC1_TRANSPARENT         (1 << 3)
+#define        MC1_BDIS_ACON_EN        (1 << 4)
+#define        MC1_OE_INT_EN           (1 << 5)
+#define        MC1_UART_EN             (1 << 6)
+#define        MC1_MASK                0x7f
+
+#define        ISP1301_MODE_CONTROL_2          0x12    /* u8 read, set, +1 clear */
+
+#define        MC2_GLOBAL_PWR_DN       (1 << 0)
+#define        MC2_SPD_SUSP_CTRL       (1 << 1)
+#define        MC2_BI_DI               (1 << 2)
+#define        MC2_TRANSP_BDIR0        (1 << 3)
+#define        MC2_TRANSP_BDIR1        (1 << 4)
+#define        MC2_AUDIO_EN            (1 << 5)
+#define        MC2_PSW_EN              (1 << 6)
+#define        MC2_EN2V7               (1 << 7)
+
+#define        ISP1301_OTG_CONTROL_1           0x06    /* u8 read, set, +1 clear */
+#      define  OTG1_DP_PULLUP          (1 << 0)
+#      define  OTG1_DM_PULLUP          (1 << 1)
+#      define  OTG1_DP_PULLDOWN        (1 << 2)
+#      define  OTG1_DM_PULLDOWN        (1 << 3)
+#      define  OTG1_ID_PULLDOWN        (1 << 4)
+#      define  OTG1_VBUS_DRV           (1 << 5)
+#      define  OTG1_VBUS_DISCHRG       (1 << 6)
+#      define  OTG1_VBUS_CHRG          (1 << 7)
+#define        ISP1301_OTG_STATUS              0x10    /* u8 readonly */
+#      define  OTG_B_SESS_END          (1 << 6)
+#      define  OTG_B_SESS_VLD          (1 << 7)
+
+#define ISP1301_I2C_ADDR 0x2C
+
+#define ISP1301_I2C_MODE_CONTROL_1 0x4
+#define ISP1301_I2C_MODE_CONTROL_2 0x12
+#define ISP1301_I2C_OTG_CONTROL_1 0x6
+#define ISP1301_I2C_OTG_CONTROL_2 0x10
+#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
+#define ISP1301_I2C_INTERRUPT_LATCH 0xA
+#define ISP1301_I2C_INTERRUPT_FALLING 0xC
+#define ISP1301_I2C_INTERRUPT_RISING 0xE
+#define ISP1301_I2C_REG_CLEAR_ADDR 1
+
+struct i2c_driver isp1301_driver;
+struct i2c_client *isp1301_i2c_client;
+
+extern int usb_disabled(void);
+extern int ocpi_enable(void);
+
+static struct clk *usb_clk;
+
+static int isp1301_probe(struct i2c_adapter *adap);
+static int isp1301_detach(struct i2c_client *client);
+static int isp1301_command(struct i2c_client *client, unsigned int cmd,
+                          void *arg);
+
+static unsigned short normal_i2c[] =
+    { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
+static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+       .normal_i2c = normal_i2c,
+       .probe = dummy_i2c_addrlist,
+       .ignore = dummy_i2c_addrlist,
+};
+
+struct i2c_driver isp1301_driver = {
+       .id = I2C_DRIVERID_I2CDEV,      /* Fake Id */
+       .class = I2C_CLASS_HWMON,
+       .attach_adapter = isp1301_probe,
+       .detach_client = isp1301_detach,
+       .command = isp1301_command
+};
+
+static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct i2c_client *c;
+
+       c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL);
+
+       if (!c)
+               return -ENOMEM;
+
+       strcpy(c->name, "isp1301");
+       c->flags = 0;
+       c->addr = addr;
+       c->adapter = adap;
+       c->driver = &isp1301_driver;
+
+       isp1301_i2c_client = c;
+
+       return i2c_attach_client(c);
+}
+
+static int isp1301_probe(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, isp1301_attach);
+}
+
+static int isp1301_detach(struct i2c_client *client)
+{
+       i2c_detach_client(client);
+       kfree(isp1301_i2c_client);
+       return 0;
+}
+
+/* No commands defined */
+static int isp1301_command(struct i2c_client *client, unsigned int cmd,
+                          void *arg)
+{
+       return 0;
+}
+
+static void i2c_write(u8 buf, u8 subaddr)
+{
+       char tmpbuf[2];
+
+       tmpbuf[0] = subaddr;    /*register number */
+       tmpbuf[1] = buf;        /*register data */
+       i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2);
+}
+
+static void isp1301_configure(void)
+{
+       /* PNX4008 only supports DAT_SE0 USB mode */
+       /* PNX4008 R2A requires setting the MAX603 to output 3.6V */
+       /* Power up externel charge-pump */
+
+       i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1);
+       i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG),
+                 ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL,
+                 ISP1301_I2C_MODE_CONTROL_2);
+       i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL),
+                 ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN,
+                 ISP1301_I2C_OTG_CONTROL_1);
+       i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN),
+                 ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(0xFF,
+                 ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(0xFF,
+                 ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(0xFF,
+                 ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR);
+
+}
+
+static inline void isp1301_vbus_on(void)
+{
+       i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1);
+}
+
+static inline void isp1301_vbus_off(void)
+{
+       i2c_write(OTG1_VBUS_DRV,
+                 ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+}
+
+static void pnx4008_start_hc(void)
+{
+       unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
+       __raw_writel(tmp, USB_OTG_STAT_CONTROL);
+       isp1301_vbus_on();
+}
+
+static void pnx4008_stop_hc(void)
+{
+       unsigned long tmp;
+       isp1301_vbus_off();
+       tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
+       __raw_writel(tmp, USB_OTG_STAT_CONTROL);
+}
+
+static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
+
+       if ((ret = ohci_init(ohci)) < 0)
+               return ret;
+
+       if ((ret = ohci_run(ohci)) < 0) {
+               dev_err(hcd->self.controller, "can't start\n");
+               ohci_stop(hcd);
+               return ret;
+       }
+       return 0;
+}
+
+static const struct hc_driver ohci_pnx4008_hc_driver = {
+       .description = hcd_name,
+       .product_desc =         "pnx4008 OHCI",
+
+       /*
+        * generic hardware linkage
+        */
+       .irq = ohci_irq,
+       .flags = HCD_USB11 | HCD_MEMORY,
+
+       .hcd_priv_size =        sizeof(struct ohci_hcd),
+       /*
+        * basic lifecycle operations
+        */
+       .start = ohci_pnx4008_start,
+       .stop = ohci_stop,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue = ohci_urb_enqueue,
+       .urb_dequeue = ohci_urb_dequeue,
+       .endpoint_disable = ohci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number = ohci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data = ohci_hub_status_data,
+       .hub_control = ohci_hub_control,
+
+       .start_port_reset = ohci_start_port_reset,
+};
+
+#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON)
+
+static void pnx4008_set_usb_bits(void)
+{
+       start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
+       start_int_ack(SE_USB_OTG_ATX_INT_N);
+       start_int_umask(SE_USB_OTG_ATX_INT_N);
+
+       start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
+       start_int_ack(SE_USB_OTG_TIMER_INT);
+       start_int_umask(SE_USB_OTG_TIMER_INT);
+
+       start_int_set_rising_edge(SE_USB_I2C_INT);
+       start_int_ack(SE_USB_I2C_INT);
+       start_int_umask(SE_USB_I2C_INT);
+
+       start_int_set_rising_edge(SE_USB_INT);
+       start_int_ack(SE_USB_INT);
+       start_int_umask(SE_USB_INT);
+
+       start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
+       start_int_ack(SE_USB_NEED_CLK_INT);
+       start_int_umask(SE_USB_NEED_CLK_INT);
+
+       start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
+       start_int_ack(SE_USB_AHB_NEED_CLK_INT);
+       start_int_umask(SE_USB_AHB_NEED_CLK_INT);
+}
+
+static void pnx4008_unset_usb_bits(void)
+{
+       start_int_mask(SE_USB_OTG_ATX_INT_N);
+       start_int_mask(SE_USB_OTG_TIMER_INT);
+       start_int_mask(SE_USB_I2C_INT);
+       start_int_mask(SE_USB_INT);
+       start_int_mask(SE_USB_NEED_CLK_INT);
+       start_int_mask(SE_USB_AHB_NEED_CLK_INT);
+}
+
+static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = 0;
+       struct ohci_hcd *ohci;
+       const struct hc_driver *driver = &ohci_pnx4008_hc_driver;
+
+       int ret = 0, irq;
+
+       dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name);
+       if (usb_disabled()) {
+               err("USB is disabled");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (pdev->num_resources != 2
+           || pdev->resource[0].flags != IORESOURCE_MEM
+           || pdev->resource[1].flags != IORESOURCE_IRQ) {
+               err("Invalid resource configuration");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* Enable AHB slave USB clock, needed for further USB clock control */
+       __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+
+       ret = i2c_add_driver(&isp1301_driver);
+       if (ret < 0) {
+               err("failed to connect I2C to ISP1301 USB Transceiver");
+               goto out;
+       }
+
+       isp1301_configure();
+
+       /* Enable USB PLL */
+       usb_clk = clk_get(&pdev->dev, "ck_pll5");
+       if (IS_ERR(usb_clk)) {
+               err("failed to acquire USB PLL");
+               ret = PTR_ERR(usb_clk);
+               goto out1;
+       }
+
+       ret = clk_enable(usb_clk);
+       if (ret < 0) {
+               err("failed to start USB PLL");
+               goto out2;
+       }
+
+       ret = clk_set_rate(usb_clk, 48000);
+       if (ret < 0) {
+               err("failed to set USB clock rate");
+               goto out3;
+       }
+
+       __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
+
+       /* Set to enable all needed USB clocks */
+       __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL);
+
+       while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
+              USB_CLOCK_MASK) ;
+
+       hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+       if (!hcd) {
+               err("Failed to allocate HC buffer");
+               ret = -ENOMEM;
+               goto out3;
+       }
+
+       /* Set all USB bits in the Start Enable register */
+       pnx4008_set_usb_bits();
+
+       hcd->rsrc_start = pdev->resource[0].start;
+       hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+               dev_dbg(&pdev->dev, "request_mem_region failed\n");
+               ret =  -ENOMEM;
+               goto out4;
+       }
+       hcd->regs = (void __iomem *)pdev->resource[0].start;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = -ENXIO;
+               goto out4;
+       }
+
+       hcd->self.hcpriv = (void *)hcd;
+
+       pnx4008_start_hc();
+       platform_set_drvdata(pdev, hcd);
+       ohci = hcd_to_ohci(hcd);
+       ohci_hcd_init(ohci);
+
+       dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
+       ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+       if (ret == 0)
+               return ret;
+
+       pnx4008_stop_hc();
+out4:
+       pnx4008_unset_usb_bits();
+       usb_put_hcd(hcd);
+out3:
+       clk_disable(usb_clk);
+out2:
+       clk_put(usb_clk);
+out1:
+       i2c_del_driver(&isp1301_driver);
+out:
+       return ret;
+}
+
+static int usb_hcd_pnx4008_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_remove_hcd(hcd);
+       pnx4008_stop_hc();
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+       pnx4008_unset_usb_bits();
+       clk_disable(usb_clk);
+       clk_put(usb_clk);
+       i2c_del_driver(&isp1301_driver);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver usb_hcd_pnx4008_driver = {
+       .driver = {
+               .name = "usb-ohci",
+       },
+       .probe = usb_hcd_pnx4008_probe,
+       .remove = usb_hcd_pnx4008_remove,
+};
+
+static int __init usb_hcd_pnx4008_init(void)
+{
+       return platform_driver_register(&usb_hcd_pnx4008_driver);
+}
+
+static void __exit usb_hcd_pnx4008_cleanup(void)
+{
+       return platform_driver_unregister(&usb_hcd_pnx4008_driver);
+}
+
+module_init(usb_hcd_pnx4008_init);
+module_exit(usb_hcd_pnx4008_cleanup);
index 9fe56ff1615dab3740cf6d75b4149c1b3556c131..d9d1ae236bd517458ca7bbd27a80f17663c837c8 100644 (file)
@@ -148,6 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .start =                ohci_ppc_soc_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -166,6 +167,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -195,6 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_ppc_soc_driver = {
        .probe          = ohci_hcd_ppc_soc_drv_probe,
        .remove         = ohci_hcd_ppc_soc_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
        /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
index 6f559e102789462e9efbff65ee30bcbf45e92bf4..e176b04d7aeb4ea4921c102ab614dc69ea037906 100644 (file)
@@ -270,6 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .start =                ohci_pxa27x_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -288,6 +289,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef  CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -357,6 +359,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_pxa27x_driver = {
        .probe          = ohci_hcd_pxa27x_drv_probe,
        .remove         = ohci_hcd_pxa27x_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        .suspend        = ohci_hcd_pxa27x_drv_suspend, 
        .resume         = ohci_hcd_pxa27x_drv_resume,
index d2fc6969a9f77ae6784fe2838aee33e9fe5f9bbe..59e436424d4145fc1e181b3b25c9a047e6b17180 100644 (file)
@@ -370,7 +370,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
                goto err_mem;
        }
 
-       usb_clk = clk_get(&dev->dev, "upll");
+       usb_clk = clk_get(&dev->dev, "usb-bus-host");
        if (IS_ERR(usb_clk)) {
                dev_err(&dev->dev, "cannot get usb-host clock\n");
                retval = -ENOENT;
@@ -447,6 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .start =                ohci_s3c2410_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -465,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .hub_status_data =      ohci_s3c2410_hub_status_data,
        .hub_control =          ohci_s3c2410_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -490,6 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_s3c2410_driver = {
        .probe          = ohci_hcd_s3c2410_drv_probe,
        .remove         = ohci_hcd_s3c2410_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        /*.suspend      = ohci_hcd_s3c2410_drv_suspend, */
        /*.resume       = ohci_hcd_s3c2410_drv_resume, */
        .driver         = {
index ce3de106cadc46872f8d57491b634c7a2aa2ac67..71371de32ada4c21bed7e61d7a30914ea35db9b4 100644 (file)
@@ -212,10 +212,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         * basic lifecycle operations
         */
        .start =                ohci_sa1111_start,
-#ifdef CONFIG_PM
-       /* suspend:             ohci_sa1111_suspend,  -- tbd */
-       /* resume:              ohci_sa1111_resume,   -- tbd */
-#endif
        .stop =                 ohci_stop,
 
        /*
@@ -235,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index caacf14371f510dd45f031eb0c765d1b6e6aec8c..a2f42a2f47c6f440165fb05be038dae041668167 100644 (file)
@@ -159,7 +159,7 @@ static const int cc_to_error [16] = {
        /* Bit Stuff  */               -EPROTO,
        /* Data Togg  */               -EILSEQ,
        /* Stall      */               -EPIPE,
-       /* DevNotResp */               -ETIMEDOUT,
+       /* DevNotResp */               -ETIME,
        /* PIDCheck   */               -EPROTO,
        /* UnExpPID   */               -EPROTO,
        /* DataOver   */               -EOVERFLOW,
@@ -388,8 +388,7 @@ struct ohci_hcd {
        u32                     hc_control;     /* copy of hc control reg */
        unsigned long           next_statechange;       /* suspend/resume */
        u32                     fminterval;             /* saved register */
-
-       struct notifier_block   reboot_notifier;
+       unsigned                autostop:1;     /* rh auto stopping/stopped */
 
        unsigned long           flags;          /* for HC bugs */
 #define        OHCI_QUIRK_AMD756       0x01                    /* erratum #4 */
index 9de115d9db2703bad97f57506cf3a9d55d9a106c..3a586aab39395580ef2fa68c3b0e393bd9adbc3b 100644 (file)
@@ -597,7 +597,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
        /* error? retry, until "3 strikes" */
        } else if (++ep->error_count >= 3) {
                if (status & SL11H_STATMASK_TMOUT)
-                       urbstat = -ETIMEDOUT;
+                       urbstat = -ETIME;
                else if (status & SL11H_STATMASK_OVF)
                        urbstat = -EOVERFLOW;
                else
@@ -1517,7 +1517,7 @@ static int proc_sl811h_open(struct inode *inode, struct file *file)
        return single_open(file, proc_sl811h_show, PDE(inode)->data);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
        .open           = proc_sl811h_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
new file mode 100644 (file)
index 0000000..cb2e2a6
--- /dev/null
@@ -0,0 +1,3295 @@
+/*
+* Host Controller Driver for the Elan Digital Systems U132 adapter
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+* http://www.elandigitalsystems.com
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+* tony.olech@elandigitalsystems.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, version 2.
+*
+*
+* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB host drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#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>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/pci_ids.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include "../core/hcd.h"
+#include "ohci.h"
+#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+        OHCI_INTR_WDH)
+MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
+MODULE_DESCRIPTION("U132 USB Host Controller Driver");
+MODULE_LICENSE("GPL");
+#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+INT_MODULE_PARM(testing, 0);
+/* Some boards misreport power switching/overcurrent*/
+static int distrust_firmware = 1;
+module_param(distrust_firmware, bool, 0);
+MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+        "t setup");
+DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+/*
+* u132_module_lock exists to protect access to global variables
+*
+*/
+static struct semaphore u132_module_lock;
+static int u132_exiting = 0;
+static int u132_instances = 0;
+static struct list_head u132_static_list;
+/*
+* end of the global variables protected by u132_module_lock
+*/
+static struct workqueue_struct *workqueue;
+#define MAX_U132_PORTS 7
+#define MAX_U132_ADDRS 128
+#define MAX_U132_UDEVS 4
+#define MAX_U132_ENDPS 100
+#define MAX_U132_RINGS 4
+static const char *cc_to_text[16] = {
+        "No Error ",
+        "CRC Error ",
+        "Bit Stuff ",
+        "Data Togg ",
+        "Stall ",
+        "DevNotResp ",
+        "PIDCheck ",
+        "UnExpPID ",
+        "DataOver ",
+        "DataUnder ",
+        "(for hw) ",
+        "(for hw) ",
+        "BufferOver ",
+        "BuffUnder ",
+        "(for HCD) ",
+        "(for HCD) "
+};
+struct u132_port {
+        struct u132 *u132;
+        int reset;
+        int enable;
+        int power;
+        int Status;
+};
+struct u132_addr {
+        u8 address;
+};
+struct u132_udev {
+        struct kref kref;
+        struct usb_device *usb_device;
+        u8 enumeration;
+        u8 udev_number;
+        u8 usb_addr;
+        u8 portnumber;
+        u8 endp_number_in[16];
+        u8 endp_number_out[16];
+};
+#define ENDP_QUEUE_SHIFT 3
+#define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
+#define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
+struct u132_urbq {
+        struct list_head urb_more;
+        struct urb *urb;
+};
+struct u132_spin {
+        spinlock_t slock;
+};
+struct u132_endp {
+        struct kref kref;
+        u8 udev_number;
+        u8 endp_number;
+        u8 usb_addr;
+        u8 usb_endp;
+        struct u132 *u132;
+        struct list_head endp_ring;
+        struct u132_ring *ring;
+        unsigned toggle_bits:2;
+        unsigned active:1;
+        unsigned delayed:1;
+        unsigned input:1;
+        unsigned output:1;
+        unsigned pipetype:2;
+        unsigned dequeueing:1;
+        unsigned edset_flush:1;
+        unsigned spare_bits:14;
+        unsigned long jiffies;
+        struct usb_host_endpoint *hep;
+        struct u132_spin queue_lock;
+        u16 queue_size;
+        u16 queue_last;
+        u16 queue_next;
+        struct urb *urb_list[ENDP_QUEUE_SIZE];
+        struct list_head urb_more;
+        struct work_struct scheduler;
+};
+struct u132_ring {
+        unsigned in_use:1;
+        unsigned length:7;
+        u8 number;
+        struct u132 *u132;
+        struct u132_endp *curr_endp;
+        struct work_struct scheduler;
+};
+#define OHCI_QUIRK_AMD756 0x01
+#define OHCI_QUIRK_SUPERIO 0x02
+#define OHCI_QUIRK_INITRESET 0x04
+#define OHCI_BIG_ENDIAN 0x08
+#define OHCI_QUIRK_ZFMICRO 0x10
+struct u132 {
+        struct kref kref;
+        struct list_head u132_list;
+        struct semaphore sw_lock;
+        struct semaphore scheduler_lock;
+        struct u132_platform_data *board;
+        struct platform_device *platform_dev;
+        struct u132_ring ring[MAX_U132_RINGS];
+        int sequence_num;
+        int going;
+        int power;
+        int reset;
+        int num_ports;
+        u32 hc_control;
+        u32 hc_fminterval;
+        u32 hc_roothub_status;
+        u32 hc_roothub_a;
+        u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+        int flags;
+        unsigned long next_statechange;
+        struct work_struct monitor;
+        int num_endpoints;
+        struct u132_addr addr[MAX_U132_ADDRS];
+        struct u132_udev udev[MAX_U132_UDEVS];
+        struct u132_port port[MAX_U132_PORTS];
+        struct u132_endp *endp[MAX_U132_ENDPS];
+};
+int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
+        u8 width, u32 *data);
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
+        u8 width, u32 data);
+/*
+* these can not be inlines because we need the structure offset!!
+* Does anyone have a better way?????
+*/
+#define u132_read_pcimem(u132, member, data) \
+        usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0, data);
+#define u132_write_pcimem(u132, member, data) \
+        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0, data);
+#define u132_write_pcimem_byte(u132, member, data) \
+        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0x0e, data);
+static inline struct u132 *udev_to_u132(struct u132_udev *udev)
+{
+        u8 udev_number = udev->udev_number;
+        return container_of(udev, struct u132, udev[udev_number]);
+}
+
+static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
+{
+        return (struct u132 *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
+{
+        return container_of((void *)u132, struct usb_hcd, hcd_priv);
+}
+
+static inline void u132_disable(struct u132 *u132)
+{
+        u132_to_hcd(u132)->state = HC_STATE_HALT;
+}
+
+
+#define kref_to_u132(d) container_of(d, struct u132, kref)
+#define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref)
+#define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref)
+#include "../misc/usb_u132.h"
+static const char hcd_name[] = "u132_hcd";
+#define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
+        USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
+        USB_PORT_STAT_C_RESET) << 16)
+static void u132_hcd_delete(struct kref *kref)
+{
+        struct u132 *u132 = kref_to_u132(kref);
+        struct platform_device *pdev = u132->platform_dev;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        u132->going += 1;
+        down(&u132_module_lock);
+        list_del_init(&u132->u132_list);
+        u132_instances -= 1;
+        up(&u132_module_lock);
+        dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
+                "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
+        usb_put_hcd(hcd);
+}
+
+static inline void u132_u132_put_kref(struct u132 *u132)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static inline void u132_u132_init_kref(struct u132 *u132)
+{
+        kref_init(&u132->kref);
+}
+
+static void u132_udev_delete(struct kref *kref)
+{
+        struct u132_udev *udev = kref_to_u132_udev(kref);
+        udev->udev_number = 0;
+        udev->usb_device = NULL;
+        udev->usb_addr = 0;
+        udev->enumeration = 0;
+}
+
+static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
+{
+        kref_put(&udev->kref, u132_udev_delete);
+}
+
+static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
+{
+        kref_get(&udev->kref);
+}
+
+static inline void u132_udev_init_kref(struct u132 *u132,
+        struct u132_udev *udev)
+{
+        kref_init(&udev->kref);
+}
+
+static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &ring->scheduler, delta))
+                        return;
+        } else if (queue_work(workqueue, &ring->scheduler))
+                return;
+        kref_put(&u132->kref, u132_hcd_delete);
+        return;
+}
+
+static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
+        unsigned int delta)
+{
+        kref_get(&u132->kref);
+        u132_ring_requeue_work(u132, ring, delta);
+        return;
+}
+
+static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
+{
+        if (cancel_delayed_work(&ring->scheduler)) {
+                kref_put(&u132->kref, u132_hcd_delete);
+        }
+}
+
+static void u132_endp_delete(struct kref *kref)
+{
+        struct u132_endp *endp = kref_to_u132_endp(kref);
+        struct u132 *u132 = endp->u132;
+        u8 usb_addr = endp->usb_addr;
+        u8 usb_endp = endp->usb_endp;
+        u8 address = u132->addr[usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        u8 endp_number = endp->endp_number;
+        struct usb_host_endpoint *hep = endp->hep;
+        struct u132_ring *ring = endp->ring;
+        struct list_head *head = &endp->endp_ring;
+        ring->length -= 1;
+        if (endp == ring->curr_endp) {
+                if (list_empty(head)) {
+                        ring->curr_endp = NULL;
+                        list_del(head);
+                } else {
+                        struct u132_endp *next_endp = list_entry(head->next,
+                                struct u132_endp, endp_ring);
+                        ring->curr_endp = next_endp;
+                        list_del(head);
+        }} else
+                list_del(head);
+        if (endp->input) {
+                udev->endp_number_in[usb_endp] = 0;
+                u132_udev_put_kref(u132, udev);
+        }
+        if (endp->output) {
+                udev->endp_number_out[usb_endp] = 0;
+                u132_udev_put_kref(u132, udev);
+        }
+        u132->endp[endp_number - 1] = NULL;
+        hep->hcpriv = NULL;
+        kfree(endp);
+        u132_u132_put_kref(u132);
+}
+
+static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
+{
+        kref_put(&endp->kref, u132_endp_delete);
+}
+
+static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
+{
+        kref_get(&endp->kref);
+}
+
+static inline void u132_endp_init_kref(struct u132 *u132,
+        struct u132_endp *endp)
+{
+        kref_init(&endp->kref);
+        kref_get(&u132->kref);
+}
+
+static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+                        kref_get(&endp->kref);
+        } else if (queue_work(workqueue, &endp->scheduler))
+                kref_get(&endp->kref);
+        return;
+}
+
+static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
+{
+        if (cancel_delayed_work(&endp->scheduler))
+                kref_put(&endp->kref, u132_endp_delete);
+}
+
+static inline void u132_monitor_put_kref(struct u132 *u132)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &u132->monitor, delta)) {
+                        kref_get(&u132->kref);
+                }
+        } else if (queue_work(workqueue, &u132->monitor))
+                kref_get(&u132->kref);
+        return;
+}
+
+static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &u132->monitor, delta))
+                        return;
+        } else if (queue_work(workqueue, &u132->monitor))
+                return;
+        kref_put(&u132->kref, u132_hcd_delete);
+        return;
+}
+
+static void u132_monitor_cancel_work(struct u132 *u132)
+{
+        if (cancel_delayed_work(&u132->monitor))
+                kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static int read_roothub_info(struct u132 *u132)
+{
+        u32 revision;
+        int retval;
+        retval = u132_read_pcimem(u132, revision, &revision);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                        "ntrol\n", retval);
+                return retval;
+        } else if ((revision & 0xFF) == 0x10) {
+        } else if ((revision & 0xFF) == 0x11) {
+        } else {
+                dev_err(&u132->platform_dev->dev, "device revision is not valid"
+                        " %08X\n", revision);
+                return -ENODEV;
+        }
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                        "ntrol\n", retval);
+                return retval;
+        }
+        retval = u132_read_pcimem(u132, roothub.status,
+                &u132->hc_roothub_status);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                        "g roothub.status\n", retval);
+                return retval;
+        }
+        retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                        "g roothub.a\n", retval);
+                return retval;
+        }
+        {
+                int I = u132->num_ports;
+                int i = 0;
+                while (I-- > 0) {
+                        retval = u132_read_pcimem(u132, roothub.portstatus[i],
+                                &u132->hc_roothub_portstatus[i]);
+                        if (retval) {
+                                dev_err(&u132->platform_dev->dev, "error %d acc"
+                                        "essing device roothub.portstatus[%d]\n"
+                                        , retval, i);
+                                return retval;
+                        } else
+                                i += 1;
+                }
+        }
+        return 0;
+}
+
+static void u132_hcd_monitor_work(void *data)
+{
+        struct u132 *u132 = data;
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                u132_monitor_put_kref(u132);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                u132_monitor_put_kref(u132);
+                return;
+        } else {
+                int retval;
+                down(&u132->sw_lock);
+                retval = read_roothub_info(u132);
+                if (retval) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        u132_disable(u132);
+                        u132->going = 1;
+                        up(&u132->sw_lock);
+                        usb_hc_died(hcd);
+                        ftdi_elan_gone_away(u132->platform_dev);
+                        u132_monitor_put_kref(u132);
+                        return;
+                } else {
+                        u132_monitor_requeue_work(u132, 500);
+                        up(&u132->sw_lock);
+                        return;
+                }
+        }
+}
+
+static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        struct u132_ring *ring;
+        unsigned long irqs;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        urb->error_count = 0;
+        urb->status = status;
+        urb->hcpriv = NULL;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->queue_next += 1;
+        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        } else {
+                struct list_head *next = endp->urb_more.next;
+                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                        urb_more);
+                list_del(next);
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                        urbq->urb;
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                kfree(urbq);
+        } down(&u132->scheduler_lock);
+        ring = endp->ring;
+        ring->in_use = 0;
+        u132_ring_cancel_work(u132, ring);
+        u132_ring_queue_work(u132, ring, 0);
+        up(&u132->scheduler_lock);
+        u132_endp_put_kref(u132, endp);
+        usb_hcd_giveback_urb(hcd, urb, NULL);
+        return;
+}
+
+static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        u132_endp_put_kref(u132, endp);
+}
+
+static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        unsigned long irqs;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        urb->error_count = 0;
+        urb->status = status;
+        urb->hcpriv = NULL;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->queue_next += 1;
+        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        } else {
+                struct list_head *next = endp->urb_more.next;
+                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                        urb_more);
+                list_del(next);
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                        urbq->urb;
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                kfree(urbq);
+        } usb_hcd_giveback_urb(hcd, urb, NULL);
+        return;
+}
+
+static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
+                 urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
+                 urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
+                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
+                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+
+/*
+* must not LOCK sw_lock
+*
+*/
+static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer + urb->actual_length;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length += len;
+                if ((condition_code == TD_CC_NOERROR) &&
+                        (urb->transfer_buffer_length > urb->actual_length)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        if (urb->actual_length > 0) {
+                                int retval;
+                                up(&u132->scheduler_lock);
+                                retval = edset_single(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_interrupt_recv);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                        } else {
+                                ring->in_use = 0;
+                                endp->active = 0;
+                                endp->jiffies = jiffies +
+                                        msecs_to_jiffies(urb->interval);
+                                u132_ring_cancel_work(u132, ring);
+                                u132_ring_queue_work(u132, ring, 0);
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                        }
+                        return;
+                } else if ((condition_code == TD_DATAUNDERRUN) &&
+                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else {
+                        if (condition_code == TD_CC_NOERROR) {
+                                endp->toggle_bits = toggle_bits;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 1 & toggle_bits);
+                        } else if (condition_code == TD_CC_STALL) {
+                                endp->toggle_bits = 0x2;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 0);
+                        } else {
+                                endp->toggle_bits = 0x2;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 0);
+                                dev_err(&u132->platform_dev->dev, "urb=%p givin"
+                                        "g back INTERRUPT %s\n", urb,
+                                        cc_to_text[condition_code]);
+                        }
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                urb->actual_length += len;
+                endp->toggle_bits = toggle_bits;
+                if (urb->transfer_buffer_length > urb->actual_length) {
+                        int retval;
+                        up(&u132->scheduler_lock);
+                        retval = edset_output(u132, ring, endp, urb, address,
+                                endp->toggle_bits, u132_hcd_bulk_output_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer + urb->actual_length;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length += len;
+                if ((condition_code == TD_CC_NOERROR) &&
+                        (urb->transfer_buffer_length > urb->actual_length)) {
+                        int retval;
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, endp->toggle_bits,
+                                u132_hcd_bulk_input_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (condition_code == TD_CC_NOERROR) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else if ((condition_code == TD_DATAUNDERRUN) &&
+                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else if (condition_code == TD_DATAUNDERRUN) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
+                                ") giving back BULK IN %s\n", urb,
+                                cc_to_text[condition_code]);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else if (condition_code == TD_CC_STALL) {
+                        endp->toggle_bits = 0x2;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else {
+                        endp->toggle_bits = 0x2;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                        dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
+                                "ULK IN code=%d %s\n", urb, condition_code,
+                                cc_to_text[condition_code]);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length = len;
+                if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
+                        TD_DATAUNDERRUN) && ((urb->transfer_flags &
+                        URB_SHORT_NOT_OK) == 0))) {
+                        int retval;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0x3,
+                                u132_hcd_configure_empty_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (condition_code == TD_CC_STALL) {
+                        up(&u132->scheduler_lock);
+                        dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
+                                "NPUT STALL urb %p\n", urb);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
+                                "PUT %s urb %p\n", cc_to_text[condition_code],
+                                urb);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                if (usb_pipein(urb->pipe)) {
+                        int retval;
+                        struct u132_ring *ring = endp->ring;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0,
+                                u132_hcd_configure_input_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        int retval;
+                        struct u132_ring *ring = endp->ring;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0,
+                                u132_hcd_configure_empty_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                u132->addr[0].address = 0;
+                endp->usb_addr = udev->usb_addr;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                        ring->number, endp, urb, 0, endp->usb_endp, 0,
+                        u132_hcd_enumeration_empty_recv);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length = len;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                        ring->number, endp, urb, address, endp->usb_endp, 0x3,
+                        u132_hcd_initial_empty_sent);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                        ring->number, endp, urb, address, endp->usb_endp, 0,
+                        u132_hcd_initial_input_recv);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_ring_work_scheduler(void *data);
+static void u132_hcd_endp_work_scheduler(void *data);
+/*
+* this work function is only executed from the work queue
+*
+*/
+static void u132_hcd_ring_work_scheduler(void *data)
+{
+        struct u132_ring *ring = data;
+        struct u132 *u132 = ring->u132;
+        down(&u132->scheduler_lock);
+        if (ring->in_use) {
+                up(&u132->scheduler_lock);
+                u132_ring_put_kref(u132, ring);
+                return;
+        } else if (ring->curr_endp) {
+                struct u132_endp *last_endp = ring->curr_endp;
+                struct list_head *scan;
+                struct list_head *head = &last_endp->endp_ring;
+                unsigned long wakeup = 0;
+                list_for_each(scan, head) {
+                        struct u132_endp *endp = list_entry(scan,
+                                struct u132_endp, endp_ring);
+                        if (endp->queue_next == endp->queue_last) {
+                        } else if ((endp->delayed == 0)
+                                || time_after_eq(jiffies, endp->jiffies)) {
+                                ring->curr_endp = endp;
+                                u132_endp_cancel_work(u132, last_endp);
+                                u132_endp_queue_work(u132, last_endp, 0);
+                                up(&u132->scheduler_lock);
+                                u132_ring_put_kref(u132, ring);
+                                return;
+                        } else {
+                                unsigned long delta = endp->jiffies - jiffies;
+                                if (delta > wakeup)
+                                        wakeup = delta;
+                        }
+                }
+                if (last_endp->queue_next == last_endp->queue_last) {
+                } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
+                        last_endp->jiffies)) {
+                        u132_endp_cancel_work(u132, last_endp);
+                        u132_endp_queue_work(u132, last_endp, 0);
+                        up(&u132->scheduler_lock);
+                        u132_ring_put_kref(u132, ring);
+                        return;
+                } else {
+                        unsigned long delta = last_endp->jiffies - jiffies;
+                        if (delta > wakeup)
+                                wakeup = delta;
+                }
+                if (wakeup > 0) {
+                        u132_ring_requeue_work(u132, ring, wakeup);
+                        up(&u132->scheduler_lock);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        u132_ring_put_kref(u132, ring);
+                        return;
+                }
+        } else {
+                up(&u132->scheduler_lock);
+                u132_ring_put_kref(u132, ring);
+                return;
+        }
+}
+
+static void u132_hcd_endp_work_scheduler(void *data)
+{
+        struct u132_ring *ring;
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        ring = endp->ring;
+        if (endp->edset_flush) {
+                endp->edset_flush = 0;
+                if (endp->dequeueing)
+                        usb_ftdi_elan_edset_flush(u132->platform_dev,
+                                ring->number, endp);
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->active) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (ring->in_use) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->queue_next == endp->queue_last) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->pipetype == PIPE_INTERRUPT) {
+                u8 address = u132->addr[endp->usb_addr].address;
+                if (ring->in_use) {
+                        up(&u132->scheduler_lock);
+                        u132_endp_put_kref(u132, endp);
+                        return;
+                } else {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_single(u132, ring, endp, urb, address,
+                                endp->toggle_bits, u132_hcd_interrupt_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else if (endp->pipetype == PIPE_CONTROL) {
+                u8 address = u132->addr[endp->usb_addr].address;
+                if (ring->in_use) {
+                        up(&u132->scheduler_lock);
+                        u132_endp_put_kref(u132, endp);
+                        return;
+                } else if (address == 0) {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, address,
+                                0x2, u132_hcd_initial_setup_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (endp->usb_addr == 0) {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
+                                u132_hcd_enumeration_address_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        int retval;
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, address,
+                                0x2, u132_hcd_configure_setup_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else {
+                if (endp->input) {
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        if (ring->in_use) {
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                                return;
+                        } else {
+                                int retval;
+                                struct urb *urb = endp->urb_list[
+                                        ENDP_QUEUE_MASK & endp->queue_next];
+                                endp->active = 1;
+                                ring->curr_endp = endp;
+                                ring->in_use = 1;
+                                up(&u132->scheduler_lock);
+                                retval = edset_input(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_bulk_input_recv);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                                return;
+                        }
+                } else {        /* output pipe */
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        if (ring->in_use) {
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                                return;
+                        } else {
+                                int retval;
+                                struct urb *urb = endp->urb_list[
+                                        ENDP_QUEUE_MASK & endp->queue_next];
+                                endp->active = 1;
+                                ring->curr_endp = endp;
+                                ring->in_use = 1;
+                                up(&u132->scheduler_lock);
+                                retval = edset_output(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_bulk_output_sent);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                                return;
+                        }
+                }
+        }
+}
+
+static void port_power(struct u132 *u132, int pn, int is_on)
+{
+        u132->port[pn].power = is_on;
+}
+
+static void u132_power(struct u132 *u132, int is_on)
+{
+        struct usb_hcd *hcd = u132_to_hcd(u132)
+                ;        /* hub is inactive unless the port is powered */
+        if (is_on) {
+                if (u132->power)
+                        return;
+                u132->power = 1;
+                hcd->self.controller->power.power_state = PMSG_ON;
+        } else {
+                u132->power = 0;
+                hcd->state = HC_STATE_HALT;
+                hcd->self.controller->power.power_state = PMSG_SUSPEND;
+        }
+}
+
+static int u132_periodic_reinit(struct u132 *u132)
+{
+        int retval;
+        u32 fi = u132->hc_fminterval & 0x03fff;
+        u32 fit;
+        u32 fminterval;
+        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+        if (retval)
+                return retval;
+        fit = fminterval & FIT;
+        retval = u132_write_pcimem(u132, fminterval,
+                (fit ^ FIT) | u132->hc_fminterval);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, periodicstart,
+                ((9 *fi) / 10) & 0x3fff);
+        if (retval)
+                return retval;
+        return 0;
+}
+
+static char *hcfs2string(int state)
+{
+        switch (state) {
+        case OHCI_USB_RESET:
+                return "reset";
+        case OHCI_USB_RESUME:
+                return "resume";
+        case OHCI_USB_OPER:
+                return "operational";
+        case OHCI_USB_SUSPEND:
+                return "suspend";
+        }
+        return "?";
+}
+
+static int u132_usb_reset(struct u132 *u132)
+{
+        int retval;
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval)
+                return retval;
+        u132->hc_control &= OHCI_CTRL_RWC;
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        return 0;
+}
+
+static int u132_init(struct u132 *u132)
+{
+        int retval;
+        u32 control;
+        u132_disable(u132);
+        u132->next_statechange =
+                jiffies; /* SMM owns the HC? not for long! */  {
+                u32 control;
+                retval = u132_read_pcimem(u132, control, &control);
+                if (retval)
+                        return retval;
+                if (control & OHCI_CTRL_IR) {
+                        u32 temp = 50;
+                        retval = u132_write_pcimem(u132, intrenable,
+                                OHCI_INTR_OC);
+                        if (retval)
+                                return retval;
+                        retval = u132_write_pcimem_byte(u132, cmdstatus,
+                                OHCI_OCR);
+                        if (retval)
+                                return retval;
+                      check:{
+                                retval = u132_read_pcimem(u132, control,
+                                        &control);
+                                if (retval)
+                                        return retval;
+                        }
+                        if (control & OHCI_CTRL_IR) {
+                                msleep(10);
+                                if (--temp == 0) {
+                                        dev_err(&u132->platform_dev->dev, "USB "
+                                                "HC takeover failed!(BIOS/SMM b"
+                                                "ug) control=%08X\n", control);
+                                        return -EBUSY;
+                                }
+                                goto check;
+                        }
+                        u132_usb_reset(u132);
+                }
+        }
+        retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        if (u132->num_ports == 0) {
+                u32 rh_a = -1;
+                retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+                if (retval)
+                        return retval;
+                u132->num_ports = rh_a & RH_A_NDP;
+                retval = read_roothub_info(u132);
+                if (retval)
+                        return retval;
+        }
+        if (u132->num_ports > MAX_U132_PORTS) {
+                return -EINVAL;
+        }
+        return 0;
+}
+
+
+/* Start an OHCI controller, set the BUS operational
+* resets USB and controller
+* enable interrupts
+*/
+static int u132_run(struct u132 *u132)
+{
+        int retval;
+        u32 control;
+        u32 status;
+        u32 fminterval;
+        u32 periodicstart;
+        u32 cmdstatus;
+        u32 roothub_a;
+        int mask = OHCI_INTR_INIT;
+        int first = u132->hc_fminterval == 0;
+        int sleep_time = 0;
+        int reset_timeout = 30;        /* ... allow extra time */
+        u132_disable(u132);
+        if (first) {
+                u32 temp;
+                retval = u132_read_pcimem(u132, fminterval, &temp);
+                if (retval)
+                        return retval;
+                u132->hc_fminterval = temp & 0x3fff;
+                if (u132->hc_fminterval != FI) {
+                }
+                u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
+        }
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval)
+                return retval;
+        dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
+                "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
+                u132->hc_control);
+        switch (u132->hc_control & OHCI_CTRL_HCFS) {
+        case OHCI_USB_OPER:
+                sleep_time = 0;
+                break;
+        case OHCI_USB_SUSPEND:
+        case OHCI_USB_RESUME:
+                u132->hc_control &= OHCI_CTRL_RWC;
+                u132->hc_control |= OHCI_USB_RESUME;
+                sleep_time = 10;
+                break;
+        default:
+                u132->hc_control &= OHCI_CTRL_RWC;
+                u132->hc_control |= OHCI_USB_RESET;
+                sleep_time = 50;
+                break;
+        }
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        msleep(sleep_time);
+        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+        if (retval)
+                return retval;
+        if (!(roothub_a & RH_A_NPS)) {
+                int temp;        /* power down each port */
+                for (temp = 0; temp < u132->num_ports; temp++) {
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[temp], RH_PS_LSDA);
+                        if (retval)
+                                return retval;
+                }
+        }
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+      retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR);
+        if (retval)
+                return retval;
+      extra:{
+                retval = u132_read_pcimem(u132, cmdstatus, &status);
+                if (retval)
+                        return retval;
+                if (0 != (status & OHCI_HCR)) {
+                        if (--reset_timeout == 0) {
+                                dev_err(&u132->platform_dev->dev, "USB HC reset"
+                                        " timed out!\n");
+                                return -ENODEV;
+                        } else {
+                                msleep(5);
+                                goto extra;
+                        }
+                }
+        }
+        if (u132->flags & OHCI_QUIRK_INITRESET) {
+                retval = u132_write_pcimem(u132, control, u132->hc_control);
+                if (retval)
+                        return retval;
+                retval = u132_read_pcimem(u132, control, &control);
+                if (retval)
+                        return retval;
+        }
+        retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, hcca, 0x00000000);
+        if (retval)
+                return retval;
+        retval = u132_periodic_reinit(u132);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
+        if (retval)
+                return retval;
+        if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+                if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
+                        u132->flags |= OHCI_QUIRK_INITRESET;
+                        goto retry;
+                } else
+                        dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
+                                "\n", fminterval, periodicstart);
+        }                        /* start controller operations */
+        u132->hc_control &= OHCI_CTRL_RWC;
+        u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+        retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, intrstatus, mask);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, intrdisable,
+                OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+                OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+                OHCI_INTR_SO);
+        if (retval)
+                return retval;        /* handle root hub init quirks ... */
+        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+        if (retval)
+                return retval;
+        roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+        if (u132->flags & OHCI_QUIRK_SUPERIO) {
+                roothub_a |= RH_A_NOCP;
+                roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+                if (retval)
+                        return retval;
+        } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+                roothub_a |= RH_A_NPS;
+                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+                if (retval)
+                        return retval;
+        }
+        retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, roothub.b,
+                (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        mdelay((roothub_a >> 23) & 0x1fe);
+        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+        return 0;
+}
+
+static void u132_hcd_stop(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                        "ed\n", hcd);
+        } else {
+                down(&u132->sw_lock);
+                msleep(100);
+                u132_power(u132, 0);
+                up(&u132->sw_lock);
+        }
+}
+
+static int u132_hcd_start(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else if (hcd->self.controller) {
+                int retval;
+                struct platform_device *pdev =
+                        to_platform_device(hcd->self.controller);
+                u16 vendor = ((struct u132_platform_data *)
+                        (pdev->dev.platform_data))->vendor;
+                u16 device = ((struct u132_platform_data *)
+                        (pdev->dev.platform_data))->device;
+                down(&u132->sw_lock);
+                msleep(10);
+                if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
+                        u132->flags = OHCI_QUIRK_AMD756;
+                } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
+                        dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
+                                "ounds unavailable\n");
+                } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
+                        u132->flags |= OHCI_QUIRK_ZFMICRO;
+                retval = u132_run(u132);
+                if (retval) {
+                        u132_disable(u132);
+                        u132->going = 1;
+                }
+                msleep(100);
+                up(&u132->sw_lock);
+                return retval;
+        } else {
+                dev_err(&u132->platform_dev->dev, "platform_device missing\n");
+                return -ENODEV;
+        }
+}
+
+static int u132_hcd_reset(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval;
+                down(&u132->sw_lock);
+                retval = u132_init(u132);
+                if (retval) {
+                        u132_disable(u132);
+                        u132->going = 1;
+                }
+                up(&u132->sw_lock);
+                return retval;
+        }
+}
+
+static int create_endpoint_and_queue_int(struct u132 *u132,
+        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+        gfp_t mem_flags)
+{
+        struct u132_ring *ring;
+        unsigned long irqs;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        ring = endp->ring = &u132->ring[0];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        endp->pipetype = usb_pipetype(urb->pipe);
+        u132_endp_init_kref(u132, endp);
+        if (usb_pipein(urb->pipe)) {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+                endp->input = 1;
+                endp->output = 0;
+                udev->endp_number_in[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        } else {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+                endp->input = 0;
+                endp->output = 1;
+                udev->endp_number_out[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        }
+        urb->hcpriv = u132;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->delayed = 1;
+        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+        endp->udev_number = address;
+        endp->usb_addr = usb_addr;
+        endp->usb_endp = usb_endp;
+        endp->queue_size = 1;
+        endp->queue_last = 0;
+        endp->queue_next = 0;
+        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
+        return 0;
+}
+
+static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp, u8 address)
+{
+        urb->hcpriv = u132;
+        endp->delayed = 1;
+        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        } else {
+                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                        GFP_ATOMIC);
+                if (urbq == NULL) {
+                        endp->queue_size -= 1;
+                        return -ENOMEM;
+                } else {
+                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+                        urbq->urb = urb;
+                }
+        }
+        return 0;
+}
+
+static int create_endpoint_and_queue_bulk(struct u132 *u132,
+        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+        gfp_t mem_flags)
+{
+        int ring_number;
+        struct u132_ring *ring;
+        unsigned long irqs;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        endp->pipetype = usb_pipetype(urb->pipe);
+        u132_endp_init_kref(u132, endp);
+        if (usb_pipein(urb->pipe)) {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+                ring_number = 3;
+                endp->input = 1;
+                endp->output = 0;
+                udev->endp_number_in[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        } else {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+                ring_number = 2;
+                endp->input = 0;
+                endp->output = 1;
+                udev->endp_number_out[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        }
+        ring = endp->ring = &u132->ring[ring_number - 1];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        urb->hcpriv = u132;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->udev_number = address;
+        endp->usb_addr = usb_addr;
+        endp->usb_endp = usb_endp;
+        endp->queue_size = 1;
+        endp->queue_last = 0;
+        endp->queue_next = 0;
+        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        u132_endp_queue_work(u132, endp, 0);
+        return 0;
+}
+
+static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+         struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp, u8 address)
+{
+        urb->hcpriv = u132;
+        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        } else {
+                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                        GFP_ATOMIC);
+                if (urbq == NULL) {
+                        endp->queue_size -= 1;
+                        return -ENOMEM;
+                } else {
+                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+                        urbq->urb = urb;
+                }
+        }
+        return 0;
+}
+
+static int create_endpoint_and_queue_control(struct u132 *u132,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+        gfp_t mem_flags)
+{
+        struct u132_ring *ring;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        ring = endp->ring = &u132->ring[0];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        u132_endp_init_kref(u132, endp);
+        u132_endp_get_kref(u132, endp);
+        if (usb_addr == 0) {
+                unsigned long irqs;
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                endp->udev_number = address;
+                endp->usb_addr = usb_addr;
+                endp->usb_endp = usb_endp;
+                endp->input = 1;
+                endp->output = 1;
+                endp->pipetype = usb_pipetype(urb->pipe);
+                u132_udev_init_kref(u132, udev);
+                u132_udev_get_kref(u132, udev);
+                udev->endp_number_in[usb_endp] = endp_number;
+                udev->endp_number_out[usb_endp] = endp_number;
+                urb->hcpriv = u132;
+                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                endp->queue_size = 1;
+                endp->queue_last = 0;
+                endp->queue_next = 0;
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                u132_endp_queue_work(u132, endp, 0);
+                return 0;
+        } else {                /*(usb_addr > 0) */
+                unsigned long irqs;
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                endp->udev_number = address;
+                endp->usb_addr = usb_addr;
+                endp->usb_endp = usb_endp;
+                endp->input = 1;
+                endp->output = 1;
+                endp->pipetype = usb_pipetype(urb->pipe);
+                u132_udev_get_kref(u132, udev);
+                udev->enumeration = 2;
+                udev->endp_number_in[usb_endp] = endp_number;
+                udev->endp_number_out[usb_endp] = endp_number;
+                urb->hcpriv = u132;
+                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                endp->queue_size = 1;
+                endp->queue_last = 0;
+                endp->queue_next = 0;
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                u132_endp_queue_work(u132, endp, 0);
+                return 0;
+        }
+}
+
+static int queue_control_on_old_endpoint(struct u132 *u132,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp)
+{
+        if (usb_addr == 0) {
+                if (usb_pipein(urb->pipe)) {
+                        urb->hcpriv = u132;
+                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                                endp->urb_list[ENDP_QUEUE_MASK &
+                                        endp->queue_last++] = urb;
+                        } else {
+                                struct u132_urbq *urbq =
+                                        kmalloc(sizeof(struct u132_urbq),
+                                        GFP_ATOMIC);
+                                if (urbq == NULL) {
+                                        endp->queue_size -= 1;
+                                        return -ENOMEM;
+                                } else {
+                                        list_add_tail(&urbq->urb_more,
+                                                &endp->urb_more);
+                                        urbq->urb = urb;
+                                }
+                        }
+                        return 0;
+                } else {        /* usb_pipeout(urb->pipe) */
+                        struct u132_addr *addr = &u132->addr[usb_dev->devnum];
+                        int I = MAX_U132_UDEVS;
+                        int i = 0;
+                        while (--I > 0) {
+                                struct u132_udev *udev = &u132->udev[++i];
+                                if (udev->usb_device) {
+                                        continue;
+                                } else {
+                                        udev->enumeration = 1;
+                                        u132->addr[0].address = i;
+                                        endp->udev_number = i;
+                                        udev->udev_number = i;
+                                        udev->usb_addr = usb_dev->devnum;
+                                        u132_udev_init_kref(u132, udev);
+                                        udev->endp_number_in[usb_endp] =
+                                                endp->endp_number;
+                                        u132_udev_get_kref(u132, udev);
+                                        udev->endp_number_out[usb_endp] =
+                                                endp->endp_number;
+                                        udev->usb_device = usb_dev;
+                                        ((u8 *) (urb->setup_packet))[2] =
+                                                addr->address = i;
+                                        u132_udev_get_kref(u132, udev);
+                                        break;
+                                }
+                        }
+                        if (I == 0) {
+                                dev_err(&u132->platform_dev->dev, "run out of d"
+                                        "evice space\n");
+                                return -EINVAL;
+                        }
+                        urb->hcpriv = u132;
+                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                                endp->urb_list[ENDP_QUEUE_MASK &
+                                        endp->queue_last++] = urb;
+                        } else {
+                                struct u132_urbq *urbq =
+                                        kmalloc(sizeof(struct u132_urbq),
+                                        GFP_ATOMIC);
+                                if (urbq == NULL) {
+                                        endp->queue_size -= 1;
+                                        return -ENOMEM;
+                                } else {
+                                        list_add_tail(&urbq->urb_more,
+                                                &endp->urb_more);
+                                        urbq->urb = urb;
+                                }
+                        }
+                        return 0;
+                }
+        } else {                /*(usb_addr > 0) */
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                urb->hcpriv = u132;
+                if (udev->enumeration == 2) {
+                } else
+                        udev->enumeration = 2;
+                if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                                urb;
+                } else {
+                        struct u132_urbq *urbq =
+                                kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
+                        if (urbq == NULL) {
+                                endp->queue_size -= 1;
+                                return -ENOMEM;
+                        } else {
+                                list_add_tail(&urbq->urb_more, &endp->urb_more);
+                                urbq->urb = urb;
+                        }
+                }
+                return 0;
+        }
+}
+
+static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+        struct urb *urb, gfp_t mem_flags)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (irqs_disabled()) {
+                if (__GFP_WAIT & mem_flags) {
+                        printk(KERN_ERR "invalid context for function that migh"
+                                "t sleep\n");
+                        return -EINVAL;
+                }
+        }
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                return -ESHUTDOWN;
+        } else {
+                u8 usb_addr = usb_pipedevice(urb->pipe);
+                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+                struct usb_device *usb_dev = urb->dev;
+                if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+                        u8 address = u132->addr[usb_addr].address;
+                        struct u132_udev *udev = &u132->udev[address];
+                        struct u132_endp *endp = hep->hcpriv;
+                        urb->actual_length = 0;
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_int_on_old_endpoint(u132, udev,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp, address);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp,
+                                                msecs_to_jiffies(urb->interval))
+                                                ;
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else {        /*(endp == NULL) */
+                                return create_endpoint_and_queue_int(u132, udev,
+                                         hep, urb, usb_dev, usb_addr, usb_endp,
+                                        address, mem_flags);
+                        }
+                } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                        dev_err(&u132->platform_dev->dev, "the hardware does no"
+                                "t support PIPE_ISOCHRONOUS\n");
+                        return -EINVAL;
+                } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+                        u8 address = u132->addr[usb_addr].address;
+                        struct u132_udev *udev = &u132->udev[address];
+                        struct u132_endp *endp = hep->hcpriv;
+                        urb->actual_length = 0;
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_bulk_on_old_endpoint(u132, udev,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp, address);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp, 0);
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else
+                                return create_endpoint_and_queue_bulk(u132,
+                                        udev, hep, urb, usb_dev, usb_addr,
+                                        usb_endp, address, mem_flags);
+                } else {
+                        struct u132_endp *endp = hep->hcpriv;
+                        u16 urb_size = 8;
+                        u8 *b = urb->setup_packet;
+                        int i = 0;
+                        char data[30 *3 + 4];
+                        char *d = data;
+                        int m = (sizeof(data) - 1) / 3;
+                        int l = 0;
+                        data[0] = 0;
+                        while (urb_size-- > 0) {
+                                if (i > m) {
+                                } else if (i++ < m) {
+                                        int w = sprintf(d, " %02X", *b++);
+                                        d += w;
+                                        l += w;
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_control_on_old_endpoint(u132,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp, 0);
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else
+                                return create_endpoint_and_queue_control(u132,
+                                        hep, urb, usb_dev, usb_addr, usb_endp,
+                                        mem_flags);
+                }
+        }
+}
+
+static int dequeue_from_overflow_chain(struct u132 *u132,
+        struct u132_endp *endp, struct urb *urb)
+{
+        struct list_head *scan;
+        struct list_head *head = &endp->urb_more;
+        list_for_each(scan, head) {
+                struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
+                        urb_more);
+                if (urbq->urb == urb) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        list_del(scan);
+                        endp->queue_size -= 1;
+                        urb->error_count = 0;
+                        urb->hcpriv = NULL;
+                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        return 0;
+                } else
+                        continue;
+        }
+        dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
+                "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
+                "\n", urb, endp->endp_number, endp, endp->ring->number,
+                endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                endp->usb_endp, endp->usb_addr, endp->queue_size,
+                endp->queue_next, endp->queue_last);
+        return -EINVAL;
+}
+
+static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb)
+{
+        unsigned long irqs;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        if (endp->queue_size == 0) {
+                dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+                        "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+                        endp->endp_number, endp, endp->ring->number,
+                        endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                        endp->usb_endp, endp->usb_addr);
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                return -EINVAL;
+        }
+        if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
+                if (endp->active) {
+                        endp->dequeueing = 1;
+                        endp->edset_flush = 1;
+                        u132_endp_queue_work(u132, endp, 0);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        urb->hcpriv = NULL;
+                        return 0;
+                } else {
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        u132_hcd_abandon_urb(u132, endp, urb, urb->status);
+                        return 0;
+                }
+        } else {
+                u16 queue_list = 0;
+                u16 queue_size = endp->queue_size;
+                u16 queue_scan = endp->queue_next;
+                struct urb **urb_slot = NULL;
+                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                        if (urb == endp->urb_list[ENDP_QUEUE_MASK &
+                                ++queue_scan]) {
+                                urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                        queue_scan];
+                                break;
+                        } else
+                                continue;
+                }
+                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                        *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
+                                ++queue_scan];
+                        urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                queue_scan];
+                }
+                if (urb_slot) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        endp->queue_size -= 1;
+                        if (list_empty(&endp->urb_more)) {
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                        } else {
+                                struct list_head *next = endp->urb_more.next;
+                                struct u132_urbq *urbq = list_entry(next,
+                                        struct u132_urbq, urb_more);
+                                list_del(next);
+                                *urb_slot = urbq->urb;
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                kfree(urbq);
+                        } urb->error_count = 0;
+                        urb->hcpriv = NULL;
+                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        return 0;
+                } else if (list_empty(&endp->urb_more)) {
+                        dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+                                "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
+                                "=%d size=%d next=%04X last=%04X\n", urb,
+                                endp->endp_number, endp, endp->ring->number,
+                                endp->input ? 'I' : ' ',
+                                endp->output ? 'O' : ' ', endp->usb_endp,
+                                endp->usb_addr, endp->queue_size,
+                                endp->queue_next, endp->queue_last);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        return -EINVAL;
+                } else {
+                        int retval = dequeue_from_overflow_chain(u132, endp,
+                                urb);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        return retval;
+                }
+        }
+}
+
+static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 2) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else {
+                u8 usb_addr = usb_pipedevice(urb->pipe);
+                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                if (usb_pipein(urb->pipe)) {
+                        u8 endp_number = udev->endp_number_in[usb_endp];
+                        struct u132_endp *endp = u132->endp[endp_number - 1];
+                        return u132_endp_urb_dequeue(u132, endp, urb);
+                } else {
+                        u8 endp_number = udev->endp_number_out[usb_endp];
+                        struct u132_endp *endp = u132->endp[endp_number - 1];
+                        return u132_endp_urb_dequeue(u132, endp, urb);
+                }
+        }
+}
+
+static void u132_endpoint_disable(struct usb_hcd *hcd,
+        struct usb_host_endpoint *hep)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 2) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else {
+                struct u132_endp *endp = hep->hcpriv;
+                if (endp)
+                        u132_endp_put_kref(u132, endp);
+        }
+}
+
+static int u132_get_frame(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int frame = 0;
+                dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
+                msleep(100);
+                return frame;
+        }
+}
+
+static int u132_roothub_descriptor(struct u132 *u132,
+        struct usb_hub_descriptor *desc)
+{
+        int retval;
+        u16 temp;
+        u32 rh_a = -1;
+        u32 rh_b = -1;
+        retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+        if (retval)
+                return retval;
+        desc->bDescriptorType = 0x29;
+        desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
+        desc->bHubContrCurrent = 0;
+        desc->bNbrPorts = u132->num_ports;
+        temp = 1 + (u132->num_ports / 8);
+        desc->bDescLength = 7 + 2 *temp;
+        temp = 0;
+        if (rh_a & RH_A_NPS)
+                temp |= 0x0002;
+        if (rh_a & RH_A_PSM)
+                temp |= 0x0001;
+        if (rh_a & RH_A_NOCP) {
+                temp |= 0x0010;
+        } else if (rh_a & RH_A_OCPM)
+                temp |= 0x0008;
+        desc->wHubCharacteristics = cpu_to_le16(temp);
+        retval = u132_read_pcimem(u132, roothub.b, &rh_b);
+        if (retval)
+                return retval;
+        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+        desc->bitmap[0] = rh_b & RH_B_DR;
+        if (u132->num_ports > 7) {
+                desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
+                desc->bitmap[2] = 0xff;
+        } else
+                desc->bitmap[1] = 0xff;
+        return 0;
+}
+
+static int u132_roothub_status(struct u132 *u132, __le32 *desc)
+{
+        u32 rh_status = -1;
+        int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
+        *desc = cpu_to_le32(rh_status);
+        return ret_status;
+}
+
+static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int port = wIndex - 1;
+                u32 rh_portstatus = -1;
+                int ret_portstatus = u132_read_pcimem(u132,
+                        roothub.portstatus[port], &rh_portstatus);
+                *desc = cpu_to_le32(rh_portstatus);
+                if (*(u16 *) (desc + 2)) {
+                        dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
+                                "ge = %08X\n", port, *desc);
+                }
+                return ret_portstatus;
+        }
+}
+
+
+/* this timer value might be vendor-specific ... */
+#define PORT_RESET_HW_MSEC 10
+#define PORT_RESET_MSEC 10
+/* wrap-aware logic morphed from <linux/jiffies.h> */
+#define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
+static int u132_roothub_portreset(struct u132 *u132, int port_index)
+{
+        int retval;
+        u32 fmnumber;
+        u16 now;
+        u16 reset_done;
+        retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+        if (retval)
+                return retval;
+        now = fmnumber;
+        reset_done = now + PORT_RESET_MSEC;
+        do {
+                u32 portstat;
+                do {
+                        retval = u132_read_pcimem(u132,
+                                roothub.portstatus[port_index], &portstat);
+                        if (retval)
+                                return retval;
+                        if (RH_PS_PRS & portstat) {
+                                continue;
+                        } else
+                                break;
+                } while (tick_before(now, reset_done));
+                if (RH_PS_PRS & portstat)
+                        return -ENODEV;
+                if (RH_PS_CCS & portstat) {
+                        if (RH_PS_PRSC & portstat) {
+                                retval = u132_write_pcimem(u132,
+                                        roothub.portstatus[port_index],
+                                        RH_PS_PRSC);
+                                if (retval)
+                                        return retval;
+                        }
+                } else
+                        break;        /* start the next reset,
+                                sleep till it's probably done */
+                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                         RH_PS_PRS);
+                if (retval)
+                        return retval;
+                msleep(PORT_RESET_HW_MSEC);
+                retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+                if (retval)
+                        return retval;
+                now = fmnumber;
+        } while (tick_before(now, reset_done));
+        return 0;
+}
+
+static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
+        u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int retval;
+                int port_index = wIndex - 1;
+                struct u132_port *port = &u132->port[port_index];
+                port->Status &= ~(1 << wValue);
+                switch (wValue) {
+                case USB_PORT_FEAT_SUSPEND:
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[port_index], RH_PS_PSS);
+                        if (retval)
+                                return retval;
+                        return 0;
+                case USB_PORT_FEAT_POWER:
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[port_index], RH_PS_PPS);
+                        if (retval)
+                                return retval;
+                        return 0;
+                case USB_PORT_FEAT_RESET:
+                        retval = u132_roothub_portreset(u132, port_index);
+                        if (retval)
+                                return retval;
+                        return 0;
+                default:
+                        return -EPIPE;
+                }
+        }
+}
+
+static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
+        u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int port_index = wIndex - 1;
+                u32 temp;
+                int retval;
+                struct u132_port *port = &u132->port[port_index];
+                port->Status &= ~(1 << wValue);
+                switch (wValue) {
+                case USB_PORT_FEAT_ENABLE:
+                        temp = RH_PS_CCS;
+                        break;
+                case USB_PORT_FEAT_C_ENABLE:
+                        temp = RH_PS_PESC;
+                        break;
+                case USB_PORT_FEAT_SUSPEND:
+                        temp = RH_PS_POCI;
+                        if ((u132->hc_control & OHCI_CTRL_HCFS)
+                                != OHCI_USB_OPER) {
+                                dev_err(&u132->platform_dev->dev, "TODO resume_"
+                                        "root_hub\n");
+                        }
+                        break;
+                case USB_PORT_FEAT_C_SUSPEND:
+                        temp = RH_PS_PSSC;
+                        break;
+                case USB_PORT_FEAT_POWER:
+                        temp = RH_PS_LSDA;
+                        break;
+                case USB_PORT_FEAT_C_CONNECTION:
+                        temp = RH_PS_CSC;
+                        break;
+                case USB_PORT_FEAT_C_OVER_CURRENT:
+                        temp = RH_PS_OCIC;
+                        break;
+                case USB_PORT_FEAT_C_RESET:
+                        temp = RH_PS_PRSC;
+                        break;
+                default:
+                        return -EPIPE;
+                }
+                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                         temp);
+                if (retval)
+                        return retval;
+                return 0;
+        }
+}
+
+
+/* the virtual root hub timer IRQ checks for hub status*/
+static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
+                        "ed %d\n", hcd, u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                        "ed\n", hcd);
+                dump_stack();
+                return -ESHUTDOWN;
+        } else {
+                int i, changed = 0, length = 1;
+                if (u132->flags & OHCI_QUIRK_AMD756) {
+                        if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
+                                dev_err(&u132->platform_dev->dev, "bogus NDP, r"
+                                        "ereads as NDP=%d\n",
+                                        u132->hc_roothub_a & RH_A_NDP);
+                                goto done;
+                        }
+                }
+                if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
+                        buf[0] = changed = 1;
+                } else
+                        buf[0] = 0;
+                if (u132->num_ports > 7) {
+                        buf[1] = 0;
+                        length++;
+                }
+                for (i = 0; i < u132->num_ports; i++) {
+                        if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
+                                RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
+                                RH_PS_PRSC)) {
+                                changed = 1;
+                                if (i < 7) {
+                                        buf[0] |= 1 << (i + 1);
+                                } else
+                                        buf[1] |= 1 << (i - 7);
+                                continue;
+                        }
+                        if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
+                                continue;
+                        }
+                        if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
+                                continue;
+                        }
+                }
+              done:return changed ? length : 0;
+        }
+}
+
+static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+        u16 wIndex, char *buf, u16 wLength)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                down(&u132->sw_lock);
+                switch (typeReq) {
+                case ClearHubFeature:
+                        switch (wValue) {
+                        case C_HUB_OVER_CURRENT:
+                        case C_HUB_LOCAL_POWER:
+                                break;
+                        default:
+                                goto stall;
+                        }
+                        break;
+                case SetHubFeature:
+                        switch (wValue) {
+                        case C_HUB_OVER_CURRENT:
+                        case C_HUB_LOCAL_POWER:
+                                break;
+                        default:
+                                goto stall;
+                        }
+                        break;
+                case ClearPortFeature:{
+                                retval = u132_roothub_clearportfeature(u132,
+                                        wValue, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetHubDescriptor:{
+                                retval = u132_roothub_descriptor(u132,
+                                        (struct usb_hub_descriptor *)buf);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetHubStatus:{
+                                retval = u132_roothub_status(u132,
+                                        (__le32 *) buf);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetPortStatus:{
+                                retval = u132_roothub_portstatus(u132,
+                                        (__le32 *) buf, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case SetPortFeature:{
+                                retval = u132_roothub_setportfeature(u132,
+                                        wValue, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                default:
+                        goto stall;
+                      error:u132_disable(u132);
+                        u132->going = 1;
+                        break;
+                      stall:retval = -EPIPE;
+                        break;
+                }
+                up(&u132->sw_lock);
+                return retval;
+        }
+}
+
+static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static void u132_hub_irq_enable(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else if (u132->going > 0)
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+}
+
+
+#ifdef CONFIG_PM
+static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_hcd_resume(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_bus_suspend(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_bus_resume(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+#else
+#define u132_hcd_suspend NULL
+#define u132_hcd_resume NULL
+#define u132_bus_suspend NULL
+#define u132_bus_resume NULL
+#endif
+static struct hc_driver u132_hc_driver = {
+        .description = hcd_name,
+        .hcd_priv_size = sizeof(struct u132),
+        .irq = NULL,
+        .flags = HCD_USB11 | HCD_MEMORY,
+        .reset = u132_hcd_reset,
+        .start = u132_hcd_start,
+        .suspend = u132_hcd_suspend,
+        .resume = u132_hcd_resume,
+        .stop = u132_hcd_stop,
+        .urb_enqueue = u132_urb_enqueue,
+        .urb_dequeue = u132_urb_dequeue,
+        .endpoint_disable = u132_endpoint_disable,
+        .get_frame_number = u132_get_frame,
+        .hub_status_data = u132_hub_status_data,
+        .hub_control = u132_hub_control,
+        .bus_suspend = u132_bus_suspend,
+        .bus_resume = u132_bus_resume,
+        .start_port_reset = u132_start_port_reset,
+        .hub_irq_enable = u132_hub_irq_enable,
+};
+
+/*
+* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
+* is held for writing, thus this module must not call usb_remove_hcd()
+* synchronously - but instead should immediately stop activity to the
+* device and ansynchronously call usb_remove_hcd()
+*/
+static int __devexit u132_remove(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        if (hcd) {
+                struct u132 *u132 = hcd_to_u132(hcd);
+                dump_stack();
+                if (u132->going++ > 1) {
+                        return -ENODEV;
+                } else {
+                        int rings = MAX_U132_RINGS;
+                        int endps = MAX_U132_ENDPS;
+                        msleep(100);
+                        down(&u132->sw_lock);
+                        u132_monitor_cancel_work(u132);
+                        while (rings-- > 0) {
+                                struct u132_ring *ring = &u132->ring[rings];
+                                u132_ring_cancel_work(u132, ring);
+                        } while (endps-- > 0) {
+                                struct u132_endp *endp = u132->endp[endps];
+                                if (endp)
+                                        u132_endp_cancel_work(u132, endp);
+                        }
+                        u132->going += 1;
+                        printk(KERN_INFO "removing device u132.%d\n",
+                                u132->sequence_num);
+                        up(&u132->sw_lock);
+                        usb_remove_hcd(hcd);
+                        u132_u132_put_kref(u132);
+                        return 0;
+                }
+        } else
+                return 0;
+}
+
+static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
+{
+        int rings = MAX_U132_RINGS;
+        int ports = MAX_U132_PORTS;
+        int addrs = MAX_U132_ADDRS;
+        int udevs = MAX_U132_UDEVS;
+        int endps = MAX_U132_ENDPS;
+        u132->board = pdev->dev.platform_data;
+        u132->platform_dev = pdev;
+        u132->power = 0;
+        u132->reset = 0;
+        init_MUTEX(&u132->sw_lock);
+        init_MUTEX(&u132->scheduler_lock);
+        while (rings-- > 0) {
+                struct u132_ring *ring = &u132->ring[rings];
+                ring->u132 = u132;
+                ring->number = rings + 1;
+                ring->length = 0;
+                ring->curr_endp = NULL;
+                INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler,
+                        (void *)ring);
+        } down(&u132->sw_lock);
+        INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132);
+        while (ports-- > 0) {
+                struct u132_port *port = &u132->port[ports];
+                port->u132 = u132;
+                port->reset = 0;
+                port->enable = 0;
+                port->power = 0;
+                port->Status = 0;
+        } while (addrs-- > 0) {
+                struct u132_addr *addr = &u132->addr[addrs];
+                addr->address = 0;
+        } while (udevs-- > 0) {
+                struct u132_udev *udev = &u132->udev[udevs];
+                int i = ARRAY_SIZE(udev->endp_number_in);
+                int o = ARRAY_SIZE(udev->endp_number_out);
+                udev->usb_device = NULL;
+                udev->udev_number = 0;
+                udev->usb_addr = 0;
+                udev->portnumber = 0;
+                while (i-- > 0) {
+                        udev->endp_number_in[i] = 0;
+                }
+                while (o-- > 0) {
+                        udev->endp_number_out[o] = 0;
+                }
+        }
+        while (endps-- > 0) {
+                u132->endp[endps] = NULL;
+        }
+        up(&u132->sw_lock);
+        return;
+}
+
+static int __devinit u132_probe(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd;
+        msleep(100);
+        if (u132_exiting > 0) {
+                return -ENODEV;
+        }                        /* refuse to confuse usbcore */
+        if (pdev->dev.dma_mask) {
+                return -EINVAL;
+        }
+        hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+        if (!hcd) {
+                printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
+                        );
+                ftdi_elan_gone_away(pdev);
+                return -ENOMEM;
+        } else {
+                int retval = 0;
+                struct u132 *u132 = hcd_to_u132(hcd);
+                hcd->rsrc_start = 0;
+                down(&u132_module_lock);
+                list_add_tail(&u132->u132_list, &u132_static_list);
+                u132->sequence_num = ++u132_instances;
+                up(&u132_module_lock);
+                u132_u132_init_kref(u132);
+                u132_initialise(u132, pdev);
+                hcd->product_desc = "ELAN U132 Host Controller";
+                retval = usb_add_hcd(hcd, 0, 0);
+                if (retval != 0) {
+                        dev_err(&u132->platform_dev->dev, "init error %d\n",
+                                retval);
+                        u132_u132_put_kref(u132);
+                        return retval;
+                } else {
+                        u132_monitor_queue_work(u132, 100);
+                        return 0;
+                }
+        }
+}
+
+
+#ifdef CONFIG_PM
+/* for this device there's no useful distinction between the controller
+* and its root hub, except that the root hub only gets direct PM calls
+* when CONFIG_USB_SUSPEND is enabled.
+*/
+static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                if (state.event == PM_EVENT_FREEZE) {
+                        retval = u132_bus_suspend(hcd);
+                } else if (state.event == PM_EVENT_SUSPEND) {
+                        int ports = MAX_U132_PORTS;
+                        while (ports-- > 0) {
+                                port_power(u132, ports, 0);
+                        }
+                }
+                if (retval == 0)
+                        pdev->dev.power.power_state = state;
+                return retval;
+        }
+}
+
+static int u132_resume(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+                        int ports = MAX_U132_PORTS;
+                        while (ports-- > 0) {
+                                port_power(u132, ports, 1);
+                        }
+                        retval = 0;
+                } else {
+                        pdev->dev.power.power_state = PMSG_ON;
+                        retval = u132_bus_resume(hcd);
+                }
+                return retval;
+        }
+}
+
+#else
+#define u132_suspend NULL
+#define u132_resume NULL
+#endif
+/*
+* this driver is loaded explicitely by ftdi_u132
+*
+* the platform_driver struct is static because it is per type of module
+*/
+static struct platform_driver u132_platform_driver = {
+        .probe = u132_probe,
+        .remove = __devexit_p(u132_remove),
+        .suspend = u132_suspend,
+        .resume = u132_resume,
+        .driver = {
+                   .name = (char *)hcd_name,
+                   .owner = THIS_MODULE,
+                   },
+};
+static int __init u132_hcd_init(void)
+{
+        int retval;
+        INIT_LIST_HEAD(&u132_static_list);
+        u132_instances = 0;
+        u132_exiting = 0;
+        init_MUTEX(&u132_module_lock);
+        if (usb_disabled())
+                return -ENODEV;
+        printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
+                __DATE__);
+        workqueue = create_singlethread_workqueue("u132");
+        retval = platform_driver_register(&u132_platform_driver);
+        return retval;
+}
+
+
+module_init(u132_hcd_init);
+static void __exit u132_hcd_exit(void)
+{
+        struct u132 *u132;
+        struct u132 *temp;
+        down(&u132_module_lock);
+        u132_exiting += 1;
+        up(&u132_module_lock);
+        list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
+                platform_device_unregister(u132->platform_dev);
+        } platform_driver_unregister(&u132_platform_driver);
+        printk(KERN_INFO "u132-hcd driver deregistered\n");
+        wait_event(u132_hcd_wait, u132_instances == 0);
+        flush_workqueue(workqueue);
+        destroy_workqueue(workqueue);
+}
+
+
+module_exit(u132_hcd_exit);
+MODULE_LICENSE("GPL");
index dc286a48cafdeba4d687069a294a94d2980e47d1..e345f15b7d87b5e545c4d1ea0a5c9416cf38ef20 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "uhci-hcd.h"
 
-#define uhci_debug_operations (* (struct file_operations *) NULL)
+#define uhci_debug_operations (* (const struct file_operations *) NULL)
 static struct dentry *uhci_debugfs_root;
 
 #ifdef DEBUG
@@ -428,7 +428,7 @@ struct uhci_debug {
 
 static int uhci_debug_open(struct inode *inode, struct file *file)
 {
-       struct uhci_hcd *uhci = inode->u.generic_ip;
+       struct uhci_hcd *uhci = inode->i_private;
        struct uhci_debug *up;
        int ret = -ENOMEM;
        unsigned long flags;
@@ -500,7 +500,7 @@ static int uhci_debug_release(struct inode *inode, struct file *file)
 }
 
 #undef uhci_debug_operations
-static struct file_operations uhci_debug_operations = {
+static const struct file_operations uhci_debug_operations = {
        .owner =        THIS_MODULE,
        .open =         uhci_debug_open,
        .llseek =       uhci_debug_lseek,
index b7402ceb3e93c535f9223548770f193657141b9d..eb4eab98e8bf7ec62c1015e746f9a2e43777e852 100644 (file)
@@ -913,8 +913,7 @@ static int __init uhci_hcd_init(void)
        return 0;
 
 init_failed:
-       if (kmem_cache_destroy(uhci_up_cachep))
-               warn("not all urb_privs were freed!");
+       kmem_cache_destroy(uhci_up_cachep);
 
 up_failed:
        debugfs_remove(uhci_debugfs_root);
@@ -930,10 +929,7 @@ errbuf_failed:
 static void __exit uhci_hcd_cleanup(void) 
 {
        pci_unregister_driver(&uhci_pci_driver);
-       
-       if (kmem_cache_destroy(uhci_up_cachep))
-               warn("not all urb_privs were freed!");
-
+       kmem_cache_destroy(uhci_up_cachep);
        debugfs_remove(uhci_debugfs_root);
        kfree(errbuf);
 }
index c545ef92fe29ad130a7b1de0088a945e4bd29751..16fb72eb6fc9213785216414293d7f27dedd8546 100644 (file)
@@ -84,6 +84,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
                unsigned long port_addr)
 {
        int status;
+       int i;
 
        if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
                CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
@@ -92,9 +93,14 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
 
                /* The controller won't actually turn off the RD bit until
                 * it has had a chance to send a low-speed EOP sequence,
-                * which takes 3 bit times (= 2 microseconds).  We'll delay
-                * slightly longer for good luck. */
-               udelay(4);
+                * which is supposed to take 3 bit times (= 2 microseconds).
+                * Experiments show that some controllers take longer, so
+                * we'll poll for completion. */
+               for (i = 0; i < 10; ++i) {
+                       if (!(inw(port_addr) & USBPORTSC_RD))
+                               break;
+                       udelay(1);
+               }
        }
        clear_bit(port, &uhci->resuming_ports);
 }
index 08daf400f9854c9b19029c74d1534a0f64dade0a..ca6305c1d64c67ba7b529ec2b8db2fa6a1ee0f3d 100644 (file)
@@ -424,7 +424,7 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
  ***************************************************************************/
 
 static struct usb_driver mdc800_usb_driver;
-static struct file_operations mdc800_device_ops;
+static const struct file_operations mdc800_device_ops;
 static struct usb_class_driver mdc800_class = {
        .name =         "mdc800%d",
        .fops =         &mdc800_device_ops,
@@ -941,7 +941,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
 ****************************************************************************/
 
 /* File Operations of this drivers */
-static struct file_operations mdc800_device_ops =
+static const struct file_operations mdc800_device_ops =
 {
        .owner =        THIS_MODULE,
        .read =         mdc800_device_read,
index b2bafc37c414968f91e02df4e96ed2b93527f6d0..5f861331932a670affdb9769f8ef32571b957269 100644 (file)
@@ -225,7 +225,7 @@ static inline void mts_debug_dump(struct mts_desc* desc) {
 }
 
 
-static inline void mts_show_command(Scsi_Cmnd *srb)
+static inline void mts_show_command(struct scsi_cmnd *srb)
 {
        char *what = NULL;
 
@@ -309,7 +309,7 @@ static inline void mts_show_command(Scsi_Cmnd *srb)
 
 #else
 
-static inline void mts_show_command(Scsi_Cmnd * dummy)
+static inline void mts_show_command(struct scsi_cmnd * dummy)
 {
 }
 
@@ -338,7 +338,7 @@ static int mts_slave_configure (struct scsi_device *s)
        return 0;
 }
 
-static int mts_scsi_abort (Scsi_Cmnd *srb)
+static int mts_scsi_abort(struct scsi_cmnd *srb)
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
 
@@ -349,7 +349,7 @@ static int mts_scsi_abort (Scsi_Cmnd *srb)
        return FAILED;
 }
 
-static int mts_scsi_host_reset (Scsi_Cmnd *srb)
+static int mts_scsi_host_reset(struct scsi_cmnd *srb)
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
        int result, rc;
@@ -366,8 +366,8 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb)
        return result ? FAILED : SUCCESS;
 }
 
-static
-int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
+static int
+mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback);
 
 static void mts_transfer_cleanup( struct urb *transfer );
 static void mts_do_sg(struct urb * transfer, struct pt_regs *regs);
@@ -537,7 +537,7 @@ static const unsigned char mts_direction[256/8] = {
 #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
 
 static void
-mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
+mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc)
 {
        int pipe;
        struct scatterlist * sg;
@@ -588,8 +588,8 @@ mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
 }
 
 
-static
-int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
+static int
+mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback)
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
        int err = 0;
index 926d4bdc6746cb48b7352fe1d338f9e111d426c0..d5d62a93905885900ed64ca6596da41f55ea5942 100644 (file)
@@ -8,14 +8,14 @@
  *
  */
 
-typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *);
+typedef void (*mts_scsi_cmnd_callback)(struct scsi_cmnd *);
 
 
 struct mts_transfer_context
 {
        struct mts_desc* instance;
        mts_scsi_cmnd_callback final_callback;
-       Scsi_Cmnd *srb;
+       struct scsi_cmnd *srb;
        
        void* data;
        unsigned data_length;
index 650103bc9618434ad769972ebb6db5e8cf76ae01..a102a58fe3612c89589817dadcdd9b6c566d5cf4 100644 (file)
@@ -205,10 +205,12 @@ config USB_TOUCHSCREEN
        depends on USB && INPUT
        ---help---
          USB Touchscreen driver for:
-         - eGalax Touchkit USB
+         - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
          - PanJit TouchSet USB
-         - 3M MicroTouch USB
+         - 3M MicroTouch USB (EX II series)
          - ITM
+         - some other eTurboTouch
+         - Gunze AHL61
 
          Have a look at <http://linux.chapter7.ch/touchkit/> for
          a usage description and the required user-space stuff.
@@ -218,7 +220,7 @@ config USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_EGALAX
        default y
-       bool "eGalax device support" if EMBEDDED
+       bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
        depends on USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_PANJIT
@@ -228,7 +230,7 @@ config USB_TOUCHSCREEN_PANJIT
 
 config USB_TOUCHSCREEN_3M
        default y
-       bool "3M/Microtouch device support" if EMBEDDED
+       bool "3M/Microtouch EX II series device support" if EMBEDDED
        depends on USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_ITM
@@ -236,6 +238,16 @@ config USB_TOUCHSCREEN_ITM
        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_YEALINK
        tristate "Yealink usb-p1k voip phone"
        depends on USB && INPUT && EXPERIMENTAL
@@ -326,3 +338,13 @@ config USB_APPLETOUCH
 
          To compile this driver as a module, choose M here: the
          module will be called appletouch.
+
+config USB_TRANCEVIBRATOR
+       tristate "PlayStation 2 Trance Vibrator driver support"
+       depends on USB
+       help
+         Say Y here if you want to connect a PlayStation 2 Trance Vibrator
+         device to your computer's USB port.
+
+         To compile this driver as a module, choose M here: the
+         module will be called trancevibrator.
index 764114529c56af10071d2dfa94f21717edf34e18..48551be324ac61fb102a530fcd34ad0205fbed57 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 # Multipart objects.
+wacom-objs     := wacom_sys.o wacom_wac.o
 usbhid-objs    := hid-core.o
 
 # Optional parts of multipart objects.
@@ -44,6 +45,7 @@ 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_TRANCEVIBRATOR)       += trancevibrator.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 18c10e150ef37df3e2e78878dace708f4a9bba37..d83603ba40ae257aa344b5f7774c8a926e9789b5 100644 (file)
@@ -141,10 +141,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
 
        endpoint = &interface->endpoint[0].desc;
 
-       if (!(endpoint->bEndpointAddress & 0x80))
-               return -ENODEV;
-
-       if ((endpoint->bmAttributes & 3) != 3)
+       if (!usb_endpoint_is_int_in(endpoint))
                return -ENODEV;
 
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
index 044faa07e2976f49bf81bf8514f4c3b4575babbe..0aa9cc2bfd69fb5a067beaeb9664aea005abf4e3 100644 (file)
@@ -436,10 +436,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        iface_desc = iface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
                endpoint = &iface_desc->endpoint[i].desc;
-               if (!int_in_endpointAddr &&
-                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_INT)) {
+               if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
                        /* we found an interrupt in endpoint */
                        int_in_endpointAddr = endpoint->bEndpointAddress;
                        break;
index 3719fcb04b8f4bb01973f6dea86d4918e3dd1433..3558d7ed99b96e9cafdce2ea5002fb74ed4292e2 100644 (file)
@@ -732,12 +732,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
        endpoint_in = &iface_host->endpoint[0].desc;
        endpoint_out = &iface_host->endpoint[1].desc;
 
-       if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) {
-               err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
-               return -ENODEV;
-       }
-       if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
-               err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
+       if (!usb_endpoint_is_int_in(endpoint_in)) {
+               err("%s: Unexpected endpoint_in\n", __FUNCTION__);
                return -ENODEV;
        }
        if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
index 3305fb6079eb1d968bd8a3ee4357b6d3be2c7f74..81b1ea01a172e40e32790a64d6602f653b0e9171 100644 (file)
@@ -1023,7 +1023,8 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
                        return;
                case -EILSEQ:           /* protocol error or unplug */
                case -EPROTO:           /* protocol error or unplug */
-               case -ETIMEDOUT:        /* NAK */
+               case -ETIME:            /* protocol error or unplug */
+               case -ETIMEDOUT:        /* Should never happen, but... */
                        clear_bit(HID_IN_RUNNING, &hid->iofl);
                        hid_io_error(hid);
                        return;
@@ -1535,13 +1536,17 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_GLAB             0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30        0x0038
 #define USB_DEVICE_ID_1_PHIDGETSERVO_30        0x0039
-#define USB_DEVICE_ID_8_8_8_IF_KIT     0x0045
 #define USB_DEVICE_ID_0_0_4_IF_KIT     0x0040
+#define USB_DEVICE_ID_0_16_16_IF_KIT   0x0044
+#define USB_DEVICE_ID_8_8_8_IF_KIT     0x0045
+#define USB_DEVICE_ID_0_8_7_IF_KIT     0x0051
 #define USB_DEVICE_ID_0_8_8_IF_KIT     0x0053
+#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL     0x0058
 
 #define USB_VENDOR_ID_WISEGROUP                0x0925
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20        0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20        0x8104
+#define USB_DEVICE_ID_8_8_4_IF_KIT     0x8201
 #define USB_DEVICE_ID_DUAL_USB_JOYPAD   0x8866
 
 #define USB_VENDOR_ID_WISEGROUP_LTD    0x6677
@@ -1591,6 +1596,13 @@ void hid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_YEALINK          0x6993
 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K      0xb001
+
+#define USB_VENDOR_ID_ALCOR            0x058f
+#define USB_DEVICE_ID_ALCOR_USBRS232   0x9720
+
+#define USB_VENDOR_ID_SUN              0x0430
+#define USB_DEVICE_ID_RARITAN_KVM_DONGLE       0xcdab
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1608,6 +1620,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
@@ -1620,9 +1633,12 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
@@ -1690,7 +1706,11 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
@@ -1701,6 +1721,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
 
        { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
@@ -1711,6 +1732,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
index f6b839c257a7a0f33cddaafb0c7496d7b6cb28a6..a2b419d13740e08631c3f170c52f2a642c3a2a23 100644 (file)
@@ -722,7 +722,7 @@ inval:
        return -EINVAL;
 }
 
-static struct file_operations hiddev_fops = {
+static const struct file_operations hiddev_fops = {
        .owner =        THIS_MODULE,
        .read =         hiddev_read,
        .write =        hiddev_write,
index 86acb5f1907aeebe10e644a53dc37ea02e2781ac..61966d719ca3c577e7c8f4cdbe2999da6dbac0f9 100644 (file)
@@ -87,7 +87,7 @@ static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
index 4723b310f277e5358dfeb7445c92b790789af013..a903595515759b9f9dd19203758c07a37bb2616e 100644 (file)
@@ -420,8 +420,7 @@ static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_i
        for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
                endpoint = &iface->endpoint[i].desc;
 
-               if ((endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+               if (usb_endpoint_is_int_in(endpoint)) {
                        /* we found our interrupt in endpoint */
                        return endpoint;
                }
index a9ccda8810e00af0fddd555c5326b587efeafeed..5dce951f2751a2eeb8d0a3a2bff79765d924cbca 100644 (file)
@@ -107,7 +107,7 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
index b3c0d0c3eae998b45ab1de1344fe935ee9b3c95d..f0f8db6810a2900aa6160acf70d1dff75834f7f1 100644 (file)
@@ -313,9 +313,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
 
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
-       if (!(endpoint->bEndpointAddress & 0x80))
-               return -EIO;
-       if ((endpoint->bmAttributes & 3) != 3)
+       if (!usb_endpoint_is_int_in(endpoint))
                return -EIO;
 
        usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
index 0149043ffb975366b6e41cc3522734773c83ee32..30b9f820e7a894e7b1db04ec347483b5177d3735 100644 (file)
@@ -201,7 +201,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
diff --git a/drivers/usb/input/trancevibrator.c b/drivers/usb/input/trancevibrator.c
new file mode 100644 (file)
index 0000000..33cd91d
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * PlayStation 2 Trance Vibrator driver
+ *
+ * Copyright (C) 2006 Sam Hocevar <sam@zoy.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Standard include files */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org"
+#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver"
+
+#define TRANCEVIBRATOR_VENDOR_ID       0x0b49  /* ASCII Corporation */
+#define TRANCEVIBRATOR_PRODUCT_ID      0x064f  /* Trance Vibrator */
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) },
+       { },
+};
+MODULE_DEVICE_TABLE (usb, id_table);
+
+/* Driver-local specific stuff */
+struct trancevibrator {
+       struct usb_device *udev;
+       unsigned int speed;
+};
+
+static ssize_t show_speed(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct trancevibrator *tv = usb_get_intfdata(intf);
+
+       return sprintf(buf, "%d\n", tv->speed);
+}
+
+static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct trancevibrator *tv = usb_get_intfdata(intf);
+       int temp, retval;
+
+       temp = simple_strtoul(buf, NULL, 10);
+       if (temp > 255)
+               temp = 255;
+       else if (temp < 0)
+               temp = 0;
+       tv->speed = temp;
+
+       dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
+
+       /* Set speed */
+       retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
+                                0x01, /* vendor request: set speed */
+                                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                                tv->speed, /* speed value */
+                                0, NULL, 0, USB_CTRL_GET_TIMEOUT);
+       if (retval) {
+               dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
+               return retval;
+       }
+       return count;
+}
+
+static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed);
+
+static int tv_probe(struct usb_interface *interface,
+                   const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct trancevibrator *dev;
+       int retval;
+
+       dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       dev->udev = usb_get_dev(udev);
+       usb_set_intfdata(interface, dev);
+       retval = device_create_file(&interface->dev, &dev_attr_speed);
+       if (retval)
+               goto error_create_file;
+
+       return 0;
+
+error_create_file:
+       usb_put_dev(udev);
+       usb_set_intfdata(interface, NULL);
+error:
+       kfree(dev);
+       return retval;
+}
+
+static void tv_disconnect(struct usb_interface *interface)
+{
+       struct trancevibrator *dev;
+
+       dev = usb_get_intfdata (interface);
+       usb_set_intfdata(interface, NULL);
+       device_remove_file(&interface->dev, &dev_attr_speed);
+       usb_put_dev(dev->udev);
+       kfree(dev);
+}
+
+/* USB subsystem object */
+static struct usb_driver tv_driver = {
+       .name =         "trancevibrator",
+       .probe =        tv_probe,
+       .disconnect =   tv_disconnect,
+       .id_table =     id_table,
+};
+
+static int __init tv_init(void)
+{
+       int retval = usb_register(&tv_driver);
+       if (retval) {
+               err("usb_register failed. Error number %d", retval);
+               return retval;
+       }
+
+       info(DRIVER_VERSION ":" DRIVER_DESC);
+       return 0;
+}
+
+static void __exit tv_exit(void)
+{
+       usb_deregister(&tv_driver);
+}
+
+module_init (tv_init);
+module_exit (tv_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index 446935b671d989e72e270752fffa77e33a5348ae..0fb792be95efa9edc2defe878255d29db8490e9a 100644 (file)
@@ -218,7 +218,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
 
 static struct usb_device_id usb_mouse_id_table [] = {
        { USB_INTERFACE_INFO(3, 1, 2) },
-    { }                                                /* Terminating entry */
+       { }     /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
index a338bf4c2d78eda0cf50ed02b55f240f5e3932b6..4640d1000d83c024f54c80876536c62ee61de6dd 100644 (file)
@@ -2,9 +2,12 @@
  * usbtouchscreen.c
  * Driver for USB Touchscreens, supporting those devices:
  *  - eGalax Touchkit
- *  - 3M/Microtouch
+ *    includes eTurboTouch CT-410/510/700
+ *  - 3M/Microtouch  EX II series
  *  - ITM
  *  - PanJit TouchSet
+ *  - eTurboTouch
+ *  - Gunze AHL61
  *
  * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -42,7 +45,7 @@
 #include <linux/usb/input.h>
 
 
-#define DRIVER_VERSION         "v0.3"
+#define DRIVER_VERSION         "v0.4"
 #define DRIVER_AUTHOR          "Daniel Ritz <daniel.ritz@gmx.ch>"
 #define DRIVER_DESC            "USB Touchscreen Driver"
 
@@ -60,6 +63,7 @@ struct usbtouch_device_info {
        int flags;
 
        void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
+       int  (*get_pkt_len) (unsigned char *pkt, int len);
        int  (*read_data)   (unsigned char *pkt, int *x, int *y, int *touch, int *press);
        int  (*init)        (struct usbtouch_usb *usbtouch);
 };
@@ -81,8 +85,16 @@ struct usbtouch_usb {
        char phys[64];
 };
 
-static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
-                                 struct pt_regs *regs, unsigned char *pkt, int len);
+
+#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO)
+#define MULTI_PACKET
+#endif
+
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                   struct pt_regs *regs,
+                                   unsigned char *pkt, int len);
+#endif
 
 /* device types */
 enum {
@@ -91,14 +103,19 @@ enum {
        DEVTYPE_PANJIT,
        DEVTYPE_3M,
        DEVTYPE_ITM,
+       DEVTYPE_ETURBO,
+       DEVTYPE_GUNZE,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
 #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
        {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
+       {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
+       {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
+       {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
 #endif
 
 #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
@@ -116,6 +133,14 @@ static struct usb_device_id usbtouch_devices[] = {
        {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
 #endif
 
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+       {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+       {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
+#endif
+
        {}
 };
 
@@ -140,82 +165,23 @@ static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
        *touch = pkt[0] & 0x01;
 
        return 1;
-
 }
 
-static int egalax_get_pkt_len(unsigned char *buf)
+static int egalax_get_pkt_len(unsigned char *buf, int len)
 {
        switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
        case EGALAX_PKT_TYPE_REPT:
                return 5;
 
        case EGALAX_PKT_TYPE_DIAG:
+               if (len < 2)
+                       return -1;
+
                return buf[1] + 2;
        }
 
        return 0;
 }
-
-static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
-                           unsigned char *pkt, int len)
-{
-       unsigned char *buffer;
-       int pkt_len, buf_len, pos;
-
-       /* if the buffer contains data, append */
-       if (unlikely(usbtouch->buf_len)) {
-               int tmp;
-
-               /* if only 1 byte in buffer, add another one to get length */
-               if (usbtouch->buf_len == 1)
-                       usbtouch->buffer[1] = pkt[0];
-
-               pkt_len = egalax_get_pkt_len(usbtouch->buffer);
-
-               /* unknown packet: drop everything */
-               if (!pkt_len)
-                       return;
-
-               /* append, process */
-               tmp = pkt_len - usbtouch->buf_len;
-               memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
-               usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
-
-               buffer = pkt + tmp;
-               buf_len = len - tmp;
-       } else {
-               buffer = pkt;
-               buf_len = len;
-       }
-
-       /* only one byte left in buffer */
-       if (unlikely(buf_len == 1)) {
-               usbtouch->buffer[0] = buffer[0];
-               usbtouch->buf_len = 1;
-               return;
-       }
-
-       /* loop over the buffer */
-       pos = 0;
-       while (pos < buf_len) {
-               /* get packet len */
-               pkt_len = egalax_get_pkt_len(buffer + pos);
-
-               /* unknown packet: drop everything */
-               if (unlikely(!pkt_len))
-                       return;
-
-               /* full packet: process */
-               if (likely(pkt_len <= buf_len)) {
-                       usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
-               } else {
-                       /* incomplete packet: save in buffer */
-                       memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
-                       usbtouch->buf_len = buf_len - pos;
-               }
-               pos += pkt_len;
-       }
-}
 #endif
 
 
@@ -254,7 +220,7 @@ static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
 
 static int mtouch_init(struct usbtouch_usb *usbtouch)
 {
-       int ret;
+       int ret, i;
 
        ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
                              MTOUCHUSB_RESET,
@@ -264,15 +230,20 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
            __FUNCTION__, ret);
        if (ret < 0)
                return ret;
-
-       ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
-                             MTOUCHUSB_ASYNC_REPORT,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-           __FUNCTION__, ret);
-       if (ret < 0)
-               return ret;
+       msleep(150);
+
+       for (i = 0; i < 3; i++) {
+               ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+                                     MTOUCHUSB_ASYNC_REPORT,
+                                     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                                     1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
+               dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
+                   __FUNCTION__, ret);
+               if (ret >= 0)
+                       break;
+               if (ret != -EPIPE)
+                       return ret;
+       }
 
        return 0;
 }
@@ -295,6 +266,54 @@ static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *pr
 #endif
 
 
+/*****************************************************************************
+ * eTurboTouch part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+       unsigned int shift;
+
+       /* packets should start with sync */
+       if (!(pkt[0] & 0x80))
+               return 0;
+
+       shift = (6 - (pkt[0] & 0x03));
+       *x = ((pkt[3] << 7) | pkt[4]) >> shift;
+       *y = ((pkt[1] << 7) | pkt[2]) >> shift;
+       *touch = (pkt[0] & 0x10) ? 1 : 0;
+
+       return 1;
+}
+
+static int eturbo_get_pkt_len(unsigned char *buf, int len)
+{
+       if (buf[0] & 0x80)
+               return 5;
+       if (buf[0] == 0x01)
+               return 3;
+       return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * Gunze part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+       if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
+               return 0;
+
+       *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
+       *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
+       *touch = pkt[0] & 0x20;
+
+       return 1;
+}
+#endif
+
 /*****************************************************************************
  * the different device descriptors
  */
@@ -307,7 +326,8 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .max_yc         = 0x07ff,
                .rept_size      = 16,
                .flags          = USBTOUCH_FLG_BUFFER,
-               .process_pkt    = egalax_process,
+               .process_pkt    = usbtouch_process_multi,
+               .get_pkt_len    = egalax_get_pkt_len,
                .read_data      = egalax_read_data,
        },
 #endif
@@ -346,6 +366,31 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .read_data      = itm_read_data,
        },
 #endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+       [DEVTYPE_ETURBO] = {
+               .min_xc         = 0x0,
+               .max_xc         = 0x07ff,
+               .min_yc         = 0x0,
+               .max_yc         = 0x07ff,
+               .rept_size      = 8,
+               .flags          = USBTOUCH_FLG_BUFFER,
+               .process_pkt    = usbtouch_process_multi,
+               .get_pkt_len    = eturbo_get_pkt_len,
+               .read_data      = eturbo_read_data,
+       },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+       [DEVTYPE_GUNZE] = {
+               .min_xc         = 0x0,
+               .max_xc         = 0x0fff,
+               .min_yc         = 0x0,
+               .max_yc         = 0x0fff,
+               .rept_size      = 4,
+               .read_data      = gunze_read_data,
+       },
+#endif
 };
 
 
@@ -377,6 +422,83 @@ static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
 }
 
 
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                   struct pt_regs *regs,
+                                   unsigned char *pkt, int len)
+{
+       unsigned char *buffer;
+       int pkt_len, pos, buf_len, tmp;
+
+       /* process buffer */
+       if (unlikely(usbtouch->buf_len)) {
+               /* try to get size */
+               pkt_len = usbtouch->type->get_pkt_len(
+                               usbtouch->buffer, usbtouch->buf_len);
+
+               /* drop? */
+               if (unlikely(!pkt_len))
+                       goto out_flush_buf;
+
+               /* need to append -pkt_len bytes before able to get size */
+               if (unlikely(pkt_len < 0)) {
+                       int append = -pkt_len;
+                       if (unlikely(append > len))
+                              append = len;
+                       if (usbtouch->buf_len + append >= usbtouch->type->rept_size)
+                               goto out_flush_buf;
+                       memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append);
+                       usbtouch->buf_len += append;
+
+                       pkt_len = usbtouch->type->get_pkt_len(
+                                       usbtouch->buffer, usbtouch->buf_len);
+                       if (pkt_len < 0)
+                               return;
+               }
+
+               /* append */
+               tmp = pkt_len - usbtouch->buf_len;
+               if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
+                       goto out_flush_buf;
+               memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
+               usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
+
+               buffer = pkt + tmp;
+               buf_len = len - tmp;
+       } else {
+               buffer = pkt;
+               buf_len = len;
+       }
+
+       /* loop over the received packet, process */
+       pos = 0;
+       while (pos < buf_len) {
+               /* get packet len */
+               pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len);
+
+               /* unknown packet: drop everything */
+               if (unlikely(!pkt_len))
+                       goto out_flush_buf;
+
+               /* full packet: process */
+               if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
+                       usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+               } else {
+                       /* incomplete packet: save in buffer */
+                       memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
+                       usbtouch->buf_len = buf_len - pos;
+                       return;
+               }
+               pos += pkt_len;
+       }
+
+out_flush_buf:
+       usbtouch->buf_len = 0;
+       return;
+}
+#endif
+
+
 static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
 {
        struct usbtouch_usb *usbtouch = urb->context;
@@ -386,7 +508,7 @@ static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
@@ -452,7 +574,7 @@ static int usbtouch_probe(struct usb_interface *intf,
        struct usb_endpoint_descriptor *endpoint;
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usbtouch_device_info *type;
-       int err;
+       int err = -ENOMEM;
 
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
@@ -526,6 +648,7 @@ static int usbtouch_probe(struct usb_interface *intf,
                         usbtouch->data, type->rept_size,
                         usbtouch_irq, usbtouch, endpoint->bInterval);
 
+       usbtouch->irq->dev = usbtouch->udev;
        usbtouch->irq->transfer_dma = usbtouch->data_dma;
        usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -553,7 +676,7 @@ out_free_buffers:
 out_free:
        input_free_device(input_dev);
        kfree(usbtouch);
-       return -ENOMEM;
+       return err;
 }
 
 static void usbtouch_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
deleted file mode 100644 (file)
index 369461a..0000000
+++ /dev/null
@@ -1,1003 +0,0 @@
-/*
- *  USB Wacom Graphire and Wacom Intuos tablet support
- *
- *  Copyright (c) 2000-2004 Vojtech Pavlik     <vojtech@ucw.cz>
- *  Copyright (c) 2000 Andreas Bach Aaen       <abach@stofanet.dk>
- *  Copyright (c) 2000 Clifford Wolf           <clifford@clifford.at>
- *  Copyright (c) 2000 Sam Mosel               <sam.mosel@computer.org>
- *  Copyright (c) 2000 James E. Blair          <corvus@gnu.org>
- *  Copyright (c) 2000 Daniel Egger            <egger@suse.de>
- *  Copyright (c) 2001 Frederic Lepied         <flepied@mandrakesoft.com>
- *  Copyright (c) 2004 Panagiotis Issaris      <panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2006 Ping Cheng         <pingc@wacom.com>
- *
- *  ChangeLog:
- *      v0.1 (vp)  - Initial release
- *      v0.2 (aba) - Support for all buttons / combinations
- *      v0.3 (vp)  - Support for Intuos added
- *     v0.4 (sm)  - Support for more Intuos models, menustrip
- *                     relative mode, proximity.
- *     v0.5 (vp)  - Big cleanup, nifty features removed,
- *                     they belong in userspace
- *     v1.8 (vp)  - Submit URB only when operating, moved to CVS,
- *                     use input_report_key instead of report_btn and
- *                     other cleanups
- *     v1.11 (vp) - Add URB ->dev setting for new kernels
- *     v1.11 (jb) - Add support for the 4D Mouse & Lens
- *     v1.12 (de) - Add support for two more inking pen IDs
- *     v1.14 (vp) - Use new USB device id probing scheme.
- *                  Fix Wacom Graphire mouse wheel
- *     v1.18 (vp) - Fix mouse wheel direction
- *                  Make mouse relative
- *      v1.20 (fl) - Report tool id for Intuos devices
- *                 - Multi tools support
- *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
- *                 - Add PL models support
- *                - Fix Wacom Graphire mouse wheel again
- *     v1.21 (vp) - Removed protocol descriptions
- *                - Added MISC_SERIAL for tool serial numbers
- *           (gb) - Identify version on module load.
- *    v1.21.1 (fl) - added Graphire2 support
- *    v1.21.2 (fl) - added Intuos2 support
- *                 - added all the PL ids
- *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
- *                 - added smooth filter for Graphire from Peri Hankey
- *                 - added PenPartner support from Olaf van Es
- *                 - new tool ids from Ole Martin Bjoerndalen
- *     v1.29 (pc) - Add support for more tablets
- *                - Fix pressure reporting
- *     v1.30 (vp) - Merge 2.4 and 2.5 drivers
- *                - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
- *                - Cleanups here and there
- *    v1.30.1 (pi) - Added Graphire3 support
- *     v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
- *     v1.43 (pc) - Added support for Cintiq 21UX
- *                - Fixed a Graphire bug
- *                - Merged wacom_intuos3_irq into wacom_intuos_irq
- *     v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
- *                - Report Device IDs
- *     v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
- *                - Minor data report fix
- */
-
-/*
- * 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/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-#include <asm/unaligned.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.45"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-#define USB_VENDOR_ID_WACOM    0x056a
-#define STYLUS_DEVICE_ID       0x02
-#define CURSOR_DEVICE_ID       0x06
-#define ERASER_DEVICE_ID       0x0A
-
-enum {
-       PENPARTNER = 0,
-       GRAPHIRE,
-       WACOM_G4,
-       PL,
-       INTUOS,
-       INTUOS3,
-       INTUOS312,
-       INTUOS319,
-       CINTIQ,
-       MAX_TYPE
-};
-
-struct wacom_features {
-       char *name;
-       int pktlen;
-       int x_max;
-       int y_max;
-       int pressure_max;
-       int distance_max;
-       int type;
-       usb_complete_t irq;
-};
-
-struct wacom {
-       signed char *data;
-       dma_addr_t data_dma;
-       struct input_dev *dev;
-       struct usb_device *usbdev;
-       struct urb *irq;
-       struct wacom_features *features;
-       int tool[2];
-       int id[2];
-       __u32 serial[2];
-       char phys[32];
-};
-
-#define USB_REQ_GET_REPORT     0x01
-#define USB_REQ_SET_REPORT     0x09
-
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
-                               unsigned char id, void *buf, int size)
-{
-       return usb_control_msg(interface_to_usbdev(intf),
-               usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
-               USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-               (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-               buf, size, 100);
-}
-
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
-                               unsigned char id, void *buf, int size)
-{
-       return usb_control_msg(interface_to_usbdev(intf),
-               usb_sndctrlpipe(interface_to_usbdev(intf), 0),
-                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-               buf, size, 1000);
-}
-
-static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int prox, pressure, id;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2) {
-               dbg("wacom_pl_irq: received unknown report #%d", data[0]);
-               goto exit;
-       }
-
-       prox = data[1] & 0x40;
-
-       input_regs(dev, regs);
-
-       id = ERASER_DEVICE_ID;
-       if (prox) {
-
-               pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-               if (wacom->features->pressure_max > 255)
-                       pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-               pressure += (wacom->features->pressure_max + 1) / 2;
-
-               /*
-                * if going from out of proximity into proximity select between the eraser
-                * and the pen based on the state of the stylus2 button, choose eraser if
-                * pressed else choose pen. if not a proximity change from out to in, send
-                * an out of proximity for previous tool then a in for new tool.
-                */
-               if (!wacom->tool[0]) {
-                       /* Eraser bit set for DTF */
-                       if (data[1] & 0x10)
-                               wacom->tool[1] = BTN_TOOL_RUBBER;
-                       else
-                               /* Going into proximity select tool */
-                               wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-               } else {
-                       /* was entered with stylus2 pressed */
-                       if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
-                               /* report out proximity for previous tool */
-                               input_report_key(dev, wacom->tool[1], 0);
-                               input_sync(dev);
-                               wacom->tool[1] = BTN_TOOL_PEN;
-                               goto exit;
-                       }
-               }
-               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-                       /* Unknown tool selected default to pen tool */
-                       wacom->tool[1] = BTN_TOOL_PEN;
-                       id = STYLUS_DEVICE_ID;
-               }
-               input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
-               input_report_abs(dev, ABS_MISC, id); /* report tool id */
-               input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-               input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-               input_report_abs(dev, ABS_PRESSURE, pressure);
-
-               input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
-               input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
-               /* Only allow the stylus2 button to be reported for the pen tool. */
-               input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
-       } else {
-               /* report proximity-out of a (valid) tool */
-               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-                       /* Unknown tool selected default to pen tool */
-                       wacom->tool[1] = BTN_TOOL_PEN;
-               }
-               input_report_key(dev, wacom->tool[1], prox);
-       }
-
-       wacom->tool[0] = prox; /* Save proximity state */
-       input_sync(dev);
-
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int retval, id;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2) {
-               printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-       if (data[1] & 0x04) {
-               input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
-               input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
-               id = ERASER_DEVICE_ID;
-       } else {
-               input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
-               input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-               id = STYLUS_DEVICE_ID;
-       }
-       input_report_abs(dev, ABS_MISC, id); /* report tool id */
-       input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
-       input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
-       input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
-       input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-       input_report_key(dev, BTN_STYLUS2, data[1] & 0x10);
-
-       input_sync(dev);
-
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2) {
-               printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-       input_report_key(dev, BTN_TOOL_PEN, 1);
-       input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
-       input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
-       input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
-       input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
-       input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
-       input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
-       input_sync(dev);
-
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int x, y, id, rw;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] == 99) return; /* for Volito tablets */
-
-       if (data[0] != 2) {
-               dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-
-       id = STYLUS_DEVICE_ID;
-       if (data[1] & 0x10) { /* in prox */
-
-               switch ((data[1] >> 5) & 3) {
-
-                       case 0: /* Pen */
-                               wacom->tool[0] = BTN_TOOL_PEN;
-                               break;
-
-                       case 1: /* Rubber */
-                               wacom->tool[0] = BTN_TOOL_RUBBER;
-                               id = ERASER_DEVICE_ID;
-                               break;
-
-                       case 2: /* Mouse with wheel */
-                               input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
-                               if (wacom->features->type == WACOM_G4) {
-                                       rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
-                                       input_report_rel(dev, REL_WHEEL, -rw);
-                               } else
-                                       input_report_rel(dev, REL_WHEEL, -(signed char) data[6]);
-                               /* fall through */
-
-                       case 3: /* Mouse without wheel */
-                               wacom->tool[0] = BTN_TOOL_MOUSE;
-                               id = CURSOR_DEVICE_ID;
-                               input_report_key(dev, BTN_LEFT, data[1] & 0x01);
-                               input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
-                               if (wacom->features->type == WACOM_G4)
-                                       input_report_abs(dev, ABS_DISTANCE, data[6]);
-                               else
-                                       input_report_abs(dev, ABS_DISTANCE, data[7]);
-                               break;
-               }
-       }
-
-       if (data[1] & 0x90) {
-               x = le16_to_cpu(*(__le16 *) &data[2]);
-               y = le16_to_cpu(*(__le16 *) &data[4]);
-               input_report_abs(dev, ABS_X, x);
-               input_report_abs(dev, ABS_Y, y);
-               if (wacom->tool[0] != BTN_TOOL_MOUSE) {
-                       input_report_abs(dev, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
-                       input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-                       input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-                       input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
-               }
-       }
-
-       if (data[1] & 0x10)
-               input_report_abs(dev, ABS_MISC, id); /* report tool id */
-       else
-               input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
-       input_report_key(dev, wacom->tool[0], data[1] & 0x10);
-       input_sync(dev);
-
-       /* send pad data */
-       if (wacom->features->type == WACOM_G4) {
-               if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) {
-                       wacom->id[1] = 1;
-                       wacom->serial[1] = (data[7] & 0xf8);
-                       input_report_key(dev, BTN_0, (data[7] & 0x40));
-                       input_report_key(dev, BTN_4, (data[7] & 0x80));
-                       rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
-                       input_report_rel(dev, REL_WHEEL, rw);
-                       input_report_key(dev, BTN_TOOL_FINGER, 0xf0);
-                       input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
-               } else if (wacom->id[1]) {
-                       wacom->id[1] = 0;
-                       input_report_key(dev, BTN_TOOL_FINGER, 0);
-                       input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
-               }
-               input_sync(dev);
-       }
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static int wacom_intuos_inout(struct urb *urb)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int idx;
-
-       /* tool number */
-       idx = data[1] & 0x01;
-
-       /* Enter report */
-       if ((data[1] & 0xfc) == 0xc0) {
-               /* serial number of the tool */
-               wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
-                       (data[4] << 20) + (data[5] << 12) +
-                       (data[6] << 4) + (data[7] >> 4);
-
-               wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
-               switch (wacom->id[idx]) {
-                       case 0x812: /* Inking pen */
-                       case 0x801: /* Intuos3 Inking pen */
-                       case 0x012:
-                               wacom->tool[idx] = BTN_TOOL_PENCIL;
-                               break;
-                       case 0x822: /* Pen */
-                       case 0x842:
-                       case 0x852:
-                       case 0x823: /* Intuos3 Grip Pen */
-                       case 0x813: /* Intuos3 Classic Pen */
-                       case 0x885: /* Intuos3 Marker Pen */
-                       case 0x022:
-                               wacom->tool[idx] = BTN_TOOL_PEN;
-                               break;
-                       case 0x832: /* Stroke pen */
-                       case 0x032:
-                               wacom->tool[idx] = BTN_TOOL_BRUSH;
-                               break;
-                       case 0x007: /* Mouse 4D and 2D */
-                       case 0x09c:
-                       case 0x094:
-                       case 0x017: /* Intuos3 2D Mouse */
-                               wacom->tool[idx] = BTN_TOOL_MOUSE;
-                               break;
-                       case 0x096: /* Lens cursor */
-                       case 0x097: /* Intuos3 Lens cursor */
-                               wacom->tool[idx] = BTN_TOOL_LENS;
-                               break;
-                       case 0x82a: /* Eraser */
-                       case 0x85a:
-                       case 0x91a:
-                       case 0xd1a:
-                       case 0x0fa:
-                       case 0x82b: /* Intuos3 Grip Pen Eraser */
-                       case 0x81b: /* Intuos3 Classic Pen Eraser */
-                       case 0x91b: /* Intuos3 Airbrush Eraser */
-                               wacom->tool[idx] = BTN_TOOL_RUBBER;
-                               break;
-                       case 0xd12:
-                       case 0x912:
-                       case 0x112:
-                       case 0x913: /* Intuos3 Airbrush */
-                               wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
-                               break;
-                       default: /* Unknown tool */
-                               wacom->tool[idx] = BTN_TOOL_PEN;
-               }
-               if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
-                               ((wacom->features->type == INTUOS312)
-                                       || (wacom->features->type == INTUOS319)))) {
-                       input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
-                       input_report_key(dev, wacom->tool[idx], 1);
-                       input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-                       input_sync(dev);
-               }
-               return 1;
-       }
-
-       /* Exit report */
-       if ((data[1] & 0xfe) == 0x80) {
-               input_report_key(dev, wacom->tool[idx], 0);
-               input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
-               input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-               input_sync(dev);
-               return 1;
-       }
-
-       if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312)
-                       || (wacom->features->type == INTUOS319)))
-               return 1;
-       else
-               return 0;
-}
-
-static void wacom_intuos_general(struct urb *urb)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       unsigned int t;
-
-       /* general pen packet */
-       if ((data[1] & 0xb8) == 0xa0) {
-               t = (data[6] << 2) | ((data[7] >> 6) & 3);
-               input_report_abs(dev, ABS_PRESSURE, t);
-               input_report_abs(dev, ABS_TILT_X,
-                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-               input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-               input_report_key(dev, BTN_STYLUS, data[1] & 2);
-               input_report_key(dev, BTN_STYLUS2, data[1] & 4);
-               input_report_key(dev, BTN_TOUCH, t > 10);
-       }
-
-       /* airbrush second packet */
-       if ((data[1] & 0xbc) == 0xb4) {
-               input_report_abs(dev, ABS_WHEEL,
-                               (data[6] << 2) | ((data[7] >> 6) & 3));
-               input_report_abs(dev, ABS_TILT_X,
-                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-               input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-       }
-       return;
-}
-
-static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       unsigned int t;
-       int idx;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
-               dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-
-       /* tool number */
-       idx = data[1] & 0x01;
-
-       /* pad packets. Works as a second tool and is always in prox */
-       if (data[0] == 12) {
-               /* initiate the pad as a device */
-               if (wacom->tool[1] != BTN_TOOL_FINGER)
-                       wacom->tool[1] = BTN_TOOL_FINGER;
-
-               input_report_key(dev, BTN_0, (data[5] & 0x01));
-               input_report_key(dev, BTN_1, (data[5] & 0x02));
-               input_report_key(dev, BTN_2, (data[5] & 0x04));
-               input_report_key(dev, BTN_3, (data[5] & 0x08));
-               input_report_key(dev, BTN_4, (data[6] & 0x01));
-               input_report_key(dev, BTN_5, (data[6] & 0x02));
-               input_report_key(dev, BTN_6, (data[6] & 0x04));
-               input_report_key(dev, BTN_7, (data[6] & 0x08));
-               input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
-               input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
-
-               if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
-                       input_report_key(dev, wacom->tool[1], 1);
-               else
-                       input_report_key(dev, wacom->tool[1], 0);
-               input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
-               input_sync(dev);
-               goto exit;
-       }
-
-       /* process in/out prox events */
-       if (wacom_intuos_inout(urb))
-               goto exit;
-
-       /* Cintiq doesn't send data when RDY bit isn't set */
-       if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
-               goto exit;
-
-       if (wacom->features->type >= INTUOS3) {
-               input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
-               input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
-               input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
-       } else {
-               input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
-               input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
-               input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
-       }
-
-       /* process general packets */
-       wacom_intuos_general(urb);
-
-       /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
-       if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
-
-               if (data[1] & 0x02) {
-                       /* Rotation packet */
-                       if (wacom->features->type >= INTUOS3) {
-                               /* I3 marker pen rotation reported as wheel
-                                * due to valuator limitation
-                                */
-                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
-                               t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
-                                       ((t-1) / 2 + 450)) : (450 - t / 2) ;
-                               input_report_abs(dev, ABS_WHEEL, t);
-                       } else {
-                               /* 4D mouse rotation packet */
-                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
-                               input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
-                                       ((t - 1) / 2) : -t / 2);
-                       }
-
-               } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
-                       /* 4D mouse packet */
-                       input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-                       input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-                       input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-
-                       input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
-                       input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
-                       t = (data[6] << 2) | ((data[7] >> 6) & 3);
-                       input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
-
-               } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
-                       /* 2D mouse packet */
-                       input_report_key(dev, BTN_LEFT,   data[8] & 0x04);
-                       input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
-                       input_report_key(dev, BTN_RIGHT,  data[8] & 0x10);
-                       input_report_rel(dev, REL_WHEEL, (data[8] & 0x01)
-                                                - ((data[8] & 0x02) >> 1));
-
-                       /* I3 2D mouse side buttons */
-                       if (wacom->features->type == INTUOS3) {
-                               input_report_key(dev, BTN_SIDE,   data[8] & 0x40);
-                               input_report_key(dev, BTN_EXTRA,  data[8] & 0x20);
-                       }
-
-               } else if (wacom->features->type < INTUOS3) {
-                       /* Lens cursor packets */
-                       input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-                       input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-                       input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-                       input_report_key(dev, BTN_SIDE,   data[8] & 0x10);
-                       input_report_key(dev, BTN_EXTRA,  data[8] & 0x08);
-               }
-       }
-
-       input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
-       input_report_key(dev, wacom->tool[idx], 1);
-       input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-       input_sync(dev);
-
-exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                   __FUNCTION__, retval);
-}
-
-static struct wacom_features wacom_features[] = {
-       { "Wacom Penpartner",    7,   5040,  3780,  255, 32, PENPARTNER, wacom_penpartner_irq },
-        { "Wacom Graphire",      8,  10206,  7422,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire3",     8,  10208,  7424,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 32, WACOM_G4,   wacom_graphire_irq },
-       { "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 32, WACOM_G4,   wacom_graphire_irq },
-       { "Wacom Volito",        8,   5104,  3712,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom PenStation2",   8,   3250,  2320,  255, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Volito2 4x5",   8,   5104,  3712,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Volito2 2x3",   8,   3248,  2320,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom PenPartner2",   8,   3250,  2320,  255, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom PL400",         8,   5408,  4056,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL500",         8,   6144,  4608,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL600",         8,   6126,  4604,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL600SX",       8,   6260,  5016,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL550",         8,   6144,  4608,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom PL800",         8,   7220,  5780,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom PL700",         8,   6758,  5406,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom PL510",         8,   6282,  4762,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PL,         wacom_ptu_irq },
-       { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312,  wacom_intuos_irq },
-       { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319,  wacom_intuos_irq },
-       { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,     wacom_intuos_irq },
-       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { }
-};
-
-static struct usb_device_id wacom_ids[] = {
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, wacom_ids);
-
-static int wacom_open(struct input_dev *dev)
-{
-       struct wacom *wacom = dev->private;
-
-       wacom->irq->dev = wacom->usbdev;
-       if (usb_submit_urb(wacom->irq, GFP_KERNEL))
-               return -EIO;
-
-       return 0;
-}
-
-static void wacom_close(struct input_dev *dev)
-{
-       struct wacom *wacom = dev->private;
-
-       usb_kill_urb(wacom->irq);
-}
-
-static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       struct usb_device *dev = interface_to_usbdev(intf);
-       struct usb_endpoint_descriptor *endpoint;
-       struct wacom *wacom;
-       struct input_dev *input_dev;
-       char rep_data[2], limit = 0;
-
-       wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!wacom || !input_dev)
-               goto fail1;
-
-       wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
-       if (!wacom->data)
-               goto fail1;
-
-       wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
-       if (!wacom->irq)
-               goto fail2;
-
-       wacom->usbdev = dev;
-       wacom->dev = input_dev;
-       usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
-       strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
-
-       wacom->features = wacom_features + (id - wacom_ids);
-       if (wacom->features->pktlen > 10)
-               BUG();
-
-       input_dev->name = wacom->features->name;
-       usb_to_input_id(dev, &input_dev->id);
-
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = wacom;
-       input_dev->open = wacom_open;
-       input_dev->close = wacom_close;
-
-       input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
-       input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
-       input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
-
-       switch (wacom->features->type) {
-               case WACOM_G4:
-                       input_dev->evbit[0] |= BIT(EV_MSC);
-                       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
-                       /* fall through */
-
-               case GRAPHIRE:
-                       input_dev->evbit[0] |= BIT(EV_REL);
-                       input_dev->relbit[0] |= BIT(REL_WHEEL);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
-                       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
-                       break;
-
-               case INTUOS3:
-               case INTUOS312:
-               case INTUOS319:
-               case CINTIQ:
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
-                       input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
-                       input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
-                       /* fall through */
-
-               case INTUOS:
-                       input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
-                       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
-                       input_dev->relbit[0] |= BIT(REL_WHEEL);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
-                                                         | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
-                       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
-                       input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
-                       input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
-                       input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
-                       input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
-                       input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
-                       break;
-
-               case PL:
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
-                       break;
-       }
-
-       endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
-       if (wacom->features->pktlen > 10)
-               BUG();
-
-       usb_fill_int_urb(wacom->irq, dev,
-                        usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-                        wacom->data, wacom->features->pktlen,
-                        wacom->features->irq, wacom, endpoint->bInterval);
-       wacom->irq->transfer_dma = wacom->data_dma;
-       wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       input_register_device(wacom->dev);
-
-       /* Ask the tablet to report tablet data. Repeat until it succeeds */
-       do {
-               rep_data[0] = 2;
-               rep_data[1] = 2;
-               usb_set_report(intf, 3, 2, rep_data, 2);
-               usb_get_report(intf, 3, 2, rep_data, 2);
-       } while (rep_data[1] != 2 && limit++ < 5);
-
-       usb_set_intfdata(intf, wacom);
-       return 0;
-
-fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
-fail1: input_free_device(input_dev);
-       kfree(wacom);
-       return -ENOMEM;
-}
-
-static void wacom_disconnect(struct usb_interface *intf)
-{
-       struct wacom *wacom = usb_get_intfdata (intf);
-
-       usb_set_intfdata(intf, NULL);
-       if (wacom) {
-               usb_kill_urb(wacom->irq);
-               input_unregister_device(wacom->dev);
-               usb_free_urb(wacom->irq);
-               usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma);
-               kfree(wacom);
-       }
-}
-
-static struct usb_driver wacom_driver = {
-       .name =         "wacom",
-       .probe =        wacom_probe,
-       .disconnect =   wacom_disconnect,
-       .id_table =     wacom_ids,
-};
-
-static int __init wacom_init(void)
-{
-       int result = usb_register(&wacom_driver);
-       if (result == 0)
-               info(DRIVER_VERSION ":" DRIVER_DESC);
-       return result;
-}
-
-static void __exit wacom_exit(void)
-{
-       usb_deregister(&wacom_driver);
-}
-
-module_init(wacom_init);
-module_exit(wacom_exit);
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
new file mode 100644 (file)
index 0000000..832737b
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * drivers/usb/input/wacom.h
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support
+ *
+ *  Copyright (c) 2000-2004 Vojtech Pavlik     <vojtech@ucw.cz>
+ *  Copyright (c) 2000 Andreas Bach Aaen       <abach@stofanet.dk>
+ *  Copyright (c) 2000 Clifford Wolf           <clifford@clifford.at>
+ *  Copyright (c) 2000 Sam Mosel               <sam.mosel@computer.org>
+ *  Copyright (c) 2000 James E. Blair          <corvus@gnu.org>
+ *  Copyright (c) 2000 Daniel Egger            <egger@suse.de>
+ *  Copyright (c) 2001 Frederic Lepied         <flepied@mandrakesoft.com>
+ *  Copyright (c) 2004 Panagiotis Issaris      <panagiotis.issaris@mech.kuleuven.ac.be>
+ *  Copyright (c) 2002-2006 Ping Cheng         <pingc@wacom.com>
+ *
+ *  ChangeLog:
+ *      v0.1 (vp)  - Initial release
+ *      v0.2 (aba) - Support for all buttons / combinations
+ *      v0.3 (vp)  - Support for Intuos added
+ *     v0.4 (sm)  - Support for more Intuos models, menustrip
+ *                     relative mode, proximity.
+ *     v0.5 (vp)  - Big cleanup, nifty features removed,
+ *                     they belong in userspace
+ *     v1.8 (vp)  - Submit URB only when operating, moved to CVS,
+ *                     use input_report_key instead of report_btn and
+ *                     other cleanups
+ *     v1.11 (vp) - Add URB ->dev setting for new kernels
+ *     v1.11 (jb) - Add support for the 4D Mouse & Lens
+ *     v1.12 (de) - Add support for two more inking pen IDs
+ *     v1.14 (vp) - Use new USB device id probing scheme.
+ *                  Fix Wacom Graphire mouse wheel
+ *     v1.18 (vp) - Fix mouse wheel direction
+ *                  Make mouse relative
+ *      v1.20 (fl) - Report tool id for Intuos devices
+ *                 - Multi tools support
+ *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
+ *                 - Add PL models support
+ *                - Fix Wacom Graphire mouse wheel again
+ *     v1.21 (vp) - Removed protocol descriptions
+ *                - Added MISC_SERIAL for tool serial numbers
+ *           (gb) - Identify version on module load.
+ *    v1.21.1 (fl) - added Graphire2 support
+ *    v1.21.2 (fl) - added Intuos2 support
+ *                 - added all the PL ids
+ *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
+ *                 - added smooth filter for Graphire from Peri Hankey
+ *                 - added PenPartner support from Olaf van Es
+ *                 - new tool ids from Ole Martin Bjoerndalen
+ *     v1.29 (pc) - Add support for more tablets
+ *                - Fix pressure reporting
+ *     v1.30 (vp) - Merge 2.4 and 2.5 drivers
+ *                - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
+ *                - Cleanups here and there
+ *    v1.30.1 (pi) - Added Graphire3 support
+ *     v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
+ *     v1.43 (pc) - Added support for Cintiq 21UX
+ *                - Fixed a Graphire bug
+ *                - Merged wacom_intuos3_irq into wacom_intuos_irq
+ *     v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
+ *                - Report Device IDs
+ *      v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ *                 - Minor data report fix
+ *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
+ *                - where wacom_sys.c deals with system specific code,
+ *                - and wacom_wac.c deals with Wacom specific code
+ */
+
+/*
+ * 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 WACOM_H
+#define WACOM_H
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+#include <asm/unaligned.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.46"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_WACOM    0x056a
+
+struct wacom {
+       dma_addr_t data_dma;
+       struct input_dev *dev;
+       struct usb_device *usbdev;
+       struct urb *irq;
+       struct wacom_wac * wacom_wac;
+       char phys[32];
+};
+
+struct wacom_combo {
+       struct wacom * wacom;
+       struct urb * urb;
+       struct pt_regs *regs;
+};
+
+extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
+extern void wacom_sys_irq(struct urb *urb, struct pt_regs *regs);
+extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
+extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
+extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
+extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value);
+extern void wacom_input_regs(void *wcombo);
+extern void wacom_input_sync(void *wcombo);
+extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern __u16 wacom_le16_to_cpu(unsigned char *data);
+extern __u16 wacom_be16_to_cpu(unsigned char *data);
+extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
+extern const struct usb_device_id * get_device_table(void);
+
+#endif
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
new file mode 100644 (file)
index 0000000..7c3b52b
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * drivers/usb/input/wacom_sys.c
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support - system specific code
+ */
+
+/*
+ * 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 "wacom.h"
+#include "wacom_wac.h"
+
+#define USB_REQ_GET_REPORT     0x01
+#define USB_REQ_SET_REPORT     0x09
+
+static int usb_get_report(struct usb_interface *intf, unsigned char type,
+                               unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(interface_to_usbdev(intf),
+               usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+               USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+               buf, size, 100);
+}
+
+static int usb_set_report(struct usb_interface *intf, unsigned char type,
+                               unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(interface_to_usbdev(intf),
+               usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+               buf, size, 1000);
+}
+
+static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
+{
+       return wcombo->wacom->dev;
+}
+
+void wacom_sys_irq(struct urb *urb, struct pt_regs *regs)
+{
+       struct wacom *wacom = urb->context;
+       struct wacom_combo wcombo;
+       int retval;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               goto exit;
+       }
+
+       wcombo.wacom = wacom;
+       wcombo.urb = urb;
+       wcombo.regs = regs;
+
+       if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo))
+               input_sync(get_input_dev(&wcombo));
+
+ exit:
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
+               err ("%s - usb_submit_urb failed with result %d",
+                    __FUNCTION__, retval);
+}
+
+void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
+{
+       input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data);
+       return;
+}
+
+void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
+{
+       input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
+       return;
+}
+
+void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
+{
+       input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
+       return;
+}
+
+void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value)
+{
+       input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value);
+       return;
+}
+
+__u16 wacom_be16_to_cpu(unsigned char *data)
+{
+       __u16 value;
+       value = be16_to_cpu(*(__be16 *) data);
+       return value;
+}
+
+__u16 wacom_le16_to_cpu(unsigned char *data)
+{
+       __u16 value;
+       value = be16_to_cpu(*(__be16 *) data);
+       return value;
+}
+
+void wacom_input_regs(void *wcombo)
+{
+       input_regs(get_input_dev((struct wacom_combo *)wcombo), ((struct wacom_combo *)wcombo)->regs);
+       return;
+}
+
+void wacom_input_sync(void *wcombo)
+{
+       input_sync(get_input_dev((struct wacom_combo *)wcombo));
+       return;
+}
+
+static int wacom_open(struct input_dev *dev)
+{
+       struct wacom *wacom = dev->private;
+
+       wacom->irq->dev = wacom->usbdev;
+       if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+               return -EIO;
+
+       return 0;
+}
+
+static void wacom_close(struct input_dev *dev)
+{
+       struct wacom *wacom = dev->private;
+
+       usb_kill_urb(wacom->irq);
+}
+
+void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->evbit[0] |= BIT(EV_MSC);
+       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+}
+
+void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->evbit[0] |= BIT(EV_REL);
+       input_dev->relbit[0] |= BIT(REL_WHEEL);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
+}
+
+void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+       input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+       input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
+}
+
+void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
+       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+       input_dev->relbit[0] |= BIT(REL_WHEEL);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
+               | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
+       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+       input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+       input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
+}
+
+void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+}
+
+void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER);
+}
+
+static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_endpoint_descriptor *endpoint;
+       struct wacom *wacom;
+       struct wacom_wac *wacom_wac;
+       struct input_dev *input_dev;
+       char rep_data[2], limit = 0;
+
+       wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+       wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!wacom || !input_dev || !wacom_wac)
+               goto fail1;
+
+       wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
+       if (!wacom_wac->data)
+               goto fail1;
+
+       wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!wacom->irq)
+               goto fail2;
+
+       wacom->usbdev = dev;
+       wacom->dev = input_dev;
+       usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+       strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
+
+       wacom_wac->features = get_wacom_feature(id);
+       if (wacom_wac->features->pktlen > 10)
+               BUG();
+
+       input_dev->name = wacom_wac->features->name;
+       wacom->wacom_wac = wacom_wac;
+       usb_to_input_id(dev, &input_dev->id);
+
+       input_dev->cdev.dev = &intf->dev;
+       input_dev->private = wacom;
+       input_dev->open = wacom_open;
+       input_dev->close = wacom_close;
+
+       input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+       input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
+       input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
+
+       wacom_init_input_dev(input_dev, wacom_wac);
+
+       endpoint = &intf->cur_altsetting->endpoint[0].desc;
+
+       usb_fill_int_urb(wacom->irq, dev,
+                        usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+                        wacom_wac->data, wacom_wac->features->pktlen,
+                        wacom_wac->features->irq, wacom, endpoint->bInterval);
+       wacom->irq->transfer_dma = wacom->data_dma;
+       wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       input_register_device(wacom->dev);
+
+       /* Ask the tablet to report tablet data. Repeat until it succeeds */
+       do {
+               rep_data[0] = 2;
+               rep_data[1] = 2;
+               usb_set_report(intf, 3, 2, rep_data, 2);
+               usb_get_report(intf, 3, 2, rep_data, 2);
+       } while (rep_data[1] != 2 && limit++ < 5);
+
+       usb_set_intfdata(intf, wacom);
+       return 0;
+
+fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+fail1: input_free_device(input_dev);
+       kfree(wacom);
+       kfree(wacom_wac);
+       return -ENOMEM;
+}
+
+static void wacom_disconnect(struct usb_interface *intf)
+{
+       struct wacom *wacom = usb_get_intfdata (intf);
+
+       usb_set_intfdata(intf, NULL);
+       if (wacom) {
+               usb_kill_urb(wacom->irq);
+               input_unregister_device(wacom->dev);
+               usb_free_urb(wacom->irq);
+               usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+               kfree(wacom);
+               kfree(wacom->wacom_wac);
+       }
+}
+
+static struct usb_driver wacom_driver = {
+       .name =         "wacom",
+       .probe =        wacom_probe,
+       .disconnect =   wacom_disconnect,
+};
+
+static int __init wacom_init(void)
+{
+       int result;
+       wacom_driver.id_table = get_device_table();
+       result = usb_register(&wacom_driver);
+       if (result == 0)
+               info(DRIVER_VERSION ":" DRIVER_DESC);
+       return result;
+}
+
+static void __exit wacom_exit(void)
+{
+       usb_deregister(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
new file mode 100644 (file)
index 0000000..85d458c
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * drivers/usb/input/wacom_wac.c
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code
+ *
+ */
+
+/*
+ * 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 "wacom.h"
+#include "wacom_wac.h"
+
+static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+
+       switch (data[0]) {
+               case 1:
+                       wacom_input_regs(wcombo);
+                       if (data[5] & 0x80) {
+                               wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+                               wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
+                               wacom_report_key(wcombo, wacom->tool[0], 1);
+                               wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
+                               wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+                               wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+                               wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
+                               wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127));
+                               wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
+                       } else {
+                               wacom_report_key(wcombo, wacom->tool[0], 0);
+                               wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */
+                               wacom_report_abs(wcombo, ABS_PRESSURE, -1);
+                               wacom_report_key(wcombo, BTN_TOUCH, 0);
+                       }
+                       break;
+               case 2:
+                       wacom_input_regs(wcombo);
+                       wacom_report_key(wcombo, BTN_TOOL_PEN, 1);
+                       wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
+                       wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+                       wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+                       wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
+                       wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
+                       wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
+                       break;
+               default:
+                       printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
+                       return 0;
+        }
+       return 1;
+}
+
+static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int prox, id, pressure;
+
+       if (data[0] != 2) {
+               dbg("wacom_pl_irq: received unknown report #%d", data[0]);
+               return 0;
+       }
+
+       prox = data[1] & 0x40;
+
+       wacom_input_regs(wcombo);
+
+       id = ERASER_DEVICE_ID;
+       if (prox) {
+
+               pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+               if (wacom->features->pressure_max > 255)
+                       pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+               pressure += (wacom->features->pressure_max + 1) / 2;
+
+               /*
+                * if going from out of proximity into proximity select between the eraser
+                * and the pen based on the state of the stylus2 button, choose eraser if
+                * pressed else choose pen. if not a proximity change from out to in, send
+                * an out of proximity for previous tool then a in for new tool.
+                */
+               if (!wacom->tool[0]) {
+                       /* Eraser bit set for DTF */
+                       if (data[1] & 0x10)
+                               wacom->tool[1] = BTN_TOOL_RUBBER;
+                       else
+                               /* Going into proximity select tool */
+                               wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+               } else {
+                       /* was entered with stylus2 pressed */
+                       if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
+                               /* report out proximity for previous tool */
+                               wacom_report_key(wcombo, wacom->tool[1], 0);
+                               wacom_input_sync(wcombo);
+                               wacom->tool[1] = BTN_TOOL_PEN;
+                               return 0;
+                       }
+               }
+               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+                       /* Unknown tool selected default to pen tool */
+                       wacom->tool[1] = BTN_TOOL_PEN;
+                       id = STYLUS_DEVICE_ID;
+               }
+               wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */
+               wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+               wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+               wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+               wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
+
+               wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08);
+               wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10);
+               /* Only allow the stylus2 button to be reported for the pen tool. */
+               wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
+       } else {
+               /* report proximity-out of a (valid) tool */
+               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+                       /* Unknown tool selected default to pen tool */
+                       wacom->tool[1] = BTN_TOOL_PEN;
+               }
+               wacom_report_key(wcombo, wacom->tool[1], prox);
+       }
+
+       wacom->tool[0] = prox; /* Save proximity state */
+       return 1;
+}
+
+static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int id;
+
+       if (data[0] != 2) {
+               printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
+               return 0;
+       }
+
+       wacom_input_regs(wcombo);
+       if (data[1] & 0x04) {
+               wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);
+               wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);
+               id = ERASER_DEVICE_ID;
+       } else {
+               wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);
+               wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
+               id = STYLUS_DEVICE_ID;
+       }
+       wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+       wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+       wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+       wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+       wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+       wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
+       return 1;
+}
+
+static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int x, y, id, rw;
+
+       if (data[0] != 2) {
+               dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
+               return 0;
+       }
+
+       wacom_input_regs(wcombo);
+
+       id = STYLUS_DEVICE_ID;
+       if (data[1] & 0x10) { /* in prox */
+
+               switch ((data[1] >> 5) & 3) {
+
+                       case 0: /* Pen */
+                               wacom->tool[0] = BTN_TOOL_PEN;
+                               break;
+
+                       case 1: /* Rubber */
+                               wacom->tool[0] = BTN_TOOL_RUBBER;
+                               id = ERASER_DEVICE_ID;
+                               break;
+
+                       case 2: /* Mouse with wheel */
+                               wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
+                               if (wacom->features->type == WACOM_G4) {
+                                       rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
+                                       wacom_report_rel(wcombo, REL_WHEEL, -rw);
+                               } else
+                                       wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]);
+                               /* fall through */
+
+                       case 3: /* Mouse without wheel */
+                               wacom->tool[0] = BTN_TOOL_MOUSE;
+                               id = CURSOR_DEVICE_ID;
+                               wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
+                               wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
+                               if (wacom->features->type == WACOM_G4)
+                                       wacom_report_abs(wcombo, ABS_DISTANCE, data[6]);
+                               else
+                                       wacom_report_abs(wcombo, ABS_DISTANCE, data[7]);
+                               break;
+               }
+       }
+
+       if (data[1] & 0x90) {
+               x = wacom_le16_to_cpu(&data[2]);
+               y = wacom_le16_to_cpu(&data[4]);
+               wacom_report_abs(wcombo, ABS_X, x);
+               wacom_report_abs(wcombo, ABS_Y, y);
+               if (wacom->tool[0] != BTN_TOOL_MOUSE) {
+                       wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
+                       wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
+                       wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+                       wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
+               }
+       }
+
+       if (data[1] & 0x10)
+               wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+       else
+               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+       wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10);
+       wacom_input_sync(wcombo);
+
+       /* send pad data */
+       if (wacom->features->type == WACOM_G4) {
+               if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) {
+                       wacom->id[1] = 1;
+                       wacom->serial[1] = (data[7] & 0xf8);
+                       wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+                       wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
+                       rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
+                       wacom_report_rel(wcombo, REL_WHEEL, rw);
+                       wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+               } else if (wacom->id[1]) {
+                       wacom->id[1] = 0;
+                       wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+               }
+       }
+       return 1;
+}
+
+static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int idx;
+
+       /* tool number */
+       idx = data[1] & 0x01;
+
+       /* Enter report */
+       if ((data[1] & 0xfc) == 0xc0) {
+               /* serial number of the tool */
+               wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+                       (data[4] << 20) + (data[5] << 12) +
+                       (data[6] << 4) + (data[7] >> 4);
+
+               wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+               switch (wacom->id[idx]) {
+                       case 0x812: /* Inking pen */
+                       case 0x801: /* Intuos3 Inking pen */
+                       case 0x012:
+                               wacom->tool[idx] = BTN_TOOL_PENCIL;
+                               break;
+                       case 0x822: /* Pen */
+                       case 0x842:
+                       case 0x852:
+                       case 0x823: /* Intuos3 Grip Pen */
+                       case 0x813: /* Intuos3 Classic Pen */
+                       case 0x885: /* Intuos3 Marker Pen */
+                       case 0x022:
+                               wacom->tool[idx] = BTN_TOOL_PEN;
+                               break;
+                       case 0x832: /* Stroke pen */
+                       case 0x032:
+                               wacom->tool[idx] = BTN_TOOL_BRUSH;
+                               break;
+                       case 0x007: /* Mouse 4D and 2D */
+                       case 0x09c:
+                       case 0x094:
+                       case 0x017: /* Intuos3 2D Mouse */
+                               wacom->tool[idx] = BTN_TOOL_MOUSE;
+                               break;
+                       case 0x096: /* Lens cursor */
+                       case 0x097: /* Intuos3 Lens cursor */
+                               wacom->tool[idx] = BTN_TOOL_LENS;
+                               break;
+                       case 0x82a: /* Eraser */
+                       case 0x85a:
+                       case 0x91a:
+                       case 0xd1a:
+                       case 0x0fa:
+                       case 0x82b: /* Intuos3 Grip Pen Eraser */
+                       case 0x81b: /* Intuos3 Classic Pen Eraser */
+                       case 0x91b: /* Intuos3 Airbrush Eraser */
+                               wacom->tool[idx] = BTN_TOOL_RUBBER;
+                               break;
+                       case 0xd12:
+                       case 0x912:
+                       case 0x112:
+                       case 0x913: /* Intuos3 Airbrush */
+                               wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
+                               break;
+                       default: /* Unknown tool */
+                               wacom->tool[idx] = BTN_TOOL_PEN;
+               }
+               /* only large I3 support Lens Cursor */
+               if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
+                               (wacom->features->type == INTUOS3))) {
+                       wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
+                       wacom_report_key(wcombo, wacom->tool[idx], 1);
+                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+                       return 2;
+               }
+               return 1;
+       }
+
+       /* Exit report */
+       if ((data[1] & 0xfe) == 0x80) {
+               wacom_report_key(wcombo, wacom->tool[idx], 0);
+               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+               wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+               return 2;
+       }
+       return 0;
+}
+
+static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       unsigned int t;
+
+       /* general pen packet */
+       if ((data[1] & 0xb8) == 0xa0) {
+               t = (data[6] << 2) | ((data[7] >> 6) & 3);
+               wacom_report_abs(wcombo, ABS_PRESSURE, t);
+               wacom_report_abs(wcombo, ABS_TILT_X,
+                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+               wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+               wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2);
+               wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4);
+               wacom_report_key(wcombo, BTN_TOUCH, t > 10);
+       }
+
+       /* airbrush second packet */
+       if ((data[1] & 0xbc) == 0xb4) {
+               wacom_report_abs(wcombo, ABS_WHEEL,
+                               (data[6] << 2) | ((data[7] >> 6) & 3));
+               wacom_report_abs(wcombo, ABS_TILT_X,
+                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+               wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+       }
+       return;
+}
+
+static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       unsigned int t;
+       int idx, result;
+
+       if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
+               dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
+                return 0;
+       }
+
+       wacom_input_regs(wcombo);
+
+       /* tool number */
+       idx = data[1] & 0x01;
+
+       /* pad packets. Works as a second tool and is always in prox */
+       if (data[0] == 12) {
+               /* initiate the pad as a device */
+               if (wacom->tool[1] != BTN_TOOL_FINGER)
+                       wacom->tool[1] = BTN_TOOL_FINGER;
+
+               wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
+               wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
+               wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
+               wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
+               wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
+               wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
+               wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
+               wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
+               wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+               wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+               if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
+                       wacom_report_key(wcombo, wacom->tool[1], 1);
+               else
+                       wacom_report_key(wcombo, wacom->tool[1], 0);
+               wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
+                return 1;
+       }
+
+       /* process in/out prox events */
+       result = wacom_intuos_inout(wacom, wcombo);
+       if (result)
+                return result-1;
+
+       /* Cintiq doesn't send data when RDY bit isn't set */
+       if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
+                 return 0;
+
+       if (wacom->features->type >= INTUOS3) {
+               wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
+               wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
+               wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
+       } else {
+               wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2]));
+               wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4]));
+               wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
+       }
+
+       /* process general packets */
+       wacom_intuos_general(wacom, wcombo);
+
+       /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
+       if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
+
+               if (data[1] & 0x02) {
+                       /* Rotation packet */
+                       if (wacom->features->type >= INTUOS3) {
+                               /* I3 marker pen rotation reported as wheel
+                                * due to valuator limitation
+                                */
+                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
+                               t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+                                       ((t-1) / 2 + 450)) : (450 - t / 2) ;
+                               wacom_report_abs(wcombo, ABS_WHEEL, t);
+                       } else {
+                               /* 4D mouse rotation packet */
+                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
+                               wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ?
+                                       ((t - 1) / 2) : -t / 2);
+                       }
+
+               } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
+                       /* 4D mouse packet */
+                       wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
+                       wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
+                       wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
+
+                       wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x20);
+                       wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x10);
+                       t = (data[6] << 2) | ((data[7] >> 6) & 3);
+                       wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
+
+               } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
+                       /* 2D mouse packet */
+                       wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
+                       wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
+                       wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
+                       wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
+                                                - ((data[8] & 0x02) >> 1));
+
+                       /* I3 2D mouse side buttons */
+                       if (wacom->features->type == INTUOS3) {
+                               wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
+                               wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
+                       }
+
+               } else if (wacom->features->type < INTUOS3) {
+                       /* Lens cursor packets */
+                       wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
+                       wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
+                       wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
+                       wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x10);
+                       wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x08);
+               }
+       }
+
+       wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
+       wacom_report_key(wcombo, wacom->tool[idx], 1);
+       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+       return 1;
+}
+
+int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
+{
+       switch (wacom_wac->features->type) {
+               case PENPARTNER:
+                       return (wacom_penpartner_irq(wacom_wac, wcombo));
+                       break;
+               case PL:
+                       return (wacom_pl_irq(wacom_wac, wcombo));
+                       break;
+               case WACOM_G4:
+               case GRAPHIRE:
+                       return (wacom_graphire_irq(wacom_wac, wcombo));
+                       break;
+               case PTU:
+                       return (wacom_ptu_irq(wacom_wac, wcombo));
+                       break;
+               case INTUOS:
+               case INTUOS3:
+               case INTUOS3L:
+               case CINTIQ:
+                       return (wacom_intuos_irq(wacom_wac, wcombo));
+                       break;
+               default:
+                       return 0;
+       }
+       return 0;
+}
+
+void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       switch (wacom_wac->features->type) {
+               case WACOM_G4:
+                       input_dev_g4(input_dev, wacom_wac);
+                       /* fall through */
+               case GRAPHIRE:
+                       input_dev_g(input_dev, wacom_wac);
+                       break;
+               case INTUOS3:
+               case INTUOS3L:
+               case CINTIQ:
+                       input_dev_i3(input_dev, wacom_wac);
+                       /* fall through */
+               case INTUOS:
+                       input_dev_i(input_dev, wacom_wac);
+                       break;
+               case PL:
+               case PTU:
+                       input_dev_pl(input_dev, wacom_wac);
+                       break;
+               case PENPARTNER:
+                       input_dev_pt(input_dev, wacom_wac);
+                       break;
+       }
+       return;
+}
+
+static struct wacom_features wacom_features[] = {
+       { "Wacom Penpartner",    7,   5040,  3780,  255, 32, PENPARTNER,        wacom_sys_irq },
+        { "Wacom Graphire",      8,  10206,  7422,  511, 32, GRAPHIRE, wacom_sys_irq },
+       { "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire3",     8,  10208,  7424,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 32, WACOM_G4,  wacom_sys_irq },
+       { "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 32, WACOM_G4,  wacom_sys_irq },
+       { "Wacom Volito",        8,   5104,  3712,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom PenStation2",   8,   3250,  2320,  255, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Volito2 4x5",   8,   5104,  3712,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Volito2 2x3",   8,   3248,  2320,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom PenPartner2",   8,   3250,  2320,  255, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, INTUOS,    wacom_sys_irq},
+       { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, INTUOS,    wacom_sys_irq},
+       { "Wacom PL400",         8,   5408,  4056,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL500",         8,   6144,  4608,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL600",         8,   6126,  4604,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL600SX",       8,   6260,  5016,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL550",         8,   6144,  4608,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom PL800",         8,   7220,  5780,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom PL700",         8,   6758,  5406,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom PL510",         8,   6282,  4762,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PTU,       wacom_sys_irq },
+       { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS3L,  wacom_sys_irq },
+       { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS3L,  wacom_sys_irq },
+       { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,    wacom_sys_irq },
+       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,    wacom_sys_irq },
+       { }
+};
+
+static struct usb_device_id wacom_ids[] = {
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
+       { }
+};
+
+const struct usb_device_id * get_device_table(void) {
+        const struct usb_device_id * id_table = wacom_ids;
+        return id_table;
+}
+
+struct wacom_features * get_wacom_feature(const struct usb_device_id * id) {
+        int index = id - wacom_ids;
+        struct wacom_features *wf = &wacom_features[index];
+        return wf;
+}
+
+MODULE_DEVICE_TABLE(usb, wacom_ids);
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h
new file mode 100644 (file)
index 0000000..ceae7bf
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * drivers/usb/input/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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef WACOM_WAC_H
+#define WACOM_WAC_H
+
+#define STYLUS_DEVICE_ID       0x02
+#define CURSOR_DEVICE_ID       0x06
+#define ERASER_DEVICE_ID       0x0A
+
+enum {
+       PENPARTNER = 0,
+       GRAPHIRE,
+       WACOM_G4,
+       PTU,
+       PL,
+       INTUOS,
+       INTUOS3,
+       INTUOS3L,
+       CINTIQ,
+       MAX_TYPE
+};
+
+struct wacom_features {
+       char *name;
+       int pktlen;
+       int x_max;
+       int y_max;
+       int pressure_max;
+       int distance_max;
+       int type;
+       usb_complete_t irq;
+};
+
+struct wacom_wac {
+       signed char *data;
+        int tool[2];
+        int id[2];
+        __u32 serial[2];
+       struct wacom_features *features;
+};
+
+#endif
index 7b45fd3de9116715abe9c1c5c19cda527ba739e2..7291e7a2717b4ade9a3a0530ddc2e908cd9fde35 100644 (file)
@@ -971,7 +971,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
                        DRIVER_VERSION, sizeof(DRIVER_VERSION));
 
        /* Register sysfs hooks (don't care about failure) */
-       sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
+       ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
        return 0;
 }
 
index 88928a4be8057e9c286218ecacfecb17334db45e..c29658f69e2a8c0db81dc26a9d1fe9addb1bb96a 100644 (file)
@@ -32,6 +32,16 @@ config USB_EMI26
          To compile this driver as a module, choose M here: the
          module will be called emi26.
 
+config USB_ADUTUX
+       tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)"
+       depends on USB && EXPERIMENTAL
+       help
+         Say Y if you want to use an ADU device from Ontrak Control
+         Systems.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called adutux.
+
 config USB_AUERSWALD
        tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
        depends on USB && EXPERIMENTAL
@@ -115,19 +125,36 @@ config USB_CYTHERM
          To compile this driver as a module, choose M here: the
          module will be called cytherm.
 
-config USB_PHIDGETKIT
-       tristate "USB PhidgetKit support"
+config USB_PHIDGET
+       tristate "USB Phidgets drivers"
        depends on USB
        help
-         Say Y here if you want to connect a PhidgetKit USB device from
-         Phidgets Inc.
+         Say Y here to enable the various drivers for devices from
+         Phidgets inc.
+
+config USB_PHIDGETKIT
+       tristate "USB PhidgetInterfaceKit support"
+       depends on USB_PHIDGET
+       help
+         Say Y here if you want to connect a PhidgetInterfaceKit USB device
+         from Phidgets Inc.
 
          To compile this driver as a module, choose M here: the
          module will be called phidgetkit.
 
+config USB_PHIDGETMOTORCONTROL
+       tristate "USB PhidgetMotorControl support"
+       depends on USB_PHIDGET
+       help
+         Say Y here if you want to connect a PhidgetMotorControl USB device
+         from Phidgets Inc.
+
+         To compile this driver as a module, choose M here: the
+         module will be called phidgetmotorcontrol.
+
 config USB_PHIDGETSERVO
        tristate "USB PhidgetServo support"
-       depends on USB
+       depends on USB_PHIDGET
        help
          Say Y here if you want to connect an 1 or 4 Motor PhidgetServo 
          servo controller version 2.0 or 3.0.
@@ -151,6 +178,30 @@ config USB_IDMOUSE
 
          See also <http://www.fs.tum.de/~echtler/idmouse/>.
 
+config USB_FTDI_ELAN
+       tristate "Elan PCMCIA CardBus Adapter USB Client"
+       depends on USB
+       default M
+       help
+         ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
+         Currently only the U132 adapter is available.
+
+         The U132 is specifically designed for CardBus PC cards that contain
+         an OHCI host controller. Typical PC cards are the Orange Mobile 3G
+         Option GlobeTrotter Fusion card. The U132 adapter will *NOT* work
+         with PC cards that do not contain an OHCI controller. To use a U132
+         adapter you will need this "ftdi-elan" module as well as the "u132-hcd"
+         module which is a USB host controller driver that talks to the OHCI
+         controller within CardBus card that are inserted in the U132 adapter.
+
+         This driver has been tested with a CardBus OHCI USB adapter, and
+         worked with a USB PEN Drive inserted into the first USB port of
+         the PCCARD. A rather pointless thing to do, but useful for testing.
+
+         See also the USB_U132_HCD entry "Elan U132 Adapter Host Controller"
+
+         It is safe to say M here.
+
 config USB_APPLEDISPLAY
        tristate "Apple Cinema Display support"
        depends on USB
index 2927260c5812eed54c2ad21cb001762430d3f4cf..2be70fa259bfe16cc45ebbdcae5db57dd33dcd9d 100644 (file)
@@ -3,22 +3,25 @@
 # (the ones that don't fit into any other categories)
 #
 
+obj-$(CONFIG_USB_ADUTUX)       += adutux.o
 obj-$(CONFIG_USB_AUERSWALD)    += auerswald.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)      += cytherm.o
 obj-$(CONFIG_USB_EMI26)                += emi26.o
 obj-$(CONFIG_USB_EMI62)                += emi62.o
+obj-$(CONFIG_USB_FTDI_ELAN)    += ftdi-elan.o
 obj-$(CONFIG_USB_IDMOUSE)      += idmouse.o
 obj-$(CONFIG_USB_LCD)          += usblcd.o
 obj-$(CONFIG_USB_LD)           += ldusb.o
 obj-$(CONFIG_USB_LED)          += usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)    += legousbtower.o
+obj-$(CONFIG_USB_PHIDGET)      += phidget.o
 obj-$(CONFIG_USB_PHIDGETKIT)   += phidgetkit.o
+obj-$(CONFIG_USB_PHIDGETMOTORCONTROL)  += phidgetmotorcontrol.o
 obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
 obj-$(CONFIG_USB_RIO500)       += rio500.o
 obj-$(CONFIG_USB_TEST)         += usbtest.o
 obj-$(CONFIG_USB_USS720)       += uss720.o
-obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
 
 obj-$(CONFIG_USB_SISUSBVGA)    += sisusbvga/
 
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
new file mode 100644 (file)
index 0000000..d396319
--- /dev/null
@@ -0,0 +1,900 @@
+/*
+ * adutux - driver for ADU devices from Ontrak Control Systems
+ * This is an experimental driver. Use at your own risk.
+ * This driver is not supported by Ontrak Control Systems.
+ *
+ * Copyright (c) 2003 John Homppi (SCO, leave this notice here)
+ *
+ * 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.
+ *
+ * derived from the Lego USB Tower driver 0.56:
+ * Copyright (c) 2003 David Glance <davidgsf@sourceforge.net>
+ *               2001 Juergen Stuber <stuber@loria.fr>
+ * that was derived from USB Skeleton driver - 0.5
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_USB_DEBUG
+static int debug = 5;
+#else
+static int debug = 1;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(lvl, format, arg...)                                       \
+do {                                                                   \
+       if (debug >= lvl)                                               \
+               printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg); \
+} while (0)
+
+
+/* Version Information */
+#define DRIVER_VERSION "v0.0.13"
+#define DRIVER_AUTHOR "John Homppi"
+#define DRIVER_DESC "adutux (see www.ontrak.net)"
+
+/* Module parameters */
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* Define these values to match your device */
+#define ADU_VENDOR_ID 0x0a07
+#define ADU_PRODUCT_ID 0x0064
+
+/* table of devices that work with this driver */
+static struct usb_device_id device_table [] = {
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) },          /* ADU100 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) },       /* ADU120 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) },       /* ADU130 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) },      /* ADU200 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) },      /* ADU208 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) },      /* ADU218 */
+       { }/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define ADU_MINOR_BASE 0
+#else
+#define ADU_MINOR_BASE 67
+#endif
+
+/* we can have up to this number of device plugged in at once */
+#define MAX_DEVICES    16
+
+#define COMMAND_TIMEOUT        (2*HZ)  /* 60 second timeout for a command */
+
+/* Structure to hold all of our device specific stuff */
+struct adu_device {
+       struct semaphore        sem; /* locks this structure */
+       struct usb_device*      udev; /* save off the usb device pointer */
+       struct usb_interface*   interface;
+       unsigned char           minor; /* the starting minor number for this device */
+       char                    serial_number[8];
+
+       int                     open_count; /* number of times this port has been opened */
+
+       char*                   read_buffer_primary;
+       int                     read_buffer_length;
+       char*                   read_buffer_secondary;
+       int                     secondary_head;
+       int                     secondary_tail;
+       spinlock_t              buflock;
+
+       wait_queue_head_t       read_wait;
+       wait_queue_head_t       write_wait;
+
+       char*                   interrupt_in_buffer;
+       struct usb_endpoint_descriptor* interrupt_in_endpoint;
+       struct urb*             interrupt_in_urb;
+       int                     read_urb_finished;
+
+       char*                   interrupt_out_buffer;
+       struct usb_endpoint_descriptor* interrupt_out_endpoint;
+       struct urb*             interrupt_out_urb;
+};
+
+/* prevent races between open() and disconnect */
+static DEFINE_MUTEX(disconnect_mutex);
+static struct usb_driver adu_driver;
+
+static void adu_debug_data(int level, const char *function, int size,
+                          const unsigned char *data)
+{
+       int i;
+
+       if (debug < level)
+               return;
+
+       printk(KERN_DEBUG __FILE__": %s - length = %d, data = ",
+              function, size);
+       for (i = 0; i < size; ++i)
+               printk("%.2x ", data[i]);
+       printk("\n");
+}
+
+/**
+ * adu_abort_transfers
+ *      aborts transfers and frees associated data structures
+ */
+static void adu_abort_transfers(struct adu_device *dev)
+{
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (dev == NULL) {
+               dbg(1," %s : dev is null", __FUNCTION__);
+               goto exit;
+       }
+
+       if (dev->udev == NULL) {
+               dbg(1," %s : udev is null", __FUNCTION__);
+               goto exit;
+       }
+
+       dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state);
+       if (dev->udev->state == USB_STATE_NOTATTACHED) {
+               dbg(1," %s : udev is not attached", __FUNCTION__);
+               goto exit;
+       }
+
+       /* shutdown transfer */
+       usb_unlink_urb(dev->interrupt_in_urb);
+       usb_unlink_urb(dev->interrupt_out_urb);
+
+exit:
+       dbg(2," %s : leave", __FUNCTION__);
+}
+
+static void adu_delete(struct adu_device *dev)
+{
+       dbg(2, "%s enter", __FUNCTION__);
+
+       adu_abort_transfers(dev);
+
+       /* free data structures */
+       usb_free_urb(dev->interrupt_in_urb);
+       usb_free_urb(dev->interrupt_out_urb);
+       kfree(dev->read_buffer_primary);
+       kfree(dev->read_buffer_secondary);
+       kfree(dev->interrupt_in_buffer);
+       kfree(dev->interrupt_out_buffer);
+       kfree(dev);
+
+       dbg(2, "%s : leave", __FUNCTION__);
+}
+
+static void adu_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct adu_device *dev = urb->context;
+
+       dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+                      urb->transfer_buffer);
+
+       spin_lock(&dev->buflock);
+
+       if (urb->status != 0) {
+               if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) {
+                       dbg(1," %s : nonzero status received: %d",
+                           __FUNCTION__, urb->status);
+               }
+               goto exit;
+       }
+
+       if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) {
+               if (dev->read_buffer_length <
+                   (4 * le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize)) -
+                    (urb->actual_length)) {
+                       memcpy (dev->read_buffer_primary +
+                               dev->read_buffer_length,
+                               dev->interrupt_in_buffer, urb->actual_length);
+
+                       dev->read_buffer_length += urb->actual_length;
+                       dbg(2," %s reading  %d ", __FUNCTION__,
+                           urb->actual_length);
+               } else {
+                       dbg(1," %s : read_buffer overflow", __FUNCTION__);
+               }
+       }
+
+exit:
+       dev->read_urb_finished = 1;
+       spin_unlock(&dev->buflock);
+       /* always wake up so we recover from errors */
+       wake_up_interruptible(&dev->read_wait);
+       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+                      urb->transfer_buffer);
+       dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+}
+
+static void adu_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct adu_device *dev = urb->context;
+
+       dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+       adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
+
+       if (urb->status != 0) {
+               if ((urb->status != -ENOENT) &&
+                   (urb->status != -ECONNRESET)) {
+                       dbg(1, " %s :nonzero status received: %d",
+                           __FUNCTION__, urb->status);
+               }
+               goto exit;
+       }
+
+       wake_up_interruptible(&dev->write_wait);
+exit:
+
+       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+                      urb->transfer_buffer);
+       dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+}
+
+static int adu_open(struct inode *inode, struct file *file)
+{
+       struct adu_device *dev = NULL;
+       struct usb_interface *interface;
+       int subminor;
+       int retval = 0;
+
+       dbg(2,"%s : enter", __FUNCTION__);
+
+       subminor = iminor(inode);
+
+       mutex_lock(&disconnect_mutex);
+
+       interface = usb_find_interface(&adu_driver, subminor);
+       if (!interface) {
+               err("%s - error, can't find device for minor %d",
+                   __FUNCTION__, subminor);
+               retval = -ENODEV;
+               goto exit_no_device;
+       }
+
+       dev = usb_get_intfdata(interface);
+       if (!dev) {
+               retval = -ENODEV;
+               goto exit_no_device;
+       }
+
+       /* lock this device */
+       if ((retval = down_interruptible(&dev->sem))) {
+               dbg(2, "%s : sem down failed", __FUNCTION__);
+               goto exit_no_device;
+       }
+
+       /* increment our usage count for the device */
+       ++dev->open_count;
+       dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
+
+       /* save device in the file's private structure */
+       file->private_data = dev;
+
+       /* initialize in direction */
+       dev->read_buffer_length = 0;
+
+       /* fixup first read by having urb waiting for it */
+       usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+                        usb_rcvintpipe(dev->udev,
+                                       dev->interrupt_in_endpoint->bEndpointAddress),
+                        dev->interrupt_in_buffer,
+                        le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+                        adu_interrupt_in_callback, dev,
+                        dev->interrupt_in_endpoint->bInterval);
+       /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+       dev->read_urb_finished = 0;
+       usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+       /* we ignore failure */
+       /* end of fixup for first read */
+
+       up(&dev->sem);
+
+exit_no_device:
+       mutex_unlock(&disconnect_mutex);
+       dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
+
+       return retval;
+}
+
+static int adu_release_internal(struct adu_device *dev)
+{
+       int retval = 0;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (dev->udev == NULL) {
+               /* the device was unplugged before the file was released */
+               adu_delete(dev);
+               goto exit;
+       }
+
+       /* decrement our usage count for the device */
+       --dev->open_count;
+       dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+       if (dev->open_count <= 0) {
+               adu_abort_transfers(dev);
+               dev->open_count = 0;
+       }
+
+exit:
+       dbg(2," %s : leave", __FUNCTION__);
+       return retval;
+}
+
+static int adu_release(struct inode *inode, struct file *file)
+{
+       struct adu_device *dev = NULL;
+       int retval = 0;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (file == NULL) {
+               dbg(1," %s : file is NULL", __FUNCTION__);
+               retval = -ENODEV;
+               goto exit;
+       }
+
+       dev = file->private_data;
+
+       if (dev == NULL) {
+               dbg(1," %s : object is NULL", __FUNCTION__);
+               retval = -ENODEV;
+               goto exit;
+       }
+
+       /* lock our device */
+       down(&dev->sem); /* not interruptible */
+
+       if (dev->open_count <= 0) {
+               dbg(1," %s : device not opened", __FUNCTION__);
+               retval = -ENODEV;
+               goto exit;
+       }
+
+       /* do the work */
+       retval = adu_release_internal(dev);
+
+exit:
+       up(&dev->sem);
+       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       return retval;
+}
+
+static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+                       loff_t *ppos)
+{
+       struct adu_device *dev;
+       size_t bytes_read = 0;
+       size_t bytes_to_read = count;
+       int i;
+       int retval = 0;
+       int timeout = 0;
+       int should_submit = 0;
+       unsigned long flags;
+       DECLARE_WAITQUEUE(wait, current);
+
+       dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
+
+       dev = file->private_data;
+       dbg(2," %s : dev=%p", __FUNCTION__, dev);
+       /* lock this object */
+       if (down_interruptible(&dev->sem))
+               return -ERESTARTSYS;
+
+       /* verify that the device wasn't unplugged */
+       if (dev->udev == NULL || dev->minor == 0) {
+               retval = -ENODEV;
+               err("No device or device unplugged %d", retval);
+               goto exit;
+       }
+
+       /* verify that some data was requested */
+       if (count == 0) {
+               dbg(1," %s : read request of 0 bytes", __FUNCTION__);
+               goto exit;
+       }
+
+       timeout = COMMAND_TIMEOUT;
+       dbg(2," %s : about to start looping", __FUNCTION__);
+       while (bytes_to_read) {
+               int data_in_secondary = dev->secondary_tail - dev->secondary_head;
+               dbg(2," %s : while, data_in_secondary=%d, status=%d",
+                   __FUNCTION__, data_in_secondary,
+                   dev->interrupt_in_urb->status);
+
+               if (data_in_secondary) {
+                       /* drain secondary buffer */
+                       int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary;
+                       i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount);
+                       if (i < 0) {
+                               retval = -EFAULT;
+                               goto exit;
+                       }
+                       dev->secondary_head += (amount - i);
+                       bytes_read += (amount - i);
+                       bytes_to_read -= (amount - i);
+                       if (i) {
+                               retval = bytes_read ? bytes_read : -EFAULT;
+                               goto exit;
+                       }
+               } else {
+                       /* we check the primary buffer */
+                       spin_lock_irqsave (&dev->buflock, flags);
+                       if (dev->read_buffer_length) {
+                               /* we secure access to the primary */
+                               char *tmp;
+                               dbg(2," %s : swap, read_buffer_length = %d",
+                                   __FUNCTION__, dev->read_buffer_length);
+                               tmp = dev->read_buffer_secondary;
+                               dev->read_buffer_secondary = dev->read_buffer_primary;
+                               dev->read_buffer_primary = tmp;
+                               dev->secondary_head = 0;
+                               dev->secondary_tail = dev->read_buffer_length;
+                               dev->read_buffer_length = 0;
+                               spin_unlock_irqrestore(&dev->buflock, flags);
+                               /* we have a free buffer so use it */
+                               should_submit = 1;
+                       } else {
+                               /* even the primary was empty - we may need to do IO */
+                               if (dev->interrupt_in_urb->status == -EINPROGRESS) {
+                                       /* somebody is doing IO */
+                                       spin_unlock_irqrestore(&dev->buflock, flags);
+                                       dbg(2," %s : submitted already", __FUNCTION__);
+                               } else {
+                                       /* we must initiate input */
+                                       dbg(2," %s : initiate input", __FUNCTION__);
+                                       dev->read_urb_finished = 0;
+
+                                       usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+                                                        usb_rcvintpipe(dev->udev,
+                                                                       dev->interrupt_in_endpoint->bEndpointAddress),
+                                                        dev->interrupt_in_buffer,
+                                                        le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+                                                        adu_interrupt_in_callback,
+                                                        dev,
+                                                        dev->interrupt_in_endpoint->bInterval);
+                                       retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+                                       if (!retval) {
+                                               spin_unlock_irqrestore(&dev->buflock, flags);
+                                               dbg(2," %s : submitted OK", __FUNCTION__);
+                                       } else {
+                                               if (retval == -ENOMEM) {
+                                                       retval = bytes_read ? bytes_read : -ENOMEM;
+                                               }
+                                               spin_unlock_irqrestore(&dev->buflock, flags);
+                                               dbg(2," %s : submit failed", __FUNCTION__);
+                                               goto exit;
+                                       }
+                               }
+
+                               /* we wait for I/O to complete */
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               add_wait_queue(&dev->read_wait, &wait);
+                               if (!dev->read_urb_finished)
+                                       timeout = schedule_timeout(COMMAND_TIMEOUT);
+                               else
+                                       set_current_state(TASK_RUNNING);
+                               remove_wait_queue(&dev->read_wait, &wait);
+
+                               if (timeout <= 0) {
+                                       dbg(2," %s : timeout", __FUNCTION__);
+                                       retval = bytes_read ? bytes_read : -ETIMEDOUT;
+                                       goto exit;
+                               }
+
+                               if (signal_pending(current)) {
+                                       dbg(2," %s : signal pending", __FUNCTION__);
+                                       retval = bytes_read ? bytes_read : -EINTR;
+                                       goto exit;
+                               }
+                       }
+               }
+       }
+
+       retval = bytes_read;
+       /* if the primary buffer is empty then use it */
+       if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) {
+               usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+                                usb_rcvintpipe(dev->udev,
+                                               dev->interrupt_in_endpoint->bEndpointAddress),
+                                               dev->interrupt_in_buffer,
+                                               le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+                                               adu_interrupt_in_callback,
+                                               dev,
+                                               dev->interrupt_in_endpoint->bInterval);
+               /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+               dev->read_urb_finished = 0;
+               usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+               /* we ignore failure */
+       }
+
+exit:
+       /* unlock the device */
+       up(&dev->sem);
+
+       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       return retval;
+}
+
+static ssize_t adu_write(struct file *file, const __user char *buffer,
+                        size_t count, loff_t *ppos)
+{
+       struct adu_device *dev;
+       size_t bytes_written = 0;
+       size_t bytes_to_write;
+       size_t buffer_size;
+       int retval = 0;
+       int timeout = 0;
+
+       dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
+
+       dev = file->private_data;
+
+       /* lock this object */
+       down_interruptible(&dev->sem);
+
+       /* verify that the device wasn't unplugged */
+       if (dev->udev == NULL || dev->minor == 0) {
+               retval = -ENODEV;
+               err("No device or device unplugged %d", retval);
+               goto exit;
+       }
+
+       /* verify that we actually have some data to write */
+       if (count == 0) {
+               dbg(1," %s : write request of 0 bytes", __FUNCTION__);
+               goto exit;
+       }
+
+
+       while (count > 0) {
+               if (dev->interrupt_out_urb->status == -EINPROGRESS) {
+                       timeout = COMMAND_TIMEOUT;
+
+                       while (timeout > 0) {
+                               if (signal_pending(current)) {
+                               dbg(1," %s : interrupted", __FUNCTION__);
+                               retval = -EINTR;
+                               goto exit;
+                       }
+                       up(&dev->sem);
+                       timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
+                       down_interruptible(&dev->sem);
+                       if (timeout > 0) {
+                               break;
+                       }
+                       dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout);
+               }
+
+
+               dbg(1," %s : final timeout: %d", __FUNCTION__, timeout);
+
+               if (timeout == 0) {
+                       dbg(1, "%s - command timed out.", __FUNCTION__);
+                       retval = -ETIMEDOUT;
+                       goto exit;
+               }
+
+               dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
+
+               } else {
+                       dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
+
+                       /* write the data into interrupt_out_buffer from userspace */
+                       buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+                       bytes_to_write = count > buffer_size ? buffer_size : count;
+                       dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
+                           __FUNCTION__, buffer_size, count, bytes_to_write);
+
+                       if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
+                               retval = -EFAULT;
+                               goto exit;
+                       }
+
+                       /* send off the urb */
+                       usb_fill_int_urb(
+                               dev->interrupt_out_urb,
+                               dev->udev,
+                               usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
+                               dev->interrupt_out_buffer,
+                               bytes_to_write,
+                               adu_interrupt_out_callback,
+                               dev,
+                               dev->interrupt_in_endpoint->bInterval);
+                       /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+                       dev->interrupt_out_urb->actual_length = bytes_to_write;
+                       retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+                       if (retval < 0) {
+                               err("Couldn't submit interrupt_out_urb %d", retval);
+                               goto exit;
+                       }
+
+                       buffer += bytes_to_write;
+                       count -= bytes_to_write;
+
+                       bytes_written += bytes_to_write;
+               }
+       }
+
+       retval = bytes_written;
+
+exit:
+       /* unlock the device */
+       up(&dev->sem);
+
+       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+
+       return retval;
+}
+
+/* file operations needed when we register this driver */
+static struct file_operations adu_fops = {
+       .owner = THIS_MODULE,
+       .read  = adu_read,
+       .write = adu_write,
+       .open = adu_open,
+       .release = adu_release,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver adu_class = {
+       .name = "usb/adutux%d",
+       .fops = &adu_fops,
+       .minor_base = ADU_MINOR_BASE,
+};
+
+/**
+ * adu_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int adu_probe(struct usb_interface *interface,
+                    const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct adu_device *dev = NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int retval = -ENODEV;
+       int in_end_size;
+       int out_end_size;
+       int i;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (udev == NULL) {
+               dev_err(&interface->dev, "udev is NULL.\n");
+               goto exit;
+       }
+
+       /* allocate memory for our device state and intialize it */
+       dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory\n");
+               retval = -ENOMEM;
+               goto exit;
+       }
+
+       init_MUTEX(&dev->sem);
+       spin_lock_init(&dev->buflock);
+       dev->udev = udev;
+       init_waitqueue_head(&dev->read_wait);
+       init_waitqueue_head(&dev->write_wait);
+
+       iface_desc = &interface->altsetting[0];
+
+       /* set up the endpoint information */
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_int_in(endpoint))
+                       dev->interrupt_in_endpoint = endpoint;
+
+               if (usb_endpoint_is_int_out(endpoint))
+                       dev->interrupt_out_endpoint = endpoint;
+       }
+       if (dev->interrupt_in_endpoint == NULL) {
+               dev_err(&interface->dev, "interrupt in endpoint not found\n");
+               goto error;
+       }
+       if (dev->interrupt_out_endpoint == NULL) {
+               dev_err(&interface->dev, "interrupt out endpoint not found\n");
+               goto error;
+       }
+
+       in_end_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+       out_end_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+
+       dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL);
+       if (!dev->read_buffer_primary) {
+               dev_err(&interface->dev, "Couldn't allocate read_buffer_primary\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       /* debug code prime the buffer */
+       memset(dev->read_buffer_primary, 'a', in_end_size);
+       memset(dev->read_buffer_primary + in_end_size, 'b', in_end_size);
+       memset(dev->read_buffer_primary + (2 * in_end_size), 'c', in_end_size);
+       memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size);
+
+       dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL);
+       if (!dev->read_buffer_secondary) {
+               dev_err(&interface->dev, "Couldn't allocate read_buffer_secondary\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       /* debug code prime the buffer */
+       memset(dev->read_buffer_secondary, 'e', in_end_size);
+       memset(dev->read_buffer_secondary + in_end_size, 'f', in_end_size);
+       memset(dev->read_buffer_secondary + (2 * in_end_size), 'g', in_end_size);
+       memset(dev->read_buffer_secondary + (3 * in_end_size), 'h', in_end_size);
+
+       dev->interrupt_in_buffer = kmalloc(in_end_size, GFP_KERNEL);
+       if (!dev->interrupt_in_buffer) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+               goto error;
+       }
+
+       /* debug code prime the buffer */
+       memset(dev->interrupt_in_buffer, 'i', in_end_size);
+
+       dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->interrupt_in_urb) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
+               goto error;
+       }
+       dev->interrupt_out_buffer = kmalloc(out_end_size, GFP_KERNEL);
+       if (!dev->interrupt_out_buffer) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+               goto error;
+       }
+       dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->interrupt_out_urb) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_out_urb\n");
+               goto error;
+       }
+
+       if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number,
+                       sizeof(dev->serial_number))) {
+               dev_err(&interface->dev, "Could not retrieve serial number\n");
+               goto error;
+       }
+       dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number);
+
+       /* we can register the device now, as it is ready */
+       usb_set_intfdata(interface, dev);
+
+       retval = usb_register_dev(interface, &adu_class);
+
+       if (retval) {
+               /* something prevented us from registering this driver */
+               dev_err(&interface->dev, "Not able to get a minor for this device.\n");
+               usb_set_intfdata(interface, NULL);
+               goto error;
+       }
+
+       dev->minor = interface->minor;
+
+       /* let the user know what node this device is now attached to */
+       dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d",
+                udev->descriptor.idProduct, dev->serial_number,
+                (dev->minor - ADU_MINOR_BASE));
+exit:
+       dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev);
+
+       return retval;
+
+error:
+       adu_delete(dev);
+       return retval;
+}
+
+/**
+ * adu_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ */
+static void adu_disconnect(struct usb_interface *interface)
+{
+       struct adu_device *dev;
+       int minor;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       mutex_lock(&disconnect_mutex); /* not interruptible */
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       down(&dev->sem); /* not interruptible */
+
+       minor = dev->minor;
+
+       /* give back our minor */
+       usb_deregister_dev(interface, &adu_class);
+       dev->minor = 0;
+
+       /* if the device is not opened, then we clean up right now */
+       dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+       if (!dev->open_count) {
+               up(&dev->sem);
+               adu_delete(dev);
+       } else {
+               dev->udev = NULL;
+               up(&dev->sem);
+       }
+
+       mutex_unlock(&disconnect_mutex);
+
+       dev_info(&interface->dev, "ADU device adutux%d now disconnected",
+                (minor - ADU_MINOR_BASE));
+
+       dbg(2," %s : leave", __FUNCTION__);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver adu_driver = {
+       .name = "adutux",
+       .probe = adu_probe,
+       .disconnect = adu_disconnect,
+       .id_table = device_table,
+};
+
+static int __init adu_init(void)
+{
+       int result;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&adu_driver);
+       if (result < 0) {
+               err("usb_register failed for the "__FILE__" driver. "
+                   "Error number %d", result);
+               goto exit;
+       }
+
+       info("adutux " DRIVER_DESC " " DRIVER_VERSION);
+       info("adutux is an experimental driver. Use at your own risk");
+
+exit:
+       dbg(2," %s : leave, return value %d", __FUNCTION__, result);
+
+       return result;
+}
+
+static void __exit adu_exit(void)
+{
+       dbg(2," %s : enter", __FUNCTION__);
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&adu_driver);
+       dbg(2," %s : leave", __FUNCTION__);
+}
+
+module_init(adu_init);
+module_exit(adu_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index 1fef36e71c573ed10dc05b2de5240816e87fa0c5..4fd2110b34110066606726197e966eb271b00846 100644 (file)
@@ -806,7 +806,7 @@ static void auerbuf_releasebuf( pauerbuf_t bp)
 0              Initial, OK
 -EINPROGRESS   during submission until end
 -ENOENT                if urb is unlinked
--ETIMEDOUT     Transfer timed out, NAK
+-ETIME         Device did not respond
 -ENOMEM                Memory Overflow
 -ENODEV                Specified USB-device or bus doesn't exist
 -ENXIO         URB already queued
@@ -832,7 +832,7 @@ static int auerswald_status_retry (int status)
 {
        switch (status) {
        case 0:
-       case -ETIMEDOUT:
+       case -ETIME:
        case -EOVERFLOW:
        case -EAGAIN:
        case -EPIPE:
@@ -1858,7 +1858,7 @@ static int auerchar_release (struct inode *inode, struct file *file)
 
 /*----------------------------------------------------------------------*/
 /* File operation structure                                             */
-static struct file_operations auerswald_fops =
+static const struct file_operations auerswald_fops =
 {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
index 9c46746d5d002ab0881918e39ab363f71a4fb926..b63b5f34b2aa5f0f79b7103c9e14ce9e89f2b2a7 100644 (file)
@@ -209,7 +209,7 @@ static int cypress_probe(struct usb_interface *interface,
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                dev_err(&interface->dev, "Out of memory!\n");
-               goto error;
+               goto error_mem;
        }
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
@@ -218,15 +218,26 @@ static int cypress_probe(struct usb_interface *interface,
        usb_set_intfdata(interface, dev);
 
        /* create device attribute files */
-       device_create_file(&interface->dev, &dev_attr_port0);
-       device_create_file(&interface->dev, &dev_attr_port1);
+       retval = device_create_file(&interface->dev, &dev_attr_port0);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_port1);
+       if (retval)
+               goto error;
 
        /* let the user know that the device is now attached */
        dev_info(&interface->dev,
                 "Cypress CY7C63xxx device now attached\n");
+       return 0;
 
-       retval = 0;
 error:
+       device_remove_file(&interface->dev, &dev_attr_port0);
+       device_remove_file(&interface->dev, &dev_attr_port1);
+       usb_set_intfdata(interface, NULL);
+       usb_put_dev(dev->udev);
+       kfree(dev);
+
+error_mem:
        return retval;
 }
 
index b20bec445552007b23d0008bc6998a3f717244af..04e87acd6e46007cec2449ffe34c58257d55c6a8 100644 (file)
@@ -353,7 +353,7 @@ static int cytherm_probe(struct usb_interface *interface,
        dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL);
        if (dev == NULL) {
                dev_err (&interface->dev, "Out of memory\n");
-               goto error;
+               goto error_mem;
        }
 
        dev->udev = usb_get_dev(udev);
@@ -362,18 +362,35 @@ static int cytherm_probe(struct usb_interface *interface,
 
        dev->brightness = 0xFF;
 
-       device_create_file(&interface->dev, &dev_attr_brightness);   
-       device_create_file(&interface->dev, &dev_attr_temp);
-       device_create_file(&interface->dev, &dev_attr_button);
-       device_create_file(&interface->dev, &dev_attr_port0);
-       device_create_file(&interface->dev, &dev_attr_port1);
+       retval = device_create_file(&interface->dev, &dev_attr_brightness);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_temp);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_button);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_port0);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_port1);
+       if (retval)
+               goto error;
 
-       dev_info (&interface->dev, 
+       dev_info (&interface->dev,
                  "Cypress thermometer device now attached\n");
        return 0;
-
- error:
+error:
+       device_remove_file(&interface->dev, &dev_attr_brightness);
+       device_remove_file(&interface->dev, &dev_attr_temp);
+       device_remove_file(&interface->dev, &dev_attr_button);
+       device_remove_file(&interface->dev, &dev_attr_port0);
+       device_remove_file(&interface->dev, &dev_attr_port1);
+       usb_set_intfdata (interface, NULL);
+       usb_put_dev(dev->udev);
        kfree(dev);
+error_mem:
        return retval;
 }
 
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
new file mode 100644 (file)
index 0000000..b88a094
--- /dev/null
@@ -0,0 +1,2809 @@
+/*
+* USB FTDI client driver for Elan Digital Systems's Uxxx adapters
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+* http://www.elandigitalsystems.com
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+* tony.olech@elandigitalsystems.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, version 2.
+*
+*
+* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB client drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+MODULE_AUTHOR("Tony Olech");
+MODULE_DESCRIPTION("FTDI ELAN driver");
+MODULE_LICENSE("GPL");
+#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+extern struct platform_driver u132_platform_driver;
+static struct workqueue_struct *status_queue;
+static struct workqueue_struct *command_queue;
+static struct workqueue_struct *respond_queue;
+/*
+* ftdi_module_lock exists to protect access to global variables
+*
+*/
+static struct semaphore ftdi_module_lock;
+static int ftdi_instances = 0;
+static struct list_head ftdi_static_list;
+/*
+* end of the global variables protected by ftdi_module_lock
+*/
+#include "usb_u132.h"
+#define TD_DEVNOTRESP 5
+/* Define these values to match your devices*/
+#define USB_FTDI_ELAN_VENDOR_ID 0x0403
+#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
+/* table of devices that work with this driver*/
+static struct usb_device_id ftdi_elan_table[] = {
+        {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)},
+        { /* Terminating entry */ }
+};
+
+MODULE_DEVICE_TABLE(usb, ftdi_elan_table);
+/* only the jtag(firmware upgrade device) interface requires
+* a device file and corresponding minor number, but the
+* interface is created unconditionally - I suppose it could
+* be configured or not according to a module parameter.
+* But since we(now) require one interface per device,
+* and since it unlikely that a normal installation would
+* require more than a couple of elan-ftdi devices, 8 seems
+* like a reasonable limit to have here, and if someone
+* really requires more than 8 devices, then they can frig the
+* code and recompile
+*/
+#define USB_FTDI_ELAN_MINOR_BASE 192
+#define COMMAND_BITS 5
+#define COMMAND_SIZE (1<<COMMAND_BITS)
+#define COMMAND_MASK (COMMAND_SIZE-1)
+struct u132_command {
+        u8 header;
+        u16 length;
+        u8 address;
+        u8 width;
+        u32 value;
+        int follows;
+        void *buffer;
+};
+#define RESPOND_BITS 5
+#define RESPOND_SIZE (1<<RESPOND_BITS)
+#define RESPOND_MASK (RESPOND_SIZE-1)
+struct u132_respond {
+        u8 header;
+        u8 address;
+        u32 *value;
+        int *result;
+        struct completion wait_completion;
+};
+struct u132_target {
+        void *endp;
+        struct urb *urb;
+        int toggle_bits;
+        int error_count;
+        int condition_code;
+        int repeat_number;
+        int halted;
+        int skipped;
+        int actual;
+        int non_null;
+        int active;
+        int abandoning;
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+                int toggle_bits, int error_count, int condition_code,
+                int repeat_number, int halted, int skipped, int actual,
+                int non_null);
+};
+/* Structure to hold all of our device specific stuff*/
+struct usb_ftdi {
+        struct list_head ftdi_list;
+        struct semaphore u132_lock;
+        int command_next;
+        int command_head;
+        struct u132_command command[COMMAND_SIZE];
+        int respond_next;
+        int respond_head;
+        struct u132_respond respond[RESPOND_SIZE];
+        struct u132_target target[4];
+        char device_name[16];
+        unsigned synchronized:1;
+        unsigned enumerated:1;
+        unsigned registered:1;
+        unsigned initialized:1;
+        unsigned card_ejected:1;
+        int function;
+        int sequence_num;
+        int disconnected;
+        int gone_away;
+        int stuck_status;
+        int status_queue_delay;
+        struct semaphore sw_lock;
+        struct usb_device *udev;
+        struct usb_interface *interface;
+        struct usb_class_driver *class;
+        struct work_struct status_work;
+        struct work_struct command_work;
+        struct work_struct respond_work;
+        struct u132_platform_data platform_data;
+        struct resource resources[0];
+        struct platform_device platform_dev;
+        unsigned char *bulk_in_buffer;
+        size_t bulk_in_size;
+        size_t bulk_in_last;
+        size_t bulk_in_left;
+        __u8 bulk_in_endpointAddr;
+        __u8 bulk_out_endpointAddr;
+        struct kref kref;
+        u32 controlreg;
+        u8 response[4 + 1024];
+        int expected;
+        int recieved;
+        int ed_found;
+};
+#define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref)
+#define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \
+        platform_dev)
+static struct usb_driver ftdi_elan_driver;
+static void ftdi_elan_delete(struct kref *kref)
+{
+        struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref);
+        dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi);
+        usb_put_dev(ftdi->udev);
+        ftdi->disconnected += 1;
+        down(&ftdi_module_lock);
+        list_del_init(&ftdi->ftdi_list);
+        ftdi_instances -= 1;
+        up(&ftdi_module_lock);
+        kfree(ftdi->bulk_in_buffer);
+        ftdi->bulk_in_buffer = NULL;
+}
+
+static void ftdi_elan_put_kref(struct usb_ftdi *ftdi)
+{
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_elan_get_kref(struct usb_ftdi *ftdi)
+{
+        kref_get(&ftdi->kref);
+}
+
+static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
+{
+        kref_init(&ftdi->kref);
+}
+
+static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+                        return;
+        } else if (queue_work(status_queue, &ftdi->status_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(status_queue, &ftdi->status_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->status_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(command_queue, &ftdi->command_work,
+                        delta))
+                        return;
+        } else if (queue_work(command_queue, &ftdi->command_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(command_queue, &ftdi->command_work,
+                        delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(command_queue, &ftdi->command_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->command_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_response_requeue_work(struct usb_ftdi *ftdi,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(respond_queue, &ftdi->respond_work,
+                        delta))
+                        return;
+        } else if (queue_work(respond_queue, &ftdi->respond_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(respond_queue, &ftdi->respond_work,
+                        delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(respond_queue, &ftdi->respond_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->respond_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+void ftdi_elan_gone_away(struct platform_device *pdev)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        ftdi->gone_away += 1;
+        ftdi_elan_put_kref(ftdi);
+}
+
+
+EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
+void ftdi_release_platform_dev(struct device *dev)
+{
+        dev->parent = NULL;
+}
+
+static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
+        struct u132_target *target, u8 *buffer, int length);
+static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi);
+static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi);
+static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_synchronize(struct usb_ftdi *ftdi);
+static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi);
+static int ftdi_elan_command_engine(struct usb_ftdi *ftdi);
+static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi);
+static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi)
+{
+        int result;
+        if (ftdi->platform_dev.dev.parent)
+                return -EBUSY;
+        ftdi_elan_get_kref(ftdi);
+        ftdi->platform_data.potpg = 100;
+        ftdi->platform_data.reset = NULL;
+        ftdi->platform_dev.id = ftdi->sequence_num;
+        ftdi->platform_dev.resource = ftdi->resources;
+        ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources);
+        ftdi->platform_dev.dev.platform_data = &ftdi->platform_data;
+        ftdi->platform_dev.dev.parent = NULL;
+        ftdi->platform_dev.dev.release = ftdi_release_platform_dev;
+        ftdi->platform_dev.dev.dma_mask = NULL;
+        snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd");
+        ftdi->platform_dev.name = ftdi->device_name;
+        dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd");
+        request_module("u132_hcd");
+        dev_info(&ftdi->udev->dev, "registering '%s'\n",
+                ftdi->platform_dev.name);
+        result = platform_device_register(&ftdi->platform_dev);
+        return result;
+}
+
+static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
+{
+        down(&ftdi->u132_lock);
+        while (ftdi->respond_next > ftdi->respond_head) {
+                struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &
+                        ftdi->respond_head++];
+                *respond->result = -ESHUTDOWN;
+                *respond->value = 0;
+                complete(&respond->wait_completion);
+        } up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                if (target->active == 1) {
+                        target->condition_code = TD_DEVNOTRESP;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, NULL, 0);
+                        down(&ftdi->u132_lock);
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                target->abandoning = 1;
+              wait_1:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x80 | (ed_number << 5) | 0x4;
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait_1;
+                        }
+                }
+              wait_2:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x90 | (ed_number << 5);
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait_2;
+                        }
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                target->abandoning = 1;
+              wait:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x80 | (ed_number << 5) | 0x4;
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait;
+                        }
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
+{
+        ftdi_command_queue_work(ftdi, 0);
+        return;
+}
+
+static void ftdi_elan_command_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                int retval = ftdi_elan_command_engine(ftdi);
+                if (retval == -ESHUTDOWN) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval)
+                        dev_err(&ftdi->udev->dev, "command error %d\n", retval);
+                ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10));
+                return;
+        }
+}
+
+static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
+{
+        ftdi_respond_queue_work(ftdi, 0);
+        return;
+}
+
+static void ftdi_elan_respond_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                int retval = ftdi_elan_respond_engine(ftdi);
+                if (retval == 0) {
+                } else if (retval == -ESHUTDOWN) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -EILSEQ) {
+                        ftdi->disconnected += 1;
+                } else {
+                        ftdi->disconnected += 1;
+                        dev_err(&ftdi->udev->dev, "respond error %d\n", retval);
+                }
+                if (ftdi->disconnected > 0) {
+                        ftdi_elan_abandon_completions(ftdi);
+                        ftdi_elan_abandon_targets(ftdi);
+                }
+                ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10));
+                return;
+        }
+}
+
+
+/*
+* the sw_lock is initially held and will be freed
+* after the FTDI has been synchronized
+*
+*/
+static void ftdi_elan_status_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        int work_delay_in_msec = 0;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else if (ftdi->synchronized == 0) {
+                down(&ftdi->sw_lock);
+                if (ftdi_elan_synchronize(ftdi) == 0) {
+                        ftdi->synchronized = 1;
+                        ftdi_command_queue_work(ftdi, 1);
+                        ftdi_respond_queue_work(ftdi, 1);
+                        up(&ftdi->sw_lock);
+                        work_delay_in_msec = 100;
+                } else {
+                        dev_err(&ftdi->udev->dev, "synchronize failed\n");
+                        up(&ftdi->sw_lock);
+                        work_delay_in_msec = 10 *1000;
+                }
+        } else if (ftdi->stuck_status > 0) {
+                if (ftdi_elan_stuck_waiting(ftdi) == 0) {
+                        ftdi->stuck_status = 0;
+                        ftdi->synchronized = 0;
+                } else if ((ftdi->stuck_status++ % 60) == 1) {
+                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "
+                                "- please remove\n");
+                } else
+                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "
+                                "- checked %d times\n", ftdi->stuck_status);
+                work_delay_in_msec = 100;
+        } else if (ftdi->enumerated == 0) {
+                if (ftdi_elan_enumeratePCI(ftdi) == 0) {
+                        ftdi->enumerated = 1;
+                        work_delay_in_msec = 250;
+                } else
+                        work_delay_in_msec = 1000;
+        } else if (ftdi->initialized == 0) {
+                if (ftdi_elan_setupOHCI(ftdi) == 0) {
+                        ftdi->initialized = 1;
+                        work_delay_in_msec = 500;
+                } else {
+                        dev_err(&ftdi->udev->dev, "initialized failed - trying "
+                                "again in 10 seconds\n");
+                        work_delay_in_msec = 10 *1000;
+                }
+        } else if (ftdi->registered == 0) {
+                work_delay_in_msec = 10;
+                if (ftdi_elan_hcd_init(ftdi) == 0) {
+                        ftdi->registered = 1;
+                } else
+                        dev_err(&ftdi->udev->dev, "register failed\n");
+                work_delay_in_msec = 250;
+        } else {
+                if (ftdi_elan_checkingPCI(ftdi) == 0) {
+                        work_delay_in_msec = 250;
+                } else if (ftdi->controlreg & 0x00400000) {
+                        if (ftdi->gone_away > 0) {
+                                dev_err(&ftdi->udev->dev, "PCI device eject con"
+                                        "firmed platform_dev.dev.parent=%p plat"
+                                        "form_dev.dev=%p\n",
+                                        ftdi->platform_dev.dev.parent,
+                                        &ftdi->platform_dev.dev);
+                                platform_device_unregister(&ftdi->platform_dev);
+                                ftdi->platform_dev.dev.parent = NULL;
+                                ftdi->registered = 0;
+                                ftdi->enumerated = 0;
+                                ftdi->card_ejected = 0;
+                                ftdi->initialized = 0;
+                                ftdi->gone_away = 0;
+                        } else
+                                ftdi_elan_flush_targets(ftdi);
+                        work_delay_in_msec = 250;
+                } else {
+                        dev_err(&ftdi->udev->dev, "PCI device has disappeared\n"
+                                );
+                        ftdi_elan_cancel_targets(ftdi);
+                        work_delay_in_msec = 500;
+                        ftdi->enumerated = 0;
+                        ftdi->initialized = 0;
+                }
+        }
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                ftdi_status_requeue_work(ftdi,
+                        msecs_to_jiffies(work_delay_in_msec));
+                return;
+        }
+}
+
+
+/*
+* file_operations for the jtag interface
+*
+* the usage count for the device is incremented on open()
+* and decremented on release()
+*/
+static int ftdi_elan_open(struct inode *inode, struct file *file)
+{
+        int subminor = iminor(inode);
+        struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver,
+                subminor);
+        if (!interface) {
+                printk(KERN_ERR "can't find device for minor %d\n", subminor);
+                return -ENODEV;
+        } else {
+                struct usb_ftdi *ftdi = usb_get_intfdata(interface);
+                if (!ftdi) {
+                        return -ENODEV;
+                } else {
+                        if (down_interruptible(&ftdi->sw_lock)) {
+                                return -EINTR;
+                        } else {
+                                ftdi_elan_get_kref(ftdi);
+                                file->private_data = ftdi;
+                                return 0;
+                        }
+                }
+        }
+}
+
+static int ftdi_elan_release(struct inode *inode, struct file *file)
+{
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi == NULL)
+                return -ENODEV;
+        up(&ftdi->sw_lock);        /* decrement the count on our device */
+        ftdi_elan_put_kref(ftdi);
+        return 0;
+}
+
+
+#define FTDI_ELAN_IOC_MAGIC 0xA1
+#define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132)
+static int ftdi_elan_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+        switch (cmd) {
+        case FTDI_ELAN_IOCDEBUG:{
+                        char line[132];
+                        int size = strncpy_from_user(line,
+                                (const char __user *)arg, sizeof(line));
+                        if (size < 0) {
+                                return -EINVAL;
+                        } else {
+                                printk(KERN_ERR "TODO: ioctl %s\n", line);
+                                return 0;
+                        }
+                }
+        default:
+                return -EFAULT;
+        }
+}
+
+
+/*
+*
+* blocking bulk reads are used to get data from the device
+*
+*/
+static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
+                             size_t count, loff_t *ppos)
+{
+        char data[30 *3 + 4];
+        char *d = data;
+        int m = (sizeof(data) - 1) / 3;
+        int bytes_read = 0;
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        }
+        data[0] = 0;
+      have:if (ftdi->bulk_in_left > 0) {
+                if (count-- > 0) {
+                        char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer;
+                        ftdi->bulk_in_left -= 1;
+                        if (bytes_read < m) {
+                                d += sprintf(d, " %02X", 0x000000FF & *p);
+                        } else if (bytes_read > m) {
+                        } else
+                                d += sprintf(d, " ..");
+                        if (copy_to_user(buffer++, p, 1)) {
+                                return -EFAULT;
+                        } else {
+                                bytes_read += 1;
+                                goto have;
+                        }
+                } else
+                        return bytes_read;
+        }
+      more:if (count > 0) {
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(50));
+                if (packet_bytes > 2) {
+                        ftdi->bulk_in_left = packet_bytes - 2;
+                        ftdi->bulk_in_last = 1;
+                        goto have;
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else if (bytes_read > 0) {
+                                return bytes_read;
+                        } else
+                                return retval;
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return bytes_read;
+                } else
+                        return retval;
+        } else
+                return bytes_read;
+}
+
+static void ftdi_elan_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
+        if (urb->status && !(urb->status == -ENOENT || urb->status ==
+                -ECONNRESET || urb->status == -ESHUTDOWN)) {
+                dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %"
+                        "d\n", urb, urb->status);
+        }
+        usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                urb->transfer_buffer, urb->transfer_dma);
+}
+
+static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi,
+        char *buf, int command_size, int total_size)
+{
+        int ed_commands = 0;
+        int b = 0;
+        int I = command_size;
+        int i = ftdi->command_head;
+        while (I-- > 0) {
+                struct u132_command *command = &ftdi->command[COMMAND_MASK &
+                        i++];
+                int F = command->follows;
+                u8 *f = command->buffer;
+                if (command->header & 0x80) {
+                        ed_commands |= 1 << (0x3 & (command->header >> 5));
+                }
+                buf[b++] = command->header;
+                buf[b++] = (command->length >> 0) & 0x00FF;
+                buf[b++] = (command->length >> 8) & 0x00FF;
+                buf[b++] = command->address;
+                buf[b++] = command->width;
+                while (F-- > 0) {
+                        buf[b++] = *f++;
+                }
+        }
+        return ed_commands;
+}
+
+static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size)
+{
+        int total_size = 0;
+        int I = command_size;
+        int i = ftdi->command_head;
+        while (I-- > 0) {
+                struct u132_command *command = &ftdi->command[COMMAND_MASK &
+                        i++];
+                total_size += 5 + command->follows;
+        } return total_size;
+}
+
+static int ftdi_elan_command_engine(struct usb_ftdi *ftdi)
+{
+        int retval;
+        char *buf;
+        int ed_commands;
+        int total_size;
+        struct urb *urb;
+        int command_size = ftdi->command_next - ftdi->command_head;
+        if (command_size == 0)
+                return 0;
+        total_size = ftdi_elan_total_command_size(ftdi, command_size);
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not get a urb to write %d comm"
+                        "ands totaling %d bytes to the Uxxx\n", command_size,
+                        total_size);
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL,
+                &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c"
+                        "ommands totaling %d bytes to the Uxxx\n", command_size,
+                         total_size);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf,
+                command_size, total_size);
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, total_size,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        if (ed_commands) {
+                char diag[40 *3 + 4];
+                char *d = diag;
+                int m = total_size;
+                u8 *c = buf;
+                int s = (sizeof(diag) - 1) / 3;
+                diag[0] = 0;
+                while (s-- > 0 && m-- > 0) {
+                        if (s > 0 || m == 0) {
+                                d += sprintf(d, " %02X", *c++);
+                        } else
+                                d += sprintf(d, " ..");
+                }
+        }
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write "
+                        "%d commands totaling %d bytes to the Uxxx\n", retval,
+                        urb, command_size, total_size);
+                usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return retval;
+        }
+        usb_free_urb(urb);        /* release our reference to this urb,
+                the USB core will eventually free it entirely */
+        ftdi->command_head += command_size;
+        ftdi_elan_kick_respond_queue(ftdi);
+        return 0;
+}
+
+static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
+        struct u132_target *target, u8 *buffer, int length)
+{
+        struct urb *urb = target->urb;
+        int halted = target->halted;
+        int skipped = target->skipped;
+        int actual = target->actual;
+        int non_null = target->non_null;
+        int toggle_bits = target->toggle_bits;
+        int error_count = target->error_count;
+        int condition_code = target->condition_code;
+        int repeat_number = target->repeat_number;
+        void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int,
+                int, int, int, int) = target->callback;
+        target->active -= 1;
+        target->callback = NULL;
+        (*callback) (target->endp, urb, buffer, length, toggle_bits,
+                error_count, condition_code, repeat_number, halted, skipped,
+                actual, non_null);
+}
+
+static char *have_ed_set_response(struct usb_ftdi *ftdi,
+        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
+        char *b)
+{
+        int payload = (ed_length >> 0) & 0x07FF;
+        down(&ftdi->u132_lock);
+        target->actual = 0;
+        target->non_null = (ed_length >> 15) & 0x0001;
+        target->repeat_number = (ed_length >> 11) & 0x000F;
+        if (ed_type == 0x02) {
+                if (payload == 0 || target->abandoning > 0) {
+                        target->abandoning = 0;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        return ftdi->response;
+                } else {
+                        ftdi->expected = 4 + payload;
+                        ftdi->ed_found = 1;
+                        up(&ftdi->u132_lock);
+                        return b;
+                }
+        } else if (ed_type == 0x03) {
+                if (payload == 0 || target->abandoning > 0) {
+                        target->abandoning = 0;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        return ftdi->response;
+                } else {
+                        ftdi->expected = 4 + payload;
+                        ftdi->ed_found = 1;
+                        up(&ftdi->u132_lock);
+                        return b;
+                }
+        } else if (ed_type == 0x01) {
+                target->abandoning = 0;
+                up(&ftdi->u132_lock);
+                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                        payload);
+                ftdi->recieved = 0;
+                ftdi->expected = 4;
+                ftdi->ed_found = 0;
+                return ftdi->response;
+        } else {
+                target->abandoning = 0;
+                up(&ftdi->u132_lock);
+                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                        payload);
+                ftdi->recieved = 0;
+                ftdi->expected = 4;
+                ftdi->ed_found = 0;
+                return ftdi->response;
+        }
+}
+
+static char *have_ed_get_response(struct usb_ftdi *ftdi,
+        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
+        char *b)
+{
+        down(&ftdi->u132_lock);
+        target->condition_code = TD_DEVNOTRESP;
+        target->actual = (ed_length >> 0) & 0x01FF;
+        target->non_null = (ed_length >> 15) & 0x0001;
+        target->repeat_number = (ed_length >> 11) & 0x000F;
+        up(&ftdi->u132_lock);
+        if (target->active)
+                ftdi_elan_do_callback(ftdi, target, NULL, 0);
+        target->abandoning = 0;
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        return ftdi->response;
+}
+
+
+/*
+* The engine tries to empty the FTDI fifo
+*
+* all responses found in the fifo data are dispatched thus
+* the response buffer can only ever hold a maximum sized
+* response from the Uxxx.
+*
+*/
+static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
+{
+        u8 *b = ftdi->response + ftdi->recieved;
+        int bytes_read = 0;
+        int retry_on_empty = 1;
+        int retry_on_timeout = 3;
+        int empty_packets = 0;
+      read:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(500));
+                char diag[30 *3 + 4];
+                char *d = diag;
+                int m = packet_bytes;
+                u8 *c = ftdi->bulk_in_buffer;
+                int s = (sizeof(diag) - 1) / 3;
+                diag[0] = 0;
+                while (s-- > 0 && m-- > 0) {
+                        if (s > 0 || m == 0) {
+                                d += sprintf(d, " %02X", *c++);
+                        } else
+                                d += sprintf(d, " ..");
+                }
+                if (packet_bytes > 2) {
+                        ftdi->bulk_in_left = packet_bytes - 2;
+                        ftdi->bulk_in_last = 1;
+                        goto have;
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT with packe"
+                                        "t_bytes = %d with total %d bytes%s\n",
+                                        packet_bytes, bytes_read, diag);
+                                goto more;
+                        } else if (bytes_read > 0) {
+                                dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n",
+                                        bytes_read, diag);
+                                return -ENOMEM;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT with packe"
+                                        "t_bytes = %d with total %d bytes%s\n",
+                                        packet_bytes, bytes_read, diag);
+                                return -ENOMEM;
+                        }
+                } else if (retval == -EILSEQ) {
+                        dev_err(&ftdi->udev->dev, "error = %d with packet_bytes"
+                                " = %d with total %d bytes%s\n", retval,
+                                packet_bytes, bytes_read, diag);
+                        return retval;
+                } else if (retval) {
+                        dev_err(&ftdi->udev->dev, "error = %d with packet_bytes"
+                                " = %d with total %d bytes%s\n", retval,
+                                packet_bytes, bytes_read, diag);
+                        return retval;
+                } else if (packet_bytes == 2) {
+                        unsigned char s0 = ftdi->bulk_in_buffer[0];
+                        unsigned char s1 = ftdi->bulk_in_buffer[1];
+                        empty_packets += 1;
+                        if (s0 == 0x31 && s1 == 0x60) {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        } else if (s0 == 0x31 && s1 == 0x00) {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        } else {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        }
+                } else if (packet_bytes == 1) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return 0;
+                } else {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return 0;
+                }
+        }
+      more:{
+                goto read;
+        }
+      have:if (ftdi->bulk_in_left > 0) {
+                u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last];
+                bytes_read += 1;
+                ftdi->bulk_in_left -= 1;
+                if (ftdi->recieved == 0 && c == 0xFF) {
+                        goto have;
+                } else
+                        *b++ = c;
+                if (++ftdi->recieved < ftdi->expected) {
+                        goto have;
+                } else if (ftdi->ed_found) {
+                        int ed_number = (ftdi->response[0] >> 5) & 0x03;
+                        u16 ed_length = (ftdi->response[2] << 8) |
+                                ftdi->response[1];
+                        struct u132_target *target = &ftdi->target[ed_number];
+                        int payload = (ed_length >> 0) & 0x07FF;
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = payload;
+                        u8 *c = 4 + ftdi->response;
+                        int s = (sizeof(diag) - 1) / 3;
+                        diag[0] = 0;
+                        while (s-- > 0 && m-- > 0) {
+                                if (s > 0 || m == 0) {
+                                        d += sprintf(d, " %02X", *c++);
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        b = ftdi->response;
+                        goto have;
+                } else if (ftdi->expected == 8) {
+                        u8 buscmd;
+                        int respond_head = ftdi->respond_head++;
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & respond_head];
+                        u32 data = ftdi->response[7];
+                        data <<= 8;
+                        data |= ftdi->response[6];
+                        data <<= 8;
+                        data |= ftdi->response[5];
+                        data <<= 8;
+                        data |= ftdi->response[4];
+                        *respond->value = data;
+                        *respond->result = 0;
+                        complete(&respond->wait_completion);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        b = ftdi->response;
+                        buscmd = (ftdi->response[0] >> 0) & 0x0F;
+                        if (buscmd == 0x00) {
+                        } else if (buscmd == 0x02) {
+                        } else if (buscmd == 0x06) {
+                        } else if (buscmd == 0x0A) {
+                        } else
+                                dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) va"
+                                        "lue = %08X\n", buscmd, data);
+                        goto have;
+                } else {
+                        if ((ftdi->response[0] & 0x80) == 0x00) {
+                                ftdi->expected = 8;
+                                goto have;
+                        } else {
+                                int ed_number = (ftdi->response[0] >> 5) & 0x03;
+                                int ed_type = (ftdi->response[0] >> 0) & 0x03;
+                                u16 ed_length = (ftdi->response[2] << 8) |
+                                        ftdi->response[1];
+                                struct u132_target *target = &ftdi->target[
+                                        ed_number];
+                                target->halted = (ftdi->response[0] >> 3) &
+                                        0x01;
+                                target->skipped = (ftdi->response[0] >> 2) &
+                                        0x01;
+                                target->toggle_bits = (ftdi->response[3] >> 6)
+                                        & 0x03;
+                                target->error_count = (ftdi->response[3] >> 4)
+                                        & 0x03;
+                                target->condition_code = (ftdi->response[
+                                        3] >> 0) & 0x0F;
+                                if ((ftdi->response[0] & 0x10) == 0x00) {
+                                        b = have_ed_set_response(ftdi, target,
+                                                ed_length, ed_number, ed_type,
+                                                b);
+                                        goto have;
+                                } else {
+                                        b = have_ed_get_response(ftdi, target,
+                                                ed_length, ed_number, ed_type,
+                                                b);
+                                        goto have;
+                                }
+                        }
+                }
+        } else
+                goto more;
+}
+
+
+/*
+* create a urb, and a buffer for it, and copy the data to the urb
+*
+*/
+static ssize_t ftdi_elan_write(struct file *file,
+                              const char __user *user_buffer, size_t count,
+                              loff_t *ppos)
+{
+        int retval = 0;
+        struct urb *urb;
+        char *buf;
+        char data[30 *3 + 4];
+        char *d = data;
+        const char __user *s = user_buffer;
+        int m = (sizeof(data) - 1) / 3;
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        }
+        if (count == 0) {
+                goto exit;
+        }
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                retval = -ENOMEM;
+                goto error_1;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL,
+                &urb->transfer_dma);
+        if (!buf) {
+                retval = -ENOMEM;
+                goto error_2;
+        }
+        if (copy_from_user(buf, user_buffer, count)) {
+                retval = -EFAULT;
+                goto error_3;
+        }
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, count,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed submitting write urb, error %"
+                        "d\n", retval);
+                goto error_4;
+        }
+        usb_free_urb(urb);
+      exit:;
+        if (count > m) {
+                int I = m - 1;
+                while (I-- > 0) {
+                        d += sprintf(d, " %02X", 0x000000FF & *s++);
+                }
+                d += sprintf(d, " ..");
+        } else {
+                int I = count;
+                while (I-- > 0) {
+                        d += sprintf(d, " %02X", 0x000000FF & *s++);
+                }
+        }
+        return count;
+      error_4: error_3:usb_buffer_free(ftdi->udev, count, buf,
+              urb->transfer_dma);
+      error_2:usb_free_urb(urb);
+      error_1:return retval;
+}
+
+static struct file_operations ftdi_elan_fops = {
+        .owner = THIS_MODULE,
+        .llseek = no_llseek,
+        .ioctl = ftdi_elan_ioctl,
+        .read = ftdi_elan_read,
+        .write = ftdi_elan_write,
+        .open = ftdi_elan_open,
+        .release = ftdi_elan_release,
+};
+
+/*
+* usb class driver info in order to get a minor number from the usb core,
+* and to have the device registered with the driver core
+*/
+static struct usb_class_driver ftdi_elan_jtag_class = {
+        .name = "ftdi-%d-jtag",
+        .fops = &ftdi_elan_fops,
+        .minor_base = USB_FTDI_ELAN_MINOR_BASE,
+};
+
+/*
+* the following definitions are for the
+* ELAN FPGA state machgine processor that
+* lies on the other side of the FTDI chip
+*/
+#define cPCIu132rd 0x0
+#define cPCIu132wr 0x1
+#define cPCIiord 0x2
+#define cPCIiowr 0x3
+#define cPCImemrd 0x6
+#define cPCImemwr 0x7
+#define cPCIcfgrd 0xA
+#define cPCIcfgwr 0xB
+#define cPCInull 0xF
+#define cU132cmd_status 0x0
+#define cU132flash 0x1
+#define cPIDsetup 0x0
+#define cPIDout 0x1
+#define cPIDin 0x2
+#define cPIDinonce 0x3
+#define cCCnoerror 0x0
+#define cCCcrc 0x1
+#define cCCbitstuff 0x2
+#define cCCtoggle 0x3
+#define cCCstall 0x4
+#define cCCnoresp 0x5
+#define cCCbadpid1 0x6
+#define cCCbadpid2 0x7
+#define cCCdataoverrun 0x8
+#define cCCdataunderrun 0x9
+#define cCCbuffoverrun 0xC
+#define cCCbuffunderrun 0xD
+#define cCCnotaccessed 0xF
+static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
+{
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | cPCIu132wr;
+                        command->length = 0x04;
+                        command->address = 0x00;
+                        command->width = 0x00;
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
+        u8 width, u32 data)
+{
+        u8 addressofs = config_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | (cPCIcfgwr & 0x0F);
+                        command->length = 0x04;
+                        command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
+        u8 width, u32 data)
+{
+        u8 addressofs = mem_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | (cPCImemwr & 0x0F);
+                        command->length = 0x04;
+                        command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
+        u8 width, u32 data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem);
+static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
+{
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | cPCIu132rd;
+                        command->length = 0x04;
+                        respond->address = command->address = cU132cmd_status;
+                        command->width = 0x00;
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_read_reg(ftdi, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
+static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
+        u8 width, u32 *data)
+{
+        u8 addressofs = config_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | (cPCIcfgrd &
+                                0x0F);
+                        command->length = 0x04;
+                        respond->address = command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
+        u8 width, u32 *data)
+{
+        u8 addressofs = mem_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | (cPCImemrd &
+                                0x0F);
+                        command->length = 0x04;
+                        respond->address = command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
+        u8 width, u32 *data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else
+                return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem);
+static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x80 | (ed << 5);
+                        command->length = 0x8007;
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 8;
+                        command->value = 0;
+                        command->buffer = urb->setup_packet;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup);
+static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        int remaining_length = urb->transfer_buffer_length -
+                                urb->actual_length;
+                        command->header = 0x82 | (ed << 5);
+                        if (remaining_length == 0) {
+                                command->length = 0x0000;
+                        } else if (remaining_length > 1024) {
+                                command->length = 0x8000 | 1023;
+                        } else
+                                command->length = 0x8000 | (remaining_length -
+                                        1);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input);
+static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x81 | (ed << 5);
+                        command->length = 0x0000;
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty);
+static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        u8 *b;
+                        u16 urb_size;
+                        int i = 0;
+                        char data[30 *3 + 4];
+                        char *d = data;
+                        int m = (sizeof(data) - 1) / 3;
+                        int l = 0;
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x81 | (ed << 5);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = min(1024,
+                                urb->transfer_buffer_length -
+                                urb->actual_length);
+                        command->value = 0;
+                        command->buffer = urb->transfer_buffer +
+                                urb->actual_length;
+                        command->length = 0x8000 | (command->follows - 1);
+                        b = command->buffer;
+                        urb_size = command->follows;
+                        data[0] = 0;
+                        while (urb_size-- > 0) {
+                                if (i > m) {
+                                } else if (i++ < m) {
+                                        int w = sprintf(d, " %02X", *b++);
+                                        d += w;
+                                        l += w;
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output);
+static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        int remaining_length = urb->transfer_buffer_length -
+                                urb->actual_length;
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x83 | (ed << 5);
+                        if (remaining_length == 0) {
+                                command->length = 0x0000;
+                        } else if (remaining_length > 1024) {
+                                command->length = 0x8000 | 1023;
+                        } else
+                                command->length = 0x8000 | (remaining_length -
+                                        1);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single);
+static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp)
+{
+        u8 ed = ed_number - 1;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                struct u132_target *target = &ftdi->target[ed];
+                down(&ftdi->u132_lock);
+                if (target->abandoning > 0) {
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        target->abandoning = 1;
+                      wait_1:if (target->active == 1) {
+                                int command_size = ftdi->command_next -
+                                        ftdi->command_head;
+                                if (command_size < COMMAND_SIZE) {
+                                        struct u132_command *command =
+                                                &ftdi->command[COMMAND_MASK &
+                                                ftdi->command_next];
+                                        command->header = 0x80 | (ed << 5) |
+                                                0x4;
+                                        command->length = 0x00;
+                                        command->address = 0x00;
+                                        command->width = 0x00;
+                                        command->follows = 0;
+                                        command->value = 0;
+                                        command->buffer = &command->value;
+                                        ftdi->command_next += 1;
+                                        ftdi_elan_kick_command_queue(ftdi);
+                                } else {
+                                        up(&ftdi->u132_lock);
+                                        msleep(100);
+                                        down(&ftdi->u132_lock);
+                                        goto wait_1;
+                                }
+                        }
+                        up(&ftdi->u132_lock);
+                        return 0;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
+        void *endp)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_flush(ftdi, ed_number, endp);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush);
+static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi)
+{
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        int retry_on_status = 20;
+      more:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(100));
+                if (packet_bytes > 2) {
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = (sizeof(diag) - 1) / 3;
+                        char *b = ftdi->bulk_in_buffer;
+                        int bytes_read = 0;
+                        diag[0] = 0;
+                        while (packet_bytes-- > 0) {
+                                char c = *b++;
+                                if (bytes_read < m) {
+                                        d += sprintf(d, " %02X",
+                                                0x000000FF & c);
+                                } else if (bytes_read > m) {
+                                } else
+                                        d += sprintf(d, " ..");
+                                bytes_read += 1;
+                                continue;
+                        }
+                        goto more;
+                } else if (packet_bytes > 1) {
+                        char s1 = ftdi->bulk_in_buffer[0];
+                        char s2 = ftdi->bulk_in_buffer[1];
+                        if (s1 == 0x31 && s2 == 0x60) {
+                                return 0;
+                        } else if (retry_on_status-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (packet_bytes > 0) {
+                        char b1 = ftdi->bulk_in_buffer[0];
+                        dev_err(&ftdi->udev->dev, "only one byte flushed from F"
+                                "TDI = %02X\n", b1);
+                        if (retry_on_status-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT retry limi"
+                                        "t reached\n");
+                                return -ENOMEM;
+                        }
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "empty packet retry l"
+                                        "imit reached\n");
+                                return -ENOMEM;
+                        }
+                } else {
+                        dev_err(&ftdi->udev->dev, "error = %d\n", retval);
+                        return retval;
+                }
+        }
+        return -1;
+}
+
+
+/*
+* send the long flush sequence
+*
+*/
+static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi)
+{
+        int retval;
+        struct urb *urb;
+        char *buf;
+        int I = 257;
+        int i = 0;
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not alloc a urb for flush sequ"
+                        "ence\n");
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer for flush seq"
+                        "uence\n");
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        while (I-- > 0)
+                buf[i++] = 0x55;
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, i,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed to submit urb containing the "
+                        "flush sequence\n");
+                usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        usb_free_urb(urb);
+        return 0;
+}
+
+
+/*
+* send the reset sequence
+*
+*/
+static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi)
+{
+        int retval;
+        struct urb *urb;
+        char *buf;
+        int I = 4;
+        int i = 0;
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not get a urb for the reset se"
+                        "quence\n");
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer for the reset"
+                        " sequence\n");
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        buf[i++] = 0x55;
+        buf[i++] = 0xAA;
+        buf[i++] = 0x5A;
+        buf[i++] = 0xA5;
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, i,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed to submit urb containing the "
+                        "reset sequence\n");
+                usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        usb_free_urb(urb);
+        return 0;
+}
+
+static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
+{
+        int retval;
+        int long_stop = 10;
+        int retry_on_timeout = 5;
+        int retry_on_empty = 10;
+        int err_count = 0;
+        retval = ftdi_elan_flush_input_fifo(ftdi);
+        if (retval)
+                return retval;
+        ftdi->bulk_in_left = 0;
+        ftdi->bulk_in_last = -1;
+        while (long_stop-- > 0) {
+                int read_stop;
+                int read_stuck;
+                retval = ftdi_elan_synchronize_flush(ftdi);
+                if (retval)
+                        return retval;
+                retval = ftdi_elan_flush_input_fifo(ftdi);
+                if (retval)
+                        return retval;
+              reset:retval = ftdi_elan_synchronize_reset(ftdi);
+                if (retval)
+                        return retval;
+                read_stop = 100;
+                read_stuck = 10;
+              read:{
+                        int packet_bytes = 0;
+                        retval = usb_bulk_msg(ftdi->udev,
+                                usb_rcvbulkpipe(ftdi->udev,
+                                ftdi->bulk_in_endpointAddr),
+                                ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                                &packet_bytes, msecs_to_jiffies(500));
+                        if (packet_bytes > 2) {
+                                char diag[30 *3 + 4];
+                                char *d = diag;
+                                int m = (sizeof(diag) - 1) / 3;
+                                char *b = ftdi->bulk_in_buffer;
+                                int bytes_read = 0;
+                                unsigned char c = 0;
+                                diag[0] = 0;
+                                while (packet_bytes-- > 0) {
+                                        c = *b++;
+                                        if (bytes_read < m) {
+                                                d += sprintf(d, " %02X", c);
+                                        } else if (bytes_read > m) {
+                                        } else
+                                                d += sprintf(d, " ..");
+                                        bytes_read += 1;
+                                        continue;
+                                }
+                                if (c == 0x7E) {
+                                        return 0;
+                                } else {
+                                        if (c == 0x55) {
+                                                goto read;
+                                        } else if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                }
+                        } else if (packet_bytes > 1) {
+                                unsigned char s1 = ftdi->bulk_in_buffer[0];
+                                unsigned char s2 = ftdi->bulk_in_buffer[1];
+                                if (s1 == 0x31 && s2 == 0x00) {
+                                        if (read_stuck-- > 0) {
+                                                goto read;
+                                        } else
+                                                goto reset;
+                                } else if (s1 == 0x31 && s2 == 0x60) {
+                                        if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                } else {
+                                        if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                }
+                        } else if (packet_bytes > 0) {
+                                if (read_stop-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "retry limit "
+                                                "reached\n");
+                                        continue;
+                                }
+                        } else if (retval == -ETIMEDOUT) {
+                                if (retry_on_timeout-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "TIMED OUT re"
+                                                "try limit reached\n");
+                                        continue;
+                                }
+                        } else if (retval == 0) {
+                                if (retry_on_empty-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "empty packet"
+                                                " retry limit reached\n");
+                                        continue;
+                                }
+                        } else {
+                                err_count += 1;
+                                dev_err(&ftdi->udev->dev, "error = %d\n",
+                                        retval);
+                                if (read_stop-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "retry limit "
+                                                "reached\n");
+                                        continue;
+                                }
+                        }
+                }
+        }
+        dev_err(&ftdi->udev->dev, "failed to synchronize\n");
+        return -EFAULT;
+}
+
+static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi)
+{
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        int retry_on_status = 50;
+      more:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(1000));
+                if (packet_bytes > 2) {
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = (sizeof(diag) - 1) / 3;
+                        char *b = ftdi->bulk_in_buffer;
+                        int bytes_read = 0;
+                        diag[0] = 0;
+                        while (packet_bytes-- > 0) {
+                                char c = *b++;
+                                if (bytes_read < m) {
+                                        d += sprintf(d, " %02X",
+                                                0x000000FF & c);
+                                } else if (bytes_read > m) {
+                                } else
+                                        d += sprintf(d, " ..");
+                                bytes_read += 1;
+                                continue;
+                        }
+                        goto more;
+                } else if (packet_bytes > 1) {
+                        char s1 = ftdi->bulk_in_buffer[0];
+                        char s2 = ftdi->bulk_in_buffer[1];
+                        if (s1 == 0x31 && s2 == 0x60) {
+                                return 0;
+                        } else if (retry_on_status-- > 0) {
+                                msleep(5);
+                                goto more;
+                        } else
+                                return -EFAULT;
+                } else if (packet_bytes > 0) {
+                        char b1 = ftdi->bulk_in_buffer[0];
+                        dev_err(&ftdi->udev->dev, "only one byte flushed from F"
+                                "TDI = %02X\n", b1);
+                        if (retry_on_status-- > 0) {
+                                msleep(5);
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT retry limi"
+                                        "t reached\n");
+                                return -ENOMEM;
+                        }
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "empty packet retry l"
+                                        "imit reached\n");
+                                return -ENOMEM;
+                        }
+                } else {
+                        dev_err(&ftdi->udev->dev, "error = %d\n", retval);
+                        return -ENOMEM;
+                }
+        }
+        return -1;
+}
+
+static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
+{
+        int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        if (ftdi->controlreg & 0x00400000) {
+                if (ftdi->card_ejected) {
+                } else {
+                        ftdi->card_ejected = 1;
+                        dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = "
+                                "%08X\n", ftdi->controlreg);
+                }
+                return -ENODEV;
+        } else {
+                u8 fn = ftdi->function - 1;
+                int activePCIfn = fn << 8;
+                u32 pcidata;
+                u32 pciVID;
+                u32 pciPID;
+                int reg = 0;
+                UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                        &pcidata);
+                if (UxxxStatus)
+                        return UxxxStatus;
+                pciVID = pcidata & 0xFFFF;
+                pciPID = (pcidata >> 16) & 0xFFFF;
+                if (pciVID == ftdi->platform_data.vendor && pciPID ==
+                        ftdi->platform_data.device) {
+                        return 0;
+                } else {
+                        dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X devi"
+                                "ce=%04X pciPID=%04X\n",
+                                ftdi->platform_data.vendor, pciVID,
+                                ftdi->platform_data.device, pciPID);
+                        return -ENODEV;
+                }
+        }
+}
+
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+{
+        u32 latence_timer;
+        u32 controlreg;
+        int UxxxStatus;
+        u32 pcidata;
+        int reg = 0;
+        int foundOHCI = 0;
+        u8 fn;
+        int activePCIfn = 0;
+        u32 pciVID = 0;
+        u32 pciPID = 0;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(750);
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(250);
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(1000);
+        for (fn = 0; (fn < 4) && (!foundOHCI); fn++) {
+                activePCIfn = fn << 8;
+                ftdi->function = fn + 1;
+                UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                        &pcidata);
+                if (UxxxStatus)
+                        return UxxxStatus;
+                pciVID = pcidata & 0xFFFF;
+                pciPID = (pcidata >> 16) & 0xFFFF;
+                if ((pciVID == 0x1045) && (pciPID == 0xc861)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) {
+                }
+        }
+        if (foundOHCI == 0) {
+                return -ENXIO;
+        }
+        ftdi->platform_data.vendor = pciVID;
+        ftdi->platform_data.device = pciPID;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 16;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+                0xFFFFFFFF);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+                0xF0000000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 12;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &latence_timer);
+        if (UxxxStatus)
+                return UxxxStatus;
+        latence_timer &= 0xFFFF00FF;
+        latence_timer |= 0x00001600;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+                latence_timer);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 4;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+                0x06);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        return 0;
+}
+
+static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
+{
+        u32 pcidata;
+        int U132Status;
+        int reg;
+        int reset_repeat = 0;
+      do_reset:reg = 8;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01);
+        if (U132Status)
+                return U132Status;
+      reset_check:{
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+                if (pcidata & 1) {
+                        msleep(500);
+                        if (reset_repeat++ > 100) {
+                                reset_repeat = 0;
+                                goto do_reset;
+                        } else
+                                goto reset_check;
+                }
+        }
+        goto dump_regs;
+        msleep(500);
+        reg = 0x28;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x40;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x34;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 4;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(250);
+        reg = 8;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x28;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 8;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x48;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x34;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(100);
+        reg = 0x50;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+      power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        if (!(pcidata & 1)) {
+                msleep(500);
+                goto power_check;
+        }
+        msleep(3000);
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(750);
+        reg = 0x54;
+        if (0) {
+                U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
+                if (U132Status)
+                        return U132Status;
+        }
+        if (0) {
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+        }
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+      dump_regs:for (reg = 0; reg <= 0x54; reg += 4) {
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+        }
+        return 0;
+}
+
+
+/*
+* we use only the first bulk-in and bulk-out endpoints
+*/
+static int ftdi_elan_probe(struct usb_interface *interface,
+        const struct usb_device_id *id)
+{
+        struct usb_host_interface *iface_desc;
+        struct usb_endpoint_descriptor *endpoint;
+        size_t buffer_size;
+        int i;
+        int retval = -ENOMEM;
+        struct usb_ftdi *ftdi = kmalloc(sizeof(struct usb_ftdi), GFP_KERNEL);
+        if (ftdi == NULL) {
+                printk(KERN_ERR "Out of memory\n");
+                return -ENOMEM;
+        }
+        memset(ftdi, 0x00, sizeof(struct usb_ftdi));
+        down(&ftdi_module_lock);
+        list_add_tail(&ftdi->ftdi_list, &ftdi_static_list);
+        ftdi->sequence_num = ++ftdi_instances;
+        up(&ftdi_module_lock);
+        ftdi_elan_init_kref(ftdi);
+        init_MUTEX(&ftdi->sw_lock);
+        ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
+        ftdi->interface = interface;
+        init_MUTEX(&ftdi->u132_lock);
+        ftdi->expected = 4;
+        iface_desc = interface->cur_altsetting;
+        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+                endpoint = &iface_desc->endpoint[i].desc;
+                if (!ftdi->bulk_in_endpointAddr &&
+                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        == USB_DIR_IN) && ((endpoint->bmAttributes &
+                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
+                        {
+                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                        ftdi->bulk_in_size = buffer_size;
+                        ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+                        ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                        if (!ftdi->bulk_in_buffer) {
+                                dev_err(&ftdi->udev->dev, "Could not allocate b"
+                                        "ulk_in_buffer\n");
+                                retval = -ENOMEM;
+                                goto error;
+                        }
+                }
+                if (!ftdi->bulk_out_endpointAddr &&
+                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        == USB_DIR_OUT) && ((endpoint->bmAttributes &
+                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
+                        {
+                        ftdi->bulk_out_endpointAddr =
+                                endpoint->bEndpointAddress;
+                }
+        }
+        if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) {
+                dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk"
+                        "-out endpoints\n");
+                retval = -ENODEV;
+                goto error;
+        }
+        dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n",
+                iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr,
+                ftdi->bulk_out_endpointAddr);
+        usb_set_intfdata(interface, ftdi);
+        if (iface_desc->desc.bInterfaceNumber == 0 &&
+                ftdi->bulk_in_endpointAddr == 0x81 &&
+                ftdi->bulk_out_endpointAddr == 0x02) {
+                retval = usb_register_dev(interface, &ftdi_elan_jtag_class);
+                if (retval) {
+                        dev_err(&ftdi->udev->dev, "Not able to get a minor for "
+                                "this device.\n");
+                        usb_set_intfdata(interface, NULL);
+                        retval = -ENOMEM;
+                        goto error;
+                } else {
+                        ftdi->class = &ftdi_elan_jtag_class;
+                        dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface "
+                                "%d now attached to ftdi%d\n", ftdi,
+                                iface_desc->desc.bInterfaceNumber,
+                                interface->minor);
+                        return 0;
+                }
+        } else if (iface_desc->desc.bInterfaceNumber == 1 &&
+                ftdi->bulk_in_endpointAddr == 0x83 &&
+                ftdi->bulk_out_endpointAddr == 0x04) {
+                ftdi->class = NULL;
+                dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a"
+                        "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber);
+                INIT_WORK(&ftdi->status_work, ftdi_elan_status_work,
+                        (void *)ftdi);
+                INIT_WORK(&ftdi->command_work, ftdi_elan_command_work,
+                        (void *)ftdi);
+                INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work,
+                        (void *)ftdi);
+                ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
+                return 0;
+        } else {
+                dev_err(&ftdi->udev->dev,
+                        "Could not find ELAN's U132 device\n");
+                retval = -ENODEV;
+                goto error;
+        }
+      error:if (ftdi) {
+                ftdi_elan_put_kref(ftdi);
+        }
+        return retval;
+}
+
+static void ftdi_elan_disconnect(struct usb_interface *interface)
+{
+        struct usb_ftdi *ftdi = usb_get_intfdata(interface);
+        ftdi->disconnected += 1;
+        if (ftdi->class) {
+                int minor = interface->minor;
+                struct usb_class_driver *class = ftdi->class;
+                usb_set_intfdata(interface, NULL);
+                usb_deregister_dev(interface, class);
+                dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on min"
+                        "or %d now disconnected\n", minor);
+        } else {
+                ftdi_status_cancel_work(ftdi);
+                ftdi_command_cancel_work(ftdi);
+                ftdi_response_cancel_work(ftdi);
+                ftdi_elan_abandon_completions(ftdi);
+                ftdi_elan_abandon_targets(ftdi);
+                if (ftdi->registered) {
+                        platform_device_unregister(&ftdi->platform_dev);
+                        ftdi->synchronized = 0;
+                        ftdi->enumerated = 0;
+                        ftdi->registered = 0;
+                }
+                flush_workqueue(status_queue);
+                flush_workqueue(command_queue);
+                flush_workqueue(respond_queue);
+                ftdi->disconnected += 1;
+                usb_set_intfdata(interface, NULL);
+                dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller inter"
+                        "face now disconnected\n");
+        }
+        ftdi_elan_put_kref(ftdi);
+}
+
+static struct usb_driver ftdi_elan_driver = {
+        .name = "ftdi-elan",
+        .probe = ftdi_elan_probe,
+        .disconnect = ftdi_elan_disconnect,
+        .id_table = ftdi_elan_table,
+};
+static int __init ftdi_elan_init(void)
+{
+        int result;
+        printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
+                 __TIME__, __DATE__);
+        init_MUTEX(&ftdi_module_lock);
+        INIT_LIST_HEAD(&ftdi_static_list);
+        status_queue = create_singlethread_workqueue("ftdi-status-control");
+        command_queue = create_singlethread_workqueue("ftdi-command-engine");
+        respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
+        result = usb_register(&ftdi_elan_driver);
+        if (result)
+                printk(KERN_ERR "usb_register failed. Error number %d\n",
+                        result);
+        return result;
+}
+
+static void __exit ftdi_elan_exit(void)
+{
+        struct usb_ftdi *ftdi;
+        struct usb_ftdi *temp;
+        usb_deregister(&ftdi_elan_driver);
+        printk(KERN_INFO "ftdi_u132 driver deregistered\n");
+        list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) {
+                ftdi_status_cancel_work(ftdi);
+                ftdi_command_cancel_work(ftdi);
+                ftdi_response_cancel_work(ftdi);
+        } flush_workqueue(status_queue);
+        destroy_workqueue(status_queue);
+        status_queue = NULL;
+        flush_workqueue(command_queue);
+        destroy_workqueue(command_queue);
+        command_queue = NULL;
+        flush_workqueue(respond_queue);
+        destroy_workqueue(respond_queue);
+        respond_queue = NULL;
+}
+
+
+module_init(ftdi_elan_init);
+module_exit(ftdi_elan_exit);
index fcd69c52aea93a9f2acb1736672929ee7e70c2e9..8e6e195a22ba326229de458591eec586a1e4df9a 100644 (file)
@@ -98,7 +98,7 @@ static int idmouse_probe(struct usb_interface *interface,
 static void idmouse_disconnect(struct usb_interface *interface);
 
 /* file operation pointers */
-static struct file_operations idmouse_fops = {
+static const struct file_operations idmouse_fops = {
        .owner = THIS_MODULE,
        .read = idmouse_read,
        .open = idmouse_open,
index f30ab1fbb3c8c5f119edf1ac66dd1e3d31341bfe..10b640339d8dc6e832a1c20cabdb272ebe0c323a 100644 (file)
@@ -589,7 +589,7 @@ exit:
 }
 
 /* file operations needed when we register this driver */
-static struct file_operations ld_usb_fops = {
+static const struct file_operations ld_usb_fops = {
        .owner =        THIS_MODULE,
        .read  =        ld_usb_read,
        .write =        ld_usb_write,
@@ -657,15 +657,11 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
 
-               if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+               if (usb_endpoint_is_int_in(endpoint))
                        dev->interrupt_in_endpoint = endpoint;
-               }
 
-               if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+               if (usb_endpoint_is_int_out(endpoint))
                        dev->interrupt_out_endpoint = endpoint;
-               }
        }
        if (dev->interrupt_in_endpoint == NULL) {
                dev_err(&intf->dev, "Interrupt in endpoint not found\n");
index 7699d970e680d783bbb83c6a06280c9552bf2fcb..77c36e63c7bff169c405357bbec5270565ab80bb 100644 (file)
@@ -259,7 +259,7 @@ static void tower_disconnect        (struct usb_interface *interface);
 static DEFINE_MUTEX (disconnect_mutex);
 
 /* file operations needed when we register this driver */
-static struct file_operations tower_fops = {
+static const struct file_operations tower_fops = {
        .owner =        THIS_MODULE,
        .read  =        tower_read,
        .write =        tower_write,
diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c
new file mode 100644 (file)
index 0000000..735ed33
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * USB Phidgets class
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/device.h>
+
+struct class *phidget_class;
+
+static int __init init_phidget(void)
+{
+       phidget_class = class_create(THIS_MODULE, "phidget");
+
+       if (IS_ERR(phidget_class))
+               return PTR_ERR(phidget_class);
+
+       return 0;
+}
+
+static void __exit cleanup_phidget(void)
+{
+       class_destroy(phidget_class);
+}
+
+EXPORT_SYMBOL_GPL(phidget_class);
+
+module_init(init_phidget);
+module_exit(cleanup_phidget);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_DESCRIPTION("Container module for phidget class");
+
diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h
new file mode 100644 (file)
index 0000000..c401190
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * USB Phidgets class
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.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.
+ */
+
+extern struct class *phidget_class;
index bfbbbfbb92bcca4ef3b56fe8aea5241ef057ca7b..78e419904abf361d3463abc625d29fe6c7b32ae3 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 
+#include "phidget.h"
+
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
 
@@ -42,26 +44,35 @@ struct driver_interfacekit {
        int inputs;
        int outputs;
        int has_lcd;
+       int amnesiac;
 };
-#define ifkit(_sensors, _inputs, _outputs, _lcd)                       \
-static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = { \
+
+#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac)            \
+{                                                                      \
        .sensors        = _sensors,                                     \
        .inputs         = _inputs,                                      \
        .outputs        = _outputs,                                     \
        .has_lcd        = _lcd,                                         \
+       .amnesiac       = _amnesiac                                     \
 };
-ifkit(0, 0, 4, 0);
-ifkit(8, 8, 8, 0);
-ifkit(0, 4, 7, 1);
-ifkit(8, 8, 4, 0);
-ifkit(0, 8, 8, 1);
-ifkit(0, 16, 16, 0);
+
+static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0);
+static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1);
+static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0);
+static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0);
+static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0);
+static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0);
+static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0);
+
+static unsigned long device_no;
 
 struct interfacekit {
        struct usb_device *udev;
        struct usb_interface *intf;
        struct driver_interfacekit *ifkit;
+       struct device *dev;
        unsigned long outputs;
+       int dev_no;
        u8 inputs[MAX_INTERFACES];
        u16 sensors[MAX_INTERFACES];
        u8 lcd_files_on;
@@ -71,6 +82,7 @@ struct interfacekit {
        dma_addr_t data_dma;
 
        struct work_struct do_notify;
+       struct work_struct do_resubmit;
        unsigned long input_events;
        unsigned long sensor_events;
 };
@@ -78,8 +90,10 @@ struct interfacekit {
 static struct usb_device_id id_table[] = {
        {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
                .driver_info = (kernel_ulong_t)&ph_004},
-       {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888),
-               .driver_info = (kernel_ulong_t)&ph_888},
+       {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814),
+               .driver_info = (kernel_ulong_t)&ph_888o},
+       {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff),
+               .driver_info = (kernel_ulong_t)&ph_888n},
        {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
                .driver_info = (kernel_ulong_t)&ph_047},
        {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
@@ -92,16 +106,11 @@ static struct usb_device_id id_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static int change_outputs(struct interfacekit *kit, int output_num, int enable)
+static int set_outputs(struct interfacekit *kit)
 {
        u8 *buffer;
        int retval;
 
-       if (enable)
-               set_bit(output_num, &kit->outputs);
-       else
-               clear_bit(output_num, &kit->outputs);
-
        buffer = kzalloc(4, GFP_KERNEL);
        if (!buffer) {
                dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
@@ -121,6 +130,9 @@ static int change_outputs(struct interfacekit *kit, int output_num, int enable)
                                retval);
        kfree(buffer);
 
+       if (kit->ifkit->amnesiac)
+               schedule_delayed_work(&kit->do_resubmit, HZ / 2);
+
        return retval < 0 ? retval : 0;
 }
 
@@ -180,21 +192,24 @@ exit:
 }
 
 #define set_lcd_line(number)   \
-static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)     \
-{                                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);                             \
-       struct interfacekit *kit = usb_get_intfdata(intf);                              \
-       change_string(kit, buf, number - 1);                                            \
-       return count;                                                                   \
-}                                                                                      \
-static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
+static ssize_t lcd_line_##number(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
+{                                                                      \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
+       change_string(kit, buf, number - 1);                            \
+       return count;                                                   \
+}
+
+#define lcd_line_attr(number)                                          \
+       __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number)
+
 set_lcd_line(1);
 set_lcd_line(2);
 
 static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct usb_interface *intf = to_usb_interface(dev);
-       struct interfacekit *kit = usb_get_intfdata(intf);
+       struct interfacekit *kit = dev_get_drvdata(dev);
        int enabled;
        unsigned char *buffer;
        int retval = -ENOMEM;
@@ -226,23 +241,30 @@ exit:
        kfree(buffer);
        return retval;
 }
-static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
+
+static struct device_attribute dev_lcd_line_attrs[] = {
+       lcd_line_attr(1),
+       lcd_line_attr(2),
+       __ATTR(backlight, S_IWUGO, NULL, set_backlight)
+};
 
 static void remove_lcd_files(struct interfacekit *kit)
 {
+       int i;
+
        if (kit->lcd_files_on) {
                dev_dbg(&kit->udev->dev, "Removing lcd files\n");
-               device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1);
-               device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2);
-               device_remove_file(&kit->intf->dev, &dev_attr_backlight);
+
+               for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++)
+                       device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
        }
 }
 
 static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct usb_interface *intf = to_usb_interface(dev);
-       struct interfacekit *kit = usb_get_intfdata(intf);
+       struct interfacekit *kit = dev_get_drvdata(dev);
        int enable;
+       int i, rc;
        
        if (kit->ifkit->has_lcd == 0)
                return -ENODEV;
@@ -253,9 +275,12 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att
        if (enable) {
                if (!kit->lcd_files_on) {
                        dev_dbg(&kit->udev->dev, "Adding lcd files\n");
-                       device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1);
-                       device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2);
-                       device_create_file(&kit->intf->dev, &dev_attr_backlight);
+                       for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) {
+                               rc = device_create_file(kit->dev,
+                                       &dev_lcd_line_attrs[i]);
+                               if (rc)
+                                       goto out;
+                       }
                        kit->lcd_files_on = 1;
                }
        } else {
@@ -266,7 +291,13 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att
        }
        
        return count;
+out:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
+
+       return rc;
 }
+
 static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
 
 static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
@@ -362,44 +393,58 @@ static void do_notify(void *data)
        for (i=0; i<kit->ifkit->inputs; i++) {
                if (test_and_clear_bit(i, &kit->input_events)) {
                        sprintf(sysfs_file, "input%d", i + 1);
-                       sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+                       sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
                }
        }
 
        for (i=0; i<kit->ifkit->sensors; i++) {
                if (test_and_clear_bit(i, &kit->sensor_events)) {
                        sprintf(sysfs_file, "sensor%d", i + 1);
-                       sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+                       sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
                }
        }
 }
 
+static void do_resubmit(void *data)
+{
+       set_outputs(data);
+}
+
 #define show_set_output(value)         \
-static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf,   \
-                                                       size_t count)   \
+static ssize_t set_output##value(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
-       int enabled;                                                    \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
+       int enable;                                                     \
        int retval;                                                     \
                                                                        \
-       if (sscanf(buf, "%d", &enabled) < 1)                            \
+       if (sscanf(buf, "%d", &enable) < 1)                             \
                return -EINVAL;                                         \
                                                                        \
-       retval = change_outputs(kit, value - 1, enabled);               \
+       if (enable)                                                     \
+               set_bit(value - 1, &kit->outputs);                      \
+       else                                                            \
+               clear_bit(value - 1, &kit->outputs);                    \
+                                                                       \
+       retval = set_outputs(kit);                                      \
                                                                        \
        return retval ? retval : count;                                 \
 }                                                                      \
                                                                        \
-static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf)        \
+static ssize_t show_output##value(struct device *dev,                  \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
                                                                        \
        return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
-}                                                                      \
-static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO,                   \
-               show_output##value, set_output##value);
+}
+
+#define output_attr(value)                                             \
+       __ATTR(output##value, S_IWUGO | S_IRUGO,                        \
+               show_output##value, set_output##value)
+
 show_set_output(1);
 show_set_output(2);
 show_set_output(3);
@@ -417,15 +462,24 @@ show_set_output(14);
 show_set_output(15);
 show_set_output(16);
 
+static struct device_attribute dev_output_attrs[] = {
+       output_attr(1), output_attr(2), output_attr(3), output_attr(4),
+       output_attr(5), output_attr(6), output_attr(7), output_attr(8),
+       output_attr(9), output_attr(10), output_attr(11), output_attr(12),
+       output_attr(13), output_attr(14), output_attr(15), output_attr(16)
+};
+
 #define show_input(value)      \
-static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_input##value(struct device *dev,                   \
+                       struct device_attribute *attr, char *buf)       \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
                                                                        \
        return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]);       \
-}                                                                      \
-static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
+}
+
+#define input_attr(value)                                              \
+       __ATTR(input##value, S_IRUGO, show_input##value, NULL)
 
 show_input(1);
 show_input(2);
@@ -444,15 +498,25 @@ show_input(14);
 show_input(15);
 show_input(16);
 
+static struct device_attribute dev_input_attrs[] = {
+       input_attr(1), input_attr(2), input_attr(3), input_attr(4),
+       input_attr(5), input_attr(6), input_attr(7), input_attr(8),
+       input_attr(9), input_attr(10), input_attr(11), input_attr(12),
+       input_attr(13), input_attr(14), input_attr(15), input_attr(16)
+};
+
 #define show_sensor(value)     \
-static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf)        \
+static ssize_t show_sensor##value(struct device *dev,                  \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
                                                                        \
        return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]);      \
-}                                                                      \
-static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
+}
+
+#define sensor_attr(value)                                             \
+       __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL)
 
 show_sensor(1);
 show_sensor(2);
@@ -463,6 +527,11 @@ show_sensor(6);
 show_sensor(7);
 show_sensor(8);
 
+static struct device_attribute dev_sensor_attrs[] = {
+       sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4),
+       sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8)
+};
+
 static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct usb_device *dev = interface_to_usbdev(intf);
@@ -471,6 +540,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
        struct interfacekit *kit;
        struct driver_interfacekit *ifkit;
        int pipe, maxp, rc = -ENOMEM;
+       int bit, value, i;
 
        ifkit = (struct driver_interfacekit *)id->driver_info;
        if (!ifkit)
@@ -493,6 +563,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
        if (!kit)
                goto out;
 
+       kit->dev_no = -1;
        kit->ifkit = ifkit;
        kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
        if (!kit->data)
@@ -505,6 +576,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
        kit->udev = usb_get_dev(dev);
        kit->intf = intf;
        INIT_WORK(&kit->do_notify, do_notify, kit);
+       INIT_WORK(&kit->do_resubmit, do_resubmit, kit);
        usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
                        maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
                        interfacekit_irq, kit, endpoint->bInterval);
@@ -513,85 +585,80 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
 
        usb_set_intfdata(intf, kit);
 
+        do {
+                bit = find_first_zero_bit(&device_no, sizeof(device_no));
+                value = test_and_set_bit(bit, &device_no);
+        } while(value);
+        kit->dev_no = bit;
+
+        kit->dev = device_create(phidget_class, &kit->udev->dev, 0,
+                               "interfacekit%d", kit->dev_no);
+        if (IS_ERR(kit->dev)) {
+                rc = PTR_ERR(kit->dev);
+                kit->dev = NULL;
+                goto out;
+        }
+       dev_set_drvdata(kit->dev, kit);
+
        if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
                rc = -EIO;
                goto out;
        }
 
-       if (ifkit->outputs >= 4) {
-               device_create_file(&intf->dev, &dev_attr_output1);
-               device_create_file(&intf->dev, &dev_attr_output2);
-               device_create_file(&intf->dev, &dev_attr_output3);
-               device_create_file(&intf->dev, &dev_attr_output4);
-       }
-       if (ifkit->outputs >= 8) {
-               device_create_file(&intf->dev, &dev_attr_output5);
-               device_create_file(&intf->dev, &dev_attr_output6);
-               device_create_file(&intf->dev, &dev_attr_output7);
-               device_create_file(&intf->dev, &dev_attr_output8);
-       } 
-       if (ifkit->outputs == 16) {
-               device_create_file(&intf->dev, &dev_attr_output9);
-               device_create_file(&intf->dev, &dev_attr_output10);
-               device_create_file(&intf->dev, &dev_attr_output11);
-               device_create_file(&intf->dev, &dev_attr_output12);
-               device_create_file(&intf->dev, &dev_attr_output13);
-               device_create_file(&intf->dev, &dev_attr_output14);
-               device_create_file(&intf->dev, &dev_attr_output15);
-               device_create_file(&intf->dev, &dev_attr_output16);
+       for (i=0; i<ifkit->outputs; i++ ) {
+               rc = device_create_file(kit->dev, &dev_output_attrs[i]);
+               if (rc)
+                       goto out2;
        }
 
-       if (ifkit->inputs >= 4) {
-               device_create_file(&intf->dev, &dev_attr_input1);
-               device_create_file(&intf->dev, &dev_attr_input2);
-               device_create_file(&intf->dev, &dev_attr_input3);
-               device_create_file(&intf->dev, &dev_attr_input4);
-       }
-       if (ifkit->inputs >= 8) {
-               device_create_file(&intf->dev, &dev_attr_input5);
-               device_create_file(&intf->dev, &dev_attr_input6);
-               device_create_file(&intf->dev, &dev_attr_input7);
-               device_create_file(&intf->dev, &dev_attr_input8);
-       }
-       if (ifkit->inputs == 16) {
-               device_create_file(&intf->dev, &dev_attr_input9);
-               device_create_file(&intf->dev, &dev_attr_input10);
-               device_create_file(&intf->dev, &dev_attr_input11);
-               device_create_file(&intf->dev, &dev_attr_input12);
-               device_create_file(&intf->dev, &dev_attr_input13);
-               device_create_file(&intf->dev, &dev_attr_input14);
-               device_create_file(&intf->dev, &dev_attr_input15);
-               device_create_file(&intf->dev, &dev_attr_input16);
+       for (i=0; i<ifkit->inputs; i++ ) {
+               rc = device_create_file(kit->dev, &dev_input_attrs[i]);
+               if (rc)
+                       goto out3;
        }
 
-       if (ifkit->sensors >= 4) {
-               device_create_file(&intf->dev, &dev_attr_sensor1);
-               device_create_file(&intf->dev, &dev_attr_sensor2);
-               device_create_file(&intf->dev, &dev_attr_sensor3);
-               device_create_file(&intf->dev, &dev_attr_sensor4);
+       for (i=0; i<ifkit->sensors; i++ ) {
+               rc = device_create_file(kit->dev, &dev_sensor_attrs[i]);
+               if (rc)
+                       goto out4;
        }
-       if (ifkit->sensors >= 7) {
-               device_create_file(&intf->dev, &dev_attr_sensor5);
-               device_create_file(&intf->dev, &dev_attr_sensor6);
-               device_create_file(&intf->dev, &dev_attr_sensor7);
-       }
-       if (ifkit->sensors == 8)
-               device_create_file(&intf->dev, &dev_attr_sensor8);
 
-       if (ifkit->has_lcd)
-               device_create_file(&intf->dev, &dev_attr_lcd);
+       if (ifkit->has_lcd) {
+               rc = device_create_file(kit->dev, &dev_attr_lcd);
+               if (rc)
+                       goto out4;
+
+       }
 
        dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
                        ifkit->sensors, ifkit->inputs, ifkit->outputs);
 
        return 0;
 
+out4:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_sensor_attrs[i]);
+
+       i = ifkit->inputs;
+out3:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_input_attrs[i]);
+
+       i = ifkit->outputs;
+out2:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_output_attrs[i]);
 out:
        if (kit) {
                if (kit->irq)
                        usb_free_urb(kit->irq);
                if (kit->data)
                        usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
+               if (kit->dev)
+                       device_unregister(kit->dev);
+               if (kit->dev_no >= 0)
+                       clear_bit(kit->dev_no, &device_no);
+
                kfree(kit);
        }
 
@@ -601,6 +668,7 @@ out:
 static void interfacekit_disconnect(struct usb_interface *interface)
 {
        struct interfacekit *kit;
+       int i;
 
        kit = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
@@ -612,74 +680,30 @@ static void interfacekit_disconnect(struct usb_interface *interface)
        usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma);
 
        cancel_delayed_work(&kit->do_notify);
+       cancel_delayed_work(&kit->do_resubmit);
 
-       if (kit->ifkit->outputs >= 4) {
-               device_remove_file(&interface->dev, &dev_attr_output1);
-               device_remove_file(&interface->dev, &dev_attr_output2);
-               device_remove_file(&interface->dev, &dev_attr_output3);
-               device_remove_file(&interface->dev, &dev_attr_output4);
-       }
-       if (kit->ifkit->outputs >= 8) {
-               device_remove_file(&interface->dev, &dev_attr_output5);
-               device_remove_file(&interface->dev, &dev_attr_output6);
-               device_remove_file(&interface->dev, &dev_attr_output7);
-               device_remove_file(&interface->dev, &dev_attr_output8);
-       }
-       if (kit->ifkit->outputs == 16) {
-               device_remove_file(&interface->dev, &dev_attr_output9);
-               device_remove_file(&interface->dev, &dev_attr_output10);
-               device_remove_file(&interface->dev, &dev_attr_output11);
-               device_remove_file(&interface->dev, &dev_attr_output12);
-               device_remove_file(&interface->dev, &dev_attr_output13);
-               device_remove_file(&interface->dev, &dev_attr_output14);
-               device_remove_file(&interface->dev, &dev_attr_output15);
-               device_remove_file(&interface->dev, &dev_attr_output16);
-       }
+       for (i=0; i<kit->ifkit->outputs; i++)
+               device_remove_file(kit->dev, &dev_output_attrs[i]);
 
-       if (kit->ifkit->inputs >= 4) {
-               device_remove_file(&interface->dev, &dev_attr_input1);
-               device_remove_file(&interface->dev, &dev_attr_input2);
-               device_remove_file(&interface->dev, &dev_attr_input3);
-               device_remove_file(&interface->dev, &dev_attr_input4);
-       }
-       if (kit->ifkit->inputs >= 8) {
-               device_remove_file(&interface->dev, &dev_attr_input5);
-               device_remove_file(&interface->dev, &dev_attr_input6);
-               device_remove_file(&interface->dev, &dev_attr_input7);
-               device_remove_file(&interface->dev, &dev_attr_input8);
-       }
-       if (kit->ifkit->inputs == 16) {
-               device_remove_file(&interface->dev, &dev_attr_input9);
-               device_remove_file(&interface->dev, &dev_attr_input10);
-               device_remove_file(&interface->dev, &dev_attr_input11);
-               device_remove_file(&interface->dev, &dev_attr_input12);
-               device_remove_file(&interface->dev, &dev_attr_input13);
-               device_remove_file(&interface->dev, &dev_attr_input14);
-               device_remove_file(&interface->dev, &dev_attr_input15);
-               device_remove_file(&interface->dev, &dev_attr_input16);
-       }
+       for (i=0; i<kit->ifkit->inputs; i++)
+               device_remove_file(kit->dev, &dev_input_attrs[i]);
 
-       if (kit->ifkit->sensors >= 4) {
-               device_remove_file(&interface->dev, &dev_attr_sensor1);
-               device_remove_file(&interface->dev, &dev_attr_sensor2);
-               device_remove_file(&interface->dev, &dev_attr_sensor3);
-               device_remove_file(&interface->dev, &dev_attr_sensor4);
-       }
-       if (kit->ifkit->sensors >= 7) {
-               device_remove_file(&interface->dev, &dev_attr_sensor5);
-               device_remove_file(&interface->dev, &dev_attr_sensor6);
-               device_remove_file(&interface->dev, &dev_attr_sensor7);
+       for (i=0; i<kit->ifkit->sensors; i++)
+               device_remove_file(kit->dev, &dev_sensor_attrs[i]);
+
+       if (kit->ifkit->has_lcd) {
+               device_remove_file(kit->dev, &dev_attr_lcd);
+               remove_lcd_files(kit);
        }
-       if (kit->ifkit->sensors == 8)
-               device_remove_file(&interface->dev, &dev_attr_sensor8);
 
-       if (kit->ifkit->has_lcd)
-               device_remove_file(&interface->dev, &dev_attr_lcd);
+       device_unregister(kit->dev);
 
        dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
                kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
 
        usb_put_dev(kit->udev);
+       clear_bit(kit->dev_no, &device_no);
+
        kfree(kit);
 }
 
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
new file mode 100644 (file)
index 0000000..6b59b62
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * USB Phidget MotorControl driver
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "phidget.h"
+
+#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
+#define DRIVER_DESC "USB PhidgetMotorControl Driver"
+
+#define USB_VENDOR_ID_GLAB             0x06c2
+#define USB_DEVICE_ID_MOTORCONTROL     0x0058
+
+#define URB_INT_SIZE                   8
+
+static unsigned long device_no;
+
+struct motorcontrol {
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       struct device *dev;
+       int dev_no;
+       u8 inputs[4];
+       s8 desired_speed[2];
+       s8 speed[2];
+       s16 _current[2];
+       s8 acceleration[2];
+       struct urb *irq;
+       unsigned char *data;
+       dma_addr_t data_dma;
+
+       struct work_struct do_notify;
+       unsigned long input_events;
+       unsigned long speed_events;
+       unsigned long exceed_events;
+};
+
+static struct usb_device_id id_table[] = {
+       { USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) },
+       {}
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int set_motor(struct motorcontrol *mc, int motor)
+{
+       u8 *buffer;
+       int speed, speed2, acceleration;
+       int retval;
+
+       buffer = kzalloc(8, GFP_KERNEL);
+       if (!buffer) {
+               dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       acceleration = mc->acceleration[motor] * 10;
+       /* -127 <= speed <= 127 */
+       speed = (mc->desired_speed[motor] * 127) / 100;
+       /* -0x7300 <= speed2 <= 0x7300 */
+       speed2 = (mc->desired_speed[motor] * 230 * 128) / 100;
+
+       buffer[0] = motor;
+       buffer[1] = speed;
+       buffer[2] = acceleration >> 8;
+       buffer[3] = acceleration;
+       buffer[4] = speed2 >> 8;
+       buffer[5] = speed2;
+
+       retval = usb_control_msg(mc->udev,
+                        usb_sndctrlpipe(mc->udev, 0),
+                        0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
+
+       if (retval != 8)
+               dev_err(&mc->intf->dev, "usb_control_msg returned %d\n",
+                               retval);
+       kfree(buffer);
+
+       return retval < 0 ? retval : 0;
+}
+
+static void motorcontrol_irq(struct urb *urb, struct pt_regs *regs)
+{
+       struct motorcontrol *mc = urb->context;
+       unsigned char *buffer = mc->data;
+       int i, level;
+       int status;
+
+       switch (urb->status) {
+       case 0:                 /* success */
+               break;
+       case -ECONNRESET:       /* unlink */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       /* -EPIPE:  should clear the halt */
+       default:                /* error */
+               goto resubmit;
+       }
+
+       /* digital inputs */
+       for (i=0; i<4; i++) {
+               level = (buffer[0] >> i) & 1;
+               if (mc->inputs[i] != level) {
+                       mc->inputs[i] = level;
+                       set_bit(i, &mc->input_events);
+               }
+       }
+
+       /* motor speed */
+       if (buffer[2] == 0) {
+               for (i=0; i<2; i++) {
+               level = ((s8)buffer[4+i]) * 100 / 127;
+                       if (mc->speed[i] != level) {
+                               mc->speed[i] = level;
+                               set_bit(i, &mc->speed_events);
+                       }
+               }
+       } else {
+               int index = buffer[3] & 1;
+
+               level = ((s8)buffer[4] << 8) | buffer[5];
+               level = level * 100 / 29440;
+               if (mc->speed[index] != level) {
+                       mc->speed[index] = level;
+                       set_bit(index, &mc->speed_events);
+               }
+
+               level = ((s8)buffer[6] << 8) | buffer[7];
+               mc->_current[index] = level * 100 / 1572;
+       }
+
+       if (buffer[1] & 1)
+               set_bit(0, &mc->exceed_events);
+
+       if (buffer[1] & 2)
+               set_bit(1, &mc->exceed_events);
+
+       if (mc->input_events || mc->exceed_events || mc->speed_events)
+               schedule_work(&mc->do_notify);
+
+resubmit:
+       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       if (status)
+               dev_err(&mc->intf->dev,
+                       "can't resubmit intr, %s-%s/motorcontrol0, status %d",
+                       mc->udev->bus->bus_name,
+                       mc->udev->devpath, status);
+}
+
+static void do_notify(void *data)
+{
+       struct motorcontrol *mc = data;
+       int i;
+       char sysfs_file[8];
+
+       for (i=0; i<4; i++) {
+               if (test_and_clear_bit(i, &mc->input_events)) {
+                       sprintf(sysfs_file, "input%d", i);
+                       sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
+               }
+       }
+
+       for (i=0; i<2; i++) {
+               if (test_and_clear_bit(i, &mc->speed_events)) {
+                       sprintf(sysfs_file, "speed%d", i);
+                       sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
+               }
+       }
+
+       for (i=0; i<2; i++) {
+               if (test_and_clear_bit(i, &mc->exceed_events))
+                       dev_warn(&mc->intf->dev,
+                               "motor #%d exceeds 1.5 Amp current limit\n", i);
+       }
+}
+
+#define show_set_speed(value)          \
+static ssize_t set_speed##value(struct device *dev,                    \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+       int speed;                                                      \
+       int retval;                                                     \
+                                                                       \
+       if (sscanf(buf, "%d", &speed) < 1)                              \
+               return -EINVAL;                                         \
+                                                                       \
+       if (speed < -100 || speed > 100)                                \
+               return -EINVAL;                                         \
+                                                                       \
+       mc->desired_speed[value] = speed;                               \
+                                                                       \
+       retval = set_motor(mc, value);                                  \
+                                                                       \
+       return retval ? retval : count;                                 \
+}                                                                      \
+                                                                       \
+static ssize_t show_speed##value(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%d\n", mc->speed[value]);                  \
+}
+
+#define speed_attr(value)                                              \
+       __ATTR(speed##value, S_IWUGO | S_IRUGO,                         \
+               show_speed##value, set_speed##value)
+
+show_set_speed(0);
+show_set_speed(1);
+
+#define show_set_acceleration(value)           \
+static ssize_t set_acceleration##value(struct device *dev,             \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+       int acceleration;                                               \
+       int retval;                                                     \
+                                                                       \
+       if (sscanf(buf, "%d", &acceleration) < 1)                       \
+               return -EINVAL;                                         \
+                                                                       \
+       if (acceleration < 0 || acceleration > 100)                     \
+               return -EINVAL;                                         \
+                                                                       \
+       mc->acceleration[value] = acceleration;                         \
+                                                                       \
+       retval = set_motor(mc, value);                                  \
+                                                                       \
+       return retval ? retval : count;                                 \
+}                                                                      \
+                                                                       \
+static ssize_t show_acceleration##value(struct device *dev,            \
+                                       struct device_attribute *attr,  \
+                                                       char *buf)      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%d\n", mc->acceleration[value]);           \
+}
+
+#define acceleration_attr(value)       \
+       __ATTR(acceleration##value, S_IWUGO | S_IRUGO,                  \
+               show_acceleration##value, set_acceleration##value)
+
+show_set_acceleration(0);
+show_set_acceleration(1);
+
+#define show_current(value)    \
+static ssize_t show_current##value(struct device *dev,                 \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%dmA\n", (int)mc->_current[value]);        \
+}
+
+#define current_attr(value)    \
+       __ATTR(current##value, S_IRUGO, show_current##value, NULL)
+
+show_current(0);
+show_current(1);
+
+#define show_input(value)      \
+static ssize_t show_input##value(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%d\n", (int)mc->inputs[value]);            \
+}
+
+#define input_attr(value)      \
+       __ATTR(input##value, S_IRUGO, show_input##value, NULL)
+
+show_input(0);
+show_input(1);
+show_input(2);
+show_input(3);
+
+static struct device_attribute dev_attrs[] = {
+       input_attr(0),
+       input_attr(1),
+       input_attr(2),
+       input_attr(3),
+       speed_attr(0),
+       speed_attr(1),
+       acceleration_attr(0),
+       acceleration_attr(1),
+       current_attr(0),
+       current_attr(1)
+};
+
+static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_host_interface *interface;
+       struct usb_endpoint_descriptor *endpoint;
+       struct motorcontrol *mc;
+       int pipe, maxp, rc = -ENOMEM;
+       int bit, value, i;
+
+       interface = intf->cur_altsetting;
+       if (interface->desc.bNumEndpoints != 1)
+               return -ENODEV;
+
+       endpoint = &interface->endpoint[0].desc;
+       if (!(endpoint->bEndpointAddress & 0x80))
+               return -ENODEV;
+
+       /*
+        * bmAttributes
+        */
+       pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+       maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+       mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+       if (!mc)
+               goto out;
+
+       mc->dev_no = -1;
+       mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);
+       if (!mc->data)
+               goto out;
+
+       mc->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mc->irq)
+               goto out;
+
+       mc->udev = usb_get_dev(dev);
+       mc->intf = intf;
+       mc->acceleration[0] = mc->acceleration[1] = 10;
+       INIT_WORK(&mc->do_notify, do_notify, mc);
+       usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
+                       maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
+                       motorcontrol_irq, mc, endpoint->bInterval);
+       mc->irq->transfer_dma = mc->data_dma;
+       mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       usb_set_intfdata(intf, mc);
+
+       do {
+               bit = find_first_zero_bit(&device_no, sizeof(device_no));
+               value = test_and_set_bit(bit, &device_no);
+       } while(value);
+       mc->dev_no = bit;
+
+       mc->dev = device_create(phidget_class, &mc->udev->dev, 0,
+                               "motorcontrol%d", mc->dev_no);
+       if (IS_ERR(mc->dev)) {
+               rc = PTR_ERR(mc->dev);
+               mc->dev = NULL;
+               goto out;
+       }
+
+       dev_set_drvdata(mc->dev, mc);
+
+       if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
+               rc = -EIO;
+               goto out;
+       }
+
+       for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
+               rc = device_create_file(mc->dev, &dev_attrs[i]);
+               if (rc)
+                       goto out2;
+       }
+
+       dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
+
+       return 0;
+out2:
+       while (i-- > 0)
+               device_remove_file(mc->dev, &dev_attrs[i]);
+out:
+       if (mc) {
+               if (mc->irq)
+                       usb_free_urb(mc->irq);
+               if (mc->data)
+                       usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
+               if (mc->dev)
+                       device_unregister(mc->dev);
+               if (mc->dev_no >= 0)
+                       clear_bit(mc->dev_no, &device_no);
+
+               kfree(mc);
+       }
+
+       return rc;
+}
+
+static void motorcontrol_disconnect(struct usb_interface *interface)
+{
+       struct motorcontrol *mc;
+       int i;
+
+       mc = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+       if (!mc)
+               return;
+
+       usb_kill_urb(mc->irq);
+       usb_free_urb(mc->irq);
+       usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma);
+
+       cancel_delayed_work(&mc->do_notify);
+
+       for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
+               device_remove_file(mc->dev, &dev_attrs[i]);
+
+       device_unregister(mc->dev);
+
+       usb_put_dev(mc->udev);
+       clear_bit(mc->dev_no, &device_no);
+       kfree(mc);
+
+       dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
+}
+
+static struct usb_driver motorcontrol_driver = {
+       .name = "phidgetmotorcontrol",
+       .probe = motorcontrol_probe,
+       .disconnect = motorcontrol_disconnect,
+       .id_table = id_table
+};
+
+static int __init motorcontrol_init(void)
+{
+       int retval = 0;
+
+       retval = usb_register(&motorcontrol_driver);
+       if (retval)
+               err("usb_register failed. Error number %d", retval);
+
+       return retval;
+}
+
+static void __exit motorcontrol_exit(void)
+{
+       usb_deregister(&motorcontrol_driver);
+}
+
+module_init(motorcontrol_init);
+module_exit(motorcontrol_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index c0df79c9653810b17e0e87737eb9e1ab37b1dad0..7163f05c5b27063eb18b7554372fe99280205c8b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * USB PhidgetServo driver 1.0
  *
- * Copyright (C) 2004 Sean Young <sean@mess.org>
+ * Copyright (C) 2004, 2006 Sean Young <sean@mess.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
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
- *
- * Jun 16, 2004: Sean Young <sean@mess.org>
- *  - cleanups
- *  - was using memory after kfree()
- * Aug 8, 2004: Sean Young <sean@mess.org>
- *  - set the highest angle as high as the hardware allows, there are 
- *    some odd servos out there
- *
  */
 
 #include <linux/kernel.h>
@@ -32,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 
+#include "phidget.h"
+
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetServo Driver"
 
@@ -70,8 +64,12 @@ static struct usb_device_id id_table[] = {
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
+static int unsigned long device_no;
+
 struct phidget_servo {
        struct usb_device *udev;
+       struct device *dev;
+       int dev_no;
        ulong type;
        int pulse[4];
        int degrees[4];
@@ -203,16 +201,16 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
 }
 
 #define show_set(value)        \
-static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr,                    \
+static ssize_t set_servo##value (struct device *dev,                   \
+                                       struct device_attribute *attr,  \
                                        const char *buf, size_t count)  \
 {                                                                      \
        int degrees, minutes, retval;                                   \
-       struct usb_interface *intf = to_usb_interface (dev);            \
-       struct phidget_servo *servo = usb_get_intfdata (intf);          \
+       struct phidget_servo *servo = dev_get_drvdata(dev);             \
                                                                        \
        minutes = 0;                                                    \
        /* must at least convert degrees */                             \
-       if (sscanf (buf, "%d.%d", &degrees, &minutes) < 1) {            \
+       if (sscanf(buf, "%d.%d", &degrees, &minutes) < 1) {             \
                return -EINVAL;                                         \
        }                                                               \
                                                                        \
@@ -220,86 +218,127 @@ static ssize_t set_servo##value (struct device *dev, struct device_attribute *at
                return -EINVAL;                                         \
                                                                        \
        if (servo->type & SERVO_VERSION_30)                             \
-               retval = change_position_v30 (servo, value, degrees,    \
+               retval = change_position_v30(servo, value, degrees,     \
                                                        minutes);       \
        else                                                            \
-               retval = change_position_v20 (servo, value, degrees,    \
+               retval = change_position_v20(servo, value, degrees,     \
                                                        minutes);       \
                                                                        \
        return retval < 0 ? retval : count;                             \
 }                                                                      \
                                                                        \
-static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf)        \
+static ssize_t show_servo##value (struct device *dev,                  \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface (dev);            \
-       struct phidget_servo *servo = usb_get_intfdata (intf);          \
+       struct phidget_servo *servo = dev_get_drvdata(dev);             \
                                                                        \
-       return sprintf (buf, "%d.%02d\n", servo->degrees[value],        \
+       return sprintf(buf, "%d.%02d\n", servo->degrees[value],         \
                                servo->minutes[value]);                 \
-}                                                                      \
-static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO,                    \
-         show_servo##value, set_servo##value);
+}
 
+#define servo_attr(value)                                              \
+       __ATTR(servo##value, S_IWUGO | S_IRUGO,                         \
+               show_servo##value, set_servo##value)
 show_set(0);
 show_set(1);
 show_set(2);
 show_set(3);
 
+static struct device_attribute dev_attrs[] = {
+       servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3)
+};
+
 static int
 servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
        struct usb_device *udev = interface_to_usbdev(interface);
        struct phidget_servo *dev;
+       int bit, value, rc;
+       int servo_count, i;
 
        dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
        if (dev == NULL) {
                dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out;
        }
 
        dev->udev = usb_get_dev(udev);
        dev->type = id->driver_info;
+       dev->dev_no = -1;
        usb_set_intfdata(interface, dev);
 
-       device_create_file(&interface->dev, &dev_attr_servo0);
-       if (dev->type & SERVO_COUNT_QUAD) {
-               device_create_file(&interface->dev, &dev_attr_servo1);
-               device_create_file(&interface->dev, &dev_attr_servo2);
-               device_create_file(&interface->dev, &dev_attr_servo3);
+        do {
+                bit = find_first_zero_bit(&device_no, sizeof(device_no));
+                value = test_and_set_bit(bit, &device_no);
+        } while (value);
+       dev->dev_no = bit;
+
+       dev->dev = device_create(phidget_class, &dev->udev->dev, 0,
+                                "servo%d", dev->dev_no);
+       if (IS_ERR(dev->dev)) {
+               rc = PTR_ERR(dev->dev);
+               dev->dev = NULL;
+               goto out;
+       }
+
+       servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
+
+       for (i=0; i<servo_count; i++) {
+               rc = device_create_file(dev->dev, &dev_attrs[i]);
+               if (rc)
+                       goto out2;
        }
 
        dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
-               dev->type & SERVO_COUNT_QUAD ? 4 : 1,
-               dev->type & SERVO_VERSION_30 ? 3 : 2);
+               servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
 
-       if(!(dev->type & SERVO_VERSION_30))
+       if (!(dev->type & SERVO_VERSION_30))
                dev_info(&interface->dev,
                         "WARNING: v2.0 not tested! Please report if it works.\n");
 
        return 0;
+out2:
+       while (i-- > 0)
+               device_remove_file(dev->dev, &dev_attrs[i]);
+out:
+       if (dev) {
+               if (dev->dev)
+                       device_unregister(dev->dev);
+               if (dev->dev_no >= 0)
+                       clear_bit(dev->dev_no, &device_no);
+
+               kfree(dev);
+       }
+
+       return rc;
 }
 
 static void
 servo_disconnect(struct usb_interface *interface)
 {
        struct phidget_servo *dev;
+       int servo_count, i;
 
        dev = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
 
-       device_remove_file(&interface->dev, &dev_attr_servo0);
-       if (dev->type & SERVO_COUNT_QUAD) {
-               device_remove_file(&interface->dev, &dev_attr_servo1);
-               device_remove_file(&interface->dev, &dev_attr_servo2);
-               device_remove_file(&interface->dev, &dev_attr_servo3);
-       }
+       if (!dev)
+               return;
+
+       servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
+
+       for (i=0; i<servo_count; i++)
+               device_remove_file(dev->dev, &dev_attrs[i]);
 
+       device_unregister(dev->dev);
        usb_put_dev(dev->udev);
 
        dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
-               dev->type & SERVO_COUNT_QUAD ? 4 : 1,
-               dev->type & SERVO_VERSION_30 ? 3 : 2);
+               servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
 
+       clear_bit(dev->dev_no, &device_no);
        kfree(dev);
 }
 
index e16582f3733c16a093ad30b4dbcf417093098f4a..a44124c7e8514860861aa291ee4ded07afe53145 100644 (file)
@@ -3179,7 +3179,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 }
 #endif
 
-static struct file_operations usb_sisusb_fops = {
+static const struct file_operations usb_sisusb_fops = {
        .owner =        THIS_MODULE,
        .open =         sisusb_open,
        .release =      sisusb_release,
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h
new file mode 100644 (file)
index 0000000..551ba89
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+* Common Header File for the Elan Digital Systems U132 adapter
+* this file should be included by both the "ftdi-u132" and
+* the "u132-hcd" modules.
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+*(http://www.elandigitalsystems.com)
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+*(tony.olech@elandigitalsystems.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, version 2.
+*
+*
+* The driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB client drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+* The driver consists of two modules, the "ftdi-u132" module is
+* a USB client driver that interfaces to the FTDI chip within
+* the U132 adapter manufactured by Elan Digital Systems, and the
+* "u132-hcd" module is a USB host controller driver that talks
+* to the OHCI controller within CardBus card that are inserted
+* in the U132 adapter.
+*
+* The "ftdi-u132" module should be loaded automatically by the
+* hot plug system when the U132 adapter is plugged in. The module
+* initialises the adapter which mostly consists of synchronising
+* the FTDI chip, before continuously polling the adapter to detect
+* PC card insertions. As soon as a PC card containing a recognised
+* OHCI controller is seen the "ftdi-u132" module explicitly requests
+* the kernel to load the "u132-hcd" module.
+*
+* The "ftdi-u132" module provides the interface to the inserted
+* PC card and the "u132-hcd" module uses the API to send and recieve
+* data. The API features call-backs, so that part of the "u132-hcd"
+* module code will run in the context of one of the kernel threads
+* of the "ftdi-u132" module.
+*
+*/
+int ftdi_elan_switch_on_diagnostics(int number);
+void ftdi_elan_gone_away(struct platform_device *pdev);
+void start_usb_lock_device_tracing(void);
+struct u132_platform_data {
+        u16 vendor;
+        u16 device;
+        u8 potpg;
+        void (*port_power) (struct device *dev, int is_on);
+        void (*reset) (struct device *dev);
+};
+int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
+        void *endp);
index e095772dd8e9eebc2887afc835b105d72af09d03..dbaca9f1efadc02de7d6544523e75a039f26a104 100644 (file)
@@ -239,7 +239,7 @@ error:
        return retval;
 }
 
-static struct file_operations lcd_fops = {
+static const struct file_operations lcd_fops = {
         .owner =        THIS_MODULE,
         .read =         lcd_read,
         .write =        lcd_write,
@@ -290,9 +290,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
                endpoint = &iface_desc->endpoint[i].desc;
 
                if (!dev->bulk_in_endpointAddr &&
-                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                        dev->bulk_in_size = buffer_size;
@@ -305,9 +303,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
                }
 
                if (!dev->bulk_out_endpointAddr &&
-                   !(endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
                }
index 0c5ee0ad6bb952fecc1eda6708cbab753ebc4120..49c5c5c4c431ee2aabd7ce0b081e913d2634b6f6 100644 (file)
@@ -108,22 +108,34 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id
        dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
        if (dev == NULL) {
                dev_err(&interface->dev, "Out of memory\n");
-               goto error;
+               goto error_mem;
        }
 
        dev->udev = usb_get_dev(udev);
 
        usb_set_intfdata (interface, dev);
 
-       device_create_file(&interface->dev, &dev_attr_blue);
-       device_create_file(&interface->dev, &dev_attr_red);
-       device_create_file(&interface->dev, &dev_attr_green);
+       retval = device_create_file(&interface->dev, &dev_attr_blue);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_red);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_green);
+       if (retval)
+               goto error;
 
        dev_info(&interface->dev, "USB LED device now attached\n");
        return 0;
 
 error:
+       device_remove_file(&interface->dev, &dev_attr_blue);
+       device_remove_file(&interface->dev, &dev_attr_red);
+       device_remove_file(&interface->dev, &dev_attr_green);
+       usb_set_intfdata (interface, NULL);
+       usb_put_dev(dev->udev);
        kfree(dev);
+error_mem:
        return retval;
 }
 
index 275a66f8305878b2f435506e675a851454b586af..394bbf2f68d44f0b81807773be8a12e992fb690c 100644 (file)
@@ -265,7 +265,6 @@ static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
        ubus->mon_bus = NULL;
        mbus->u_bus = NULL;
        mb();
-       // usb_bus_put(ubus);
 }
 
 /*
@@ -297,12 +296,12 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
        INIT_LIST_HEAD(&mbus->r_list);
 
        /*
-        * This usb_bus_get here is superfluous, because we receive
-        * a notification if usb_bus is about to be removed.
+        * We don't need to take a reference to ubus, because we receive
+        * a notification if the bus is about to be removed.
         */
-       // usb_bus_get(ubus);
        mbus->u_bus = ubus;
        ubus->mon_bus = mbus;
+       mbus->uses_dma = ubus->uses_dma;
 
        rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
        if (rc <= 0 || rc >= NAMESZ)
index 1fe01d994a793f79ec801a663a8ddb1eec54a345..f6d1491256c4453ebfb1b06f2a908b4c29d364fd 100644 (file)
@@ -28,7 +28,7 @@ static int mon_stat_open(struct inode *inode, struct file *file)
        if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL)
                return -ENOMEM;
 
-       mbus = inode->u.generic_ip;
+       mbus = inode->i_private;
 
        sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
            "nreaders %d events %u text_lost %u\n",
@@ -62,7 +62,7 @@ static int mon_stat_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-struct file_operations mon_fops_stat = {
+const struct file_operations mon_fops_stat = {
        .owner =        THIS_MODULE,
        .open =         mon_stat_open,
        .llseek =       no_llseek,
index f961a770cee2ea2a24d2ef01e39fd7d73fc99b0e..7a2346c53284b93a502b47b5911159f343a70ecc 100644 (file)
@@ -75,13 +75,13 @@ static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
  */
 
 static inline char mon_text_get_setup(struct mon_event_text *ep,
-    struct urb *urb, char ev_type)
+    struct urb *urb, char ev_type, struct mon_bus *mbus)
 {
 
        if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
                return '-';
 
-       if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+       if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
        if (urb->setup_packet == NULL)
                return 'Z';     /* '0' would be not as pretty. */
@@ -91,7 +91,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
 }
 
 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
-    int len, char ev_type)
+    int len, char ev_type, struct mon_bus *mbus)
 {
        int pipe = urb->pipe;
 
@@ -117,7 +117,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
         * contain non-NULL garbage in case the upper level promised to
         * set DMA for the HCD.
         */
-       if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+       if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
                return mon_dmapeek(ep->data, urb->transfer_dma, len);
 
        if (urb->transfer_buffer == NULL)
@@ -161,8 +161,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
        /* Collecting status makes debugging sense for submits, too */
        ep->status = urb->status;
 
-       ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
-       ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
+       ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
+       ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
+                       rp->r.m_bus);
 
        rp->nevents++;
        list_add_tail(&ep->e_link, &rp->e_list);
@@ -238,7 +239,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
        int rc;
 
        mutex_lock(&mon_lock);
-       mbus = inode->u.generic_ip;
+       mbus = inode->i_private;
        ubus = mbus->u_bus;
 
        rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
@@ -401,7 +402,7 @@ static int mon_text_release(struct inode *inode, struct file *file)
        struct mon_event_text *ep;
 
        mutex_lock(&mon_lock);
-       mbus = inode->u.generic_ip;
+       mbus = inode->i_private;
 
        if (mbus->nreaders <= 0) {
                printk(KERN_ERR TAG ": consistency error on close\n");
@@ -435,7 +436,7 @@ static int mon_text_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-struct file_operations mon_fops_text = {
+const struct file_operations mon_fops_text = {
        .owner =        THIS_MODULE,
        .open =         mon_text_open,
        .llseek =       no_llseek,
index 33678c24ebeed5713b06a9eb1fd32d3283effc67..ab9d02d5df77a448c0c829c42b5b3633fbdfc054 100644 (file)
@@ -20,6 +20,7 @@ struct mon_bus {
        struct dentry *dent_s;          /* Debugging file */
        struct dentry *dent_t;          /* Text interface file */
        struct usb_bus *u_bus;
+       int uses_dma;
 
        /* Ref */
        int nreaders;                   /* Under mon_lock AND mbus->lock */
@@ -53,7 +54,7 @@ extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
 
 extern struct mutex mon_lock;
 
-extern struct file_operations mon_fops_text;
-extern struct file_operations mon_fops_stat;
+extern const struct file_operations mon_fops_text;
+extern const struct file_operations mon_fops_stat;
 
 #endif /* __USB_MON_H */
index 2e2bbc003e9392c7ae974b6ee62f86a1b287eb9d..9c0eacf7055c1d65169ad536fc4d21450da74eae 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * ASIX AX8817X based USB 2.0 Ethernet Devices
- * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
  * Copyright (c) 2002-2003 TiVo Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,6 +37,9 @@
 
 #include "usbnet.h"
 
+#define DRIVER_VERSION "14-Jun-2006"
+static const char driver_name [] = "asix";
+
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 
 #define AX_CMD_SET_SW_MII              0x06
 #define AX_CMD_WRITE_EEPROM            0x0c
 #define AX_CMD_WRITE_ENABLE            0x0d
 #define AX_CMD_WRITE_DISABLE           0x0e
+#define AX_CMD_READ_RX_CTL             0x0f
 #define AX_CMD_WRITE_RX_CTL            0x10
 #define AX_CMD_READ_IPG012             0x11
 #define AX_CMD_WRITE_IPG0              0x12
 #define AX_CMD_WRITE_IPG1              0x13
+#define AX_CMD_READ_NODE_ID            0x13
 #define AX_CMD_WRITE_IPG2              0x14
 #define AX_CMD_WRITE_MULTI_FILTER      0x16
-#define AX_CMD_READ_NODE_ID            0x17
+#define AX88172_CMD_READ_NODE_ID       0x17
 #define AX_CMD_READ_PHY_ID             0x19
 #define AX_CMD_READ_MEDIUM_STATUS      0x1a
 #define AX_CMD_WRITE_MEDIUM_MODE       0x1b
 #define AX_CMD_READ_MONITOR_MODE       0x1c
 #define AX_CMD_WRITE_MONITOR_MODE      0x1d
+#define AX_CMD_READ_GPIOS              0x1e
 #define AX_CMD_WRITE_GPIOS             0x1f
 #define AX_CMD_SW_RESET                        0x20
 #define AX_CMD_SW_PHY_STATUS           0x21
 #define AX_CMD_SW_PHY_SELECT           0x22
-#define AX88772_CMD_READ_NODE_ID       0x13
 
 #define AX_MONITOR_MODE                        0x01
 #define AX_MONITOR_LINK                        0x02
 #define AX_MONITOR_HSFS                        0x10
 
 /* AX88172 Medium Status Register values */
-#define AX_MEDIUM_FULL_DUPLEX          0x02
-#define AX_MEDIUM_TX_ABORT_ALLOW       0x04
-#define AX_MEDIUM_FLOW_CONTROL_EN      0x10
+#define AX88172_MEDIUM_FD              0x02
+#define AX88172_MEDIUM_TX              0x04
+#define AX88172_MEDIUM_FC              0x10
+#define AX88172_MEDIUM_DEFAULT \
+               ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC )
 
 #define AX_MCAST_FILTER_SIZE           8
 #define AX_MAX_MCAST                   64
 
-#define AX_EEPROM_LEN                  0x40
-
 #define AX_SWRESET_CLEAR               0x00
 #define AX_SWRESET_RR                  0x01
 #define AX_SWRESET_RT                  0x02
 #define AX88772_IPG1_DEFAULT           0x0c
 #define AX88772_IPG2_DEFAULT           0x12
 
-#define AX88772_MEDIUM_FULL_DUPLEX     0x0002
-#define AX88772_MEDIUM_RESERVED                0x0004
-#define AX88772_MEDIUM_RX_FC_ENABLE    0x0010
-#define AX88772_MEDIUM_TX_FC_ENABLE    0x0020
-#define AX88772_MEDIUM_PAUSE_FORMAT    0x0080
-#define AX88772_MEDIUM_RX_ENABLE       0x0100
-#define AX88772_MEDIUM_100MB           0x0200
-#define AX88772_MEDIUM_DEFAULT \
-       (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
-        AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
-        AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+/* AX88772 & AX88178 Medium Mode Register */
+#define AX_MEDIUM_PF           0x0080
+#define AX_MEDIUM_JFE          0x0040
+#define AX_MEDIUM_TFC          0x0020
+#define AX_MEDIUM_RFC          0x0010
+#define AX_MEDIUM_ENCK         0x0008
+#define AX_MEDIUM_AC           0x0004
+#define AX_MEDIUM_FD           0x0002
+#define AX_MEDIUM_GM           0x0001
+#define AX_MEDIUM_SM           0x1000
+#define AX_MEDIUM_SBP          0x0800
+#define AX_MEDIUM_PS           0x0200
+#define AX_MEDIUM_RE           0x0100
+
+#define AX88178_MEDIUM_DEFAULT \
+       (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
+        AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
+        AX_MEDIUM_RE )
 
-#define AX_EEPROM_MAGIC                        0xdeadbeef
+#define AX88772_MEDIUM_DEFAULT \
+       (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
+        AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+        AX_MEDIUM_AC | AX_MEDIUM_RE )
+
+/* AX88772 & AX88178 RX_CTL values */
+#define AX_RX_CTL_SO                   0x0080
+#define AX_RX_CTL_AP                   0x0020
+#define AX_RX_CTL_AM                   0x0010
+#define AX_RX_CTL_AB                   0x0008
+#define AX_RX_CTL_SEP                  0x0004
+#define AX_RX_CTL_AMALL                        0x0002
+#define AX_RX_CTL_PRO                  0x0001
+#define AX_RX_CTL_MFB_2048             0x0000
+#define AX_RX_CTL_MFB_4096             0x0100
+#define AX_RX_CTL_MFB_8192             0x0200
+#define AX_RX_CTL_MFB_16384            0x0300
+
+#define AX_DEFAULT_RX_CTL      \
+       (AX_RX_CTL_SO | AX_RX_CTL_AB )
+
+/* GPIO 0 .. 2 toggles */
+#define AX_GPIO_GPO0EN         0x01    /* GPIO0 Output enable */
+#define AX_GPIO_GPO_0          0x02    /* GPIO0 Output value */
+#define AX_GPIO_GPO1EN         0x04    /* GPIO1 Output enable */
+#define AX_GPIO_GPO_1          0x08    /* GPIO1 Output value */
+#define AX_GPIO_GPO2EN         0x10    /* GPIO2 Output enable */
+#define AX_GPIO_GPO_2          0x20    /* GPIO2 Output value */
+#define AX_GPIO_RESERVED       0x40    /* Reserved */
+#define AX_GPIO_RSE            0x80    /* Reload serial EEPROM */
+
+#define AX_EEPROM_MAGIC                0xdeadbeef
+#define AX88172_EEPROM_LEN     0x40
+#define AX88772_EEPROM_LEN     0xff
+
+#define PHY_MODE_MARVELL       0x0000
+#define MII_MARVELL_LED_CTRL   0x0018
+#define MII_MARVELL_STATUS     0x001b
+#define MII_MARVELL_CTRL       0x0014
+
+#define MARVELL_LED_MANUAL     0x0019
+
+#define MARVELL_STATUS_HWCFG   0x0004
+
+#define MARVELL_CTRL_TXDELAY   0x0002
+#define MARVELL_CTRL_RXDELAY   0x0080
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
        u8 multi_filter[AX_MCAST_FILTER_SIZE];
+       u8 phymode;
+       u8 ledmode;
+       u8 eeprom_len;
 };
 
 struct ax88172_int_data {
@@ -122,6 +183,8 @@ struct ax88172_int_data {
 static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                            u16 size, void *data)
 {
+       devdbg(dev,"asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+               cmd, value, index, size);
        return usb_control_msg(
                dev->udev,
                usb_rcvctrlpipe(dev->udev, 0),
@@ -137,6 +200,8 @@ static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                             u16 size, void *data)
 {
+       devdbg(dev,"asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+               cmd, value, index, size);
        return usb_control_msg(
                dev->udev,
                usb_sndctrlpipe(dev->udev, 0),
@@ -161,12 +226,167 @@ static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
        usb_free_urb(urb);
 }
 
+static void
+asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                                   u16 size, void *data)
+{
+       struct usb_ctrlrequest *req;
+       int status;
+       struct urb *urb;
+
+       devdbg(dev,"asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+               cmd, value, index, size);
+       if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+               deverr(dev, "Error allocating URB in write_cmd_async!");
+               return;
+       }
+
+       if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
+               deverr(dev, "Failed to allocate memory for control request");
+               usb_free_urb(urb);
+               return;
+       }
+
+       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       req->bRequest = cmd;
+       req->wValue = value;
+       req->wIndex = index;
+       req->wLength = size;
+
+       usb_fill_control_urb(urb, dev->udev,
+                            usb_sndctrlpipe(dev->udev, 0),
+                            (void *)req, data, size,
+                            asix_async_cmd_callback, req);
+
+       if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               deverr(dev, "Error submitting the control message: status=%d",
+                               status);
+               kfree(req);
+               usb_free_urb(urb);
+       }
+}
+
+static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       u8  *head;
+       u32  header;
+       char *packet;
+       struct sk_buff *ax_skb;
+       u16 size;
+
+       head = (u8 *) skb->data;
+       memcpy(&header, head, sizeof(header));
+       le32_to_cpus(&header);
+       packet = head + sizeof(header);
+
+       skb_pull(skb, 4);
+
+       while (skb->len > 0) {
+               if ((short)(header & 0x0000ffff) !=
+                   ~((short)((header & 0xffff0000) >> 16))) {
+                       deverr(dev,"asix_rx_fixup() Bad Header Length");
+               }
+               /* get the packet length */
+               size = (u16) (header & 0x0000ffff);
+
+               if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+                       return 2;
+               if (size > ETH_FRAME_LEN) {
+                       deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
+                       return 0;
+               }
+               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               if (ax_skb) {
+                       ax_skb->len = size;
+                       ax_skb->data = packet;
+                       ax_skb->tail = packet + size;
+                       usbnet_skb_return(dev, ax_skb);
+               } else {
+                       return 0;
+               }
+
+               skb_pull(skb, (size + 1) & 0xfffe);
+
+               if (skb->len == 0)
+                       break;
+
+               head = (u8 *) skb->data;
+               memcpy(&header, head, sizeof(header));
+               le32_to_cpus(&header);
+               packet = head + sizeof(header);
+               skb_pull(skb, 4);
+       }
+
+       if (skb->len < 0) {
+               deverr(dev,"asix_rx_fixup() Bad SKB Length %d", skb->len);
+               return 0;
+       }
+       return 1;
+}
+
+static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+                                       gfp_t flags)
+{
+       int padlen;
+       int headroom = skb_headroom(skb);
+       int tailroom = skb_tailroom(skb);
+       u32 packet_len;
+       u32 padbytes = 0xffff0000;
+
+       padlen = ((skb->len + 4) % 512) ? 0 : 4;
+
+       if ((!skb_cloned(skb))
+           && ((headroom + tailroom) >= (4 + padlen))) {
+               if ((headroom < 4) || (tailroom < padlen)) {
+                       skb->data = memmove(skb->head + 4, skb->data, skb->len);
+                       skb->tail = skb->data + skb->len;
+               }
+       } else {
+               struct sk_buff *skb2;
+               skb2 = skb_copy_expand(skb, 4, padlen, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       skb_push(skb, 4);
+       packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+       memcpy(skb->data, &packet_len, sizeof(packet_len));
+
+       if ((skb->len % 512) == 0) {
+               memcpy( skb->tail, &padbytes, sizeof(padbytes));
+               skb_put(skb, sizeof(padbytes));
+       }
+       return skb;
+}
+
+static void asix_status(struct usbnet *dev, struct urb *urb)
+{
+       struct ax88172_int_data *event;
+       int link;
+
+       if (urb->actual_length < 8)
+               return;
+
+       event = urb->transfer_buffer;
+       link = event->link & 0x01;
+       if (netif_carrier_ok(dev->net) != link) {
+               if (link) {
+                       netif_carrier_on(dev->net);
+                       usbnet_defer_kevent (dev, EVENT_LINK_RESET );
+               } else
+                       netif_carrier_off(dev->net);
+               devdbg(dev, "Link Status is: %d", link);
+       }
+}
+
 static inline int asix_set_sw_mii(struct usbnet *dev)
 {
        int ret;
        ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
        if (ret < 0)
-               devdbg(dev, "Failed to enable software MII access");
+               deverr(dev, "Failed to enable software MII access");
        return ret;
 }
 
@@ -175,24 +395,27 @@ static inline int asix_set_hw_mii(struct usbnet *dev)
        int ret;
        ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
        if (ret < 0)
-               devdbg(dev, "Failed to enable hardware MII access");
+               deverr(dev, "Failed to enable hardware MII access");
        return ret;
 }
 
-static inline int asix_get_phyid(struct usbnet *dev)
+static inline int asix_get_phy_addr(struct usbnet *dev)
 {
        int ret = 0;
        void *buf;
 
+       devdbg(dev, "asix_get_phy_addr()");
+
        buf = kmalloc(2, GFP_KERNEL);
        if (!buf)
                goto out1;
 
        if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
                                    0, 0, 2, buf)) < 2) {
-               devdbg(dev, "Error reading PHYID register: %02x", ret);
+               deverr(dev, "Error reading PHYID register: %02x", ret);
                goto out2;
        }
+       devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((u16 *)buf));
        ret = *((u8 *)buf + 1);
 out2:
        kfree(buf);
@@ -206,8 +429,29 @@ static int asix_sw_reset(struct usbnet *dev, u8 flags)
 
         ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
        if (ret < 0)
-               devdbg(dev,"Failed to send software reset: %02x", ret);
+               deverr(dev,"Failed to send software reset: %02x", ret);
+
+       return ret;
+}
 
+static u16 asix_read_rx_ctl(struct usbnet *dev)
+{
+       u16 ret = 0;
+       void *buf;
+
+       buf = kmalloc(2, GFP_KERNEL);
+       if (!buf)
+               goto out1;
+
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL,
+                                   0, 0, 2, buf)) < 2) {
+               deverr(dev, "Error reading RX_CTL register: %02x", ret);
+               goto out2;
+       }
+       ret = le16_to_cpu(*((u16 *)buf));
+out2:
+       kfree(buf);
+out1:
        return ret;
 }
 
@@ -215,82 +459,79 @@ static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
 {
        int ret;
 
+       devdbg(dev,"asix_write_rx_ctl() - mode = 0x%04x", mode);
        ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
        if (ret < 0)
-                devdbg(dev, "Failed to write RX_CTL mode: %02x", ret);
+               deverr(dev, "Failed to write RX_CTL mode to 0x%04x: %02x",
+                      mode, ret);
 
        return ret;
 }
 
-static void asix_status(struct usbnet *dev, struct urb *urb)
+static u16 asix_read_medium_status(struct usbnet *dev)
 {
-       struct ax88172_int_data *event;
-       int link;
+       u16 ret = 0;
+       void *buf;
 
-       if (urb->actual_length < 8)
-               return;
+       buf = kmalloc(2, GFP_KERNEL);
+       if (!buf)
+               goto out1;
 
-       event = urb->transfer_buffer;
-       link = event->link & 0x01;
-       if (netif_carrier_ok(dev->net) != link) {
-               if (link) {
-                       netif_carrier_on(dev->net);
-                       usbnet_defer_kevent (dev, EVENT_LINK_RESET );
-               } else
-                       netif_carrier_off(dev->net);
-               devdbg(dev, "Link Status is: %d", link);
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS,
+                                   0, 0, 2, buf)) < 2) {
+               deverr(dev, "Error reading Medium Status register: %02x", ret);
+               goto out2;
        }
+       ret = le16_to_cpu(*((u16 *)buf));
+out2:
+       kfree(buf);
+out1:
+       return ret;
 }
 
-static void
-asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-                                   u16 size, void *data)
+static int asix_write_medium_mode(struct usbnet *dev, u16 mode)
 {
-       struct usb_ctrlrequest *req;
-       int status;
-       struct urb *urb;
+       int ret;
 
-       if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
-               devdbg(dev, "Error allocating URB in write_cmd_async!");
-               return;
-       }
+       devdbg(dev,"asix_write_medium_mode() - mode = 0x%04x", mode);
+       ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       if (ret < 0)
+               deverr(dev, "Failed to write Medium Mode mode to 0x%04x: %02x",
+                       mode, ret);
 
-       if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
-               deverr(dev, "Failed to allocate memory for control request");
-               usb_free_urb(urb);
-               return;
-       }
+       return ret;
+}
 
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       req->bRequest = cmd;
-       req->wValue = cpu_to_le16(value);
-       req->wIndex = cpu_to_le16(index);
-       req->wLength = cpu_to_le16(size);
+static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
+{
+       int ret;
 
-       usb_fill_control_urb(urb, dev->udev,
-                            usb_sndctrlpipe(dev->udev, 0),
-                            (void *)req, data, size,
-                            asix_async_cmd_callback, req);
+       devdbg(dev,"asix_write_gpio() - value = 0x%04x", value);
+       ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
+       if (ret < 0)
+               deverr(dev, "Failed to write GPIO value 0x%04x: %02x",
+                       value, ret);
 
-       if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-               deverr(dev, "Error submitting the control message: status=%d",
-                               status);
-               kfree(req);
-               usb_free_urb(urb);
-       }
+       if (sleep)
+               msleep(sleep);
+
+       return ret;
 }
 
+/*
+ * AX88772 & AX88178 have a 16-bit RX_CTL value
+ */
 static void asix_set_multicast(struct net_device *net)
 {
        struct usbnet *dev = netdev_priv(net);
        struct asix_data *data = (struct asix_data *)&dev->data;
-       u8 rx_ctl = 0x8c;
+       u16 rx_ctl = AX_DEFAULT_RX_CTL;
 
        if (net->flags & IFF_PROMISC) {
-               rx_ctl |= 0x01;
+               rx_ctl |= AX_RX_CTL_PRO;
        } else if (net->flags & IFF_ALLMULTI
                   || net->mc_count > AX_MAX_MCAST) {
-               rx_ctl |= 0x02;
+               rx_ctl |= AX_RX_CTL_AMALL;
        } else if (net->mc_count == 0) {
                /* just broadcast and directed */
        } else {
@@ -317,7 +558,7 @@ static void asix_set_multicast(struct net_device *net)
                asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
                                   AX_MCAST_FILTER_SIZE, data->multi_filter);
 
-               rx_ctl |= 0x10;
+               rx_ctl |= AX_RX_CTL_AM;
        }
 
        asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
@@ -333,50 +574,43 @@ static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
                                (__u16)loc, 2, (u16 *)&res);
        asix_set_hw_mii(dev);
 
-       return res & 0xffff;
-}
+       devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff));
 
-/* same as above, but converts resulting value to cpu byte order */
-static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
-{
-       return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc));
+       return le16_to_cpu(res & 0xffff);
 }
 
 static void
 asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 {
        struct usbnet *dev = netdev_priv(netdev);
-       u16 res = val;
+       u16 res = cpu_to_le16(val);
 
+       devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val);
        asix_set_sw_mii(dev);
        asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
                                (__u16)loc, 2, (u16 *)&res);
        asix_set_hw_mii(dev);
 }
 
-/* same as above, but converts new value to le16 byte order before writing */
-static void
-asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
+static u32 asix_get_phyid(struct usbnet *dev)
 {
-       asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
-}
+       int phy_reg;
+       u32 phy_id;
 
-static int ax88172_link_reset(struct usbnet *dev)
-{
-       u16 lpa;
-       u16 adv;
-       u16 res;
-       u8 mode;
+       phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
+       if (phy_reg < 0)
+               return 0;
 
-       mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
-       lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-       adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
-       res = mii_nway_result(lpa|adv);
-       if (res & LPA_DUPLEX)
-               mode |= AX_MEDIUM_FULL_DUPLEX;
-       asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       phy_id = (phy_reg & 0xffff) << 16;
 
-       return 0;
+       phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
+       if (phy_reg < 0)
+               return 0;
+
+       phy_id |= (phy_reg & 0xffff);
+
+       return phy_id;
 }
 
 static void
@@ -423,7 +657,10 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 
 static int asix_get_eeprom_len(struct net_device *net)
 {
-       return AX_EEPROM_LEN;
+       struct usbnet *dev = netdev_priv(net);
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
+       return data->eeprom_len;
 }
 
 static int asix_get_eeprom(struct net_device *net,
@@ -453,9 +690,14 @@ static int asix_get_eeprom(struct net_device *net,
 static void asix_get_drvinfo (struct net_device *net,
                                 struct ethtool_drvinfo *info)
 {
+       struct usbnet *dev = netdev_priv(net);
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
        /* Inherit standard device info */
        usbnet_get_drvinfo(net, info);
-       info->eedump_len = 0x3e;
+       strncpy (info->driver, driver_name, sizeof info->driver);
+       strncpy (info->version, DRIVER_VERSION, sizeof info->version);
+       info->eedump_len = data->eeprom_len;
 }
 
 static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
@@ -468,17 +710,44 @@ static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
 static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
        struct usbnet *dev = netdev_priv(net);
+       int res = mii_ethtool_sset(&dev->mii,cmd);
+
+       /* link speed/duplex might have changed */
+       if (dev->driver_info->link_reset)
+               dev->driver_info->link_reset(dev);
 
-       return mii_ethtool_sset(&dev->mii,cmd);
+       return res;
 }
 
-/* We need to override some ethtool_ops so we require our
-   own structure so we don't interfere with other usbnet
-   devices that may be connected at the same time. */
-static struct ethtool_ops ax88172_ethtool_ops = {
-       .get_drvinfo            = asix_get_drvinfo,
-       .get_link               = ethtool_op_get_link,
-       .get_msglevel           = usbnet_get_msglevel,
+static int asix_nway_reset(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return mii_nway_restart(&dev->mii);
+}
+
+static u32 asix_get_link(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return mii_link_ok(&dev->mii);
+}
+
+static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+/* We need to override some ethtool_ops so we require our
+   own structure so we don't interfere with other usbnet
+   devices that may be connected at the same time. */
+static struct ethtool_ops ax88172_ethtool_ops = {
+       .get_drvinfo            = asix_get_drvinfo,
+       .get_link               = asix_get_link,
+       .nway_reset             = asix_nway_reset,
+       .get_msglevel           = usbnet_get_msglevel,
        .set_msglevel           = usbnet_set_msglevel,
        .get_wol                = asix_get_wol,
        .set_wol                = asix_set_wol,
@@ -488,11 +757,66 @@ static struct ethtool_ops ax88172_ethtool_ops = {
        .set_settings           = asix_set_settings,
 };
 
-static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static void ax88172_set_multicast(struct net_device *net)
 {
        struct usbnet *dev = netdev_priv(net);
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u8 rx_ctl = 0x8c;
 
-       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+       if (net->flags & IFF_PROMISC) {
+               rx_ctl |= 0x01;
+       } else if (net->flags & IFF_ALLMULTI
+                  || net->mc_count > AX_MAX_MCAST) {
+               rx_ctl |= 0x02;
+       } else if (net->mc_count == 0) {
+               /* just broadcast and directed */
+       } else {
+               /* We use the 20 byte dev->data
+                * for our 8 byte filter buffer
+                * to avoid allocating memory that
+                * is tricky to free later */
+               struct dev_mc_list *mc_list = net->mc_list;
+               u32 crc_bits;
+               int i;
+
+               memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+
+               /* Build the multicast hash filter. */
+               for (i = 0; i < net->mc_count; i++) {
+                       crc_bits =
+                           ether_crc(ETH_ALEN,
+                                     mc_list->dmi_addr) >> 26;
+                       data->multi_filter[crc_bits >> 3] |=
+                           1 << (crc_bits & 7);
+                       mc_list = mc_list->next;
+               }
+
+               asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+                                  AX_MCAST_FILTER_SIZE, data->multi_filter);
+
+               rx_ctl |= 0x10;
+       }
+
+       asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+}
+
+static int ax88172_link_reset(struct usbnet *dev)
+{
+       u8 mode;
+       struct ethtool_cmd ecmd;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = AX88172_MEDIUM_DEFAULT;
+
+       if (ecmd.duplex != DUPLEX_FULL)
+               mode |= ~AX88172_MEDIUM_FD;
+
+       devdbg(dev, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+       asix_write_medium_mode(dev, mode);
+
+       return 0;
 }
 
 static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -501,6 +825,9 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
        void *buf;
        int i;
        unsigned long gpio_bits = dev->driver_info->data;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
+       data->eeprom_len = AX88172_EEPROM_LEN;
 
        usbnet_get_endpoints(dev,intf);
 
@@ -519,12 +846,12 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
                msleep(5);
        }
 
-       if ((ret = asix_write_rx_ctl(dev,0x80)) < 0)
+       if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0)
                goto out2;
 
        /* Get the MAC address */
        memset(buf, 0, ETH_ALEN);
-       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+       if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID,
                                0, 0, 6, buf)) < 0) {
                dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
                goto out2;
@@ -537,14 +864,14 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->mii.mdio_write = asix_mdio_write;
        dev->mii.phy_id_mask = 0x3f;
        dev->mii.reg_num_mask = 0x1f;
-       dev->mii.phy_id = asix_get_phyid(dev);
+       dev->mii.phy_id = asix_get_phy_addr(dev);
        dev->net->do_ioctl = asix_ioctl;
 
-       dev->net->set_multicast_list = asix_set_multicast;
+       dev->net->set_multicast_list = ax88172_set_multicast;
        dev->net->ethtool_ops = &ax88172_ethtool_ops;
 
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
        mii_nway_restart(&dev->mii);
 
@@ -557,7 +884,8 @@ out1:
 
 static struct ethtool_ops ax88772_ethtool_ops = {
        .get_drvinfo            = asix_get_drvinfo,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = asix_get_link,
+       .nway_reset             = asix_nway_reset,
        .get_msglevel           = usbnet_get_msglevel,
        .set_msglevel           = usbnet_set_msglevel,
        .get_wol                = asix_get_wol,
@@ -568,10 +896,37 @@ static struct ethtool_ops ax88772_ethtool_ops = {
        .set_settings           = asix_set_settings,
 };
 
+static int ax88772_link_reset(struct usbnet *dev)
+{
+       u16 mode;
+       struct ethtool_cmd ecmd;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = AX88772_MEDIUM_DEFAULT;
+
+       if (ecmd.speed != SPEED_100)
+               mode &= ~AX_MEDIUM_PS;
+
+       if (ecmd.duplex != DUPLEX_FULL)
+               mode &= ~AX_MEDIUM_FD;
+
+       devdbg(dev, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+       asix_write_medium_mode(dev, mode);
+
+       return 0;
+}
+
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
        void *buf;
+       u16 rx_ctl;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u32 phyid;
+
+       data->eeprom_len = AX88772_EEPROM_LEN;
 
        usbnet_get_endpoints(dev,intf);
 
@@ -582,13 +937,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                goto out1;
        }
 
-       if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
-                                    0x00B0, 0, 0, buf)) < 0)
+       if ((ret = asix_write_gpio(dev,
+                       AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
                goto out2;
 
-       msleep(5);
        if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
-                               0x0001, 0, 0, buf)) < 0) {
+                               0x0000, 0, 0, buf)) < 0) {
                dbg("Select PHY #1 failed: %d", ret);
                goto out2;
        }
@@ -605,36 +959,34 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                goto out2;
 
        msleep(150);
-       if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0)
+       rx_ctl = asix_read_rx_ctl(dev);
+       dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
+       if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0)
                goto out2;
 
+       rx_ctl = asix_read_rx_ctl(dev);
+       dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
+
        /* Get the MAC address */
        memset(buf, 0, ETH_ALEN);
-       if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
                                0, 0, ETH_ALEN, buf)) < 0) {
                dbg("Failed to read MAC address: %d", ret);
                goto out2;
        }
        memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-       if ((ret = asix_set_sw_mii(dev)) < 0)
-               goto out2;
-
-       if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG,
-                               0x0010, 2, 2, buf)) < 0)
-                       || (*((u16 *)buf) != 0x003b)) {
-               dbg("Read PHY register 2 must be 0x3b00: %d", ret);
-               goto out2;
-       }
-
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = asix_mdio_read;
        dev->mii.mdio_write = asix_mdio_write;
-       dev->mii.phy_id_mask = 0xff;
-       dev->mii.reg_num_mask = 0xff;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0x1f;
        dev->net->do_ioctl = asix_ioctl;
-       dev->mii.phy_id = asix_get_phyid(dev);
+       dev->mii.phy_id = asix_get_phy_addr(dev);
+
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
 
        if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
                goto out2;
@@ -649,16 +1001,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->set_multicast_list = asix_set_multicast;
        dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                        ADVERTISE_ALL | ADVERTISE_CSMA);
        mii_nway_restart(&dev->mii);
 
-       if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
-                               AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
-               dbg("Write medium mode register: %d", ret);
+       if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0)
                goto out2;
-       }
 
        if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
                                AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
@@ -666,13 +1015,17 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
                goto out2;
        }
-       if ((ret = asix_set_hw_mii(dev)) < 0)
-               goto out2;
 
        /* Set RX_CTL to default values with 2k buffer, and enable cactus */
-       if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0)
+       if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
                goto out2;
 
+       rx_ctl = asix_read_rx_ctl(dev);
+       dbg("RX_CTL is 0x%04x after all initializations", rx_ctl);
+
+       rx_ctl = asix_read_medium_status(dev);
+       dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
+
        kfree(buf);
 
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
@@ -690,120 +1043,285 @@ out1:
        return ret;
 }
 
-static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+static struct ethtool_ops ax88178_ethtool_ops = {
+       .get_drvinfo            = asix_get_drvinfo,
+       .get_link               = asix_get_link,
+       .nway_reset             = asix_nway_reset,
+       .get_msglevel           = usbnet_get_msglevel,
+       .set_msglevel           = usbnet_set_msglevel,
+       .get_wol                = asix_get_wol,
+       .set_wol                = asix_set_wol,
+       .get_eeprom_len         = asix_get_eeprom_len,
+       .get_eeprom             = asix_get_eeprom,
+       .get_settings           = asix_get_settings,
+       .set_settings           = asix_set_settings,
+};
+
+static int marvell_phy_init(struct usbnet *dev)
 {
-       u8  *head;
-       u32  header;
-       char *packet;
-       struct sk_buff *ax_skb;
-       u16 size;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u16 reg;
 
-       head = (u8 *) skb->data;
-       memcpy(&header, head, sizeof(header));
-       le32_to_cpus(&header);
-       packet = head + sizeof(header);
+       devdbg(dev,"marvell_phy_init()");
 
-       skb_pull(skb, 4);
+       reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS);
+       devdbg(dev,"MII_MARVELL_STATUS = 0x%04x", reg);
 
-       while (skb->len > 0) {
-               if ((short)(header & 0x0000ffff) !=
-                   ~((short)((header & 0xffff0000) >> 16))) {
-                       devdbg(dev,"header length data is error");
-               }
-               /* get the packet length */
-               size = (u16) (header & 0x0000ffff);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL,
+                       MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY);
 
-               if ((skb->len) - ((size + 1) & 0xfffe) == 0)
-                       return 2;
-               if (size > ETH_FRAME_LEN) {
-                       devdbg(dev,"invalid rx length %d", size);
-                       return 0;
-               }
-               ax_skb = skb_clone(skb, GFP_ATOMIC);
-               if (ax_skb) {
-                       ax_skb->len = size;
-                       ax_skb->data = packet;
-                       ax_skb->tail = packet + size;
-                       usbnet_skb_return(dev, ax_skb);
-               } else {
-                       return 0;
-               }
+       if (data->ledmode) {
+               reg = asix_mdio_read(dev->net, dev->mii.phy_id,
+                       MII_MARVELL_LED_CTRL);
+               devdbg(dev,"MII_MARVELL_LED_CTRL (1) = 0x%04x", reg);
 
-               skb_pull(skb, (size + 1) & 0xfffe);
+               reg &= 0xf8ff;
+               reg |= (1 + 0x0100);
+               asix_mdio_write(dev->net, dev->mii.phy_id,
+                       MII_MARVELL_LED_CTRL, reg);
 
-               if (skb->len == 0)
-                       break;
+               reg = asix_mdio_read(dev->net, dev->mii.phy_id,
+                       MII_MARVELL_LED_CTRL);
+               devdbg(dev,"MII_MARVELL_LED_CTRL (2) = 0x%04x", reg);
+               reg &= 0xfc0f;
+       }
 
-               head = (u8 *) skb->data;
-               memcpy(&header, head, sizeof(header));
-               le32_to_cpus(&header);
-               packet = head + sizeof(header);
-               skb_pull(skb, 4);
+       return 0;
+}
+
+static int marvell_led_status(struct usbnet *dev, u16 speed)
+{
+       u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL);
+
+       devdbg(dev, "marvell_led_status() read 0x%04x", reg);
+
+       /* Clear out the center LED bits - 0x03F0 */
+       reg &= 0xfc0f;
+
+       switch (speed) {
+               case SPEED_1000:
+                       reg |= 0x03e0;
+                       break;
+               case SPEED_100:
+                       reg |= 0x03b0;
+                       break;
+               default:
+                       reg |= 0x02f0;
        }
 
-       if (skb->len < 0) {
-               devdbg(dev,"invalid rx length %d", skb->len);
-               return 0;
+       devdbg(dev, "marvell_led_status() writing 0x%04x", reg);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg);
+
+       return 0;
+}
+
+static int ax88178_link_reset(struct usbnet *dev)
+{
+       u16 mode;
+       struct ethtool_cmd ecmd;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
+       devdbg(dev,"ax88178_link_reset()");
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = AX88178_MEDIUM_DEFAULT;
+
+       if (ecmd.speed == SPEED_1000)
+               mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
+       else if (ecmd.speed == SPEED_100)
+               mode |= AX_MEDIUM_PS;
+       else
+               mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
+
+       if (ecmd.duplex == DUPLEX_FULL)
+               mode |= AX_MEDIUM_FD;
+       else
+               mode &= ~AX_MEDIUM_FD;
+
+       devdbg(dev, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+       asix_write_medium_mode(dev, mode);
+
+       if (data->phymode == PHY_MODE_MARVELL && data->ledmode)
+               marvell_led_status(dev, ecmd.speed);
+
+       return 0;
+}
+
+static void ax88178_set_mfb(struct usbnet *dev)
+{
+       u16 mfb = AX_RX_CTL_MFB_16384;
+       u16 rxctl;
+       u16 medium;
+       int old_rx_urb_size = dev->rx_urb_size;
+
+       if (dev->hard_mtu < 2048) {
+               dev->rx_urb_size = 2048;
+               mfb = AX_RX_CTL_MFB_2048;
+       } else if (dev->hard_mtu < 4096) {
+               dev->rx_urb_size = 4096;
+               mfb = AX_RX_CTL_MFB_4096;
+       } else if (dev->hard_mtu < 8192) {
+               dev->rx_urb_size = 8192;
+               mfb = AX_RX_CTL_MFB_8192;
+       } else if (dev->hard_mtu < 16384) {
+               dev->rx_urb_size = 16384;
+               mfb = AX_RX_CTL_MFB_16384;
        }
-       return 1;
+
+       rxctl = asix_read_rx_ctl(dev);
+       asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb);
+
+       medium = asix_read_medium_status(dev);
+       if (dev->net->mtu > 1500)
+               medium |= AX_MEDIUM_JFE;
+       else
+               medium &= ~AX_MEDIUM_JFE;
+       asix_write_medium_mode(dev, medium);
+
+       if (dev->rx_urb_size > old_rx_urb_size)
+               usbnet_unlink_rx_urbs(dev);
 }
 
-static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-                                       gfp_t flags)
+static int ax88178_change_mtu(struct net_device *net, int new_mtu)
 {
-       int padlen;
-       int headroom = skb_headroom(skb);
-       int tailroom = skb_tailroom(skb);
-       u32 packet_len;
-       u32 padbytes = 0xffff0000;
+       struct usbnet *dev = netdev_priv(net);
+       int ll_mtu = new_mtu + net->hard_header_len + 4;
 
-       padlen = ((skb->len + 4) % 512) ? 0 : 4;
+       devdbg(dev, "ax88178_change_mtu() new_mtu=%d", new_mtu);
 
-       if ((!skb_cloned(skb))
-           && ((headroom + tailroom) >= (4 + padlen))) {
-               if ((headroom < 4) || (tailroom < padlen)) {
-                       skb->data = memmove(skb->head + 4, skb->data, skb->len);
-                       skb->tail = skb->data + skb->len;
-               }
+       if (new_mtu <= 0 || ll_mtu > 16384)
+               return -EINVAL;
+
+       if ((ll_mtu % dev->maxpacket) == 0)
+               return -EDOM;
+
+       net->mtu = new_mtu;
+       dev->hard_mtu = net->mtu + net->hard_header_len;
+       ax88178_set_mfb(dev);
+
+       return 0;
+}
+
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       int ret;
+       void *buf;
+       u16 eeprom;
+       int gpio0 = 0;
+       u32 phyid;
+
+       usbnet_get_endpoints(dev,intf);
+
+       buf = kmalloc(6, GFP_KERNEL);
+       if(!buf) {
+               dbg ("Cannot allocate memory for buffer");
+               ret = -ENOMEM;
+               goto out1;
+       }
+
+       eeprom = 0;
+       asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &eeprom);
+       dbg("GPIO Status: 0x%04x", eeprom);
+
+       asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
+       asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
+       asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
+
+       dbg("EEPROM index 0x17 is 0x%04x", eeprom);
+
+       if (eeprom == 0xffff) {
+               data->phymode = PHY_MODE_MARVELL;
+               data->ledmode = 0;
+               gpio0 = 1;
        } else {
-               struct sk_buff *skb2;
-               skb2 = skb_copy_expand(skb, 4, padlen, flags);
-               dev_kfree_skb_any(skb);
-               skb = skb2;
-               if (!skb)
-                       return NULL;
+               data->phymode = eeprom & 7;
+               data->ledmode = eeprom >> 8;
+               gpio0 = (eeprom & 0x80) ? 0 : 1;
        }
+       dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
 
-       skb_push(skb, 4);
-       packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-       memcpy(skb->data, &packet_len, sizeof(packet_len));
+       asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
+       if ((eeprom >> 8) != 1) {
+               asix_write_gpio(dev, 0x003c, 30);
+               asix_write_gpio(dev, 0x001c, 300);
+               asix_write_gpio(dev, 0x003c, 30);
+       } else {
+               dbg("gpio phymode == 1 path");
+               asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
+               asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
+       }
 
-       if ((skb->len % 512) == 0) {
-               memcpy( skb->tail, &padbytes, sizeof(padbytes));
-               skb_put(skb, sizeof(padbytes));
+       asix_sw_reset(dev, 0);
+       msleep(150);
+
+       asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
+       msleep(150);
+
+       asix_write_rx_ctl(dev, 0);
+
+       /* Get the MAC address */
+       memset(buf, 0, ETH_ALEN);
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+                               0, 0, ETH_ALEN, buf)) < 0) {
+               dbg("Failed to read MAC address: %d", ret);
+               goto out2;
        }
-       return skb;
-}
+       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-static int ax88772_link_reset(struct usbnet *dev)
-{
-       u16 lpa;
-       u16 adv;
-       u16 res;
-       u16 mode;
+       /* Initialize MII structure */
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = asix_mdio_read;
+       dev->mii.mdio_write = asix_mdio_write;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0xff;
+       dev->mii.supports_gmii = 1;
+       dev->net->do_ioctl = asix_ioctl;
+       dev->mii.phy_id = asix_get_phy_addr(dev);
+       dev->net->set_multicast_list = asix_set_multicast;
+       dev->net->ethtool_ops = &ax88178_ethtool_ops;
+       dev->net->change_mtu = &ax88178_change_mtu;
 
-       mode = AX88772_MEDIUM_DEFAULT;
-       lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-       adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
-       res = mii_nway_result(lpa|adv);
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
 
-       if ((res & LPA_DUPLEX) == 0)
-               mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
-       if ((res & LPA_100) == 0)
-               mode &= ~AX88772_MEDIUM_100MB;
-       asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       if (data->phymode == PHY_MODE_MARVELL) {
+               marvell_phy_init(dev);
+               msleep(60);
+       }
+
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+                       BMCR_RESET | BMCR_ANENABLE);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+                       ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+                       ADVERTISE_1000FULL);
+
+       mii_nway_restart(&dev->mii);
+
+       if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0)
+               goto out2;
+
+       if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
+               goto out2;
+
+       kfree(buf);
+
+       /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+       if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+               /* hard_mtu  is still the default - the device does not support
+                  jumbo eth frames */
+               dev->rx_urb_size = 2048;
+       }
 
        return 0;
+
+out2:
+       kfree(buf);
+out1:
+       return ret;
 }
 
 static const struct driver_info ax8817x_info = {
@@ -853,8 +1371,19 @@ static const struct driver_info ax88772_info = {
        .link_reset = ax88772_link_reset,
        .reset = ax88772_link_reset,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-       .rx_fixup = ax88772_rx_fixup,
-       .tx_fixup = ax88772_tx_fixup,
+       .rx_fixup = asix_rx_fixup,
+       .tx_fixup = asix_tx_fixup,
+};
+
+static const struct driver_info ax88178_info = {
+       .description = "ASIX AX88178 USB 2.0 Ethernet",
+       .bind = ax88178_bind,
+       .status = asix_status,
+       .link_reset = ax88178_link_reset,
+       .reset = ax88178_link_reset,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = asix_rx_fixup,
+       .tx_fixup = asix_tx_fixup,
 };
 
 static const struct usb_device_id      products [] = {
@@ -913,7 +1442,7 @@ static const struct usb_device_id  products [] = {
 }, {
        // ASIX AX88178 10/100/1000
        USB_DEVICE (0x0b95, 0x1780),
-       .driver_info = (unsigned long) &ax88772_info,
+       .driver_info = (unsigned long) &ax88178_info,
 }, {
        // Linksys USB200M Rev 2
        USB_DEVICE (0x13b1, 0x0018),
@@ -922,6 +1451,18 @@ static const struct usb_device_id products [] = {
        // 0Q0 cable ethernet
        USB_DEVICE (0x1557, 0x7720),
        .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // DLink DUB-E100 H/W Ver B1
+       USB_DEVICE (0x07d1, 0x3c05),
+       .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // DLink DUB-E100 H/W Ver B1 Alternate
+       USB_DEVICE (0x2001, 0x3c05),
+       .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // Linksys USB1000
+       USB_DEVICE (0x1737, 0x0039),
+       .driver_info = (unsigned long) &ax88178_info,
 },
        { },            // END
 };
index def3bb8e22901509bf35b618d14fb3402f8a2f43..544d41fe9b9261fb5ad2740e3ecba447cd662bf1 100644 (file)
@@ -165,6 +165,7 @@ static struct usb_device_id usb_klsi_table[] = {
        { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
        { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
        { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
+       { USB_DEVICE(0x1668, 0x0323) }, /* Actiontec USB Ethernet */
        { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
        {} /* Null terminator */
 };
index a9b6eeac3e3fa5da89949bca70990f2258c3e279..301baa72bac7b4ed20859a4fe64b97dfd545a9b4 100644 (file)
@@ -498,25 +498,24 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *
 net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
-       int                     padlen;
        struct sk_buff          *skb2;
        struct nc_header        *header = NULL;
        struct nc_trailer       *trailer = NULL;
+       int                     padlen = sizeof (struct nc_trailer);
        int                     len = skb->len;
 
-       padlen = ((len + sizeof (struct nc_header)
-                       + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+       if (!((len + padlen + sizeof (struct nc_header)) & 0x01))
+               padlen++;
        if (!skb_cloned(skb)) {
                int     headroom = skb_headroom(skb);
                int     tailroom = skb_tailroom(skb);
 
-               if ((padlen + sizeof (struct nc_trailer)) <= tailroom
-                           && sizeof (struct nc_header) <= headroom)
+               if (padlen <= tailroom &&
+                   sizeof(struct nc_header) <= headroom)
                        /* There's enough head and tail room */
                        goto encapsulate;
 
-               if ((sizeof (struct nc_header) + padlen
-                                       + sizeof (struct nc_trailer)) <
+               if ((sizeof (struct nc_header) + padlen) <
                                (headroom + tailroom)) {
                        /* There's enough total room, so just readjust */
                        skb->data = memmove(skb->head
@@ -530,7 +529,7 @@ net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
        /* Create a new skb to use with the correct size */
        skb2 = skb_copy_expand(skb,
                                sizeof (struct nc_header),
-                               sizeof (struct nc_trailer) + padlen,
+                               padlen,
                                flags);
        dev_kfree_skb_any(skb);
        if (!skb2)
index ab21f960d255f250c01f43912744103ab73cd03f..918cf5a77c08208f99e89aeede993397413d2129 100644 (file)
@@ -45,7 +45,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
+#define DRIVER_VERSION "v0.6.14 (2006/09/27)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -339,7 +339,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
        }
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
 
        return ret;
 }
@@ -376,7 +376,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
 
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
        return -ETIMEDOUT;
 }
 
@@ -413,7 +413,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
        return -ETIMEDOUT;
 }
 
@@ -461,7 +461,7 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
                return ret;
 fail:
        if (netif_msg_drv(pegasus))
-               dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
+               dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__);
        return -ETIMEDOUT;
 }
 #endif                         /* PEGASUS_WRITE_EEPROM */
@@ -481,8 +481,12 @@ static void set_ethernet_addr(pegasus_t * pegasus)
 {
        __u8 node_id[6];
 
-       get_node_id(pegasus, node_id);
-       set_registers(pegasus, EthID, sizeof (node_id), node_id);
+       if (pegasus->features & PEGASUS_II) {
+               get_registers(pegasus, 0x10, sizeof(node_id), node_id);
+       } else {
+               get_node_id(pegasus, node_id);
+               set_registers(pegasus, EthID, sizeof (node_id), node_id);
+       }
        memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
 }
 
@@ -619,7 +623,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
        switch (urb->status) {
        case 0:
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                if (netif_msg_rx_err(pegasus))
                        pr_debug("%s: reset MAC\n", net->name);
                pegasus->flags &= ~PEGASUS_RX_BUSY;
index a72685b96061dfb862a85aa8368e7758ce227089..2364c20993874f381c4975430000a56fb8a4a9a4 100644 (file)
@@ -438,7 +438,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
                break;
        case -ENOENT:
                return; /* the urb is in unlink state */
-       case -ETIMEDOUT:
+       case -ETIME:
                warn("may be reset is needed?..");
                goto goon;
        default:
index 54183e173a6d9a071b30609ab744490b08061243..98a522f1e264412bc7b15971aee924125930eedd 100644 (file)
  * let the USB host controller be busy for 5msec or more before an irq
  * is required, under load.  Jumbograms change the equation.
  */
-#define        RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
-#define        TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
+#define RX_MAX_QUEUE_MEMORY (60 * 1518)
+#define        RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+                       (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
+#define        TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+                       (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
 
 // reawaken network queue this soon after stopping; else watchdog barks
 #define TX_TIMEOUT_JIFFIES     (5*HZ)
@@ -227,13 +230,23 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
 {
        struct usbnet   *dev = netdev_priv(net);
        int             ll_mtu = new_mtu + net->hard_header_len;
+       int             old_hard_mtu = dev->hard_mtu;
+       int             old_rx_urb_size = dev->rx_urb_size;
 
-       if (new_mtu <= 0 || ll_mtu > dev->hard_mtu)
+       if (new_mtu <= 0)
                return -EINVAL;
        // no second zero-length packet read wanted after mtu-sized packets
        if ((ll_mtu % dev->maxpacket) == 0)
                return -EDOM;
        net->mtu = new_mtu;
+
+       dev->hard_mtu = net->mtu + net->hard_header_len;
+       if (dev->rx_urb_size == old_hard_mtu) {
+               dev->rx_urb_size = dev->hard_mtu;
+               if (dev->rx_urb_size > old_rx_urb_size)
+                       usbnet_unlink_rx_urbs(dev);
+       }
+
        return 0;
 }
 
@@ -412,9 +425,9 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
            // we get controller i/o faults during khubd disconnect() delays.
            // throttle down resubmits, to avoid log floods; just temporarily,
            // so we still recover when the fault isn't a khubd delay.
-           case -EPROTO:               // ehci
-           case -ETIMEDOUT:            // ohci
-           case -EILSEQ:               // uhci
+           case -EPROTO:
+           case -ETIME:
+           case -EILSEQ:
                dev->stats.rx_errors++;
                if (!timer_pending (&dev->delay)) {
                        mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -521,6 +534,17 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
        return count;
 }
 
+// Flush all pending rx urbs
+// minidrivers may need to do this when the MTU changes
+
+void usbnet_unlink_rx_urbs(struct usbnet *dev)
+{
+       if (netif_running(dev->net)) {
+               (void) unlink_urbs (dev, &dev->rxq);
+               tasklet_schedule(&dev->bh);
+       }
+}
+EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
 
 /*-------------------------------------------------------------------------*/
 
@@ -629,7 +653,7 @@ static int usbnet_open (struct net_device *net)
 
                devinfo (dev, "open: enable queueing "
                                "(rx %d, tx %d) mtu %d %s framing",
-                       RX_QLEN (dev), TX_QLEN (dev), dev->net->mtu,
+                       (int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu,
                        framing);
        }
 
@@ -797,9 +821,9 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
 
                // like rx, tx gets controller i/o faults during khubd delays
                // and so it uses the same throttling mechanism.
-               case -EPROTO:           // ehci
-               case -ETIMEDOUT:        // ohci
-               case -EILSEQ:           // uhci
+               case -EPROTO:
+               case -ETIME:
+               case -EILSEQ:
                        if (!timer_pending (&dev->delay)) {
                                mod_timer (&dev->delay,
                                        jiffies + THROTTLE_JIFFIES);
index 89fc4958eecf81f72c5f93128d5994168b7f3c43..c0746f0454afe277e4d970e81f6f36ea48305b25 100644 (file)
@@ -166,6 +166,7 @@ struct skb_data {   /* skb->cb is one of these */
 extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *);
 extern void usbnet_defer_kevent (struct usbnet *, int);
 extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
+extern void usbnet_unlink_rx_urbs(struct usbnet *);
 
 extern u32 usbnet_get_msglevel (struct net_device *);
 extern void usbnet_set_msglevel (struct net_device *, u32);
index f5b9438c94f0f29bd35392906b59759420ebad44..5076b9d97057aee810faf064414485eec2f475e9 100644 (file)
@@ -53,6 +53,15 @@ config USB_SERIAL_GENERIC
          support" be compiled as a module for this driver to be used
          properly.
 
+config USB_SERIAL_AIRCABLE
+       tristate "AIRcable USB Bluetooth Dongle Driver (EXPERIMENTAL)"
+       depends on USB_SERIAL && EXPERIMENTAL
+       help
+           Say Y here if you want to use AIRcable USB Bluetoot Dongle.
+
+           To compile this driver as a module, choose M here: the module
+           will be called aircable.
+
 config USB_SERIAL_AIRPRIME
        tristate "USB AirPrime CDMA Wireless Driver"
        depends on USB_SERIAL
@@ -413,6 +422,21 @@ config USB_SERIAL_MCT_U232
          To compile this driver as a module, choose M here: the
          module will be called mct_u232.
 
+config USB_SERIAL_MOS7840
+       tristate "USB Moschip 7840/7820 USB Serial Driver"
+       depends on USB_SERIAL
+       ---help---
+         Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
+         Dual-Serial port device from MosChip Semiconductor.
+
+         The MCS7840 and MCS7820 have been developed to connect a wide range
+         of standard serial devices to a USB host.  The MCS7840 has a USB
+         device controller connected to four (4) individual UARTs while the
+         MCS7820 controller connects to two (2) individual UARTs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mos7840.  If unsure, choose N.
+
 config USB_SERIAL_NAVMAN
        tristate "USB Navman GPS device"
        depends on USB_SERIAL
@@ -526,5 +550,6 @@ config USB_EZUSB
        depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
        default y
 
+
 endmenu
 
index 8efed2ce1ba38260f97968b4c9c9e84f86fbf491..8dce83340e3109aa655d84512524f82510fe48cf 100644 (file)
@@ -11,6 +11,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB)             += ezusb.o
 
 usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
 
+obj-$(CONFIG_USB_SERIAL_AIRCABLE)              += aircable.o
 obj-$(CONFIG_USB_SERIAL_AIRPRIME)              += airprime.o
 obj-$(CONFIG_USB_SERIAL_ARK3116)               += ark3116.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)                        += belkin_sa.o
@@ -33,6 +34,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)          += keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_KLSI)                  += kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)             += kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)              += mct_u232.o
+obj-$(CONFIG_USB_SERIAL_MOS7840)               += mos7840.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)                        += navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)                        += option.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
new file mode 100644 (file)
index 0000000..2ccd9de
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * AIRcable USB Bluetooth Dongle Driver.
+ *
+ * Copyright (C) 2006 Manuel Francisco Naranjo (naranjo.manuel@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.
+ *
+ * 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
+ * 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.
+ *
+ * The device simply need some stuff to understand data comming from the usb
+ * 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 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,
+ * if there is data coming that does not contain any header, then that is data
+ * that must go directly to the tty, as there is no documentation about if there
+ * is any other control code, I will simply check for the first
+ * one.
+ *
+ * The driver registers himself with the USB-serial core and the USB Core. I had
+ * to implement a probe function agains USB-serial, because other way, the
+ * driver was attaching himself to both interfaces. I have tryed with different
+ * configurations of usb_serial_driver with out exit, only the probe function
+ * could handle this correctly.
+ *
+ * I have taken some info from a Greg Kroah-Hartman article:
+ * http://www.linuxjournal.com/article/6573
+ * And from Linux Device Driver Kit CD, which is a great work, the authors taken
+ * the work to recompile lots of information an knowladge in drivers development
+ * and made it all avaible inside a cd.
+ * URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/
+ *
+ */
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/circ_buf.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static int debug;
+
+/* Vendor and Product ID */
+#define AIRCABLE_VID           0x16CA
+#define AIRCABLE_USB_PID       0x1502
+
+/* write buffer size defines */
+#define AIRCABLE_BUF_SIZE      2048
+
+/* Protocol Stuff */
+#define HCI_HEADER_LENGTH      0x4
+#define TX_HEADER_0            0x20
+#define TX_HEADER_1            0x29
+#define RX_HEADER_0            0x00
+#define RX_HEADER_1            0x20
+#define MAX_HCI_FRAMESIZE      60
+#define HCI_COMPLETE_FRAME     64
+
+/* rx_flags */
+#define THROTTLED              0x01
+#define ACTUALLY_THROTTLED     0x02
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0b2"
+#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>"
+#define DRIVER_DESC "AIRcable USB Driver"
+
+/* ID table that will be registered with USB core */
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+
+/* Internal Structure */
+struct aircable_private {
+       spinlock_t rx_lock;             /* spinlock for the receive lines */
+       struct circ_buf *tx_buf;        /* write buffer */
+       struct circ_buf *rx_buf;        /* read buffer */
+       int rx_flags;                   /* for throttilng */
+       struct work_struct rx_work;     /* work cue for the receiving line */
+};
+
+/* Private methods */
+
+/* Circular Buffer Methods, code from ti_usb_3410_5052 used */
+/*
+ * serial_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void serial_buf_clear(struct circ_buf *cb)
+{
+       cb->head = cb->tail = 0;
+}
+
+/*
+ * serial_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct circ_buf *serial_buf_alloc(void)
+{
+       struct circ_buf *cb;
+       cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+       if (cb == NULL)
+               return NULL;
+       cb->buf = kmalloc(AIRCABLE_BUF_SIZE, GFP_KERNEL);
+       if (cb->buf == NULL) {
+               kfree(cb);
+               return NULL;
+       }
+       serial_buf_clear(cb);
+       return cb;
+}
+
+/*
+ * serial_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void serial_buf_free(struct circ_buf *cb)
+{
+       kfree(cb->buf);
+       kfree(cb);
+}
+
+/*
+ * serial_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static int serial_buf_data_avail(struct circ_buf *cb)
+{
+       return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE);
+}
+
+/*
+ * serial_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static int serial_buf_put(struct circ_buf *cb, const char *buf, int count)
+{
+       int c, ret = 0;
+       while (1) {
+               c = CIRC_SPACE_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+               if (count < c)
+                       c = count;
+               if (c <= 0)
+                       break;
+               memcpy(cb->buf + cb->head, buf, c);
+               cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1);
+               buf += c;
+               count -= c;
+               ret= c;
+       }
+       return ret;
+}
+
+/*
+ * serial_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static int serial_buf_get(struct circ_buf *cb, char *buf, int count)
+{
+       int c, ret = 0;
+       while (1) {
+               c = CIRC_CNT_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+               if (count < c)
+                       c = count;
+               if (c <= 0)
+                       break;
+               memcpy(buf, cb->buf + cb->tail, c);
+               cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1);
+               buf += c;
+               count -= c;
+               ret= c;
+       }
+       return ret;
+}
+
+/* End of circula buffer methods */
+
+static void aircable_send(struct usb_serial_port *port)
+{
+       int count, result;
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       unsigned char* buf;
+       dbg("%s - port %d", __FUNCTION__, port->number);
+       if (port->write_urb_busy)
+               return;
+
+       count = min(serial_buf_data_avail(priv->tx_buf), MAX_HCI_FRAMESIZE);
+       if (count == 0)
+               return;
+
+       buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
+       if (!buf) {
+               err("%s- kzalloc(%d) failed.", __FUNCTION__,
+                   count + HCI_HEADER_LENGTH);
+               return;
+       }
+
+       buf[0] = TX_HEADER_0;
+       buf[1] = TX_HEADER_1;
+       buf[2] = (unsigned char)count;
+       buf[3] = (unsigned char)(count >> 8);
+       serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
+
+       memcpy(port->write_urb->transfer_buffer, buf,
+              count + HCI_HEADER_LENGTH);
+
+       kfree(buf);
+       port->write_urb_busy = 1;
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                             count + HCI_HEADER_LENGTH,
+                             port->write_urb->transfer_buffer);
+       port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH;
+       port->write_urb->dev = port->serial->dev;
+       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+
+       if (result) {
+               dev_err(&port->dev,
+                       "%s - failed submitting write urb, error %d\n",
+                       __FUNCTION__, result);
+               port->write_urb_busy = 0;
+       }
+
+       schedule_work(&port->work);
+}
+
+static void aircable_read(void *params)
+{
+       struct usb_serial_port *port = params;
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       struct tty_struct *tty;
+       unsigned char *data;
+       int count;
+       if (priv->rx_flags & THROTTLED){
+               if (priv->rx_flags & ACTUALLY_THROTTLED)
+                       schedule_work(&priv->rx_work);
+               return;
+       }
+
+       /* By now I will flush data to the tty in packages of no more than
+        * 64 bytes, to ensure I do not get throttled.
+        * Ask USB mailing list for better aproach.
+        */
+       tty = port->tty;
+
+       if (!tty)
+               schedule_work(&priv->rx_work);
+
+       count = min(64, serial_buf_data_avail(priv->rx_buf));
+
+       if (count <= 0)
+               return; //We have finished sending everything.
+
+       tty_prepare_flip_string(tty, &data, count);
+       if (!data){
+               err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
+               return;
+       }
+
+       serial_buf_get(priv->rx_buf, data, count);
+
+       tty_flip_buffer_push(tty);
+
+       if (serial_buf_data_avail(priv->rx_buf))
+               schedule_work(&priv->rx_work);
+
+       return;
+}
+/* End of private methods */
+
+static int aircable_probe(struct usb_serial *serial,
+                         const struct usb_device_id *id)
+{
+       struct usb_host_interface *iface_desc = serial->interface->cur_altsetting;
+       struct usb_endpoint_descriptor *endpoint;
+       int num_bulk_out=0;
+       int i;
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+                       ((endpoint->bmAttributes & 3) == 0x02)) {
+                       /* we found our bulk out endpoint */
+                       dbg("found bulk out on endpoint %d", i);
+                       ++num_bulk_out;
+               }
+       }
+
+       if (num_bulk_out == 0) {
+               dbg("Invalid interface, discarding");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int aircable_attach (struct usb_serial *serial)
+{
+       struct usb_serial_port *port = serial->port[0];
+       struct aircable_private *priv;
+
+       priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
+       if (!priv){
+               err("%s- kmalloc(%Zd) failed.", __FUNCTION__,
+                       sizeof(struct aircable_private));
+               return -ENOMEM;
+       }
+
+       /* Allocation of Circular Buffers */
+       priv->tx_buf = serial_buf_alloc();
+       if (priv->tx_buf == NULL) {
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       priv->rx_buf = serial_buf_alloc();
+       if (priv->rx_buf == NULL) {
+               kfree(priv->tx_buf);
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
+       INIT_WORK(&priv->rx_work, aircable_read, port);
+
+       usb_set_serial_port_data(serial->port[0], priv);
+
+       return 0;
+}
+
+static void aircable_shutdown(struct usb_serial *serial)
+{
+
+       struct usb_serial_port *port = serial->port[0];
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+
+       dbg("%s", __FUNCTION__);
+
+       if (priv) {
+               serial_buf_free(priv->tx_buf);
+               serial_buf_free(priv->rx_buf);
+               usb_set_serial_port_data(port, NULL);
+               kfree(priv);
+       }
+}
+
+static int aircable_write_room(struct usb_serial_port *port)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       return serial_buf_data_avail(priv->tx_buf);
+}
+
+static int aircable_write(struct usb_serial_port *port,
+                         const unsigned char *source, int count)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       int temp;
+
+       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
+
+       if (!count){
+               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               return count;
+       }
+
+       temp = serial_buf_put(priv->tx_buf, source, count);
+
+       aircable_send(port);
+
+       if (count > AIRCABLE_BUF_SIZE)
+               count = AIRCABLE_BUF_SIZE;
+
+       return count;
+
+}
+
+static void aircable_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       int result;
+
+       dbg("%s - urb->status: %d", __FUNCTION__ , urb->status);
+
+       /* This has been taken from cypress_m8.c cypress_write_int_callback */
+       switch (urb->status) {
+               case 0:
+                       /* success */
+                       break;
+               case -ECONNRESET:
+               case -ENOENT:
+               case -ESHUTDOWN:
+                       /* this urb is terminated, clean up */
+                       dbg("%s - urb shutting down with status: %d",
+                           __FUNCTION__, urb->status);
+                       port->write_urb_busy = 0;
+                       return;
+               default:
+                       /* error in the urb, so we have to resubmit it */
+                       dbg("%s - Overflow in write", __FUNCTION__);
+                       dbg("%s - nonzero write bulk status received: %d",
+                           __FUNCTION__, urb->status);
+                       port->write_urb->transfer_buffer_length = 1;
+                       port->write_urb->dev = port->serial->dev;
+                       result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+                       if (result)
+                               dev_err(&urb->dev->dev,
+                                       "%s - failed resubmitting write urb, error %d\n",
+                                       __FUNCTION__, result);
+                       else
+                               return;
+       }
+
+       port->write_urb_busy = 0;
+
+       aircable_send(port);
+}
+
+static void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       struct tty_struct *tty;
+       unsigned long no_packages, remaining, package_length, i;
+       int result, shift = 0;
+       unsigned char *temp;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (urb->status) {
+               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               if (!port->open_count) {
+                       dbg("%s - port is closed, exiting.", __FUNCTION__);
+                       return;
+               }
+               if (urb->status == -EPROTO) {
+                       dbg("%s - caught -EPROTO, resubmitting the urb",
+                           __FUNCTION__);
+                       usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+                                         usb_rcvbulkpipe(port->serial->dev,
+                                                         port->bulk_in_endpointAddress),
+                                         port->read_urb->transfer_buffer,
+                                         port->read_urb->transfer_buffer_length,
+                                         aircable_read_bulk_callback, port);
+
+                       result = usb_submit_urb(urb, GFP_ATOMIC);
+                       if (result)
+                               dev_err(&urb->dev->dev,
+                                       "%s - failed resubmitting read urb, error %d\n",
+                                       __FUNCTION__, result);
+                       return;
+               }
+               dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
+               return;
+       }
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                               urb->actual_length,urb->transfer_buffer);
+
+       tty = port->tty;
+       if (tty && urb->actual_length) {
+               if (urb->actual_length <= 2) {
+                       /* This is an incomplete package */
+                       serial_buf_put(priv->rx_buf, urb->transfer_buffer,
+                                      urb->actual_length);
+               } else {
+                       temp = urb->transfer_buffer;
+                       if (temp[0] == RX_HEADER_0)
+                               shift = HCI_HEADER_LENGTH;
+
+                       remaining = urb->actual_length;
+                       no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
+
+                       if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
+                               no_packages+=1;
+
+                       for (i = 0; i < no_packages ;i++) {
+                               if (remaining > (HCI_COMPLETE_FRAME))
+                                       package_length = HCI_COMPLETE_FRAME;
+                               else
+                                       package_length = remaining;
+                               remaining -= package_length;
+
+                               serial_buf_put(priv->rx_buf,
+                                       urb->transfer_buffer + shift +
+                                       (HCI_COMPLETE_FRAME) * (i),
+                                       package_length - shift);
+                       }
+               }
+               aircable_read(port);
+       }
+
+       /* Schedule the next read _if_ we are still open */
+       if (port->open_count) {
+               usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+                                 usb_rcvbulkpipe(port->serial->dev,
+                                                 port->bulk_in_endpointAddress),
+                                 port->read_urb->transfer_buffer,
+                                 port->read_urb->transfer_buffer_length,
+                                 aircable_read_bulk_callback, port);
+
+               result = usb_submit_urb(urb, GFP_ATOMIC);
+               if (result)
+                       dev_err(&urb->dev->dev,
+                               "%s - failed resubmitting read urb, error %d\n",
+                               __FUNCTION__, result);
+       }
+
+       return;
+}
+
+/* Based on ftdi_sio.c throttle */
+static void aircable_throttle(struct usb_serial_port *port)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->rx_lock, flags);
+       priv->rx_flags |= THROTTLED;
+       spin_unlock_irqrestore(&priv->rx_lock, flags);
+}
+
+/* Based on ftdi_sio.c unthrottle */
+static void aircable_unthrottle(struct usb_serial_port *port)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       int actually_throttled;
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->rx_lock, flags);
+       actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+       priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
+       spin_unlock_irqrestore(&priv->rx_lock, flags);
+
+       if (actually_throttled)
+               schedule_work(&priv->rx_work);
+}
+
+static struct usb_serial_driver aircable_device = {
+       .description =          "aircable",
+       .id_table =             id_table,
+       .num_ports =            1,
+       .attach =               aircable_attach,
+       .probe =                aircable_probe,
+       .shutdown =             aircable_shutdown,
+       .write =                aircable_write,
+       .write_room =           aircable_write_room,
+       .write_bulk_callback =  aircable_write_bulk_callback,
+       .read_bulk_callback =   aircable_read_bulk_callback,
+       .throttle =             aircable_throttle,
+       .unthrottle =           aircable_unthrottle,
+};
+
+static struct usb_driver aircable_driver = {
+       .name =         "aircable",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+};
+
+static int __init aircable_init (void)
+{
+       int retval;
+       retval = usb_serial_register(&aircable_device);
+       if (retval)
+               goto failed_serial_register;
+       retval = usb_register(&aircable_driver);
+       if (retval)
+               goto failed_usb_register;
+       return 0;
+
+failed_serial_register:
+       usb_serial_deregister(&aircable_device);
+failed_usb_register:
+       return retval;
+}
+
+static void __exit aircable_exit (void)
+{
+       usb_deregister(&aircable_driver);
+       usb_serial_deregister(&aircable_device);
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_init(aircable_init);
+module_exit(aircable_exit);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
index 62082532a8b346359899b2291c59a69a3b7bcfad..6e1a84a858d4df72eb6cf99ff4397d12aa23f9a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AirPrime CDMA Wireless Serial USB driver
  *
- * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License version
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
 static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
-       { USB_DEVICE(0xf3d, 0x0112) },  /* AirPrime CDMA Wireless PC Card */
-       { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+       { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */
+       { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
+       { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
        { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
+       { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
+#define URB_TRANSFER_BUFFER_SIZE       4096
+#define NUM_READ_URBS                  4
+#define NUM_WRITE_URBS                 4
+#define NUM_BULK_EPS                   3
+#define MAX_BULK_EPS                   6
+
+/* if overridden by the user, then use their value for the size of the
+ * read and write urbs, and the number of endpoints */
+static int buffer_size = URB_TRANSFER_BUFFER_SIZE;
+static int endpoints = NUM_BULK_EPS;
+static int debug;
+struct airprime_private {
+       spinlock_t lock;
+       int outstanding_urbs;
+       int throttled;
+       struct urb *read_urbp[NUM_READ_URBS];
+};
+
+static void airprime_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       unsigned char *data = urb->transfer_buffer;
+       struct tty_struct *tty;
+       int result;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (urb->status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __FUNCTION__, urb->status);
+               /* something happened, so free up the memory for this urb */
+               if (urb->transfer_buffer) {
+                       kfree (urb->transfer_buffer);
+                       urb->transfer_buffer = NULL;
+               }
+               return;
+       }
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+
+       tty = port->tty;
+       if (tty && urb->actual_length) {
+               tty_insert_flip_string (tty, data, urb->actual_length);
+               tty_flip_buffer_push (tty);
+       }
+
+       result = usb_submit_urb (urb, GFP_ATOMIC);
+       if (result)
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+                       __FUNCTION__, result);
+       return;
+}
+
+static void airprime_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* free up the transfer buffer, as usb_free_urb() does not do this */
+       kfree (urb->transfer_buffer);
+
+       if (urb->status)
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, urb->status);
+       spin_lock_irqsave(&priv->lock, flags);
+       --priv->outstanding_urbs;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       usb_serial_port_softint(port);
+}
+
+static int airprime_open(struct usb_serial_port *port, struct file *filp)
+{
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       char *buffer = NULL;
+       int i;
+       int result = 0;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* initialize our private data structure if it isn't already created */
+       if (!priv) {
+               priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+               if (!priv) {
+                       result = -ENOMEM;
+                       goto out;
+               }
+               spin_lock_init(&priv->lock);
+               usb_set_serial_port_data(port, priv);
+       }
+
+       for (i = 0; i < NUM_READ_URBS; ++i) {
+               buffer = kmalloc(buffer_size, GFP_KERNEL);
+               if (!buffer) {
+                       dev_err(&port->dev, "%s - out of memory.\n",
+                               __FUNCTION__);
+                       result = -ENOMEM;
+                       goto errout;
+               }
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       dev_err(&port->dev, "%s - no more urbs?\n",
+                               __FUNCTION__);
+                       result = -ENOMEM;
+                       goto errout;
+               }
+               usb_fill_bulk_urb(urb, serial->dev,
+                                 usb_rcvbulkpipe(serial->dev,
+                                                 port->bulk_out_endpointAddress),
+                                 buffer, buffer_size,
+                                 airprime_read_bulk_callback, port);
+               result = usb_submit_urb(urb, GFP_KERNEL);
+               if (result) {
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb %d for port %d, error %d\n",
+                               __FUNCTION__, i, port->number, result);
+                       goto errout;
+               }
+               /* remember this urb so we can kill it when the port is closed */
+               priv->read_urbp[i] = urb;
+       }
+       goto out;
+
+ errout:
+       /* some error happened, cancel any submitted urbs and clean up anything that
+          got allocated successfully */
+
+       for ( ; i >= 0; --i) {
+               urb = priv->read_urbp[i];
+               if (urb) {
+                       /* This urb was submitted successfully. So we have to
+                          cancel it.
+                          Unlinking the urb will invoke read_bulk_callback()
+                          with an error status, so its transfer buffer will
+                          be freed there */
+                       if (usb_unlink_urb (urb) != -EINPROGRESS) {
+                               /* comments in drivers/usb/core/urb.c say this
+                                  can only happen if the urb was never submitted,
+                                  or has completed already.
+                                  Either way we may have to free the transfer
+                                  buffer here. */
+                               if (urb->transfer_buffer) {
+                                       kfree (urb->transfer_buffer);
+                                       urb->transfer_buffer = NULL;
+                               }
+                       }
+                       usb_free_urb (urb);
+               }
+       }
+
+ out:
+       return result;
+}
+
+static void airprime_close(struct usb_serial_port *port, struct file * filp)
+{
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       int i;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* killing the urb will invoke read_bulk_callback() with an error status,
+          so the transfer buffer will be freed there */
+       for (i = 0; i < NUM_READ_URBS; ++i) {
+               usb_kill_urb (priv->read_urbp[i]);
+               usb_free_urb (priv->read_urbp[i]);
+       }
+
+       /* free up private structure */
+       kfree (priv);
+       usb_set_serial_port_data(port, NULL);
+}
+
+static int airprime_write(struct usb_serial_port *port,
+                         const unsigned char *buf, int count)
+{
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       unsigned char *buffer;
+       unsigned long flags;
+       int status;
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (priv->outstanding_urbs > NUM_WRITE_URBS) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               dbg("%s - write limit hit\n", __FUNCTION__);
+               return 0;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+       buffer = kmalloc(count, GFP_ATOMIC);
+       if (!buffer) {
+               dev_err(&port->dev, "out of memory\n");
+               return -ENOMEM;
+       }
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(&port->dev, "no more free urbs\n");
+               kfree (buffer);
+               return -ENOMEM;
+       }
+       memcpy (buffer, buf, count);
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+       usb_fill_bulk_urb(urb, serial->dev,
+                         usb_sndbulkpipe(serial->dev,
+                                         port->bulk_out_endpointAddress),
+                         buffer, count,
+                         airprime_write_bulk_callback, port);
+
+       /* send it down the pipe */
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status) {
+               dev_err(&port->dev,
+                       "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+                       __FUNCTION__, status);
+               count = status;
+               kfree (buffer);
+       } else {
+               spin_lock_irqsave(&priv->lock, flags);
+               ++priv->outstanding_urbs;
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       /* we are done with this urb, so let the host driver
+        * really free it when it is finished with it */
+       usb_free_urb (urb);
+       return count;
+}
+
 static struct usb_driver airprime_driver = {
        .name =         "airprime",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table,
-       .no_dynamic_id =        1,
+       .no_dynamic_id =        1,
 };
 
 static struct usb_serial_driver airprime_device = {
@@ -42,13 +280,17 @@ static struct usb_serial_driver airprime_device = {
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
        .num_bulk_out =         NUM_DONT_CARE,
-       .num_ports =            1,
+       .open =                 airprime_open,
+       .close =                airprime_close,
+       .write =                airprime_write,
 };
 
 static int __init airprime_init(void)
 {
        int retval;
 
+       airprime_device.num_ports =
+               (endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS;
        retval = usb_serial_register(&airprime_device);
        if (retval)
                return retval;
@@ -60,6 +302,8 @@ static int __init airprime_init(void)
 
 static void __exit airprime_exit(void)
 {
+       dbg("%s", __FUNCTION__);
+
        usb_deregister(&airprime_driver);
        usb_serial_deregister(&airprime_device);
 }
@@ -67,3 +311,10 @@ static void __exit airprime_exit(void)
 module_init(airprime_init);
 module_exit(airprime_exit);
 MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled");
+module_param(buffer_size, int, 0);
+MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)");
+module_param(endpoints, int, 0);
+MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");
index 970d9ef0a7a5cce77eadc5b9d09a5ec6c2cc798f..ca52f12f0e24847df78ccc44e84bcd47dff63e86 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2006
+ *   Simon Schulz (ark3116_driver <at> auctionant.de)
+ *
  * ark3116
  * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
  *   productid=0x0232) (used in a datacable called KQ-U8A)
@@ -8,8 +11,6 @@
  *
  *  - based on logs created by usbsnoopy
  *
- *  Author   : Simon Schulz [ark3116_driver<AT>auctionant.de]
- *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -22,6 +23,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial.h>
+#include <asm/uaccess.h>
 
 
 static int debug;
@@ -43,10 +46,10 @@ static inline void ARK3116_SND(struct usb_serial *serial, int seq,
 {
        int result;
        result = usb_control_msg(serial->dev,
-                                usb_sndctrlpipe(serial->dev,0),
+                                usb_sndctrlpipe(serial->dev, 0),
                                 request, requesttype, value, index,
-                                NULL,0x00, 1000);
-       dbg("%03d > ok",seq);
+                                NULL, 0x00, 1000);
+       dbg("%03d > ok", seq);
 }
 
 static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
@@ -56,27 +59,25 @@ static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
 {
        int result;
        result = usb_control_msg(serial->dev,
-                             usb_rcvctrlpipe(serial->dev,0),
-                             request, requesttype, value, index,
-                             buf, 0x0000001, 1000);
+                                usb_rcvctrlpipe(serial->dev, 0),
+                                request, requesttype, value, index,
+                                buf, 0x0000001, 1000);
        if (result)
-               dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
+               dbg("%03d < %d bytes [0x%02X]", seq, result, buf[0]);
        else
                dbg("%03d < 0 bytes", seq);
 }
 
-
 static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
                                     __u8 request, __u8 requesttype,
                                     __u16 value, __u16 index, char *buf)
 {
        usb_control_msg(serial->dev,
-                       usb_rcvctrlpipe(serial->dev,0),
+                       usb_rcvctrlpipe(serial->dev, 0),
                        request, requesttype, value, index,
                        buf, 0x0000001, 1000);
 }
 
-
 static int ark3116_attach(struct usb_serial *serial)
 {
        char *buf;
@@ -84,10 +85,10 @@ static int ark3116_attach(struct usb_serial *serial)
        int i;
 
        for (i = 0; i < serial->num_ports; ++i) {
-               priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
+               priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL);
                if (!priv)
                        goto cleanup;
-               memset (priv, 0x00, sizeof (struct ark3116_private));
+               memset(priv, 0x00, sizeof (struct ark3116_private));
                spin_lock_init(&priv->lock);
 
                usb_set_serial_port_data(serial->port[i], priv);
@@ -95,63 +96,62 @@ static int ark3116_attach(struct usb_serial *serial)
 
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
-               dbg("error kmalloc -> out of mem ?");
+               dbg("error kmalloc -> out of mem?");
                goto cleanup;
        }
 
        /* 3 */
-       ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002);
-       ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001);
-       ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008);
-       ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B);
+       ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002);
+       ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001);
+       ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008);
+       ARK3116_SND(serial, 6, 0xFE, 0x40, 0x0000, 0x000B);
 
        /* <-- seq7 */
-       ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf);
-       ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003);
-       ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000);
-       ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001);
-       ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003);
+       ARK3116_RCV(serial,  7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+       ARK3116_SND(serial,  8, 0xFE, 0x40, 0x0080, 0x0003);
+       ARK3116_SND(serial,  9, 0xFE, 0x40, 0x001A, 0x0000);
+       ARK3116_SND(serial, 10, 0xFE, 0x40, 0x0000, 0x0001);
+       ARK3116_SND(serial, 11, 0xFE, 0x40, 0x0000, 0x0003);
 
        /* <-- seq12 */
-       ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
-       ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004);
+       ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
+       ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004);
 
        /* 14 */
-       ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
-       ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004);
+       ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
+       ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004);
 
        /* 16 */
-       ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+       ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
        /* --> seq17 */
-       ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004);
+       ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004);
 
        /* <-- seq18 */
-       ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+       ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf);
 
        /* --> seq19 */
-       ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004);
-
+       ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004);
 
        /* <-- seq20 */
-       /* seems like serial port status info (RTS, CTS,...) */
-       /* returns modem control line status ?! */
-       ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
-
-       /* set 9600 baud & do some init ?! */
-       ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
-       ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000);
-       ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001);
-       ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
-       ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
-       ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
-       ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
-       ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003);
+       /* seems like serial port status info (RTS, CTS, ...) */
+       /* returns modem control line status?! */
+       ARK3116_RCV(serial, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
+
+       /* set 9600 baud & do some init?! */
+       ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003);
+       ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000);
+       ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001);
+       ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003);
+       ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+       ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003);
+       ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+       ARK3116_SND(serial, 154, 0xFE, 0x40, 0x0003, 0x0003);
 
        kfree(buf);
-       return(0);
+       return 0;
 
 cleanup:
-       for (--i; i>=0; --i)
+       for (--i; i >= 0; --i)
                usb_set_serial_port_data(serial->port[i], NULL);
        return -ENOMEM;
 }
@@ -180,7 +180,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
                *(port->tty->termios) = tty_std_termios;
-               port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+               port->tty->termios->c_cflag = B9600 | CS8
+                                             | CREAD | HUPCL | CLOCAL;
                priv->termios_initialized = 1;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -204,8 +205,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
        }
 
        /* set data bit count (8/7/6/5) */
-       if (cflag & CSIZE){
-               switch (cflag & CSIZE){
+       if (cflag & CSIZE) {
+               switch (cflag & CSIZE) {
                case CS5:
                        config |= 0x00;
                        dbg("setting CS5");
@@ -219,7 +220,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                        dbg("setting CS7");
                        break;
                default:
-                       err ("CSIZE was set but not CS5-CS8, using CS8!");
+                       err("CSIZE was set but not CS5-CS8, using CS8!");
+                       /* fall through */
                case CS8:
                        config |= 0x03;
                        dbg("setting CS8");
@@ -227,8 +229,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                }
        }
 
-       /* set parity (NONE,EVEN,ODD) */
-       if (cflag & PARENB){
+       /* set parity (NONE/EVEN/ODD) */
+       if (cflag & PARENB) {
                if (cflag & PARODD) {
                        config |= 0x08;
                        dbg("setting parity to ODD");
@@ -240,20 +242,19 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                dbg("setting parity to NONE");
        }
 
-       /* SET STOPBIT (1/2) */
+       /* set stop bit (1/2) */
        if (cflag & CSTOPB) {
                config |= 0x04;
-               dbg ("setting 2 stop bits");
+               dbg("setting 2 stop bits");
        } else {
-               dbg ("setting 1 stop bit");
+               dbg("setting 1 stop bit");
        }
 
-
-       /* set baudrate: */
+       /* set baudrate */
        baud = 0;
-       switch (cflag & CBAUD){
+       switch (cflag & CBAUD) {
                case B0:
-                       err("can't set 0baud, using 9600 instead");
+                       err("can't set 0 baud, using 9600 instead");
                        break;
                case B75:       baud = 75;      break;
                case B150:      baud = 150;     break;
@@ -285,38 +286,40 @@ static void ark3116_set_termios(struct usb_serial_port *port,
         */
        if (baud == 460800)
                /* strange, for 460800 the formula is wrong
-                * (dont use round(), then 9600baud is wrong) */
+                * if using round() then 9600baud is wrong) */
                ark3116_baud = 7;
        else
                ark3116_baud = 3000000 / baud;
 
        /* ? */
-       ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf);
+       ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf);
+
        /* offset = buf[0]; */
        /* offset = 0x03; */
-       /* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */
-
+       /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */
 
        /* set baudrate */
-       dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
-       ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
-       ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF)   ,0x0000);
-       ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
-       ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+       dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud);
+       ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003);
+       ARK3116_SND(serial, 148, 0xFE, 0x40,
+                           (ark3116_baud & 0x00FF), 0x0000);
+       ARK3116_SND(serial, 149, 0xFE, 0x40,
+                           (ark3116_baud & 0xFF00) >> 8, 0x0001);
+       ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003);
 
        /* ? */
-       ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
-       ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+       ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+       ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003);
 
        /* set data bit count, stop bit count & parity: */
        dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
-       ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
-       ARK3116_SND(serial,154,0xFE,0x40,config,0x0003);
+       ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+       ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003);
 
        if (cflag & CRTSCTS)
-               dbg("CRTSCTS not supported by chipset ?!");
+               dbg("CRTSCTS not supported by chipset?!");
 
-       /* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */
+       /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */
 
        kfree(buf);
        return;
@@ -329,11 +332,11 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
        char *buf;
        int result = 0;
 
-       dbg("%s -  port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __FUNCTION__, port->number);
 
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
-               dbg("error kmalloc -> out of mem ?");
+               dbg("error kmalloc -> out of mem?");
                return -ENOMEM;
        }
 
@@ -342,44 +345,68 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
                return result;
 
        /* open */
-       ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf);
+       ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf);
 
-       ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003);
-       ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000);
-       ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001);
-       ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003);
+       ARK3116_SND(serial, 112, 0xFE, 0x40, 0x0082, 0x0003);
+       ARK3116_SND(serial, 113, 0xFE, 0x40, 0x001A, 0x0000);
+       ARK3116_SND(serial, 114, 0xFE, 0x40, 0x0000, 0x0001);
+       ARK3116_SND(serial, 115, 0xFE, 0x40, 0x0002, 0x0003);
 
-       ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf);
-       ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004);
+       ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+       ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004);
 
-       ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf);
-       ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004);
+       ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf);
+       ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004);
 
-       ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+       ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
 
-       ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004);
+       ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004);
 
-       ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+       ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf);
 
-       ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004);
+       ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004);
 
-       /* returns different values (control lines ?!) */
-       ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+       /* returns different values (control lines?!) */
+       ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
 
-       /* initialise termios: */
+       /* initialise termios */
        if (port->tty)
                ark3116_set_termios(port, &tmp_termios);
 
        kfree(buf);
 
        return result;
-
 }
 
 static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
-       dbg("ioctl not supported yet...");
+       struct serial_struct serstruct;
+       void __user *user_arg = (void __user *)arg;
+
+       switch (cmd) {
+       case TIOCGSERIAL:
+               /* XXX: Some of these values are probably wrong. */
+               memset(&serstruct, 0, sizeof (serstruct));
+               serstruct.type = PORT_16654;
+               serstruct.line = port->serial->minor;
+               serstruct.port = port->number;
+               serstruct.custom_divisor = 0;
+               serstruct.baud_base = 460800;
+
+               if (copy_to_user(user_arg, &serstruct, sizeof (serstruct)))
+                       return -EFAULT;
+
+               return 0;
+       case TIOCSSERIAL:
+               if (copy_from_user(&serstruct, user_arg, sizeof (serstruct)))
+                       return -EFAULT;
+               return 0;
+       default:
+               dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd);
+               break;
+       }
+
        return -ENOIOCTLCMD;
 }
 
@@ -389,7 +416,7 @@ static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
        char *buf;
        char temp;
 
-       /* seems like serial port status info (RTS, CTS,...) is stored
+       /* seems like serial port status info (RTS, CTS, ...) is stored
         * in reg(?) 0x0006
         * pcb connection point 11 = GND -> sets bit4 of response
         * pcb connection point  7 = GND -> sets bit6 of response
@@ -401,16 +428,16 @@ static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
                return -ENOMEM;
        }
 
-       /* read register: */
-       ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf);
+       /* read register */
+       ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf);
        temp = buf[0];
        kfree(buf);
 
-       /* i do not really know if bit4=CTS and bit6=DSR... was just a
-        * quick guess !!
+       /* i do not really know if bit4=CTS and bit6=DSR... just a
+        * quick guess!
         */
-       return  (temp & (1<<4) ? TIOCM_CTS : 0) |
-               (temp & (1<<6) ? TIOCM_DSR : 0);
+       return (temp & (1<<4) ? TIOCM_CTS : 0)
+              | (temp & (1<<6) ? TIOCM_DSR : 0);
 }
 
 static struct usb_driver ark3116_driver = {
index 6286aba86fae2340beaed87c5f2a970050053939..d954ec34b018504b0cde6706030e3a29fac46ea9 100644 (file)
@@ -214,14 +214,14 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
                return (0);
        }
 
-       spin_lock(&port->lock);
+       spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
-               spin_unlock(&port->lock);
+               spin_unlock_bh(&port->lock);
                dbg("%s - already writing", __FUNCTION__);
                return 0;
        }
        port->write_urb_busy = 1;
-       spin_unlock(&port->lock);
+       spin_unlock_bh(&port->lock);
 
        spin_lock_irqsave(&priv->lock, flags);
 
index ee70fddcab6031a8f1c045da4e71c09b3c4d1f9b..e1173c1aee37c1280931cf7e32b17589d833480d 100644 (file)
@@ -129,6 +129,9 @@ struct cypress_private {
        int cmd_ctrl;                      /* always set this to 1 before issuing a command */
        struct cypress_buf *buf;           /* write buffer */
        int write_urb_in_use;              /* write urb in use indicator */
+       int write_urb_interval;            /* interval to use for write urb */
+       int read_urb_interval;             /* interval to use for read urb */
+       int comm_is_ok;                    /* true if communication is (still) ok */
        int termios_initialized;
        __u8 line_control;                 /* holds dtr / rts value */
        __u8 current_status;               /* received from last read - info on dsr,cts,cd,ri,etc */
@@ -168,6 +171,7 @@ static int  cypress_tiocmset                (struct usb_serial_port *port, struct file *file,
 static int  cypress_chars_in_buffer    (struct usb_serial_port *port);
 static void cypress_throttle           (struct usb_serial_port *port);
 static void cypress_unthrottle         (struct usb_serial_port *port);
+static void cypress_set_dead           (struct usb_serial_port *port);
 static void cypress_read_int_callback  (struct urb *urb, struct pt_regs *regs);
 static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs);
 /* baud helper functions */
@@ -288,6 +292,9 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
        
        priv = usb_get_serial_port_data(port);
 
+       if (!priv->comm_is_ok)
+               return -ENODEV;
+
        switch(cypress_request_type) {
                case CYPRESS_SET_CONFIG:
 
@@ -365,13 +372,12 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
                                if (tries++ >= 3)
                                        break;
 
-                               if (retval == EPIPE)
-                                       usb_clear_halt(port->serial->dev, 0x00);
-                       } while (retval != 8 && retval != ENODEV);
+                       } while (retval != 8 && retval != -ENODEV);
 
-                       if (retval != 8)
+                       if (retval != 8) {
                                err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
-                       else {
+                               cypress_set_dead(port);
+                       } else {
                                spin_lock_irqsave(&priv->lock, flags);
                                priv->baud_rate = new_baudrate;
                                priv->cbr_mask = baud_mask;
@@ -392,12 +398,11 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
                                if (tries++ >= 3)
                                        break;
 
-                               if (retval == EPIPE)
-                                       usb_clear_halt(port->serial->dev, 0x00);
-                       } while (retval != 5 && retval != ENODEV);
+                       } while (retval != 5 && retval != -ENODEV);
 
                        if (retval != 5) {
                                err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
+                               cypress_set_dead(port);
                                return retval;
                        } else {
                                spin_lock_irqsave(&priv->lock, flags);
@@ -419,6 +424,24 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
 } /* cypress_serial_control */
 
 
+static void cypress_set_dead(struct usb_serial_port *port)
+{
+       struct cypress_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (!priv->comm_is_ok) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return;
+       }
+       priv->comm_is_ok = 0;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       err("cypress_m8 suspending failing port %d - interval might be too short",
+           port->number);
+}
+
+
 /* given a baud mask, it will return integer baud on success */
 static int mask_to_rate (unsigned mask)
 {
@@ -472,13 +495,15 @@ static unsigned rate_to_mask (int rate)
 static int generic_startup (struct usb_serial *serial)
 {
        struct cypress_private *priv;
+       struct usb_serial_port *port = serial->port[0];
 
-       dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
+       dbg("%s - port %d", __FUNCTION__, port->number);
 
        priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
+       priv->comm_is_ok = !0;
        spin_lock_init(&priv->lock);
        priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE);
        if (priv->buf == NULL) {
@@ -489,13 +514,24 @@ static int generic_startup (struct usb_serial *serial)
        
        usb_reset_configuration (serial->dev);
        
-       interval = 1;
        priv->cmd_ctrl = 0;
        priv->line_control = 0;
        priv->termios_initialized = 0;
        priv->rx_flags = 0;
        priv->cbr_mask = B300;
-       usb_set_serial_port_data(serial->port[0], priv);
+       if (interval > 0) {
+               priv->write_urb_interval = interval;
+               priv->read_urb_interval = interval;
+               dbg("%s - port %d read & write intervals forced to %d",
+                   __FUNCTION__,port->number,interval);
+       } else {
+               priv->write_urb_interval = port->interrupt_out_urb->interval;
+               priv->read_urb_interval = port->interrupt_in_urb->interval;
+               dbg("%s - port %d intervals: read=%d write=%d",
+                   __FUNCTION__,port->number,
+                   priv->read_urb_interval,priv->write_urb_interval);
+       }
+       usb_set_serial_port_data(port, priv);
        
        return 0;
 }
@@ -585,6 +621,9 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
+       if (!priv->comm_is_ok)
+               return -EIO;
+
        /* clear halts before open */
        usb_clear_halt(serial->dev, 0x81);
        usb_clear_halt(serial->dev, 0x02);
@@ -624,11 +663,12 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
        usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
                usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
                port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
-               cypress_read_int_callback, port, interval);
+               cypress_read_int_callback, port, priv->read_urb_interval);
        result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 
        if (result){
                dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               cypress_set_dead(port);
        }
 
        return result;
@@ -733,6 +773,9 @@ static void cypress_send(struct usb_serial_port *port)
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        
+       if (!priv->comm_is_ok)
+               return;
+
        dbg("%s - port %d", __FUNCTION__, port->number);
        dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
        
@@ -806,14 +849,16 @@ send:
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
                              port->interrupt_out_urb->transfer_buffer);
 
-       port->interrupt_out_urb->transfer_buffer_length = actual_size;
-       port->interrupt_out_urb->dev = port->serial->dev;
-       port->interrupt_out_urb->interval = interval;
+       usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
+               usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
+               port->interrupt_out_buffer, port->interrupt_out_size,
+               cypress_write_int_callback, port, priv->write_urb_interval);
        result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
                        result);
                priv->write_urb_in_use = 0;
+               cypress_set_dead(port);
        }
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -1214,13 +1259,18 @@ static void cypress_unthrottle (struct usb_serial_port *port)
        priv->rx_flags = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       if (!priv->comm_is_ok)
+               return;
+
        if (actually_throttled) {
                port->interrupt_in_urb->dev = port->serial->dev;
 
                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-               if (result)
+               if (result) {
                        dev_err(&port->dev, "%s - failed submitting read urb, "
                                        "error %d\n", __FUNCTION__, result);
+                       cypress_set_dead(port);
+               }
        }
 }
 
@@ -1240,9 +1290,22 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read status received: %d", __FUNCTION__,
-                               urb->status);
+       switch (urb->status) {
+       case 0: /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* precursor to disconnect so just go away */
+               return;
+       case -EPIPE:
+               usb_clear_halt(port->serial->dev,0x81);
+               break;
+       default:
+               /* something ugly is going on... */
+               dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
+                       __FUNCTION__,urb->status);
+               cypress_set_dead(port);
                return;
        }
 
@@ -1343,18 +1406,20 @@ continue_read:
 
        /* Continue trying to always read... unless the port has closed. */
 
-       if (port->open_count > 0) {
+       if (port->open_count > 0 && priv->comm_is_ok) {
                usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
                                usb_rcvintpipe(port->serial->dev,
                                        port->interrupt_in_endpointAddress),
                                port->interrupt_in_urb->transfer_buffer,
                                port->interrupt_in_urb->transfer_buffer_length,
-                               cypress_read_int_callback, port, interval);
+                               cypress_read_int_callback, port, priv->read_urb_interval);
                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-               if (result)
+               if (result) {
                        dev_err(&urb->dev->dev, "%s - failed resubmitting "
                                        "read urb, error %d\n", __FUNCTION__,
                                        result);
+                       cypress_set_dead(port);
+               }
        }
 
        return;
@@ -1380,20 +1445,26 @@ static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs)
                        dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
                        priv->write_urb_in_use = 0;
                        return;
-               case -EPIPE: /* no break needed */
+               case -EPIPE: /* no break needed; clear halt and resubmit */
+                       if (!priv->comm_is_ok)
+                               break;
                        usb_clear_halt(port->serial->dev, 0x02);
-               default:
                        /* error in the urb, so we have to resubmit it */
-                       dbg("%s - Overflow in write", __FUNCTION__);
                        dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
                        port->interrupt_out_urb->transfer_buffer_length = 1;
                        port->interrupt_out_urb->dev = port->serial->dev;
                        result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
-                       if (result)
-                               dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
-                                       __FUNCTION__, result);
-                       else
+                       if (!result)
                                return;
+                       dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
+                               __FUNCTION__, result);
+                       cypress_set_dead(port);
+                       break;
+               default:
+                       dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
+                               __FUNCTION__,urb->status);
+                       cypress_set_dead(port);
+                       break;
        }
        
        priv->write_urb_in_use = 0;
index c6115aa1b4456ced571506c9f324e4a864e88aaf..e774a27c6c9857bf9677d166f55f5d55e6271866 100644 (file)
@@ -344,6 +344,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
+       { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
@@ -507,6 +508,9 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
        { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -1101,25 +1105,29 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
 static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
 static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
 
-static void create_sysfs_attrs(struct usb_serial *serial)
-{      
+static int create_sysfs_attrs(struct usb_serial *serial)
+{
        struct ftdi_private *priv;
        struct usb_device *udev;
+       int retval = 0;
 
        dbg("%s",__FUNCTION__);
-       
+
        priv = usb_get_serial_port_data(serial->port[0]);
        udev = serial->dev;
-       
+
        /* XXX I've no idea if the original SIO supports the event_char
         * sysfs parameter, so I'm playing it safe.  */
        if (priv->chip_type != SIO) {
                dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
-               device_create_file(&udev->dev, &dev_attr_event_char);
-               if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
-                       device_create_file(&udev->dev, &dev_attr_latency_timer);
+               retval = device_create_file(&udev->dev, &dev_attr_event_char);
+               if ((!retval) &&
+                   (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
+                       retval = device_create_file(&udev->dev,
+                                                   &dev_attr_latency_timer);
                }
        }
+       return retval;
 }
 
 static void remove_sysfs_attrs(struct usb_serial *serial)
@@ -1162,7 +1170,8 @@ static int ftdi_sio_attach (struct usb_serial *serial)
        struct usb_serial_port *port = serial->port[0];
        struct ftdi_private *priv;
        struct ftdi_sio_quirk *quirk;
-       
+       int retval;
+
        dbg("%s",__FUNCTION__);
 
        priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
@@ -1203,15 +1212,18 @@ static int ftdi_sio_attach (struct usb_serial *serial)
        usb_set_serial_port_data(serial->port[0], priv);
 
        ftdi_determine_type (serial->port[0]);
-       create_sysfs_attrs(serial);
+       retval = create_sysfs_attrs(serial);
+       if (retval)
+               dev_err(&serial->dev->dev, "Error creating sysfs files, "
+                       "continuing\n");
 
        /* Check for device requiring special set up. */
        quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
        if (quirk && quirk->setup) {
                quirk->setup(serial);
        }
-       
-       return (0);
+
+       return 0;
 } /* ftdi_sio_attach */
 
 
index 77299996f7ee045cc5d73c330f97b5b5774f0470..f0edb87d2dd51c7831fa661be827758fffe6999e 100644 (file)
 #define SEALEVEL_2102_PID      0x2102  /* SeaLINK+485 (2102) */
 #define SEALEVEL_2103_PID      0x2103  /* SeaLINK+232I (2103) */
 #define SEALEVEL_2104_PID      0x2104  /* SeaLINK+485I (2104) */
+#define SEALEVEL_2106_PID      0x9020  /* SeaLINK+422 (2106) */
 #define SEALEVEL_2201_1_PID    0x2211  /* SeaPORT+2/232 (2201) Port 1 */
 #define SEALEVEL_2201_2_PID    0x2221  /* SeaPORT+2/232 (2201) Port 2 */
 #define SEALEVEL_2202_1_PID    0x2212  /* SeaPORT+2/485 (2202) Port 1 */
  */
 #define FTDI_GAMMA_SCOUT_PID           0xD678  /* Gamma Scout online */
 
+/*
+ * Tactrix OpenPort (ECU) devices.
+ * OpenPort 1.3M submitted by Donour Sizemore.
+ * OpenPort 1.3S and 1.3U submitted by Ian Abbott.
+ */
+#define FTDI_TACTRIX_OPENPORT_13M_PID  0xCC48  /* OpenPort 1.3 Mitsubishi */
+#define FTDI_TACTRIX_OPENPORT_13S_PID  0xCC49  /* OpenPort 1.3 Subaru */
+#define FTDI_TACTRIX_OPENPORT_13U_PID  0xCC4A  /* OpenPort 1.3 Universal */
+
 /* Commands */
 #define FTDI_SIO_RESET                 0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL    1 /* Set the modem control register */
index 727852634be9c91526419fe243b6b009382d69fc..4b1196a8b09e946364fb28e8fdcb625900b78e9a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Garmin GPS driver
  *
- * Copyright (C) 2004 Hermann Kneissel herkne@users.sourceforge.net
+ * Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net
  *
  * The latest version of the driver can be found at
  * http://sourceforge.net/projects/garmin-gps/
@@ -37,6 +37,8 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
+#include <linux/version.h>
+
 /* the mode to be set when the port ist opened */
 static int initial_mode = 1;
 
@@ -50,7 +52,7 @@ static int debug = 0;
  */
 
 #define VERSION_MAJOR  0
-#define VERSION_MINOR  23
+#define VERSION_MINOR  28
 
 #define _STR(s) #s
 #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
@@ -164,7 +166,8 @@ struct garmin_data {
 #define FLAGS_SESSION_REPLY1_SEEN 0x0080
 #define FLAGS_SESSION_REPLY2_SEEN 0x0040
 #define FLAGS_BULK_IN_ACTIVE      0x0020
-#define FLAGS_THROTTLED           0x0010
+#define FLAGS_BULK_IN_RESTART     0x0010
+#define FLAGS_THROTTLED           0x0008
 #define CLEAR_HALT_REQUIRED       0x0001
 
 #define FLAGS_QUEUING             0x0100
@@ -224,7 +227,7 @@ static struct usb_driver garmin_driver = {
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table,
-       .no_dynamic_id =        1,
+       .no_dynamic_id = 1,
 };
 
 
@@ -270,7 +273,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
 
 
 static void send_to_tty(struct usb_serial_port *port,
-                        char *data, unsigned int actual_length)
+                       char *data, unsigned int actual_length)
 {
        struct tty_struct *tty = port->tty;
 
@@ -294,15 +297,15 @@ static void send_to_tty(struct usb_serial_port *port,
  * queue a received (usb-)packet for later processing
  */
 static int pkt_add(struct garmin_data * garmin_data_p,
-                   unsigned char *data, unsigned int data_length)
+                  unsigned char *data, unsigned int data_length)
 {
+       int state = 0;
        int result = 0;
        unsigned long flags;
        struct garmin_packet *pkt;
 
        /* process only packets containg data ... */
        if (data_length) {
-               garmin_data_p->flags |= FLAGS_QUEUING;
                pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
                              GFP_ATOMIC);
                if (pkt == NULL) {
@@ -313,14 +316,16 @@ static int pkt_add(struct garmin_data * garmin_data_p,
                memcpy(pkt->data, data, data_length);
 
                spin_lock_irqsave(&garmin_data_p->lock, flags);
+               garmin_data_p->flags |= FLAGS_QUEUING;
                result = list_empty(&garmin_data_p->pktlist);
                pkt->seq = garmin_data_p->seq_counter++;
                list_add_tail(&pkt->list, &garmin_data_p->pktlist);
+               state = garmin_data_p->state;
                spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
                /* in serial mode, if someone is waiting for data from
                   the device, iconvert and send the next packet to tty. */
-               if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) {
+               if (result && (state == STATE_GSP_WAIT_DATA)) {
                        gsp_next_packet(garmin_data_p);
                }
        }
@@ -370,9 +375,9 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
 static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
 {
        __u8 pkt[10];
-        __u8 cksum = 0;
-        __u8 *ptr = pkt;
-        unsigned  l = 0;
+       __u8 cksum = 0;
+       __u8 *ptr = pkt;
+       unsigned  l = 0;
 
        dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
 
@@ -416,7 +421,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
 static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
 {
        const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
-        __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
+       __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
 
        int cksum = 0;
        int n = 0;
@@ -447,11 +452,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
                n++;
        }
 
-       if ((0xff & (cksum + *recpkt)) != 0) {
-                dbg("%s - invalid checksum, expected %02x, got %02x",
-                        __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
-                return -EINVPKT;
-        }
+       if ((0xff & (cksum + *recpkt)) != 0) {
+               dbg("%s - invalid checksum, expected %02x, got %02x",
+                       __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
+               return -EINVPKT;
+       }
 
        usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
        usbdata[1] = __cpu_to_le32(pktid);
@@ -491,20 +496,28 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
  */
 
 static int gsp_receive(struct garmin_data * garmin_data_p,
-                       const unsigned char *buf, int count)
+                      const unsigned char *buf, int count)
 {
+       unsigned long flags;
        int offs = 0;
        int ack_or_nak_seen = 0;
        int i = 0;
-       __u8 *dest = garmin_data_p->inbuffer;
-       int size = garmin_data_p->insize;
+       __u8 *dest;
+       int size;
        // dleSeen: set if last byte read was a DLE
-       int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+       int dleSeen;
        // skip: if set, skip incoming data until possible start of
        //       new packet
-       int skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+       int skip;
        __u8 data;
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
+       dest = garmin_data_p->inbuffer;
+       size = garmin_data_p->insize;
+       dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+       skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
        dbg("%s - dle=%d skip=%d size=%d count=%d",
                __FUNCTION__, dleSeen, skip, size, count);
 
@@ -572,6 +585,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
                }
        }
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
+
        garmin_data_p->insize = size;
 
        // copy flags back to structure
@@ -587,6 +602,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
 
        if (ack_or_nak_seen) {
                garmin_data_p->state = STATE_GSP_WAIT_DATA;
+       }
+
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+       if (ack_or_nak_seen) {
                gsp_next_packet(garmin_data_p);
        }
 
@@ -676,7 +696,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
        src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
        if (k > (GARMIN_PKTHDR_LENGTH-2)) {
                /* can't add stuffing DLEs in place, move data to end 
-                   of buffer ... */
+                  of buffer ... */
                dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
                memcpy(dst, src, datalen);
                src = dst;
@@ -755,8 +775,9 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
  * or even incomplete packets
  */
 static int nat_receive(struct garmin_data * garmin_data_p,
-                       const unsigned char *buf, int count)
+                      const unsigned char *buf, int count)
 {
+       unsigned long flags;
        __u8 * dest;
        int offs = 0;
        int result = count;
@@ -803,7 +824,9 @@ static int nat_receive(struct garmin_data * garmin_data_p,
                                /* if this was an abort-transfer command,
                                   flush all queued data. */
                                if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+                                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                                        garmin_data_p->flags |= FLAGS_DROP_DATA;
+                                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                                        pkt_clear(garmin_data_p);
                                }
                        }
@@ -839,12 +862,15 @@ static void priv_status_resp(struct usb_serial_port *port)
 
 static int process_resetdev_request(struct usb_serial_port *port)
 {
+       unsigned long flags;
        int status;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
        garmin_data_p->state = STATE_RESET;
        garmin_data_p->serial_num = 0;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        usb_kill_urb (port->interrupt_in_urb);
        dbg("%s - usb_reset_device", __FUNCTION__ );
@@ -862,6 +888,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
  */
 static int garmin_clear(struct garmin_data * garmin_data_p)
 {
+       unsigned long flags;
        int status = 0;
 
        struct usb_serial_port *port = garmin_data_p->port;
@@ -875,8 +902,10 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
        /* flush all queued data */
        pkt_clear(garmin_data_p);
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->insize = 0;
        garmin_data_p->outsize = 0;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        return status;
 }
@@ -888,6 +917,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
 
 static int garmin_init_session(struct usb_serial_port *port)
 {
+       unsigned long flags;
        struct usb_serial *serial = port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        int status = 0;
@@ -913,7 +943,9 @@ static int garmin_init_session(struct usb_serial_port *port)
 
                if (status >= 0) {
 
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->ignorePkts++;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
                        /* not needed, but the win32 driver does it too ... */
                        status = garmin_write_bulk(port,
@@ -921,7 +953,9 @@ static int garmin_init_session(struct usb_serial_port *port)
                                                   sizeof(GARMIN_START_SESSION_REQ2));
                        if (status >= 0) {
                                status = 0;
+                               spin_lock_irqsave(&garmin_data_p->lock, flags);
                                garmin_data_p->ignorePkts++;
+                               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                        }
                }
        }
@@ -935,6 +969,7 @@ static int garmin_init_session(struct usb_serial_port *port)
 
 static int garmin_open (struct usb_serial_port *port, struct file *filp)
 {
+       unsigned long flags;
        int status = 0;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
@@ -948,9 +983,11 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
        if (port->tty)
                port->tty->low_latency = 1;
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->mode  = initial_mode;
        garmin_data_p->count = 0;
        garmin_data_p->flags = 0;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        /* shutdown any bulk reads that might be going on */
        usb_kill_urb (port->write_urb);
@@ -996,6 +1033,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
 
 static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+       unsigned long flags;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
@@ -1007,7 +1045,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        if (urb->status) {
                dbg("%s - nonzero write bulk status received: %d",
                        __FUNCTION__, urb->status);
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
        }
 
        usb_serial_port_softint(port);
@@ -1015,8 +1055,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
 
 static int garmin_write_bulk (struct usb_serial_port *port,
-                              const unsigned char *buf, int count)
+                             const unsigned char *buf, int count)
 {
+       unsigned long flags;
        struct usb_serial *serial = port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        struct urb *urb;
@@ -1026,7 +1067,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
        dbg("%s - port %d, state %d", __FUNCTION__, port->number,
                garmin_data_p->state);
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~FLAGS_DROP_DATA;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        buffer = kmalloc (count, GFP_ATOMIC);
        if (!buffer) {
@@ -1053,7 +1096,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
        urb->transfer_flags |= URB_ZERO_PACKET;
 
        if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                if (garmin_data_p->mode == MODE_GARMIN_SERIAL)  {
                        pkt_clear(garmin_data_p);
                        garmin_data_p->state = STATE_GSP_WAIT_DATA;
@@ -1087,8 +1132,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
 
 
 static int garmin_write (struct usb_serial_port *port,
-                         const unsigned char *buf, int count)
+                        const unsigned char *buf, int count)
 {
+       unsigned long flags;
        int pktid, pktsiz, len;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        __le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
@@ -1139,7 +1185,9 @@ static int garmin_write (struct usb_serial_port *port,
                                break;
 
                        case PRIV_PKTID_RESET_REQ:
+                               spin_lock_irqsave(&garmin_data_p->lock, flags);
                                garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+                               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                                break;
 
                        case PRIV_PKTID_SET_DEF_MODE:
@@ -1155,6 +1203,8 @@ static int garmin_write (struct usb_serial_port *port,
                }
        }
 
+       garmin_data_p->ignorePkts = 0;
+
        if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
                return gsp_receive(garmin_data_p, buf, count);
        } else {        /* MODE_NATIVE */
@@ -1177,10 +1227,10 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
 {
        /*
         * Report back the number of bytes currently in our input buffer.
-         * Will this lock up the driver - the buffer contains an incomplete
-         * package which will not be written to the device until it
-         * has been completed ?
-         */
+        * Will this lock up the driver - the buffer contains an incomplete
+        * package which will not be written to the device until it
+        * has been completed ?
+        */
        //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        //return garmin_data_p->insize;
        return 0;
@@ -1190,6 +1240,8 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
 static void garmin_read_process(struct garmin_data * garmin_data_p,
                                 unsigned char *data, unsigned data_length)
 {
+       unsigned long flags;
+
        if (garmin_data_p->flags & FLAGS_DROP_DATA) {
                /* abort-transfer cmd is actice */
                dbg("%s - pkt dropped", __FUNCTION__);
@@ -1200,11 +1252,14 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
                   if a reset is required or not when closing
                   the device */
                if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
-                               sizeof(GARMIN_APP_LAYER_REPLY)))
+                               sizeof(GARMIN_APP_LAYER_REPLY))) {
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+               }
 
                /* if throttling is active or postprecessing is required
-                  put the received data in th input queue, otherwise
+                  put the received data in the input queue, otherwise
                   send it directly to the tty port */
                if (garmin_data_p->flags & FLAGS_QUEUING) {
                        pkt_add(garmin_data_p, data, data_length);
@@ -1221,6 +1276,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
 
 static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+       unsigned long flags;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial =  port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
@@ -1245,19 +1301,30 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
        garmin_read_process(garmin_data_p, data, urb->actual_length);
 
-       /* Continue trying to read until nothing more is received  */
-       if (urb->actual_length > 0) {
-               usb_fill_bulk_urb (port->read_urb, serial->dev,
-                          usb_rcvbulkpipe (serial->dev,
-                                           port->bulk_in_endpointAddress),
-                          port->read_urb->transfer_buffer,
-                          port->read_urb->transfer_buffer_length,
-                          garmin_read_bulk_callback, port);
+       if (urb->actual_length == 0 &&
+                       0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
+               garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
                if (status)
                        dev_err(&port->dev,
                                "%s - failed resubmitting read urb, error %d\n",
                                __FUNCTION__, status);
+       } else if (urb->actual_length > 0) {
+               /* Continue trying to read until nothing more is received  */
+               if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
+                       status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+                       if (status)
+                               dev_err(&port->dev,
+                                       "%s - failed resubmitting read urb, error %d\n",
+                                       __FUNCTION__, status);
+               }
+       } else {
+               dbg("%s - end of bulk data", __FUNCTION__);
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
+               garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
        }
        return;
 }
@@ -1265,6 +1332,7 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
 static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
 {
+       unsigned long flags;
        int status;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial = port->serial;
@@ -1297,25 +1365,41 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
 
                dbg("%s - bulk data available.", __FUNCTION__);
 
-               /* bulk data available */
-               usb_fill_bulk_urb (port->read_urb, serial->dev,
-                               usb_rcvbulkpipe (serial->dev,
-                               port->bulk_in_endpointAddress),
-                               port->read_urb->transfer_buffer,
-                               port->read_urb->transfer_buffer_length,
-                               garmin_read_bulk_callback, port);
-               status = usb_submit_urb(port->read_urb, GFP_KERNEL);
-               if (status) {
-                       dev_err(&port->dev,
-                               "%s - failed submitting read urb, error %d\n",
-                       __FUNCTION__, status);
+               if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+
+                       /* bulk data available */
+                       usb_fill_bulk_urb (port->read_urb, serial->dev,
+                                       usb_rcvbulkpipe (serial->dev,
+                                       port->bulk_in_endpointAddress),
+                                       port->read_urb->transfer_buffer,
+                                       port->read_urb->transfer_buffer_length,
+                                       garmin_read_bulk_callback, port);
+                       status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+                       if (status) {
+                               dev_err(&port->dev,
+                                       "%s - failed submitting read urb, error %d\n",
+                               __FUNCTION__, status);
+                       } else {
+                               spin_lock_irqsave(&garmin_data_p->lock, flags);
+                               garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
+                               /* do not send this packet to the user */
+                               garmin_data_p->ignorePkts = 1;
+                               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+                       }
+               } else {
+                       /* bulk-in transfer still active */
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
+                       garmin_data_p->flags |= FLAGS_BULK_IN_RESTART;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                }
 
        } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
                         && 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
                                        sizeof(GARMIN_START_SESSION_REPLY))) {
 
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
                /* save the serial number */
                garmin_data_p->serial_num 
@@ -1330,7 +1414,9 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
                   ignore it. */
                dbg("%s - pkt ignored (%d)",
                        __FUNCTION__, garmin_data_p->ignorePkts);
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->ignorePkts--;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
        } else {
                garmin_read_process(garmin_data_p, data, urb->actual_length);
        }
@@ -1351,18 +1437,20 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
  */
 static int garmin_flush_queue(struct garmin_data * garmin_data_p)
 {
+       unsigned long flags;
        struct garmin_packet *pkt;
 
        if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
                pkt = pkt_pop(garmin_data_p);
                if (pkt != NULL) {
-
                        send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
                        kfree(pkt);
                        mod_timer(&garmin_data_p->timer, (1)+jiffies);
 
                } else {
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->flags &= ~FLAGS_QUEUING;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                }
        }
        return 0;
@@ -1371,26 +1459,41 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p)
 
 static void garmin_throttle (struct usb_serial_port *port)
 {
+       unsigned long flags;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
        dbg("%s - port %d", __FUNCTION__, port->number);
        /* set flag, data received will be put into a queue
           for later processing */
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 }
 
 
 static void garmin_unthrottle (struct usb_serial_port *port)
 {
+       unsigned long flags;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+       int status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~FLAGS_THROTTLED;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        /* in native mode send queued data to tty, in
           serial mode nothing needs to be done here */
        if (garmin_data_p->mode == MODE_NATIVE)
                garmin_flush_queue(garmin_data_p);
+
+       if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+               status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+               if (status)
+                       dev_err(&port->dev,
+                               "%s - failed resubmitting read urb, error %d\n",
+                               __FUNCTION__, status);
+       }
 }
 
 
@@ -1420,11 +1523,12 @@ static int garmin_attach (struct usb_serial *serial)
 
        dbg("%s", __FUNCTION__);
 
-       garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+       garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
        if (garmin_data_p == NULL) {
                dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
                return -ENOMEM;
        }
+       memset (garmin_data_p, 0, sizeof(struct garmin_data));
        init_timer(&garmin_data_p->timer);
        spin_lock_init(&garmin_data_p->lock);
        INIT_LIST_HEAD(&garmin_data_p->pktlist);
@@ -1459,10 +1563,10 @@ static void garmin_shutdown (struct usb_serial *serial)
 /* All of the device info needed */
 static struct usb_serial_driver garmin_device = {
        .driver = {
-               .owner =        THIS_MODULE,
-               .name =         "garmin_gps",
+               .owner       = THIS_MODULE,
+               .name        = "garmin_gps",
        },
-       .description =          "Garmin GPS usb/tty",
+       .description         = "Garmin GPS usb/tty",
        .id_table            = id_table,
        .num_interrupt_in    = 1,
        .num_bulk_in         = 1,
@@ -1483,6 +1587,7 @@ static struct usb_serial_driver garmin_device = {
 };
 
 
+
 static int __init garmin_init (void)
 {
        int retval;
index 17271355639397be219a44c2e3c4fe75f13bd7f2..21cbaa0fb96b998e99084ac3bc3ed6db1ac2f3dc 100644 (file)
@@ -175,14 +175,14 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
 
        /* only do something if we have a bulk out endpoint */
        if (serial->num_bulk_out) {
-               spin_lock(&port->lock);
+               spin_lock_bh(&port->lock);
                if (port->write_urb_busy) {
-                       spin_unlock(&port->lock);
+                       spin_unlock_bh(&port->lock);
                        dbg("%s - already writing", __FUNCTION__);
                        return 0;
                }
                port->write_urb_busy = 1;
-               spin_unlock(&port->lock);
+               spin_unlock_bh(&port->lock);
 
                count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
index 9840bade79f974acc9231665498500205ac0ff96..cbc725a6c58eb15aa606f6e40a37b6e3404493bf 100644 (file)
@@ -479,6 +479,7 @@ static struct usb_device_id ipaq_id_table [] = {
        { USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */
        { USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */
        { USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */
+       { USB_DEVICE(0x0BB4, 0x0BCE) }, /* "High Tech Computer Corp" */
        { USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */
        { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
        { USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
@@ -652,11 +653,6 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
        port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
        
        msleep(1000*initial_wait);
-       /* Start reading from the device */
-       usb_fill_bulk_urb(port->read_urb, serial->dev, 
-                     usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-                     port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-                     ipaq_read_bulk_callback, port);
 
        /*
         * Send out control message observed in win98 sniffs. Not sure what
@@ -670,18 +666,31 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
                                0x1, 0, NULL, 0, 100);
-               if (result == 0) {
-                       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-                       if (result) {
-                               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
-                               goto error;
-                       }
-                       return 0;
-               }
+               if (!result)
+                       break;
+
                msleep(1000);
        }
-       err("%s - failed doing control urb, error %d", __FUNCTION__, result);
-       goto error;
+
+       if (!retries && result) {
+               err("%s - failed doing control urb, error %d", __FUNCTION__,
+                   result);
+               goto error;
+       }
+
+       /* Start reading from the device */
+       usb_fill_bulk_urb(port->read_urb, serial->dev,
+                     usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+                     port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+                     ipaq_read_bulk_callback, port);
+
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       if (result) {
+               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+               goto error;
+       }
+
+       return 0;
 
 enomem:
        result = -ENOMEM;
index 87306cb6f9f5a065c6ead79b10e60b77b76a6f2a..812bc213a963349643b0e974cdf8b47629b57fef 100644 (file)
@@ -394,14 +394,14 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
                return 0;
        }
 
-       spin_lock(&port->lock);
+       spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
-               spin_unlock(&port->lock);
+               spin_unlock_bh(&port->lock);
                dbg("%s - already writing", __FUNCTION__);
                return 0;
        }
        port->write_urb_busy = 1;
-       spin_unlock(&port->lock);
+       spin_unlock_bh(&port->lock);
 
        count = min(count, port->bulk_out_size);
        memcpy(port->bulk_out_buffer, buf, count);
index 1738b0b6a376dd90e41a1fadf8a3486eff6f0fac..1b348df388ed2586a2ce0937c3f4af9e3b61c934 100644 (file)
@@ -342,14 +342,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
        if (count == 0)
                return 0;
 
-       spin_lock(&port->lock);
+       spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
-               spin_unlock(&port->lock);
+               spin_unlock_bh(&port->lock);
                dbg("%s - already writing", __FUNCTION__);
                return 0;
        }
        port->write_urb_busy = 1;
-       spin_unlock(&port->lock);
+       spin_unlock_bh(&port->lock);
 
        transfer_buffer = port->write_urb->transfer_buffer;
        transfer_size = min(count, port->bulk_out_size - 1);
index 49b8dc039d1fef8f68aca71fee6efdb02082f458..59e777f1e8fdd3502eafab416be7d84bdc15d7ee 100644 (file)
@@ -518,13 +518,13 @@ static int keyspan_pda_write(struct usb_serial_port *port,
           the TX urb is in-flight (wait until it completes)
           the device is full (wait until it says there is room)
        */
-       spin_lock(&port->lock);
+       spin_lock_bh(&port->lock);
        if (port->write_urb_busy || priv->tx_throttled) {
-               spin_unlock(&port->lock);
+               spin_unlock_bh(&port->lock);
                return 0;
        }
        port->write_urb_busy = 1;
-       spin_unlock(&port->lock);
+       spin_unlock_bh(&port->lock);
 
        /* At this point the URB is in our control, nobody else can submit it
           again (the only sudden transition was the one from EINPROGRESS to
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
new file mode 100644 (file)
index 0000000..95bf571
--- /dev/null
@@ -0,0 +1,2962 @@
+/*
+ * 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
+ *
+ * Clean ups from Moschip version and a few ioctl implementations by:
+ *     Paul B Schroeder <pschroeder "at" uplogix "dot" com>
+ *
+ * Originally based on drivers/usb/serial/io_edgeport.c which is:
+ *      Copyright (C) 2000 Inside Out Networks, All rights reserved.
+ *      Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.3.1"
+#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
+
+/*
+ * 16C50 UART register defines
+ */
+
+#define LCR_BITS_5             0x00    /* 5 bits/char */
+#define LCR_BITS_6             0x01    /* 6 bits/char */
+#define LCR_BITS_7             0x02    /* 7 bits/char */
+#define LCR_BITS_8             0x03    /* 8 bits/char */
+#define LCR_BITS_MASK          0x03    /* Mask for bits/char field */
+
+#define LCR_STOP_1             0x00    /* 1 stop bit */
+#define LCR_STOP_1_5           0x04    /* 1.5 stop bits (if 5   bits/char) */
+#define LCR_STOP_2             0x04    /* 2 stop bits   (if 6-8 bits/char) */
+#define LCR_STOP_MASK          0x04    /* Mask for stop bits field */
+
+#define LCR_PAR_NONE           0x00    /* No parity */
+#define LCR_PAR_ODD            0x08    /* Odd parity */
+#define LCR_PAR_EVEN           0x18    /* Even parity */
+#define LCR_PAR_MARK           0x28    /* Force parity bit to 1 */
+#define LCR_PAR_SPACE          0x38    /* Force parity bit to 0 */
+#define LCR_PAR_MASK           0x38    /* Mask for parity field */
+
+#define LCR_SET_BREAK          0x40    /* Set Break condition */
+#define LCR_DL_ENABLE          0x80    /* Enable access to divisor latch */
+
+#define MCR_DTR                0x01    /* Assert DTR */
+#define MCR_RTS                0x02    /* Assert RTS */
+#define MCR_OUT1               0x04    /* Loopback only: Sets state of RI */
+#define MCR_MASTER_IE          0x08    /* Enable interrupt outputs */
+#define MCR_LOOPBACK           0x10    /* Set internal (digital) loopback mode */
+#define MCR_XON_ANY            0x20    /* Enable any char to exit XOFF mode */
+
+#define MOS7840_MSR_CTS        0x10    /* Current state of CTS */
+#define MOS7840_MSR_DSR        0x20    /* Current state of DSR */
+#define MOS7840_MSR_RI         0x40    /* Current state of RI */
+#define MOS7840_MSR_CD         0x80    /* Current state of CD */
+
+/*
+ * Defines used for sending commands to port
+ */
+
+#define WAIT_FOR_EVER   (HZ * 0 )      /* timeout urb is wait for ever */
+#define MOS_WDR_TIMEOUT (HZ * 5 )      /* default urb timeout */
+
+#define MOS_PORT1       0x0200
+#define MOS_PORT2       0x0300
+#define MOS_VENREG      0x0000
+#define MOS_MAX_PORT   0x02
+#define MOS_WRITE       0x0E
+#define MOS_READ        0x0D
+
+/* Requests */
+#define MCS_RD_RTYPE    0xC0
+#define MCS_WR_RTYPE    0x40
+#define MCS_RDREQ       0x0D
+#define MCS_WRREQ       0x0E
+#define MCS_CTRL_TIMEOUT        500
+#define VENDOR_READ_LENGTH      (0x01)
+
+#define MAX_NAME_LEN    64
+
+#define ZLP_REG1  0x3A         //Zero_Flag_Reg1    58
+#define ZLP_REG5  0x3E         //Zero_Flag_Reg5    62
+
+/* For higher baud Rates use TIOCEXBAUD */
+#define TIOCEXBAUD     0x5462
+
+/* vendor id and device id defines */
+
+#define USB_VENDOR_ID_MOSCHIP           0x9710
+#define MOSCHIP_DEVICE_ID_7840          0x7840
+#define MOSCHIP_DEVICE_ID_7820          0x7820
+
+/* Interrupt Rotinue Defines    */
+
+#define SERIAL_IIR_RLS      0x06
+#define SERIAL_IIR_MS       0x00
+
+/*
+ *  Emulation of the bit mask on the LINE STATUS REGISTER.
+ */
+#define SERIAL_LSR_DR       0x0001
+#define SERIAL_LSR_OE       0x0002
+#define SERIAL_LSR_PE       0x0004
+#define SERIAL_LSR_FE       0x0008
+#define SERIAL_LSR_BI       0x0010
+
+#define MOS_MSR_DELTA_CTS   0x10
+#define MOS_MSR_DELTA_DSR   0x20
+#define MOS_MSR_DELTA_RI    0x40
+#define MOS_MSR_DELTA_CD    0x80
+
+// Serial Port register Address
+#define INTERRUPT_ENABLE_REGISTER  ((__u16)(0x01))
+#define FIFO_CONTROL_REGISTER      ((__u16)(0x02))
+#define LINE_CONTROL_REGISTER      ((__u16)(0x03))
+#define MODEM_CONTROL_REGISTER     ((__u16)(0x04))
+#define LINE_STATUS_REGISTER       ((__u16)(0x05))
+#define MODEM_STATUS_REGISTER      ((__u16)(0x06))
+#define SCRATCH_PAD_REGISTER       ((__u16)(0x07))
+#define DIVISOR_LATCH_LSB          ((__u16)(0x00))
+#define DIVISOR_LATCH_MSB          ((__u16)(0x01))
+
+#define CLK_MULTI_REGISTER         ((__u16)(0x02))
+#define CLK_START_VALUE_REGISTER   ((__u16)(0x03))
+
+#define SERIAL_LCR_DLAB            ((__u16)(0x0080))
+
+/*
+ * URB POOL related defines
+ */
+#define NUM_URBS                        16     /* URB Count */
+#define URB_TRANSFER_BUFFER_SIZE        32     /* URB Size  */
+
+
+static struct usb_device_id moschip_port_id_table[] = {
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+       {}                      /* terminating entry */
+};
+
+static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+       {}                      /* terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);
+
+/* This structure holds all of the local port information */
+
+struct moschip_port {
+       int port_num;           /*Actual port number in the device(1,2,etc) */
+       struct urb *write_urb;  /* write URB for this port */
+       struct urb *read_urb;   /* read URB for this port */
+       __u8 shadowLCR;         /* last LCR value received */
+       __u8 shadowMCR;         /* last MCR value received */
+       char open;
+       wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
+       wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
+       int delta_msr_cond;
+       struct async_icount icount;
+       struct usb_serial_port *port;   /* loop back to the owner of this object */
+
+       /*Offsets */
+       __u8 SpRegOffset;
+       __u8 ControlRegOffset;
+       __u8 DcrRegOffset;
+       //for processing control URBS in interrupt context
+       struct urb *control_urb;
+       char *ctrl_buf;
+       int MsrLsr;
+
+       struct urb *write_urb_pool[NUM_URBS];
+};
+
+
+static int debug;
+static int mos7840_num_ports;  //this says the number of ports in the device
+static int mos7840_num_open_ports;
+
+
+/*
+ * mos7840_set_reg_sync
+ *     To set the Control register by calling usb_fill_control_urb function
+ *     by passing usb_sndctrlpipe function as parameter.
+ */
+
+static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
+                               __u16 val)
+{
+       struct usb_device *dev = port->serial->dev;
+       val = val & 0x00ff;
+       dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val);
+
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+                              MCS_WR_RTYPE, val, reg, NULL, 0,
+                              MOS_WDR_TIMEOUT);
+}
+
+/*
+ * mos7840_get_reg_sync
+ *     To set the Uart register by calling usb_fill_control_urb function by
+ *     passing usb_rcvctrlpipe function as parameter.
+ */
+
+static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
+                               __u16 * val)
+{
+       struct usb_device *dev = port->serial->dev;
+       int ret = 0;
+
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+                             MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
+                             MOS_WDR_TIMEOUT);
+       dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val);
+       *val = (*val) & 0x00ff;
+       return ret;
+}
+
+/*
+ * mos7840_set_uart_reg
+ *     To set the Uart register by calling usb_fill_control_urb function by
+ *     passing usb_sndctrlpipe function as parameter.
+ */
+
+static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
+                               __u16 val)
+{
+
+       struct usb_device *dev = port->serial->dev;
+       val = val & 0x00ff;
+       // For the UART control registers, the application number need to be Or'ed
+       if (mos7840_num_ports == 4) {
+               val |=
+                   (((__u16) port->number - (__u16) (port->serial->minor)) +
+                    1) << 8;
+               dbg("mos7840_set_uart_reg application number is %x\n", val);
+       } else {
+               if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
+                       val |=
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 1) << 8;
+                       dbg("mos7840_set_uart_reg application number is %x\n",
+                           val);
+               } else {
+                       val |=
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 2) << 8;
+                       dbg("mos7840_set_uart_reg application number is %x\n",
+                           val);
+               }
+       }
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+                              MCS_WR_RTYPE, val, reg, NULL, 0,
+                              MOS_WDR_TIMEOUT);
+
+}
+
+/*
+ * mos7840_get_uart_reg
+ *     To set the Control register by calling usb_fill_control_urb function
+ *     by passing usb_rcvctrlpipe function as parameter.
+ */
+static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
+                               __u16 * val)
+{
+       struct usb_device *dev = port->serial->dev;
+       int ret = 0;
+       __u16 Wval;
+
+       //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
+       /*Wval  is same as application number */
+       if (mos7840_num_ports == 4) {
+               Wval =
+                   (((__u16) port->number - (__u16) (port->serial->minor)) +
+                    1) << 8;
+               dbg("mos7840_get_uart_reg application number is %x\n", Wval);
+       } else {
+               if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
+                       Wval =
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 1) << 8;
+                       dbg("mos7840_get_uart_reg application number is %x\n",
+                           Wval);
+               } else {
+                       Wval =
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 2) << 8;
+                       dbg("mos7840_get_uart_reg application number is %x\n",
+                           Wval);
+               }
+       }
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+                             MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,
+                             MOS_WDR_TIMEOUT);
+       *val = (*val) & 0x00ff;
+       return ret;
+}
+
+static void mos7840_dump_serial_port(struct moschip_port *mos7840_port)
+{
+
+       dbg("***************************************\n");
+       dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset);
+       dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset);
+       dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset);
+       dbg("***************************************\n");
+
+}
+
+/************************************************************************/
+/************************************************************************/
+/*             I N T E R F A C E   F U N C T I O N S                   */
+/*             I N T E R F A C E   F U N C T I O N S                   */
+/************************************************************************/
+/************************************************************************/
+
+static inline void mos7840_set_port_private(struct usb_serial_port *port,
+                                           struct moschip_port *data)
+{
+       usb_set_serial_port_data(port, (void *)data);
+}
+
+static inline struct moschip_port *mos7840_get_port_private(struct
+                                                           usb_serial_port
+                                                           *port)
+{
+       return (struct moschip_port *)usb_get_serial_port_data(port);
+}
+
+static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
+{
+       struct moschip_port *mos7840_port;
+       struct async_icount *icount;
+       mos7840_port = port;
+       icount = &mos7840_port->icount;
+       if (new_msr &
+           (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
+            MOS_MSR_DELTA_CD)) {
+               icount = &mos7840_port->icount;
+
+               /* update input line counters */
+               if (new_msr & MOS_MSR_DELTA_CTS) {
+                       icount->cts++;
+               }
+               if (new_msr & MOS_MSR_DELTA_DSR) {
+                       icount->dsr++;
+               }
+               if (new_msr & MOS_MSR_DELTA_CD) {
+                       icount->dcd++;
+               }
+               if (new_msr & MOS_MSR_DELTA_RI) {
+                       icount->rng++;
+               }
+       }
+
+       return 0;
+}
+
+static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
+{
+       struct async_icount *icount;
+
+       dbg("%s - %02x", __FUNCTION__, new_lsr);
+
+       if (new_lsr & SERIAL_LSR_BI) {
+               //
+               // Parity and Framing errors only count if they
+               // occur exclusive of a break being
+               // received.
+               //
+               new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
+       }
+
+       /* update input line counters */
+       icount = &port->icount;
+       if (new_lsr & SERIAL_LSR_BI) {
+               icount->brk++;
+       }
+       if (new_lsr & SERIAL_LSR_OE) {
+               icount->overrun++;
+       }
+       if (new_lsr & SERIAL_LSR_PE) {
+               icount->parity++;
+       }
+       if (new_lsr & SERIAL_LSR_FE) {
+               icount->frame++;
+       }
+
+       return 0;
+}
+
+/************************************************************************/
+/************************************************************************/
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/************************************************************************/
+/************************************************************************/
+
+static void mos7840_control_callback(struct urb *urb, struct pt_regs *regs)
+{
+       unsigned char *data;
+       struct moschip_port *mos7840_port;
+       __u8 regval = 0x0;
+
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+                   urb->status);
+               goto exit;
+       }
+
+       mos7840_port = (struct moschip_port *)urb->context;
+
+       dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
+       dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
+           mos7840_port->MsrLsr, mos7840_port->port_num);
+       data = urb->transfer_buffer;
+       regval = (__u8) data[0];
+       dbg("%s data is %x\n", __FUNCTION__, regval);
+       if (mos7840_port->MsrLsr == 0)
+               mos7840_handle_new_msr(mos7840_port, regval);
+       else if (mos7840_port->MsrLsr == 1)
+               mos7840_handle_new_lsr(mos7840_port, regval);
+
+      exit:
+       return;
+}
+
+static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
+                          __u16 * val)
+{
+       struct usb_device *dev = mcs->port->serial->dev;
+       struct usb_ctrlrequest *dr = NULL;
+       unsigned char *buffer = NULL;
+       int ret = 0;
+       buffer = (__u8 *) mcs->ctrl_buf;
+
+//      dr=(struct usb_ctrlrequest *)(buffer);
+       dr = (void *)(buffer + 2);
+       dr->bRequestType = MCS_RD_RTYPE;
+       dr->bRequest = MCS_RDREQ;
+       dr->wValue = cpu_to_le16(Wval); //0;
+       dr->wIndex = cpu_to_le16(reg);
+       dr->wLength = cpu_to_le16(2);
+
+       usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0),
+                            (unsigned char *)dr, buffer, 2,
+                            mos7840_control_callback, mcs);
+       mcs->control_urb->transfer_buffer_length = 2;
+       ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+       return ret;
+}
+
+/*****************************************************************************
+ * mos7840_interrupt_callback
+ *     this is the callback function for when we have received data on the
+ *     interrupt endpoint.
+ *****************************************************************************/
+
+static void mos7840_interrupt_callback(struct urb *urb, struct pt_regs *regs)
+{
+       int result;
+       int length;
+       struct moschip_port *mos7840_port;
+       struct usb_serial *serial;
+       __u16 Data;
+       unsigned char *data;
+       __u8 sp[5], st;
+       int i;
+       __u16 wval;
+
+       dbg("%s", " : Entering\n");
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+                   urb->status);
+               goto exit;
+       }
+
+       length = urb->actual_length;
+       data = urb->transfer_buffer;
+
+       serial = (struct usb_serial *)urb->context;
+
+       /* Moschip get 5 bytes
+        * Byte 1 IIR Port 1 (port.number is 0)
+        * Byte 2 IIR Port 2 (port.number is 1)
+        * Byte 3 IIR Port 3 (port.number is 2)
+        * Byte 4 IIR Port 4 (port.number is 3)
+        * Byte 5 FIFO status for both */
+
+       if (length && length > 5) {
+               dbg("%s \n", "Wrong data !!!");
+               return;
+       }
+
+       sp[0] = (__u8) data[0];
+       sp[1] = (__u8) data[1];
+       sp[2] = (__u8) data[2];
+       sp[3] = (__u8) data[3];
+       st = (__u8) data[4];
+
+       for (i = 0; i < serial->num_ports; i++) {
+               mos7840_port = mos7840_get_port_private(serial->port[i]);
+               wval =
+                   (((__u16) serial->port[i]->number -
+                     (__u16) (serial->minor)) + 1) << 8;
+               if (mos7840_port->open) {
+                       if (sp[i] & 0x01) {
+                               dbg("SP%d No Interrupt !!!\n", i);
+                       } else {
+                               switch (sp[i] & 0x0f) {
+                               case SERIAL_IIR_RLS:
+                                       dbg("Serial Port %d: Receiver status error or ", i);
+                                       dbg("address bit detected in 9-bit mode\n");
+                                       mos7840_port->MsrLsr = 1;
+                                       mos7840_get_reg(mos7840_port, wval,
+                                                       LINE_STATUS_REGISTER,
+                                                       &Data);
+                                       break;
+                               case SERIAL_IIR_MS:
+                                       dbg("Serial Port %d: Modem status change\n", i);
+                                       mos7840_port->MsrLsr = 0;
+                                       mos7840_get_reg(mos7840_port, wval,
+                                                       MODEM_STATUS_REGISTER,
+                                                       &Data);
+                                       break;
+                               }
+                       }
+               }
+       }
+      exit:
+       result = usb_submit_urb(urb, GFP_ATOMIC);
+       if (result) {
+               dev_err(&urb->dev->dev,
+                       "%s - Error %d submitting interrupt urb\n",
+                       __FUNCTION__, result);
+       }
+
+       return;
+
+}
+
+static int mos7840_port_paranoia_check(struct usb_serial_port *port,
+                                      const char *function)
+{
+       if (!port) {
+               dbg("%s - port == NULL", function);
+               return -1;
+       }
+       if (!port->serial) {
+               dbg("%s - port->serial == NULL", function);
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static int mos7840_serial_paranoia_check(struct usb_serial *serial,
+                                        const char *function)
+{
+       if (!serial) {
+               dbg("%s - serial == NULL", function);
+               return -1;
+       }
+       if (!serial->type) {
+               dbg("%s - serial->type == NULL!", function);
+               return -1;
+       }
+
+       return 0;
+}
+
+static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
+                                                const char *function)
+{
+       /* if no port was specified, or it fails a paranoia check */
+       if (!port ||
+           mos7840_port_paranoia_check(port, function) ||
+           mos7840_serial_paranoia_check(port->serial, function)) {
+               /* then say that we don't have a valid usb_serial thing, which will                  * end up genrating -ENODEV return values */
+               return NULL;
+       }
+
+       return port->serial;
+}
+
+/*****************************************************************************
+ * mos7840_bulk_in_callback
+ *     this is the callback function for when we have received data on the
+ *     bulk in endpoint.
+ *****************************************************************************/
+
+static void mos7840_bulk_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+       int status;
+       unsigned char *data;
+       struct usb_serial *serial;
+       struct usb_serial_port *port;
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       if (urb->status) {
+               dbg("nonzero read bulk status received: %d", urb->status);
+               return;
+       }
+
+       mos7840_port = (struct moschip_port *)urb->context;
+       if (!mos7840_port) {
+               dbg("%s", "NULL mos7840_port pointer \n");
+               return;
+       }
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       if (!serial) {
+               dbg("%s\n", "Bad serial pointer ");
+               return;
+       }
+
+       dbg("%s\n", "Entering... \n");
+
+       data = urb->transfer_buffer;
+
+       dbg("%s", "Entering ........... \n");
+
+       if (urb->actual_length) {
+               tty = mos7840_port->port->tty;
+               if (tty) {
+                       tty_buffer_request_room(tty, urb->actual_length);
+                       tty_insert_flip_string(tty, data, urb->actual_length);
+                       dbg(" %s \n", data);
+                       tty_flip_buffer_push(tty);
+               }
+               mos7840_port->icount.rx += urb->actual_length;
+               dbg("mos7840_port->icount.rx is %d:\n",
+                   mos7840_port->icount.rx);
+       }
+
+       if (!mos7840_port->read_urb) {
+               dbg("%s", "URB KILLED !!!\n");
+               return;
+       }
+
+       if (mos7840_port->read_urb->status != -EINPROGRESS) {
+               mos7840_port->read_urb->dev = serial->dev;
+
+               status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+               if (status) {
+                       dbg(" usb_submit_urb(read bulk) failed, status = %d",
+                           status);
+               }
+       }
+}
+
+/*****************************************************************************
+ * mos7840_bulk_out_data_callback
+ *     this is the callback function for when we have finished sending serial data
+ *     on the bulk out endpoint.
+ *****************************************************************************/
+
+static void mos7840_bulk_out_data_callback(struct urb *urb,
+                                          struct pt_regs *regs)
+{
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       if (urb->status) {
+               dbg("nonzero write bulk status received:%d\n", urb->status);
+               return;
+       }
+
+       mos7840_port = (struct moschip_port *)urb->context;
+       if (!mos7840_port) {
+               dbg("%s", "NULL mos7840_port pointer \n");
+               return;
+       }
+
+       if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       dbg("%s \n", "Entering .........");
+
+       tty = mos7840_port->port->tty;
+
+       if (tty && mos7840_port->open) {
+               /* let the tty driver wakeup if it has a special *
+                * write_wakeup function                         */
+
+               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
+                   && tty->ldisc.write_wakeup) {
+                       (tty->ldisc.write_wakeup) (tty);
+               }
+
+               /* tell the tty driver that something has changed */
+               wake_up_interruptible(&tty->write_wait);
+       }
+
+}
+
+/************************************************************************/
+/*       D R I V E R  T T Y  I N T E R F A C E  F U N C T I O N S       */
+/************************************************************************/
+#ifdef MCSSerialProbe
+static int mos7840_serial_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id)
+{
+
+       /*need to implement the mode_reg reading and updating\
+          structures usb_serial_ device_type\
+          (i.e num_ports, num_bulkin,bulkout etc) */
+       /* Also we can update the changes  attach */
+       return 1;
+}
+#endif
+
+/*****************************************************************************
+ * mos7840_open
+ *     this function is called by the tty driver when a port is opened
+ *     If successful, we return 0
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+{
+       int response;
+       int j;
+       struct usb_serial *serial;
+       struct urb *urb;
+       __u16 Data;
+       int status;
+       struct moschip_port *mos7840_port;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return -ENODEV;
+       }
+
+       mos7840_num_open_ports++;
+       serial = port->serial;
+
+       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return -ENODEV;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return -ENODEV;
+
+       usb_clear_halt(serial->dev, port->write_urb->pipe);
+       usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+       /* Initialising the write urb pool */
+       for (j = 0; j < NUM_URBS; ++j) {
+               urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               mos7840_port->write_urb_pool[j] = urb;
+
+               if (urb == NULL) {
+                       err("No more urbs???");
+                       continue;
+               }
+
+               urb->transfer_buffer = NULL;
+               urb->transfer_buffer =
+                   kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+               if (!urb->transfer_buffer) {
+                       err("%s-out of memory for urb buffers.", __FUNCTION__);
+                       continue;
+               }
+       }
+
+/*****************************************************************************
+ * Initialize MCS7840 -- Write Init values to corresponding Registers
+ *
+ * Register Index
+ * 1 : IER
+ * 2 : FCR
+ * 3 : LCR
+ * 4 : MCR
+ *
+ * 0x08 : SP1/2 Control Reg
+ *****************************************************************************/
+
+//NEED to check the following Block
+
+       status = 0;
+       Data = 0x0;
+       status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
+       if (status < 0) {
+               dbg("Reading Spreg failed\n");
+               return -1;
+       }
+       Data |= 0x80;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+       if (status < 0) {
+               dbg("writing Spreg failed\n");
+               return -1;
+       }
+
+       Data &= ~0x80;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+       if (status < 0) {
+               dbg("writing Spreg failed\n");
+               return -1;
+       }
+//End of block to be checked
+
+       status = 0;
+       Data = 0x0;
+       status =
+           mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+       if (status < 0) {
+               dbg("Reading Controlreg failed\n");
+               return -1;
+       }
+       Data |= 0x08;           //Driver done bit
+       Data |= 0x20;           //rx_disable
+       status = 0;
+       status =
+           mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+       if (status < 0) {
+               dbg("writing Controlreg failed\n");
+               return -1;
+       }
+       //do register settings here
+       // Set all regs to the device default values.
+       ////////////////////////////////////
+       // First Disable all interrupts.
+       ////////////////////////////////////
+
+       Data = 0x00;
+       status = 0;
+       status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+       if (status < 0) {
+               dbg("disableing interrupts failed\n");
+               return -1;
+       }
+       // Set FIFO_CONTROL_REGISTER to the default value
+       Data = 0x00;
+       status = 0;
+       status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+       if (status < 0) {
+               dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
+               return -1;
+       }
+
+       Data = 0xcf;
+       status = 0;
+       status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+       if (status < 0) {
+               dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
+               return -1;
+       }
+
+       Data = 0x03;
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+       mos7840_port->shadowLCR = Data;
+
+       Data = 0x0b;
+       status = 0;
+       status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+       mos7840_port->shadowMCR = Data;
+
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+       mos7840_port->shadowLCR = Data;
+
+       Data |= SERIAL_LCR_DLAB;        //data latch enable in LCR 0x80
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       Data = 0x0c;
+       status = 0;
+       status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
+
+       Data = 0x0;
+       status = 0;
+       status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
+
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+
+       Data = Data & ~SERIAL_LCR_DLAB;
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+       mos7840_port->shadowLCR = Data;
+
+       //clearing Bulkin and Bulkout Fifo
+       Data = 0x0;
+       status = 0;
+       status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
+
+       Data = Data | 0x0c;
+       status = 0;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+
+       Data = Data & ~0x0c;
+       status = 0;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+       //Finally enable all interrupts
+       Data = 0x0;
+       Data = 0x0c;
+       status = 0;
+       status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       //clearing rx_disable
+       Data = 0x0;
+       status = 0;
+       status =
+           mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+       Data = Data & ~0x20;
+       status = 0;
+       status =
+           mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+
+       // rx_negate
+       Data = 0x0;
+       status = 0;
+       status =
+           mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+       Data = Data | 0x10;
+       status = 0;
+       status =
+           mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+
+       /* force low_latency on so that our tty_push actually forces *
+        * the data through,otherwise it is scheduled, and with      *
+        * high data rates (like with OHCI) data can get lost.       */
+
+       if (port->tty)
+               port->tty->low_latency = 1;
+/* Check to see if we've set up our endpoint info yet    *
+     * (can't set it up in mos7840_startup as the structures *
+     * were not set up at that time.)                        */
+       if (mos7840_num_open_ports == 1) {
+               if (serial->port[0]->interrupt_in_buffer == NULL) {
+
+                       /* set up interrupt urb */
+
+                       usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
+                                        serial->dev,
+                                        usb_rcvintpipe(serial->dev,
+                                                       serial->port[0]->
+                                                       interrupt_in_endpointAddress),
+                                        serial->port[0]->interrupt_in_buffer,
+                                        serial->port[0]->interrupt_in_urb->
+                                        transfer_buffer_length,
+                                        mos7840_interrupt_callback,
+                                        serial,
+                                        serial->port[0]->interrupt_in_urb->
+                                        interval);
+
+                       /* start interrupt read for mos7840               *
+                        * will continue as long as mos7840 is connected  */
+
+                       response =
+                           usb_submit_urb(serial->port[0]->interrupt_in_urb,
+                                          GFP_KERNEL);
+                       if (response) {
+                               err("%s - Error %d submitting interrupt urb",
+                                   __FUNCTION__, response);
+                       }
+
+               }
+
+       }
+
+       /* see if we've set up our endpoint info yet   *
+        * (can't set it up in mos7840_startup as the  *
+        * structures were not set up at that time.)   */
+
+       dbg("port number is %d \n", port->number);
+       dbg("serial number is %d \n", port->serial->minor);
+       dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress);
+       dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress);
+       dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress);
+       dbg("port's number in the device is %d\n", mos7840_port->port_num);
+       mos7840_port->read_urb = port->read_urb;
+
+       /* set up our bulk in urb */
+
+       usb_fill_bulk_urb(mos7840_port->read_urb,
+                         serial->dev,
+                         usb_rcvbulkpipe(serial->dev,
+                                         port->bulk_in_endpointAddress),
+                         port->bulk_in_buffer,
+                         mos7840_port->read_urb->transfer_buffer_length,
+                         mos7840_bulk_in_callback, mos7840_port);
+
+       dbg("mos7840_open: bulkin endpoint is %d\n",
+           port->bulk_in_endpointAddress);
+       response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
+       if (response) {
+               err("%s - Error %d submitting control urb", __FUNCTION__,
+                   response);
+       }
+
+       /* initialize our wait queues */
+       init_waitqueue_head(&mos7840_port->wait_chase);
+       init_waitqueue_head(&mos7840_port->delta_msr_wait);
+
+       /* initialize our icount structure */
+       memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
+
+       /* initialize our port settings */
+       mos7840_port->shadowMCR = MCR_MASTER_IE;        /* Must set to enable ints! */
+       /* send a open port command */
+       mos7840_port->open = 1;
+       //mos7840_change_port_settings(mos7840_port,old_termios);
+       mos7840_port->icount.tx = 0;
+       mos7840_port->icount.rx = 0;
+
+       dbg("\n\nusb_serial serial:%x       mos7840_port:%x\n      usb_serial_port port:%x\n\n", (unsigned int)serial, (unsigned int)mos7840_port, (unsigned int)port);
+
+       return 0;
+
+}
+
+/*****************************************************************************
+ * mos7840_chars_in_buffer
+ *     this function is called by the tty driver when it wants to know how many
+ *     bytes of data we currently have outstanding in the port (data that has
+ *     been written, but hasn't made it out the port yet)
+ *     If successful, we return the number of bytes left to be written in the
+ *     system,
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+{
+       int i;
+       int chars = 0;
+       struct moschip_port *mos7840_port;
+
+       dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       if (mos7840_port == NULL) {
+               dbg("%s \n", "mos7840_break:leaving ...........");
+               return -1;
+       }
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (mos7840_port->write_urb_pool[i]->status == -EINPROGRESS) {
+                       chars += URB_TRANSFER_BUFFER_SIZE;
+               }
+       }
+       dbg("%s - returns %d", __FUNCTION__, chars);
+       return (chars);
+
+}
+
+/************************************************************************
+ *
+ * mos7840_block_until_tx_empty
+ *
+ *     This function will block the close until one of the following:
+ *             1. TX count are 0
+ *             2. The mos7840 has stopped
+ *             3. A timout of 3 seconds without activity has expired
+ *
+ ************************************************************************/
+static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+{
+       int timeout = HZ / 10;
+       int wait = 30;
+       int count;
+
+       while (1) {
+
+               count = mos7840_chars_in_buffer(mos7840_port->port);
+
+               /* Check for Buffer status */
+               if (count <= 0) {
+                       return;
+               }
+
+               /* Block the thread for a while */
+               interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
+                                              timeout);
+
+               /* No activity.. count down section */
+               wait--;
+               if (wait == 0) {
+                       dbg("%s - TIMEOUT", __FUNCTION__);
+                       return;
+               } else {
+                       /* Reset timout value back to seconds */
+                       wait = 30;
+               }
+       }
+}
+
+/*****************************************************************************
+ * mos7840_close
+ *     this function is called by the tty driver when a port is closed
+ *****************************************************************************/
+
+static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+{
+       struct usb_serial *serial;
+       struct moschip_port *mos7840_port;
+       int j;
+       __u16 Data;
+
+       dbg("%s\n", "mos7840_close:entering...");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       if (!serial) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL) {
+               return;
+       }
+
+       for (j = 0; j < NUM_URBS; ++j)
+               usb_kill_urb(mos7840_port->write_urb_pool[j]);
+
+       /* Freeing Write URBs */
+       for (j = 0; j < NUM_URBS; ++j) {
+               if (mos7840_port->write_urb_pool[j]) {
+                       if (mos7840_port->write_urb_pool[j]->transfer_buffer)
+                               kfree(mos7840_port->write_urb_pool[j]->
+                                     transfer_buffer);
+
+                       usb_free_urb(mos7840_port->write_urb_pool[j]);
+               }
+       }
+
+       if (serial->dev) {
+               /* flush and block until tx is empty */
+               mos7840_block_until_tx_empty(mos7840_port);
+       }
+
+       /* While closing port, shutdown all bulk read, write  *
+        * and interrupt read if they exists                  */
+       if (serial->dev) {
+
+               if (mos7840_port->write_urb) {
+                       dbg("%s", "Shutdown bulk write\n");
+                       usb_kill_urb(mos7840_port->write_urb);
+               }
+
+               if (mos7840_port->read_urb) {
+                       dbg("%s", "Shutdown bulk read\n");
+                       usb_kill_urb(mos7840_port->read_urb);
+               }
+               if ((&mos7840_port->control_urb)) {
+                       dbg("%s", "Shutdown control read\n");
+                       //      usb_kill_urb (mos7840_port->control_urb);
+
+               }
+       }
+//              if(mos7840_port->ctrl_buf != NULL)
+//                      kfree(mos7840_port->ctrl_buf);
+       mos7840_num_open_ports--;
+       dbg("mos7840_num_open_ports in close%d:in port%d\n",
+           mos7840_num_open_ports, port->number);
+       if (mos7840_num_open_ports == 0) {
+               if (serial->port[0]->interrupt_in_urb) {
+                       dbg("%s", "Shutdown interrupt_in_urb\n");
+               }
+       }
+
+       if (mos7840_port->write_urb) {
+               /* if this urb had a transfer buffer already (old tx) free it */
+
+               if (mos7840_port->write_urb->transfer_buffer != NULL) {
+                       kfree(mos7840_port->write_urb->transfer_buffer);
+               }
+               usb_free_urb(mos7840_port->write_urb);
+       }
+
+       Data = 0x0;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+       Data = 0x00;
+       mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       mos7840_port->open = 0;
+
+       dbg("%s \n", "Leaving ............");
+}
+
+/************************************************************************
+ *
+ * mos7840_block_until_chase_response
+ *
+ *     This function will block the close until one of the following:
+ *             1. Response to our Chase comes from mos7840
+ *             2. A timout of 10 seconds without activity has expired
+ *                (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
+ *
+ ************************************************************************/
+
+static void mos7840_block_until_chase_response(struct moschip_port
+                                              *mos7840_port)
+{
+       int timeout = 1 * HZ;
+       int wait = 10;
+       int count;
+
+       while (1) {
+               count = mos7840_chars_in_buffer(mos7840_port->port);
+
+               /* Check for Buffer status */
+               if (count <= 0) {
+                       return;
+               }
+
+               /* Block the thread for a while */
+               interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
+                                              timeout);
+               /* No activity.. count down section */
+               wait--;
+               if (wait == 0) {
+                       dbg("%s - TIMEOUT", __FUNCTION__);
+                       return;
+               } else {
+                       /* Reset timout value back to seconds */
+                       wait = 10;
+               }
+       }
+
+}
+
+/*****************************************************************************
+ * mos7840_break
+ *     this function sends a break to the port
+ *****************************************************************************/
+static void mos7840_break(struct usb_serial_port *port, int break_state)
+{
+       unsigned char data;
+       struct usb_serial *serial;
+       struct moschip_port *mos7840_port;
+
+       dbg("%s \n", "Entering ...........");
+       dbg("mos7840_break: Start\n");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       if (!serial) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL) {
+               return;
+       }
+
+       if (serial->dev) {
+
+               /* flush and block until tx is empty */
+               mos7840_block_until_chase_response(mos7840_port);
+       }
+
+       if (break_state == -1) {
+               data = mos7840_port->shadowLCR | LCR_SET_BREAK;
+       } else {
+               data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
+       }
+
+       mos7840_port->shadowLCR = data;
+       dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+       mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
+                            mos7840_port->shadowLCR);
+
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_write_room
+ *     this function is called by the tty driver when it wants to know how many
+ *     bytes of data we can accept for a specific port.
+ *     If successful, we return the amount of room that we have for this port
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_write_room(struct usb_serial_port *port)
+{
+       int i;
+       int room = 0;
+       struct moschip_port *mos7840_port;
+
+       dbg("%s \n", " mos7840_write_room:entering ...........");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               dbg("%s \n", " mos7840_write_room:leaving ...........");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       if (mos7840_port == NULL) {
+               dbg("%s \n", "mos7840_break:leaving ...........");
+               return -1;
+       }
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+                       room += URB_TRANSFER_BUFFER_SIZE;
+               }
+       }
+
+       dbg("%s - returns %d", __FUNCTION__, room);
+       return (room);
+
+}
+
+/*****************************************************************************
+ * mos7840_write
+ *     this function is called by the tty driver when data should be written to
+ *     the port.
+ *     If successful, we return the number of bytes written, otherwise we
+ *      return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_write(struct usb_serial_port *port,
+                        const unsigned char *data, int count)
+{
+       int status;
+       int i;
+       int bytes_sent = 0;
+       int transfer_size;
+       int from_user = 0;
+
+       struct moschip_port *mos7840_port;
+       struct usb_serial *serial;
+       struct urb *urb;
+       //__u16 Data;
+       const unsigned char *current_position = data;
+       unsigned char *data1;
+       dbg("%s \n", "entering ...........");
+       //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR);
+
+#ifdef NOTMOS7840
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+       mos7840_port->shadowLCR = Data;
+       dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data);
+       dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+
+       //Data = 0x03;
+       //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data);
+       //mos7840_port->shadowLCR=Data;//Need to add later
+
+       Data |= SERIAL_LCR_DLAB;        //data latch enable in LCR 0x80
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       //Data = 0x0c;
+       //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
+       dbg("mos7840_write:DLL value is %x\n", Data);
+
+       Data = 0x0;
+       status = 0;
+       status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
+       dbg("mos7840_write:DLM value is %x\n", Data);
+
+       Data = Data & ~SERIAL_LCR_DLAB;
+       dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+#endif
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return -1;
+       }
+
+       serial = port->serial;
+       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       if (mos7840_port == NULL) {
+               dbg("%s", "mos7840_port is NULL\n");
+               return -1;
+       }
+
+       /* try to find a free urb in the list */
+       urb = NULL;
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+                       urb = mos7840_port->write_urb_pool[i];
+                       dbg("\nURB:%d", i);
+                       break;
+               }
+       }
+
+       if (urb == NULL) {
+               dbg("%s - no more free urbs", __FUNCTION__);
+               goto exit;
+       }
+
+       if (urb->transfer_buffer == NULL) {
+               urb->transfer_buffer =
+                   kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+
+               if (urb->transfer_buffer == NULL) {
+                       err("%s no more kernel memory...", __FUNCTION__);
+                       goto exit;
+               }
+       }
+       transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
+
+       if (from_user) {
+               if (copy_from_user
+                   (urb->transfer_buffer, current_position, transfer_size)) {
+                       bytes_sent = -EFAULT;
+                       goto exit;
+               }
+       } else {
+               memcpy(urb->transfer_buffer, current_position, transfer_size);
+       }
+
+       /* fill urb with data and submit  */
+       usb_fill_bulk_urb(urb,
+                         serial->dev,
+                         usb_sndbulkpipe(serial->dev,
+                                         port->bulk_out_endpointAddress),
+                         urb->transfer_buffer,
+                         transfer_size,
+                         mos7840_bulk_out_data_callback, mos7840_port);
+
+       data1 = urb->transfer_buffer;
+       dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress);
+
+       /* send it down the pipe */
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+
+       if (status) {
+               err("%s - usb_submit_urb(write bulk) failed with status = %d",
+                   __FUNCTION__, status);
+               bytes_sent = status;
+               goto exit;
+       }
+       bytes_sent = transfer_size;
+       mos7840_port->icount.tx += transfer_size;
+       dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+      exit:
+
+       return bytes_sent;
+
+}
+
+/*****************************************************************************
+ * mos7840_throttle
+ *     this function is called by the tty driver when it wants to stop the data
+ *     being read from the port.
+ *****************************************************************************/
+
+static void mos7840_throttle(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+       int status;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       dbg("- port %d\n", port->number);
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return;
+
+       if (!mos7840_port->open) {
+               dbg("%s\n", "port not opened");
+               return;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       tty = port->tty;
+       if (!tty) {
+               dbg("%s - no tty available", __FUNCTION__);
+               return;
+       }
+
+       /* if we are implementing XON/XOFF, send the stop character */
+       if (I_IXOFF(tty)) {
+               unsigned char stop_char = STOP_CHAR(tty);
+               status = mos7840_write(port, &stop_char, 1);
+               if (status <= 0) {
+                       return;
+               }
+       }
+
+       /* if we are implementing RTS/CTS, toggle that line */
+       if (tty->termios->c_cflag & CRTSCTS) {
+               mos7840_port->shadowMCR &= ~MCR_RTS;
+               status = 0;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+                                        mos7840_port->shadowMCR);
+
+               if (status < 0) {
+                       return;
+               }
+       }
+
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_unthrottle
+ *     this function is called by the tty driver when it wants to resume the data
+ *     being read from the port (called after SerialThrottle is called)
+ *****************************************************************************/
+static void mos7840_unthrottle(struct usb_serial_port *port)
+{
+       struct tty_struct *tty;
+       int status;
+       struct moschip_port *mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       if (mos7840_port == NULL)
+               return;
+
+       if (!mos7840_port->open) {
+               dbg("%s - port not opened", __FUNCTION__);
+               return;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       tty = port->tty;
+       if (!tty) {
+               dbg("%s - no tty available", __FUNCTION__);
+               return;
+       }
+
+       /* if we are implementing XON/XOFF, send the start character */
+       if (I_IXOFF(tty)) {
+               unsigned char start_char = START_CHAR(tty);
+               status = mos7840_write(port, &start_char, 1);
+               if (status <= 0) {
+                       return;
+               }
+       }
+
+       /* if we are implementing RTS/CTS, toggle that line */
+       if (tty->termios->c_cflag & CRTSCTS) {
+               mos7840_port->shadowMCR |= MCR_RTS;
+               status = 0;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+                                        mos7840_port->shadowMCR);
+               if (status < 0) {
+                       return;
+               }
+       }
+
+       return;
+}
+
+static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+       struct moschip_port *mos7840_port;
+       unsigned int result;
+       __u16 msr;
+       __u16 mcr;
+       int status = 0;
+       mos7840_port = mos7840_get_port_private(port);
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (mos7840_port == NULL)
+               return -ENODEV;
+
+       status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
+       status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
+       result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
+           | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
+           | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
+           | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)
+           | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)
+           | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
+           | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
+
+       dbg("%s - 0x%04X", __FUNCTION__, result);
+
+       return result;
+}
+
+static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+                           unsigned int set, unsigned int clear)
+{
+       struct moschip_port *mos7840_port;
+       unsigned int mcr;
+       unsigned int status;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return -ENODEV;
+
+       mcr = mos7840_port->shadowMCR;
+       if (clear & TIOCM_RTS)
+               mcr &= ~MCR_RTS;
+       if (clear & TIOCM_DTR)
+               mcr &= ~MCR_DTR;
+       if (clear & TIOCM_LOOP)
+               mcr &= ~MCR_LOOPBACK;
+
+       if (set & TIOCM_RTS)
+               mcr |= MCR_RTS;
+       if (set & TIOCM_DTR)
+               mcr |= MCR_DTR;
+       if (set & TIOCM_LOOP)
+               mcr |= MCR_LOOPBACK;
+
+       mos7840_port->shadowMCR = mcr;
+
+       status = 0;
+       status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
+       if (status < 0) {
+               dbg("setting MODEM_CONTROL_REGISTER Failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_calc_baud_rate_divisor
+ *     this function calculates the proper baud rate divisor for the specified
+ *     baud rate.
+ *****************************************************************************/
+static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
+                                         __u16 * clk_sel_val)
+{
+
+       dbg("%s - %d", __FUNCTION__, baudRate);
+
+       if (baudRate <= 115200) {
+               *divisor = 115200 / baudRate;
+               *clk_sel_val = 0x0;
+       }
+       if ((baudRate > 115200) && (baudRate <= 230400)) {
+               *divisor = 230400 / baudRate;
+               *clk_sel_val = 0x10;
+       } else if ((baudRate > 230400) && (baudRate <= 403200)) {
+               *divisor = 403200 / baudRate;
+               *clk_sel_val = 0x20;
+       } else if ((baudRate > 403200) && (baudRate <= 460800)) {
+               *divisor = 460800 / baudRate;
+               *clk_sel_val = 0x30;
+       } else if ((baudRate > 460800) && (baudRate <= 806400)) {
+               *divisor = 806400 / baudRate;
+               *clk_sel_val = 0x40;
+       } else if ((baudRate > 806400) && (baudRate <= 921600)) {
+               *divisor = 921600 / baudRate;
+               *clk_sel_val = 0x50;
+       } else if ((baudRate > 921600) && (baudRate <= 1572864)) {
+               *divisor = 1572864 / baudRate;
+               *clk_sel_val = 0x60;
+       } else if ((baudRate > 1572864) && (baudRate <= 3145728)) {
+               *divisor = 3145728 / baudRate;
+               *clk_sel_val = 0x70;
+       }
+       return 0;
+
+#ifdef NOTMCS7840
+
+       for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) {
+               if (mos7840_divisor_table[i].BaudRate == baudrate) {
+                       *divisor = mos7840_divisor_table[i].Divisor;
+                       return 0;
+               }
+       }
+
+       /* After trying for all the standard baud rates    *
+        * Try calculating the divisor for this baud rate  */
+
+       if (baudrate > 75 && baudrate < 230400) {
+               /* get the divisor */
+               custom = (__u16) (230400L / baudrate);
+
+               /* Check for round off */
+               round1 = (__u16) (2304000L / baudrate);
+               round = (__u16) (round1 - (custom * 10));
+               if (round > 4) {
+                       custom++;
+               }
+               *divisor = custom;
+
+               dbg(" Baud %d = %d\n", baudrate, custom);
+               return 0;
+       }
+
+       dbg("%s\n", " Baud calculation Failed...");
+       return -1;
+#endif
+}
+
+/*****************************************************************************
+ * mos7840_send_cmd_write_baud_rate
+ *     this function sends the proper command to change the baud rate of the
+ *     specified port.
+ *****************************************************************************/
+
+static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+                                           int baudRate)
+{
+       int divisor = 0;
+       int status;
+       __u16 Data;
+       unsigned char number;
+       __u16 clk_sel_val;
+       struct usb_serial_port *port;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+               dbg("%s", "Invalid Serial \n");
+               return -1;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+
+       dbg("%s - port = %d, baud = %d", __FUNCTION__,
+           mos7840_port->port->number, baudRate);
+       //reset clk_uart_sel in spregOffset
+       if (baudRate > 115200) {
+#ifdef HW_flow_control
+               //NOTE: need to see the pther register to modify
+               //setting h/w flow control bit to 1;
+               status = 0;
+               Data = 0x2b;
+               mos7840_port->shadowMCR = Data;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+               if (status < 0) {
+                       dbg("Writing spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+#endif
+
+       } else {
+#ifdef HW_flow_control
+               //setting h/w flow control bit to 0;
+               status = 0;
+               Data = 0xb;
+               mos7840_port->shadowMCR = Data;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+               if (status < 0) {
+                       dbg("Writing spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+#endif
+
+       }
+
+       if (1)                  //baudRate <= 115200)
+       {
+               clk_sel_val = 0x0;
+               Data = 0x0;
+               status = 0;
+               status =
+                   mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+                                                  &clk_sel_val);
+               status =
+                   mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
+                                        &Data);
+               if (status < 0) {
+                       dbg("reading spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+               Data = (Data & 0x8f) | clk_sel_val;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+               if (status < 0) {
+                       dbg("Writing spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+               /* Calculate the Divisor */
+
+               if (status) {
+                       err("%s - bad baud rate", __FUNCTION__);
+                       dbg("%s\n", "bad baud rate");
+                       return status;
+               }
+               /* Enable access to divisor latch */
+               Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB;
+               mos7840_port->shadowLCR = Data;
+               mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+               /* Write the divisor */
+               Data = (unsigned char)(divisor & 0xff);
+               dbg("set_serial_baud Value to write DLL is %x\n", Data);
+               mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
+
+               Data = (unsigned char)((divisor & 0xff00) >> 8);
+               dbg("set_serial_baud Value to write DLM is %x\n", Data);
+               mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
+
+               /* Disable access to divisor latch */
+               Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB;
+               mos7840_port->shadowLCR = Data;
+               mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       }
+
+       return status;
+}
+
+/*****************************************************************************
+ * mos7840_change_port_settings
+ *     This routine is called to set the UART on the device to match
+ *      the specified new settings.
+ *****************************************************************************/
+
+static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+                                        struct termios *old_termios)
+{
+       struct tty_struct *tty;
+       int baud;
+       unsigned cflag;
+       unsigned iflag;
+       __u8 lData;
+       __u8 lParity;
+       __u8 lStop;
+       int status;
+       __u16 Data;
+       struct usb_serial_port *port;
+       struct usb_serial *serial;
+
+       if (mos7840_port == NULL)
+               return;
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+               dbg("%s", "Invalid Serial \n");
+               return;
+       }
+
+       serial = port->serial;
+
+       dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
+
+       if (!mos7840_port->open) {
+               dbg("%s - port not opened", __FUNCTION__);
+               return;
+       }
+
+       tty = mos7840_port->port->tty;
+
+       if ((!tty) || (!tty->termios)) {
+               dbg("%s - no tty structures", __FUNCTION__);
+               return;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       lData = LCR_BITS_8;
+       lStop = LCR_STOP_1;
+       lParity = LCR_PAR_NONE;
+
+       cflag = tty->termios->c_cflag;
+       iflag = tty->termios->c_iflag;
+
+       /* Change the number of bits */
+       if (cflag & CSIZE) {
+               switch (cflag & CSIZE) {
+               case CS5:
+                       lData = LCR_BITS_5;
+                       break;
+
+               case CS6:
+                       lData = LCR_BITS_6;
+                       break;
+
+               case CS7:
+                       lData = LCR_BITS_7;
+                       break;
+               default:
+               case CS8:
+                       lData = LCR_BITS_8;
+                       break;
+               }
+       }
+       /* Change the Parity bit */
+       if (cflag & PARENB) {
+               if (cflag & PARODD) {
+                       lParity = LCR_PAR_ODD;
+                       dbg("%s - parity = odd", __FUNCTION__);
+               } else {
+                       lParity = LCR_PAR_EVEN;
+                       dbg("%s - parity = even", __FUNCTION__);
+               }
+
+       } else {
+               dbg("%s - parity = none", __FUNCTION__);
+       }
+
+       if (cflag & CMSPAR) {
+               lParity = lParity | 0x20;
+       }
+
+       /* Change the Stop bit */
+       if (cflag & CSTOPB) {
+               lStop = LCR_STOP_2;
+               dbg("%s - stop bits = 2", __FUNCTION__);
+       } else {
+               lStop = LCR_STOP_1;
+               dbg("%s - stop bits = 1", __FUNCTION__);
+       }
+
+       /* Update the LCR with the correct value */
+       mos7840_port->shadowLCR &=
+           ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+       mos7840_port->shadowLCR |= (lData | lParity | lStop);
+
+       dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+       /* Disable Interrupts */
+       Data = 0x00;
+       mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       Data = 0x00;
+       mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+
+       Data = 0xcf;
+       mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+
+       /* Send the updated LCR value to the mos7840 */
+       Data = mos7840_port->shadowLCR;
+
+       mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       Data = 0x00b;
+       mos7840_port->shadowMCR = Data;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+       Data = 0x00b;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+       /* set up the MCR register and send it to the mos7840 */
+
+       mos7840_port->shadowMCR = MCR_MASTER_IE;
+       if (cflag & CBAUD) {
+               mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
+       }
+
+       if (cflag & CRTSCTS) {
+               mos7840_port->shadowMCR |= (MCR_XON_ANY);
+
+       } else {
+               mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
+       }
+
+       Data = mos7840_port->shadowMCR;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+       /* Determine divisor based on baud rate */
+       baud = tty_get_baud_rate(tty);
+
+       if (!baud) {
+               /* pick a default, any default... */
+               dbg("%s\n", "Picked default baud...");
+               baud = 9600;
+       }
+
+       dbg("%s - baud rate = %d", __FUNCTION__, baud);
+       status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
+
+       /* Enable Interrupts */
+       Data = 0x0c;
+       mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       if (mos7840_port->read_urb->status != -EINPROGRESS) {
+               mos7840_port->read_urb->dev = serial->dev;
+
+               status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+               if (status) {
+                       dbg(" usb_submit_urb(read bulk) failed, status = %d",
+                           status);
+               }
+       }
+       wake_up(&mos7840_port->delta_msr_wait);
+       mos7840_port->delta_msr_cond = 1;
+       dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n",
+           mos7840_port->shadowLCR);
+
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_set_termios
+ *     this function is called by the tty driver when it wants to change
+ *     the termios structure
+ *****************************************************************************/
+
+static void mos7840_set_termios(struct usb_serial_port *port,
+                               struct termios *old_termios)
+{
+       int status;
+       unsigned int cflag;
+       struct usb_serial *serial;
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+       dbg("mos7840_set_termios: START\n");
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       serial = port->serial;
+
+       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+               dbg("%s", "Invalid Serial \n");
+               return;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return;
+
+       tty = port->tty;
+
+       if (!port->tty || !port->tty->termios) {
+               dbg("%s - no tty or termios", __FUNCTION__);
+               return;
+       }
+
+       if (!mos7840_port->open) {
+               dbg("%s - port not opened", __FUNCTION__);
+               return;
+       }
+
+       dbg("%s\n", "setting termios - ");
+
+       cflag = tty->termios->c_cflag;
+
+       if (!cflag) {
+               dbg("%s %s\n", __FUNCTION__, "cflag is NULL");
+               return;
+       }
+
+       /* check that they really want us to change something */
+       if (old_termios) {
+               if ((cflag == old_termios->c_cflag) &&
+                   (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+                    RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg("%s\n", "Nothing to change");
+                       return;
+               }
+       }
+
+       dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+           tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
+
+       if (old_termios) {
+               dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+                   old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
+       }
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* change the port settings to the new ones specified */
+
+       mos7840_change_port_settings(mos7840_port, old_termios);
+
+       if (!mos7840_port->read_urb) {
+               dbg("%s", "URB KILLED !!!!!\n");
+               return;
+       }
+
+       if (mos7840_port->read_urb->status != -EINPROGRESS) {
+               mos7840_port->read_urb->dev = serial->dev;
+               status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+               if (status) {
+                       dbg(" usb_submit_urb(read bulk) failed, status = %d",
+                           status);
+               }
+       }
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *         is emptied.  On bus types like RS485, the transmitter must
+ *         release the bus after transmitting. This must be done when
+ *         the transmit shift register is empty, not be done when the
+ *         transmit holding register is empty.  This functionality
+ *         allows an RS485 driver to be written in user space.
+ *****************************************************************************/
+
+static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+                               unsigned int *value)
+{
+       int count;
+       unsigned int result = 0;
+
+       count = mos7840_chars_in_buffer(mos7840_port->port);
+       if (count == 0) {
+               dbg("%s -- Empty", __FUNCTION__);
+               result = TIOCSER_TEMT;
+       }
+
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_bytes_avail - get number of bytes available
+ *
+ * Purpose: Let user call ioctl to get the count of number of bytes available.
+ *****************************************************************************/
+
+static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
+                                  unsigned int *value)
+{
+       unsigned int result = 0;
+       struct tty_struct *tty = mos7840_port->port->tty;
+
+       if (!tty)
+               return -ENOIOCTLCMD;
+
+       result = tty->read_cnt;
+
+       dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+
+       return -ENOIOCTLCMD;
+}
+
+/*****************************************************************************
+ * mos7840_set_modem_info
+ *      function to set modem info
+ *****************************************************************************/
+
+static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
+                                 unsigned int cmd, unsigned int *value)
+{
+       unsigned int mcr;
+       unsigned int arg;
+       __u16 Data;
+       int status;
+       struct usb_serial_port *port;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       mcr = mos7840_port->shadowMCR;
+
+       if (copy_from_user(&arg, value, sizeof(int)))
+               return -EFAULT;
+
+       switch (cmd) {
+       case TIOCMBIS:
+               if (arg & TIOCM_RTS)
+                       mcr |= MCR_RTS;
+               if (arg & TIOCM_DTR)
+                       mcr |= MCR_RTS;
+               if (arg & TIOCM_LOOP)
+                       mcr |= MCR_LOOPBACK;
+               break;
+
+       case TIOCMBIC:
+               if (arg & TIOCM_RTS)
+                       mcr &= ~MCR_RTS;
+               if (arg & TIOCM_DTR)
+                       mcr &= ~MCR_RTS;
+               if (arg & TIOCM_LOOP)
+                       mcr &= ~MCR_LOOPBACK;
+               break;
+
+       case TIOCMSET:
+               /* turn off the RTS and DTR and LOOPBACK
+                * and then only turn on what was asked to */
+               mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
+               mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+               mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+               mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
+               break;
+       }
+
+       mos7840_port->shadowMCR = mcr;
+
+       Data = mos7840_port->shadowMCR;
+       status = 0;
+       status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+       if (status < 0) {
+               dbg("setting MODEM_CONTROL_REGISTER Failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_modem_info
+ *      function to get modem info
+ *****************************************************************************/
+
+static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
+                                 unsigned int *value)
+{
+       unsigned int result = 0;
+       __u16 msr;
+       unsigned int mcr = mos7840_port->shadowMCR;
+       int status = 0;
+       status =
+           mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,
+                                &msr);
+       result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)      /* 0x002 */
+           |((mcr & MCR_RTS) ? TIOCM_RTS : 0)  /* 0x004 */
+           |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)  /* 0x020 */
+           |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)   /* 0x040 */
+           |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)    /* 0x080 */
+           |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
+
+       dbg("%s -- %x", __FUNCTION__, result);
+
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_serial_info
+ *      function to get information about serial port
+ *****************************************************************************/
+
+static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
+                                  struct serial_struct *retinfo)
+{
+       struct serial_struct tmp;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       if (!retinfo)
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       tmp.type = PORT_16550A;
+       tmp.line = mos7840_port->port->serial->minor;
+       tmp.port = mos7840_port->port->number;
+       tmp.irq = 0;
+       tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+       tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
+       tmp.baud_base = 9600;
+       tmp.close_delay = 5 * HZ;
+       tmp.closing_wait = 30 * HZ;
+
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+       return 0;
+}
+
+/*****************************************************************************
+ * SerialIoctl
+ *     this function handles any ioctl calls to the driver
+ *****************************************************************************/
+
+static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+
+       struct async_icount cnow;
+       struct async_icount cprev;
+       struct serial_icounter_struct icount;
+       int mosret = 0;
+       int retval;
+       struct tty_ldisc *ld;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       tty = mos7840_port->port->tty;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+
+       switch (cmd) {
+               /* return number of bytes available */
+
+       case TIOCINQ:
+               dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
+               return mos7840_get_bytes_avail(mos7840_port,
+                                              (unsigned int *)arg);
+               break;
+
+       case TIOCOUTQ:
+               dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
+               return put_user(tty->driver->chars_in_buffer ?
+                               tty->driver->chars_in_buffer(tty) : 0,
+                               (int __user *)arg);
+               break;
+
+       case TCFLSH:
+               retval = tty_check_change(tty);
+               if (retval)
+                       return retval;
+
+               ld = tty_ldisc_ref(tty);
+               switch (arg) {
+               case TCIFLUSH:
+                       if (ld && ld->flush_buffer)
+                               ld->flush_buffer(tty);
+                       break;
+               case TCIOFLUSH:
+                       if (ld && ld->flush_buffer)
+                               ld->flush_buffer(tty);
+                       /* fall through */
+               case TCOFLUSH:
+                       if (tty->driver->flush_buffer)
+                               tty->driver->flush_buffer(tty);
+                       break;
+               default:
+                       tty_ldisc_deref(ld);
+                       return -EINVAL;
+               }
+               tty_ldisc_deref(ld);
+               return 0;
+
+       case TCGETS:
+               if (kernel_termios_to_user_termios
+                   ((struct termios __user *)arg, tty->termios))
+                       return -EFAULT;
+               return 0;
+
+       case TIOCSERGETLSR:
+               dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
+               return mos7840_get_lsr_info(mos7840_port, (unsigned int *)arg);
+               return 0;
+
+       case TIOCMBIS:
+       case TIOCMBIC:
+       case TIOCMSET:
+               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+                   port->number);
+               mosret =
+                   mos7840_set_modem_info(mos7840_port, cmd,
+                                          (unsigned int *)arg);
+               return mosret;
+
+       case TIOCMGET:
+               dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
+               return mos7840_get_modem_info(mos7840_port,
+                                             (unsigned int *)arg);
+
+       case TIOCGSERIAL:
+               dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+               return mos7840_get_serial_info(mos7840_port,
+                                              (struct serial_struct *)arg);
+
+       case TIOCSSERIAL:
+               dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+               break;
+
+       case TIOCMIWAIT:
+               dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+               cprev = mos7840_port->icount;
+               while (1) {
+                       //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+                       mos7840_port->delta_msr_cond = 0;
+                       wait_event_interruptible(mos7840_port->delta_msr_wait,
+                                                (mos7840_port->
+                                                 delta_msr_cond == 1));
+
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
+                       cnow = mos7840_port->icount;
+                       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 */
+               break;
+
+       case TIOCGICOUNT:
+               cnow = mos7840_port->icount;
+               icount.cts = cnow.cts;
+               icount.dsr = cnow.dsr;
+               icount.rng = cnow.rng;
+               icount.dcd = cnow.dcd;
+               icount.rx = cnow.rx;
+               icount.tx = cnow.tx;
+               icount.frame = cnow.frame;
+               icount.overrun = cnow.overrun;
+               icount.parity = cnow.parity;
+               icount.brk = cnow.brk;
+               icount.buf_overrun = cnow.buf_overrun;
+
+               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+                   port->number, icount.rx, icount.tx);
+               if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+                       return -EFAULT;
+               return 0;
+
+       case TIOCEXBAUD:
+               return 0;
+       default:
+               break;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static int mos7840_calc_num_ports(struct usb_serial *serial)
+{
+
+       dbg("numberofendpoints: %d \n",
+           (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
+       dbg("numberofendpoints: %d \n",
+           (int)serial->interface->altsetting->desc.bNumEndpoints);
+       if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
+               mos7840_num_ports = 2;
+               serial->type->num_ports = 2;
+       } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+               mos7840_num_ports = 4;
+               serial->type->num_bulk_in = 4;
+               serial->type->num_bulk_out = 4;
+               serial->type->num_ports = 4;
+       }
+
+       return mos7840_num_ports;
+}
+
+/****************************************************************************
+ * mos7840_startup
+ ****************************************************************************/
+
+static int mos7840_startup(struct usb_serial *serial)
+{
+       struct moschip_port *mos7840_port;
+       struct usb_device *dev;
+       int i, status;
+
+       __u16 Data;
+       dbg("%s \n", " mos7840_startup :entering..........");
+
+       if (!serial) {
+               dbg("%s\n", "Invalid Handler");
+               return -1;
+       }
+
+       dev = serial->dev;
+
+       dbg("%s\n", "Entering...");
+
+       /* we set up the pointers to the endpoints in the mos7840_open *
+        * function, as the structures aren't created yet.             */
+
+       /* set up port private structures */
+       for (i = 0; i < serial->num_ports; ++i) {
+               mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL);
+               if (mos7840_port == NULL) {
+                       err("%s - Out of memory", __FUNCTION__);
+                       return -ENOMEM;
+               }
+               memset(mos7840_port, 0, sizeof(struct moschip_port));
+
+               /* Initialize all port interrupt end point to port 0 int endpoint *
+                * Our device has only one interrupt end point comman to all port */
+
+               mos7840_port->port = serial->port[i];
+               mos7840_set_port_private(serial->port[i], mos7840_port);
+
+               mos7840_port->port_num = ((serial->port[i]->number -
+                                          (serial->port[i]->serial->minor)) +
+                                         1);
+
+               if (mos7840_port->port_num == 1) {
+                       mos7840_port->SpRegOffset = 0x0;
+                       mos7840_port->ControlRegOffset = 0x1;
+                       mos7840_port->DcrRegOffset = 0x4;
+               } else if ((mos7840_port->port_num == 2)
+                          && (mos7840_num_ports == 4)) {
+                       mos7840_port->SpRegOffset = 0x8;
+                       mos7840_port->ControlRegOffset = 0x9;
+                       mos7840_port->DcrRegOffset = 0x16;
+               } else if ((mos7840_port->port_num == 2)
+                          && (mos7840_num_ports == 2)) {
+                       mos7840_port->SpRegOffset = 0xa;
+                       mos7840_port->ControlRegOffset = 0xb;
+                       mos7840_port->DcrRegOffset = 0x19;
+               } else if ((mos7840_port->port_num == 3)
+                          && (mos7840_num_ports == 4)) {
+                       mos7840_port->SpRegOffset = 0xa;
+                       mos7840_port->ControlRegOffset = 0xb;
+                       mos7840_port->DcrRegOffset = 0x19;
+               } else if ((mos7840_port->port_num == 4)
+                          && (mos7840_num_ports == 4)) {
+                       mos7840_port->SpRegOffset = 0xc;
+                       mos7840_port->ControlRegOffset = 0xd;
+                       mos7840_port->DcrRegOffset = 0x1c;
+               }
+               mos7840_dump_serial_port(mos7840_port);
+
+               mos7840_set_port_private(serial->port[i], mos7840_port);
+
+               //enable rx_disable bit in control register
+
+               status =
+                   mos7840_get_reg_sync(serial->port[i],
+                                        mos7840_port->ControlRegOffset, &Data);
+               if (status < 0) {
+                       dbg("Reading ControlReg failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("ControlReg Reading success val is %x, status%d\n",
+                           Data, status);
+               Data |= 0x08;   //setting driver done bit
+               Data |= 0x04;   //sp1_bit to have cts change reflect in modem status reg
+
+               //Data |= 0x20; //rx_disable bit
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        mos7840_port->ControlRegOffset, Data);
+               if (status < 0) {
+                       dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("ControlReg Writing success(rx_disable) status%d\n",
+                           status);
+
+               //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3
+               Data = 0x01;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        (__u16) (mos7840_port->DcrRegOffset +
+                                                 0), Data);
+               if (status < 0) {
+                       dbg("Writing DCR0 failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("DCR0 Writing success status%d\n", status);
+
+               Data = 0x05;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        (__u16) (mos7840_port->DcrRegOffset +
+                                                 1), Data);
+               if (status < 0) {
+                       dbg("Writing DCR1 failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("DCR1 Writing success status%d\n", status);
+
+               Data = 0x24;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        (__u16) (mos7840_port->DcrRegOffset +
+                                                 2), Data);
+               if (status < 0) {
+                       dbg("Writing DCR2 failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("DCR2 Writing success status%d\n", status);
+
+               // write values in clkstart0x0 and clkmulti 0x20
+               Data = 0x0;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        CLK_START_VALUE_REGISTER, Data);
+               if (status < 0) {
+                       dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+
+               Data = 0x20;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
+                                        Data);
+               if (status < 0) {
+                       dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
+                           status);
+                       break;
+               } else
+                       dbg("CLK_MULTI_REGISTER Writing success status%d\n",
+                           status);
+
+               //write value 0x0 to scratchpad register
+               Data = 0x00;
+               status = 0;
+               status =
+                   mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
+                                        Data);
+               if (status < 0) {
+                       dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n",
+                           status);
+                       break;
+               } else
+                       dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
+                           status);
+
+               //Zero Length flag register
+               if ((mos7840_port->port_num != 1)
+                   && (mos7840_num_ports == 2)) {
+
+                       Data = 0xff;
+                       status = 0;
+                       status = mos7840_set_reg_sync(serial->port[i],
+                                                     (__u16) (ZLP_REG1 +
+                                                              ((__u16)
+                                                               mos7840_port->
+                                                               port_num)),
+                                                     Data);
+                       dbg("ZLIP offset%x\n",
+                           (__u16) (ZLP_REG1 +
+                                    ((__u16) mos7840_port->port_num)));
+                       if (status < 0) {
+                               dbg("Writing ZLP_REG%d failed status-0x%x\n",
+                                   i + 2, status);
+                               break;
+                       } else
+                               dbg("ZLP_REG%d Writing success status%d\n",
+                                   i + 2, status);
+               } else {
+                       Data = 0xff;
+                       status = 0;
+                       status = mos7840_set_reg_sync(serial->port[i],
+                                                     (__u16) (ZLP_REG1 +
+                                                              ((__u16)
+                                                               mos7840_port->
+                                                               port_num) -
+                                                              0x1), Data);
+                       dbg("ZLIP offset%x\n",
+                           (__u16) (ZLP_REG1 +
+                                    ((__u16) mos7840_port->port_num) - 0x1));
+                       if (status < 0) {
+                               dbg("Writing ZLP_REG%d failed status-0x%x\n",
+                                   i + 1, status);
+                               break;
+                       } else
+                               dbg("ZLP_REG%d Writing success status%d\n",
+                                   i + 1, status);
+
+               }
+               mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+
+       }
+
+       //Zero Length flag enable
+       Data = 0x0f;
+       status = 0;
+       status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+       if (status < 0) {
+               dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
+               return -1;
+       } else
+               dbg("ZLP_REG5 Writing success status%d\n", status);
+
+       /* setting configuration feature to one */
+       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                       (__u8) 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 5 * HZ);
+       return 0;
+}
+
+/****************************************************************************
+ * mos7840_shutdown
+ *     This function is called whenever the device is removed from the usb bus.
+ ****************************************************************************/
+
+static void mos7840_shutdown(struct usb_serial *serial)
+{
+       int i;
+       struct moschip_port *mos7840_port;
+       dbg("%s \n", " shutdown :entering..........");
+
+       if (!serial) {
+               dbg("%s", "Invalid Handler \n");
+               return;
+       }
+
+       /*      check for the ports to be closed,close the ports and disconnect         */
+
+       /* free private structure allocated for serial port  *
+        * stop reads and writes on all ports                */
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               mos7840_port = mos7840_get_port_private(serial->port[i]);
+               kfree(mos7840_port->ctrl_buf);
+               usb_kill_urb(mos7840_port->control_urb);
+               kfree(mos7840_port);
+               mos7840_set_port_private(serial->port[i], NULL);
+       }
+
+       dbg("%s\n", "Thank u :: ");
+
+}
+
+static struct usb_serial_driver moschip7840_4port_device = {
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "mos7840",
+                  },
+       .description = DRIVER_DESC,
+       .id_table = moschip_port_id_table,
+       .num_interrupt_in = 1,  //NUM_DONT_CARE,//1,
+#ifdef check
+       .num_bulk_in = 4,
+       .num_bulk_out = 4,
+       .num_ports = 4,
+#endif
+       .open = mos7840_open,
+       .close = mos7840_close,
+       .write = mos7840_write,
+       .write_room = mos7840_write_room,
+       .chars_in_buffer = mos7840_chars_in_buffer,
+       .throttle = mos7840_throttle,
+       .unthrottle = mos7840_unthrottle,
+       .calc_num_ports = mos7840_calc_num_ports,
+#ifdef MCSSerialProbe
+       .probe = mos7840_serial_probe,
+#endif
+       .ioctl = mos7840_ioctl,
+       .set_termios = mos7840_set_termios,
+       .break_ctl = mos7840_break,
+       .tiocmget = mos7840_tiocmget,
+       .tiocmset = mos7840_tiocmset,
+       .attach = mos7840_startup,
+       .shutdown = mos7840_shutdown,
+       .read_bulk_callback = mos7840_bulk_in_callback,
+       .read_int_callback = mos7840_interrupt_callback,
+};
+
+static struct usb_driver io_driver = {
+       .name = "mos7840",
+       .probe = usb_serial_probe,
+       .disconnect = usb_serial_disconnect,
+       .id_table = moschip_id_table_combined,
+};
+
+/****************************************************************************
+ * moschip7840_init
+ *     This is called by the module subsystem, or on startup to initialize us
+ ****************************************************************************/
+static int __init moschip7840_init(void)
+{
+       int retval;
+
+       dbg("%s \n", " mos7840_init :entering..........");
+
+       /* Register with the usb serial */
+       retval = usb_serial_register(&moschip7840_4port_device);
+
+       if (retval)
+               goto failed_port_device_register;
+
+       dbg("%s\n", "Entring...");
+       info(DRIVER_DESC " " DRIVER_VERSION);
+
+       /* Register with the usb */
+       retval = usb_register(&io_driver);
+
+       if (retval)
+               goto failed_usb_register;
+
+       if (retval == 0) {
+               dbg("%s\n", "Leaving...");
+               return 0;
+       }
+
+      failed_usb_register:
+       usb_serial_deregister(&moschip7840_4port_device);
+
+      failed_port_device_register:
+
+       return retval;
+}
+
+/****************************************************************************
+ * moschip7840_exit
+ *     Called when the driver is about to be unloaded.
+ ****************************************************************************/
+static void __exit moschip7840_exit(void)
+{
+
+       dbg("%s \n", " mos7840_exit :entering..........");
+
+       usb_deregister(&io_driver);
+
+       usb_serial_deregister(&moschip7840_4port_device);
+
+       dbg("%s\n", "Entring...");
+}
+
+module_init(moschip7840_init);
+module_exit(moschip7840_exit);
+
+/* Module information */
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
index e49f40913c27550e0c121c8d01bdf8ef909d0ae7..a764ff4e326cfb2c6695af4e226b9389a3a5e866 100644 (file)
@@ -256,14 +256,14 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
                return (0);
        }
 
-       spin_lock(&wport->lock);
+       spin_lock_bh(&wport->lock);
        if (wport->write_urb_busy) {
-               spin_unlock(&wport->lock);
+               spin_unlock_bh(&wport->lock);
                dbg("%s - already writing", __FUNCTION__);
                return 0;
        }
        wport->write_urb_busy = 1;
-       spin_unlock(&wport->lock);
+       spin_unlock_bh(&wport->lock);
 
        count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
 
index 65e4d046951aa7439c0de36eda9b699a90b2a476..9c18173e33fb90710fdda8e3161625eb2cde0e19 100644 (file)
@@ -81,10 +81,12 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
        { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
        { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
+       { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
+       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver pl2303_driver = {
        .name =         "pl2303",
@@ -127,65 +129,6 @@ static struct usb_driver pl2303_driver = {
 #define UART_OVERRUN_ERROR             0x40
 #define UART_CTS                       0x80
 
-/* function prototypes for a PL2303 serial converter */
-static int pl2303_open (struct usb_serial_port *port, struct file *filp);
-static void pl2303_close (struct usb_serial_port *port, struct file *filp);
-static void pl2303_set_termios (struct usb_serial_port *port,
-                               struct termios *old);
-static int pl2303_ioctl (struct usb_serial_port *port, struct file *file,
-                        unsigned int cmd, unsigned long arg);
-static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs);
-static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static int pl2303_write (struct usb_serial_port *port,
-                        const unsigned char *buf, int count);
-static void pl2303_send (struct usb_serial_port *port);
-static int pl2303_write_room(struct usb_serial_port *port);
-static int pl2303_chars_in_buffer(struct usb_serial_port *port);
-static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-                           unsigned int set, unsigned int clear);
-static int pl2303_startup (struct usb_serial *serial);
-static void pl2303_shutdown (struct usb_serial *serial);
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
-static void pl2303_buf_free(struct pl2303_buf *pb);
-static void pl2303_buf_clear(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
-       unsigned int count);
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
-       unsigned int count);
-
-
-/* All of the device info needed for the PL2303 SIO serial converter */
-static struct usb_serial_driver pl2303_device = {
-       .driver = {
-               .owner =        THIS_MODULE,
-               .name =         "pl2303",
-       },
-       .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 pl2303_open,
-       .close =                pl2303_close,
-       .write =                pl2303_write,
-       .ioctl =                pl2303_ioctl,
-       .break_ctl =            pl2303_break_ctl,
-       .set_termios =          pl2303_set_termios,
-       .tiocmget =             pl2303_tiocmget,
-       .tiocmset =             pl2303_tiocmset,
-       .read_bulk_callback =   pl2303_read_bulk_callback,
-       .read_int_callback =    pl2303_read_int_callback,
-       .write_bulk_callback =  pl2303_write_bulk_callback,
-       .write_room =           pl2303_write_room,
-       .chars_in_buffer =      pl2303_chars_in_buffer,
-       .attach =               pl2303_startup,
-       .shutdown =             pl2303_shutdown,
-};
 
 enum pl2303_type {
        type_0,         /* don't know the difference between type 0 and */
@@ -204,8 +147,166 @@ struct pl2303_private {
        enum pl2303_type type;
 };
 
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+       struct pl2303_buf *pb;
+
+       if (size == 0)
+               return NULL;
+
+       pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+       if (pb == NULL)
+               return NULL;
+
+       pb->buf_buf = kmalloc(size, GFP_KERNEL);
+       if (pb->buf_buf == NULL) {
+               kfree(pb);
+               return NULL;
+       }
+
+       pb->buf_size = size;
+       pb->buf_get = pb->buf_put = pb->buf_buf;
+
+       return pb;
+}
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+       if (pb) {
+               kfree(pb->buf_buf);
+               kfree(pb);
+       }
+}
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+       if (pb != NULL)
+               pb->buf_get = pb->buf_put;
+               /* equivalent to a get of all data available */
+}
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+       if (pb == NULL)
+               return 0;
+
+       return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+       if (pb == NULL)
+               return 0;
+
+       return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+                                  unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len  = pl2303_buf_space_avail(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_put;
+       if (count > len) {
+               memcpy(pb->buf_put, buf, len);
+               memcpy(pb->buf_buf, buf+len, count - len);
+               pb->buf_put = pb->buf_buf + count - len;
+       } else {
+               memcpy(pb->buf_put, buf, count);
+               if (count < len)
+                       pb->buf_put += count;
+               else /* count == len */
+                       pb->buf_put = pb->buf_buf;
+       }
+
+       return count;
+}
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+                                  unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len = pl2303_buf_data_avail(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_get;
+       if (count > len) {
+               memcpy(buf, pb->buf_get, len);
+               memcpy(buf+len, pb->buf_buf, count - len);
+               pb->buf_get = pb->buf_buf + count - len;
+       } else {
+               memcpy(buf, pb->buf_get, count);
+               if (count < len)
+                       pb->buf_get += count;
+               else /* count == len */
+                       pb->buf_get = pb->buf_buf;
+       }
+
+       return count;
+}
 
-static int pl2303_startup (struct usb_serial *serial)
+static int pl2303_startup(struct usb_serial *serial)
 {
        struct pl2303_private *priv;
        enum pl2303_type type = type_0;
@@ -247,36 +348,17 @@ cleanup:
        return -ENOMEM;
 }
 
-static int set_control_lines (struct usb_device *dev, u8 value)
+static int set_control_lines(struct usb_device *dev, u8 value)
 {
        int retval;
        
-       retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0),
-                                 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
-                                 value, 0, NULL, 0, 100);
+       retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                                SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
+                                value, 0, NULL, 0, 100);
        dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
        return retval;
 }
 
-static int pl2303_write (struct usb_serial_port *port,  const unsigned char *buf, int count)
-{
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-
-       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
-
-       if (!count)
-               return count;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       count = pl2303_buf_put(priv->buf, buf, count);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       pl2303_send(port);
-
-       return count;
-}
-
 static void pl2303_send(struct usb_serial_port *port)
 {
        int count, result;
@@ -293,7 +375,7 @@ static void pl2303_send(struct usb_serial_port *port)
        }
 
        count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
-               port->bulk_out_size);
+                              port->bulk_out_size);
 
        if (count == 0) {
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -304,13 +386,15 @@ static void pl2303_send(struct usb_serial_port *port)
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
+                             port->write_urb->transfer_buffer);
 
        port->write_urb->transfer_buffer_length = count;
        port->write_urb->dev = port->serial->dev;
-       result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting write urb,"
+                       " error %d\n", __FUNCTION__, result);
                priv->write_urb_in_use = 0;
                // TODO: reschedule pl2303_send
        }
@@ -318,6 +402,26 @@ static void pl2303_send(struct usb_serial_port *port)
        usb_serial_port_softint(port);
 }
 
+static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
+                       int count)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+
+       if (!count)
+               return count;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       count = pl2303_buf_put(priv->buf, buf, count);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       pl2303_send(port);
+
+       return count;
+}
+
 static int pl2303_write_room(struct usb_serial_port *port)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -350,7 +454,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
        return chars;
 }
 
-static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void pl2303_set_termios(struct usb_serial_port *port,
+                              struct termios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -371,7 +476,8 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
                *(port->tty->termios) = tty_std_termios;
-               port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+               port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
+                                             HUPCL | CLOCAL;
                priv->termios_initialized = 1;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -380,24 +486,24 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
        /* check that they really want us to change something */
        if (old_termios) {
                if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-                   dbg("%s - nothing to change...", __FUNCTION__);
-                   return;
+                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
+                    RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg("%s - nothing to change...", __FUNCTION__);
+                       return;
                }
        }
 
-       buf = kzalloc (7, GFP_KERNEL);
+       buf = kzalloc(7, GFP_KERNEL);
        if (!buf) {
                dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
                return;
        }
-       
-       i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
-                            GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
-                            0, 0, buf, 7, 100);
-       dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
-            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
+       i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                           GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+                           0, 0, buf, 7, 100);
+       dbg("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
+           buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
        if (cflag & CSIZE) {
                switch (cflag & CSIZE) {
@@ -429,7 +535,8 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
                case B230400:   baud = 230400;  break;
                case B460800:   baud = 460800;  break;
                default:
-                       dev_err(&port->dev, "pl2303 driver does not support the baudrate requested (fix it)\n");
+                       dev_err(&port->dev, "pl2303 driver does not support"
+                               " the baudrate requested (fix it)\n");
                        break;
        }
        dbg("%s - baud = %d", __FUNCTION__, baud);
@@ -469,10 +576,10 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
                dbg("%s - parity = none", __FUNCTION__);
        }
 
-       i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-                            SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 
-                            0, 0, buf, 7, 100);
-       dbg ("0x21:0x20:0:0  %d", i);
+       i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                           SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
+                           0, 0, buf, 7, 100);
+       dbg("0x21:0x20:0:0  %d", i);
 
        /* change control lines if we are switching to or from B0 */
        spin_lock_irqsave(&priv->lock, flags);
@@ -488,13 +595,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
        } else {
                spin_unlock_irqrestore(&priv->lock, flags);
        }
-       
+
        buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
 
-       i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
-                            GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
-                            0, 0, buf, 7, 100);
-       dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
+       i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                           GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+                           0, 0, buf, 7, 100);
+       dbg("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
        if (cflag & CRTSCTS) {
@@ -503,18 +610,82 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
                        index = 0x61;
                else
                        index = 0x41;
-               i = usb_control_msg(serial->dev, 
+               i = usb_control_msg(serial->dev,
                                    usb_sndctrlpipe(serial->dev, 0),
                                    VENDOR_WRITE_REQUEST,
                                    VENDOR_WRITE_REQUEST_TYPE,
                                    0x0, index, NULL, 0, 100);
-               dbg ("0x40:0x1:0x0:0x%x  %d", index, i);
+               dbg("0x40:0x1:0x0:0x%x  %d", index, i);
        }
 
-       kfree (buf);
+       kfree(buf);
 }
 
-static int pl2303_open (struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int c_cflag;
+       int bps;
+       long timeout;
+       wait_queue_t wait;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* wait for data to drain from the buffer */
+       spin_lock_irqsave(&priv->lock, flags);
+       timeout = PL2303_CLOSING_WAIT;
+       init_waitqueue_entry(&wait, current);
+       add_wait_queue(&port->tty->write_wait, &wait);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (pl2303_buf_data_avail(priv->buf) == 0 ||
+                   timeout == 0 || signal_pending(current) ||
+                   !usb_get_intfdata(port->serial->interface)) /* disconnect */
+                       break;
+               spin_unlock_irqrestore(&priv->lock, flags);
+               timeout = schedule_timeout(timeout);
+               spin_lock_irqsave(&priv->lock, flags);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&port->tty->write_wait, &wait);
+       /* clear out any remaining data in the buffer */
+       pl2303_buf_clear(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* wait for characters to drain from the device */
+       /* (this is long enough for the entire 256 byte */
+       /* pl2303 hardware buffer to drain with no flow */
+       /* control for data rates of 1200 bps or more, */
+       /* for lower rates we should really know how much */
+       /* data is in the buffer to compute a delay */
+       /* that is not unnecessarily long) */
+       bps = tty_get_baud_rate(port->tty);
+       if (bps > 1200)
+               timeout = max((HZ*2560)/bps,HZ/10);
+       else
+               timeout = 2*HZ;
+       schedule_timeout_interruptible(timeout);
+
+       /* shutdown our urbs */
+       dbg("%s - shutting down urbs", __FUNCTION__);
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       if (port->tty) {
+               c_cflag = port->tty->termios->c_cflag;
+               if (c_cflag & HUPCL) {
+                       /* drop DTR and RTS */
+                       spin_lock_irqsave(&priv->lock, flags);
+                       priv->line_control = 0;
+                       spin_unlock_irqrestore(&priv->lock, flags);
+                       set_control_lines(port->serial->dev, 0);
+               }
+       }
+}
+
+static int pl2303_open(struct usb_serial_port *port, struct file *filp)
 {
        struct termios tmp_termios;
        struct usb_serial *serial = port->serial;
@@ -566,100 +737,37 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
 
        kfree(buf);
 
-       /* Setup termios */
-       if (port->tty) {
-               pl2303_set_termios (port, &tmp_termios);
-       }
-
-       //FIXME: need to assert RTS and DTR if CRTSCTS off
-
-       dbg("%s - submitting read urb", __FUNCTION__);
-       port->read_urb->dev = serial->dev;
-       result = usb_submit_urb (port->read_urb, GFP_KERNEL);
-       if (result) {
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
-               pl2303_close (port, NULL);
-               return -EPROTO;
-       }
-
-       dbg("%s - submitting interrupt urb", __FUNCTION__);
-       port->interrupt_in_urb->dev = serial->dev;
-       result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
-       if (result) {
-               dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result);
-               pl2303_close (port, NULL);
-               return -EPROTO;
-       }
-       return 0;
-}
-
-
-static void pl2303_close (struct usb_serial_port *port, struct file *filp)
-{
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
-
-       dbg("%s - port %d", __FUNCTION__, port->number);
-
-       /* wait for data to drain from the buffer */
-       spin_lock_irqsave(&priv->lock, flags);
-       timeout = PL2303_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&port->tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (pl2303_buf_data_avail(priv->buf) == 0
-               || timeout == 0 || signal_pending(current)
-               || !usb_get_intfdata(port->serial->interface))  /* disconnect */
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&port->tty->write_wait, &wait);
-       /* clear out any remaining data in the buffer */
-       pl2303_buf_clear(priv->buf);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* wait for characters to drain from the device */
-       /* (this is long enough for the entire 256 byte */
-       /* pl2303 hardware buffer to drain with no flow */
-       /* control for data rates of 1200 bps or more, */
-       /* for lower rates we should really know how much */
-       /* data is in the buffer to compute a delay */
-       /* that is not unnecessarily long) */
-       bps = tty_get_baud_rate(port->tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560)/bps,HZ/10);
-       else
-               timeout = 2*HZ;
-       schedule_timeout_interruptible(timeout);
-
-       /* shutdown our urbs */
-       dbg("%s - shutting down urbs", __FUNCTION__);
-       usb_kill_urb(port->write_urb);
-       usb_kill_urb(port->read_urb);
-       usb_kill_urb(port->interrupt_in_urb);
-
+       /* Setup termios */
        if (port->tty) {
-               c_cflag = port->tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore (&priv->lock, flags);
-                       set_control_lines (port->serial->dev, 0);
-               }
+               pl2303_set_termios(port, &tmp_termios);
+       }
+
+       //FIXME: need to assert RTS and DTR if CRTSCTS off
+
+       dbg("%s - submitting read urb", __FUNCTION__);
+       port->read_urb->dev = serial->dev;
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       if (result) {
+               dev_err(&port->dev, "%s - failed submitting read urb,"
+                       " error %d\n", __FUNCTION__, result);
+               pl2303_close(port, NULL);
+               return -EPROTO;
+       }
+
+       dbg("%s - submitting interrupt urb", __FUNCTION__);
+       port->interrupt_in_urb->dev = serial->dev;
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+       if (result) {
+               dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+                       " error %d\n", __FUNCTION__, result);
+               pl2303_close(port, NULL);
+               return -EPROTO;
        }
+       return 0;
 }
 
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-                           unsigned int set, unsigned int clear)
+static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+                          unsigned int set, unsigned int clear)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
@@ -668,7 +776,7 @@ static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
 
-       spin_lock_irqsave (&priv->lock, flags);
+       spin_lock_irqsave(&priv->lock, flags);
        if (set & TIOCM_RTS)
                priv->line_control |= CONTROL_RTS;
        if (set & TIOCM_DTR)
@@ -678,12 +786,12 @@ static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
        if (clear & TIOCM_DTR)
                priv->line_control &= ~CONTROL_DTR;
        control = priv->line_control;
-       spin_unlock_irqrestore (&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
-       return set_control_lines (port->serial->dev, control);
+       return set_control_lines(port->serial->dev, control);
 }
 
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
+static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
@@ -696,10 +804,10 @@ static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
 
-       spin_lock_irqsave (&priv->lock, flags);
+       spin_lock_irqsave(&priv->lock, flags);
        mcr = priv->line_control;
        status = priv->line_status;
-       spin_unlock_irqrestore (&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        result = ((mcr & CONTROL_DTR)           ? TIOCM_DTR : 0)
                  | ((mcr & CONTROL_RTS)        ? TIOCM_RTS : 0)
@@ -721,22 +829,22 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        unsigned int status;
        unsigned int changed;
 
-       spin_lock_irqsave (&priv->lock, flags);
+       spin_lock_irqsave(&priv->lock, flags);
        prevstatus = priv->line_status;
-       spin_unlock_irqrestore (&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
                interruptible_sleep_on(&priv->delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
-               
-               spin_lock_irqsave (&priv->lock, flags);
+
+               spin_lock_irqsave(&priv->lock, flags);
                status = priv->line_status;
-               spin_unlock_irqrestore (&priv->lock, flags);
-               
+               spin_unlock_irqrestore(&priv->lock, flags);
+
                changed=prevstatus^status;
-               
+
                if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
                    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
                    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||
@@ -749,7 +857,8 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        return 0;
 }
 
-static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+                       unsigned int cmd, unsigned long arg)
 {
        dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
 
@@ -766,7 +875,7 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign
        return -ENOIOCTLCMD;
 }
 
-static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
 {
        struct usb_serial *serial = port->serial;
        u16 state;
@@ -780,15 +889,14 @@ static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
                state = BREAK_ON;
        dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
-       result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
-                                 0, NULL, 0, 100);
+       result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                                BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+                                0, NULL, 0, 100);
        if (result)
                dbg("%s - error sending break = %d", __FUNCTION__, result);
 }
 
-
-static void pl2303_shutdown (struct usb_serial *serial)
+static void pl2303_shutdown(struct usb_serial *serial)
 {
        int i;
        struct pl2303_private *priv;
@@ -802,7 +910,7 @@ static void pl2303_shutdown (struct usb_serial *serial)
                        kfree(priv);
                        usb_set_serial_port_data(serial->port[i], NULL);
                }
-       }               
+       }
 }
 
 static void pl2303_update_line_status(struct usb_serial_port *port,
@@ -814,29 +922,33 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
        unsigned long flags;
        u8 status_idx = UART_STATE;
        u8 length = UART_STATE + 1;
+       u16 idv, idp;
+
+       idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
+       idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
 
-       if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
-           (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 ||
-            le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_SX1 ||
-            le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X75)) {
-               length = 1;
-               status_idx = 0;
+
+       if (idv == SIEMENS_VENDOR_ID) {
+               if (idp == SIEMENS_PRODUCT_ID_X65 ||
+                   idp == SIEMENS_PRODUCT_ID_SX1 ||
+                   idp == SIEMENS_PRODUCT_ID_X75) {
+
+                       length = 1;
+                       status_idx = 0;
+               }
        }
 
        if (actual_length < length)
-               goto exit;
+               return;
 
         /* Save off the uart status for others to look at */
        spin_lock_irqsave(&priv->lock, flags);
        priv->line_status = data[status_idx];
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible (&priv->delta_msr_wait);
-
-exit:
-       return;
+       wake_up_interruptible(&priv->delta_msr_wait);
 }
 
-static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_read_int_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        unsigned char *data = urb->transfer_buffer;
@@ -853,25 +965,29 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+                   urb->status);
                goto exit;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                             urb->actual_length, urb->transfer_buffer);
+
        pl2303_update_line_status(port, data, actual_length);
 
 exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status)
-               dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+               dev_err(&urb->dev->dev,
+                       "%s - usb_submit_urb failed with result %d\n",
                        __FUNCTION__, status);
 }
 
-
-static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -892,20 +1008,25 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
                        return;
                }
                if (urb->status == -EPROTO) {
-                       /* PL2303 mysteriously fails with -EPROTO reschedule the read */
-                       dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+                       /* PL2303 mysteriously fails with -EPROTO reschedule
+                        * the read */
+                       dbg("%s - caught -EPROTO, resubmitting the urb",
+                           __FUNCTION__);
                        urb->status = 0;
                        urb->dev = port->serial->dev;
                        result = usb_submit_urb(urb, GFP_ATOMIC);
                        if (result)
-                               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                               dev_err(&urb->dev->dev, "%s - failed"
+                                       " resubmitting read urb, error %d\n",
+                                       __FUNCTION__, result);
                        return;
                }
                dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                             urb->actual_length, data);
 
        /* get tty_flag from status */
        tty_flag = TTY_NORMAL;
@@ -914,7 +1035,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
        status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible (&priv->delta_msr_wait);
+       wake_up_interruptible(&priv->delta_msr_wait);
 
        /* break takes precedence over parity, */
        /* which takes precedence over framing errors */
@@ -933,8 +1054,8 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
                if (status & UART_OVERRUN_ERROR)
                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                for (i = 0; i < urb->actual_length; ++i)
-                       tty_insert_flip_char (tty, data[i], tty_flag);
-               tty_flip_buffer_push (tty);
+                       tty_insert_flip_char(tty, data[i], tty_flag);
+               tty_flip_buffer_push(tty);
        }
 
        /* Schedule the next read _if_ we are still open */
@@ -942,15 +1063,14 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
                urb->dev = port->serial->dev;
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result)
-                       dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&urb->dev->dev, "%s - failed resubmitting"
+                               " read urb, error %d\n", __FUNCTION__, result);
        }
 
        return;
 }
 
-
-
-static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -966,18 +1086,21 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
                priv->write_urb_in_use = 0;
                return;
        default:
                /* error in the urb, so we have to resubmit it */
                dbg("%s - Overflow in write", __FUNCTION__);
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
+                   urb->status);
                port->write_urb->transfer_buffer_length = 1;
                port->write_urb->dev = port->serial->dev;
-               result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result)
-                       dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&urb->dev->dev, "%s - failed resubmitting write"
+                               " urb, error %d\n", __FUNCTION__, result);
                else
                        return;
        }
@@ -988,191 +1111,38 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        pl2303_send(port);
 }
 
+/* All of the device info needed for the PL2303 SIO serial converter */
+static struct usb_serial_driver pl2303_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "pl2303",
+       },
+       .id_table =             id_table,
+       .num_interrupt_in =     NUM_DONT_CARE,
+       .num_bulk_in =          1,
+       .num_bulk_out =         1,
+       .num_ports =            1,
+       .open =                 pl2303_open,
+       .close =                pl2303_close,
+       .write =                pl2303_write,
+       .ioctl =                pl2303_ioctl,
+       .break_ctl =            pl2303_break_ctl,
+       .set_termios =          pl2303_set_termios,
+       .tiocmget =             pl2303_tiocmget,
+       .tiocmset =             pl2303_tiocmset,
+       .read_bulk_callback =   pl2303_read_bulk_callback,
+       .read_int_callback =    pl2303_read_int_callback,
+       .write_bulk_callback =  pl2303_write_bulk_callback,
+       .write_room =           pl2303_write_room,
+       .chars_in_buffer =      pl2303_chars_in_buffer,
+       .attach =               pl2303_startup,
+       .shutdown =             pl2303_shutdown,
+};
 
-/*
- * pl2303_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
-{
-
-       struct pl2303_buf *pb;
-
-
-       if (size == 0)
-               return NULL;
-
-       pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
-       if (pb == NULL)
-               return NULL;
-
-       pb->buf_buf = kmalloc(size, GFP_KERNEL);
-       if (pb->buf_buf == NULL) {
-               kfree(pb);
-               return NULL;
-       }
-
-       pb->buf_size = size;
-       pb->buf_get = pb->buf_put = pb->buf_buf;
-
-       return pb;
-
-}
-
-
-/*
- * pl2303_buf_free
- *
- * Free the buffer and all associated memory.
- */
-
-static void pl2303_buf_free(struct pl2303_buf *pb)
-{
-       if (pb) {
-               kfree(pb->buf_buf);
-               kfree(pb);
-       }
-}
-
-
-/*
- * pl2303_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-
-static void pl2303_buf_clear(struct pl2303_buf *pb)
-{
-       if (pb != NULL)
-               pb->buf_get = pb->buf_put;
-               /* equivalent to a get of all data available */
-}
-
-
-/*
- * pl2303_buf_data_avail
- *
- * Return the number of bytes of data available in the circular
- * buffer.
- */
-
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
-{
-       if (pb != NULL)
-               return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
-       else
-               return 0;
-}
-
-
-/*
- * pl2303_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
-{
-       if (pb != NULL)
-               return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
-       else
-               return 0;
-}
-
-
-/*
- * pl2303_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
-       unsigned int count)
-{
-
-       unsigned int len;
-
-
-       if (pb == NULL)
-               return 0;
-
-       len  = pl2303_buf_space_avail(pb);
-       if (count > len)
-               count = len;
-
-       if (count == 0)
-               return 0;
-
-       len = pb->buf_buf + pb->buf_size - pb->buf_put;
-       if (count > len) {
-               memcpy(pb->buf_put, buf, len);
-               memcpy(pb->buf_buf, buf+len, count - len);
-               pb->buf_put = pb->buf_buf + count - len;
-       } else {
-               memcpy(pb->buf_put, buf, count);
-               if (count < len)
-                       pb->buf_put += count;
-               else /* count == len */
-                       pb->buf_put = pb->buf_buf;
-       }
-
-       return count;
-
-}
-
-
-/*
- * pl2303_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
-       unsigned int count)
-{
-
-       unsigned int len;
-
-
-       if (pb == NULL)
-               return 0;
-
-       len = pl2303_buf_data_avail(pb);
-       if (count > len)
-               count = len;
-
-       if (count == 0)
-               return 0;
-
-       len = pb->buf_buf + pb->buf_size - pb->buf_get;
-       if (count > len) {
-               memcpy(buf, pb->buf_get, len);
-               memcpy(buf+len, pb->buf_buf, count - len);
-               pb->buf_get = pb->buf_buf + count - len;
-       } else {
-               memcpy(buf, pb->buf_get, count);
-               if (count < len)
-                       pb->buf_get += count;
-               else /* count == len */
-                       pb->buf_get = pb->buf_buf;
-       }
-
-       return count;
-
-}
-
-static int __init pl2303_init (void)
+static int __init pl2303_init(void)
 {
        int retval;
+
        retval = usb_serial_register(&pl2303_device);
        if (retval)
                goto failed_usb_serial_register;
@@ -1187,14 +1157,12 @@ failed_usb_serial_register:
        return retval;
 }
 
-
-static void __exit pl2303_exit (void)
+static void __exit pl2303_exit(void)
 {
-       usb_deregister (&pl2303_driver);
-       usb_serial_deregister (&pl2303_device);
+       usb_deregister(&pl2303_driver);
+       usb_serial_deregister(&pl2303_device);
 }
 
-
 module_init(pl2303_init);
 module_exit(pl2303_exit);
 
index 55195e76eb6fb1bf42af33c07be1953e7048a64c..65a5039665e71d31610d5d73645321dd6389b0f0 100644 (file)
 /* Belkin "F5U257" Serial Adapter */
 #define BELKIN_VENDOR_ID       0x050d
 #define BELKIN_PRODUCT_ID      0x0257
+
+/* Alcor Micro Corp. USB 2.0 TO RS-232 */
+#define ALCOR_VENDOR_ID                0x058F
+#define ALCOR_PRODUCT_ID       0x9720
+
+/* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
+#define HUAWEI_VENDOR_ID       0x12d1
+#define HUAWEI_PRODUCT_ID      0x1001
index 789771ecdb11013a168ffc5fa0157474ab4538dc..1e07dfad68535b54a80a8860f9fc8b71e1f6f615 100644 (file)
@@ -298,14 +298,14 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
                dbg ("%s - write request of 0 bytes", __FUNCTION__);
                return (0);
        }
-       spin_lock(&port->lock);
+       spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
-               spin_unlock(&port->lock);
+               spin_unlock_bh(&port->lock);
                dbg("%s - already writing", __FUNCTION__);
                return 0;
        }
        port->write_urb_busy = 1;
-       spin_unlock(&port->lock);
+       spin_unlock_bh(&port->lock);
 
        packet_length = port->bulk_out_size;    // get max packetsize
 
index e06a41bd0f3ba4b458aaf11470c901965cff7710..0222d92842b8ba79e89404d58ebcd06c729e8a2a 100644 (file)
@@ -676,33 +676,29 @@ int usb_serial_probe(struct usb_interface *interface,
        iface_desc = interface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
-               
-               if ((endpoint->bEndpointAddress & 0x80) &&
-                   ((endpoint->bmAttributes & 3) == 0x02)) {
+
+               if (usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        dbg("found bulk in on endpoint %d", i);
                        bulk_in_endpoint[num_bulk_in] = endpoint;
                        ++num_bulk_in;
                }
 
-               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-                   ((endpoint->bmAttributes & 3) == 0x02)) {
+               if (usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dbg("found bulk out on endpoint %d", i);
                        bulk_out_endpoint[num_bulk_out] = endpoint;
                        ++num_bulk_out;
                }
-               
-               if ((endpoint->bEndpointAddress & 0x80) &&
-                   ((endpoint->bmAttributes & 3) == 0x03)) {
+
+               if (usb_endpoint_is_int_in(endpoint)) {
                        /* we found a interrupt in endpoint */
                        dbg("found interrupt in on endpoint %d", i);
                        interrupt_in_endpoint[num_interrupt_in] = endpoint;
                        ++num_interrupt_in;
                }
 
-               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-                   ((endpoint->bmAttributes & 3) == 0x03)) {
+               if (usb_endpoint_is_int_out(endpoint)) {
                        /* we found an interrupt out endpoint */
                        dbg("found interrupt out on endpoint %d", i);
                        interrupt_out_endpoint[num_interrupt_out] = endpoint;
@@ -716,14 +712,15 @@ int usb_serial_probe(struct usb_interface *interface,
        if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
             (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
            ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
-            (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) {
+            (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
+           ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
+            (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
                if (interface != dev->actconfig->interface[0]) {
                        /* check out the endpoints of the other interface*/
                        iface_desc = dev->actconfig->interface[0]->cur_altsetting;
                        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                                endpoint = &iface_desc->endpoint[i].desc;
-                               if ((endpoint->bEndpointAddress & 0x80) &&
-                                   ((endpoint->bmAttributes & 3) == 0x03)) {
+                               if (usb_endpoint_is_int_in(endpoint)) {
                                        /* we found a interrupt in endpoint */
                                        dbg("found interrupt in for Prolific device on separate interface");
                                        interrupt_in_endpoint[num_interrupt_in] = endpoint;
@@ -937,7 +934,10 @@ int usb_serial_probe(struct usb_interface *interface,
 
                snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
                dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
-               device_register (&port->dev);
+               retval = device_register(&port->dev);
+               if (retval)
+                       dev_err(&port->dev, "Error registering port device, "
+                               "continuing\n");
        }
 
        usb_serial_console_init (debug, minor);
index be9eec2257436c2152aecd9e0d20462f69902b2e..422a4b288e346f589687aada8950d294dfbf469a 100644 (file)
@@ -8,8 +8,7 @@ comment "may also be needed; see USB_STORAGE Help for more information"
 
 config USB_STORAGE
        tristate "USB Mass Storage support"
-       depends on USB
-       select SCSI
+       depends on USB && SCSI
        ---help---
          Say Y here if you want to connect USB mass storage devices to your
          computer's USB port. This is the driver you need for USB
@@ -18,7 +17,7 @@ config USB_STORAGE
          similar devices. This driver may also be used for some cameras
          and card readers.
 
-         This option 'selects' (turns on, enables) 'SCSI', but you
+         This option depends on 'SCSI' support being enabled, but you
          probably also need 'SCSI device support: SCSI disk support'
          (BLK_DEV_SD) for most USB storage devices.
 
@@ -135,6 +134,18 @@ config USB_STORAGE_ONETOUCH
          this input in any keybinding software. (e.g. gnome's keyboard short-
          cuts)
 
+config USB_STORAGE_KARMA
+       bool "Support for Rio Karma music player"
+       depends on USB_STORAGE
+       help
+         Say Y here to include additional code to support the Rio Karma
+         USB interface.
+
+         This code places the Rio Karma into mass storage mode, enabling
+         it to be mounted as an ordinary filesystem. Performing an eject
+         on the resulting scsi device node returns the Karma to normal
+         operation.
+
 config USB_LIBUSUAL
        bool "The shared table of common (or usual) storage devices"
        depends on USB
index 8cbba22508a47d77d3a39897d4138e7be5a7f7ae..023969b4385b689265b3836cb130a6dd8de64fad 100644 (file)
@@ -20,6 +20,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)   += alauda.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)    += karma.o
 
 usb-storage-objs :=    scsiglue.o protocol.o transport.o usb.o \
                        initializers.o $(usb-storage-obj-y)
index ab173b30076eb1b7ac2ec3a2fe257a78863918d5..5b06f9240d05caa2b348c7cf55cf520ff2ca2240 100644 (file)
 #include "debug.h"
 #include "transport.h"
 
-#define RIO_MSC 0x08
-#define RIOP_INIT "RIOP\x00\x01\x08"
-#define RIOP_INIT_LEN 7
-#define RIO_SEND_LEN 40
-#define RIO_RECV_LEN 0x200
-
 /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
  * mode */
 int usb_stor_euscsi_init(struct us_data *us)
@@ -97,70 +91,3 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
 
        return (res ? -1 : 0);
 }
-
-/* Place the Rio Karma into mass storage mode.
- *
- * The initialization begins by sending 40 bytes starting
- * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
- * packet with the high four bits set and everything else null.
- *
- * Next, we send RIOP\x80\x00\x08\x00.  Each time, a 512 byte response
- * must be read, but we must loop until byte 5 in the response is 0x08,
- * indicating success.  */
-int rio_karma_init(struct us_data *us)
-{
-       int result, partial;
-       char *recv;
-       unsigned long timeout;
-
-       // us->iobuf is big enough to hold cmd but not receive
-       if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
-               goto die_nomem;
-
-       US_DEBUGP("Initializing Karma...\n");
-
-       memset(us->iobuf, 0, RIO_SEND_LEN);
-       memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);
-
-       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-               us->iobuf, RIO_SEND_LEN, &partial);
-       if (result != USB_STOR_XFER_GOOD)
-               goto die;
-
-       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-               recv, RIO_RECV_LEN, &partial);
-       if (result != USB_STOR_XFER_GOOD)
-               goto die;
-
-       us->iobuf[4] = 0x80;
-       us->iobuf[5] = 0;
-       timeout = jiffies + msecs_to_jiffies(3000);
-       for (;;) {
-               US_DEBUGP("Sending init command\n");
-               result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-                       us->iobuf, RIO_SEND_LEN, &partial);
-               if (result != USB_STOR_XFER_GOOD)
-                       goto die;
-
-               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-                       recv, RIO_RECV_LEN, &partial);
-               if (result != USB_STOR_XFER_GOOD)
-                       goto die;
-
-               if (recv[5] == RIO_MSC)
-                       break;
-               if (time_after(jiffies, timeout))
-                       goto die;
-               msleep(10);
-       }
-       US_DEBUGP("Karma initialized.\n");
-       kfree(recv);
-       return 0;
-
-die:
-       kfree(recv);
-die_nomem:
-       US_DEBUGP("Could not initialize karma.\n");
-       return USB_STOR_TRANSPORT_FAILED;
-}
-
index 927f7781080f0afebff4b1e5ee4602cf27b6526a..e2967a4d48a2e30d0fa694f233d10941ec88121a 100644 (file)
@@ -47,4 +47,3 @@ int usb_stor_euscsi_init(struct us_data *us);
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
-int rio_karma_init(struct us_data *us);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
new file mode 100644 (file)
index 0000000..0d79ae5
--- /dev/null
@@ -0,0 +1,155 @@
+/* Driver for Rio Karma
+ *
+ *   (c) 2006 Bob Copeland <me@bobcopeland.com>
+ *   (c) 2006 Keith Bennett <keith@mcs.st-and.ac.uk>
+ *
+ * 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.
+ */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "debug.h"
+#include "karma.h"
+
+#define RIO_PREFIX "RIOP\x00"
+#define RIO_PREFIX_LEN 5
+#define RIO_SEND_LEN 40
+#define RIO_RECV_LEN 0x200
+
+#define RIO_ENTER_STORAGE 0x1
+#define RIO_LEAVE_STORAGE 0x2
+#define RIO_RESET 0xC
+
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
+
+struct karma_data {
+       int in_storage;
+       char *recv;
+};
+
+/*
+ * Send commands to Rio Karma.
+ *
+ * For each command we send 40 bytes starting 'RIOP\0' followed by
+ * the command number and a sequence number, which the device will ack
+ * with a 512-byte packet with the high four bits set and everything
+ * else null.  Then we send 'RIOP\x80' followed by a zero and the
+ * sequence number, until byte 5 in the response repeats the sequence
+ * number.
+ */
+static int rio_karma_send_command(char cmd, struct us_data *us)
+{
+       int result, partial;
+       unsigned long timeout;
+       static unsigned char seq = 1;
+       struct karma_data *data = (struct karma_data *) us->extra;
+
+       US_DEBUGP("karma: sending command %04x\n", cmd);
+       memset(us->iobuf, 0, RIO_SEND_LEN);
+       memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
+       us->iobuf[5] = cmd;
+       us->iobuf[6] = seq;
+
+       timeout = jiffies + msecs_to_jiffies(6000);
+       for (;;) {
+               result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+                       us->iobuf, RIO_SEND_LEN, &partial);
+               if (result != USB_STOR_XFER_GOOD)
+                       goto err;
+
+               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+                       data->recv, RIO_RECV_LEN, &partial);
+               if (result != USB_STOR_XFER_GOOD)
+                       goto err;
+
+               if (data->recv[5] == seq)
+                       break;
+
+               if (time_after(jiffies, timeout))
+                       goto err;
+
+               us->iobuf[4] = 0x80;
+               us->iobuf[5] = 0;
+               msleep(50);
+       }
+
+       seq++;
+       if (seq == 0)
+               seq = 1;
+
+       US_DEBUGP("karma: sent command %04x\n", cmd);
+       return 0;
+err:
+       US_DEBUGP("karma: command %04x failed\n", cmd);
+       return USB_STOR_TRANSPORT_FAILED;
+}
+
+/*
+ * Trap START_STOP and READ_10 to leave/re-enter storage mode.
+ * Everything else is propagated to the normal bulk layer.
+ */
+int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+       int ret;
+       struct karma_data *data = (struct karma_data *) us->extra;
+
+       if (srb->cmnd[0] == READ_10 && !data->in_storage) {
+               ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+               if (ret)
+                       return ret;
+
+               data->in_storage = 1;
+               return usb_stor_Bulk_transport(srb, us);
+       } else if (srb->cmnd[0] == START_STOP) {
+               ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us);
+               if (ret)
+                       return ret;
+
+               data->in_storage = 0;
+               return rio_karma_send_command(RIO_RESET, us);
+       }
+       return usb_stor_Bulk_transport(srb, us);
+}
+
+static void rio_karma_destructor(void *extra)
+{
+       struct karma_data *data = (struct karma_data *) extra;
+       kfree(data->recv);
+}
+
+int rio_karma_init(struct us_data *us)
+{
+       int ret = 0;
+       struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
+       if (!data)
+               goto out;
+
+       data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
+       if (!data->recv) {
+               kfree(data);
+               goto out;
+       }
+
+       us->extra = data;
+       us->extra_destructor = rio_karma_destructor;
+       ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+       data->in_storage = (ret == 0);
+out:
+       return ret;
+}
diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h
new file mode 100644 (file)
index 0000000..8a60972
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _KARMA_USB_H
+#define _KARMA_USB_H
+
+extern int rio_karma_init(struct us_data *us);
+extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us);
+
+#endif
index b1ec4a718547316c62cf39fa4872ffd7651424f9..599ad10a761b703da02f989eb51a88d0941ae0fd 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/usb.h>
 #include <linux/usb_usual.h>
 #include <linux/vmalloc.h>
+#include <linux/kthread.h>
 
 /*
  */
@@ -117,7 +118,7 @@ static int usu_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
        unsigned long type;
-       int rc;
+       struct task_struct* task;
        unsigned long flags;
 
        type = USB_US_TYPE(id->driver_info);
@@ -132,8 +133,9 @@ static int usu_probe(struct usb_interface *intf,
        stat[type].fls |= USU_MOD_FL_THREAD;
        spin_unlock_irqrestore(&usu_lock, flags);
 
-       rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
-       if (rc < 0) {
+       task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
+       if (IS_ERR(task)) {
+               int rc = PTR_ERR(task);
                printk(KERN_WARNING "libusual: "
                    "Unable to start the thread for %s: %d\n",
                    bias_names[type], rc);
@@ -175,8 +177,6 @@ static int usu_probe_thread(void *arg)
        int rc;
        unsigned long flags;
 
-       daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */
-
        /* A completion does not work here because it's counted. */
        down(&usu_init_notify);
        up(&usu_init_notify);
index 313920d980c9aa7b7fc39c7864409b2ed7bb6130..f843a0bcf107a55b2d3f65a65be2875519357fc9 100644 (file)
@@ -135,6 +135,7 @@ int onetouch_connect_input(struct us_data *ss)
        struct usb_onetouch *onetouch;
        struct input_dev *input_dev;
        int pipe, maxp;
+       int error = -ENOMEM;
 
        interface = ss->pusb_intf->cur_altsetting;
 
@@ -211,15 +212,18 @@ int onetouch_connect_input(struct us_data *ss)
        ss->suspend_resume_hook = usb_onetouch_pm_hook;
 #endif
 
-       input_register_device(onetouch->dev);
+       error = input_register_device(onetouch->dev);
+       if (error)
+               goto fail3;
 
        return 0;
 
+ fail3:        usb_free_urb(onetouch->irq);
  fail2:        usb_buffer_free(udev, ONETOUCH_PKT_LEN,
                        onetouch->data, onetouch->data_dma);
  fail1:        kfree(onetouch);
        input_free_device(input_dev);
-       return -ENOMEM;
+       return error;
 }
 
 void onetouch_release_input(void *onetouch_)
index a4b7df9ff8c165fd3067f7c8e8ff5ead4becf2a4..e1072d52d6419a93b7b9135dd05cf5a09cb9b913 100644 (file)
@@ -72,12 +72,27 @@ static const char* host_info(struct Scsi_Host *host)
 
 static int slave_alloc (struct scsi_device *sdev)
 {
+       struct us_data *us = host_to_us(sdev->host);
+
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
         * the extra data and many devices choke if asked for more or
         * less than 36 bytes.
         */
        sdev->inquiry_len = 36;
+
+       /*
+        * The UFI spec treates the Peripheral Qualifier bits in an
+        * INQUIRY result as reserved and requires devices to set them
+        * to 0.  However the SCSI spec requires these bits to be set
+        * to 3 to indicate when a LUN is not present.
+        *
+        * Let the scanning code know if this target merely sets
+        * Peripheral Device Type to 0x1f to indicate no LUN.
+        */
+       if (us->subclass == US_SC_UFI)
+               sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
        return 0;
 }
 
index d6acc92a4ae36ac66757450f9522f7cb667128f6..f23514c4e649bdd6947ce0301cf730e2344ef540 100644 (file)
@@ -294,11 +294,6 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
                        return USB_STOR_XFER_ERROR;
                return USB_STOR_XFER_STALLED;
 
-       /* timeout or excessively long NAK */
-       case -ETIMEDOUT:
-               US_DEBUGP("-- timeout or NAK\n");
-               return USB_STOR_XFER_ERROR;
-
        /* babble - the device tried to send more than we wanted to read */
        case -EOVERFLOW:
                US_DEBUGP("-- babble\n");
index b130e170b4a8a44c94e6ed07844fcab01b326797..c9a8d50106d1a3bef5b9f1359baad58d015f1725 100644 (file)
@@ -152,6 +152,13 @@ UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
+/* Reported by Jon Hart <Jon.Hart@web.de> */
+UNUSUAL_DEV(  0x0421, 0x0434, 0x0100, 0x0100,
+               "Nokia",
+               "E60",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
  * Einar Th. Einarsson <einarthered@gmail.com> */
 UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,
@@ -218,10 +225,12 @@ UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_NOT_LOCKABLE ),
 
+#ifdef CONFIG_USB_STORAGE_KARMA
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
                "Rio",
                "Rio Karma",
-               US_SC_SCSI, US_PR_BULK, rio_karma_init, 0),
+               US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+#endif
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
@@ -631,6 +640,13 @@ UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
                "Digital Camera EX-20 DSC",
                US_SC_8070, US_PR_DEVICE, NULL, 0 ),
 
+/* Reported by <Hendryk.Pfeiffer@gmx.de> */
+UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
+               "LaCie",
+               "DVD+-RW",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_GO_SLOW ),
+
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
  * Some versions of this device need the SubClass and Protocol overrides
  * while others don't.
@@ -1254,6 +1270,13 @@ UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_NO_WP_DETECT ),
 
+/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
+               "Sony Ericsson",
+               "P990i",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY ),
+
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
                "Sony Ericsson",
@@ -1261,6 +1284,13 @@ UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
+               "Sony Ericsson",
+               "P990i",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY ),
+
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
  * Entry is needed only for the initializer function override.
index 8d7bdcb5924d402f891cbf1a07c2584400a28cb3..b8d6031b09750245ce4bdece07ed7528e4a7e6c1 100644 (file)
@@ -98,6 +98,9 @@
 #ifdef CONFIG_USB_STORAGE_ALAUDA
 #include "alauda.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_KARMA
+#include "karma.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -646,6 +649,14 @@ static int get_transport(struct us_data *us)
                break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_KARMA
+       case US_PR_KARMA:
+               us->transport_name = "Rio Karma/Bulk";
+               us->transport = rio_karma_transport;
+               us->transport_reset = usb_stor_Bulk_reset;
+               break;
+#endif
+
        default:
                return -EIO;
        }
index b362039792b30fb596a916f8229f00b536b368ef..1b51d3187a95c8d99c87de153de5afed4a9831ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * USB Skeleton driver - 2.0
+ * USB Skeleton driver - 2.2
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
  *
@@ -7,9 +7,8 @@
  *     modify it under the terms of the GNU General Public License as
  *     published by the Free Software Foundation, version 2.
  *
- * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
- * but has been rewritten to be easy to read and use, as no locks are now
- * needed anymore.
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
  *
  */
 
@@ -21,6 +20,7 @@
 #include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
 
 
 /* Define these values to match your devices */
@@ -32,38 +32,39 @@ static struct usb_device_id skel_table [] = {
        { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
-MODULE_DEVICE_TABLE (usb, skel_table);
+MODULE_DEVICE_TABLE(usb, skel_table);
 
 
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE    192
 
 /* our private defines. if this grows any larger, use your own .h file */
-#define MAX_TRANSFER           ( PAGE_SIZE - 512 )
+#define MAX_TRANSFER           (PAGE_SIZE - 512)
 #define WRITES_IN_FLIGHT       8
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-       struct usb_device *     udev;                   /* the usb device for this device */
-       struct usb_interface *  interface;              /* the interface for this device */
+       struct usb_device       *dev;                   /* the usb device for this device */
+       struct usb_interface    *interface;             /* the interface for this device */
        struct semaphore        limit_sem;              /* limiting the number of writes in progress */
-       unsigned char *         bulk_in_buffer;         /* the buffer to receive data */
+       unsigned char           *bulk_in_buffer;        /* the buffer to receive data */
        size_t                  bulk_in_size;           /* the size of the receive buffer */
        __u8                    bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
        __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
        struct kref             kref;
+       struct mutex            io_mutex;               /* synchronize I/O with disconnect */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
 static struct usb_driver skel_driver;
 
 static void skel_delete(struct kref *kref)
-{      
+{
        struct usb_skel *dev = to_skel_dev(kref);
 
        usb_put_dev(dev->udev);
-       kfree (dev->bulk_in_buffer);
-       kfree (dev);
+       kfree(dev->bulk_in_buffer);
+       kfree(dev);
 }
 
 static int skel_open(struct inode *inode, struct file *file)
@@ -89,6 +90,11 @@ static int skel_open(struct inode *inode, struct file *file)
                goto exit;
        }
 
+       /* prevent the device from being autosuspended */
+       retval = usb_autopm_get_interface(interface);
+       if (retval)
+               goto exit;
+
        /* increment our usage count for the device */
        kref_get(&dev->kref);
 
@@ -107,6 +113,12 @@ static int skel_release(struct inode *inode, struct file *file)
        if (dev == NULL)
                return -ENODEV;
 
+       /* allow the device to be autosuspended */
+       mutex_lock(&dev->io_mutex);
+       if (dev->interface)
+               usb_autopm_put_interface(dev->interface);
+       mutex_unlock(&dev->io_mutex);
+
        /* decrement the count on our device */
        kref_put(&dev->kref, skel_delete);
        return 0;
@@ -115,11 +127,17 @@ static int skel_release(struct inode *inode, struct file *file)
 static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct usb_skel *dev;
-       int retval = 0;
+       int retval;
        int bytes_read;
 
        dev = (struct usb_skel *)file->private_data;
-       
+
+       mutex_lock(&dev->io_mutex);
+       if (!dev->interface) {          /* disconnect() was called */
+               retval = -ENODEV;
+               goto exit;
+       }
+
        /* do a blocking bulk read to get data from the device */
        retval = usb_bulk_msg(dev->udev,
                              usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
@@ -135,6 +153,8 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *
                        retval = bytes_read;
        }
 
+exit:
+       mutex_unlock(&dev->io_mutex);
        return retval;
 }
 
@@ -145,16 +165,16 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
        dev = (struct usb_skel *)urb->context;
 
        /* sync/async unlink faults aren't errors */
-       if (urb->status && 
-           !(urb->status == -ENOENT || 
+       if (urb->status &&
+           !(urb->status == -ENOENT ||
              urb->status == -ECONNRESET ||
              urb->status == -ESHUTDOWN)) {
-               dbg("%s - nonzero write bulk status received: %d",
+               err("%s - nonzero write bulk status received: %d",
                    __FUNCTION__, urb->status);
        }
 
        /* free up our allocated buffer */
-       usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
                        urb->transfer_buffer, urb->transfer_dma);
        up(&dev->limit_sem);
 }
@@ -179,6 +199,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
                goto exit;
        }
 
+       mutex_lock(&dev->io_mutex);
+       if (!dev->interface) {          /* disconnect() was called */
+               retval = -ENODEV;
+               goto error;
+       }
+
        /* create a urb, and a buffer for it, and copy the data to the urb */
        urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb) {
@@ -213,17 +239,22 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
        /* release our reference to this urb, the USB core will eventually free it entirely */
        usb_free_urb(urb);
 
-exit:
+       mutex_unlock(&dev->io_mutex);
        return writesize;
 
 error:
-       usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
-       usb_free_urb(urb);
+       if (urb) {
+               usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
+               usb_free_urb(urb);
+       }
+       mutex_unlock(&dev->io_mutex);
        up(&dev->limit_sem);
+
+exit:
        return retval;
 }
 
-static struct file_operations skel_fops = {
+static const struct file_operations skel_fops = {
        .owner =        THIS_MODULE,
        .read =         skel_read,
        .write =        skel_write,
@@ -231,7 +262,7 @@ static struct file_operations skel_fops = {
        .release =      skel_release,
 };
 
-/* 
+/*
  * usb class driver info in order to get a minor number from the usb core,
  * and to have the device registered with the driver core
  */
@@ -243,7 +274,7 @@ static struct usb_class_driver skel_class = {
 
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-       struct usb_skel *dev = NULL;
+       struct usb_skel *dev;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
        size_t buffer_size;
@@ -252,12 +283,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
 
        /* allocate memory for our device state and initialize it */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
+       if (!dev) {
                err("Out of memory");
                goto error;
        }
        kref_init(&dev->kref);
        sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+       mutex_init(&dev->io_mutex);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
@@ -269,10 +301,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
                endpoint = &iface_desc->endpoint[i].desc;
 
                if (!dev->bulk_in_endpointAddr &&
-                   ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                                       == USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                        dev->bulk_in_size = buffer_size;
@@ -285,10 +314,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
                }
 
                if (!dev->bulk_out_endpointAddr &&
-                   ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                                       == USB_DIR_OUT) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
                }
@@ -334,6 +360,11 @@ static void skel_disconnect(struct usb_interface *interface)
        /* give back our minor */
        usb_deregister_dev(interface, &skel_class);
 
+       /* prevent more I/O from starting */
+       mutex_lock(&dev->io_mutex);
+       dev->interface = NULL;
+       mutex_unlock(&dev->io_mutex);
+
        unlock_kernel();
 
        /* decrement our usage count */
@@ -367,7 +398,7 @@ static void __exit usb_skel_exit(void)
        usb_deregister(&skel_driver);
 }
 
-module_init (usb_skel_init);
-module_exit (usb_skel_exit);
+module_init(usb_skel_init);
+module_exit(usb_skel_exit);
 
 MODULE_LICENSE("GPL");
index 702eb933cf88bc9414ccbcb85e74de2dcfc18b08..e0ef3328942c44ff0eb09f249388aca98cc1cbcf 100644 (file)
@@ -825,30 +825,48 @@ config FB_I810_I2C
        help
 
 config FB_INTEL
-       tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
+       tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
        depends on FB && EXPERIMENTAL && PCI && X86
        select AGP
        select AGP_INTEL
+       select I2C_ALGOBIT if FB_INTEL_I2C
+       select I2C if FB_INTEL_I2C
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        help
          This driver supports the on-board graphics built in to the Intel
-          830M/845G/852GM/855GM/865G chipsets.
+          830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM chipsets.
           Say Y if you have and plan to use such a board.
 
-          To compile this driver as a module, choose M here: the
+         If you say Y here and want DDC/I2C support you must first say Y to
+         "I2C support" and "I2C bit-banging support" in the character devices
+         section.
+
+         If you say M here then "I2C support" and "I2C bit-banging support"
+         can be build either as modules or built-in.
+
+         To compile this driver as a module, choose M here: the
          module will be called intelfb.
 
+         For more information, please read <file:Documentation/fb/intelfb.txt>
+
 config FB_INTEL_DEBUG
-        bool "Intel driver Debug Messages"
+       bool "Intel driver Debug Messages"
        depends on FB_INTEL
        ---help---
          Say Y here if you want the Intel driver to output all sorts
          of debugging informations to provide to the maintainer when
          something goes wrong.
 
+config FB_INTEL_I2C
+       bool "DDC/I2C for Intel framebuffer support"
+       depends on FB_INTEL
+       default y
+       help
+         Say Y here if you want DDC/I2C support for your on-board Intel graphics.
+
 config FB_MATROX
        tristate "Matrox acceleration"
        depends on FB && PCI
index ffc72ae3ada80a01f98c959099b004e57bc5aed4..fe1488374f620cad6fa5fce1e8eef17b3ff79132 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <asm/cpu/dac.h>
 #include <asm/hp6xx/hp6xx.h>
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
 
 #define HP680_MAX_INTENSITY 255
 #define HP680_DEFAULT_INTENSITY 10
@@ -163,6 +163,6 @@ static void __exit hp680bl_exit(void)
 module_init(hp680bl_init);
 module_exit(hp680bl_exit);
 
-MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>");
+MODULE_AUTHOR("Andriy Skulysh <askulysh@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
 MODULE_LICENSE("GPL");
index caf1eca199b0041fa526afe23ae6f10393443a52..628571c63bacc4905517c5563a7fc0fa7848c564 100644 (file)
@@ -33,19 +33,19 @@ static unsigned long locomolcd_flags;
 
 static void locomolcd_on(int comadj)
 {
-       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1);
+       locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 1);
        mdelay(2);
 
-       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1);
+       locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 1);
        mdelay(2);
 
        locomo_m62332_senddata(locomolcd_dev, comadj, 0);
        mdelay(5);
 
-       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1);
+       locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 1);
        mdelay(10);
 
        /* TFTCRST | CPSOUT=0 | CPSEN */
@@ -58,8 +58,8 @@ static void locomolcd_on(int comadj)
        locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
        mdelay(10);
 
-       locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1);
+       locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 1);
 }
 
 static void locomolcd_off(int comadj)
@@ -68,16 +68,16 @@ static void locomolcd_off(int comadj)
        locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
        mdelay(1);
 
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
        mdelay(110);
 
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
        mdelay(700);
 
        /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
        locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0);
-       locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
+       locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
 }
 
 void locomolcd_power(int on)
@@ -167,14 +167,14 @@ static int locomolcd_resume(struct locomo_dev *dev)
 #define locomolcd_resume       NULL
 #endif
 
-static int locomolcd_probe(struct locomo_dev *dev)
+static int locomolcd_probe(struct locomo_dev *ldev)
 {
        unsigned long flags;
 
        local_irq_save(flags);
-       locomolcd_dev = dev;
+       locomolcd_dev = ldev;
 
-       locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0);
+       locomo_gpio_set_dir(ldev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
 
        /* the poodle_lcd_power function is called for the first time
         * from fs_initcall, which is before locomo is activated.
index 4444bef68fbafb03ca4d41aae1a46a8abfd740e6..aa3935df852ad6f9f04f1fce4c53091c8f0f8511 100644 (file)
@@ -6,7 +6,7 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
        bool "VGA text console" if EMBEDDED || !X86
-       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE
+       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH
        default y
        help
          Saying Y here will allow you to use Linux in text mode through a
index 4cc6b454265ee8b7ccdd60d439856365bc1ab867..3afb472763c0488fddcd1dd5a4c0e3bb5817c1f8 100644 (file)
@@ -4,7 +4,7 @@
  * (C) 1999 Mihai Spatar
  * (C) 2000 YAEGASHI Takeshi
  * (C) 2003, 2004 Paul Mundt
- * (C) 2003, 2004 Andriy Skulysh
+ * (C) 2003, 2004, 2006 Andriy Skulysh
  *
  *  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
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/fb.h>
 
 #include <asm/machvec.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
-
-#ifdef MACH_HP600
+#include <asm/hd64461.h>
 #include <asm/cpu/dac.h>
 #include <asm/hp6xx/hp6xx.h>
-#endif
 
 #define        WIDTH 640
 
@@ -45,7 +43,6 @@ static struct fb_var_screeninfo hitfb_var __initdata = {
 static struct fb_fix_screeninfo hitfb_fix __initdata = {
        .id             = "Hitachi HD64461",
        .type           = FB_TYPE_PACKED_PIXELS,
-       .ypanstep       = 8,
        .accel          = FB_ACCEL_NONE,
 };
 
@@ -73,26 +70,14 @@ static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy,
        if (truecolor)
                saddr <<= 1;
 
-       fb_writew(width, HD64461_BBTDWR);
-       fb_writew(height, HD64461_BBTDHR);
+       fb_writew(width-1, HD64461_BBTDWR);
+       fb_writew(height-1, HD64461_BBTDHR);
 
        fb_writew(saddr & 0xffff, HD64461_BBTDSARL);
        fb_writew(saddr >> 16, HD64461_BBTDSARH);
 
 }
 
-static inline void hitfb_accel_solidfill(int truecolor, u16 dx, u16 dy,
-                                        u16 width, u16 height, u16 color)
-{
-       hitfb_accel_set_dest(truecolor, dx, dy, width, height);
-
-       fb_writew(0x00f0, HD64461_BBTROPR);
-       fb_writew(16, HD64461_BBTMDR);
-       fb_writew(color, HD64461_GRSCR);
-
-       hitfb_accel_start(truecolor);
-}
-
 static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
                                      u16 dy, u16 width, u16 height, u16 rop,
                                      u32 mask_addr)
@@ -100,6 +85,8 @@ static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
        u32 saddr, daddr;
        u32 maddr = 0;
 
+       height--;
+       width--;
        fb_writew(rop, HD64461_BBTROPR);
        if ((sy < dy) || ((sy == dy) && (sx <= dx))) {
                saddr = WIDTH * (sy + height) + sx + width;
@@ -146,6 +133,7 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
        if (rect->rop != ROP_COPY)
                cfb_fillrect(p, rect);
        else {
+               hitfb_accel_wait();
                fb_writew(0x00f0, HD64461_BBTROPR);
                fb_writew(16, HD64461_BBTMDR);
 
@@ -161,16 +149,15 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
                                             rect->height);
                        hitfb_accel_start(0);
                }
-               hitfb_accel_wait();
        }
 }
 
 static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
 {
+       hitfb_accel_wait();
        hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy,
                           area->dx, area->dy, area->width, area->height,
                           0x00cc, 0);
-       hitfb_accel_wait();
 }
 
 static int hitfb_pan_display(struct fb_var_screeninfo *var,
@@ -182,7 +169,7 @@ static int hitfb_pan_display(struct fb_var_screeninfo *var,
        if (xoffset != 0)
                return -EINVAL;
 
-       fb_writew(yoffset, HD64461_LCDCBAR);
+       fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
 
        return 0;
 }
@@ -192,12 +179,6 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
        unsigned short v;
 
        if (blank_mode) {
-#ifdef MACH_HP600
-               sh_dac_disable(DAC_LCD_BRIGHTNESS);
-               v = fb_readw(HD64461_GPBDR);
-               v |= HD64461_GPBDR_LCDOFF;
-               fb_writew(v, HD64461_GPBDR);
-#endif
                v = fb_readw(HD64461_LDR1);
                v &= ~HD64461_LDR1_DON;
                fb_writew(v, HD64461_LDR1);
@@ -213,19 +194,18 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
                v = fb_readw(HD64461_STBCR);
                v &= ~HD64461_STBCR_SLCDST;
                fb_writew(v, HD64461_STBCR);
-#ifdef MACH_HP600
-               sh_dac_enable(DAC_LCD_BRIGHTNESS);
-               v = fb_readw(HD64461_GPBDR);
-               v &= ~HD64461_GPBDR_LCDOFF;
-               fb_writew(v, HD64461_GPBDR);
-#endif
-               v = fb_readw(HD64461_LDR1);
-               v |= HD64461_LDR1_DON;
-               fb_writew(v, HD64461_LDR1);
 
                v = fb_readw(HD64461_LCDCCR);
-               v &= ~HD64461_LCDCCR_MOFF;
+               v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ);
                fb_writew(v, HD64461_LCDCCR);
+
+               do {
+                   v = fb_readw(HD64461_LCDCCR);
+               } while(v&HD64461_LCDCCR_STBACK);
+
+               v = fb_readw(HD64461_LDR1);
+               v |= HD64461_LDR1_DON;
+               fb_writew(v, HD64461_LDR1);
        }
        return 0;
 }
@@ -233,7 +213,7 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
 static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                           unsigned blue, unsigned transp, struct fb_info *info)
 {
-       if (regno >= info->cmap.len)
+       if (regno >= 256)
                return 1;
 
        switch (info->var.bits_per_pixel) {
@@ -244,6 +224,8 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                fb_writew(blue >> 10, HD64461_CPTWDR);
                break;
        case 16:
+               if (regno >= 16)
+                       return 1;
                ((u32 *) (info->pseudo_palette))[regno] =
                    ((red & 0xf800)) |
                    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
@@ -252,26 +234,113 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
        return 0;
 }
 
+static int hitfb_sync(struct fb_info *info)
+{
+       hitfb_accel_wait();
+
+       return 0;
+}
+
+static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       int maxy;
+
+       var->xres = info->var.xres;
+       var->xres_virtual = info->var.xres;
+       var->yres = info->var.yres;
+
+       if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16))
+               var->bits_per_pixel = info->var.bits_per_pixel;
+
+       if (var->yres_virtual < var->yres)
+               var->yres_virtual = var->yres;
+
+       maxy = info->fix.smem_len / var->xres;
+
+       if (var->bits_per_pixel == 16)
+               maxy /= 2;
+
+       if (var->yres_virtual > maxy)
+               var->yres_virtual = maxy;
+
+       var->xoffset = 0;
+       var->yoffset = 0;
+
+       switch (var->bits_per_pixel) {
+       case 8:
+               var->red.offset = 0;
+               var->red.length = 8;
+               var->green.offset = 0;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       case 16:                /* RGB 565 */
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       }
+
+       return 0;
+}
+
+static int hitfb_set_par(struct fb_info *info)
+{
+       unsigned short ldr3;
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               info->fix.line_length = info->var.xres;
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               info->fix.ypanstep = 16;
+               break;
+       case 16:
+               info->fix.line_length = info->var.xres*2;
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               info->fix.ypanstep = 8;
+               break;
+       }
+
+       fb_writew(info->fix.line_length, HD64461_LCDCLOR);
+       ldr3 = fb_readw(HD64461_LDR3);
+       ldr3 &= ~15;
+       ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8;
+       fb_writew(ldr3, HD64461_LDR3);
+       return 0;
+}
+
 static struct fb_ops hitfb_ops = {
        .owner          = THIS_MODULE,
+       .fb_check_var   = hitfb_check_var,
+       .fb_set_par             = hitfb_set_par,
        .fb_setcolreg   = hitfb_setcolreg,
        .fb_blank       = hitfb_blank,
+       .fb_sync        = hitfb_sync,
        .fb_pan_display = hitfb_pan_display,
        .fb_fillrect    = hitfb_fillrect,
        .fb_copyarea    = hitfb_copyarea,
        .fb_imageblit   = cfb_imageblit,
 };
 
-int __init hitfb_init(void)
+static int __init hitfb_probe(struct platform_device *dev)
 {
        unsigned short lcdclor, ldr3, ldvndr;
-       int size;
 
        if (fb_get_options("hitfb", NULL))
                return -ENODEV;
 
+       hitfb_fix.mmio_start = CONFIG_HD64461_IOBASE+0x1000;
+       hitfb_fix.mmio_len = 0x1000;
        hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
-       hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024;
+       hitfb_fix.smem_len = 512 * 1024;
 
        lcdclor = fb_readw(HD64461_LCDCLOR);
        ldvndr = fb_readw(HD64461_LDVNDR);
@@ -321,12 +390,12 @@ int __init hitfb_init(void)
        fb_info.var = hitfb_var;
        fb_info.fix = hitfb_fix;
        fb_info.pseudo_palette = pseudo_palette;
-       fb_info.flags = FBINFO_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+               FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
 
        fb_info.screen_base = (void *)hitfb_fix.smem_start;
 
-       size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16;
-       fb_alloc_cmap(&fb_info.cmap, size, 0);
+       fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
        if (register_framebuffer(&fb_info) < 0)
                return -EINVAL;
@@ -336,9 +405,75 @@ int __init hitfb_init(void)
        return 0;
 }
 
+static int __devexit hitfb_remove(struct platform_device *dev)
+{
+       return unregister_framebuffer(&fb_info);
+}
+
+#ifdef CONFIG_PM
+static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
+{
+       u16 v;
+
+       hitfb_blank(1,0);
+       v = fb_readw(HD64461_STBCR);
+       v |= HD64461_STBCR_SLCKE_IST;
+       fb_writew(v, HD64461_STBCR);
+
+       return 0;
+}
+
+static int hitfb_resume(struct platform_device *dev)
+{
+       u16 v;
+
+       v = fb_readw(HD64461_STBCR);
+       v &= ~HD64461_STBCR_SLCKE_OST;
+       msleep(100);
+       v = fb_readw(HD64461_STBCR);
+       v &= ~HD64461_STBCR_SLCKE_IST;
+       fb_writew(v, HD64461_STBCR);
+       hitfb_blank(0,0);
+
+       return 0;
+}
+#endif
+
+static struct platform_driver hitfb_driver = {
+       .probe          = hitfb_probe,
+       .remove         = __devexit_p(hitfb_remove),
+#ifdef CONFIG_PM
+       .suspend        = hitfb_suspend,
+       .resume         = hitfb_resume,
+#endif
+       .driver         = {
+               .name   = "hitfb",
+       },
+};
+
+static struct platform_device hitfb_device = {
+       .name   = "hitfb",
+       .id     = -1,
+};
+
+static int __init hitfb_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&hitfb_driver);
+       if (!ret) {
+               ret = platform_device_register(&hitfb_device);
+               if (ret)
+                       platform_driver_unregister(&hitfb_driver);
+       }
+       return ret;
+}
+
+
 static void __exit hitfb_exit(void)
 {
-       unregister_framebuffer(&fb_info);
+       platform_device_unregister(&hitfb_device);
+       platform_driver_unregister(&hitfb_driver);
 }
 
 module_init(hitfb_init);
index c1f7b49975dd1a8bb78fd1817ddfd33cd3e5018a..7d06b38e80a00f7e4f5d7ead2062a46da7e5730d 100644 (file)
@@ -98,7 +98,6 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
        chan->algo.getsda               = i810i2c_getsda;
        chan->algo.getscl               = i810i2c_getscl;
        chan->algo.udelay               = 10;
-       chan->algo.mdelay               = 10;
         chan->algo.timeout              = (HZ/2);
         chan->algo.data                 = chan;
 
index 722d21d6e5cd3a7d00f60bafebb9c04ae9a18852..6c782d3ae1bede62c0bc8a7c93526c144d102600 100644 (file)
@@ -1,6 +1,8 @@
 obj-$(CONFIG_FB_INTEL) += intelfb.o
 
-intelfb-objs := intelfbdrv.o intelfbhw.o
+intelfb-y := intelfbdrv.o intelfbhw.o
+intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
+intelfb-objs := $(intelfb-y)
 
 ifdef CONFIG_FB_INTEL_DEBUG
 #EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
index e290d7460e1bee1840487b5cc84194e9fa1db51e..80b94c19a9fac5ea30f373654fb8a78b0d83740b 100644 (file)
@@ -6,6 +6,10 @@
 #include <linux/agp_backend.h>
 #include <linux/fb.h>
 
+#ifdef CONFIG_FB_INTEL_I2C
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#endif
 
 /*** Version/name ***/
 #define INTELFB_VERSION                        "0.9.4"
 /* Intel agpgart driver */
 #define AGP_PHYSICAL_MEMORY     2
 
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_OUTPUTS 6
+
+/* these are outputs from the chip - integrated only
+   external chips are via DVO or SDVO output */
+#define INTELFB_OUTPUT_UNUSED 0
+#define INTELFB_OUTPUT_ANALOG 1
+#define INTELFB_OUTPUT_DVO 2
+#define INTELFB_OUTPUT_SDVO 3
+#define INTELFB_OUTPUT_LVDS 4
+#define INTELFB_OUTPUT_TVOUT 5
+
+#define INTELFB_DVO_CHIP_NONE 0
+#define INTELFB_DVO_CHIP_LVDS 1
+#define INTELFB_DVO_CHIP_TMDS 2
+#define INTELFB_DVO_CHIP_TVOUT 4
+
+#define INTELFB_OUTPUT_PIPE_NC  0
+#define INTELFB_OUTPUT_PIPE_A   1
+#define INTELFB_OUTPUT_PIPE_B   2
+
 /*** Data Types ***/
 
 /* supported chipsets */
@@ -195,6 +222,10 @@ struct intelfb_hwstate {
        u32 mem_mode;
        u32 fw_blc_0;
        u32 fw_blc_1;
+       u16 hwstam;
+       u16 ier;
+       u16 iir;
+       u16 imr;
 };
 
 struct intelfb_heap_data {
@@ -204,6 +235,33 @@ struct intelfb_heap_data {
        u32 size;    // in bytes
 };
 
+#ifdef CONFIG_FB_INTEL_I2C
+struct intelfb_i2c_chan {
+    struct intelfb_info *dinfo;
+    u32 reg;
+    struct i2c_adapter adapter;
+    struct i2c_algo_bit_data algo;
+};
+#endif
+
+struct intelfb_output_rec {
+    int type;
+    int pipe;
+    int flags;
+
+#ifdef CONFIG_FB_INTEL_I2C
+    struct intelfb_i2c_chan i2c_bus;
+    struct intelfb_i2c_chan ddc_bus;
+#endif
+};
+
+struct intelfb_vsync {
+       wait_queue_head_t wait;
+       unsigned int count;
+       int pan_display;
+       u32 pan_offset;
+};
+
 struct intelfb_info {
        struct fb_info *info;
        struct fb_ops  *fbops;
@@ -220,7 +278,7 @@ struct intelfb_info {
        u8 fbmem_gart;
 
        /* mtrr support */
-       u32 mtrr_reg;
+       int mtrr_reg;
        u32 has_mtrr;
 
        /* heap data */
@@ -267,6 +325,12 @@ struct intelfb_info {
        int fixed_mode;
        int ring_active;
        int flag;
+       unsigned long irq_flags;
+       int open;
+
+       /* vsync */
+       struct intelfb_vsync vsync;
+       spinlock_t int_lock;
 
        /* hw cursor */
        int cursor_on;
@@ -285,12 +349,25 @@ struct intelfb_info {
        
        /* index into plls */
        int pll_index;
+
+       /* outputs */
+       int num_outputs;
+       struct intelfb_output_rec output[MAX_OUTPUTS];
 };
 
 #define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM))
 
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC      _IOW('F', 0x20, __u32)
+#endif
+
 /*** function prototypes ***/
 
 extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
 
+#ifdef CONFIG_FB_INTEL_I2C
+extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo);
+extern void intelfb_delete_i2c_busses(struct intelfb_info *dinfo);
+#endif
+
 #endif /* _INTELFB_H */
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
new file mode 100644 (file)
index 0000000..c1113d6
--- /dev/null
@@ -0,0 +1,200 @@
+/**************************************************************************
+
+ Copyright 2006 Dave Airlie <airlied@linux.ie>
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+#include "intelfb.h"
+#include "intelfbhw.h"
+
+/* bit locations in the registers */
+#define SCL_DIR_MASK           0x0001
+#define SCL_DIR                        0x0002
+#define SCL_VAL_MASK           0x0004
+#define SCL_VAL_OUT            0x0008
+#define SCL_VAL_IN             0x0010
+#define SDA_DIR_MASK           0x0100
+#define SDA_DIR                        0x0200
+#define SDA_VAL_MASK           0x0400
+#define SDA_VAL_OUT            0x0800
+#define SDA_VAL_IN             0x1000
+
+static void intelfb_gpio_setscl(void *data, int state)
+{
+       struct intelfb_i2c_chan *chan = data;
+       struct intelfb_info *dinfo = chan->dinfo;
+       u32 val;
+
+       OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
+       val = INREG(chan->reg);
+}
+
+static void intelfb_gpio_setsda(void *data, int state)
+{
+       struct intelfb_i2c_chan *chan = data;
+       struct intelfb_info *dinfo = chan->dinfo;
+       u32 val;
+
+       OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
+       val = INREG(chan->reg);
+}
+
+static int intelfb_gpio_getscl(void *data)
+{
+       struct intelfb_i2c_chan *chan = data;
+       struct intelfb_info *dinfo = chan->dinfo;
+       u32 val;
+
+       OUTREG(chan->reg, SCL_DIR_MASK);
+       OUTREG(chan->reg, 0);
+       val = INREG(chan->reg);
+       return ((val & SCL_VAL_IN) != 0);
+}
+
+static int intelfb_gpio_getsda(void *data)
+{
+       struct intelfb_i2c_chan *chan = data;
+       struct intelfb_info *dinfo = chan->dinfo;
+       u32 val;
+
+       OUTREG(chan->reg, SDA_DIR_MASK);
+       OUTREG(chan->reg, 0);
+       val = INREG(chan->reg);
+       return ((val & SDA_VAL_IN) != 0);
+}
+
+static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
+                                                                struct intelfb_i2c_chan *chan,
+                                                                const u32 reg, const char *name)
+{
+       int rc;
+
+       chan->dinfo                                     = dinfo;
+       chan->reg                                       = reg;
+       snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name);
+       chan->adapter.owner                     = THIS_MODULE;
+       chan->adapter.id                        = I2C_HW_B_INTELFB;
+       chan->adapter.algo_data         = &chan->algo;
+       chan->adapter.dev.parent        = &chan->dinfo->pdev->dev;
+       chan->algo.setsda                       = intelfb_gpio_setsda;
+       chan->algo.setscl                       = intelfb_gpio_setscl;
+       chan->algo.getsda                       = intelfb_gpio_getsda;
+       chan->algo.getscl                       = intelfb_gpio_getscl;
+       chan->algo.udelay                       = 40;
+       chan->algo.timeout                      = 20;
+       chan->algo.data                         = chan;
+
+       i2c_set_adapdata(&chan->adapter, chan);
+
+       /* Raise SCL and SDA */
+       intelfb_gpio_setsda(chan, 1);
+       intelfb_gpio_setscl(chan, 1);
+       udelay(20);
+
+       rc = i2c_bit_add_bus(&chan->adapter);
+       if (rc == 0)
+               DBG_MSG("I2C bus %s registered.\n", name);
+       else
+               WRN_MSG("Failed to register I2C bus %s.\n", name);
+       return rc;
+}
+
+void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
+{
+       int i = 0;
+
+       /* everyone has at least a single analog output */
+       dinfo->num_outputs = 1;
+       dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
+
+       /* setup the DDC bus for analog output */
+       intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, "CRTDDC_A");
+       i++;
+
+    /* need to add the output busses for each device
+       - this function is very incomplete
+       - i915GM has LVDS and TVOUT for example
+    */
+    switch(dinfo->chipset) {
+       case INTEL_830M:
+       case INTEL_845G:
+       case INTEL_855GM:
+       case INTEL_865G:
+               dinfo->output[i].type = INTELFB_OUTPUT_DVO;
+               intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOD, "DVODDC_D");
+               intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "DVOI2C_E");
+               i++;
+               break;
+       case INTEL_915G:
+       case INTEL_915GM:
+               /* has  some LVDS + tv-out */
+       case INTEL_945G:
+       case INTEL_945GM:
+               /* SDVO ports have a single control bus - 2 devices */
+               dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
+               intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "SDVOCTRL_E");
+               /* TODO: initialize the SDVO */
+//             I830SDVOInit(pScrn, i, DVOB);
+               i++;
+
+               /* set up SDVOC */
+               dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
+               dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
+               /* TODO: initialize the SDVO */
+//             I830SDVOInit(pScrn, i, DVOC);
+               i++;
+               break;
+       }
+       dinfo->num_outputs = i;
+}
+
+void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
+{
+       int i;
+
+       for (i = 0; i < MAX_OUTPUTS; i++) {
+               if (dinfo->output[i].i2c_bus.dinfo) {
+                       i2c_bit_del_bus(&dinfo->output[i].i2c_bus.adapter);
+                       dinfo->output[i].i2c_bus.dinfo = NULL;
+               }
+               if (dinfo->output[i].ddc_bus.dinfo) {
+                       i2c_bit_del_bus(&dinfo->output[i].ddc_bus.adapter);
+                       dinfo->output[i].ddc_bus.dinfo = NULL;
+               }
+       }
+}
index 06af89d44a0ddc90e06ab7db005de0843d96014a..6f9de04193d216d62f62511f7bbb0cd821d3c0df 100644 (file)
 static void __devinit get_initial_mode(struct intelfb_info *dinfo);
 static void update_dinfo(struct intelfb_info *dinfo,
                         struct fb_var_screeninfo *var);
+static int intelfb_open(struct fb_info *info, int user);
+static int intelfb_release(struct fb_info *info, int user);
 static int intelfb_check_var(struct fb_var_screeninfo *var,
                             struct fb_info *info);
 static int intelfb_set_par(struct fb_info *info);
@@ -194,6 +196,8 @@ static int num_registered = 0;
 /* fb ops */
 static struct fb_ops intel_fb_ops = {
        .owner =                THIS_MODULE,
+       .fb_open =              intelfb_open,
+       .fb_release =           intelfb_release,
        .fb_check_var =         intelfb_check_var,
        .fb_set_par =           intelfb_set_par,
        .fb_setcolreg =         intelfb_setcolreg,
@@ -446,6 +450,8 @@ cleanup(struct intelfb_info *dinfo)
        if (!dinfo)
                return;
 
+       intelfbhw_disable_irq(dinfo);
+
        fb_dealloc_cmap(&dinfo->info->cmap);
        kfree(dinfo->info->pixmap.addr);
 
@@ -467,6 +473,11 @@ cleanup(struct intelfb_info *dinfo)
                agp_free_memory(dinfo->gtt_ring_mem);
        }
 
+#ifdef CONFIG_FB_INTEL_I2C
+       /* un-register I2C bus */
+       intelfb_delete_i2c_busses(dinfo);
+#endif
+
        if (dinfo->mmio_base)
                iounmap((void __iomem *)dinfo->mmio_base);
        if (dinfo->aperture.virtual)
@@ -844,6 +855,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (bailearly == 5)
                bailout(dinfo);
 
+#ifdef CONFIG_FB_INTEL_I2C
+       /* register I2C bus */
+       intelfb_create_i2c_busses(dinfo);
+#endif
+
        if (bailearly == 6)
                bailout(dinfo);
 
@@ -888,6 +904,13 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        dinfo->registered = 1;
+       dinfo->open = 0;
+
+       init_waitqueue_head(&dinfo->vsync.wait);
+       spin_lock_init(&dinfo->int_lock);
+       dinfo->irq_flags = 0;
+       dinfo->vsync.pan_display = 0;
+       dinfo->vsync.pan_offset = 0;
 
        return 0;
 
@@ -1187,6 +1210,34 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
  *                       fbdev interface                       *
  ***************************************************************/
 
+static int
+intelfb_open(struct fb_info *info, int user)
+{
+       struct intelfb_info *dinfo = GET_DINFO(info);
+
+       if (user) {
+               dinfo->open++;
+       }
+
+       return 0;
+}
+
+static int
+intelfb_release(struct fb_info *info, int user)
+{
+       struct intelfb_info *dinfo = GET_DINFO(info);
+
+       if (user) {
+               dinfo->open--;
+               msleep(1);
+               if (!dinfo->open) {
+                       intelfbhw_disable_irq(dinfo);
+               }
+       }
+
+       return 0;
+}
+
 static int
 intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
@@ -1433,6 +1484,19 @@ static int
 intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
        int retval = 0;
+       struct intelfb_info *dinfo = GET_DINFO(info);
+       u32 pipe = 0;
+
+       switch (cmd) {
+               case FBIO_WAITFORVSYNC:
+                       if (get_user(pipe, (__u32 __user *)arg))
+                               return -EFAULT;
+
+                       retval = intelfbhw_wait_for_vsync(dinfo, pipe);
+                       break;
+               default:
+                       break;
+       }
 
        return retval;
 }
index 2a9322f9cfdc3f220c35afac745f648b8f8c764f..f887f1efd3fef1676201321665651c147668fda7 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
+#include <linux/interrupt.h>
 
 #include <asm/io.h>
 
@@ -368,7 +369,13 @@ intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 
        offset += dinfo->fb.offset << 12;
 
-       OUTREG(DSPABASE, offset);
+       dinfo->vsync.pan_offset = offset;
+       if ((var->activate & FB_ACTIVATE_VBL) && !intelfbhw_enable_irq(dinfo, 0)) {
+               dinfo->vsync.pan_display = 1;
+       } else {
+               dinfo->vsync.pan_display = 0;
+               OUTREG(DSPABASE, offset);
+       }
 
        return 0;
 }
@@ -585,6 +592,11 @@ intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
        hw->fw_blc_0 = INREG(FW_BLC_0);
        hw->fw_blc_1 = INREG(FW_BLC_1);
 
+       hw->hwstam = INREG16(HWSTAM);
+       hw->ier = INREG16(IER);
+       hw->iir = INREG16(IIR);
+       hw->imr = INREG16(IMR);
+
        return 0;
 }
 
@@ -613,6 +625,7 @@ static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvd
        return vco / p;
 }
 
+#if REGDUMP
 static void
 intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
 {
@@ -638,6 +651,7 @@ intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
        *o_p1 = p1;
        *o_p2 = p2;
 }
+#endif
 
 
 void
@@ -794,6 +808,10 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
        printk("        FW_BLC_0                0x%08x\n", hw->fw_blc_0);
        printk("        FW_BLC_1                0x%08x\n", hw->fw_blc_1);
 
+       printk("        HWSTAM                  0x%04x\n", hw->hwstam);
+       printk("        IER                     0x%04x\n", hw->ier);
+       printk("        IIR                     0x%04x\n", hw->iir);
+       printk("        IMR                     0x%04x\n", hw->imr);
        printk("hw state dump end\n");
 #endif
 }
@@ -1932,3 +1950,119 @@ intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
                addr += 16;
        }
 }
+
+static irqreturn_t
+intelfbhw_irq(int irq, void *dev_id, struct pt_regs *fp) {
+       int handled = 0;
+       u16 tmp;
+       struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;
+
+       spin_lock(&dinfo->int_lock);
+
+       tmp = INREG16(IIR);
+       tmp &= VSYNC_PIPE_A_INTERRUPT;
+
+       if (tmp == 0) {
+               spin_unlock(&dinfo->int_lock);
+               return IRQ_RETVAL(handled);
+       }
+
+       OUTREG16(IIR, tmp);
+
+       if (tmp & VSYNC_PIPE_A_INTERRUPT) {
+               dinfo->vsync.count++;
+               if (dinfo->vsync.pan_display) {
+                       dinfo->vsync.pan_display = 0;
+                       OUTREG(DSPABASE, dinfo->vsync.pan_offset);
+               }
+               wake_up_interruptible(&dinfo->vsync.wait);
+               handled = 1;
+       }
+
+       spin_unlock(&dinfo->int_lock);
+
+       return IRQ_RETVAL(handled);
+}
+
+int
+intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) {
+
+       if (!test_and_set_bit(0, &dinfo->irq_flags)) {
+               if (request_irq(dinfo->pdev->irq, intelfbhw_irq, SA_SHIRQ, "intelfb", dinfo)) {
+                       clear_bit(0, &dinfo->irq_flags);
+                       return -EINVAL;
+               }
+
+               spin_lock_irq(&dinfo->int_lock);
+               OUTREG16(HWSTAM, 0xfffe);
+               OUTREG16(IMR, 0x0);
+               OUTREG16(IER, VSYNC_PIPE_A_INTERRUPT);
+               spin_unlock_irq(&dinfo->int_lock);
+       } else if (reenable) {
+               u16 ier;
+
+               spin_lock_irq(&dinfo->int_lock);
+               ier = INREG16(IER);
+               if ((ier & VSYNC_PIPE_A_INTERRUPT)) {
+                       DBG_MSG("someone disabled the IRQ [%08X]\n", ier);
+                       OUTREG(IER, VSYNC_PIPE_A_INTERRUPT);
+               }
+               spin_unlock_irq(&dinfo->int_lock);
+       }
+       return 0;
+}
+
+void
+intelfbhw_disable_irq(struct intelfb_info *dinfo) {
+       u16 tmp;
+
+       if (test_and_clear_bit(0, &dinfo->irq_flags)) {
+               if (dinfo->vsync.pan_display) {
+                       dinfo->vsync.pan_display = 0;
+                       OUTREG(DSPABASE, dinfo->vsync.pan_offset);
+               }
+               spin_lock_irq(&dinfo->int_lock);
+               OUTREG16(HWSTAM, 0xffff);
+               OUTREG16(IMR, 0xffff);
+               OUTREG16(IER, 0x0);
+
+               tmp = INREG16(IIR);
+               OUTREG16(IIR, tmp);
+               spin_unlock_irq(&dinfo->int_lock);
+
+               free_irq(dinfo->pdev->irq, dinfo);
+       }
+}
+
+int
+intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe) {
+       struct intelfb_vsync *vsync;
+       unsigned int count;
+       int ret;
+
+       switch (pipe) {
+               case 0:
+                       vsync = &dinfo->vsync;
+                       break;
+               default:
+                       return -ENODEV;
+       }
+
+       ret = intelfbhw_enable_irq(dinfo, 0);
+       if (ret) {
+               return ret;
+       }
+
+       count = vsync->count;
+       ret = wait_event_interruptible_timeout(vsync->wait, count != vsync->count, HZ/10);
+       if (ret < 0) {
+               return ret;
+       }
+       if (ret == 0) {
+               intelfbhw_enable_irq(dinfo, 1);
+               DBG_MSG("wait_for_vsync timed out!\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
index 10acda098b71e5c5685c739d105f2c12d90598c4..8c54ba8fbdda2e0bd240f00e87d289d17430cbb9 100644 (file)
 #define INSTDONE               0x2090
 #define PRI_RING_EMPTY                 1
 
+#define HWSTAM                 0x2098
+#define IER                    0x20A0
+#define IIR                    0x20A4
+#define IMR                    0x20A8
+#define VSYNC_PIPE_A_INTERRUPT         (1 << 7)
+#define PIPE_A_EVENT_INTERRUPT         (1 << 4)
+#define VSYNC_PIPE_B_INTERRUPT         (1 << 5)
+#define PIPE_B_EVENT_INTERRUPT         (1 << 4)
+#define HOST_PORT_EVENT_INTERRUPT      (1 << 3)
+#define CAPTURE_EVENT_INTERRUPT                (1 << 2)
+#define USER_DEFINED_INTERRUPT         (1 << 1)
+#define BREAKPOINT_INTERRUPT           1
+
 #define INSTPM                 0x20c0
 #define SYNC_FLUSH_ENABLE              (1 << 5)
 
 #define FW_DISPC_BL_SHIFT              8
 #define FW_DISPC_BL_MASK               0x7
 
+#define GPIOA             0x5010
+#define GPIOB             0x5014
+#define GPIOC             0x5018 // this may be external DDC on i830
+#define GPIOD             0x501C // this is DVO DDC
+#define GPIOE             0x5020 // this is DVO i2C
+#define GPIOF             0x5024
 
 /* PLL registers */
 #define VGA0_DIVISOR           0x06000
 
 /* I/O macros */
 #define INREG8(addr)         readb((u8 __iomem *)(dinfo->mmio_base + (addr)))
+#define INREG16(addr)        readw((u16 __iomem *)(dinfo->mmio_base + (addr)))
 #define INREG(addr)          readl((u32 __iomem *)(dinfo->mmio_base + (addr)))
 #define OUTREG8(addr, val)    writeb((val),(u8 __iomem *)(dinfo->mmio_base + \
                                                           (addr)))
+#define OUTREG16(addr, val)    writew((val),(u16 __iomem *)(dinfo->mmio_base + \
+                                                          (addr)))
 #define OUTREG(addr, val)     writel((val),(u32 __iomem *)(dinfo->mmio_base + \
                                      (addr)))
 
@@ -545,5 +567,8 @@ extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
 extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
                                  int height, u8 *data);
 extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
+extern int intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable);
+extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
+extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
 
 #endif /* _INTELFBHW_H */
index 57abbae5520f1d8cddb8fd93255c7eb7e706b23a..795c1a99a680b9f64d3ff84023b811291930b9bc 100644 (file)
@@ -95,12 +95,12 @@ static struct i2c_adapter matrox_i2c_adapter_template =
 
 static struct i2c_algo_bit_data matrox_i2c_algo_template =
 {
-       NULL,
-       matroxfb_gpio_setsda,
-       matroxfb_gpio_setscl,
-       matroxfb_gpio_getsda,
-       matroxfb_gpio_getscl,
-       10, 10, 100,
+       .setsda         = matroxfb_gpio_setsda,
+       .setscl         = matroxfb_gpio_setscl,
+       .getsda         = matroxfb_gpio_getsda,
+       .getscl         = matroxfb_gpio_getscl,
+       .udelay         = 10,
+       .timeout        = 100,
 };
 
 static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
index 940ba2be55e9eddc0abd875320bfcc25ee5bdeb3..78dc59a1751bfcf43a9f96952959d09b20643070 100644 (file)
@@ -187,7 +187,7 @@ static short do_blank = 0;          /* (Un)Blank the screen */
 static unsigned int is_blanked = 0;            /* Is the screen blanked? */
 
 #ifdef CONFIG_SH_STORE_QUEUES
-static struct sq_mapping *pvr2fb_map;
+static unsigned long pvr2fb_map;
 #endif
 
 #ifdef CONFIG_SH_DMA
@@ -213,15 +213,17 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
 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,
                            size_t count, loff_t *ppos);
+#endif
 
 static struct fb_ops pvr2fb_ops = {
-       .owner          = THIS_MODULE,
-       .fb_setcolreg   = pvr2fb_setcolreg,
-       .fb_blank       = pvr2fb_blank,
-       .fb_check_var   = pvr2fb_check_var,
-       .fb_set_par     = pvr2fb_set_par,
+       .owner          = THIS_MODULE,
+       .fb_setcolreg   = pvr2fb_setcolreg,
+       .fb_blank       = pvr2fb_blank,
+       .fb_check_var   = pvr2fb_check_var,
+       .fb_set_par     = pvr2fb_set_par,
 #ifdef CONFIG_SH_DMA
        .fb_write       = pvr2fb_write,
 #endif
@@ -783,7 +785,7 @@ static int __init pvr2fb_common_init(void)
                goto out_err;
        }
 
-       fb_memset((unsigned long)fb_info->screen_base, 0, pvr2_fix.smem_len);
+       fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len);
 
        pvr2_fix.ypanstep       = nopan  ? 0 : 1;
        pvr2_fix.ywrapstep      = nowrap ? 0 : 1;
@@ -820,7 +822,7 @@ static int __init pvr2fb_common_init(void)
               modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10));
        printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", 
               fb_info->node, fb_info->var.xres, fb_info->var.yres,
-              fb_info->var.bits_per_pixel, 
+              fb_info->var.bits_per_pixel,
               get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
               (char *)pvr2_get_param(cables, NULL, cable_type, 3),
               (char *)pvr2_get_param(outputs, NULL, video_output, 3));
@@ -829,10 +831,10 @@ static int __init pvr2fb_common_init(void)
        printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node);
 
        pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
-                             fb_info->fix.id);
+                             fb_info->fix.id, pgprot_val(PAGE_SHARED));
 
        printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n",
-              fb_info->node, pvr2fb_map->sq_addr);
+              fb_info->node, pvr2fb_map);
 #endif
 
        return 0;
index e83befd16d634328ddb6029df79aaa3330f1a5a1..d7d810dbf0bdb6b1db553b35529eb99a651a2a25 100644 (file)
@@ -148,7 +148,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
                chan->adapter.algo_data         = &chan->algo;
                chan->adapter.dev.parent        = &chan->par->pcidev->dev;
                chan->algo.udelay               = 40;
-               chan->algo.mdelay               = 5;
                chan->algo.timeout              = 20;
                chan->algo.data                 = chan;
 
index 22f7ccd58d38725f7c23f5064c3ace5047aba97f..0f628041e3f7660c75fb846985b4124ba571cffe 100644 (file)
@@ -460,8 +460,10 @@ static int __init init_v9fs(void)
 
        ret = v9fs_mux_global_init();
        if (!ret)
-               ret = register_filesystem(&v9fs_fs_type);
-
+               return ret;
+       ret = register_filesystem(&v9fs_fs_type);
+       if (!ret)
+               v9fs_mux_global_exit();
        return ret;
 }
 
index eae50c9d6dc41f0ca06524357008775a59d74fe1..5241c600ce28be2f00f0eb454b41db882beab1a8 100644 (file)
@@ -204,7 +204,6 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = sb->s_blocksize;
                inode->i_blocks = 0;
                inode->i_rdev = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -234,7 +233,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
                        inode->i_op = &v9fs_symlink_inode_operations;
                        break;
                case S_IFDIR:
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        if(v9ses->extended)
                                inode->i_op = &v9fs_dir_inode_operations_ext;
                        else
@@ -950,9 +949,8 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
 
        inode->i_size = stat->length;
 
-       inode->i_blksize = sb->s_blocksize;
        inode->i_blocks =
-           (inode->i_size + inode->i_blksize - 1) >> sb->s_blocksize_bits;
+           (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 }
 
 /**
index a27002668bd36a7abb3074bfa41036ae16580b73..1453d2d164f7c2d5a94e5da75d41dbba9d94a66e 100644 (file)
@@ -4,6 +4,8 @@
 
 menu "File systems"
 
+if BLOCK
+
 config EXT2_FS
        tristate "Second extended fs support"
        help
@@ -399,6 +401,8 @@ config ROMFS_FS
          If you don't know whether you need it, then you don't need it:
          answer N.
 
+endif
+
 config INOTIFY
        bool "Inotify file change notification support"
        default y
@@ -530,6 +534,7 @@ config FUSE_FS
          If you want to develop a userspace FS, or if you want to use
          a filesystem based on FUSE, answer Y or M.
 
+if BLOCK
 menu "CD-ROM/DVD Filesystems"
 
 config ISO9660_FS
@@ -597,7 +602,9 @@ config UDF_NLS
        depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y)
 
 endmenu
+endif
 
+if BLOCK
 menu "DOS/FAT/NT Filesystems"
 
 config FAT_FS
@@ -782,6 +789,7 @@ config NTFS_RW
          It is perfectly safe to say N here.
 
 endmenu
+endif
 
 menu "Pseudo filesystems"
 
@@ -826,6 +834,25 @@ config PROC_VMCORE
         help
         Exports the dump image of crashed kernel in ELF format.
 
+config PROC_SYSCTL
+       bool "Sysctl support (/proc/sys)" if EMBEDDED
+       depends on PROC_FS
+       select SYSCTL
+       default y
+       ---help---
+         The sysctl interface provides a means of dynamically changing
+         certain kernel parameters and variables on the fly without requiring
+         a recompile of the kernel or reboot of the system.  The primary
+         interface is through /proc/sys.  If you say Y here a tree of
+         modifiable sysctl entries will be generated beneath the
+          /proc/sys directory. They are explained in the files
+         in <file:Documentation/sysctl/>.  Note that enabling this
+         option will enlarge the kernel by at least 8 KB.
+
+         As it is generally a good thing, you should say Y here unless
+         building a kernel for install/rescue disks or your system is very
+         limited in memory.
+
 config SYSFS
        bool "sysfs file system support" if EMBEDDED
        default y
@@ -862,6 +889,19 @@ config TMPFS
 
          See <file:Documentation/filesystems/tmpfs.txt> for details.
 
+config TMPFS_POSIX_ACL
+       bool "Tmpfs POSIX Access Control Lists"
+       depends on TMPFS
+       select GENERIC_ACL
+       help
+         POSIX Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
+
+         To learn more about Access Control Lists, visit the POSIX ACLs for
+         Linux website <http://acl.bestbits.at/>.
+
+         If you don't know what Access Control Lists are, say N.
+
 config HUGETLBFS
        bool "HugeTLB file system support"
        depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
@@ -907,7 +947,7 @@ menu "Miscellaneous filesystems"
 
 config ADFS_FS
        tristate "ADFS file system support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on BLOCK && EXPERIMENTAL
        help
          The Acorn Disc Filing System is the standard file system of the
          RiscOS operating system which runs on Acorn's ARM-based Risc PC
@@ -935,7 +975,7 @@ config ADFS_FS_RW
 
 config AFFS_FS
        tristate "Amiga FFS file system support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on BLOCK && EXPERIMENTAL
        help
          The Fast File System (FFS) is the common file system used on hard
          disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20).  Say Y
@@ -957,7 +997,7 @@ config AFFS_FS
 
 config HFS_FS
        tristate "Apple Macintosh file system support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on BLOCK && EXPERIMENTAL
        select NLS
        help
          If you say Y here, you will be able to mount Macintosh-formatted
@@ -970,6 +1010,7 @@ config HFS_FS
 
 config HFSPLUS_FS
        tristate "Apple Extended HFS file system support"
+       depends on BLOCK
        select NLS
        select NLS_UTF8
        help
@@ -983,7 +1024,7 @@ config HFSPLUS_FS
 
 config BEFS_FS
        tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on BLOCK && EXPERIMENTAL
        select NLS
        help
          The BeOS File System (BeFS) is the native file system of Be, Inc's
@@ -1010,7 +1051,7 @@ config BEFS_DEBUG
 
 config BFS_FS
        tristate "BFS file system support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on BLOCK && EXPERIMENTAL
        help
          Boot File System (BFS) is a file system used under SCO UnixWare to
          allow the bootloader access to the kernel image and other important
@@ -1032,7 +1073,7 @@ config BFS_FS
 
 config EFS_FS
        tristate "EFS file system support (read only) (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on BLOCK && EXPERIMENTAL
        help
          EFS is an older file system used for non-ISO9660 CD-ROMs and hard
          disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
@@ -1047,7 +1088,7 @@ config EFS_FS
 
 config JFFS_FS
        tristate "Journalling Flash File System (JFFS) support"
-       depends on MTD
+       depends on MTD && BLOCK
        help
          JFFS is the Journaling Flash File System developed by Axis
          Communications in Sweden, aimed at providing a crash/powerdown-safe
@@ -1232,6 +1273,7 @@ endchoice
 
 config CRAMFS
        tristate "Compressed ROM file system support (cramfs)"
+       depends on BLOCK
        select ZLIB_INFLATE
        help
          Saying Y here includes support for CramFs (Compressed ROM File
@@ -1251,6 +1293,7 @@ config CRAMFS
 
 config VXFS_FS
        tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
+       depends on BLOCK
        help
          FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
          file system format.  VERITAS VxFS(TM) is the standard file system
@@ -1268,6 +1311,7 @@ config VXFS_FS
 
 config HPFS_FS
        tristate "OS/2 HPFS file system support"
+       depends on BLOCK
        help
          OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
          is the file system used for organizing files on OS/2 hard disk
@@ -1284,6 +1328,7 @@ config HPFS_FS
 
 config QNX4FS_FS
        tristate "QNX4 file system support (read only)"
+       depends on BLOCK
        help
          This is the file system used by the real-time operating systems
          QNX 4 and QNX 6 (the latter is also called QNX RTP).
@@ -1311,6 +1356,7 @@ config QNX4FS_RW
 
 config SYSV_FS
        tristate "System V/Xenix/V7/Coherent file system support"
+       depends on BLOCK
        help
          SCO, Xenix and Coherent are commercial Unix systems for Intel
          machines, and Version 7 was used on the DEC PDP-11. Saying Y
@@ -1349,6 +1395,7 @@ config SYSV_FS
 
 config UFS_FS
        tristate "UFS file system support (read only)"
+       depends on BLOCK
        help
          BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
          OpenBSD and NeXTstep) use a file system called UFS. Some System V
@@ -1921,13 +1968,19 @@ config 9P_FS
 
          If unsure, say N.
 
+config GENERIC_ACL
+       bool
+       select FS_POSIX_ACL
+
 endmenu
 
+if BLOCK
 menu "Partition Types"
 
 source "fs/partitions/Kconfig"
 
 endmenu
+endif
 
 source "fs/nls/Kconfig"
 
index 89135428a539184580b2b0305ec46f6e7d5bfa86..819b2a93bebe55cb4cc137514872892f90fa83da 100644 (file)
@@ -5,12 +5,18 @@
 # Rewritten to use lists instead of if-statements.
 # 
 
-obj-y :=       open.o read_write.o file_table.o buffer.o  bio.o super.o \
-               block_dev.o char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
+obj-y :=       open.o read_write.o file_table.o super.o \
+               char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
                ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
                attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
-               seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
-               ioprio.o pnode.o drop_caches.o splice.o sync.o
+               seq_file.o xattr.o libfs.o fs-writeback.o \
+               pnode.o drop_caches.o splice.o sync.o utimes.o
+
+ifeq ($(CONFIG_BLOCK),y)
+obj-y +=       buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
+else
+obj-y +=       no-block.o
+endif
 
 obj-$(CONFIG_INOTIFY)          += inotify.o
 obj-$(CONFIG_INOTIFY_USER)     += inotify_user.o
@@ -35,6 +41,7 @@ obj-$(CONFIG_BINFMT_FLAT)     += binfmt_flat.o
 obj-$(CONFIG_FS_MBCACHE)       += mbcache.o
 obj-$(CONFIG_FS_POSIX_ACL)     += posix_acl.o xattr_acl.o
 obj-$(CONFIG_NFS_COMMON)       += nfs_common/
+obj-$(CONFIG_GENERIC_ACL)      += generic_acl.o
 
 obj-$(CONFIG_QUOTA)            += dquot.o
 obj-$(CONFIG_QFMT_V1)          += quota_v1.o
index 1014b9f2117b2bd2e6bc00086f8bcc9d84475d0e..6101ea679cb1bf7772ba5da5342d7fb6def023ee 100644 (file)
 
 const struct file_operations adfs_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
        .mmap           = generic_file_mmap,
        .fsync          = file_fsync,
-       .write          = generic_file_write,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .sendfile       = generic_file_sendfile,
 };
 
index 534f3eecc985c7b5bfe9231bd4807db4091e388d..7e7a04be1278cf36994a0c2f934419e2ba919060 100644 (file)
@@ -269,7 +269,6 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
        inode->i_ino     = obj->file_id;
        inode->i_size    = obj->size;
        inode->i_nlink   = 2;
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks  = (inode->i_size + sb->s_blocksize - 1) >>
                            sb->s_blocksize_bits;
 
index 82011019494ccf6bbcefa838e28b5c130739470b..9ade139086fcebb7c48206a686ac06011edea40c 100644 (file)
@@ -251,8 +251,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(adfs_inode_cachep))
-               printk(KERN_INFO "adfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(adfs_inode_cachep);
 }
 
 static struct super_operations adfs_sops = {
@@ -339,11 +338,10 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_flags |= MS_NODIRATIME;
 
-       asb = kmalloc(sizeof(*asb), GFP_KERNEL);
+       asb = kzalloc(sizeof(*asb), GFP_KERNEL);
        if (!asb)
                return -ENOMEM;
        sb->s_fs_info = asb;
-       memset(asb, 0, sizeof(*asb));
 
        /* set default options */
        asb->s_uid = 0;
index 3de8590e4f6a56a35d13e09be2e8a3012df2fb54..05b5e22de759e10513301ac7b441bc4127c3b492 100644 (file)
@@ -27,8 +27,10 @@ static int affs_file_release(struct inode *inode, struct file *filp);
 
 const struct file_operations affs_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .open           = affs_file_open,
        .release        = affs_file_release,
index 17352011ab6700120d22501cc0ebce6992ba79dc..5ea72c3a16c3b52d4654d9a65223a09b6c87cbb4 100644 (file)
@@ -109,8 +109,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(affs_inode_cachep))
-               printk(KERN_INFO "affs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(affs_inode_cachep);
 }
 
 static struct super_operations affs_sops = {
@@ -280,11 +279,10 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op                = &affs_sops;
        sb->s_flags |= MS_NODIRATIME;
 
-       sbi = kmalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
        init_MUTEX(&sbi->s_bmlock);
 
        if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
index 67d6634101fdcc81e75787c87d8084f5c13256c9..2e8c42639eaa54803887b441758d6e176b4cb58b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
-#include <linux/buffer_head.h>
 #include "volume.h"
 #include "vnode.h"
 #include <rxrpc/call.h>
@@ -37,7 +36,6 @@ struct inode_operations afs_file_inode_operations = {
 
 const struct address_space_operations afs_fs_aops = {
        .readpage       = afs_file_readpage,
-       .sync_page      = block_sync_page,
        .set_page_dirty = __set_page_dirty_nobuffers,
        .releasepage    = afs_file_releasepage,
        .invalidatepage = afs_file_invalidatepage,
index 4ebb30a50ed5a876d28c7830e0083c10a1aa26f9..6f37754906c201cb49940b2efbd57b5c6b9a978f 100644 (file)
@@ -72,7 +72,6 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
        inode->i_ctime.tv_sec   = vnode->status.mtime_server;
        inode->i_ctime.tv_nsec  = 0;
        inode->i_atime          = inode->i_mtime = inode->i_ctime;
-       inode->i_blksize        = PAGE_CACHE_SIZE;
        inode->i_blocks         = 0;
        inode->i_version        = vnode->fid.unique;
        inode->i_mapping->a_ops = &afs_fs_aops;
index 101d21b6c03715b45ead510a2abccb706f23d209..86463ec9ccb496cea5907ec1de2075c982d4849d 100644 (file)
@@ -775,6 +775,7 @@ static int afs_proc_cell_servers_release(struct inode *inode,
  * first item
  */
 static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
+       __acquires(m->private->sv_lock)
 {
        struct list_head *_p;
        struct afs_cell *cell = m->private;
@@ -823,6 +824,7 @@ static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
  * clean up after reading from the cells list
  */
 static void afs_proc_cell_servers_stop(struct seq_file *p, void *v)
+       __releases(p->private->sv_lock)
 {
        struct afs_cell *cell = p->private;
 
index 331f730a1fb34435223c000ea590ecd078a0784d..782ee7c600caf0ec80c43f9c91407d1d93d6d506 100644 (file)
@@ -281,11 +281,10 @@ int afs_vlocation_lookup(struct afs_cell *cell,
        spin_unlock(&cell->vl_gylock);
 
        /* not in the cell's in-memory lists - create a new record */
-       vlocation = kmalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
+       vlocation = kzalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
        if (!vlocation)
                return -ENOMEM;
 
-       memset(vlocation, 0, sizeof(struct afs_vlocation));
        atomic_set(&vlocation->usage, 1);
        INIT_LIST_HEAD(&vlocation->link);
        rwlock_init(&vlocation->lock);
index 0ff4b86476e39288313fe3f92bd7ed1aaaedd3d3..768c6dbd323ac625277d478086a98f4585a6ae88 100644 (file)
@@ -186,11 +186,10 @@ int afs_volume_lookup(const char *name, struct afs_cell *cell, int rwpath,
        _debug("creating new volume record");
 
        ret = -ENOMEM;
-       volume = kmalloc(sizeof(struct afs_volume), GFP_KERNEL);
+       volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL);
        if (!volume)
                goto error_up;
 
-       memset(volume, 0, sizeof(struct afs_volume));
        atomic_set(&volume->usage, 1);
        volume->type            = type;
        volume->type_force      = force;
index 950630187acc72a781de4cc6ef936045be5bd0be..2e0d1505ee367c4cd7d3169c9b7a08b8fedaa930 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -15,6 +15,7 @@
 #include <linux/aio_abi.h>
 #include <linux/module.h>
 #include <linux/syscalls.h>
+#include <linux/uio.h>
 
 #define DEBUG 0
 
@@ -414,6 +415,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
        req->ki_retry = NULL;
        req->ki_dtor = NULL;
        req->private = NULL;
+       req->ki_iovec = NULL;
        INIT_LIST_HEAD(&req->ki_run_list);
 
        /* Check if the completion queue has enough free space to
@@ -459,6 +461,8 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
 
        if (req->ki_dtor)
                req->ki_dtor(req);
+       if (req->ki_iovec != &req->ki_inline_vec)
+               kfree(req->ki_iovec);
        kmem_cache_free(kiocb_cachep, req);
        ctx->reqs_active--;
 
@@ -1300,63 +1304,63 @@ asmlinkage long sys_io_destroy(aio_context_t ctx)
        return -EINVAL;
 }
 
-/*
- * aio_p{read,write} are the default  ki_retry methods for
- * IO_CMD_P{READ,WRITE}.  They maintains kiocb retry state around potentially
- * multiple calls to f_op->aio_read().  They loop around partial progress
- * instead of returning -EIOCBRETRY because they don't have the means to call
- * kick_iocb().
- */
-static ssize_t aio_pread(struct kiocb *iocb)
+static void aio_advance_iovec(struct kiocb *iocb, ssize_t ret)
 {
-       struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       ssize_t ret = 0;
-
-       do {
-               ret = file->f_op->aio_read(iocb, iocb->ki_buf,
-                       iocb->ki_left, iocb->ki_pos);
-               /*
-                * Can't just depend on iocb->ki_left to determine
-                * whether we are done. This may have been a short read.
-                */
-               if (ret > 0) {
-                       iocb->ki_buf += ret;
-                       iocb->ki_left -= ret;
+       struct iovec *iov = &iocb->ki_iovec[iocb->ki_cur_seg];
+
+       BUG_ON(ret <= 0);
+
+       while (iocb->ki_cur_seg < iocb->ki_nr_segs && ret > 0) {
+               ssize_t this = min((ssize_t)iov->iov_len, ret);
+               iov->iov_base += this;
+               iov->iov_len -= this;
+               iocb->ki_left -= this;
+               ret -= this;
+               if (iov->iov_len == 0) {
+                       iocb->ki_cur_seg++;
+                       iov++;
                }
+       }
 
-               /*
-                * For pipes and sockets we return once we have some data; for
-                * regular files we retry till we complete the entire read or
-                * find that we can't read any more data (e.g short reads).
-                */
-       } while (ret > 0 && iocb->ki_left > 0 &&
-                !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode));
-
-       /* This means we must have transferred all that we could */
-       /* No need to retry anymore */
-       if ((ret == 0) || (iocb->ki_left == 0))
-               ret = iocb->ki_nbytes - iocb->ki_left;
-
-       return ret;
+       /* the caller should not have done more io than what fit in
+        * the remaining iovecs */
+       BUG_ON(ret > 0 && iocb->ki_left == 0);
 }
 
-/* see aio_pread() */
-static ssize_t aio_pwrite(struct kiocb *iocb)
+static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
 {
        struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
+       ssize_t (*rw_op)(struct kiocb *, const struct iovec *,
+                        unsigned long, loff_t);
        ssize_t ret = 0;
+       unsigned short opcode;
+
+       if ((iocb->ki_opcode == IOCB_CMD_PREADV) ||
+               (iocb->ki_opcode == IOCB_CMD_PREAD)) {
+               rw_op = file->f_op->aio_read;
+               opcode = IOCB_CMD_PREADV;
+       } else {
+               rw_op = file->f_op->aio_write;
+               opcode = IOCB_CMD_PWRITEV;
+       }
 
        do {
-               ret = file->f_op->aio_write(iocb, iocb->ki_buf,
-                       iocb->ki_left, iocb->ki_pos);
-               if (ret > 0) {
-                       iocb->ki_buf += ret;
-                       iocb->ki_left -= ret;
-               }
-       } while (ret > 0 && iocb->ki_left > 0);
+               ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
+                           iocb->ki_nr_segs - iocb->ki_cur_seg,
+                           iocb->ki_pos);
+               if (ret > 0)
+                       aio_advance_iovec(iocb, ret);
+
+       /* retry all partial writes.  retry partial reads as long as its a
+        * regular file. */
+       } while (ret > 0 && iocb->ki_left > 0 &&
+                (opcode == IOCB_CMD_PWRITEV ||
+                 (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))));
 
+       /* This means we must have transferred all that we could */
+       /* No need to retry anymore */
        if ((ret == 0) || (iocb->ki_left == 0))
                ret = iocb->ki_nbytes - iocb->ki_left;
 
@@ -1383,6 +1387,38 @@ static ssize_t aio_fsync(struct kiocb *iocb)
        return ret;
 }
 
+static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb)
+{
+       ssize_t ret;
+
+       ret = rw_copy_check_uvector(type, (struct iovec __user *)kiocb->ki_buf,
+                                   kiocb->ki_nbytes, 1,
+                                   &kiocb->ki_inline_vec, &kiocb->ki_iovec);
+       if (ret < 0)
+               goto out;
+
+       kiocb->ki_nr_segs = kiocb->ki_nbytes;
+       kiocb->ki_cur_seg = 0;
+       /* ki_nbytes/left now reflect bytes instead of segs */
+       kiocb->ki_nbytes = ret;
+       kiocb->ki_left = ret;
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+{
+       kiocb->ki_iovec = &kiocb->ki_inline_vec;
+       kiocb->ki_iovec->iov_base = kiocb->ki_buf;
+       kiocb->ki_iovec->iov_len = kiocb->ki_left;
+       kiocb->ki_nr_segs = 1;
+       kiocb->ki_cur_seg = 0;
+       kiocb->ki_nbytes = kiocb->ki_left;
+       return 0;
+}
+
 /*
  * aio_setup_iocb:
  *     Performs the initial checks and aio retry method
@@ -1405,9 +1441,12 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
                ret = security_file_permission(file, MAY_READ);
                if (unlikely(ret))
                        break;
+               ret = aio_setup_single_vector(kiocb);
+               if (ret)
+                       break;
                ret = -EINVAL;
                if (file->f_op->aio_read)
-                       kiocb->ki_retry = aio_pread;
+                       kiocb->ki_retry = aio_rw_vect_retry;
                break;
        case IOCB_CMD_PWRITE:
                ret = -EBADF;
@@ -1420,9 +1459,40 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
                ret = security_file_permission(file, MAY_WRITE);
                if (unlikely(ret))
                        break;
+               ret = aio_setup_single_vector(kiocb);
+               if (ret)
+                       break;
+               ret = -EINVAL;
+               if (file->f_op->aio_write)
+                       kiocb->ki_retry = aio_rw_vect_retry;
+               break;
+       case IOCB_CMD_PREADV:
+               ret = -EBADF;
+               if (unlikely(!(file->f_mode & FMODE_READ)))
+                       break;
+               ret = security_file_permission(file, MAY_READ);
+               if (unlikely(ret))
+                       break;
+               ret = aio_setup_vectored_rw(READ, kiocb);
+               if (ret)
+                       break;
+               ret = -EINVAL;
+               if (file->f_op->aio_read)
+                       kiocb->ki_retry = aio_rw_vect_retry;
+               break;
+       case IOCB_CMD_PWRITEV:
+               ret = -EBADF;
+               if (unlikely(!(file->f_mode & FMODE_WRITE)))
+                       break;
+               ret = security_file_permission(file, MAY_WRITE);
+               if (unlikely(ret))
+                       break;
+               ret = aio_setup_vectored_rw(WRITE, kiocb);
+               if (ret)
+                       break;
                ret = -EINVAL;
                if (file->f_op->aio_write)
-                       kiocb->ki_retry = aio_pwrite;
+                       kiocb->ki_retry = aio_rw_vect_retry;
                break;
        case IOCB_CMD_FDSYNC:
                ret = -EINVAL;
index af2efbbb5d76ef7a6db921ba43316b5570c4dadf..2c9759baad61bf0f875c4adbb4abba6e8fdebb04 100644 (file)
@@ -129,10 +129,9 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        struct autofs_sb_info *sbi;
        int minproto, maxproto;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if ( !sbi )
                goto fail_unlock;
-       memset(sbi, 0, sizeof(*sbi));
        DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
 
        s->s_fs_info = sbi;
@@ -217,7 +216,6 @@ static void autofs_read_inode(struct inode *inode)
        inode->i_nlink = 2;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_blocks = 0;
-       inode->i_blksize = 1024;
 
        if ( ino == AUTOFS_ROOT_INO ) {
                inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
@@ -242,7 +240,7 @@ static void autofs_read_inode(struct inode *inode)
                
                inode->i_op = &autofs_symlink_inode_operations;
                sl = &sbi->symlink[n];
-               inode->u.generic_ip = sl;
+               inode->i_private = sl;
                inode->i_mode = S_IFLNK | S_IRWXUGO;
                inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
                inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
index 9cac08d6a873111086c8ab75529976589e12dfce..368a1c33a3c824effc61b722bdcebc0f35e62f3d 100644 (file)
@@ -414,7 +414,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
 
        dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL;
        autofs_hash_delete(ent);
-       dir->i_nlink--;
+       drop_nlink(dir);
        d_drop(dentry);
        unlock_kernel();
 
@@ -466,7 +466,7 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        ent->dentry = dentry;
        autofs_hash_insert(dh,ent);
 
-       dir->i_nlink++;
+       inc_nlink(dir);
        d_instantiate(dentry, iget(dir->i_sb,ino));
        unlock_kernel();
 
index 52e8772b066e33fece33d73ae5ddf30568c5b4ca..c74f2eb6577521ffec6f01bb1a7f0d21f66af5c1 100644 (file)
@@ -15,7 +15,7 @@
 /* Nothing to release.. */
 static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
+       char *s=((struct autofs_symlink *)dentry->d_inode->i_private)->data;
        nd_set_link(nd, s);
        return NULL;
 }
index 11a6a9ae51b77442bd650a4d07574fee9a822336..800ce876caeca6e33fc427e40d34d89a69923ed3 100644 (file)
@@ -447,7 +447,6 @@ struct inode *autofs4_get_inode(struct super_block *sb,
                inode->i_uid = 0;
                inode->i_gid = 0;
        }
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
index 5100f984783faa123caabf76ad97e1718bdea70e..c1493524da4d614da928caec7abbfc845c417c0c 100644 (file)
@@ -137,7 +137,9 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
                nd.flags = LOOKUP_DIRECTORY;
                ret = (dentry->d_op->d_revalidate)(dentry, &nd);
 
-               if (!ret) {
+               if (ret <= 0) {
+                       if (ret < 0)
+                               status = ret;
                        dcache_dir_close(inode, file);
                        goto out;
                }
@@ -279,9 +281,6 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
 
                DPRINTK("mount done status=%d", status);
 
-               if (status && dentry->d_inode)
-                       return status; /* Try to get the kernel to invalidate this dentry */
-
                /* Turn this into a real negative dentry? */
                if (status == -ENOENT) {
                        spin_lock(&dentry->d_lock);
@@ -357,7 +356,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
         * don't try to mount it again.
         */
        spin_lock(&dcache_lock);
-       if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
+       if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
                spin_unlock(&dcache_lock);
 
                status = try_to_fill_dentry(dentry, 0);
@@ -400,13 +399,23 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        int oz_mode = autofs4_oz_mode(sbi);
        int flags = nd ? nd->flags : 0;
-       int status = 0;
+       int status = 1;
 
        /* Pending dentry */
        if (autofs4_ispending(dentry)) {
-               if (!oz_mode)
-                       status = try_to_fill_dentry(dentry, flags);
-               return !status;
+               /* The daemon never causes a mount to trigger */
+               if (oz_mode)
+                       return 1;
+
+               /*
+                * A zero status is success otherwise we have a
+                * negative error code.
+                */
+               status = try_to_fill_dentry(dentry, flags);
+               if (status == 0)
+                               return 1;
+
+               return status;
        }
 
        /* Negative dentry.. invalidate if "old" */
@@ -421,9 +430,19 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
                DPRINTK("dentry=%p %.*s, emptydir",
                         dentry, dentry->d_name.len, dentry->d_name.name);
                spin_unlock(&dcache_lock);
-               if (!oz_mode)
-                       status = try_to_fill_dentry(dentry, flags);
-               return !status;
+               /* The daemon never causes a mount to trigger */
+               if (oz_mode)
+                       return 1;
+
+               /*
+                * A zero status is success otherwise we have a
+                * negative error code.
+                */
+               status = try_to_fill_dentry(dentry, flags);
+               if (status == 0)
+                       return 1;
+
+               return status;
        }
        spin_unlock(&dcache_lock);
 
@@ -518,6 +537,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
                            return ERR_PTR(-ERESTARTNOINTR);
                        }
                }
+               spin_lock(&dentry->d_lock);
+               dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
+               spin_unlock(&dentry->d_lock);
        }
 
        /*
@@ -616,7 +638,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
        dput(ino->dentry);
 
        dentry->d_inode->i_size = 0;
-       dentry->d_inode->i_nlink = 0;
+       clear_nlink(dentry->d_inode);
 
        dir->i_mtime = CURRENT_TIME;
 
@@ -651,10 +673,10 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
        }
        dput(ino->dentry);
        dentry->d_inode->i_size = 0;
-       dentry->d_inode->i_nlink = 0;
+       clear_nlink(dentry->d_inode);
 
        if (dir->i_nlink)
-               dir->i_nlink--;
+               drop_nlink(dir);
 
        return 0;
 }
@@ -691,7 +713,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (p_ino && dentry->d_parent != dentry)
                atomic_inc(&p_ino->count);
        ino->inode = inode;
-       dir->i_nlink++;
+       inc_nlink(dir);
        dir->i_mtime = CURRENT_TIME;
 
        return 0;
index 80599ae339669d3a3a962d64d974f62fb30a58d6..34e6d7b220c322b9399c32a701fe4910c256946f 100644 (file)
@@ -40,8 +40,6 @@ static const struct file_operations bad_file_ops =
        .aio_fsync      = EIO_ERROR,
        .fasync         = EIO_ERROR,
        .lock           = EIO_ERROR,
-       .readv          = EIO_ERROR,
-       .writev         = EIO_ERROR,
        .sendfile       = EIO_ERROR,
        .sendpage       = EIO_ERROR,
        .get_unmapped_area = EIO_ERROR,
index 50cfca5c7efd570588d549a5f23f9f5650fd360d..57020c7a7e6589fc84717d6015743bcbd9004627 100644 (file)
@@ -365,7 +365,6 @@ befs_read_inode(struct inode *inode)
        inode->i_mtime.tv_nsec = 0;   /* lower 16 bits are not a time */        
        inode->i_ctime = inode->i_mtime;
        inode->i_atime = inode->i_mtime;
-       inode->i_blksize = befs_sb->block_size;
 
        befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num);
        befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent);
@@ -446,9 +445,7 @@ befs_init_inodecache(void)
 static void
 befs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(befs_inode_cachep))
-               printk(KERN_ERR "befs_destroy_inodecache: "
-                      "not all structures were freed\n");
+       kmem_cache_destroy(befs_inode_cachep);
 }
 
 /*
index 26fad96217380786af130867e2e8f943d670fe4b..a650f1d0b85ea815860ef528d0177ceefa51655e 100644 (file)
@@ -102,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
        inode->i_uid = current->fsuid;
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        inode->i_op = &bfs_file_inops;
        inode->i_fop = &bfs_file_operations;
        inode->i_mapping->a_ops = &bfs_aops;
@@ -117,8 +117,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
 
        err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
        if (err) {
-               inode->i_nlink--;
-               mark_inode_dirty(inode);
+               inode_dec_link_count(inode);
                iput(inode);
                unlock_kernel();
                return err;
@@ -164,7 +163,7 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new
                unlock_kernel();
                return err;
        }
-       inode->i_nlink++;
+       inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
        atomic_inc(&inode->i_count);
@@ -196,9 +195,8 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
        mark_buffer_dirty(bh);
        dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        mark_inode_dirty(dir);
-       inode->i_nlink--;
        inode->i_ctime = dir->i_ctime;
-       mark_inode_dirty(inode);
+       inode_dec_link_count(inode);
        error = 0;
 
 out_brelse:
@@ -249,9 +247,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
        mark_inode_dirty(old_dir);
        if (new_inode) {
-               new_inode->i_nlink--;
                new_inode->i_ctime = CURRENT_TIME_SEC;
-               mark_inode_dirty(new_inode);
+               inode_dec_link_count(new_inode);
        }
        mark_buffer_dirty(old_bh);
        error = 0;
index 3d5aca28a0a0980922c83c0b197d1cf52cb27593..a9164a87f8deebfee1ceefd1f722bb0baac75491 100644 (file)
 
 const struct file_operations bfs_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .sendfile       = generic_file_sendfile,
 };
index cf74f3d4d966d0f81c8abace34a1bfe79d9050e8..ed27ffb3459e9ea73ea23b476b27cf1bf95d0320 100644 (file)
@@ -76,7 +76,6 @@ static void bfs_read_inode(struct inode * inode)
        inode->i_size = BFS_FILESIZE(di);
        inode->i_blocks = BFS_FILEBLOCKS(di);
         if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
-       inode->i_blksize = PAGE_SIZE;
        inode->i_atime.tv_sec =  le32_to_cpu(di->i_atime);
        inode->i_mtime.tv_sec =  le32_to_cpu(di->i_mtime);
        inode->i_ctime.tv_sec =  le32_to_cpu(di->i_ctime);
@@ -268,8 +267,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(bfs_inode_cachep))
-               printk(KERN_INFO "bfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(bfs_inode_cachep);
 }
 
 static struct super_operations bfs_sops = {
@@ -311,11 +309,10 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
        unsigned i, imap_len;
        struct bfs_sb_info * info;
 
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
        s->s_fs_info = info;
-       memset(info, 0, sizeof(*info));
 
        sb_set_blocksize(s, BFS_BSIZE);
 
@@ -338,10 +335,9 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
                        + BFS_ROOT_INO - 1;
 
        imap_len = info->si_lasti/8 + 1;
-       info->si_imap = kmalloc(imap_len, GFP_KERNEL);
+       info->si_imap = kzalloc(imap_len, GFP_KERNEL);
        if (!info->si_imap)
                goto out;
-       memset(info->si_imap, 0, imap_len);
        for (i=0; i<BFS_ROOT_INO; i++) 
                set_bit(i, info->si_imap);
 
index f312103434d4594fcd8d532c90bb8b4cf4698289..517e111bb7ef4acbb94f95fb560cb4c2734f4d5b 100644 (file)
@@ -278,6 +278,13 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                return -ENOEXEC;
        }
 
+       /*
+        * Requires a mmap handler. This prevents people from using a.out
+        * as part of an exploit attack against /proc-related vulnerabilities.
+        */
+       if (!bprm->file->f_op || !bprm->file->f_op->mmap)
+               return -ENOEXEC;
+
        fd_offset = N_TXTOFF(ex);
 
        /* Check initial limits. This avoids letting people circumvent
@@ -476,6 +483,13 @@ static int load_aout_library(struct file *file)
                goto out;
        }
 
+       /*
+        * Requires a mmap handler. This prevents people from using a.out
+        * as part of an exploit attack against /proc-related vulnerabilities.
+        */
+       if (!file->f_op || !file->f_op->mmap)
+               goto out;
+
        if (N_FLAGS(ex))
                goto out;
 
index dfd8cfb7fb5dcd213ab74c41474c81e06a69f8e1..06435f3665f472f7a1e7ff4879627bff3064c740 100644 (file)
@@ -46,7 +46,6 @@
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
 static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
-extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
 
 #ifndef elf_addr_t
 #define elf_addr_t unsigned long
@@ -1038,10 +1037,8 @@ out_free_interp:
 out_free_file:
        sys_close(elf_exec_fileno);
 out_free_fh:
-       if (files) {
-               put_files_struct(current->files);
-               current->files = files;
-       }
+       if (files)
+               reset_files_struct(current, files);
 out_free_ph:
        kfree(elf_phdata);
        goto out;
@@ -1154,11 +1151,23 @@ static int dump_write(struct file *file, const void *addr, int nr)
 
 static int dump_seek(struct file *file, loff_t off)
 {
-       if (file->f_op->llseek) {
-               if (file->f_op->llseek(file, off, 0) != off)
+       if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+               if (file->f_op->llseek(file, off, 1) != off)
                        return 0;
-       } else
-               file->f_pos = off;
+       } else {
+               char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+               if (!buf)
+                       return 0;
+               while (off > 0) {
+                       unsigned long n = off;
+                       if (n > PAGE_SIZE)
+                               n = PAGE_SIZE;
+                       if (!dump_write(file, buf, n))
+                               return 0;
+                       off -= n;
+               }
+               free_page((unsigned long)buf);
+       }
        return 1;
 }
 
@@ -1206,30 +1215,35 @@ static int notesize(struct memelfnote *en)
        return sz;
 }
 
-#define DUMP_WRITE(addr, nr)   \
-       do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
-#define DUMP_SEEK(off) \
-       do { if (!dump_seek(file, (off))) return 0; } while(0)
+#define DUMP_WRITE(addr, nr, foffset)  \
+       do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
 
-static int writenote(struct memelfnote *men, struct file *file)
+static int alignfile(struct file *file, loff_t *foffset)
 {
-       struct elf_note en;
+       char buf[4] = { 0, };
+       DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
+       return 1;
+}
 
+static int writenote(struct memelfnote *men, struct file *file,
+                       loff_t *foffset)
+{
+       struct elf_note en;
        en.n_namesz = strlen(men->name) + 1;
        en.n_descsz = men->datasz;
        en.n_type = men->type;
 
-       DUMP_WRITE(&en, sizeof(en));
-       DUMP_WRITE(men->name, en.n_namesz);
-       /* XXX - cast from long long to long to avoid need for libgcc.a */
-       DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));      /* XXX */
-       DUMP_WRITE(men->data, men->datasz);
-       DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));      /* XXX */
+       DUMP_WRITE(&en, sizeof(en), foffset);
+       DUMP_WRITE(men->name, en.n_namesz, foffset);
+       if (!alignfile(file, foffset))
+               return 0;
+       DUMP_WRITE(men->data, men->datasz, foffset);
+       if (!alignfile(file, foffset))
+               return 0;
 
        return 1;
 }
 #undef DUMP_WRITE
-#undef DUMP_SEEK
 
 #define DUMP_WRITE(addr, nr)   \
        if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
@@ -1429,7 +1443,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
        int i;
        struct vm_area_struct *vma;
        struct elfhdr *elf = NULL;
-       loff_t offset = 0, dataoff;
+       loff_t offset = 0, dataoff, foffset;
        unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
        int numnote;
        struct memelfnote *notes = NULL;
@@ -1481,20 +1495,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
 
        if (signr) {
                struct elf_thread_status *tmp;
-               read_lock(&tasklist_lock);
+               rcu_read_lock();
                do_each_thread(g,p)
                        if (current->mm == p->mm && current != p) {
                                tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
                                if (!tmp) {
-                                       read_unlock(&tasklist_lock);
+                                       rcu_read_unlock();
                                        goto cleanup;
                                }
-                               INIT_LIST_HEAD(&tmp->list);
                                tmp->thread = p;
                                list_add(&tmp->list, &thread_list);
                        }
                while_each_thread(g,p);
-               read_unlock(&tasklist_lock);
+               rcu_read_unlock();
                list_for_each(t, &thread_list) {
                        struct elf_thread_status *tmp;
                        int sz;
@@ -1573,7 +1586,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
                DUMP_WRITE(&phdr, sizeof(phdr));
        }
 
-       /* Page-align dumped data */
+       foffset = offset;
+
        dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
        /* Write program headers for segments dump */
@@ -1598,6 +1612,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
                phdr.p_align = ELF_EXEC_PAGESIZE;
 
                DUMP_WRITE(&phdr, sizeof(phdr));
+               foffset += sizeof(phdr);
        }
 
 #ifdef ELF_CORE_WRITE_EXTRA_PHDRS
@@ -1606,7 +1621,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
 
        /* write out the notes section */
        for (i = 0; i < numnote; i++)
-               if (!writenote(notes + i, file))
+               if (!writenote(notes + i, file, &foffset))
                        goto end_coredump;
 
        /* write out the thread status notes section */
@@ -1615,11 +1630,12 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
                                list_entry(t, struct elf_thread_status, list);
 
                for (i = 0; i < tmp->num_notes; i++)
-                       if (!writenote(&tmp->notes[i], file))
+                       if (!writenote(&tmp->notes[i], file, &foffset))
                                goto end_coredump;
        }
-       DUMP_SEEK(dataoff);
+
+       /* Align to page */
+       DUMP_SEEK(dataoff - foffset);
 
        for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
                unsigned long addr;
@@ -1635,10 +1651,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
 
                        if (get_user_pages(current, current->mm, addr, 1, 0, 1,
                                                &page, &vma) <= 0) {
-                               DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                               DUMP_SEEK(PAGE_SIZE);
                        } else {
                                if (page == ZERO_PAGE(addr)) {
-                                       DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                                       DUMP_SEEK(PAGE_SIZE);
                                } else {
                                        void *kaddr;
                                        flush_cache_page(vma, addr,
@@ -1662,13 +1678,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
        ELF_CORE_WRITE_EXTRA_DATA;
 #endif
 
-       if (file->f_pos != offset) {
-               /* Sanity check */
-               printk(KERN_WARNING
-                      "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n",
-                      file->f_pos, offset);
-       }
-
 end_coredump:
        set_fs(fs);
 
index 2f336582922940ffb9160d664f39acff70fe3ad1..f86d5c9ce5ebda5eaf4c94fbd441dd770a24b9c4 100644 (file)
@@ -1597,20 +1597,19 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
 
        if (signr) {
                struct elf_thread_status *tmp;
-               read_lock(&tasklist_lock);
+               rcu_read_lock();
                do_each_thread(g,p)
                        if (current->mm == p->mm && current != p) {
                                tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
                                if (!tmp) {
-                                       read_unlock(&tasklist_lock);
+                                       rcu_read_unlock();
                                        goto cleanup;
                                }
-                               INIT_LIST_HEAD(&tmp->list);
                                tmp->thread = p;
                                list_add(&tmp->list, &thread_list);
                        }
                while_each_thread(g,p);
-               read_unlock(&tasklist_lock);
+               rcu_read_unlock();
                list_for_each(t, &thread_list) {
                        struct elf_thread_status *tmp;
                        int sz;
index 34ebbc191e46ada5e8c488257e9e131b0060cac3..1713c48fef5494e5e8ef361a83b5795ecaae4ce9 100644 (file)
@@ -215,10 +215,8 @@ _error:
        bprm->interp_flags = 0;
        bprm->interp_data = 0;
 _unshare:
-       if (files) {
-               put_files_struct(current->files);
-               current->files = files;
-       }
+       if (files)
+               reset_files_struct(current, files);
        goto _ret;
 }
 
@@ -507,7 +505,6 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime =
                        current_fs_time(inode->i_sb);
@@ -517,7 +514,7 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
 
 static void bm_clear_inode(struct inode *inode)
 {
-       kfree(inode->u.generic_ip);
+       kfree(inode->i_private);
 }
 
 static void kill_node(Node *e)
@@ -545,7 +542,7 @@ static void kill_node(Node *e)
 static ssize_t
 bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
 {
-       Node *e = file->f_dentry->d_inode->u.generic_ip;
+       Node *e = file->f_dentry->d_inode->i_private;
        loff_t pos = *ppos;
        ssize_t res;
        char *page;
@@ -579,7 +576,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
                                size_t count, loff_t *ppos)
 {
        struct dentry *root;
-       Node *e = file->f_dentry->d_inode->u.generic_ip;
+       Node *e = file->f_dentry->d_inode->i_private;
        int res = parse_command(buffer, count);
 
        switch (res) {
@@ -646,7 +643,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
        }
 
        e->dentry = dget(dentry);
-       inode->u.generic_ip = e;
+       inode->i_private = e;
        inode->i_fop = &bm_entry_operations;
 
        d_instantiate(dentry, inode);
index 6a0b9ad8f8c9d031d4c32fb32e1c53e0677d1ef2..8f93e939f21375abe2c205fd2783c319098cc87f 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2001 Jens Axboe <axboe@kernel.dk>
  *
  * 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
@@ -1142,7 +1142,7 @@ static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale)
                struct biovec_slab *bp = bvec_slabs + i;
                mempool_t **bvp = bs->bvec_pools + i;
 
-               if (i >= scale)
+               if (pool_entries > 1 && i >= scale)
                        pool_entries >>= 1;
 
                *bvp = mempool_create_slab_pool(pool_entries, bp->slab);
index 045f98854f14ab91c71cc6a61a9cafb1716a53c4..bc8f27cc448314b2eaf99cc93628671d51d5adc1 100644 (file)
 #include <linux/module.h>
 #include <linux/blkpg.h>
 #include <linux/buffer_head.h>
+#include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/mount.h>
 #include <linux/uio.h>
 #include <linux/namei.h>
 #include <asm/uaccess.h>
+#include "internal.h"
 
 struct bdev_inode {
        struct block_device bdev;
@@ -543,11 +545,11 @@ static struct kobject *bdev_get_holder(struct block_device *bdev)
                return kobject_get(bdev->bd_disk->holder_dir);
 }
 
-static void add_symlink(struct kobject *from, struct kobject *to)
+static int add_symlink(struct kobject *from, struct kobject *to)
 {
        if (!from || !to)
-               return;
-       sysfs_create_link(from, to, kobject_name(to));
+               return 0;
+       return sysfs_create_link(from, to, kobject_name(to));
 }
 
 static void del_symlink(struct kobject *from, struct kobject *to)
@@ -648,30 +650,38 @@ static void free_bd_holder(struct bd_holder *bo)
  * If there is no matching entry with @bo in @bdev->bd_holder_list,
  * add @bo to the list, create symlinks.
  *
- * Returns 1 if @bo was added to the list.
- * Returns 0 if @bo wasn't used by any reason and should be freed.
+ * Returns 0 if symlinks are created or already there.
+ * Returns -ve if something fails and @bo can be freed.
  */
 static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
 {
        struct bd_holder *tmp;
+       int ret;
 
        if (!bo)
-               return 0;
+               return -EINVAL;
 
        list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
                if (tmp->sdir == bo->sdir) {
                        tmp->count++;
+                       /* We've already done what we need to do here. */
+                       free_bd_holder(bo);
                        return 0;
                }
        }
 
        if (!bd_holder_grab_dirs(bdev, bo))
-               return 0;
+               return -EBUSY;
 
-       add_symlink(bo->sdir, bo->sdev);
-       add_symlink(bo->hdir, bo->hdev);
-       list_add_tail(&bo->list, &bdev->bd_holder_list);
-       return 1;
+       ret = add_symlink(bo->sdir, bo->sdev);
+       if (ret == 0) {
+               ret = add_symlink(bo->hdir, bo->hdev);
+               if (ret)
+                       del_symlink(bo->sdir, bo->sdev);
+       }
+       if (ret == 0)
+               list_add_tail(&bo->list, &bdev->bd_holder_list);
+       return ret;
 }
 
 /**
@@ -741,7 +751,9 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
 
        mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
        res = bd_claim(bdev, holder);
-       if (res || !add_bd_holder(bdev, bo))
+       if (res == 0)
+               res = add_bd_holder(bdev, bo);
+       if (res)
                free_bd_holder(bo);
        mutex_unlock(&bdev->bd_mutex);
 
@@ -1021,7 +1033,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
                                rescan_partitions(bdev->bd_disk, bdev);
                } else {
                        mutex_lock_nested(&bdev->bd_contains->bd_mutex,
-                                         BD_MUTEX_PARTITION);
+                                         BD_MUTEX_WHOLE);
                        bdev->bd_contains->bd_part_count++;
                        mutex_unlock(&bdev->bd_contains->bd_mutex);
                }
@@ -1142,22 +1154,6 @@ static int blkdev_close(struct inode * inode, struct file * filp)
        return blkdev_put(bdev);
 }
 
-static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
-                                  size_t count, loff_t *ppos)
-{
-       struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
-       return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
-static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
-                                  size_t count, loff_t pos)
-{
-       struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
-       return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
 static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
        return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -1177,18 +1173,16 @@ const struct file_operations def_blk_fops = {
        .open           = blkdev_open,
        .release        = blkdev_close,
        .llseek         = block_llseek,
-       .read           = generic_file_read,
-       .write          = blkdev_file_write,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
-       .aio_write      = blkdev_file_aio_write, 
+       .aio_write      = generic_file_aio_write_nolock,
        .mmap           = generic_file_mmap,
        .fsync          = block_fsync,
        .unlocked_ioctl = block_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .readv          = generic_file_readv,
-       .writev         = generic_file_write_nolock,
        .sendfile       = generic_file_sendfile,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
@@ -1303,3 +1297,24 @@ void close_bdev_excl(struct block_device *bdev)
 }
 
 EXPORT_SYMBOL(close_bdev_excl);
+
+int __invalidate_device(struct block_device *bdev)
+{
+       struct super_block *sb = get_super(bdev);
+       int res = 0;
+
+       if (sb) {
+               /*
+                * no need to lock the super, get_super holds the
+                * read mutex so the filesystem cannot go away
+                * under us (->put_super runs with the write lock
+                * hold).
+                */
+               shrink_dcache_sb(sb);
+               res = invalidate_inodes(sb);
+               drop_super(sb);
+       }
+       invalidate_bdev(bdev, 0);
+       return res;
+}
+EXPORT_SYMBOL(__invalidate_device);
index 3b6d701073e7f09a311f10297a58d8c06e715df5..16cfbcd254f15fa05eb452eb512297c439605035 100644 (file)
@@ -159,31 +159,6 @@ int sync_blockdev(struct block_device *bdev)
 }
 EXPORT_SYMBOL(sync_blockdev);
 
-static void __fsync_super(struct super_block *sb)
-{
-       sync_inodes_sb(sb, 0);
-       DQUOT_SYNC(sb);
-       lock_super(sb);
-       if (sb->s_dirt && sb->s_op->write_super)
-               sb->s_op->write_super(sb);
-       unlock_super(sb);
-       if (sb->s_op->sync_fs)
-               sb->s_op->sync_fs(sb, 1);
-       sync_blockdev(sb->s_bdev);
-       sync_inodes_sb(sb, 1);
-}
-
-/*
- * Write out and wait upon all dirty data associated with this
- * superblock.  Filesystem data as well as the underlying block
- * device.  Takes the superblock lock.
- */
-int fsync_super(struct super_block *sb)
-{
-       __fsync_super(sb);
-       return sync_blockdev(sb->s_bdev);
-}
-
 /*
  * Write out and wait upon all dirty data associated with this
  * device.   Filesystem data as well as the underlying block
@@ -259,118 +234,6 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb)
 }
 EXPORT_SYMBOL(thaw_bdev);
 
-/*
- * sync everything.  Start out by waking pdflush, because that writes back
- * all queues in parallel.
- */
-static void do_sync(unsigned long wait)
-{
-       wakeup_pdflush(0);
-       sync_inodes(0);         /* All mappings, inodes and their blockdevs */
-       DQUOT_SYNC(NULL);
-       sync_supers();          /* Write the superblocks */
-       sync_filesystems(0);    /* Start syncing the filesystems */
-       sync_filesystems(wait); /* Waitingly sync the filesystems */
-       sync_inodes(wait);      /* Mappings, inodes and blockdevs, again. */
-       if (!wait)
-               printk("Emergency Sync complete\n");
-       if (unlikely(laptop_mode))
-               laptop_sync_completion();
-}
-
-asmlinkage long sys_sync(void)
-{
-       do_sync(1);
-       return 0;
-}
-
-void emergency_sync(void)
-{
-       pdflush_operation(do_sync, 0);
-}
-
-/*
- * Generic function to fsync a file.
- *
- * filp may be NULL if called via the msync of a vma.
- */
-int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
-{
-       struct inode * inode = dentry->d_inode;
-       struct super_block * sb;
-       int ret, err;
-
-       /* sync the inode to buffers */
-       ret = write_inode_now(inode, 0);
-
-       /* sync the superblock to buffers */
-       sb = inode->i_sb;
-       lock_super(sb);
-       if (sb->s_op->write_super)
-               sb->s_op->write_super(sb);
-       unlock_super(sb);
-
-       /* .. finally sync the buffers to disk */
-       err = sync_blockdev(sb->s_bdev);
-       if (!ret)
-               ret = err;
-       return ret;
-}
-
-long do_fsync(struct file *file, int datasync)
-{
-       int ret;
-       int err;
-       struct address_space *mapping = file->f_mapping;
-
-       if (!file->f_op || !file->f_op->fsync) {
-               /* Why?  We can still call filemap_fdatawrite */
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = filemap_fdatawrite(mapping);
-
-       /*
-        * We need to protect against concurrent writers, which could cause
-        * livelocks in fsync_buffers_list().
-        */
-       mutex_lock(&mapping->host->i_mutex);
-       err = file->f_op->fsync(file, file->f_dentry, datasync);
-       if (!ret)
-               ret = err;
-       mutex_unlock(&mapping->host->i_mutex);
-       err = filemap_fdatawait(mapping);
-       if (!ret)
-               ret = err;
-out:
-       return ret;
-}
-
-static long __do_fsync(unsigned int fd, int datasync)
-{
-       struct file *file;
-       int ret = -EBADF;
-
-       file = fget(fd);
-       if (file) {
-               ret = do_fsync(file, datasync);
-               fput(file);
-       }
-       return ret;
-}
-
-asmlinkage long sys_fsync(unsigned int fd)
-{
-       return __do_fsync(fd, 0);
-}
-
-asmlinkage long sys_fdatasync(unsigned int fd)
-{
-       return __do_fsync(fd, 1);
-}
-
 /*
  * Various filesystems appear to want __find_get_block to be non-blocking.
  * But it's the page lock which protects the buffers.  To get around this,
@@ -1550,35 +1413,6 @@ static void discard_buffer(struct buffer_head * bh)
        unlock_buffer(bh);
 }
 
-/**
- * try_to_release_page() - release old fs-specific metadata on a page
- *
- * @page: the page which the kernel is trying to free
- * @gfp_mask: memory allocation flags (and I/O mode)
- *
- * The address_space is to try to release any data against the page
- * (presumably at page->private).  If the release was successful, return `1'.
- * Otherwise return zero.
- *
- * The @gfp_mask argument specifies whether I/O may be performed to release
- * this page (__GFP_IO), and whether the call may block (__GFP_WAIT).
- *
- * NOTE: @gfp_mask may go away, and this function may become non-blocking.
- */
-int try_to_release_page(struct page *page, gfp_t gfp_mask)
-{
-       struct address_space * const mapping = page->mapping;
-
-       BUG_ON(!PageLocked(page));
-       if (PageWriteback(page))
-               return 0;
-       
-       if (mapping && mapping->a_ops->releasepage)
-               return mapping->a_ops->releasepage(page, gfp_mask);
-       return try_to_free_buffers(page);
-}
-EXPORT_SYMBOL(try_to_release_page);
-
 /**
  * block_invalidatepage - invalidate part of all of a buffer-backed page
  *
@@ -1630,14 +1464,6 @@ out:
 }
 EXPORT_SYMBOL(block_invalidatepage);
 
-void do_invalidatepage(struct page *page, unsigned long offset)
-{
-       void (*invalidatepage)(struct page *, unsigned long);
-       invalidatepage = page->mapping->a_ops->invalidatepage ? :
-               block_invalidatepage;
-       (*invalidatepage)(page, offset);
-}
-
 /*
  * We attach and possibly dirty the buffers atomically wrt
  * __set_page_dirty_buffers() via private_lock.  try_to_free_buffers
index 3483d3cf80873432d7696f6f3f68b4adef928b01..a885f46ca001f117a9b8bc3bd4ac0e140b5c9e3e 100644 (file)
 #include <linux/kobj_map.h>
 #include <linux/cdev.h>
 #include <linux/mutex.h>
+#include <linux/backing-dev.h>
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
+#include "internal.h"
+
+/*
+ * capabilities for /dev/mem, /dev/kmem and similar directly mappable character
+ * devices
+ * - permits shared-mmap for read, write and/or exec
+ * - does not permit private mmap in NOMMU mode (can't do COW)
+ * - no readahead or I/O queue unplugging required
+ */
+struct backing_dev_info directly_mappable_cdev_bdi = {
+       .capabilities   = (
+#ifdef CONFIG_MMU
+               /* permit private copies of the data to be taken */
+               BDI_CAP_MAP_COPY |
+#endif
+               /* permit direct mmap, for read, write or exec */
+               BDI_CAP_MAP_DIRECT |
+               BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP),
+};
 
 static struct kobj_map *cdev_map;
 
@@ -109,13 +129,31 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
 
        for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
                if ((*cp)->major > major ||
-                   ((*cp)->major == major && (*cp)->baseminor >= baseminor))
+                   ((*cp)->major == major &&
+                    (((*cp)->baseminor >= baseminor) ||
+                     ((*cp)->baseminor + (*cp)->minorct > baseminor))))
                        break;
-       if (*cp && (*cp)->major == major &&
-           (*cp)->baseminor < baseminor + minorct) {
-               ret = -EBUSY;
-               goto out;
+
+       /* Check for overlapping minor ranges.  */
+       if (*cp && (*cp)->major == major) {
+               int old_min = (*cp)->baseminor;
+               int old_max = (*cp)->baseminor + (*cp)->minorct - 1;
+               int new_min = baseminor;
+               int new_max = baseminor + minorct - 1;
+
+               /* New driver overlaps from the left.  */
+               if (new_max >= old_min && new_max <= old_max) {
+                       ret = -EBUSY;
+                       goto out;
+               }
+
+               /* New driver overlaps from the right.  */
+               if (new_min <= old_max && new_min >= old_min) {
+                       ret = -EBUSY;
+                       goto out;
+               }
        }
+
        cd->next = *cp;
        *cp = cd;
        mutex_unlock(&chrdevs_lock);
@@ -146,6 +184,15 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
        return cd;
 }
 
+/**
+ * register_chrdev_region() - register a range of device numbers
+ * @from: the first in the desired range of device numbers; must include
+ *        the major number.
+ * @count: the number of consecutive device numbers required
+ * @name: the name of the device or driver.
+ *
+ * Return value is zero on success, a negative error code on failure.
+ */
 int register_chrdev_region(dev_t from, unsigned count, const char *name)
 {
        struct char_device_struct *cd;
@@ -171,6 +218,17 @@ fail:
        return PTR_ERR(cd);
 }
 
+/**
+ * alloc_chrdev_region() - register a range of char device numbers
+ * @dev: output parameter for first assigned number
+ * @baseminor: first of the requested range of minor numbers
+ * @count: the number of minor numbers required
+ * @name: the name of the associated device or driver
+ *
+ * Allocates a range of char device numbers.  The major number will be
+ * chosen dynamically, and returned (along with the first minor number)
+ * in @dev.  Returns zero or a negative error code.
+ */
 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
                        const char *name)
 {
@@ -240,6 +298,15 @@ out2:
        return err;
 }
 
+/**
+ * unregister_chrdev_region() - return a range of device numbers
+ * @from: the first in the range of numbers to unregister
+ * @count: the number of device numbers to unregister
+ *
+ * This function will unregister a range of @count device numbers,
+ * starting with @from.  The caller should normally be the one who
+ * allocated those numbers in the first place...
+ */
 void unregister_chrdev_region(dev_t from, unsigned count)
 {
        dev_t to = from + count;
@@ -377,6 +444,16 @@ static int exact_lock(dev_t dev, void *data)
        return cdev_get(p) ? 0 : -1;
 }
 
+/**
+ * cdev_add() - add a char device to the system
+ * @p: the cdev structure for the device
+ * @dev: the first device number for which this device is responsible
+ * @count: the number of consecutive minor numbers corresponding to this
+ *         device
+ *
+ * cdev_add() adds the device represented by @p to the system, making it
+ * live immediately.  A negative error code is returned on failure.
+ */
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
        p->dev = dev;
@@ -389,6 +466,13 @@ static void cdev_unmap(dev_t dev, unsigned count)
        kobj_unmap(cdev_map, dev, count);
 }
 
+/**
+ * cdev_del() - remove a cdev from the system
+ * @p: the cdev structure to be removed
+ *
+ * cdev_del() removes @p from the system, possibly freeing the structure
+ * itself.
+ */
 void cdev_del(struct cdev *p)
 {
        cdev_unmap(p->dev, p->count);
@@ -417,6 +501,11 @@ static struct kobj_type ktype_cdev_dynamic = {
        .release        = cdev_dynamic_release,
 };
 
+/**
+ * cdev_alloc() - allocate a cdev structure
+ *
+ * Allocates and returns a cdev structure, or NULL on failure.
+ */
 struct cdev *cdev_alloc(void)
 {
        struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
@@ -428,6 +517,14 @@ struct cdev *cdev_alloc(void)
        return p;
 }
 
+/**
+ * cdev_init() - initialize a cdev structure
+ * @cdev: the structure to initialize
+ * @fops: the file_operations for this device
+ *
+ * Initializes @cdev, remembering @fops, making it ready to add to the
+ * system with cdev_add().
+ */
 void cdev_init(struct cdev *cdev, const struct file_operations *fops)
 {
        memset(cdev, 0, sizeof *cdev);
@@ -461,3 +558,4 @@ EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
 EXPORT_SYMBOL(register_chrdev);
 EXPORT_SYMBOL(unregister_chrdev);
+EXPORT_SYMBOL(directly_mappable_cdev_bdi);
index c3ef1c0d0e684786969bdb1c1caf7e860e2afd9e..c00c654f2e11c0ce9cdbb3d597bb1afe9e673ddb 100644 (file)
@@ -253,7 +253,6 @@ cifs_alloc_inode(struct super_block *sb)
        file data or metadata */
        cifs_inode->clientCanCacheRead = FALSE;
        cifs_inode->clientCanCacheAll = FALSE;
-       cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
        cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
        cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
        INIT_LIST_HEAD(&cifs_inode->openFileList);
@@ -481,25 +480,13 @@ cifs_get_sb(struct file_system_type *fs_type,
        return simple_set_mnt(mnt, sb);
 }
 
-static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t *ppos)
-{
-       struct inode *inode = file->f_dentry->d_inode;
-       ssize_t written;
-
-       written = generic_file_writev(file, iov, nr_segs, ppos);
-       if (!CIFS_I(inode)->clientCanCacheAll)
-               filemap_fdatawrite(inode->i_mapping);
-       return written;
-}
-
-static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
-                                  size_t count, loff_t pos)
+static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                                  unsigned long nr_segs, loff_t pos)
 {
        struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
        ssize_t written;
 
-       written = generic_file_aio_write(iocb, buf, count, pos);
+       written = generic_file_aio_write(iocb, iov, nr_segs, pos);
        if (!CIFS_I(inode)->clientCanCacheAll)
                filemap_fdatawrite(inode->i_mapping);
        return written;
@@ -578,8 +565,6 @@ struct inode_operations cifs_symlink_inode_ops = {
 const struct file_operations cifs_file_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
-       .readv = generic_file_readv,
-       .writev = cifs_file_writev,
        .aio_read = generic_file_aio_read,
        .aio_write = cifs_file_aio_write,
        .open = cifs_open,
@@ -621,8 +606,6 @@ const struct file_operations cifs_file_direct_ops = {
 const struct file_operations cifs_file_nobrl_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
-       .readv = generic_file_readv,
-       .writev = cifs_file_writev,
        .aio_read = generic_file_aio_read,
        .aio_write = cifs_file_aio_write,
        .open = cifs_open,
@@ -699,8 +682,7 @@ cifs_init_inodecache(void)
 static void
 cifs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(cifs_inode_cachep))
-               printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
+       kmem_cache_destroy(cifs_inode_cachep);
 }
 
 static int
@@ -778,13 +760,9 @@ static void
 cifs_destroy_request_bufs(void)
 {
        mempool_destroy(cifs_req_poolp);
-       if (kmem_cache_destroy(cifs_req_cachep))
-               printk(KERN_WARNING
-                      "cifs_destroy_request_cache: error not all structures were freed\n");
+       kmem_cache_destroy(cifs_req_cachep);
        mempool_destroy(cifs_sm_req_poolp);
-       if (kmem_cache_destroy(cifs_sm_req_cachep))
-               printk(KERN_WARNING
-                     "cifs_destroy_request_cache: cifs_small_rq free error\n");
+       kmem_cache_destroy(cifs_sm_req_cachep);
 }
 
 static int
@@ -819,13 +797,8 @@ static void
 cifs_destroy_mids(void)
 {
        mempool_destroy(cifs_mid_poolp);
-       if (kmem_cache_destroy(cifs_mid_cachep))
-               printk(KERN_WARNING
-                      "cifs_destroy_mids: error not all structures were freed\n");
-
-       if (kmem_cache_destroy(cifs_oplock_cachep))
-               printk(KERN_WARNING
-                      "error not all oplock structures were freed\n");
+       kmem_cache_destroy(cifs_mid_cachep);
+       kmem_cache_destroy(cifs_oplock_cachep);
 }
 
 static int cifs_oplock_thread(void * dummyarg)
index ddb012a68023fe0818d50670f2fb81a990dbab56..976a691c5a680561a97b1aede8840e292b23ce73 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/backing-dev.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <linux/mpage.h>
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
 #include <linux/smp_lock.h>
index b88147c1dc27f0df435b6251376a73b7dfc531cb..6b90ef98e4cfe9cdfcd224bdb0a2df202b66612f 100644 (file)
@@ -19,7 +19,6 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 #include <linux/fs.h>
-#include <linux/buffer_head.h>
 #include <linux/stat.h>
 #include <linux/pagemap.h>
 #include <asm/div64.h>
@@ -591,7 +590,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
 
        if (!rc) {
                if (direntry->d_inode)
-                       direntry->d_inode->i_nlink--;
+                       drop_nlink(direntry->d_inode);
        } else if (rc == -ENOENT) {
                d_drop(direntry);
        } else if (rc == -ETXTBSY) {
@@ -610,7 +609,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                        CIFSSMBClose(xid, pTcon, netfid);
                        if (direntry->d_inode)
-                               direntry->d_inode->i_nlink--;
+                               drop_nlink(direntry->d_inode);
                }
        } else if (rc == -EACCES) {
                /* try only if r/o attribute set in local lookup data? */
@@ -664,7 +663,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                        if (!rc) {
                                if (direntry->d_inode)
-                                       direntry->d_inode->i_nlink--;
+                                       drop_nlink(direntry->d_inode);
                        } else if (rc == -ETXTBSY) {
                                int oplock = FALSE;
                                __u16 netfid;
@@ -685,7 +684,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
                                        CIFSSMBClose(xid, pTcon, netfid);
                                        if (direntry->d_inode)
-                                               direntry->d_inode->i_nlink--;
+                                               drop_nlink(direntry->d_inode);
                                }
                        /* BB if rc = -ETXTBUSY goto the rename logic BB */
                        }
@@ -736,7 +735,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                cFYI(1, ("cifs_mkdir returned 0x%x", rc));
                d_drop(direntry);
        } else {
-               inode->i_nlink++;
+               inc_nlink(inode);
                if (pTcon->ses->capabilities & CAP_UNIX)
                        rc = cifs_get_inode_info_unix(&newinode, full_path,
                                                      inode->i_sb,xid);
@@ -817,9 +816,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
        if (!rc) {
-               inode->i_nlink--;
+               drop_nlink(inode);
                i_size_write(direntry->d_inode,0);
-               direntry->d_inode->i_nlink = 0;
+               clear_nlink(direntry->d_inode);
        }
 
        cifsInode = CIFS_I(direntry->d_inode);
index b0ea6687ab55e8116a4790a52682e24c71146c34..e34c7db00f6feccaba099b9604352e7745322a03 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
 #include "cifsproto.h"
@@ -74,7 +73,7 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
                        }
                        break;
 #ifdef CONFIG_CIFS_POSIX
-               case EXT2_IOC_GETFLAGS:
+               case FS_IOC_GETFLAGS:
                        if(CIFS_UNIX_EXTATTR_CAP & caps) {
                                if (pSMBFile == NULL)
                                        break;
@@ -82,12 +81,12 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
                                        &ExtAttrBits, &ExtAttrMask);
                                if(rc == 0)
                                        rc = put_user(ExtAttrBits &
-                                               EXT2_FL_USER_VISIBLE,
+                                               FS_FL_USER_VISIBLE,
                                                (int __user *)arg);
                        }
                        break;
 
-               case EXT2_IOC_SETFLAGS:
+               case FS_IOC_SETFLAGS:
                        if(CIFS_UNIX_EXTATTR_CAP & caps) {
                                if(get_user(ExtAttrBits,(int __user *)arg)) {
                                        rc = -EFAULT;
index 9aeb58a7d369380d3f81a5f63569c66405af2463..b27b34537bf23c2bf3bbc566c1155c3d331df7a1 100644 (file)
@@ -216,10 +216,9 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 
        if (allocation_size < end_of_file)
                cFYI(1, ("May be sparse file, allocation less than file size"));
-       cFYI(1, ("File Size %ld and blocks %llu and blocksize %ld",
+       cFYI(1, ("File Size %ld and blocks %llu",
                (unsigned long)tmp_inode->i_size,
-               (unsigned long long)tmp_inode->i_blocks,
-               tmp_inode->i_blksize));
+               (unsigned long long)tmp_inode->i_blocks));
        if (S_ISREG(tmp_inode->i_mode)) {
                cFYI(1, ("File inode"));
                tmp_inode->i_op = &cifs_file_inode_ops;
index 5597080cb8114a0ea0eb6f020f7fc285f37a1b57..95a54253c0479989ec20f047d4bd821ecd5adf30 100644 (file)
@@ -110,8 +110,6 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
                inode->i_nlink = attr->va_nlink;
        if (attr->va_size != -1)
                inode->i_size = attr->va_size;
-       if (attr->va_blocksize != -1)
-               inode->i_blksize = attr->va_blocksize;
        if (attr->va_size != -1)
                inode->i_blocks = (attr->va_size + 511) >> 9;
        if (attr->va_atime.tv_sec != -1) 
index 71f2ea632e5376168d5b8aa4f194604941021104..0102b28a15fb5f8230eea9904d04f481d3e4068c 100644 (file)
@@ -304,7 +304,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
        coda_dir_changed(dir_inode, 0);
        atomic_inc(&inode->i_count);
        d_instantiate(de, inode);
-       inode->i_nlink++;
+       inc_nlink(inode);
         
 out:
        unlock_kernel();
@@ -367,7 +367,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
         }
 
        coda_dir_changed(dir, 0);
-       de->d_inode->i_nlink--;
+       drop_nlink(de->d_inode);
        unlock_kernel();
 
         return 0;
@@ -394,7 +394,7 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
         }
 
        coda_dir_changed(dir, -1);
-       de->d_inode->i_nlink--;
+       drop_nlink(de->d_inode);
        d_delete(de);
        unlock_kernel();
 
@@ -513,7 +513,7 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
        ino_t ino;
        int ret, i;
 
-       vdir = (struct venus_dirent *)kmalloc(sizeof(*vdir), GFP_KERNEL);
+       vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
        if (!vdir) return -ENOMEM;
 
        i = filp->f_pos;
index 87f1dc8aa24b1c21f110f12701f0b8551e1a9b45..88d12332116489bd6dc2cb475dc8727cffe88a18 100644 (file)
@@ -80,8 +80,7 @@ int coda_init_inodecache(void)
 
 void coda_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(coda_inode_cachep))
-               printk(KERN_INFO "coda_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(coda_inode_cachep);
 }
 
 static int coda_remount(struct super_block *sb, int *flags, char *data)
index ce982f6e8c80270be3fd23f8f9553c486626986e..13fb08d096c436f5caba903abd57420935baa0cd 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
-#include <linux/acct.h>
+#include <linux/tsacct_kern.h>
 #include <linux/mm.h>
 
 #include <net/sock.h>          /* siocdevprivate_ioctl */
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/ioctls.h>
-
-extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+#include "internal.h"
 
 int compat_log = 1;
 
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
 int compat_printk(const char *fmt, ...)
 {
        va_list ap;
@@ -69,6 +70,8 @@ int compat_printk(const char *fmt, ...)
        return ret;
 }
 
+#include "read_write.h"
+
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -313,9 +316,6 @@ out:
 #define IOCTL_HASHSIZE 256
 static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
 
-extern struct ioctl_trans ioctl_start[];
-extern int ioctl_table_size;
-
 static inline unsigned long ioctl32_hash(unsigned long cmd)
 {
        return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
@@ -838,8 +838,6 @@ static int do_nfs4_super_data_conv(void *raw_data)
        return 0;
 }
 
-extern int copy_mount_options (const void __user *, unsigned long *);
-
 #define SMBFS_NAME      "smbfs"
 #define NCPFS_NAME      "ncpfs"
 #define NFS4_NAME      "nfs4"
@@ -1153,9 +1151,6 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
                               const struct compat_iovec __user *uvector,
                               unsigned long nr_segs, loff_t *pos)
 {
-       typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
-       typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
-
        compat_ssize_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov=iovstack, *vector;
@@ -1238,39 +1233,18 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        fnv = NULL;
        if (type == READ) {
                fn = file->f_op->read;
-               fnv = file->f_op->readv;
+               fnv = file->f_op->aio_read;
        } else {
                fn = (io_fn_t)file->f_op->write;
-               fnv = file->f_op->writev;
-       }
-       if (fnv) {
-               ret = fnv(file, iov, nr_segs, pos);
-               goto out;
+               fnv = file->f_op->aio_write;
        }
 
-       /* Do it by hand, with file-ops */
-       ret = 0;
-       vector = iov;
-       while (nr_segs > 0) {
-               void __user * base;
-               size_t len;
-               ssize_t nr;
-
-               base = vector->iov_base;
-               len = vector->iov_len;
-               vector++;
-               nr_segs--;
-
-               nr = fn(file, base, len, pos);
+       if (fnv)
+               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
+                                               pos, fnv);
+       else
+               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
 
-               if (nr < 0) {
-                       if (!ret) ret = nr;
-                       break;
-               }
-               ret += nr;
-               if (nr != len)
-                       break;
-       }
 out:
        if (iov != iovstack)
                kfree(iov);
@@ -1298,7 +1272,7 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign
                goto out;
 
        ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
+       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
                goto out;
 
        ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos);
@@ -1321,7 +1295,7 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig
                goto out;
 
        ret = -EINVAL;
-       if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
+       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
                goto out;
 
        ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos);
index 4063a939697768d990faa971a4488efe21f80dcb..27ca1aa305625fbc19b0122b7875d75f06125c53 100644 (file)
 #include <linux/if_pppox.h>
 #include <linux/mtio.h>
 #include <linux/cdrom.h>
-#include <linux/loop.h>
 #include <linux/auto_fs.h>
 #include <linux/auto_fs4.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
 #include <linux/fb.h>
-#include <linux/ext2_fs.h>
-#include <linux/ext3_jbd.h>
-#include <linux/ext3_fs.h>
 #include <linux/videodev.h>
 #include <linux/netdevice.h>
 #include <linux/raw.h>
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/serial.h>
-#include <linux/reiserfs_fs.h>
 #include <linux/if_tun.h>
 #include <linux/ctype.h>
 #include <linux/ioctl32.h>
 #include <linux/syscalls.h>
-#include <linux/ncp_fs.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
 #include <linux/wireless.h>
 #include <linux/nbd.h>
 #include <linux/random.h>
 #include <linux/filter.h>
-#include <linux/msdos_fs.h>
 #include <linux/pktcdvd.h>
 
 #include <linux/hiddev.h>
 #include <linux/dvb/video.h>
 #include <linux/lp.h>
 
-/* Aiee. Someone does not find a difference between int and long */
-#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
-#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
-#define EXT3_IOC32_GETVERSION             _IOR('f', 3, int)
-#define EXT3_IOC32_SETVERSION             _IOW('f', 4, int)
-#define EXT3_IOC32_GETRSVSZ               _IOR('f', 5, int)
-#define EXT3_IOC32_SETRSVSZ               _IOW('f', 6, int)
-#define EXT3_IOC32_GROUP_EXTEND           _IOW('f', 7, unsigned int)
-#ifdef CONFIG_JBD_DEBUG
-#define EXT3_IOC32_WAIT_FOR_READONLY      _IOR('f', 99, int)
-#endif
-
-#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
-#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
-
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
                              unsigned long arg, struct file *f)
 {
@@ -176,34 +154,6 @@ static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
        return err;
 }
 
-static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       /* These are just misnamed, they actually get/put from/to user an int */
-       switch (cmd) {
-       case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
-       case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
-       case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
-       case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
-       }
-       return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
-}
-
-static int do_ext3_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       /* These are just misnamed, they actually get/put from/to user an int */
-       switch (cmd) {
-       case EXT3_IOC32_GETVERSION: cmd = EXT3_IOC_GETVERSION; break;
-       case EXT3_IOC32_SETVERSION: cmd = EXT3_IOC_SETVERSION; break;
-       case EXT3_IOC32_GETRSVSZ: cmd = EXT3_IOC_GETRSVSZ; break;
-       case EXT3_IOC32_SETRSVSZ: cmd = EXT3_IOC_SETRSVSZ; break;
-       case EXT3_IOC32_GROUP_EXTEND: cmd = EXT3_IOC_GROUP_EXTEND; break;
-#ifdef CONFIG_JBD_DEBUG
-       case EXT3_IOC32_WAIT_FOR_READONLY: cmd = EXT3_IOC_WAIT_FOR_READONLY; break;
-#endif
-       }
-       return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
-}
-
 struct compat_video_event {
        int32_t         type;
        compat_time_t   timestamp;
@@ -694,6 +644,7 @@ out:
 }
 #endif
 
+#ifdef CONFIG_BLOCK
 struct hd_geometry32 {
        unsigned char heads;
        unsigned char sectors;
@@ -918,6 +869,7 @@ static int sg_grt_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
        }
        return err;
 }
+#endif /* CONFIG_BLOCK */
 
 struct sock_fprog32 {
        unsigned short  len;
@@ -1041,6 +993,7 @@ static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 }
 
 
+#ifdef CONFIG_BLOCK
 struct mtget32 {
        compat_long_t   mt_type;
        compat_long_t   mt_resid;
@@ -1213,73 +1166,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
 
        return err;
 }
-
-struct loop_info32 {
-       compat_int_t    lo_number;      /* ioctl r/o */
-       compat_dev_t    lo_device;      /* ioctl r/o */
-       compat_ulong_t  lo_inode;       /* ioctl r/o */
-       compat_dev_t    lo_rdevice;     /* ioctl r/o */
-       compat_int_t    lo_offset;
-       compat_int_t    lo_encrypt_type;
-       compat_int_t    lo_encrypt_key_size;    /* ioctl w/o */
-       compat_int_t    lo_flags;       /* ioctl r/o */
-       char            lo_name[LO_NAME_SIZE];
-       unsigned char   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
-       compat_ulong_t  lo_init[2];
-       char            reserved[4];
-};
-
-static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       mm_segment_t old_fs = get_fs();
-       struct loop_info l;
-       struct loop_info32 __user *ul;
-       int err = -EINVAL;
-
-       ul = compat_ptr(arg);
-       switch(cmd) {
-       case LOOP_SET_STATUS:
-               err = get_user(l.lo_number, &ul->lo_number);
-               err |= __get_user(l.lo_device, &ul->lo_device);
-               err |= __get_user(l.lo_inode, &ul->lo_inode);
-               err |= __get_user(l.lo_rdevice, &ul->lo_rdevice);
-               err |= __copy_from_user(&l.lo_offset, &ul->lo_offset,
-                       8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
-               if (err) {
-                       err = -EFAULT;
-               } else {
-                       set_fs (KERNEL_DS);
-                       err = sys_ioctl (fd, cmd, (unsigned long)&l);
-                       set_fs (old_fs);
-               }
-               break;
-       case LOOP_GET_STATUS:
-               set_fs (KERNEL_DS);
-               err = sys_ioctl (fd, cmd, (unsigned long)&l);
-               set_fs (old_fs);
-               if (!err) {
-                       err = put_user(l.lo_number, &ul->lo_number);
-                       err |= __put_user(l.lo_device, &ul->lo_device);
-                       err |= __put_user(l.lo_inode, &ul->lo_inode);
-                       err |= __put_user(l.lo_rdevice, &ul->lo_rdevice);
-                       err |= __copy_to_user(&ul->lo_offset, &l.lo_offset,
-                               (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
-                       if (err)
-                               err = -EFAULT;
-               }
-               break;
-       default: {
-               static int count;
-               if (++count <= 20)
-                       printk("%s: Unknown loop ioctl cmd, fd(%d) "
-                              "cmd(%08x) arg(%08lx)\n",
-                              __FUNCTION__, fd, cmd, arg);
-       }
-       }
-       return err;
-}
-
-extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
+#endif /* CONFIG_BLOCK */
 
 #ifdef CONFIG_VT
 
@@ -1607,6 +1494,7 @@ ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
        return -EINVAL;
 }
 
+#ifdef CONFIG_BLOCK
 static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
        /* The mkswap binary hard codes it to Intel value :-((( */
@@ -1641,12 +1529,14 @@ static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
 
        return sys_ioctl(fd, cmd, (unsigned long)a);
 }
+#endif
 
 static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
        return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
 }
 
+#ifdef CONFIG_BLOCK
 /* Fix sizeof(sizeof()) breakage */
 #define BLKBSZGET_32   _IOR(0x12,112,int)
 #define BLKBSZSET_32   _IOW(0x12,113,int)
@@ -1667,6 +1557,7 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
 {
        return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg));
 }
+#endif
 
 /* Bluetooth ioctls */
 #define HCIUARTSETPROTO        _IOW('U', 200, int)
@@ -1687,6 +1578,7 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
 #define HIDPGETCONNLIST        _IOR('H', 210, int)
 #define HIDPGETCONNINFO        _IOR('H', 211, int)
 
+#ifdef CONFIG_BLOCK
 struct floppy_struct32 {
        compat_uint_t   size;
        compat_uint_t   sect;
@@ -2011,6 +1903,7 @@ out:
        kfree(karg);
        return err;
 }
+#endif
 
 struct mtd_oob_buf32 {
        u_int32_t start;
@@ -2052,61 +1945,7 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
        return err;
 }      
 
-#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
-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;
-
-        return 0;
-}
-
-static int vfat_ioctl32(unsigned fd, 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];
-
-       switch(cmd)
-       {
-               case VFAT_IOCTL_READDIR_BOTH32:
-                       cmd = VFAT_IOCTL_READDIR_BOTH;
-                       break;
-               case VFAT_IOCTL_READDIR_SHORT32:
-                       cmd = VFAT_IOCTL_READDIR_SHORT;
-                       break;
-       }
-
-       set_fs(KERNEL_DS);
-       ret = sys_ioctl(fd,cmd,(unsigned long)&d);
-       set_fs(oldfs);
-       if (ret >= 0) {
-               ret |= put_dirent32(&d[0], p);
-               ret |= put_dirent32(&d[1], p + 1);
-       }
-       return ret;
-}
-
-#define REISERFS_IOC_UNPACK32               _IOW(0xCD,1,int)
-
-static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr)
-{
-        if (cmd == REISERFS_IOC_UNPACK32)
-                cmd = REISERFS_IOC_UNPACK;
-
-        return sys_ioctl(fd,cmd,ptr);
-}
-
+#ifdef CONFIG_BLOCK
 struct raw32_config_request
 {
         compat_int_t    raw_minor;
@@ -2171,6 +2010,7 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
         }
         return ret;
 }
+#endif /* CONFIG_BLOCK */
 
 struct serial_struct32 {
         compat_int_t    type;
@@ -2507,193 +2347,6 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
        }
 }
 
-#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
-struct ncp_ioctl_request_32 {
-       u32 function;
-       u32 size;
-       compat_caddr_t data;
-};
-
-struct ncp_fs_info_v2_32 {
-       s32 version;
-       u32 mounted_uid;
-       u32 connection;
-       u32 buffer_size;
-
-       u32 volume_number;
-       u32 directory_id;
-
-       u32 dummy1;
-       u32 dummy2;
-       u32 dummy3;
-};
-
-struct ncp_objectname_ioctl_32
-{
-       s32             auth_type;
-       u32             object_name_len;
-       compat_caddr_t  object_name;    /* an userspace data, in most cases user name */
-};
-
-struct ncp_privatedata_ioctl_32
-{
-       u32             len;
-       compat_caddr_t  data;           /* ~1000 for NDS */
-};
-
-#define        NCP_IOC_NCPREQUEST_32           _IOR('n', 1, struct ncp_ioctl_request_32)
-#define NCP_IOC_GETMOUNTUID2_32                _IOW('n', 2, u32)
-#define NCP_IOC_GET_FS_INFO_V2_32      _IOWR('n', 4, struct ncp_fs_info_v2_32)
-#define NCP_IOC_GETOBJECTNAME_32       _IOWR('n', 9, struct ncp_objectname_ioctl_32)
-#define NCP_IOC_SETOBJECTNAME_32       _IOR('n', 9, struct ncp_objectname_ioctl_32)
-#define NCP_IOC_GETPRIVATEDATA_32      _IOWR('n', 10, struct ncp_privatedata_ioctl_32)
-#define NCP_IOC_SETPRIVATEDATA_32      _IOR('n', 10, struct ncp_privatedata_ioctl_32)
-
-static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct ncp_ioctl_request_32 n32;
-       struct ncp_ioctl_request __user *p = compat_alloc_user_space(sizeof(*p));
-
-       if (copy_from_user(&n32, compat_ptr(arg), sizeof(n32)) ||
-           put_user(n32.function, &p->function) ||
-           put_user(n32.size, &p->size) ||
-           put_user(compat_ptr(n32.data), &p->data))
-               return -EFAULT;
-
-       return sys_ioctl(fd, NCP_IOC_NCPREQUEST, (unsigned long)p);
-}
-
-static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       mm_segment_t old_fs = get_fs();
-       __kernel_uid_t kuid;
-       int err;
-
-       cmd = NCP_IOC_GETMOUNTUID2;
-
-       set_fs(KERNEL_DS);
-       err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
-       set_fs(old_fs);
-
-       if (!err)
-               err = put_user(kuid,
-                              (unsigned int __user *) compat_ptr(arg));
-
-       return err;
-}
-
-static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       mm_segment_t old_fs = get_fs();
-       struct ncp_fs_info_v2_32 n32;
-       struct ncp_fs_info_v2 n;
-       int err;
-
-       if (copy_from_user(&n32, compat_ptr(arg), sizeof(n32)))
-               return -EFAULT;
-       if (n32.version != NCP_GET_FS_INFO_VERSION_V2)
-               return -EINVAL;
-       n.version = NCP_GET_FS_INFO_VERSION_V2;
-
-       set_fs(KERNEL_DS);
-       err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n);
-       set_fs(old_fs);
-
-       if (!err) {
-               n32.version = n.version;
-               n32.mounted_uid = n.mounted_uid;
-               n32.connection = n.connection;
-               n32.buffer_size = n.buffer_size;
-               n32.volume_number = n.volume_number;
-               n32.directory_id = n.directory_id;
-               n32.dummy1 = n.dummy1;
-               n32.dummy2 = n.dummy2;
-               n32.dummy3 = n.dummy3;
-               err = copy_to_user(compat_ptr(arg), &n32, sizeof(n32)) ? -EFAULT : 0;
-       }
-       return err;
-}
-
-static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct ncp_objectname_ioctl_32 n32, __user *p32 = compat_ptr(arg);
-       struct ncp_objectname_ioctl __user *p = compat_alloc_user_space(sizeof(*p));
-       s32 auth_type;
-       u32 name_len;
-       int err;
-
-       if (copy_from_user(&n32, p32, sizeof(n32)) ||
-           put_user(n32.object_name_len, &p->object_name_len) ||
-           put_user(compat_ptr(n32.object_name), &p->object_name))
-               return -EFAULT;
-
-       err = sys_ioctl(fd, NCP_IOC_GETOBJECTNAME, (unsigned long)p);
-        if (err)
-               return err;
-
-       if (get_user(auth_type, &p->auth_type) ||
-           put_user(auth_type, &p32->auth_type) ||
-           get_user(name_len, &p->object_name_len) ||
-           put_user(name_len, &p32->object_name_len))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct ncp_objectname_ioctl_32 n32, __user *p32 = compat_ptr(arg);
-       struct ncp_objectname_ioctl __user *p = compat_alloc_user_space(sizeof(*p));
-
-       if (copy_from_user(&n32, p32, sizeof(n32)) ||
-           put_user(n32.auth_type, &p->auth_type) ||
-           put_user(n32.object_name_len, &p->object_name_len) ||
-           put_user(compat_ptr(n32.object_name), &p->object_name))
-               return -EFAULT;
-
-       return sys_ioctl(fd, NCP_IOC_SETOBJECTNAME, (unsigned long)p);
-}
-
-static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct ncp_privatedata_ioctl_32 n32, __user *p32 = compat_ptr(arg);
-       struct ncp_privatedata_ioctl __user *p =
-               compat_alloc_user_space(sizeof(*p));
-       u32 len;
-       int err;
-
-       if (copy_from_user(&n32, p32, sizeof(n32)) ||
-           put_user(n32.len, &p->len) ||
-           put_user(compat_ptr(n32.data), &p->data))
-               return -EFAULT;
-
-       err = sys_ioctl(fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)p);
-        if (err)
-               return err;
-
-       if (get_user(len, &p->len) ||
-           put_user(len, &p32->len))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct ncp_privatedata_ioctl_32 n32;
-       struct ncp_privatedata_ioctl_32 __user *p32 = compat_ptr(arg);
-       struct ncp_privatedata_ioctl __user *p =
-               compat_alloc_user_space(sizeof(*p));
-
-       if (copy_from_user(&n32, p32, sizeof(n32)) ||
-           put_user(n32.len, &p->len) ||
-           put_user(compat_ptr(n32.data), &p->data))
-               return -EFAULT;
-
-       return sys_ioctl(fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)p);
-}
-#endif
-
 static int
 lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -2777,6 +2430,7 @@ HANDLE_IOCTL(SIOCBRDELIF, dev_ifsioc)
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
 #endif
+#ifdef CONFIG_BLOCK
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
 HANDLE_IOCTL(BLKRAGET, w_long)
 HANDLE_IOCTL(BLKGETSIZE, w_long)
@@ -2802,16 +2456,17 @@ HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
 HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
 HANDLE_IOCTL(SG_IO,sg_ioctl_trans)
 HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans)
+#endif
 HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
+#ifdef CONFIG_BLOCK
 HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
-HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
-HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
+#endif
 #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
 HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
 #ifdef CONFIG_VT
@@ -2821,19 +2476,6 @@ HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
 HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
 HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
 #endif
-HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl)
-HANDLE_IOCTL(EXT3_IOC32_GETVERSION, do_ext3_ioctl)
-HANDLE_IOCTL(EXT3_IOC32_SETVERSION, do_ext3_ioctl)
-HANDLE_IOCTL(EXT3_IOC32_GETRSVSZ, do_ext3_ioctl)
-HANDLE_IOCTL(EXT3_IOC32_SETRSVSZ, do_ext3_ioctl)
-HANDLE_IOCTL(EXT3_IOC32_GROUP_EXTEND, do_ext3_ioctl)
-COMPATIBLE_IOCTL(EXT3_IOC_GROUP_ADD)
-#ifdef CONFIG_JBD_DEBUG
-HANDLE_IOCTL(EXT3_IOC32_WAIT_FOR_READONLY, do_ext3_ioctl)
-#endif
 /* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
 HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
@@ -2863,16 +2505,14 @@ HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
 HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
 HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
 /* block stuff */
+#ifdef CONFIG_BLOCK
 HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
 HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
 HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64)
-/* vfat */
-HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
-HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
-HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32)
 /* Raw devices */
 HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
 HANDLE_IOCTL(RAW_GETBIND, raw_ioctl)
+#endif
 /* Serial */
 HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl)
 HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
@@ -2920,16 +2560,6 @@ HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl)
 HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl)
 HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl)
 
-#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
-HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
-HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2)
-HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2)
-HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname)
-HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname)
-HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata)
-HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
-#endif
-
 /* dvb */
 HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event)
 HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture)
index 816e8ef645605a5cdd505b7bdd6be8e8bf38345a..8a3b6a1a6ad139aa50ba1da2e10bdf6cd0de2980 100644 (file)
@@ -139,7 +139,7 @@ static int init_dir(struct inode * inode)
        inode->i_fop = &configfs_dir_operations;
 
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-       inode->i_nlink++;
+       inc_nlink(inode);
        return 0;
 }
 
@@ -169,7 +169,7 @@ static int create_dir(struct config_item * k, struct dentry * p,
        if (!error) {
                error = configfs_create(d, mode, init_dir);
                if (!error) {
-                       p->d_inode->i_nlink++;
+                       inc_nlink(p->d_inode);
                        (d)->d_op = &configfs_dentry_ops;
                } else {
                        struct configfs_dirent *sd = d->d_fsdata;
index f499803743e04add3d576dc919e0a54752d00ba1..85105e50f7db668702b36ea78a32feaa6ef12593 100644 (file)
@@ -274,9 +274,8 @@ static int check_perm(struct inode * inode, struct file * file)
        /* No error? Great, allocate a buffer for the file, and store it
         * it in file->private_data for easy access.
         */
-       buffer = kmalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
+       buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
        if (buffer) {
-               memset(buffer,0,sizeof(struct configfs_buffer));
                init_MUTEX(&buffer->sem);
                buffer->needs_read_fill = 1;
                buffer->ops = ops;
index e14488ca6411fef8db1fb86e1252f49b99f9b2a7..fb18917954a91f95643b38352adab17a42e98600 100644 (file)
@@ -76,11 +76,10 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
 
        if (!sd_iattr) {
                /* setting attributes for the first time, allocate now */
-               sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+               sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
                if (!sd_iattr)
                        return -ENOMEM;
                /* assign default attributes */
-               memset(sd_iattr, 0, sizeof(struct iattr));
                sd_iattr->ia_mode = sd->s_mode;
                sd_iattr->ia_uid = 0;
                sd_iattr->ia_gid = 0;
@@ -136,7 +135,6 @@ struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
 {
        struct inode * inode = new_inode(configfs_sb);
        if (inode) {
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &configfs_aops;
                inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
index 3e5fe843e1df7588564dad9f3d5140318c6b84b6..68bd5c93ca524a089d1881bbcb9b5da4ef563b74 100644 (file)
@@ -84,7 +84,7 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent)
                inode->i_op = &configfs_dir_inode_operations;
                inode->i_fop = &configfs_dir_operations;
                /* directory inodes start off with i_nlink == 2 (for "." entry) */
-               inode->i_nlink++;
+               inc_nlink(inode);
        } else {
                pr_debug("configfs: could not get root inode\n");
                return -ENOMEM;
index 223c0431042deaa8fb77aa99626100338e546f4e..a624c3ec81892870545cd80bea3f22c91069c2ab 100644 (file)
@@ -73,7 +73,6 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque)
        inode->i_uid = cramfs_inode->uid;
        inode->i_size = cramfs_inode->size;
        inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_gid = cramfs_inode->gid;
        /* Struct copy intentional */
        inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
@@ -242,11 +241,10 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_flags |= MS_RDONLY;
 
-       sbi = kmalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct cramfs_sb_info));
 
        /* Invalidate the read buffers on mount: think disk change.. */
        mutex_lock(&read_mutex);
@@ -545,8 +543,15 @@ static struct file_system_type cramfs_fs_type = {
 
 static int __init init_cramfs_fs(void)
 {
-       cramfs_uncompress_init();
-       return register_filesystem(&cramfs_fs_type);
+       int rv;
+
+       rv = cramfs_uncompress_init();
+       if (rv < 0)
+               return rv;
+       rv = register_filesystem(&cramfs_fs_type);
+       if (rv < 0)
+               cramfs_uncompress_exit();
+       return rv;
 }
 
 static void __exit exit_cramfs_fs(void)
index 8def89f2c4383b052490eeba366241adc07ccaa8..fc3ccb74626ffb3a581da4049c703242352dedfa 100644 (file)
@@ -68,11 +68,10 @@ int cramfs_uncompress_init(void)
        return 0;
 }
 
-int cramfs_uncompress_exit(void)
+void cramfs_uncompress_exit(void)
 {
        if (!--initialized) {
                zlib_inflateEnd(&stream);
                vfree(stream.workspace);
        }
-       return 0;
 }
index 17b392a2049ebfb9b39103ecedbd9fe6ec884828..fc2faa44f8d185b6be9b8600a4ffb9991d5b980f 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/seqlock.h>
 #include <linux/swap.h>
 #include <linux/bootmem.h>
+#include "internal.h"
 
 
 int sysctl_vfs_cache_pressure __read_mostly = 100;
@@ -1877,9 +1878,6 @@ kmem_cache_t *filp_cachep __read_mostly;
 
 EXPORT_SYMBOL(d_genocide);
 
-extern void bdev_cache_init(void);
-extern void chrdev_init(void);
-
 void __init vfs_caches_init_early(void)
 {
        dcache_init_early();
index e4b430552c88055c0d1f6ccf9e1c58f5a68f9f91..bf3901ab1744b25355ca54ea82deb578f8aeffc0 100644 (file)
@@ -32,8 +32,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
 
 static int default_open(struct inode *inode, struct file *file)
 {
-       if (inode->u.generic_ip)
-               file->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               file->private_data = inode->i_private;
 
        return 0;
 }
index 3ca268d2e5a228c40bf647fe21059cfb7a1506a0..ecf3da9edf21ab65a1a291a5edf8836dcdcaa520 100644 (file)
@@ -40,7 +40,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
@@ -55,7 +54,7 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
                        inode->i_fop = &simple_dir_operations;
 
                        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        break;
                }
        }
@@ -88,7 +87,7 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
        res = debugfs_mknod(dir, dentry, mode, 0);
        if (!res)
-               dir->i_nlink++;
+               inc_nlink(dir);
        return res;
 }
 
@@ -168,7 +167,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
  *          directory dentry if set.  If this paramater is NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @data: a pointer to something that the caller will want to get to later
- *        on.  The inode.u.generic_ip pointer will point to this value on
+ *        on.  The inode.i_private pointer will point to this value on
  *        the open() call.
  * @fops: a pointer to a struct file_operations that should be used for
  *        this file.
@@ -209,7 +208,7 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
 
        if (dentry->d_inode) {
                if (data)
-                       dentry->d_inode->u.generic_ip = data;
+                       dentry->d_inode->i_private = data;
                if (fops)
                        dentry->d_inode->i_fop = fops;
        }
index f7aef5bb584a7deb5736f556da5b9155b754a760..5f7b5a6025bfec943dc390f02bcaa92ef7201b1e 100644 (file)
@@ -113,7 +113,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
        inode->i_ino = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_blocks = 0;
-       inode->i_blksize = 1024;
        inode->i_uid = inode->i_gid = 0;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
        inode->i_op = &simple_dir_inode_operations;
@@ -172,12 +171,11 @@ int devpts_pty_new(struct tty_struct *tty)
                return -ENOMEM;
 
        inode->i_ino = number+2;
-       inode->i_blksize = 1024;
        inode->i_uid = config.setuid ? config.uid : current->fsuid;
        inode->i_gid = config.setgid ? config.gid : current->fsgid;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        init_special_inode(inode, S_IFCHR|config.mode, device);
-       inode->u.generic_ip = tty;
+       inode->i_private = tty;
 
        dentry = get_node(number);
        if (!IS_ERR(dentry) && !dentry->d_inode)
@@ -196,7 +194,7 @@ struct tty_struct *devpts_get_tty(int number)
        tty = NULL;
        if (!IS_ERR(dentry)) {
                if (dentry->d_inode)
-                       tty = dentry->d_inode->u.generic_ip;
+                       tty = dentry->d_inode->i_private;
                dput(dentry);
        }
 
index 0122a279106a9dd4a0475557901471be5c428546..9af789567e513b4575c9066711b8b6f595c949c7 100644 (file)
@@ -834,6 +834,9 @@ static void print_warning(struct dquot *dquot, const char warntype)
        if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
                return;
 
+       mutex_lock(&tty_mutex);
+       if (!current->signal->tty)
+               goto out_lock;
        tty_write_message(current->signal->tty, dquot->dq_sb->s_id);
        if (warntype == ISOFTWARN || warntype == BSOFTWARN)
                tty_write_message(current->signal->tty, ": warning, ");
@@ -861,6 +864,8 @@ static void print_warning(struct dquot *dquot, const char warntype)
                        break;
        }
        tty_write_message(current->signal->tty, msg);
+out_lock:
+       mutex_unlock(&tty_mutex);
 }
 
 static inline void flush_warnings(struct dquot **dquots, char *warntype)
index 8ac2462ae5dd28b45b7e5e27e5216df85be43e9f..b3f50651eb6bd1a979a2d2442c4294b48141780b 100644 (file)
@@ -90,8 +90,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(efs_inode_cachep))
-               printk(KERN_INFO "efs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(efs_inode_cachep);
 }
 
 static void efs_put_super(struct super_block *s)
@@ -248,11 +247,10 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
        struct buffer_head *bh;
        struct inode *root;
 
-       sb = kmalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
+       sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
        if (!sb)
                return -ENOMEM;
        s->s_fs_info = sb;
-       memset(sb, 0, sizeof(struct efs_sb_info));
  
        s->s_magic              = EFS_SUPER_MAGIC;
        if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
index 3a3567433b921795c9ba6a7fe879a9b6760c923f..8d544334bcd22d216b057620900834e73b756698 100644 (file)
@@ -1590,7 +1590,6 @@ static struct inode *ep_eventpoll_inode(void)
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blksize = PAGE_SIZE;
        return inode;
 
 eexit_1:
index 54135df2a9662cbf1f222ee468067812f52e1f72..6270f8f20a638195b1e1c1fc59bba00d8f4d2bd3 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -46,7 +46,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/rmap.h>
-#include <linux/acct.h>
+#include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
 
@@ -58,7 +58,7 @@
 #endif
 
 int core_uses_pid;
-char core_pattern[65] = "core";
+char core_pattern[128] = "core";
 int suid_dumpable = 0;
 
 EXPORT_SYMBOL(suid_dumpable);
@@ -595,7 +595,7 @@ static int de_thread(struct task_struct *tsk)
        if (!newsighand)
                return -ENOMEM;
 
-       if (thread_group_empty(current))
+       if (thread_group_empty(tsk))
                goto no_thread_group;
 
        /*
@@ -620,17 +620,17 @@ static int de_thread(struct task_struct *tsk)
         * Reparenting needs write_lock on tasklist_lock,
         * so it is safe to do it under read_lock.
         */
-       if (unlikely(current->group_leader == child_reaper))
-               child_reaper = current;
+       if (unlikely(tsk->group_leader == child_reaper))
+               child_reaper = tsk;
 
-       zap_other_threads(current);
+       zap_other_threads(tsk);
        read_unlock(&tasklist_lock);
 
        /*
         * Account for the thread group leader hanging around:
         */
        count = 1;
-       if (!thread_group_leader(current)) {
+       if (!thread_group_leader(tsk)) {
                count = 2;
                /*
                 * The SIGALRM timer survives the exec, but needs to point
@@ -639,14 +639,14 @@ static int de_thread(struct task_struct *tsk)
                 * synchronize with any firing (by calling del_timer_sync)
                 * before we can safely let the old group leader die.
                 */
-               sig->tsk = current;
+               sig->tsk = tsk;
                spin_unlock_irq(lock);
                if (hrtimer_cancel(&sig->real_timer))
                        hrtimer_restart(&sig->real_timer);
                spin_lock_irq(lock);
        }
        while (atomic_read(&sig->count) > count) {
-               sig->group_exit_task = current;
+               sig->group_exit_task = tsk;
                sig->notify_count = count;
                __set_current_state(TASK_UNINTERRUPTIBLE);
                spin_unlock_irq(lock);
@@ -662,13 +662,13 @@ static int de_thread(struct task_struct *tsk)
         * do is to wait for the thread group leader to become inactive,
         * and to assume its PID:
         */
-       if (!thread_group_leader(current)) {
+       if (!thread_group_leader(tsk)) {
                /*
                 * Wait for the thread group leader to be a zombie.
                 * It should already be zombie at this point, most
                 * of the time.
                 */
-               leader = current->group_leader;
+               leader = tsk->group_leader;
                while (leader->exit_state != EXIT_ZOMBIE)
                        yield();
 
@@ -682,12 +682,12 @@ static int de_thread(struct task_struct *tsk)
                 * When we take on its identity by switching to its PID, we
                 * also take its birthdate (always earlier than our own).
                 */
-               current->start_time = leader->start_time;
+               tsk->start_time = leader->start_time;
 
                write_lock_irq(&tasklist_lock);
 
-               BUG_ON(leader->tgid != current->tgid);
-               BUG_ON(current->pid == current->tgid);
+               BUG_ON(leader->tgid != tsk->tgid);
+               BUG_ON(tsk->pid == tsk->tgid);
                /*
                 * An exec() starts a new thread group with the
                 * TGID of the previous thread group. Rehash the
@@ -696,24 +696,21 @@ static int de_thread(struct task_struct *tsk)
                 */
 
                /* Become a process group leader with the old leader's pid.
-                * Note: The old leader also uses thispid until release_task
+                * The old leader becomes a thread of the this thread group.
+                * Note: The old leader also uses this pid until release_task
                 *       is called.  Odd but simple and correct.
                 */
-               detach_pid(current, PIDTYPE_PID);
-               current->pid = leader->pid;
-               attach_pid(current, PIDTYPE_PID,  current->pid);
-               attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
-               attach_pid(current, PIDTYPE_SID,  current->signal->session);
-               list_replace_rcu(&leader->tasks, &current->tasks);
+               detach_pid(tsk, PIDTYPE_PID);
+               tsk->pid = leader->pid;
+               attach_pid(tsk, PIDTYPE_PID,  tsk->pid);
+               transfer_pid(leader, tsk, PIDTYPE_PGID);
+               transfer_pid(leader, tsk, PIDTYPE_SID);
+               list_replace_rcu(&leader->tasks, &tsk->tasks);
 
-               current->group_leader = current;
-               leader->group_leader = current;
+               tsk->group_leader = tsk;
+               leader->group_leader = tsk;
 
-               /* Reduce leader to a thread */
-               detach_pid(leader, PIDTYPE_PGID);
-               detach_pid(leader, PIDTYPE_SID);
-
-               current->exit_signal = SIGCHLD;
+               tsk->exit_signal = SIGCHLD;
 
                BUG_ON(leader->exit_state != EXIT_ZOMBIE);
                leader->exit_state = EXIT_DEAD;
@@ -753,7 +750,7 @@ no_thread_group:
                spin_lock(&oldsighand->siglock);
                spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING);
 
-               rcu_assign_pointer(current->sighand, newsighand);
+               rcu_assign_pointer(tsk->sighand, newsighand);
                recalc_sigpending();
 
                spin_unlock(&newsighand->siglock);
@@ -764,7 +761,7 @@ no_thread_group:
                        kmem_cache_free(sighand_cachep, oldsighand);
        }
 
-       BUG_ON(!thread_group_leader(current));
+       BUG_ON(!thread_group_leader(tsk));
        return 0;
 }
        
@@ -901,8 +898,7 @@ int flush_old_exec(struct linux_binprm * bprm)
        return 0;
 
 mmap_failed:
-       put_files_struct(current->files);
-       current->files = files;
+       reset_files_struct(current, files);
 out:
        return retval;
 }
@@ -1467,6 +1463,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        int retval = 0;
        int fsuid = current->fsuid;
        int flag = 0;
+       int ispipe = 0;
 
        binfmt = current->binfmt;
        if (!binfmt || !binfmt->core_dump)
@@ -1508,22 +1505,34 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
        lock_kernel();
        format_corename(corename, core_pattern, signr);
        unlock_kernel();
-       file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
+       if (corename[0] == '|') {
+               /* SIGPIPE can happen, but it's just never processed */
+               if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
+                       printk(KERN_INFO "Core dump to %s pipe failed\n",
+                              corename);
+                       goto fail_unlock;
+               }
+               ispipe = 1;
+       } else
+               file = filp_open(corename,
+                                O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
        if (IS_ERR(file))
                goto fail_unlock;
        inode = file->f_dentry->d_inode;
        if (inode->i_nlink > 1)
                goto close_fail;        /* multiple links - don't dump */
-       if (d_unhashed(file->f_dentry))
+       if (!ispipe && d_unhashed(file->f_dentry))
                goto close_fail;
 
-       if (!S_ISREG(inode->i_mode))
+       /* AK: actually i see no reason to not allow this for named pipes etc.,
+          but keep the previous behaviour for now. */
+       if (!ispipe && !S_ISREG(inode->i_mode))
                goto close_fail;
        if (!file->f_op)
                goto close_fail;
        if (!file->f_op->write)
                goto close_fail;
-       if (do_truncate(file->f_dentry, 0, 0, file) != 0)
+       if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0)
                goto close_fail;
 
        retval = binfmt->core_dump(signr, regs, file);
index da52b4a5db64005173124575e63161ed1d6c3d35..7c420b800c3438fd02ab669368f48fb9a6f01c5a 100644 (file)
@@ -89,8 +89,8 @@ ext2_acl_to_disk(const struct posix_acl *acl, size_t *size)
        size_t n;
 
        *size = ext2_acl_size(acl->a_count);
-       ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
-               acl->a_count * sizeof(ext2_acl_entry), GFP_KERNEL);
+       ext_acl = kmalloc(sizeof(ext2_acl_header) + acl->a_count *
+                       sizeof(ext2_acl_entry), GFP_KERNEL);
        if (!ext_acl)
                return ERR_PTR(-ENOMEM);
        ext_acl->a_version = cpu_to_le32(EXT2_ACL_VERSION);
index 92ea8265d7d5248e046954369da84b86bb858753..3e7a84a1e509a4aad71656e7bfeb8432d8a61460 100644 (file)
@@ -661,5 +661,8 @@ const struct file_operations ext2_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = ext2_readdir,
        .ioctl          = ext2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext2_compat_ioctl,
+#endif
        .fsync          = ext2_sync_file,
 };
index e65a019fc7a58b87f80c64fcaa7944b06bd30242..c19ac153f56b72c38d564de76a4616a4f599d9e6 100644 (file)
@@ -137,6 +137,7 @@ extern void ext2_set_inode_flags(struct inode *inode);
 /* ioctl.c */
 extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
                       unsigned long);
+extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 /* namei.c */
 struct dentry *ext2_get_parent(struct dentry *child);
index 23e2c7ccec1d15794c2679c4215a917b8f0edb25..2dba473c524ad33282402305b6b1afe837caf5d3 100644 (file)
@@ -41,17 +41,18 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
  */
 const struct file_operations ext2_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
        .aio_write      = generic_file_aio_write,
        .ioctl          = ext2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext2_compat_ioctl,
+#endif
        .mmap           = generic_file_mmap,
        .open           = generic_file_open,
        .release        = ext2_release_file,
        .fsync          = ext2_sync_file,
-       .readv          = generic_file_readv,
-       .writev         = generic_file_writev,
        .sendfile       = generic_file_sendfile,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
@@ -63,6 +64,9 @@ const struct file_operations ext2_xip_file_operations = {
        .read           = xip_file_read,
        .write          = xip_file_write,
        .ioctl          = ext2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext2_compat_ioctl,
+#endif
        .mmap           = xip_file_mmap,
        .open           = generic_file_open,
        .release        = ext2_release_file,
index 695f69ccf9088a072e4a899ec431629a14d44ebd..2cb545bf0f3c42dba436626c2832bed511e1f7fb 100644 (file)
@@ -574,7 +574,6 @@ got:
        inode->i_mode = mode;
 
        inode->i_ino = ino;
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
        memset(ei->i_data, 0, sizeof(ei->i_data));
index fb4d3220eb8d717918445b13d8f920023e3a13fb..dd4e14c221e0e07c67c96e2ae06e6c3b755f225e 100644 (file)
@@ -1094,7 +1094,6 @@ void ext2_read_inode (struct inode * inode)
                brelse (bh);
                goto bad_inode;
        }
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
        ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
index 3ca9afdf713d579d92f2037cc5ee4f69db9ab3da..1dfba77eab10dc348e0ac3c4fa4e23d2448ac281 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/capability.h>
 #include <linux/time.h>
 #include <linux/sched.h>
+#include <linux/compat.h>
+#include <linux/smp_lock.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 
@@ -80,3 +82,33 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                return -ENOTTY;
        }
 }
+
+#ifdef CONFIG_COMPAT
+long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       int ret;
+
+       /* These are just misnamed, they actually get/put from/to user an int */
+       switch (cmd) {
+       case EXT2_IOC32_GETFLAGS:
+               cmd = EXT2_IOC_GETFLAGS;
+               break;
+       case EXT2_IOC32_SETFLAGS:
+               cmd = EXT2_IOC_SETFLAGS;
+               break;
+       case EXT2_IOC32_GETVERSION:
+               cmd = EXT2_IOC_GETVERSION;
+               break;
+       case EXT2_IOC32_SETVERSION:
+               cmd = EXT2_IOC_SETVERSION;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       lock_kernel();
+       ret = ext2_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+       unlock_kernel();
+       return ret;
+}
+#endif
index 4ca8249853219cbee8529031e8602052cda46db2..e1af5b4cf80c100c26ce08a559bbdab12de8753b 100644 (file)
@@ -326,7 +326,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
                ext2_set_link(new_dir, new_de, new_page, old_inode);
                new_inode->i_ctime = CURRENT_TIME_SEC;
                if (dir_de)
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                inode_dec_link_count(new_inode);
        } else {
                if (dir_de) {
index 4286ff6330b6a0b006ca159e5041b6e75ed2075b..513cd421ac0b6627da069f16a1274154500a8374 100644 (file)
@@ -184,8 +184,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ext2_inode_cachep))
-               printk(KERN_INFO "ext2_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ext2_inode_cachep);
 }
 
 static void ext2_clear_inode(struct inode *inode)
@@ -544,17 +543,24 @@ static int ext2_check_descriptors (struct super_block * sb)
        int i;
        int desc_block = 0;
        struct ext2_sb_info *sbi = EXT2_SB(sb);
-       unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       unsigned long first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       unsigned long last_block;
        struct ext2_group_desc * gdp = NULL;
 
        ext2_debug ("Checking group descriptors");
 
        for (i = 0; i < sbi->s_groups_count; i++)
        {
+               if (i == sbi->s_groups_count - 1)
+                       last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+               else
+                       last_block = first_block +
+                               (EXT2_BLOCKS_PER_GROUP(sb) - 1);
+
                if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext2_group_desc *) sbi->s_group_desc[desc_block++]->b_data;
-               if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_block_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_block_bitmap) > last_block)
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Block bitmap for group %d"
@@ -562,8 +568,8 @@ static int ext2_check_descriptors (struct super_block * sb)
                                    i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_inode_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Inode bitmap for group %d"
@@ -571,9 +577,9 @@ static int ext2_check_descriptors (struct super_block * sb)
                                    i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_table) < block ||
-                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
-                   block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
+                   last_block)
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Inode table for group %d"
@@ -581,7 +587,7 @@ static int ext2_check_descriptors (struct super_block * sb)
                                    i, (unsigned long) le32_to_cpu(gdp->bg_inode_table));
                        return 0;
                }
-               block += EXT2_BLOCKS_PER_GROUP(sb);
+               first_block += EXT2_BLOCKS_PER_GROUP(sb);
                gdp++;
        }
        return 1;
@@ -648,11 +654,10 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        int i, j;
        __le32 features;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
 
        /*
         * See what the current blocksize for the device is, and
@@ -861,10 +866,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 
        if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext2;
-       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
-                                       le32_to_cpu(es->s_first_data_block) +
-                                      EXT2_BLOCKS_PER_GROUP(sb) - 1) /
-                                      EXT2_BLOCKS_PER_GROUP(sb);
+       sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
+                               le32_to_cpu(es->s_first_data_block) - 1)
+                                       / EXT2_BLOCKS_PER_GROUP(sb)) + 1;
        db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
                   EXT2_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
index 86ae8e93adb9d84dadbace346c65f0c5b09952fa..af52a7f8b291d0baf3542246fb90703032cfbecc 100644 (file)
@@ -521,11 +521,10 @@ bad_block:                ext2_error(sb, "ext2_xattr_set",
                }
        } else {
                /* Allocate a buffer where we construct the new block. */
-               header = kmalloc(sb->s_blocksize, GFP_KERNEL);
+               header = kzalloc(sb->s_blocksize, GFP_KERNEL);
                error = -ENOMEM;
                if (header == NULL)
                        goto cleanup;
-               memset(header, 0, sb->s_blocksize);
                end = (char *)header + sb->s_blocksize;
                header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
                header->h_blocks = header->h_refcount = cpu_to_le32(1);
index 0d21d558b87a19d2105d32ff8df19698ffe439a5..1e5038d9a01b9f469015b83f8ee7eb07a9abf8f8 100644 (file)
@@ -90,8 +90,8 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size)
        size_t n;
 
        *size = ext3_acl_size(acl->a_count);
-       ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
-               acl->a_count * sizeof(ext3_acl_entry), GFP_KERNEL);
+       ext_acl = kmalloc(sizeof(ext3_acl_header) + acl->a_count *
+                       sizeof(ext3_acl_entry), GFP_KERNEL);
        if (!ext_acl)
                return ERR_PTR(-ENOMEM);
        ext_acl->a_version = cpu_to_le32(EXT3_ACL_VERSION);
@@ -258,7 +258,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
                default:
                        return -EINVAL;
        }
-       if (acl) {
+       if (acl) {
                value = ext3_acl_to_disk(acl, &size);
                if (IS_ERR(value))
                        return (int)PTR_ERR(value);
index 063d994bda0b2c42f49571c5893f514c82898459..b41a7d7e20f006bc7e85a6e4b2315cf38ee2fdc9 100644 (file)
 
 #define in_range(b, first, len)        ((b) >= (first) && (b) <= (first) + (len) - 1)
 
+/**
+ * ext3_get_group_desc() -- load group descriptor from disk
+ * @sb:                        super block
+ * @block_group:       given block group
+ * @bh:                        pointer to the buffer head to store the block
+ *                     group descriptor
+ */
 struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
                                             unsigned int block_group,
                                             struct buffer_head ** bh)
@@ -73,8 +80,12 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
        return desc + offset;
 }
 
-/*
- * Read the bitmap for a given block_group, reading into the specified 
+/**
+ * read_block_bitmap()
+ * @sb:                        super block
+ * @block_group:       given block group
+ *
+ * Read the bitmap for a given block_group, reading into the specified
  * slot in the superblock's bitmap cache.
  *
  * Return buffer_head on success or NULL in case of failure.
@@ -103,15 +114,22 @@ error_out:
  * Operations include:
  * dump, find, add, remove, is_empty, find_next_reservable_window, etc.
  *
- * We use sorted double linked list for the per-filesystem reservation
- * window list. (like in vm_region).
+ * We use a red-black tree to represent per-filesystem reservation
+ * windows.
+ *
+ */
+
+/**
+ * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
+ * @rb_root:           root of per-filesystem reservation rb tree
+ * @verbose:           verbose mode
+ * @fn:                        function which wishes to dump the reservation map
  *
- * Initially, we keep those small operations in the abstract functions,
- * so later if we need a better searching tree than double linked-list,
- * we could easily switch to that without changing too much
- * code.
+ * If verbose is turned on, it will print the whole block reservation
+ * windows(start, end).        Otherwise, it will only print out the "bad" windows,
+ * those windows that overlap with their immediate neighbors.
  */
-#if 0
+#if 1
 static void __rsv_window_dump(struct rb_root *root, int verbose,
                              const char *fn)
 {
@@ -129,7 +147,7 @@ restart:
                rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node);
                if (verbose)
                        printk("reservation window 0x%p "
-                              "start:  %d, end:  %d\n",
+                              "start:  %lu, end:  %lu\n",
                               rsv, rsv->rsv_start, rsv->rsv_end);
                if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
                        printk("Bad reservation %p (start >= end)\n",
@@ -161,6 +179,22 @@ restart:
 #define rsv_window_dump(root, verbose) do {} while (0)
 #endif
 
+/**
+ * goal_in_my_reservation()
+ * @rsv:               inode's reservation window
+ * @grp_goal:          given goal block relative to the allocation block group
+ * @group:             the current allocation block group
+ * @sb:                        filesystem super block
+ *
+ * Test if the given goal block (group relative) is within the file's
+ * own block reservation window range.
+ *
+ * If the reservation window is outside the goal allocation group, return 0;
+ * grp_goal (given goal block) could be -1, which means no specific
+ * goal block. In this case, always return 1.
+ * If the goal block is within the reservation window, return 1;
+ * otherwise, return 0;
+ */
 static int
 goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
                        unsigned int group, struct super_block * sb)
@@ -168,7 +202,7 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
        ext3_fsblk_t group_first_block, group_last_block;
 
        group_first_block = ext3_group_first_block_no(sb, group);
-       group_last_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1;
+       group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
        if ((rsv->_rsv_start > group_last_block) ||
            (rsv->_rsv_end < group_first_block))
@@ -179,7 +213,11 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
        return 1;
 }
 
-/*
+/**
+ * search_reserve_window()
+ * @rb_root:           root of reservation tree
+ * @goal:              target allocation block
+ *
  * Find the reserved window which includes the goal, or the previous one
  * if the goal is not in any window.
  * Returns NULL if there are no windows or if all windows start after the goal.
@@ -216,6 +254,13 @@ search_reserve_window(struct rb_root *root, ext3_fsblk_t goal)
        return rsv;
 }
 
+/**
+ * ext3_rsv_window_add() -- Insert a window to the block reservation rb tree.
+ * @sb:                        super block
+ * @rsv:               reservation window to add
+ *
+ * Must be called with rsv_lock hold.
+ */
 void ext3_rsv_window_add(struct super_block *sb,
                    struct ext3_reserve_window_node *rsv)
 {
@@ -236,14 +281,25 @@ void ext3_rsv_window_add(struct super_block *sb,
                        p = &(*p)->rb_left;
                else if (start > this->rsv_end)
                        p = &(*p)->rb_right;
-               else
+               else {
+                       rsv_window_dump(root, 1);
                        BUG();
+               }
        }
 
        rb_link_node(node, parent, p);
        rb_insert_color(node, root);
 }
 
+/**
+ * ext3_rsv_window_remove() -- unlink a window from the reservation rb tree
+ * @sb:                        super block
+ * @rsv:               reservation window to remove
+ *
+ * Mark the block reservation window as not allocated, and unlink it
+ * from the filesystem reservation window rb tree. Must be called with
+ * rsv_lock hold.
+ */
 static void rsv_window_remove(struct super_block *sb,
                              struct ext3_reserve_window_node *rsv)
 {
@@ -253,11 +309,39 @@ static void rsv_window_remove(struct super_block *sb,
        rb_erase(&rsv->rsv_node, &EXT3_SB(sb)->s_rsv_window_root);
 }
 
+/*
+ * rsv_is_empty() -- Check if the reservation window is allocated.
+ * @rsv:               given reservation window to check
+ *
+ * returns 1 if the end block is EXT3_RESERVE_WINDOW_NOT_ALLOCATED.
+ */
 static inline int rsv_is_empty(struct ext3_reserve_window *rsv)
 {
        /* a valid reservation end block could not be 0 */
-       return (rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED);
+       return rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
 }
+
+/**
+ * ext3_init_block_alloc_info()
+ * @inode:             file inode structure
+ *
+ * Allocate and initialize the reservation window structure, and
+ * link the window to the ext3 inode structure at last
+ *
+ * The reservation window structure is only dynamically allocated
+ * and linked to ext3 inode the first time the open file
+ * needs a new block. So, before every ext3_new_block(s) call, for
+ * regular files, we should check whether the reservation window
+ * structure exists or not. In the latter case, this function is called.
+ * Fail to do so will result in block reservation being turned off for that
+ * open file.
+ *
+ * This function is called from ext3_get_blocks_handle(), also called
+ * when setting the reservation window size through ioctl before the file
+ * is open for write (needs block allocation).
+ *
+ * Needs truncate_mutex protection prior to call this function.
+ */
 void ext3_init_block_alloc_info(struct inode *inode)
 {
        struct ext3_inode_info *ei = EXT3_I(inode);
@@ -271,7 +355,7 @@ void ext3_init_block_alloc_info(struct inode *inode)
                rsv->rsv_start = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
                rsv->rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
 
-               /*
+               /*
                 * if filesystem is mounted with NORESERVATION, the goal
                 * reservation window size is set to zero to indicate
                 * block reservation is off
@@ -287,6 +371,19 @@ void ext3_init_block_alloc_info(struct inode *inode)
        ei->i_block_alloc_info = block_i;
 }
 
+/**
+ * ext3_discard_reservation()
+ * @inode:             inode
+ *
+ * Discard(free) block reservation window on last file close, or truncate
+ * or at last iput().
+ *
+ * It is being called in three cases:
+ *     ext3_release_file(): last writer close the file
+ *     ext3_clear_inode(): last iput(), when nobody link to this file.
+ *     ext3_truncate(): when the block indirect map is about to change.
+ *
+ */
 void ext3_discard_reservation(struct inode *inode)
 {
        struct ext3_inode_info *ei = EXT3_I(inode);
@@ -306,7 +403,14 @@ void ext3_discard_reservation(struct inode *inode)
        }
 }
 
-/* Free given blocks, update quota and i_blocks field */
+/**
+ * ext3_free_blocks_sb() -- Free given blocks and update quota
+ * @handle:                    handle to this transaction
+ * @sb:                                super block
+ * @block:                     start physcial block to free
+ * @count:                     number of blocks to free
+ * @pdquot_freed_blocks:       pointer to quota
+ */
 void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
                         ext3_fsblk_t block, unsigned long count,
                         unsigned long *pdquot_freed_blocks)
@@ -419,8 +523,8 @@ do_more:
                }
                /* @@@ This prevents newly-allocated data from being
                 * freed and then reallocated within the same
-                * transaction. 
-                * 
+                * transaction.
+                *
                 * Ideally we would want to allow that to happen, but to
                 * do so requires making journal_forget() capable of
                 * revoking the queued write of a data block, which
@@ -433,7 +537,7 @@ do_more:
                 * safe not to set the allocation bit in the committed
                 * bitmap, because we know that there is no outstanding
                 * activity on the buffer any more and so it is safe to
-                * reallocate it.  
+                * reallocate it.
                 */
                BUFFER_TRACE(bitmap_bh, "set in b_committed_data");
                J_ASSERT_BH(bitmap_bh,
@@ -490,7 +594,13 @@ error_return:
        return;
 }
 
-/* Free given blocks, update quota and i_blocks field */
+/**
+ * ext3_free_blocks() -- Free given blocks and update quota
+ * @handle:            handle for this transaction
+ * @inode:             inode
+ * @block:             start physical block to free
+ * @count:             number of blocks to count
+ */
 void ext3_free_blocks(handle_t *handle, struct inode *inode,
                        ext3_fsblk_t block, unsigned long count)
 {
@@ -508,7 +618,11 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode,
        return;
 }
 
-/*
+/**
+ * ext3_test_allocatable()
+ * @nr:                        given allocation block group
+ * @bh:                        bufferhead contains the bitmap of the given block group
+ *
  * For ext3 allocations, we must not reuse any blocks which are
  * allocated in the bitmap buffer's "last committed data" copy.  This
  * prevents deletes from freeing up the page for reuse until we have
@@ -518,7 +632,7 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode,
  * data would allow the old block to be overwritten before the
  * transaction committed (because we force data to disk before commit).
  * This would lead to corruption if we crashed between overwriting the
- * data and committing the delete. 
+ * data and committing the delete.
  *
  * @@@ We may want to make this allocation behaviour conditional on
  * data-writes at some point, and disable it for metadata allocations or
@@ -541,6 +655,16 @@ static int ext3_test_allocatable(ext3_grpblk_t nr, struct buffer_head *bh)
        return ret;
 }
 
+/**
+ * bitmap_search_next_usable_block()
+ * @start:             the starting block (group relative) of the search
+ * @bh:                        bufferhead contains the block group bitmap
+ * @maxblocks:         the ending block (group relative) of the reservation
+ *
+ * The bitmap search --- search forward alternately through the actual
+ * bitmap on disk and the last-committed copy in journal, until we find a
+ * bit free in both bitmaps.
+ */
 static ext3_grpblk_t
 bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
                                        ext3_grpblk_t maxblocks)
@@ -548,11 +672,6 @@ bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
        ext3_grpblk_t next;
        struct journal_head *jh = bh2jh(bh);
 
-       /*
-        * The bitmap search --- search forward alternately through the actual
-        * bitmap and the last-committed copy until we find a bit free in
-        * both
-        */
        while (start < maxblocks) {
                next = ext3_find_next_zero_bit(bh->b_data, maxblocks, start);
                if (next >= maxblocks)
@@ -562,14 +681,20 @@ bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
                jbd_lock_bh_state(bh);
                if (jh->b_committed_data)
                        start = ext3_find_next_zero_bit(jh->b_committed_data,
-                                                       maxblocks, next);
+                                                       maxblocks, next);
                jbd_unlock_bh_state(bh);
        }
        return -1;
 }
 
-/*
- * Find an allocatable block in a bitmap.  We honour both the bitmap and
+/**
+ * find_next_usable_block()
+ * @start:             the starting block (group relative) to find next
+ *                     allocatable block in bitmap.
+ * @bh:                        bufferhead contains the block group bitmap
+ * @maxblocks:         the ending block (group relative) for the search
+ *
+ * Find an allocatable block in a bitmap.  We honor both the bitmap and
  * its last-committed copy (if that exists), and perform the "most
  * appropriate allocation" algorithm of looking for a free block near
  * the initial goal; then for a free byte somewhere in the bitmap; then
@@ -584,7 +709,7 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
 
        if (start > 0) {
                /*
-                * The goal was occupied; search forward for a free 
+                * The goal was occupied; search forward for a free
                 * block within the next XX blocks.
                 *
                 * end_goal is more or less random, but it has to be
@@ -620,7 +745,11 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
        return here;
 }
 
-/*
+/**
+ * claim_block()
+ * @block:             the free block (group relative) to allocate
+ * @bh:                        the bufferhead containts the block group bitmap
+ *
  * We think we can allocate this block in this bitmap.  Try to set the bit.
  * If that succeeds then check that nobody has allocated and then freed the
  * block since we saw that is was not marked in b_committed_data.  If it _was_
@@ -646,7 +775,26 @@ claim_block(spinlock_t *lock, ext3_grpblk_t block, struct buffer_head *bh)
        return ret;
 }
 
-/*
+/**
+ * ext3_try_to_allocate()
+ * @sb:                        superblock
+ * @handle:            handle to this transaction
+ * @group:             given allocation block group
+ * @bitmap_bh:         bufferhead holds the block bitmap
+ * @grp_goal:          given target block within the group
+ * @count:             target number of blocks to allocate
+ * @my_rsv:            reservation window
+ *
+ * Attempt to allocate blocks within a give range. Set the range of allocation
+ * first, then find the first free bit(s) from the bitmap (within the range),
+ * and at last, allocate the blocks by claiming the found free bit as allocated.
+ *
+ * To set the range of this allocation:
+ *     if there is a reservation window, only try to allocate block(s) from the
+ *     file's own reservation window;
+ *     Otherwise, the allocation range starts from the give goal block, ends at
+ *     the block group's last block.
+ *
  * If we failed to allocate the desired block then we may end up crossing to a
  * new bitmap.  In that case we must release write access to the old one via
  * ext3_journal_release_buffer(), else we'll run out of credits.
@@ -703,7 +851,8 @@ repeat:
        }
        start = grp_goal;
 
-       if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) {
+       if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group),
+               grp_goal, bitmap_bh)) {
                /*
                 * The block was allocated by another thread, or it was
                 * allocated and then freed by another thread
@@ -718,7 +867,8 @@ repeat:
        grp_goal++;
        while (num < *count && grp_goal < end
                && ext3_test_allocatable(grp_goal, bitmap_bh)
-               && claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) {
+               && claim_block(sb_bgl_lock(EXT3_SB(sb), group),
+                               grp_goal, bitmap_bh)) {
                num++;
                grp_goal++;
        }
@@ -730,12 +880,12 @@ fail_access:
 }
 
 /**
- *     find_next_reservable_window():
+ *     find_next_reservable_window():
  *             find a reservable space within the given range.
  *             It does not allocate the reservation window for now:
  *             alloc_new_reservation() will do the work later.
  *
- *     @search_head: the head of the searching list;
+ *     @search_head: the head of the searching list;
  *             This is not necessarily the list head of the whole filesystem
  *
  *             We have both head and start_block to assist the search
@@ -743,12 +893,12 @@ fail_access:
  *             but we will shift to the place where start_block is,
  *             then start from there, when looking for a reservable space.
  *
- *     @size: the target new reservation window size
+ *     @size: the target new reservation window size
  *
- *     @group_first_block: the first block we consider to start
+ *     @group_first_block: the first block we consider to start
  *                     the real search from
  *
- *     @last_block:
+ *     @last_block:
  *             the maximum block number that our goal reservable space
  *             could start from. This is normally the last block in this
  *             group. The search will end when we found the start of next
@@ -756,10 +906,10 @@ fail_access:
  *             This could handle the cross boundary reservation window
  *             request.
  *
- *     basically we search from the given range, rather than the whole
- *     reservation double linked list, (start_block, last_block)
- *     to find a free region that is of my size and has not
- *     been reserved.
+ *     basically we search from the given range, rather than the whole
+ *     reservation double linked list, (start_block, last_block)
+ *     to find a free region that is of my size and has not
+ *     been reserved.
  *
  */
 static int find_next_reservable_window(
@@ -812,7 +962,7 @@ static int find_next_reservable_window(
                        /*
                         * Found a reserveable space big enough.  We could
                         * have a reservation across the group boundary here
-                        */
+                        */
                        break;
                }
        }
@@ -848,7 +998,7 @@ static int find_next_reservable_window(
 }
 
 /**
- *     alloc_new_reservation()--allocate a new reservation window
+ *     alloc_new_reservation()--allocate a new reservation window
  *
  *             To make a new reservation, we search part of the filesystem
  *             reservation list (the list that inside the group). We try to
@@ -897,7 +1047,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
        spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
 
        group_first_block = ext3_group_first_block_no(sb, group);
-       group_end_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1;
+       group_end_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
        if (grp_goal < 0)
                start_block = group_first_block;
@@ -929,9 +1079,10 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
                if ((my_rsv->rsv_alloc_hit >
                     (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {
                        /*
-                        * if we previously allocation hit ration is greater than half
-                        * we double the size of reservation window next time
-                        * otherwise keep the same
+                        * if the previously allocation hit ratio is
+                        * greater than 1/2, then we double the size of
+                        * the reservation window the next time,
+                        * otherwise we keep the same size window
                         */
                        size = size * 2;
                        if (size > EXT3_MAX_RESERVE_BLOCKS)
@@ -1010,6 +1161,23 @@ retry:
        goto retry;
 }
 
+/**
+ * try_to_extend_reservation()
+ * @my_rsv:            given reservation window
+ * @sb:                        super block
+ * @size:              the delta to extend
+ *
+ * Attempt to expand the reservation window large enough to have
+ * required number of free blocks
+ *
+ * Since ext3_try_to_allocate() will always allocate blocks within
+ * the reservation window range, if the window size is too small,
+ * multiple blocks allocation has to stop at the end of the reservation
+ * window. To make this more efficient, given the total number of
+ * blocks needed and the current size of the window, we try to
+ * expand the reservation window size if necessary on a best-effort
+ * basis before ext3_new_blocks() tries to allocate blocks,
+ */
 static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
                        struct super_block *sb, int size)
 {
@@ -1035,7 +1203,17 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
        spin_unlock(rsv_lock);
 }
 
-/*
+/**
+ * ext3_try_to_allocate_with_rsv()
+ * @sb:                        superblock
+ * @handle:            handle to this transaction
+ * @group:             given allocation block group
+ * @bitmap_bh:         bufferhead holds the block bitmap
+ * @grp_goal:          given target block within the group
+ * @count:             target number of blocks to allocate
+ * @my_rsv:            reservation window
+ * @errp:              pointer to store the error code
+ *
  * This is the main function used to allocate a new block and its reservation
  * window.
  *
@@ -1051,9 +1229,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
  * reservation), and there are lots of free blocks, but they are all
  * being reserved.
  *
- * We use a sorted double linked list for the per-filesystem reservation list.
- * The insert, remove and find a free space(non-reserved) operations for the
- * sorted double linked list should be fast.
+ * We use a red-black tree for the per-filesystem reservation list.
  *
  */
 static ext3_grpblk_t
@@ -1063,7 +1239,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        struct ext3_reserve_window_node * my_rsv,
                        unsigned long *count, int *errp)
 {
-       ext3_fsblk_t group_first_block;
+       ext3_fsblk_t group_first_block, group_last_block;
        ext3_grpblk_t ret = 0;
        int fatal;
        unsigned long num = *count;
@@ -1100,6 +1276,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
         * first block is the block number of the first block in this group
         */
        group_first_block = ext3_group_first_block_no(sb, group);
+       group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
        /*
         * Basically we will allocate a new block from inode's reservation
@@ -1118,7 +1295,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
         */
        while (1) {
                if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
-                       !goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) {
+                       !goal_in_my_reservation(&my_rsv->rsv_window,
+                                               grp_goal, group, sb)) {
                        if (my_rsv->rsv_goal_size < *count)
                                my_rsv->rsv_goal_size = *count;
                        ret = alloc_new_reservation(my_rsv, grp_goal, sb,
@@ -1126,17 +1304,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        if (ret < 0)
                                break;                  /* failed */
 
-                       if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb))
+                       if (!goal_in_my_reservation(&my_rsv->rsv_window,
+                                                       grp_goal, group, sb))
                                grp_goal = -1;
-               } else if (grp_goal > 0 && (my_rsv->rsv_end-grp_goal+1) < *count)
+               } else if (grp_goal > 0 &&
+                         (my_rsv->rsv_end-grp_goal+1) < *count)
                        try_to_extend_reservation(my_rsv, sb,
                                        *count-my_rsv->rsv_end + grp_goal - 1);
 
-               if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
-                   || (my_rsv->rsv_end < group_first_block))
+               if ((my_rsv->rsv_start > group_last_block) ||
+                               (my_rsv->rsv_end < group_first_block)) {
+                       rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1);
                        BUG();
-               ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, grp_goal,
-                                          &num, &my_rsv->rsv_window);
+               }
+               ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh,
+                                          grp_goal, &num, &my_rsv->rsv_window);
                if (ret >= 0) {
                        my_rsv->rsv_alloc_hit += num;
                        *count = num;
@@ -1161,6 +1343,12 @@ out:
        return ret;
 }
 
+/**
+ * ext3_has_free_blocks()
+ * @sbi:               in-core super block structure.
+ *
+ * Check if filesystem has at least 1 free block available for allocation.
+ */
 static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 {
        ext3_fsblk_t free_blocks, root_blocks;
@@ -1175,11 +1363,17 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
        return 1;
 }
 
-/*
+/**
+ * ext3_should_retry_alloc()
+ * @sb:                        super block
+ * @retries            number of attemps has been made
+ *
  * ext3_should_retry_alloc() is called when ENOSPC is returned, and if
  * it is profitable to retry the operation, this function will wait
  * for the current or commiting transaction to complete, and then
  * return TRUE.
+ *
+ * if the total number of retries exceed three times, return FALSE.
  */
 int ext3_should_retry_alloc(struct super_block *sb, int *retries)
 {
@@ -1191,13 +1385,19 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
        return journal_force_commit_nested(EXT3_SB(sb)->s_journal);
 }
 
-/*
- * ext3_new_block uses a goal block to assist allocation.  If the goal is
- * free, or there is a free block within 32 blocks of the goal, that block
- * is allocated.  Otherwise a forward search is made for a free block; within 
- * each block group the search first looks for an entire free byte in the block
- * bitmap, and then for any free bit if that fails.
- * This function also updates quota and i_blocks field.
+/**
+ * ext3_new_blocks() -- core block(s) allocation function
+ * @handle:            handle to this transaction
+ * @inode:             file inode
+ * @goal:              given target block(filesystem wide)
+ * @count:             target number of blocks to allocate
+ * @errp:              error code
+ *
+ * ext3_new_blocks uses a goal block to assist allocation.  It tries to
+ * allocate block(s) from the block group contains the goal block first. If that
+ * fails, it will try to allocate block(s) from other block groups without
+ * any specific goal block.
+ *
  */
 ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
                        ext3_fsblk_t goal, unsigned long *count, int *errp)
@@ -1303,7 +1503,7 @@ retry_alloc:
        smp_rmb();
 
        /*
-        * Now search the rest of the groups.  We assume that 
+        * Now search the rest of the groups.  We assume that
         * i and gdp correctly point to the last group visited.
         */
        for (bgi = 0; bgi < ngroups; bgi++) {
@@ -1428,7 +1628,7 @@ allocated:
 
        spin_lock(sb_bgl_lock(sbi, group_no));
        gdp->bg_free_blocks_count =
-                       cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - num);
+                       cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
        spin_unlock(sb_bgl_lock(sbi, group_no));
        percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
 
@@ -1471,6 +1671,12 @@ ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode,
        return ext3_new_blocks(handle, inode, goal, &count, errp);
 }
 
+/**
+ * ext3_count_free_blocks() -- count filesystem free blocks
+ * @sb:                superblock
+ *
+ * Adds up the number of free blocks from each block group.
+ */
 ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb)
 {
        ext3_fsblk_t desc_count;
index ce4f82b9e528d6dd6a64045144f34792611bf764..b9176eed98d1258518bd9cebfbbdb071baa458fc 100644 (file)
@@ -20,7 +20,7 @@ unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars)
        unsigned int i;
        unsigned long sum = 0;
 
-       if (!map) 
+       if (!map)
                return (0);
        for (i = 0; i < numchars; i++)
                sum += nibblemap[map->b_data[i] & 0xf] +
index fbb0d4ed07d4322e947f081f1af4dd6fd025ce33..d0b54f30b914e5304f367252e5f6a3bd96ac8d38 100644 (file)
@@ -44,6 +44,9 @@ const struct file_operations ext3_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = ext3_readdir,         /* we take BKL. needed?*/
        .ioctl          = ext3_ioctl,           /* BKL held */
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext3_compat_ioctl,
+#endif
        .fsync          = ext3_sync_file,       /* BKL held */
 #ifdef CONFIG_EXT3_INDEX
        .release        = ext3_release_dir,
@@ -59,7 +62,7 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
 
        return (ext3_filetype_table[filetype]);
 }
-                              
+
 
 int ext3_check_dir_entry (const char * function, struct inode * dir,
                          struct ext3_dir_entry_2 * de,
@@ -67,7 +70,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
                          unsigned long offset)
 {
        const char * error_msg = NULL;
-       const int rlen = le16_to_cpu(de->rec_len);
+       const int rlen = le16_to_cpu(de->rec_len);
 
        if (rlen < EXT3_DIR_REC_LEN(1))
                error_msg = "rec_len is smaller than minimal";
@@ -162,7 +165,7 @@ revalidate:
                 * to make sure. */
                if (filp->f_version != inode->i_version) {
                        for (i = 0; i < sb->s_blocksize && i < offset; ) {
-                               de = (struct ext3_dir_entry_2 *) 
+                               de = (struct ext3_dir_entry_2 *)
                                        (bh->b_data + i);
                                /* It's too expensive to do a full
                                 * dirent test each time round this
@@ -181,7 +184,7 @@ revalidate:
                        filp->f_version = inode->i_version;
                }
 
-               while (!error && filp->f_pos < inode->i_size 
+               while (!error && filp->f_pos < inode->i_size
                       && offset < sb->s_blocksize) {
                        de = (struct ext3_dir_entry_2 *) (bh->b_data + offset);
                        if (!ext3_check_dir_entry ("ext3_readdir", inode, de,
@@ -229,7 +232,7 @@ out:
 /*
  * These functions convert from the major/minor hash to an f_pos
  * value.
- * 
+ *
  * Currently we only use major hash numer.  This is unfortunate, but
  * on 32-bit machines, the same VFS interface is used for lseek and
  * llseek, so if we use the 64 bit offset, then the 32-bit versions of
@@ -250,7 +253,7 @@ out:
 struct fname {
        __u32           hash;
        __u32           minor_hash;
-       struct rb_node  rb_hash; 
+       struct rb_node  rb_hash;
        struct fname    *next;
        __u32           inode;
        __u8            name_len;
@@ -343,10 +346,9 @@ int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
 
        /* Create and allocate the fname structure */
        len = sizeof(struct fname) + dirent->name_len + 1;
-       new_fn = kmalloc(len, GFP_KERNEL);
+       new_fn = kzalloc(len, GFP_KERNEL);
        if (!new_fn)
                return -ENOMEM;
-       memset(new_fn, 0, len);
        new_fn->hash = hash;
        new_fn->minor_hash = minor_hash;
        new_fn->inode = le32_to_cpu(dirent->inode);
@@ -410,7 +412,7 @@ static int call_filldir(struct file * filp, void * dirent,
        curr_pos = hash2pos(fname->hash, fname->minor_hash);
        while (fname) {
                error = filldir(dirent, fname->name,
-                               fname->name_len, curr_pos, 
+                               fname->name_len, curr_pos,
                                fname->inode,
                                get_dtype(sb, fname->file_type));
                if (error) {
@@ -465,7 +467,7 @@ static int ext3_dx_readdir(struct file * filp,
                /*
                 * Fill the rbtree if we have no more entries,
                 * or the inode has changed since we last read in the
-                * cached entries. 
+                * cached entries.
                 */
                if ((!info->curr_node) ||
                    (filp->f_version != inode->i_version)) {
index 1efefb630ea971dae9728b32ac8beace5ad79187..e96c388047e09a0a89e1595b01ddc079745e9a0f 100644 (file)
@@ -48,14 +48,15 @@ static int ext3_release_file (struct inode * inode, struct file * filp)
 }
 
 static ssize_t
-ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_dentry->d_inode;
        ssize_t ret;
        int err;
 
-       ret = generic_file_aio_write(iocb, buf, count, pos);
+       ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
 
        /*
         * Skip flushing if there was an error, or if nothing was written.
@@ -100,7 +101,7 @@ ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
 
 force_commit:
        err = ext3_force_commit(inode->i_sb);
-       if (err) 
+       if (err)
                return err;
        return ret;
 }
@@ -111,9 +112,10 @@ const struct file_operations ext3_file_operations = {
        .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
        .aio_write      = ext3_file_write,
-       .readv          = generic_file_readv,
-       .writev         = generic_file_writev,
        .ioctl          = ext3_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext3_compat_ioctl,
+#endif
        .mmap           = generic_file_mmap,
        .open           = generic_file_open,
        .release        = ext3_release_file,
index 49382a208e05e3fdd1bf62e8f9495a46a614e587..dd1fd3c0fc05c1bf4593decf9cd692df28558079 100644 (file)
@@ -8,14 +8,14 @@
  *                      Universite Pierre et Marie Curie (Paris VI)
  *  from
  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
- * 
+ *
  *  ext3fs fsync primitive
  *
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
- * 
+ *
  *  Removed unnecessary code duplication for little endian machines
- *  and excessive __inline__s. 
+ *  and excessive __inline__s.
  *        Andi Kleen, 1997
  *
  * Major simplications and cleanup - we only need to do the metadata, because
index 5a2d1235ead01562b5ca04988ed12a2a92ea86dd..deeb27b5ba833d25009c33c3c31752fec8d79dd3 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2002 by Theodore Ts'o
  *
  * This file is released under the GPL v2.
- * 
+ *
  * This file may be redistributed under the terms of the GNU Public
  * License.
  */
@@ -80,11 +80,11 @@ static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
  * Returns the hash of a filename.  If len is 0 and name is NULL, then
  * this function can be used to test whether or not a hash version is
  * supported.
- * 
+ *
  * The seed is an 4 longword (32 bits) "secret" which can be used to
  * uniquify a hash.  If the seed is all zero's, then some default seed
  * may be used.
- * 
+ *
  * A particular hash version specifies whether or not the seed is
  * represented, and whether or not the returned hash is 32 bits or 64
  * bits.  32 bit hashes will return 0 for the minor hash.
@@ -95,7 +95,7 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
        __u32   minor_hash = 0;
        const char      *p;
        int             i;
-       __u32           in[8], buf[4];
+       __u32           in[8], buf[4];
 
        /* Initialize the default seed for the hash checksum functions */
        buf[0] = 0x67452301;
index 36546ed36a1476df87adf736bcab38a9dbcac822..e45dbd65173624c10796655baa0566c98ece4f29 100644 (file)
@@ -202,7 +202,7 @@ error_return:
 static int find_group_dir(struct super_block *sb, struct inode *parent)
 {
        int ngroups = EXT3_SB(sb)->s_groups_count;
-       int freei, avefreei;
+       unsigned int freei, avefreei;
        struct ext3_group_desc *desc, *best_desc = NULL;
        struct buffer_head *bh;
        int group, best_group = -1;
@@ -216,7 +216,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
                        continue;
                if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
                        continue;
-               if (!best_desc || 
+               if (!best_desc ||
                    (le16_to_cpu(desc->bg_free_blocks_count) >
                     le16_to_cpu(best_desc->bg_free_blocks_count))) {
                        best_group = group;
@@ -226,30 +226,30 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
        return best_group;
 }
 
-/* 
- * Orlov's allocator for directories. 
- * 
+/*
+ * Orlov's allocator for directories.
+ *
  * We always try to spread first-level directories.
  *
- * If there are blockgroups with both free inodes and free blocks counts 
- * not worse than average we return one with smallest directory count. 
- * Otherwise we simply return a random group. 
- * 
- * For the rest rules look so: 
- * 
- * It's OK to put directory into a group unless 
- * it has too many directories already (max_dirs) or 
- * it has too few free inodes left (min_inodes) or 
- * it has too few free blocks left (min_blocks) or 
- * it's already running too large debt (max_debt). 
- * Parent's group is prefered, if it doesn't satisfy these 
- * conditions we search cyclically through the rest. If none 
- * of the groups look good we just look for a group with more 
- * free inodes than average (starting at parent's group). 
- * 
- * Debt is incremented each time we allocate a directory and decremented 
- * when we allocate an inode, within 0--255. 
- */ 
+ * If there are blockgroups with both free inodes and free blocks counts
+ * not worse than average we return one with smallest directory count.
+ * Otherwise we simply return a random group.
+ *
+ * For the rest rules look so:
+ *
+ * It's OK to put directory into a group unless
+ * it has too many directories already (max_dirs) or
+ * it has too few free inodes left (min_inodes) or
+ * it has too few free blocks left (min_blocks) or
+ * it's already running too large debt (max_debt).
+ * Parent's group is prefered, if it doesn't satisfy these
+ * conditions we search cyclically through the rest. If none
+ * of the groups look good we just look for a group with more
+ * free inodes than average (starting at parent's group).
+ *
+ * Debt is incremented each time we allocate a directory and decremented
+ * when we allocate an inode, within 0--255.
+ */
 
 #define INODE_COST 64
 #define BLOCK_COST 256
@@ -261,10 +261,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
        struct ext3_super_block *es = sbi->s_es;
        int ngroups = sbi->s_groups_count;
        int inodes_per_group = EXT3_INODES_PER_GROUP(sb);
-       int freei, avefreei;
+       unsigned int freei, avefreei;
        ext3_fsblk_t freeb, avefreeb;
        ext3_fsblk_t blocks_per_dir;
-       int ndirs;
+       unsigned int ndirs;
        int max_debt, max_dirs, min_inodes;
        ext3_grpblk_t min_blocks;
        int group = -1, i;
@@ -454,7 +454,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
                        group = find_group_dir(sb, dir);
                else
                        group = find_group_orlov(sb, dir);
-       } else 
+       } else
                group = find_group_other(sb, dir);
 
        err = -ENOSPC;
@@ -559,7 +559,6 @@ got:
 
        inode->i_ino = ino;
        /* This is the optimal IO size (for stat), not the fs block size */
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 
index 84be02e93652bd8e5548d8f07ad6e57c5947c817..03ba5bcab18633725372096cd94c9e52b6aa83cc 100644 (file)
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  Goal-directed block allocation by Stephen Tweedie
- *     (sct@redhat.com), 1993, 1998
+ *     (sct@redhat.com), 1993, 1998
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  *  64-bit file support on 64-bit platforms by Jakub Jelinek
- *     (jj@sunsite.ms.mff.cuni.cz)
+ *     (jj@sunsite.ms.mff.cuni.cz)
  *
  *  Assorted race fixes, rewrite of ext3_get_block() by Al Viro, 2000
  */
@@ -36,6 +36,7 @@
 #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/uio.h>
+#include <linux/bio.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -55,7 +56,7 @@ static int ext3_inode_is_fast_symlink(struct inode *inode)
 /*
  * The ext3 forget function must perform a revoke if we are freeing data
  * which has been journaled.  Metadata (eg. indirect blocks) must be
- * revoked in all cases. 
+ * revoked in all cases.
  *
  * "bh" may be NULL: a metadata block may have been freed from memory
  * but there may still be a record of it in the journal, and that record
@@ -105,7 +106,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
  * Work out how many blocks we need to proceed with the next chunk of a
  * truncate transaction.
  */
-static unsigned long blocks_for_truncate(struct inode *inode) 
+static unsigned long blocks_for_truncate(struct inode *inode)
 {
        unsigned long needed;
 
@@ -122,13 +123,13 @@ static unsigned long blocks_for_truncate(struct inode *inode)
 
        /* But we need to bound the transaction so we don't overflow the
         * journal. */
-       if (needed > EXT3_MAX_TRANS_DATA) 
+       if (needed > EXT3_MAX_TRANS_DATA)
                needed = EXT3_MAX_TRANS_DATA;
 
        return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
 }
 
-/* 
+/*
  * Truncate transactions can be complex and absolutely huge.  So we need to
  * be able to restart the transaction at a conventient checkpoint to make
  * sure we don't overflow the journal.
@@ -136,9 +137,9 @@ static unsigned long blocks_for_truncate(struct inode *inode)
  * start_transaction gets us a new handle for a truncate transaction,
  * and extend_transaction tries to extend the existing one a bit.  If
  * extend fails, we need to propagate the failure up and restart the
- * transaction in the top-level truncate loop. --sct 
+ * transaction in the top-level truncate loop. --sct
  */
-static handle_t *start_transaction(struct inode *inode) 
+static handle_t *start_transaction(struct inode *inode)
 {
        handle_t *result;
 
@@ -215,12 +216,12 @@ void ext3_delete_inode (struct inode * inode)
        ext3_orphan_del(handle, inode);
        EXT3_I(inode)->i_dtime  = get_seconds();
 
-       /* 
+       /*
         * One subtle ordering requirement: if anything has gone wrong
         * (transaction abort, IO errors, whatever), then we can still
         * do these next steps (the fs will already have been marked as
         * having errors), but we can't free the inode if the mark_dirty
-        * fails.  
+        * fails.
         */
        if (ext3_mark_inode_dirty(handle, inode))
                /* If that failed, just do the required in-core inode clear. */
@@ -398,7 +399,7 @@ no_block:
  *       + if there is a block to the left of our position - allocate near it.
  *       + if pointer will live in indirect block - allocate near that block.
  *       + if pointer will live in inode - allocate in the same
- *         cylinder group. 
+ *         cylinder group.
  *
  * In the latter case we colour the starting block by the callers PID to
  * prevent it from clashing with concurrent allocations for a different inode
@@ -470,7 +471,7 @@ static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block,
  *     ext3_blks_to_allocate: Look up the block map and count the number
  *     of direct blocks need to be allocated for the given branch.
  *
- *     @branch: chain of indirect blocks
+ *     @branch: chain of indirect blocks
  *     @k: number of blocks need for indirect blocks
  *     @blks: number of data blocks to be mapped.
  *     @blocks_to_boundary:  the offset in the indirect block
@@ -744,7 +745,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
                jbd_debug(5, "splicing indirect only\n");
                BUFFER_TRACE(where->bh, "call ext3_journal_dirty_metadata");
                err = ext3_journal_dirty_metadata(handle, where->bh);
-               if (err) 
+               if (err)
                        goto err_out;
        } else {
                /*
@@ -1073,7 +1074,7 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode,
                return bh;
        if (buffer_uptodate(bh))
                return bh;
-       ll_rw_block(READ, 1, &bh);
+       ll_rw_block(READ_META, 1, &bh);
        wait_on_buffer(bh);
        if (buffer_uptodate(bh))
                return bh;
@@ -1098,7 +1099,7 @@ static int walk_page_buffers(     handle_t *handle,
 
        for (   bh = head, block_start = 0;
                ret == 0 && (bh != head || !block_start);
-               block_start = block_end, bh = next)
+               block_start = block_end, bh = next)
        {
                next = bh->b_this_page;
                block_end = block_start + blocksize;
@@ -1137,7 +1138,7 @@ static int walk_page_buffers(     handle_t *handle,
  * So what we do is to rely on the fact that journal_stop/journal_start
  * will _not_ run commit under these circumstances because handle->h_ref
  * is elevated.  We'll still have enough credits for the tiny quotafile
- * write.  
+ * write.
  */
 static int do_journal_get_write_access(handle_t *handle,
                                        struct buffer_head *bh)
@@ -1282,7 +1283,7 @@ static int ext3_journalled_commit_write(struct file *file,
        if (inode->i_size > EXT3_I(inode)->i_disksize) {
                EXT3_I(inode)->i_disksize = inode->i_size;
                ret2 = ext3_mark_inode_dirty(handle, inode);
-               if (!ret) 
+               if (!ret)
                        ret = ret2;
        }
        ret2 = ext3_journal_stop(handle);
@@ -1291,7 +1292,7 @@ static int ext3_journalled_commit_write(struct file *file,
        return ret;
 }
 
-/* 
+/*
  * bmap() is special.  It gets used by applications such as lilo and by
  * the swapper to find the on-disk block of a specific piece of data.
  *
@@ -1300,10 +1301,10 @@ static int ext3_journalled_commit_write(struct file *file,
  * filesystem and enables swap, then they may get a nasty shock when the
  * data getting swapped to that swapfile suddenly gets overwritten by
  * the original zero's written out previously to the journal and
- * awaiting writeback in the kernel's buffer cache. 
+ * awaiting writeback in the kernel's buffer cache.
  *
  * So, if we see any bmap calls here on a modified, data-journaled file,
- * take extra steps to flush any blocks which might be in the cache. 
+ * take extra steps to flush any blocks which might be in the cache.
  */
 static sector_t ext3_bmap(struct address_space *mapping, sector_t block)
 {
@@ -1312,16 +1313,16 @@ static sector_t ext3_bmap(struct address_space *mapping, sector_t block)
        int err;
 
        if (EXT3_I(inode)->i_state & EXT3_STATE_JDATA) {
-               /* 
+               /*
                 * This is a REALLY heavyweight approach, but the use of
                 * bmap on dirty files is expected to be extremely rare:
                 * only if we run lilo or swapon on a freshly made file
-                * do we expect this to happen. 
+                * do we expect this to happen.
                 *
                 * (bmap requires CAP_SYS_RAWIO so this does not
                 * represent an unprivileged user DOS attack --- we'd be
                 * in trouble if mortal users could trigger this path at
-                * will.) 
+                * will.)
                 *
                 * NB. EXT3_STATE_JDATA is not set on files other than
                 * regular files.  If somebody wants to bmap a directory
@@ -1457,7 +1458,7 @@ static int ext3_ordered_writepage(struct page *page,
         */
 
        /*
-        * And attach them to the current transaction.  But only if 
+        * And attach them to the current transaction.  But only if
         * block_write_full_page() succeeded.  Otherwise they are unmapped,
         * and generally junk.
         */
@@ -1644,7 +1645,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
                }
        }
 
-       ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, 
+       ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                 offset, nr_segs,
                                 ext3_get_block, NULL);
 
@@ -2025,7 +2026,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
                           __le32 *first, __le32 *last)
 {
        ext3_fsblk_t block_to_free = 0;    /* Starting block # of a run */
-       unsigned long count = 0;            /* Number of blocks in the run */ 
+       unsigned long count = 0;            /* Number of blocks in the run */
        __le32 *block_to_free_p = NULL;     /* Pointer into inode/ind
                                               corresponding to
                                               block_to_free */
@@ -2054,7 +2055,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
                        } else if (nr == block_to_free + count) {
                                count++;
                        } else {
-                               ext3_clear_blocks(handle, inode, this_bh, 
+                               ext3_clear_blocks(handle, inode, this_bh,
                                                  block_to_free,
                                                  count, block_to_free_p, p);
                                block_to_free = nr;
@@ -2115,7 +2116,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
                         */
                        if (!bh) {
                                ext3_error(inode->i_sb, "ext3_free_branches",
-                                          "Read failure, inode=%ld, block="E3FSBLK,
+                                          "Read failure, inode=%lu, block="E3FSBLK,
                                           inode->i_ino, nr);
                                continue;
                        }
@@ -2184,7 +2185,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
                                        *p = 0;
                                        BUFFER_TRACE(parent_bh,
                                        "call ext3_journal_dirty_metadata");
-                                       ext3_journal_dirty_metadata(handle, 
+                                       ext3_journal_dirty_metadata(handle,
                                                                    parent_bh);
                                }
                        }
@@ -2540,7 +2541,7 @@ make_io:
                 */
                get_bh(bh);
                bh->b_end_io = end_buffer_read_sync;
-               submit_bh(READ, bh);
+               submit_bh(READ_META, bh);
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
                        ext3_error(inode->i_sb, "ext3_get_inode_loc",
@@ -2632,9 +2633,6 @@ void ext3_read_inode(struct inode * inode)
                 * recovery code: that's fine, we're about to complete
                 * the process of deleting those. */
        }
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size
-                                        * (for stat), not the fs block
-                                        * size */  
        inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
 #ifdef EXT3_FRAGMENTS
@@ -2704,7 +2702,7 @@ void ext3_read_inode(struct inode * inode)
                if (raw_inode->i_block[0])
                        init_special_inode(inode, inode->i_mode,
                           old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
-               else 
+               else
                        init_special_inode(inode, inode->i_mode,
                           new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
        }
@@ -2724,8 +2722,8 @@ bad_inode:
  *
  * The caller must have write access to iloc->bh.
  */
-static int ext3_do_update_inode(handle_t *handle, 
-                               struct inode *inode, 
+static int ext3_do_update_inode(handle_t *handle,
+                               struct inode *inode,
                                struct ext3_iloc *iloc)
 {
        struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
@@ -2900,7 +2898,7 @@ int ext3_write_inode(struct inode *inode, int wait)
  * commit will leave the blocks being flushed in an unused state on
  * disk.  (On recovery, the inode will get truncated and the blocks will
  * be freed, so we have a strong guarantee that no future commit will
- * leave these blocks visible to the user.)  
+ * leave these blocks visible to the user.)
  *
  * Called with inode->sem down.
  */
@@ -3043,13 +3041,13 @@ int ext3_mark_iloc_dirty(handle_t *handle,
        return err;
 }
 
-/* 
+/*
  * On success, We end up with an outstanding reference count against
- * iloc->bh.  This _must_ be cleaned up later. 
+ * iloc->bh.  This _must_ be cleaned up later.
  */
 
 int
-ext3_reserve_inode_write(handle_t *handle, struct inode *inode, 
+ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
                         struct ext3_iloc *iloc)
 {
        int err = 0;
@@ -3139,7 +3137,7 @@ out:
 }
 
 #if 0
-/* 
+/*
  * Bind an inode's backing buffer_head into this transaction, to prevent
  * it from being flushed to disk early.  Unlike
  * ext3_reserve_inode_write, this leaves behind no bh reference and
@@ -3157,7 +3155,7 @@ static int ext3_pin_inode(handle_t *handle, struct inode *inode)
                        BUFFER_TRACE(iloc.bh, "get_write_access");
                        err = journal_get_write_access(handle, iloc.bh);
                        if (!err)
-                               err = ext3_journal_dirty_metadata(handle, 
+                               err = ext3_journal_dirty_metadata(handle,
                                                                  iloc.bh);
                        brelse(iloc.bh);
                }
index 3a6b012d120cedae637169ee747ec43b36b25e47..12daa68695721ffaf4a06bfa087d2018fceeb845 100644 (file)
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
 #include <linux/time.h>
+#include <linux/compat.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
-
 int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                unsigned long arg)
 {
@@ -252,3 +253,55 @@ flags_err:
                return -ENOTTY;
        }
 }
+
+#ifdef CONFIG_COMPAT
+long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       int ret;
+
+       /* These are just misnamed, they actually get/put from/to user an int */
+       switch (cmd) {
+       case EXT3_IOC32_GETFLAGS:
+               cmd = EXT3_IOC_GETFLAGS;
+               break;
+       case EXT3_IOC32_SETFLAGS:
+               cmd = EXT3_IOC_SETFLAGS;
+               break;
+       case EXT3_IOC32_GETVERSION:
+               cmd = EXT3_IOC_GETVERSION;
+               break;
+       case EXT3_IOC32_SETVERSION:
+               cmd = EXT3_IOC_SETVERSION;
+               break;
+       case EXT3_IOC32_GROUP_EXTEND:
+               cmd = EXT3_IOC_GROUP_EXTEND;
+               break;
+       case EXT3_IOC32_GETVERSION_OLD:
+               cmd = EXT3_IOC_GETVERSION_OLD;
+               break;
+       case EXT3_IOC32_SETVERSION_OLD:
+               cmd = EXT3_IOC_SETVERSION_OLD;
+               break;
+#ifdef CONFIG_JBD_DEBUG
+       case EXT3_IOC32_WAIT_FOR_READONLY:
+               cmd = EXT3_IOC_WAIT_FOR_READONLY;
+               break;
+#endif
+       case EXT3_IOC32_GETRSVSZ:
+               cmd = EXT3_IOC_GETRSVSZ;
+               break;
+       case EXT3_IOC32_SETRSVSZ:
+               cmd = EXT3_IOC_SETRSVSZ;
+               break;
+       case EXT3_IOC_GROUP_ADD:
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       lock_kernel();
+       ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+       unlock_kernel();
+       return ret;
+}
+#endif
index 2aa7101b27cd31bda494dbf5d688f1aa469f2985..906731a20f1ae37c4f7be8999d72d7986cbabadd 100644 (file)
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  *  Directory entry file type support and forward compatibility hooks
- *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
+ *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
  *  Hash Tree Directory indexing (c)
- *     Daniel Phillips, 2001
+ *     Daniel Phillips, 2001
  *  Hash Tree Directory indexing porting
- *     Christopher Li, 2002
+ *     Christopher Li, 2002
  *  Hash Tree Directory indexing cleanup
- *     Theodore Ts'o, 2002
+ *     Theodore Ts'o, 2002
  */
 
 #include <linux/fs.h>
@@ -35,6 +35,7 @@
 #include <linux/string.h>
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
+#include <linux/bio.h>
 #include <linux/smp_lock.h>
 
 #include "namei.h"
@@ -76,7 +77,7 @@ static struct buffer_head *ext3_append(handle_t *handle,
 #ifdef DX_DEBUG
 #define dxtrace(command) command
 #else
-#define dxtrace(command) 
+#define dxtrace(command)
 #endif
 
 struct fake_dirent
@@ -169,7 +170,7 @@ static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
 static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
 static int ext3_htree_next_block(struct inode *dir, __u32 hash,
                                 struct dx_frame *frame,
-                                struct dx_frame *frames, 
+                                struct dx_frame *frames,
                                 __u32 *start_hash);
 static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
                       struct ext3_dir_entry_2 **res_dir, int *err);
@@ -250,7 +251,7 @@ static void dx_show_index (char * label, struct dx_entry *entries)
 }
 
 struct stats
-{ 
+{
        unsigned names;
        unsigned space;
        unsigned bcount;
@@ -278,7 +279,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent
                                       ((char *) de - base));
                        }
                        space += EXT3_DIR_REC_LEN(de->name_len);
-                       names++;
+                       names++;
                }
                de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
@@ -464,7 +465,7 @@ static void dx_release (struct dx_frame *frames)
  */
 static int ext3_htree_next_block(struct inode *dir, __u32 hash,
                                 struct dx_frame *frame,
-                                struct dx_frame *frames, 
+                                struct dx_frame *frames,
                                 __u32 *start_hash)
 {
        struct dx_frame *p;
@@ -632,7 +633,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
                }
                count += ret;
                hashval = ~0;
-               ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, 
+               ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS,
                                            frame, frames, &hashval);
                *next_hash = hashval;
                if (ret < 0) {
@@ -649,7 +650,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
                        break;
        }
        dx_release(frames);
-       dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", 
+       dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n",
                       count, *next_hash));
        return count;
 errout:
@@ -870,7 +871,7 @@ restart:
                                bh = ext3_getblk(NULL, dir, b++, 0, &err);
                                bh_use[ra_max] = bh;
                                if (bh)
-                                       ll_rw_block(READ, 1, &bh);
+                                       ll_rw_block(READ_META, 1, &bh);
                        }
                }
                if ((bh = bh_use[ra_ptr++]) == NULL)
@@ -1050,7 +1051,7 @@ struct dentry *ext3_get_parent(struct dentry *child)
                parent = ERR_PTR(-ENOMEM);
        }
        return parent;
-} 
+}
 
 #define S_SHIFT 12
 static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = {
@@ -1198,7 +1199,7 @@ errout:
  * add_dirent_to_buf will attempt search the directory block for
  * space.  It will return -ENOSPC if no space is available, and -EIO
  * and -EEXIST if directory entry already exists.
- * 
+ *
  * NOTE!  bh is NOT released in the case where ENOSPC is returned.  In
  * all other cases bh is released.
  */
@@ -1572,7 +1573,7 @@ cleanup:
  * ext3_delete_entry deletes a directory entry by merging it with the
  * previous entry
  */
-static int ext3_delete_entry (handle_t *handle, 
+static int ext3_delete_entry (handle_t *handle,
                              struct inode * dir,
                              struct ext3_dir_entry_2 * de_del,
                              struct buffer_head * bh)
@@ -1615,12 +1616,12 @@ static int ext3_delete_entry (handle_t *handle,
  */
 static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
 {
-       inode->i_nlink++;
+       inc_nlink(inode);
 }
 
 static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
 {
-       inode->i_nlink--;
+       drop_nlink(inode);
 }
 
 static int ext3_add_nondir(handle_t *handle,
@@ -1643,12 +1644,12 @@ static int ext3_add_nondir(handle_t *handle,
  * is so far negative - it has no inode.
  *
  * If the create succeeds, we fill in the inode information
- * with d_instantiate(). 
+ * with d_instantiate().
  */
 static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
                struct nameidata *nd)
 {
-       handle_t *handle; 
+       handle_t *handle;
        struct inode * inode;
        int err, retries = 0;
 
@@ -1688,7 +1689,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
 
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
                                        2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -1742,7 +1743,7 @@ retry:
        inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
        dir_block = ext3_bread (handle, inode, 0, 1, &err);
        if (!dir_block) {
-               inode->i_nlink--; /* is this nlink == 0? */
+               drop_nlink(inode); /* is this nlink == 0? */
                ext3_mark_inode_dirty(handle, inode);
                iput (inode);
                goto out_stop;
@@ -1774,7 +1775,7 @@ retry:
                iput (inode);
                goto out_stop;
        }
-       dir->i_nlink++;
+       inc_nlink(dir);
        ext3_update_dx_flag(dir);
        ext3_mark_inode_dirty(handle, dir);
        d_instantiate(dentry, inode);
@@ -1813,10 +1814,10 @@ static int empty_dir (struct inode * inode)
        de1 = (struct ext3_dir_entry_2 *)
                        ((char *) de + le16_to_cpu(de->rec_len));
        if (le32_to_cpu(de->inode) != inode->i_ino ||
-                       !le32_to_cpu(de1->inode) || 
+                       !le32_to_cpu(de1->inode) ||
                        strcmp (".", de->name) ||
                        strcmp ("..", de1->name)) {
-               ext3_warning (inode->i_sb, "empty_dir",
+               ext3_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no `.' or `..'",
                              inode->i_ino);
                brelse (bh);
@@ -1883,7 +1884,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
         * being truncated, or files being unlinked. */
 
        /* @@@ FIXME: Observation from aviro:
-        * I think I can trigger J_ASSERT in ext3_orphan_add().  We block 
+        * I think I can trigger J_ASSERT in ext3_orphan_add().  We block
         * here (on lock_super()), so race with ext3_link() which might bump
         * ->i_nlink. For, say it, character device. Not a regular file,
         * not a directory, not a symlink and ->i_nlink > 0.
@@ -1919,8 +1920,8 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
        if (!err)
                list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
 
-       jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
-       jbd_debug(4, "orphan inode %ld will point to %d\n",
+       jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
+       jbd_debug(4, "orphan inode %lu will point to %d\n",
                        inode->i_ino, NEXT_ORPHAN(inode));
 out_unlock:
        unlock_super(sb);
@@ -2044,7 +2045,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
                              "empty directory has nlink!=2 (%d)",
                              inode->i_nlink);
        inode->i_version++;
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        /* There's no need to set i_disksize: the fact that i_nlink is
         * zero will ensure that the right thing happens during any
         * recovery. */
@@ -2052,7 +2053,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
        ext3_orphan_add(handle, inode);
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        ext3_mark_inode_dirty(handle, inode);
-       dir->i_nlink--;
+       drop_nlink(dir);
        ext3_update_dx_flag(dir);
        ext3_mark_inode_dirty(handle, dir);
 
@@ -2103,7 +2104,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
        dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        ext3_update_dx_flag(dir);
        ext3_mark_inode_dirty(handle, dir);
-       inode->i_nlink--;
+       drop_nlink(inode);
        if (!inode->i_nlink)
                ext3_orphan_add(handle, inode);
        inode->i_ctime = dir->i_ctime;
@@ -2129,7 +2130,7 @@ static int ext3_symlink (struct inode * dir,
 
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
                                        2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -2227,7 +2228,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
                DQUOT_INIT(new_dentry->d_inode);
        handle = ext3_journal_start(old_dir, 2 *
                                        EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -2325,7 +2326,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
        }
 
        if (new_inode) {
-               new_inode->i_nlink--;
+               drop_nlink(new_inode);
                new_inode->i_ctime = CURRENT_TIME_SEC;
        }
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
@@ -2336,11 +2337,11 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
                PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
                BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
                ext3_journal_dirty_metadata(handle, dir_bh);
-               old_dir->i_nlink--;
+               drop_nlink(old_dir);
                if (new_inode) {
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                } else {
-                       new_dir->i_nlink++;
+                       inc_nlink(new_dir);
                        ext3_update_dx_flag(new_dir);
                        ext3_mark_inode_dirty(handle, new_dir);
                }
@@ -2393,4 +2394,4 @@ struct inode_operations ext3_special_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .permission     = ext3_permission,
-}; 
+};
index 5e1337fd878a93c4bbd079e3daea0bf3c2d8ec3d..b73cba12f79c0512cb62362a3d5181217b184e22 100644 (file)
@@ -336,7 +336,7 @@ static int verify_reserved_gdb(struct super_block *sb,
        unsigned five = 5;
        unsigned seven = 7;
        unsigned grp;
-       __u32 *p = (__u32 *)primary->b_data;
+       __le32 *p = (__le32 *)primary->b_data;
        int gdbackups = 0;
 
        while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
@@ -380,7 +380,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        struct buffer_head *dind;
        int gdbackups;
        struct ext3_iloc iloc;
-       __u32 *data;
+       __le32 *data;
        int err;
 
        if (test_opt(sb, DEBUG))
@@ -417,7 +417,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
                goto exit_bh;
        }
 
-       data = (__u32 *)dind->b_data;
+       data = (__le32 *)dind->b_data;
        if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
                ext3_warning(sb, __FUNCTION__,
                             "new group %u GDT block "E3FSBLK" not reserved",
@@ -439,8 +439,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        if ((err = ext3_reserve_inode_write(handle, inode, &iloc)))
                goto exit_dindj;
 
-       n_group_desc = (struct buffer_head **)kmalloc((gdb_num + 1) *
-                               sizeof(struct buffer_head *), GFP_KERNEL);
+       n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
+                       GFP_KERNEL);
        if (!n_group_desc) {
                err = -ENOMEM;
                ext3_warning (sb, __FUNCTION__,
@@ -519,7 +519,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        struct buffer_head *dind;
        struct ext3_iloc iloc;
        ext3_fsblk_t blk;
-       __u32 *data, *end;
+       __le32 *data, *end;
        int gdbackups = 0;
        int res, i;
        int err;
@@ -536,8 +536,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        }
 
        blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count;
-       data = (__u32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count;
-       end = (__u32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb);
+       data = (__le32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count;
+       end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb);
 
        /* Get each reserved primary GDT block and verify it holds backups */
        for (res = 0; res < reserved_gdb; res++, blk++) {
@@ -545,7 +545,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
                        ext3_warning(sb, __FUNCTION__,
                                     "reserved block "E3FSBLK
                                     " not at offset %ld",
-                                    blk, (long)(data - (__u32 *)dind->b_data));
+                                    blk,
+                                    (long)(data - (__le32 *)dind->b_data));
                        err = -EINVAL;
                        goto exit_bh;
                }
@@ -560,7 +561,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
                        goto exit_bh;
                }
                if (++data >= end)
-                       data = (__u32 *)dind->b_data;
+                       data = (__le32 *)dind->b_data;
        }
 
        for (i = 0; i < reserved_gdb; i++) {
@@ -584,7 +585,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        blk = input->group * EXT3_BLOCKS_PER_GROUP(sb);
        for (i = 0; i < reserved_gdb; i++) {
                int err2;
-               data = (__u32 *)primary[i]->b_data;
+               data = (__le32 *)primary[i]->b_data;
                /* printk("reserving backup %lu[%u] = %lu\n",
                       primary[i]->b_blocknr, gdbackups,
                       blk + primary[i]->b_blocknr); */
@@ -689,7 +690,7 @@ exit_err:
                             "can't update backup for group %d (err %d), "
                             "forcing fsck on next reboot", group, err);
                sbi->s_mount_state &= ~EXT3_VALID_FS;
-               sbi->s_es->s_state &= ~cpu_to_le16(EXT3_VALID_FS);
+               sbi->s_es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
                mark_buffer_dirty(sbi->s_sbh);
        }
 }
@@ -730,6 +731,18 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                return -EPERM;
        }
 
+       if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
+           le32_to_cpu(es->s_blocks_count)) {
+               ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n");
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) <
+           le32_to_cpu(es->s_inodes_count)) {
+               ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n");
+               return -EINVAL;
+       }
+
        if (reserved_gdb || gdb_off == 0) {
                if (!EXT3_HAS_COMPAT_FEATURE(sb,
                                             EXT3_FEATURE_COMPAT_RESIZE_INODE)){
@@ -958,6 +971,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
 
        add = EXT3_BLOCKS_PER_GROUP(sb) - last;
 
+       if (o_blocks_count + add < o_blocks_count) {
+               ext3_warning(sb, __FUNCTION__, "blocks_count overflow");
+               return -EINVAL;
+       }
+
        if (o_blocks_count + add > n_blocks_count)
                add = n_blocks_count - o_blocks_count;
 
index 3559086eee5fb45ce45a79ed4f076b62759e2ce5..8bfd56ef18ca56d9c584b250b77ab3aa1220a337 100644 (file)
@@ -45,7 +45,7 @@
 static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
                             unsigned long journal_devnum);
 static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
-                              int);
+                              unsigned int);
 static void ext3_commit_super (struct super_block * sb,
                               struct ext3_super_block * es,
                               int sync);
@@ -62,13 +62,13 @@ static void ext3_unlockfs(struct super_block *sb);
 static void ext3_write_super (struct super_block * sb);
 static void ext3_write_super_lockfs(struct super_block *sb);
 
-/* 
+/*
  * Wrappers for journal_start/end.
  *
  * The only special thing we need to do here is to make sure that all
  * journal_end calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
- * appropriate. 
+ * appropriate.
  */
 handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
 {
@@ -90,11 +90,11 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
        return journal_start(journal, nblocks);
 }
 
-/* 
+/*
  * The only special thing we need to do here is to make sure that all
  * journal_stop calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
- * appropriate. 
+ * appropriate.
  */
 int __ext3_journal_stop(const char *where, handle_t *handle)
 {
@@ -159,20 +159,21 @@ static void ext3_handle_error(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return;
 
-       if (test_opt (sb, ERRORS_RO)) {
-               printk (KERN_CRIT "Remounting filesystem read-only\n");
-               sb->s_flags |= MS_RDONLY;
-       } else {
+       if (!test_opt (sb, ERRORS_CONT)) {
                journal_t *journal = EXT3_SB(sb)->s_journal;
 
                EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
                if (journal)
                        journal_abort(journal, -EIO);
        }
+       if (test_opt (sb, ERRORS_RO)) {
+               printk (KERN_CRIT "Remounting filesystem read-only\n");
+               sb->s_flags |= MS_RDONLY;
+       }
+       ext3_commit_super(sb, es, 1);
        if (test_opt(sb, ERRORS_PANIC))
                panic("EXT3-fs (device %s): panic forced after error\n",
                        sb->s_id);
-       ext3_commit_super(sb, es, 1);
 }
 
 void ext3_error (struct super_block * sb, const char * function,
@@ -369,16 +370,16 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
 {
        struct list_head *l;
 
-       printk(KERN_ERR "sb orphan head is %d\n", 
+       printk(KERN_ERR "sb orphan head is %d\n",
               le32_to_cpu(sbi->s_es->s_last_orphan));
 
        printk(KERN_ERR "sb_info orphan list:\n");
        list_for_each(l, &sbi->s_orphan) {
                struct inode *inode = orphan_list_entry(l);
                printk(KERN_ERR "  "
-                      "inode %s:%ld at %p: mode %o, nlink %d, next %d\n",
+                      "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
                       inode->i_sb->s_id, inode->i_ino, inode,
-                      inode->i_mode, inode->i_nlink, 
+                      inode->i_mode, inode->i_nlink,
                       NEXT_ORPHAN(inode));
        }
 }
@@ -475,7 +476,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                inode_init_once(&ei->vfs_inode);
        }
 }
+
 static int init_inodecache(void)
 {
        ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
@@ -490,8 +491,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ext3_inode_cachep))
-               printk(KERN_INFO "ext3_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ext3_inode_cachep);
 }
 
 static void ext3_clear_inode(struct inode *inode)
@@ -733,8 +733,8 @@ static match_table_t tokens = {
 
 static ext3_fsblk_t get_sb_block(void **data)
 {
-       ext3_fsblk_t    sb_block;
-       char            *options = (char *) *data;
+       ext3_fsblk_t    sb_block;
+       char            *options = (char *) *data;
 
        if (!options || strncmp(options, "sb=", 3) != 0)
                return 1;       /* Default location */
@@ -753,7 +753,7 @@ static ext3_fsblk_t get_sb_block(void **data)
 }
 
 static int parse_options (char *options, struct super_block *sb,
-                         unsigned long *inum, unsigned long *journal_devnum,
+                         unsigned int *inum, unsigned long *journal_devnum,
                          ext3_fsblk_t *n_blocks_count, int is_remount)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
@@ -1174,7 +1174,8 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
 static int ext3_check_descriptors (struct super_block * sb)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
-       ext3_fsblk_t block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext3_fsblk_t last_block;
        struct ext3_group_desc * gdp = NULL;
        int desc_block = 0;
        int i;
@@ -1183,12 +1184,17 @@ static int ext3_check_descriptors (struct super_block * sb)
 
        for (i = 0; i < sbi->s_groups_count; i++)
        {
+               if (i == sbi->s_groups_count - 1)
+                       last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+               else
+                       last_block = first_block +
+                               (EXT3_BLOCKS_PER_GROUP(sb) - 1);
+
                if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext3_group_desc *)
                                        sbi->s_group_desc[desc_block++]->b_data;
-               if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_block_bitmap) >=
-                               block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_block_bitmap) > last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Block bitmap for group %d"
@@ -1197,9 +1203,8 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_block_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_inode_bitmap) >=
-                               block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Inode bitmap for group %d"
@@ -1208,9 +1213,9 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_inode_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_table) < block ||
-                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
-                   block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
+                   last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Inode table for group %d"
@@ -1219,7 +1224,7 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_inode_table));
                        return 0;
                }
-               block += EXT3_BLOCKS_PER_GROUP(sb);
+               first_block += EXT3_BLOCKS_PER_GROUP(sb);
                gdp++;
        }
 
@@ -1301,17 +1306,17 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                DQUOT_INIT(inode);
                if (inode->i_nlink) {
                        printk(KERN_DEBUG
-                               "%s: truncating inode %ld to %Ld bytes\n",
+                               "%s: truncating inode %lu to %Ld bytes\n",
                                __FUNCTION__, inode->i_ino, inode->i_size);
-                       jbd_debug(2, "truncating inode %ld to %Ld bytes\n",
+                       jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
                                  inode->i_ino, inode->i_size);
                        ext3_truncate(inode);
                        nr_truncates++;
                } else {
                        printk(KERN_DEBUG
-                               "%s: deleting unreferenced inode %ld\n",
+                               "%s: deleting unreferenced inode %lu\n",
                                __FUNCTION__, inode->i_ino);
-                       jbd_debug(2, "deleting unreferenced inode %ld\n",
+                       jbd_debug(2, "deleting unreferenced inode %lu\n",
                                  inode->i_ino);
                        nr_orphans++;
                }
@@ -1390,7 +1395,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        ext3_fsblk_t sb_block = get_sb_block(&data);
        ext3_fsblk_t logic_sb_block;
        unsigned long offset = 0;
-       unsigned long journal_inum = 0;
+       unsigned int journal_inum = 0;
        unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
@@ -1401,11 +1406,10 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        int needs_recovery;
        __le32 features;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
        sbi->s_mount_opt = 0;
        sbi->s_resuid = EXT3_DEF_RESUID;
        sbi->s_resgid = EXT3_DEF_RESGID;
@@ -1483,7 +1487,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
            (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
             EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
             EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))
-               printk(KERN_WARNING 
+               printk(KERN_WARNING
                       "EXT3-fs warning: feature flags set on rev 0 fs, "
                       "running e2fsck is recommended\n");
        /*
@@ -1509,7 +1513,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        if (blocksize < EXT3_MIN_BLOCK_SIZE ||
            blocksize > EXT3_MAX_BLOCK_SIZE) {
-               printk(KERN_ERR 
+               printk(KERN_ERR
                       "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",
                       blocksize, sb->s_id);
                goto failed_mount;
@@ -1533,14 +1537,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
                bh = sb_bread(sb, logic_sb_block);
                if (!bh) {
-                       printk(KERN_ERR 
+                       printk(KERN_ERR
                               "EXT3-fs: Can't read superblock on 2nd try.\n");
                        goto failed_mount;
                }
                es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
                sbi->s_es = es;
                if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
-                       printk (KERN_ERR 
+                       printk (KERN_ERR
                                "EXT3-fs: Magic mismatch, very weird !\n");
                        goto failed_mount;
                }
@@ -1622,10 +1626,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext3;
-       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
-                              le32_to_cpu(es->s_first_data_block) +
-                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
-                             EXT3_BLOCKS_PER_GROUP(sb);
+       sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) - 1)
+                                      / EXT3_BLOCKS_PER_GROUP(sb)) + 1;
        db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /
                   EXT3_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
@@ -1820,7 +1823,7 @@ out_fail:
 /*
  * Setup any per-fs journal parameters now.  We'll do this both on
  * initial mount, once the journal has been initialised but before we've
- * done any recovery; and again on any subsequent remount. 
+ * done any recovery; and again on any subsequent remount.
  */
 static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
 {
@@ -1840,7 +1843,8 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
        spin_unlock(&journal->j_state_lock);
 }
 
-static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
+static journal_t *ext3_get_journal(struct super_block *sb,
+                                  unsigned int journal_inum)
 {
        struct inode *journal_inode;
        journal_t *journal;
@@ -1975,7 +1979,7 @@ static int ext3_load_journal(struct super_block *sb,
                             unsigned long journal_devnum)
 {
        journal_t *journal;
-       int journal_inum = le32_to_cpu(es->s_journal_inum);
+       unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
        dev_t journal_dev;
        int err = 0;
        int really_read_only;
@@ -2061,7 +2065,7 @@ static int ext3_load_journal(struct super_block *sb,
 
 static int ext3_create_journal(struct super_block * sb,
                               struct ext3_super_block * es,
-                              int journal_inum)
+                              unsigned int journal_inum)
 {
        journal_t *journal;
 
@@ -2074,7 +2078,7 @@ static int ext3_create_journal(struct super_block * sb,
        if (!(journal = ext3_get_journal(sb, journal_inum)))
                return -EINVAL;
 
-       printk(KERN_INFO "EXT3-fs: creating new journal on inode %d\n",
+       printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
               journal_inum);
 
        if (journal_create(journal)) {
@@ -2342,10 +2346,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                         */
                        ext3_clear_journal_err(sb, es);
                        sbi->s_mount_state = le16_to_cpu(es->s_state);
-                       if ((ret = ext3_group_extend(sb, es, n_blocks_count))) {
-                               err = ret;
+                       if ((err = ext3_group_extend(sb, es, n_blocks_count)))
                                goto restore_opts;
-                       }
                        if (!ext3_setup_super (sb, es, 0))
                                sb->s_flags &= ~MS_RDONLY;
                }
@@ -2734,7 +2736,7 @@ static int __init init_ext3_fs(void)
 out:
        destroy_inodecache();
 out1:
-       exit_ext3_xattr();
+       exit_ext3_xattr();
        return err;
 }
 
index a44a0562203a3794ac5e82389eb91708e01d036d..f86f2482f01df3a87b8a25ef9941fcc5a3a68b93 100644 (file)
@@ -75,7 +75,7 @@
 
 #ifdef EXT3_XATTR_DEBUG
 # define ea_idebug(inode, f...) do { \
-               printk(KERN_DEBUG "inode %s:%ld: ", \
+               printk(KERN_DEBUG "inode %s:%lu: ", \
                        inode->i_sb->s_id, inode->i_ino); \
                printk(f); \
                printk("\n"); \
@@ -233,7 +233,7 @@ ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
                atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
        if (ext3_xattr_check_block(bh)) {
 bad_block:     ext3_error(inode->i_sb, __FUNCTION__,
-                          "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                          "inode %lu: bad block "E3FSBLK, inode->i_ino,
                           EXT3_I(inode)->i_file_acl);
                error = -EIO;
                goto cleanup;
@@ -375,7 +375,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
                atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
        if (ext3_xattr_check_block(bh)) {
                ext3_error(inode->i_sb, __FUNCTION__,
-                          "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                          "inode %lu: bad block "E3FSBLK, inode->i_ino,
                           EXT3_I(inode)->i_file_acl);
                error = -EIO;
                goto cleanup;
@@ -647,7 +647,7 @@ ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i,
                        le32_to_cpu(BHDR(bs->bh)->h_refcount));
                if (ext3_xattr_check_block(bs->bh)) {
                        ext3_error(sb, __FUNCTION__,
-                               "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                               "inode %lu: bad block "E3FSBLK, inode->i_ino,
                                EXT3_I(inode)->i_file_acl);
                        error = -EIO;
                        goto cleanup;
@@ -848,7 +848,7 @@ cleanup_dquot:
 
 bad_block:
        ext3_error(inode->i_sb, __FUNCTION__,
-                  "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                  "inode %lu: bad block "E3FSBLK, inode->i_ino,
                   EXT3_I(inode)->i_file_acl);
        goto cleanup;
 
@@ -1077,14 +1077,14 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
        bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
        if (!bh) {
                ext3_error(inode->i_sb, __FUNCTION__,
-                       "inode %ld: block "E3FSBLK" read error", inode->i_ino,
+                       "inode %lu: block "E3FSBLK" read error", inode->i_ino,
                        EXT3_I(inode)->i_file_acl);
                goto cleanup;
        }
        if (BHDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
            BHDR(bh)->h_blocks != cpu_to_le32(1)) {
                ext3_error(inode->i_sb, __FUNCTION__,
-                       "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                       "inode %lu: bad block "E3FSBLK, inode->i_ino,
                        EXT3_I(inode)->i_file_acl);
                goto cleanup;
        }
@@ -1211,7 +1211,7 @@ again:
                bh = sb_bread(inode->i_sb, ce->e_block);
                if (!bh) {
                        ext3_error(inode->i_sb, __FUNCTION__,
-                               "inode %ld: block %lu read error",
+                               "inode %lu: block %lu read error",
                                inode->i_ino, (unsigned long) ce->e_block);
                } else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
                                EXT3_XATTR_REFCOUNT_MAX) {
index 97b967b84fc6070b7efc47887345a8e574f5d147..82cc4f59e3bae3302abd291b392eccb90f4e1be4 100644 (file)
@@ -58,8 +58,7 @@ int __init fat_cache_init(void)
 
 void fat_cache_destroy(void)
 {
-       if (kmem_cache_destroy(fat_cache_cachep))
-               printk(KERN_INFO "fat_cache: not all structures were freed\n");
+       kmem_cache_destroy(fat_cache_cachep);
 }
 
 static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
index 698b85bb1dd45855a709635eb6239a4c9bbef0d6..3e50a41662834834538886e5cd0aa4d48d0c3b08 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/dirent.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/compat.h>
 #include <asm/uaccess.h>
 
 static inline loff_t fat_make_i_pos(struct super_block *sb,
@@ -741,10 +742,65 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
        return ret;
 }
 
+#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;
+
+        return 0;
+}
+
+static long fat_compat_dir_ioctl(struct file *file, 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];
+
+       switch (cmd) {
+       case VFAT_IOCTL_READDIR_BOTH32:
+               cmd = VFAT_IOCTL_READDIR_BOTH;
+               break;
+       case VFAT_IOCTL_READDIR_SHORT32:
+               cmd = VFAT_IOCTL_READDIR_SHORT;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       set_fs(KERNEL_DS);
+       lock_kernel();
+       ret = fat_dir_ioctl(file->f_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;
+}
+#endif /* CONFIG_COMPAT */
+
 const struct file_operations fat_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = fat_readdir,
        .ioctl          = fat_dir_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = fat_compat_dir_ioctl,
+#endif
        .fsync          = file_fsync,
 };
 
index 1ee25232e6af3dd4cee629fdeba312f769cd8d02..f4b8f8b3fbdd25ed95df235862171dcf2a905a2a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/blkdev.h>
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg)
@@ -112,15 +113,24 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
        }
 }
 
+static int fat_file_release(struct inode *inode, struct file *filp)
+{
+       if ((filp->f_mode & FMODE_WRITE) &&
+            MSDOS_SB(inode->i_sb)->options.flush) {
+               fat_flush_inodes(inode->i_sb, inode, NULL);
+               blk_congestion_wait(WRITE, HZ/10);
+       }
+       return 0;
+}
+
 const struct file_operations fat_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
-       .readv          = generic_file_readv,
-       .writev         = generic_file_writev,
        .aio_read       = generic_file_aio_read,
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
+       .release        = fat_file_release,
        .ioctl          = fat_generic_ioctl,
        .fsync          = file_fsync,
        .sendfile       = generic_file_sendfile,
@@ -289,6 +299,7 @@ void fat_truncate(struct inode *inode)
        lock_kernel();
        fat_free(inode, nr_clusters);
        unlock_kernel();
+       fat_flush_inodes(inode->i_sb, inode, NULL);
 }
 
 struct inode_operations fat_file_inode_operations = {
index 31b7174176ba76798284286e8f6767419cef7e12..045738032a83d5f4579208881d17088a65326e5a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/vfs.h>
 #include <linux/parser.h>
 #include <linux/uio.h>
+#include <linux/writeback.h>
 #include <asm/unaligned.h>
 
 #ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -50,14 +51,14 @@ static int fat_add_cluster(struct inode *inode)
        return err;
 }
 
-static int __fat_get_blocks(struct inode *inode, sector_t iblock,
-                           unsigned long *max_blocks,
-                           struct buffer_head *bh_result, int create)
+static inline int __fat_get_block(struct inode *inode, sector_t iblock,
+                                 unsigned long *max_blocks,
+                                 struct buffer_head *bh_result, int create)
 {
        struct super_block *sb = inode->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
-       sector_t phys;
        unsigned long mapped_blocks;
+       sector_t phys;
        int err, offset;
 
        err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
@@ -73,7 +74,7 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
 
        if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
                fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
-                            MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
+                       MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
                return -EIO;
        }
 
@@ -93,34 +94,29 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
        err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
        if (err)
                return err;
+
        BUG_ON(!phys);
        BUG_ON(*max_blocks != mapped_blocks);
        set_buffer_new(bh_result);
        map_bh(bh_result, sb, phys);
+
        return 0;
 }
 
-static int fat_get_blocks(struct inode *inode, sector_t iblock,
-                         struct buffer_head *bh_result, int create)
+static int fat_get_block(struct inode *inode, sector_t iblock,
+                        struct buffer_head *bh_result, int create)
 {
        struct super_block *sb = inode->i_sb;
-       int err;
        unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
+       int err;
 
-       err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
+       err = __fat_get_block(inode, iblock, &max_blocks, bh_result, create);
        if (err)
                return err;
        bh_result->b_size = max_blocks << sb->s_blocksize_bits;
        return 0;
 }
 
-static int fat_get_block(struct inode *inode, sector_t iblock,
-                        struct buffer_head *bh_result, int create)
-{
-       unsigned long max_blocks = 1;
-       return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
-}
-
 static int fat_writepage(struct page *page, struct writeback_control *wbc)
 {
        return block_write_full_page(page, fat_get_block, wbc);
@@ -188,7 +184,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
         * condition of fat_get_block() and ->truncate().
         */
        return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-                                 offset, nr_segs, fat_get_blocks, NULL);
+                                 offset, nr_segs, fat_get_block, NULL);
 }
 
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
@@ -375,8 +371,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                        inode->i_flags |= S_IMMUTABLE;
        }
        MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
-       /* this is as close to the truth as we can get ... */
-       inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        inode->i_mtime.tv_sec =
@@ -528,8 +522,7 @@ static int __init fat_init_inodecache(void)
 
 static void __exit fat_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(fat_inode_cachep))
-               printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(fat_inode_cachep);
 }
 
 static int fat_remount(struct super_block *sb, int *flags, char *data)
@@ -861,7 +854,7 @@ enum {
        Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
        Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
        Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
-       Opt_obsolate, Opt_err,
+       Opt_obsolate, Opt_flush, Opt_err,
 };
 
 static match_table_t fat_tokens = {
@@ -893,7 +886,8 @@ static match_table_t fat_tokens = {
        {Opt_obsolate, "cvf_format=%20s"},
        {Opt_obsolate, "cvf_options=%100s"},
        {Opt_obsolate, "posix"},
-       {Opt_err, NULL}
+       {Opt_flush, "flush"},
+       {Opt_err, NULL},
 };
 static match_table_t msdos_tokens = {
        {Opt_nodots, "nodots"},
@@ -1034,6 +1028,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                                return 0;
                        opts->codepage = option;
                        break;
+               case Opt_flush:
+                       opts->flush = 1;
+                       break;
 
                /* msdos specific */
                case Opt_dots:
@@ -1137,7 +1134,6 @@ static int fat_read_root(struct inode *inode)
                MSDOS_I(inode)->i_start = 0;
                inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
        }
-       inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        MSDOS_I(inode)->i_logstart = 0;
@@ -1168,11 +1164,10 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        long error;
        char buf[50];
 
-       sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct msdos_sb_info));
 
        sb->s_flags |= MS_NODIRATIME;
        sb->s_magic = MSDOS_SUPER_MAGIC;
@@ -1435,6 +1430,56 @@ out_fail:
 
 EXPORT_SYMBOL_GPL(fat_fill_super);
 
+/*
+ * helper function for fat_flush_inodes.  This writes both the inode
+ * and the file data blocks, waiting for in flight data blocks before
+ * the start of the call.  It does not wait for any io started
+ * during the call
+ */
+static int writeback_inode(struct inode *inode)
+{
+
+       int ret;
+       struct address_space *mapping = inode->i_mapping;
+       struct writeback_control wbc = {
+              .sync_mode = WB_SYNC_NONE,
+             .nr_to_write = 0,
+       };
+       /* if we used WB_SYNC_ALL, sync_inode waits for the io for the
+       * inode to finish.  So WB_SYNC_NONE is sent down to sync_inode
+       * and filemap_fdatawrite is used for the data blocks
+       */
+       ret = sync_inode(inode, &wbc);
+       if (!ret)
+              ret = filemap_fdatawrite(mapping);
+       return ret;
+}
+
+/*
+ * write data and metadata corresponding to i1 and i2.  The io is
+ * started but we do not wait for any of it to finish.
+ *
+ * filemap_flush is used for the block device, so if there is a dirty
+ * page for a block already in flight, we will not wait and start the
+ * io over again
+ */
+int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2)
+{
+       int ret = 0;
+       if (!MSDOS_SB(sb)->options.flush)
+               return 0;
+       if (i1)
+               ret = writeback_inode(i1);
+       if (!ret && i2)
+               ret = writeback_inode(i2);
+       if (!ret && sb) {
+               struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+               ret = filemap_flush(mapping);
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(fat_flush_inodes);
+
 static int __init init_fat_fs(void)
 {
        int err;
index b3c6b82e6a9d8629446e77268a83a2c5c4eb1b62..8e81775c5dc818bd3b9d66e3fd895524294f5c78 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -281,80 +281,70 @@ static struct fdtable *alloc_fdtable(int nr)
 out2:
        nfds = fdt->max_fdset;
 out:
-       if (new_openset)
-               free_fdset(new_openset, nfds);
-       if (new_execset)
-               free_fdset(new_execset, nfds);
+       free_fdset(new_openset, nfds);
+       free_fdset(new_execset, nfds);
        kfree(fdt);
        return NULL;
 }
 
 /*
- * Expands the file descriptor table - it will allocate a new fdtable and
- * both fd array and fdset. It is expected to be called with the
- * files_lock held.
+ * Expand the file descriptor table.
+ * This function will allocate a new fdtable and both fd array and fdset, of
+ * the given size.
+ * Return <0 error code on error; 1 on successful completion.
+ * The files->file_lock should be held on entry, and will be held on exit.
  */
 static int expand_fdtable(struct files_struct *files, int nr)
        __releases(files->file_lock)
        __acquires(files->file_lock)
 {
-       int error = 0;
-       struct fdtable *fdt;
-       struct fdtable *nfdt = NULL;
+       struct fdtable *new_fdt, *cur_fdt;
 
        spin_unlock(&files->file_lock);
-       nfdt = alloc_fdtable(nr);
-       if (!nfdt) {
-               error = -ENOMEM;
-               spin_lock(&files->file_lock);
-               goto out;
-       }
-
+       new_fdt = alloc_fdtable(nr);
        spin_lock(&files->file_lock);
-       fdt = files_fdtable(files);
+       if (!new_fdt)
+               return -ENOMEM;
        /*
-        * Check again since another task may have expanded the
-        * fd table while we dropped the lock
+        * Check again since another task may have expanded the fd table while
+        * we dropped the lock
         */
-       if (nr >= fdt->max_fds || nr >= fdt->max_fdset) {
-               copy_fdtable(nfdt, fdt);
+       cur_fdt = files_fdtable(files);
+       if (nr >= cur_fdt->max_fds || nr >= cur_fdt->max_fdset) {
+               /* Continue as planned */
+               copy_fdtable(new_fdt, cur_fdt);
+               rcu_assign_pointer(files->fdt, new_fdt);
+               free_fdtable(cur_fdt);
        } else {
-               /* Somebody expanded while we dropped file_lock */
-               spin_unlock(&files->file_lock);
-               __free_fdtable(nfdt);
-               spin_lock(&files->file_lock);
-               goto out;
+               /* Somebody else expanded, so undo our attempt */
+               __free_fdtable(new_fdt);
        }
-       rcu_assign_pointer(files->fdt, nfdt);
-       free_fdtable(fdt);
-out:
-       return error;
+       return 1;
 }
 
 /*
  * Expand files.
- * Return <0 on error; 0 nothing done; 1 files expanded, we may have blocked.
- * Should be called with the files->file_lock spinlock held for write.
+ * This function will expand the file structures, if the requested size exceeds
+ * the current capacity and there is room for expansion.
+ * Return <0 error code on error; 0 when nothing done; 1 when files were
+ * expanded and execution may have blocked.
+ * The files->file_lock should be held on entry, and will be held on exit.
  */
 int expand_files(struct files_struct *files, int nr)
 {
-       int err, expand = 0;
        struct fdtable *fdt;
 
        fdt = files_fdtable(files);
-       if (nr >= fdt->max_fdset || nr >= fdt->max_fds) {
-               if (fdt->max_fdset >= NR_OPEN ||
-                       fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) {
-                       err = -EMFILE;
-                       goto out;
-               }
-               expand = 1;
-               if ((err = expand_fdtable(files, nr)))
-                       goto out;
-       }
-       err = expand;
-out:
-       return err;
+       /* Do we need to expand? */
+       if (nr < fdt->max_fdset && nr < fdt->max_fds)
+               return 0;
+       /* Can we expand? */
+       if (fdt->max_fdset >= NR_OPEN || fdt->max_fds >= NR_OPEN ||
+           nr >= NR_OPEN)
+               return -EMFILE;
+
+       /* All good, so we try */
+       return expand_fdtable(files, nr);
 }
 
 static void __devinit fdtable_defer_list_init(int cpu)
index 0131ba06e1ee48bc9714805efa8b15a11a21edcc..bc35a40417d7ada53223f5c93ed26875af97a646 100644 (file)
@@ -169,7 +169,7 @@ void fastcall __fput(struct file *file)
        if (file->f_op && file->f_op->release)
                file->f_op->release(inode, file);
        security_file_free(file);
-       if (unlikely(inode->i_cdev != NULL))
+       if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
                cdev_put(inode->i_cdev);
        fops_put(file->f_op);
        if (file->f_mode & FMODE_WRITE)
index 9f1072836c8ea5c940c916d8236365a26c78da84..e3fa77c6ed56dce64e3fe68892022edaa85d0e56 100644 (file)
@@ -69,8 +69,6 @@ int register_filesystem(struct file_system_type * fs)
        int res = 0;
        struct file_system_type ** p;
 
-       if (!fs)
-               return -EINVAL;
        if (fs->next)
                return -EBUSY;
        INIT_LIST_HEAD(&fs->fs_supers);
index d35979a58743599adbd82e61dc83f41bc5658efd..c8a92652612aad1352ba491b50a165624ceaba7a 100644 (file)
@@ -252,7 +252,7 @@ enum {
  * Get filesystem private data from VFS inode.
  */
 #define VXFS_INO(ip) \
-       ((struct vxfs_inode_info *)(ip)->u.generic_ip)
+       ((struct vxfs_inode_info *)(ip)->i_private)
 
 /*
  * Get filesystem private data from VFS superblock.
index ca6a39714771e317a89ad31c48e08c541438206a..4786d51ad3bd59faa1a7a93c7e944f2b6463fa71 100644 (file)
@@ -239,11 +239,10 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
        ip->i_ctime.tv_nsec = 0;
        ip->i_mtime.tv_nsec = 0;
 
-       ip->i_blksize = PAGE_SIZE;
        ip->i_blocks = vip->vii_blocks;
        ip->i_generation = vip->vii_gen;
 
-       ip->u.generic_ip = (void *)vip;
+       ip->i_private = vip;
        
 }
 
@@ -338,5 +337,5 @@ vxfs_read_inode(struct inode *ip)
 void
 vxfs_clear_inode(struct inode *ip)
 {
-       kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
+       kmem_cache_free(vxfs_inode_cachep, ip->i_private);
 }
index b74b791fc23ba6e4b905e2312518ddde0073ba16..ac28b0835ffc611a0236f3ba745744ba1ca05390 100644 (file)
@@ -260,12 +260,17 @@ static struct file_system_type vxfs_fs_type = {
 static int __init
 vxfs_init(void)
 {
+       int rv;
+
        vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
                        sizeof(struct vxfs_inode_info), 0, 
                        SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL, NULL);
-       if (vxfs_inode_cachep)
-               return register_filesystem(&vxfs_fs_type);
-       return -ENOMEM;
+       if (!vxfs_inode_cachep)
+               return -ENOMEM;
+       rv = register_filesystem(&vxfs_fs_type);
+       if (rv < 0)
+               kmem_cache_destroy(vxfs_inode_cachep);
+       return rv;
 }
 
 static void __exit
index 892643dc9af10a1a6fbf7c858fd430ab209a5724..c403b66ec83c6525532c25decbe923c32356649b 100644 (file)
@@ -22,8 +22,7 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
-
-extern struct super_block *blockdev_superblock;
+#include "internal.h"
 
 /**
  *     __mark_inode_dirty -    internal function
@@ -320,7 +319,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
 
                if (!bdi_cap_writeback_dirty(bdi)) {
                        list_move(&inode->i_list, &sb->s_dirty);
-                       if (sb == blockdev_superblock) {
+                       if (sb_is_blkdev_sb(sb)) {
                                /*
                                 * Dirty memory-backed blockdev: the ramdisk
                                 * driver does this.  Skip just this inode
@@ -337,14 +336,14 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
 
                if (wbc->nonblocking && bdi_write_congested(bdi)) {
                        wbc->encountered_congestion = 1;
-                       if (sb != blockdev_superblock)
+                       if (!sb_is_blkdev_sb(sb))
                                break;          /* Skip a congested fs */
                        list_move(&inode->i_list, &sb->s_dirty);
                        continue;               /* Skip a congested blockdev */
                }
 
                if (wbc->bdi && bdi != wbc->bdi) {
-                       if (sb != blockdev_superblock)
+                       if (!sb_is_blkdev_sb(sb))
                                break;          /* fs has the wrong queue */
                        list_move(&inode->i_list, &sb->s_dirty);
                        continue;               /* blockdev has wrong queue */
index 46fe60b2da23b2eafad38d99b62c8edacba4dd1b..16b39c053d470c3d3cc71c3881c0f5c8c834864b 100644 (file)
@@ -23,7 +23,7 @@ static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
 {
        struct fuse_conn *fc;
        mutex_lock(&fuse_mutex);
-       fc = file->f_dentry->d_inode->u.generic_ip;
+       fc = file->f_dentry->d_inode->i_private;
        if (fc)
                fc = fuse_conn_get(fc);
        mutex_unlock(&fuse_mutex);
@@ -98,7 +98,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
                inode->i_op = iop;
        inode->i_fop = fop;
        inode->i_nlink = nlink;
-       inode->u.generic_ip = fc;
+       inode->i_private = fc;
        d_add(dentry, inode);
        return dentry;
 }
@@ -116,7 +116,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
                return 0;
 
        parent = fuse_control_sb->s_root;
-       parent->d_inode->i_nlink++;
+       inc_nlink(parent->d_inode);
        sprintf(name, "%llu", (unsigned long long) fc->id);
        parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
                                     &simple_dir_inode_operations,
@@ -150,7 +150,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
 
        for (i = fc->ctl_ndents - 1; i >= 0; i--) {
                struct dentry *dentry = fc->ctl_dentry[i];
-               dentry->d_inode->u.generic_ip = NULL;
+               dentry->d_inode->i_private = NULL;
                d_drop(dentry);
                dput(dentry);
        }
index 1e2006caf15842b2c2beffe11968f3cc6311f16f..66571eafbb1eb88afd8acc0e3625bdc0342207df 100644 (file)
@@ -212,6 +212,7 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
  * Called with fc->lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
+       __releases(fc->lock)
 {
        void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
        req->end = NULL;
@@ -640,6 +641,7 @@ static void request_wait(struct fuse_conn *fc)
  */
 static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req,
                               const struct iovec *iov, unsigned long nr_segs)
+       __releases(fc->lock)
 {
        struct fuse_copy_state cs;
        struct fuse_in_header ih;
@@ -678,14 +680,15 @@ static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req,
  * request_end().  Otherwise add it to the processing list, and set
  * the 'sent' flag.
  */
-static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
-                             unsigned long nr_segs, loff_t *off)
+static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
+                             unsigned long nr_segs, loff_t pos)
 {
        int err;
        struct fuse_req *req;
        struct fuse_in *in;
        struct fuse_copy_state cs;
        unsigned reqsize;
+       struct file *file = iocb->ki_filp;
        struct fuse_conn *fc = fuse_get_conn(file);
        if (!fc)
                return -EPERM;
@@ -759,15 +762,6 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
        return err;
 }
 
-static ssize_t fuse_dev_read(struct file *file, char __user *buf,
-                            size_t nbytes, loff_t *off)
-{
-       struct iovec iov;
-       iov.iov_len = nbytes;
-       iov.iov_base = buf;
-       return fuse_dev_readv(file, &iov, 1, off);
-}
-
 /* Look up request on processing list by unique ID */
 static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
 {
@@ -812,15 +806,15 @@ static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
  * it from the list and copy the rest of the buffer to the request.
  * The request is finished by calling request_end()
  */
-static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
-                              unsigned long nr_segs, loff_t *off)
+static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
+                              unsigned long nr_segs, loff_t pos)
 {
        int err;
        unsigned nbytes = iov_length(iov, nr_segs);
        struct fuse_req *req;
        struct fuse_out_header oh;
        struct fuse_copy_state cs;
-       struct fuse_conn *fc = fuse_get_conn(file);
+       struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp);
        if (!fc)
                return -EPERM;
 
@@ -896,15 +890,6 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
        return err;
 }
 
-static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
-                             size_t nbytes, loff_t *off)
-{
-       struct iovec iov;
-       iov.iov_len = nbytes;
-       iov.iov_base = (char __user *) buf;
-       return fuse_dev_writev(file, &iov, 1, off);
-}
-
 static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
 {
        unsigned mask = POLLOUT | POLLWRNORM;
@@ -1039,10 +1024,10 @@ static int fuse_dev_fasync(int fd, struct file *file, int on)
 const struct file_operations fuse_dev_operations = {
        .owner          = THIS_MODULE,
        .llseek         = no_llseek,
-       .read           = fuse_dev_read,
-       .readv          = fuse_dev_readv,
-       .write          = fuse_dev_write,
-       .writev         = fuse_dev_writev,
+       .read           = do_sync_read,
+       .aio_read       = fuse_dev_read,
+       .write          = do_sync_write,
+       .aio_write      = fuse_dev_write,
        .poll           = fuse_dev_poll,
        .release        = fuse_dev_release,
        .fasync         = fuse_dev_fasync,
index 409ce6a7cca4ccd2e53f46693a5e4301bef87245..8605155db171359398c952d8319c551a95fb305b 100644 (file)
@@ -508,7 +508,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
                /* Set nlink to zero so the inode can be cleared, if
                    the inode does have more links this will be
                    discovered at the next lookup/getattr */
-               inode->i_nlink = 0;
+               clear_nlink(inode);
                fuse_invalidate_attr(inode);
                fuse_invalidate_attr(dir);
                fuse_invalidate_entry_cache(entry);
@@ -534,7 +534,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
        err = req->out.h.error;
        fuse_put_request(fc, req);
        if (!err) {
-               entry->d_inode->i_nlink = 0;
+               clear_nlink(entry->d_inode);
                fuse_invalidate_attr(dir);
                fuse_invalidate_entry_cache(entry);
        } else if (err == -EINTR)
@@ -776,7 +776,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
                if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
                        return -EACCES;
 
-               if (nd && (nd->flags & LOOKUP_ACCESS))
+               if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
                        return fuse_access(inode, mask);
                return 0;
        }
index 5c4fcd1dbf5908d29401aa3f83d1aac23a1d8244..183626868eea602d4658e5395ec31f46130c0afe 100644 (file)
@@ -753,8 +753,10 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
 
 static const struct file_operations fuse_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = fuse_file_mmap,
        .open           = fuse_open,
        .flush          = fuse_flush,
index 7d25092262ae71d3eb0af390b60b8e8a0c587a9e..7d0a9aee01f248ef70bb1796a013fca8dda571af 100644 (file)
@@ -118,7 +118,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
        inode->i_uid     = attr->uid;
        inode->i_gid     = attr->gid;
        i_size_write(inode, attr->size);
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks  = attr->blocks;
        inode->i_atime.tv_sec   = attr->atime;
        inode->i_atime.tv_nsec  = attr->atimensec;
@@ -252,6 +251,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
        memset(&outarg, 0, sizeof(outarg));
        req->in.numargs = 0;
        req->in.h.opcode = FUSE_STATFS;
+       req->in.h.nodeid = get_node_id(dentry->d_inode);
        req->out.numargs = 1;
        req->out.args[0].size =
                fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
new file mode 100644 (file)
index 0000000..9ccb789
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * fs/generic_acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/generic_acl.h>
+
+/**
+ * generic_acl_list  -  Generic xattr_handler->list() operation
+ * @ops:       Filesystem specific getacl and setacl callbacks
+ */
+size_t
+generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
+                int type, char *list, size_t list_size)
+{
+       struct posix_acl *acl;
+       const char *name;
+       size_t size;
+
+       acl = ops->getacl(inode, type);
+       if (!acl)
+               return 0;
+       posix_acl_release(acl);
+
+       switch(type) {
+               case ACL_TYPE_ACCESS:
+                       name = POSIX_ACL_XATTR_ACCESS;
+                       break;
+
+               case ACL_TYPE_DEFAULT:
+                       name = POSIX_ACL_XATTR_DEFAULT;
+                       break;
+
+               default:
+                       return 0;
+       }
+       size = strlen(name) + 1;
+       if (list && size <= list_size)
+               memcpy(list, name, size);
+       return size;
+}
+
+/**
+ * generic_acl_get  -  Generic xattr_handler->get() operation
+ * @ops:       Filesystem specific getacl and setacl callbacks
+ */
+int
+generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
+               int type, void *buffer, size_t size)
+{
+       struct posix_acl *acl;
+       int error;
+
+       acl = ops->getacl(inode, type);
+       if (!acl)
+               return -ENODATA;
+       error = posix_acl_to_xattr(acl, buffer, size);
+       posix_acl_release(acl);
+
+       return error;
+}
+
+/**
+ * generic_acl_set  -  Generic xattr_handler->set() operation
+ * @ops:       Filesystem specific getacl and setacl callbacks
+ */
+int
+generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
+               int type, const void *value, size_t size)
+{
+       struct posix_acl *acl = NULL;
+       int error;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+       if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+               return -EPERM;
+       if (value) {
+               acl = posix_acl_from_xattr(value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+       }
+       if (acl) {
+               mode_t mode;
+
+               error = posix_acl_valid(acl);
+               if (error)
+                       goto failed;
+               switch(type) {
+                       case ACL_TYPE_ACCESS:
+                               mode = inode->i_mode;
+                               error = posix_acl_equiv_mode(acl, &mode);
+                               if (error < 0)
+                                       goto failed;
+                               inode->i_mode = mode;
+                               if (error == 0) {
+                                       posix_acl_release(acl);
+                                       acl = NULL;
+                               }
+                               break;
+
+                       case ACL_TYPE_DEFAULT:
+                               if (!S_ISDIR(inode->i_mode)) {
+                                       error = -EINVAL;
+                                       goto failed;
+                               }
+                               break;
+               }
+       }
+       ops->setacl(inode, type, acl);
+       error = 0;
+failed:
+       posix_acl_release(acl);
+       return error;
+}
+
+/**
+ * generic_acl_init  -  Take care of acl inheritance at @inode create time
+ * @ops:       Filesystem specific getacl and setacl callbacks
+ *
+ * Files created inside a directory with a default ACL inherit the
+ * directory's default ACL.
+ */
+int
+generic_acl_init(struct inode *inode, struct inode *dir,
+                struct generic_acl_operations *ops)
+{
+       struct posix_acl *acl = NULL;
+       mode_t mode = inode->i_mode;
+       int error;
+
+       inode->i_mode = mode & ~current->fs->umask;
+       if (!S_ISLNK(inode->i_mode))
+               acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
+       if (acl) {
+               struct posix_acl *clone;
+
+               if (S_ISDIR(inode->i_mode)) {
+                       clone = posix_acl_clone(acl, GFP_KERNEL);
+                       error = -ENOMEM;
+                       if (!clone)
+                               goto cleanup;
+                       ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
+                       posix_acl_release(clone);
+               }
+               clone = posix_acl_clone(acl, GFP_KERNEL);
+               error = -ENOMEM;
+               if (!clone)
+                       goto cleanup;
+               error = posix_acl_create_masq(clone, &mode);
+               if (error >= 0) {
+                       inode->i_mode = mode;
+                       if (error > 0)
+                               ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+               }
+               posix_acl_release(clone);
+       }
+       error = 0;
+
+cleanup:
+       posix_acl_release(acl);
+       return error;
+}
+
+/**
+ * generic_acl_chmod  -  change the access acl of @inode upon chmod()
+ * @ops:       FIlesystem specific getacl and setacl callbacks
+ *
+ * A chmod also changes the permissions of the owner, group/mask, and
+ * other ACL entries.
+ */
+int
+generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
+{
+       struct posix_acl *acl, *clone;
+       int error = 0;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+       acl = ops->getacl(inode, ACL_TYPE_ACCESS);
+       if (acl) {
+               clone = posix_acl_clone(acl, GFP_KERNEL);
+               posix_acl_release(acl);
+               if (!clone)
+                       return -ENOMEM;
+               error = posix_acl_chmod_masq(clone, inode->i_mode);
+               if (!error)
+                       ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+               posix_acl_release(clone);
+       }
+       return error;
+}
index 13231dd5ce660c7ac5e16e476306289b12151c41..0d200068d0afaff014db5279d46c74dab06332bb 100644 (file)
@@ -249,10 +249,9 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
        sb = tree->inode->i_sb;
        size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
                sizeof(struct page *);
-       node = kmalloc(size, GFP_KERNEL);
+       node = kzalloc(size, GFP_KERNEL);
        if (!node)
                return NULL;
-       memset(node, 0, size);
        node->tree = tree;
        node->this = cnid;
        set_bit(HFS_BNODE_NEW, &node->flags);
index 40035799431992573e1e97f87e25e666f1061ddf..5fd0ed71f92331c3553ef9d563c0543e9fc9e9f6 100644 (file)
@@ -21,10 +21,9 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
        struct page *page;
        unsigned int size;
 
-       tree = kmalloc(sizeof(*tree), GFP_KERNEL);
+       tree = kzalloc(sizeof(*tree), GFP_KERNEL);
        if (!tree)
                return NULL;
-       memset(tree, 0, sizeof(*tree));
 
        init_MUTEX(&tree->tree_lock);
        spin_lock_init(&tree->hash_lock);
index 7cd8cc03aea7790159aa7ce5263e73655dabfd8d..37d681b4f2162da24cdaacd9b93e07108e041173 100644 (file)
@@ -246,7 +246,7 @@ static int hfs_unlink(struct inode *dir, struct dentry *dentry)
        if (res)
                return res;
 
-       inode->i_nlink--;
+       drop_nlink(inode);
        hfs_delete_inode(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
@@ -273,7 +273,7 @@ static int hfs_rmdir(struct inode *dir, struct dentry *dentry)
        res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
        if (res)
                return res;
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        hfs_delete_inode(inode);
        mark_inode_dirty(inode);
index 315cf44a90b23e60a55910c484a71d661e64fbd2..02f5573e03491b597a7d68b40fb45f72f87e4a07 100644 (file)
@@ -154,7 +154,6 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
        inode->i_gid = current->fsgid;
        inode->i_nlink = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blksize = HFS_SB(sb)->alloc_blksz;
        HFS_I(inode)->flags = 0;
        HFS_I(inode)->rsrc_inode = NULL;
        HFS_I(inode)->fs_blocks = 0;
@@ -284,7 +283,6 @@ static int hfs_read_inode(struct inode *inode, void *data)
        inode->i_uid = hsb->s_uid;
        inode->i_gid = hsb->s_gid;
        inode->i_nlink = 1;
-       inode->i_blksize = HFS_SB(inode->i_sb)->alloc_blksz;
 
        if (idata->key)
                HFS_I(inode)->cat_key = *idata->key;
@@ -603,8 +601,10 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 
 static const struct file_operations hfs_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .sendfile       = generic_file_sendfile,
        .fsync          = file_fsync,
index 34937ee83ab1052d2510d1ead5d3ca9fdf78af63..d43b4fcc8ad3967d08d353547af2d1f138e3e282 100644 (file)
@@ -356,11 +356,10 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *root_inode;
        int res;
 
-       sbi = kmalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct hfs_sb_info));
        INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 
        res = -EINVAL;
@@ -455,8 +454,7 @@ static int __init init_hfs_fs(void)
 static void __exit exit_hfs_fs(void)
 {
        unregister_filesystem(&hfs_fs_type);
-       if (kmem_cache_destroy(hfs_inode_cachep))
-               printk(KERN_ERR "hfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(hfs_inode_cachep);
 }
 
 module_init(init_hfs_fs)
index 77bf434da6796d89a9181ae50f9af0dd60a6bcf5..29da6574ba77941b22c15b4e959cd4c84b8bbee1 100644 (file)
@@ -409,10 +409,9 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
        sb = tree->inode->i_sb;
        size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
                sizeof(struct page *);
-       node = kmalloc(size, GFP_KERNEL);
+       node = kzalloc(size, GFP_KERNEL);
        if (!node)
                return NULL;
-       memset(node, 0, size);
        node->tree = tree;
        node->this = cnid;
        set_bit(HFS_BNODE_NEW, &node->flags);
index cfc852fdd1b574b0455db793706018ecdb80aef0..a9b9e872e29a6296ecd4d327bd8f2653beeb7a3e 100644 (file)
@@ -24,10 +24,9 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
        struct page *page;
        unsigned int size;
 
-       tree = kmalloc(sizeof(*tree), GFP_KERNEL);
+       tree = kzalloc(sizeof(*tree), GFP_KERNEL);
        if (!tree)
                return NULL;
-       memset(tree, 0, sizeof(*tree));
 
        init_MUTEX(&tree->tree_lock);
        spin_lock_init(&tree->hash_lock);
index 1f9ece0de326227af5a15c238aca2f7b78a61aa0..7e309751645f1618feec1547b502a5cbf5f03032 100644 (file)
@@ -298,7 +298,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
        if (res)
                return res;
 
-       inode->i_nlink++;
+       inc_nlink(inode);
        hfsplus_instantiate(dst_dentry, inode, cnid);
        atomic_inc(&inode->i_count);
        inode->i_ctime = CURRENT_TIME_SEC;
@@ -338,7 +338,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
                return res;
 
        if (inode->i_nlink > 0)
-               inode->i_nlink--;
+               drop_nlink(inode);
        hfsplus_delete_inode(inode);
        if (inode->i_ino != cnid && !inode->i_nlink) {
                if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
@@ -348,7 +348,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
                } else
                        inode->i_flags |= S_DEAD;
        } else
-               inode->i_nlink = 0;
+               clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
 
@@ -387,7 +387,7 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
        res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
        if (res)
                return res;
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        hfsplus_delete_inode(inode);
        mark_inode_dirty(inode);
index 8a1ca5ef7ada1f26468d031ee0882d61e350ca36..3915635b4470bcaa29ce094acb10b9620bf8d2c9 100644 (file)
@@ -246,12 +246,8 @@ struct hfsplus_readdir_data {
 
 /* ext2 ioctls (EXT2_IOC_GETFLAGS and EXT2_IOC_SETFLAGS) to support
  * chattr/lsattr */
-#define HFSPLUS_IOC_EXT2_GETFLAGS      _IOR('f', 1, long)
-#define HFSPLUS_IOC_EXT2_SETFLAGS      _IOW('f', 2, long)
-
-#define EXT2_FLAG_IMMUTABLE            0x00000010 /* Immutable file */
-#define EXT2_FLAG_APPEND               0x00000020 /* writes to file may only append */
-#define EXT2_FLAG_NODUMP               0x00000040 /* do not dump file */
+#define HFSPLUS_IOC_EXT2_GETFLAGS      FS_IOC_GETFLAGS
+#define HFSPLUS_IOC_EXT2_SETFLAGS      FS_IOC_SETFLAGS
 
 
 /*
index 924ecdef8091fa0323ae03e62417263cbc055330..9e36752496336fa86ea19a7fbb3bdf6e73e8d2fd 100644 (file)
@@ -282,8 +282,10 @@ static struct inode_operations hfsplus_file_inode_operations = {
 
 static const struct file_operations hfsplus_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .sendfile       = generic_file_sendfile,
        .fsync          = file_fsync,
@@ -304,7 +306,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
        inode->i_gid = current->fsgid;
        inode->i_nlink = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blksize = HFSPLUS_SB(sb).alloc_blksz;
        INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
        init_MUTEX(&HFSPLUS_I(inode).extents_lock);
        atomic_set(&HFSPLUS_I(inode).opencnt, 0);
@@ -407,7 +408,6 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
 
        HFSPLUS_I(inode).dev = 0;
-       inode->i_blksize = HFSPLUS_SB(inode->i_sb).alloc_blksz;
        if (type == HFSPLUS_FOLDER) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
index 13cf848ac8330ef03ebfbce82e3ce3ba07d5bc2c..79fd10402ea3479d3aaad8b7f6b780fa6a362216 100644 (file)
@@ -28,11 +28,11 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        case HFSPLUS_IOC_EXT2_GETFLAGS:
                flags = 0;
                if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE)
-                       flags |= EXT2_FLAG_IMMUTABLE; /* EXT2_IMMUTABLE_FL */
+                       flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */
                if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND)
-                       flags |= EXT2_FLAG_APPEND; /* EXT2_APPEND_FL */
+                       flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */
                if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP)
-                       flags |= EXT2_FLAG_NODUMP; /* EXT2_NODUMP_FL */
+                       flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */
                return put_user(flags, (int __user *)arg);
        case HFSPLUS_IOC_EXT2_SETFLAGS: {
                if (IS_RDONLY(inode))
@@ -44,32 +44,31 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                if (get_user(flags, (int __user *)arg))
                        return -EFAULT;
 
-               if (flags & (EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND) ||
+               if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) ||
                    HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) {
                        if (!capable(CAP_LINUX_IMMUTABLE))
                                return -EPERM;
                }
 
                /* don't silently ignore unsupported ext2 flags */
-               if (flags & ~(EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND|
-                             EXT2_FLAG_NODUMP))
+               if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL))
                        return -EOPNOTSUPP;
 
-               if (flags & EXT2_FLAG_IMMUTABLE) { /* EXT2_IMMUTABLE_FL */
+               if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */
                        inode->i_flags |= S_IMMUTABLE;
                        HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE;
                } else {
                        inode->i_flags &= ~S_IMMUTABLE;
                        HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
                }
-               if (flags & EXT2_FLAG_APPEND) { /* EXT2_APPEND_FL */
+               if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */
                        inode->i_flags |= S_APPEND;
                        HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND;
                } else {
                        inode->i_flags &= ~S_APPEND;
                        HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND;
                }
-               if (flags & EXT2_FLAG_NODUMP) /* EXT2_NODUMP_FL */
+               if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */
                        HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP;
                else
                        HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP;
index d279d5924f2857338815f9637567bad248f5a45e..194eede52fa46005949042c37d8e57e3ef8fe7db 100644 (file)
@@ -493,8 +493,7 @@ static int __init init_hfsplus_fs(void)
 static void __exit exit_hfsplus_fs(void)
 {
        unregister_filesystem(&hfsplus_fs_type);
-       if (kmem_cache_destroy(hfsplus_inode_cachep))
-               printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(hfsplus_inode_cachep);
 }
 
 module_init(init_hfsplus_fs)
index b82e3d9c879021ae9882158aa8df2080c73f144e..b6bd33ca3731edafe9866ce0a7a725a2bc3287c3 100644 (file)
@@ -156,7 +156,6 @@ static int read_name(struct inode *ino, char *name)
        ino->i_mode = i_mode;
        ino->i_nlink = i_nlink;
        ino->i_size = i_size;
-       ino->i_blksize = i_blksize;
        ino->i_blocks = i_blocks;
        return(0);
 }
@@ -386,13 +385,11 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 
 static const struct file_operations hostfs_file_fops = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
+       .read           = do_sync_read,
        .sendfile       = generic_file_sendfile,
        .aio_read       = generic_file_aio_read,
        .aio_write      = generic_file_aio_write,
-       .readv          = generic_file_readv,
-       .writev         = generic_file_writev,
-       .write          = generic_file_write,
+       .write          = do_sync_write,
        .mmap           = generic_file_mmap,
        .open           = hostfs_file_open,
        .release        = NULL,
index 2807aa833e62011a42ddeea45e8bc46867907229..b52b7381d10f45710f980b885731654fa5e0442d 100644 (file)
@@ -76,7 +76,7 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
                return NULL;
        }
 
-       qbh->data = data = (char *)kmalloc(2048, GFP_NOFS);
+       qbh->data = data = kmalloc(2048, GFP_NOFS);
        if (!data) {
                printk("HPFS: hpfs_map_4sectors: out of memory\n");
                goto bail;
index d9eb19b7b8aecef05ef1d49d0a12feca4b184755..8b94d24855f00b7ece487dc2b1cd5b5a741af0db 100644 (file)
@@ -113,7 +113,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
 {
        ssize_t retval;
 
-       retval = generic_file_write(file, buf, count, ppos);
+       retval = do_sync_write(file, buf, count, ppos);
        if (retval > 0)
                hpfs_i(file->f_dentry->d_inode)->i_dirty = 1;
        return retval;
@@ -122,8 +122,10 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
 const struct file_operations hpfs_file_ops =
 {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
        .write          = hpfs_file_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .release        = hpfs_file_release,
        .fsync          = hpfs_file_fsync,
index 56f2c338c4d9a1b9a9639447ae7b23666079b461..bcf6ee36e0656b258d050418de151e910c54ff2e 100644 (file)
@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i)
        i->i_gid = hpfs_sb(sb)->sb_gid;
        i->i_mode = hpfs_sb(sb)->sb_mode;
        hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;
-       i->i_blksize = 512;
        i->i_size = -1;
        i->i_blocks = -1;
        
index 59e7dc182a0c760ff78631cf162313ff6b2f97d4..2507e7393f3c6733ebda781bfea8be1d8459e927 100644 (file)
@@ -89,7 +89,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        brelse(bh);
        hpfs_mark_4buffers_dirty(&qbh0);
        hpfs_brelse4(&qbh0);
-       dir->i_nlink++;
+       inc_nlink(dir);
        insert_inode_hash(result);
 
        if (result->i_uid != current->fsuid ||
@@ -434,7 +434,7 @@ again:
                unlock_kernel();
                return -ENOSPC;
        default:
-               inode->i_nlink--;
+               drop_nlink(inode);
                err = 0;
        }
        goto out;
@@ -494,8 +494,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
                err = -ENOSPC;
                break;
        default:
-               dir->i_nlink--;
-               inode->i_nlink = 0;
+               drop_nlink(dir);
+               clear_nlink(inode);
                err = 0;
        }
        goto out;
@@ -590,7 +590,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                int r;
                if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
                        if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, (char *)new_name, new_len, NULL, &qbh1))) {
-                               new_inode->i_nlink = 0;
+                               clear_nlink(new_inode);
                                copy_de(nde, &de);
                                memcpy(nde->name, new_name, new_len);
                                hpfs_mark_4buffers_dirty(&qbh1);
@@ -635,8 +635,8 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        end:
        hpfs_i(i)->i_parent_dir = new_dir->i_ino;
        if (S_ISDIR(i->i_mode)) {
-               new_dir->i_nlink++;
-               old_dir->i_nlink--;
+               inc_nlink(new_dir);
+               drop_nlink(old_dir);
        }
        if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
                fnode->up = new_dir->i_ino;
index 8fe51c343786e99d22c2abb1b2e5b16b8a997364..450b5e0b4785c59431b002e5aa1db2b33aed70b8 100644 (file)
@@ -203,8 +203,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(hpfs_inode_cachep))
-               printk(KERN_INFO "hpfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(hpfs_inode_cachep);
 }
 
 /*
@@ -462,11 +461,10 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
        int o;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
 
        sbi->sb_bmp_dir = NULL;
        sbi->sb_cp_table = NULL;
index 3a9bdf58166f39f1ee946d7e15d8f3b4dc3b40ac..dcb6d2e988b81a3bf86ecabc2a233979c2eff5bc 100644 (file)
@@ -152,7 +152,6 @@ static void hppfs_read_inode(struct inode *ino)
        ino->i_mode = proc_ino->i_mode;
        ino->i_nlink = proc_ino->i_nlink;
        ino->i_size = proc_ino->i_size;
-       ino->i_blksize = proc_ino->i_blksize;
        ino->i_blocks = proc_ino->i_blocks;
 }
 
index c3920c96dadf2f854ab77dcb9741580859f06c95..5e03b2f67b932dcb37d61ed3dbbffb6576141cff 100644 (file)
@@ -229,7 +229,7 @@ static void hugetlbfs_delete_inode(struct inode *inode)
        clear_inode(inode);
 }
 
-static void hugetlbfs_forget_inode(struct inode *inode)
+static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock)
 {
        struct super_block *sb = inode->i_sb;
 
@@ -357,7 +357,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
                inode->i_mode = mode;
                inode->i_uid = uid;
                inode->i_gid = gid;
-               inode->i_blksize = HPAGE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &hugetlbfs_aops;
                inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
@@ -378,7 +377,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
                        inode->i_fop = &simple_dir_operations;
 
                        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        break;
                case S_IFLNK:
                        inode->i_op = &page_symlink_inode_operations;
@@ -419,7 +418,7 @@ static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
        int retval = hugetlbfs_mknod(dir, dentry, mode | S_IFDIR, 0);
        if (!retval)
-               dir->i_nlink++;
+               inc_nlink(dir);
        return retval;
 }
 
index 0bf9f0444a964bb5398e50a533a5a942eb701eae..ada7643104e14dee4bcc8a5dc5bd87b7398aad5f 100644 (file)
@@ -133,7 +133,6 @@ static struct inode *alloc_inode(struct super_block *sb)
                inode->i_bdev = NULL;
                inode->i_cdev = NULL;
                inode->i_rdev = 0;
-               inode->i_security = NULL;
                inode->dirtied_when = 0;
                if (security_inode_alloc(inode)) {
                        if (inode->i_sb->s_op->destroy_inode)
@@ -163,7 +162,7 @@ static struct inode *alloc_inode(struct super_block *sb)
                                bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
                        mapping->backing_dev_info = bdi;
                }
-               memset(&inode->u, 0, sizeof(inode->u));
+               inode->i_private = 0;
                inode->i_mapping = mapping;
        }
        return inode;
@@ -254,9 +253,9 @@ void clear_inode(struct inode *inode)
        DQUOT_DROP(inode);
        if (inode->i_sb && inode->i_sb->s_op->clear_inode)
                inode->i_sb->s_op->clear_inode(inode);
-       if (inode->i_bdev)
+       if (S_ISBLK(inode->i_mode) && inode->i_bdev)
                bd_forget(inode);
-       if (inode->i_cdev)
+       if (S_ISCHR(inode->i_mode) && inode->i_cdev)
                cd_forget(inode);
        inode->i_state = I_CLEAR;
 }
@@ -363,27 +362,6 @@ int invalidate_inodes(struct super_block * sb)
 }
 
 EXPORT_SYMBOL(invalidate_inodes);
-int __invalidate_device(struct block_device *bdev)
-{
-       struct super_block *sb = get_super(bdev);
-       int res = 0;
-
-       if (sb) {
-               /*
-                * no need to lock the super, get_super holds the
-                * read mutex so the filesystem cannot go away
-                * under us (->put_super runs with the write lock
-                * hold).
-                */
-               shrink_dcache_sb(sb);
-               res = invalidate_inodes(sb);
-               drop_super(sb);
-       }
-       invalidate_bdev(bdev, 0);
-       return res;
-}
-EXPORT_SYMBOL(__invalidate_device);
 
 static int can_unuse(struct inode *inode)
 {
diff --git a/fs/internal.h b/fs/internal.h
new file mode 100644 (file)
index 0000000..ea00126
--- /dev/null
@@ -0,0 +1,55 @@
+/* fs/ internal definitions
+ *
+ * Copyright (C) 2006 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/ioctl32.h>
+
+struct super_block;
+
+/*
+ * block_dev.c
+ */
+#ifdef CONFIG_BLOCK
+extern struct super_block *blockdev_superblock;
+extern void __init bdev_cache_init(void);
+
+static inline int sb_is_blkdev_sb(struct super_block *sb)
+{
+       return sb == blockdev_superblock;
+}
+
+#else
+static inline void bdev_cache_init(void)
+{
+}
+
+static inline int sb_is_blkdev_sb(struct super_block *sb)
+{
+       return 0;
+}
+#endif
+
+/*
+ * char_dev.c
+ */
+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
+ */
+extern int copy_mount_options(const void __user *, unsigned long *);
index 78b1deae3fa2e1a9aaa4142fa83050b434840b90..6dc6721d9e822d159fbb7e68cfc047aafe6c4e34 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * fs/ioprio.c
  *
- * Copyright (C) 2004 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk>
  *
  * Helper functions for setting/querying io priorities of processes. The
  * system calls closely mimmick getpriority/setpriority, see the man page for
@@ -47,8 +47,8 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
        /* see wmb() in current_io_context() */
        smp_read_barrier_depends();
 
-       if (ioc && ioc->set_ioprio)
-               ioc->set_ioprio(ioc, ioprio);
+       if (ioc)
+               ioc->ioprio_changed = 1;
 
        task_unlock(task);
        return 0;
@@ -81,7 +81,12 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
        }
 
        ret = -ESRCH;
-       read_lock_irq(&tasklist_lock);
+       /*
+        * We want IOPRIO_WHO_PGRP/IOPRIO_WHO_USER to be "atomic",
+        * so we can't use rcu_read_lock(). See re-copy of ->ioprio
+        * in copy_process().
+        */
+       read_lock(&tasklist_lock);
        switch (which) {
                case IOPRIO_WHO_PROCESS:
                        if (!who)
@@ -124,7 +129,7 @@ free_uid:
                        ret = -EINVAL;
        }
 
-       read_unlock_irq(&tasklist_lock);
+       read_unlock(&tasklist_lock);
        return ret;
 }
 
@@ -170,7 +175,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
        int ret = -ESRCH;
        int tmpio;
 
-       read_lock_irq(&tasklist_lock);
+       read_lock(&tasklist_lock);
        switch (which) {
                case IOPRIO_WHO_PROCESS:
                        if (!who)
@@ -221,7 +226,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
                        ret = -EINVAL;
        }
 
-       read_unlock_irq(&tasklist_lock);
+       read_unlock(&tasklist_lock);
        return ret;
 }
 
index 14391361c8863b63e21fb87f5c2351d752ebcc10..c34b862cdbf204cf5e7124408659f89108289a82 100644 (file)
@@ -96,9 +96,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(isofs_inode_cachep))
-               printk(KERN_INFO "iso_inode_cache: not all structures were "
-                                       "freed\n");
+       kmem_cache_destroy(isofs_inode_cachep);
 }
 
 static int isofs_remount(struct super_block *sb, int *flags, char *data)
@@ -557,11 +555,10 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
        struct iso9660_options          opt;
        struct isofs_sb_info          * sbi;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
 
        if (!parse_options((char *)data, &opt))
                goto out_freesbi;
@@ -963,30 +960,30 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
                        goto abort;
                }
                
-               if (nextblk) {
-                       while (b_off >= (offset + sect_size)) {
-                               struct inode *ninode;
-                               
-                               offset += sect_size;
-                               if (nextblk == 0)
-                                       goto abort;
-                               ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
-                               if (!ninode)
-                                       goto abort;
-                               firstext  = ISOFS_I(ninode)->i_first_extent;
-                               sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
-                               nextblk   = ISOFS_I(ninode)->i_next_section_block;
-                               nextoff   = ISOFS_I(ninode)->i_next_section_offset;
-                               iput(ninode);
-                               
-                               if (++section > 100) {
-                                       printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
-                                       printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
-                                              "nextblk=%lu nextoff=%lu\n",
-                                              iblock, firstext, (unsigned) sect_size,
-                                              nextblk, nextoff);
-                                       goto abort;
-                               }
+               /* On the last section, nextblk == 0, section size is likely to
+                * exceed sect_size by a partial block, and access beyond the
+                * end of the file will reach beyond the section size, too.
+                */
+               while (nextblk && (b_off >= (offset + sect_size))) {
+                       struct inode *ninode;
+
+                       offset += sect_size;
+                       ninode = isofs_iget(inode->i_sb, nextblk, nextoff);
+                       if (!ninode)
+                               goto abort;
+                       firstext  = ISOFS_I(ninode)->i_first_extent;
+                       sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode);
+                       nextblk   = ISOFS_I(ninode)->i_next_section_block;
+                       nextoff   = ISOFS_I(ninode)->i_next_section_offset;
+                       iput(ninode);
+
+                       if (++section > 100) {
+                               printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
+                               printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u "
+                                      "nextblk=%lu nextoff=%lu\n",
+                                      iblock, firstext, (unsigned) sect_size,
+                                      nextblk, nextoff);
+                               goto abort;
                        }
                }
                
@@ -1238,7 +1235,7 @@ static void isofs_read_inode(struct inode *inode)
        }
        inode->i_uid = sbi->s_uid;
        inode->i_gid = sbi->s_gid;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
 
        ei->i_format_parm[0] = 0;
        ei->i_format_parm[1] = 0;
@@ -1294,7 +1291,6 @@ static void isofs_read_inode(struct inode *inode)
                              isonum_711 (de->ext_attr_length));
 
        /* Set the number of blocks for stat() - should be done before RR */
-       inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */
        inode->i_blocks  = (inode->i_size + 511) >> 9;
 
        /*
index 47678a26c13b271d81cb50c56fa94a3fad5ff0cd..0208cc7ac5d0f0835ed0bceb206cce2baef5fae5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/checkpoint.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
  * Copyright 1999 Red Hat Software --- All Rights Reserved
@@ -9,8 +9,8 @@
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
  *
- * Checkpoint routines for the generic filesystem journaling code.  
- * Part of the ext2fs journaling system.  
+ * Checkpoint routines for the generic filesystem journaling code.
+ * Part of the ext2fs journaling system.
  *
  * Checkpointing is the process of ensuring that a section of the log is
  * committed fully to disk, so that that portion of the log can be
@@ -145,6 +145,7 @@ void __log_wait_for_space(journal_t *journal)
  * jbd_unlock_bh_state().
  */
 static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
+       __releases(journal->j_list_lock)
 {
        get_bh(bh);
        spin_unlock(&journal->j_list_lock);
@@ -225,7 +226,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
  * Try to flush one buffer from the checkpoint list to disk.
  *
  * Return 1 if something happened which requires us to abort the current
- * scan of the checkpoint list.  
+ * scan of the checkpoint list.
  *
  * Called with j_list_lock held and drops it if 1 is returned
  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
@@ -269,7 +270,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
                 * possibly block, while still holding the journal lock.
                 * We cannot afford to let the transaction logic start
                 * messing around with this buffer before we write it to
-                * disk, as that would break recoverability.  
+                * disk, as that would break recoverability.
                 */
                BUFFER_TRACE(bh, "queue");
                get_bh(bh);
@@ -292,7 +293,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
  * Perform an actual checkpoint. We take the first transaction on the
  * list of transactions to be checkpointed and send all its buffers
  * to disk. We submit larger chunks of data at once.
- * 
+ *
  * The journal should be locked before calling this function.
  */
 int log_do_checkpoint(journal_t *journal)
@@ -303,10 +304,10 @@ int log_do_checkpoint(journal_t *journal)
 
        jbd_debug(1, "Start checkpoint\n");
 
-       /* 
+       /*
         * First thing: if there are any transactions in the log which
         * don't need checkpointing, just eliminate them from the
-        * journal straight away.  
+        * journal straight away.
         */
        result = cleanup_journal_tail(journal);
        jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
@@ -384,9 +385,9 @@ out:
  * we have already got rid of any since the last update of the log tail
  * in the journal superblock.  If so, we can instantly roll the
  * superblock forward to remove those transactions from the log.
- * 
+ *
  * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
- * 
+ *
  * Called with the journal lock held.
  *
  * This is the only part of the journaling code which really needs to be
@@ -403,8 +404,8 @@ int cleanup_journal_tail(journal_t *journal)
        unsigned long   blocknr, freed;
 
        /* OK, work out the oldest transaction remaining in the log, and
-        * the log block it starts at. 
-        * 
+        * the log block it starts at.
+        *
         * If the log is now empty, we need to work out which is the
         * next transaction ID we will write, and where it will
         * start. */
@@ -479,7 +480,7 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
        if (!jh)
                return 0;
 
-       last_jh = jh->b_cpprev;
+       last_jh = jh->b_cpprev;
        do {
                jh = next_jh;
                next_jh = jh->b_cpnext;
@@ -557,7 +558,7 @@ out:
        return ret;
 }
 
-/* 
+/*
  * journal_remove_checkpoint: called after a buffer has been committed
  * to disk (either by being write-back flushed to disk, or being
  * committed to the log).
@@ -635,7 +636,7 @@ out:
  * Called with the journal locked.
  * Called with j_list_lock held.
  */
-void __journal_insert_checkpoint(struct journal_head *jh, 
+void __journal_insert_checkpoint(struct journal_head *jh,
                               transaction_t *transaction)
 {
        JBUFFER_TRACE(jh, "entry");
@@ -657,7 +658,7 @@ void __journal_insert_checkpoint(struct journal_head *jh,
 
 /*
  * We've finished with this transaction structure: adios...
- * 
+ *
  * The transaction must have no links except for the checkpoint by this
  * point.
  *
index f66724ce443a6ab7be44db95aa68f9359c451427..7af6099c911c2cbb584932f822788b5e92ab4d9f 100644 (file)
@@ -181,7 +181,7 @@ loop:
                                                transaction->t_expires))
                        should_sleep = 0;
                if (journal->j_flags & JFS_UNMOUNT)
-                       should_sleep = 0;
+                       should_sleep = 0;
                if (should_sleep) {
                        spin_unlock(&journal->j_state_lock);
                        schedule();
@@ -271,7 +271,7 @@ static void journal_kill_thread(journal_t *journal)
 int journal_write_metadata_buffer(transaction_t *transaction,
                                  struct journal_head  *jh_in,
                                  struct journal_head **jh_out,
-                                 int blocknr)
+                                 unsigned long blocknr)
 {
        int need_copy_out = 0;
        int done_copy_out = 0;
@@ -578,7 +578,7 @@ int journal_next_log_block(journal_t *journal, unsigned long *retp)
  * this is a no-op.  If needed, we can use j_blk_offset - everything is
  * ready.
  */
-int journal_bmap(journal_t *journal, unsigned long blocknr, 
+int journal_bmap(journal_t *journal, unsigned long blocknr,
                 unsigned long *retp)
 {
        int err = 0;
@@ -696,13 +696,13 @@ fail:
  *  @bdev: Block device on which to create the journal
  *  @fs_dev: Device which hold journalled filesystem for this journal.
  *  @start: Block nr Start of journal.
- *  @len:  Lenght of the journal in blocks.
+ *  @len:  Length of the journal in blocks.
  *  @blocksize: blocksize of journalling device
  *  @returns: a newly created journal_t *
- *  
+ *
  *  journal_init_dev creates a journal which maps a fixed contiguous
  *  range of blocks on an arbitrary block device.
- * 
+ *
  */
 journal_t * journal_init_dev(struct block_device *bdev,
                        struct block_device *fs_dev,
@@ -715,18 +715,8 @@ journal_t * journal_init_dev(struct block_device *bdev,
        if (!journal)
                return NULL;
 
-       journal->j_dev = bdev;
-       journal->j_fs_dev = fs_dev;
-       journal->j_blk_offset = start;
-       journal->j_maxlen = len;
-       journal->j_blocksize = blocksize;
-
-       bh = __getblk(journal->j_dev, start, journal->j_blocksize);
-       J_ASSERT(bh != NULL);
-       journal->j_sb_buffer = bh;
-       journal->j_superblock = (journal_superblock_t *)bh->b_data;
-
        /* journal descriptor can store up to n blocks -bzzz */
+       journal->j_blocksize = blocksize;
        n = journal->j_blocksize / sizeof(journal_block_tag_t);
        journal->j_wbufsize = n;
        journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
@@ -736,14 +726,23 @@ journal_t * journal_init_dev(struct block_device *bdev,
                kfree(journal);
                journal = NULL;
        }
+       journal->j_dev = bdev;
+       journal->j_fs_dev = fs_dev;
+       journal->j_blk_offset = start;
+       journal->j_maxlen = len;
+
+       bh = __getblk(journal->j_dev, start, journal->j_blocksize);
+       J_ASSERT(bh != NULL);
+       journal->j_sb_buffer = bh;
+       journal->j_superblock = (journal_superblock_t *)bh->b_data;
 
        return journal;
 }
-/** 
+
+/**
  *  journal_t * journal_init_inode () - creates a journal which maps to a inode.
  *  @inode: An inode to create the journal in
- *  
+ *
  * journal_init_inode creates a journal which maps an on-disk inode as
  * the journal.  The inode must exist already, must support bmap() and
  * must have all data blocks preallocated.
@@ -763,7 +762,7 @@ journal_t * journal_init_inode (struct inode *inode)
        journal->j_inode = inode;
        jbd_debug(1,
                  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
-                 journal, inode->i_sb->s_id, inode->i_ino, 
+                 journal, inode->i_sb->s_id, inode->i_ino,
                  (long long) inode->i_size,
                  inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
 
@@ -798,10 +797,10 @@ journal_t * journal_init_inode (struct inode *inode)
        return journal;
 }
 
-/* 
+/*
  * If the journal init or create aborts, we need to mark the journal
  * superblock as being NULL to prevent the journal destroy from writing
- * back a bogus superblock. 
+ * back a bogus superblock.
  */
 static void journal_fail_superblock (journal_t *journal)
 {
@@ -820,7 +819,7 @@ static void journal_fail_superblock (journal_t *journal)
 static int journal_reset(journal_t *journal)
 {
        journal_superblock_t *sb = journal->j_superblock;
-       unsigned int first, last;
+       unsigned long first, last;
 
        first = be32_to_cpu(sb->s_first);
        last = be32_to_cpu(sb->s_maxlen);
@@ -844,13 +843,13 @@ static int journal_reset(journal_t *journal)
        return 0;
 }
 
-/** 
+/**
  * int journal_create() - Initialise the new journal file
  * @journal: Journal to create. This structure must have been initialised
- * 
+ *
  * Given a journal_t structure which tells us which disk blocks we can
  * use, create a new journal superblock and initialise all of the
- * journal fields from scratch.  
+ * journal fields from scratch.
  **/
 int journal_create(journal_t *journal)
 {
@@ -915,7 +914,7 @@ int journal_create(journal_t *journal)
        return journal_reset(journal);
 }
 
-/** 
+/**
  * void journal_update_superblock() - Update journal sb on disk.
  * @journal: The journal to update.
  * @wait: Set to '0' if you don't want to wait for IO completion.
@@ -939,7 +938,7 @@ void journal_update_superblock(journal_t *journal, int wait)
                                journal->j_transaction_sequence) {
                jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
                        "(start %ld, seq %d, errno %d)\n",
-                       journal->j_tail, journal->j_tail_sequence, 
+                       journal->j_tail, journal->j_tail_sequence,
                        journal->j_errno);
                goto out;
        }
@@ -1062,7 +1061,7 @@ static int load_superblock(journal_t *journal)
 /**
  * int journal_load() - Read journal from disk.
  * @journal: Journal to act on.
- * 
+ *
  * Given a journal_t structure which tells us which disk blocks contain
  * a journal, read the journal from disk to initialise the in-memory
  * structures.
@@ -1094,7 +1093,7 @@ int journal_load(journal_t *journal)
        /*
         * Create a slab for this blocksize
         */
-       err = journal_create_jbd_slab(cpu_to_be32(sb->s_blocksize));
+       err = journal_create_jbd_slab(be32_to_cpu(sb->s_blocksize));
        if (err)
                return err;
 
@@ -1172,9 +1171,9 @@ void journal_destroy(journal_t *journal)
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
  * @incompat: bitmask of incompatible features
- * 
+ *
  * Check whether the journal uses all of a given set of
- * features.  Return true (non-zero) if it does. 
+ * features.  Return true (non-zero) if it does.
  **/
 
 int journal_check_used_features (journal_t *journal, unsigned long compat,
@@ -1203,7 +1202,7 @@ int journal_check_used_features (journal_t *journal, unsigned long compat,
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
  * @incompat: bitmask of incompatible features
- * 
+ *
  * Check whether the journaling code supports the use of
  * all of a given set of features on this journal.  Return true
  * (non-zero) if it can. */
@@ -1241,7 +1240,7 @@ int journal_check_available_features (journal_t *journal, unsigned long compat,
  * @incompat: bitmask of incompatible features
  *
  * Mark a given journal feature as present on the
- * superblock.  Returns true if the requested features could be set. 
+ * superblock.  Returns true if the requested features could be set.
  *
  */
 
@@ -1327,7 +1326,7 @@ static int journal_convert_superblock_v1(journal_t *journal,
 /**
  * int journal_flush () - Flush journal
  * @journal: Journal to act on.
- * 
+ *
  * Flush all data for a given journal to disk and empty the journal.
  * Filesystems can use this when remounting readonly to ensure that
  * recovery does not need to happen on remount.
@@ -1394,7 +1393,7 @@ int journal_flush(journal_t *journal)
  * int journal_wipe() - Wipe journal contents
  * @journal: Journal to act on.
  * @write: flag (see below)
- * 
+ *
  * Wipe out all of the contents of a journal, safely.  This will produce
  * a warning if the journal contains any valid recovery information.
  * Must be called between journal_init_*() and journal_load().
@@ -1449,7 +1448,7 @@ static const char *journal_dev_name(journal_t *journal, char *buffer)
 
 /*
  * Journal abort has very specific semantics, which we describe
- * for journal abort. 
+ * for journal abort.
  *
  * Two internal function, which provide abort to te jbd layer
  * itself are here.
@@ -1504,7 +1503,7 @@ static void __journal_abort_soft (journal_t *journal, int errno)
  * Perform a complete, immediate shutdown of the ENTIRE
  * journal (not of a single transaction).  This operation cannot be
  * undone without closing and reopening the journal.
- *           
+ *
  * The journal_abort function is intended to support higher level error
  * recovery mechanisms such as the ext2/ext3 remount-readonly error
  * mode.
@@ -1538,7 +1537,7 @@ static void __journal_abort_soft (journal_t *journal, int errno)
  * supply an errno; a null errno implies that absolutely no further
  * writes are done to the journal (unless there are any already in
  * progress).
- * 
+ *
  */
 
 void journal_abort(journal_t *journal, int errno)
@@ -1546,7 +1545,7 @@ void journal_abort(journal_t *journal, int errno)
        __journal_abort_soft(journal, errno);
 }
 
-/** 
+/**
  * int journal_errno () - returns the journal's error state.
  * @journal: journal to examine.
  *
@@ -1570,7 +1569,7 @@ int journal_errno(journal_t *journal)
        return err;
 }
 
-/** 
+/**
  * int journal_clear_err () - clears the journal's error state
  * @journal: journal to act on.
  *
@@ -1590,7 +1589,7 @@ int journal_clear_err(journal_t *journal)
        return err;
 }
 
-/** 
+/**
  * void journal_ack_err() - Ack journal err.
  * @journal: journal to act on.
  *
@@ -1612,7 +1611,7 @@ int journal_blocks_per_page(struct inode *inode)
 
 /*
  * Simple support for retrying memory allocations.  Introduced to help to
- * debug different VM deadlock avoidance strategies. 
+ * debug different VM deadlock avoidance strategies.
  */
 void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
 {
@@ -2047,13 +2046,7 @@ static int __init journal_init(void)
 {
        int ret;
 
-/* Static check for data structure consistency.  There's no code
- * invoked --- we'll just get a linker failure if things aren't right.
- */
-       extern void journal_bad_superblock_size(void);
-       if (sizeof(struct journal_superblock_s) != 1024)
-               journal_bad_superblock_size();
-
+       BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024);
 
        ret = journal_init_caches();
        if (ret != 0)
index de5bafb4e8534db59d76f86bf6352821a6458012..11563fe2a52bed60eafe259d92ae3aedbfa64e98 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/recovery.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
@@ -10,7 +10,7 @@
  * option, any later version, incorporated herein by reference.
  *
  * Journal recovery routines for the generic filesystem journaling code;
- * part of the ext2fs journaling system.  
+ * part of the ext2fs journaling system.
  */
 
 #ifndef __KERNEL__
@@ -25,9 +25,9 @@
 
 /*
  * Maintain information about the progress of the recovery job, so that
- * the different passes can carry information between them. 
+ * the different passes can carry information between them.
  */
-struct recovery_info 
+struct recovery_info
 {
        tid_t           start_transaction;
        tid_t           end_transaction;
@@ -46,7 +46,7 @@ static int scan_revoke_records(journal_t *, struct buffer_head *,
 #ifdef __KERNEL__
 
 /* Release readahead buffers after use */
-void journal_brelse_array(struct buffer_head *b[], int n)
+static void journal_brelse_array(struct buffer_head *b[], int n)
 {
        while (--n >= 0)
                brelse (b[n]);
@@ -116,7 +116,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
        err = 0;
 
 failed:
-       if (nbufs) 
+       if (nbufs)
                journal_brelse_array(bufs, nbufs);
        return err;
 }
@@ -128,7 +128,7 @@ failed:
  * Read a block from the journal
  */
 
-static int jread(struct buffer_head **bhp, journal_t *journal, 
+static int jread(struct buffer_head **bhp, journal_t *journal,
                 unsigned int offset)
 {
        int err;
@@ -212,14 +212,14 @@ do {                                                                      \
 /**
  * journal_recover - recovers a on-disk journal
  * @journal: the journal to recover
- * 
+ *
  * The primary function for recovering the log contents when mounting a
- * journaled device.  
+ * journaled device.
  *
  * Recovery is done in three passes.  In the first pass, we look for the
  * end of the log.  In the second, we assemble the list of revoke
  * blocks.  In the third and final pass, we replay any un-revoked blocks
- * in the log.  
+ * in the log.
  */
 int journal_recover(journal_t *journal)
 {
@@ -231,10 +231,10 @@ int journal_recover(journal_t *journal)
        memset(&info, 0, sizeof(info));
        sb = journal->j_superblock;
 
-       /* 
+       /*
         * The journal superblock's s_start field (the current log head)
         * is always zero if, and only if, the journal was cleanly
-        * unmounted.  
+        * unmounted.
         */
 
        if (!sb->s_start) {
@@ -253,7 +253,7 @@ int journal_recover(journal_t *journal)
        jbd_debug(0, "JBD: recovery, exit status %d, "
                  "recovered transactions %u to %u\n",
                  err, info.start_transaction, info.end_transaction);
-       jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n", 
+       jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
                  info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
 
        /* Restart the log at the next transaction ID, thus invalidating
@@ -268,15 +268,15 @@ int journal_recover(journal_t *journal)
 /**
  * journal_skip_recovery - Start journal and wipe exiting records
  * @journal: journal to startup
- * 
+ *
  * Locate any valid recovery information from the journal and set up the
  * journal structures in memory to ignore it (presumably because the
- * caller has evidence that it is out of date).  
+ * caller has evidence that it is out of date).
  * This function does'nt appear to be exorted..
  *
  * We perform one pass over the journal to allow us to tell the user how
  * much recovery information is being erased, and to let us initialise
- * the journal transaction sequence numbers to the next unused ID. 
+ * the journal transaction sequence numbers to the next unused ID.
  */
 int journal_skip_recovery(journal_t *journal)
 {
@@ -297,7 +297,7 @@ int journal_skip_recovery(journal_t *journal)
 #ifdef CONFIG_JBD_DEBUG
                int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
 #endif
-               jbd_debug(0, 
+               jbd_debug(0,
                          "JBD: ignoring %d transaction%s from the journal.\n",
                          dropped, (dropped == 1) ? "" : "s");
                journal->j_transaction_sequence = ++info.end_transaction;
@@ -314,7 +314,7 @@ static int do_one_pass(journal_t *journal,
        unsigned long           next_log_block;
        int                     err, success = 0;
        journal_superblock_t *  sb;
-       journal_header_t *      tmp;
+       journal_header_t *      tmp;
        struct buffer_head *    bh;
        unsigned int            sequence;
        int                     blocktype;
@@ -324,10 +324,10 @@ static int do_one_pass(journal_t *journal,
        MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
                               / sizeof(journal_block_tag_t));
 
-       /* 
+       /*
         * First thing is to establish what we expect to find in the log
         * (in terms of transaction IDs), and where (in terms of log
-        * block offsets): query the superblock.  
+        * block offsets): query the superblock.
         */
 
        sb = journal->j_superblock;
@@ -344,7 +344,7 @@ static int do_one_pass(journal_t *journal,
         * Now we walk through the log, transaction by transaction,
         * making sure that each transaction has a commit block in the
         * expected place.  Each complete transaction gets replayed back
-        * into the main filesystem. 
+        * into the main filesystem.
         */
 
        while (1) {
@@ -379,8 +379,8 @@ static int do_one_pass(journal_t *journal,
                next_log_block++;
                wrap(journal, next_log_block);
 
-               /* What kind of buffer is it? 
-                * 
+               /* What kind of buffer is it?
+                *
                 * If it is a descriptor block, check that it has the
                 * expected sequence number.  Otherwise, we're all done
                 * here. */
@@ -394,7 +394,7 @@ static int do_one_pass(journal_t *journal,
 
                blocktype = be32_to_cpu(tmp->h_blocktype);
                sequence = be32_to_cpu(tmp->h_sequence);
-               jbd_debug(3, "Found magic %d, sequence %d\n", 
+               jbd_debug(3, "Found magic %d, sequence %d\n",
                          blocktype, sequence);
 
                if (sequence != next_commit_ID) {
@@ -438,7 +438,7 @@ static int do_one_pass(journal_t *journal,
                                        /* Recover what we can, but
                                         * report failure at the end. */
                                        success = err;
-                                       printk (KERN_ERR 
+                                       printk (KERN_ERR
                                                "JBD: IO error %d recovering "
                                                "block %ld in log\n",
                                                err, io_block);
@@ -452,7 +452,7 @@ static int do_one_pass(journal_t *journal,
                                         * revoked, then we're all done
                                         * here. */
                                        if (journal_test_revoke
-                                           (journal, blocknr, 
+                                           (journal, blocknr,
                                             next_commit_ID)) {
                                                brelse(obh);
                                                ++info->nr_revoke_hits;
@@ -465,7 +465,7 @@ static int do_one_pass(journal_t *journal,
                                                        blocknr,
                                                        journal->j_blocksize);
                                        if (nbh == NULL) {
-                                               printk(KERN_ERR 
+                                               printk(KERN_ERR
                                                       "JBD: Out of memory "
                                                       "during recovery.\n");
                                                err = -ENOMEM;
@@ -537,7 +537,7 @@ static int do_one_pass(journal_t *journal,
        }
 
  done:
-       /* 
+       /*
         * We broke out of the log scan loop: either we came to the
         * known end of the log or we found an unexpected block in the
         * log.  If the latter happened, then we know that the "current"
@@ -567,7 +567,7 @@ static int do_one_pass(journal_t *journal,
 
 /* Scan a revoke record, marking all blocks mentioned as revoked. */
 
-static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, 
+static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
                               tid_t sequence, struct recovery_info *info)
 {
        journal_revoke_header_t *header;
index a56144183462e20d06ad756a5b6d062c44333838..c532429d8d9b365e9b540255e4f684071a9e0894 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/revoke.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
  *
  * Copyright 2000 Red Hat corp --- All Rights Reserved
  * Revoke is the mechanism used to prevent old log records for deleted
  * metadata from being replayed on top of newer data using the same
  * blocks.  The revoke mechanism is used in two separate places:
- * 
+ *
  * + Commit: during commit we write the entire list of the current
  *   transaction's revoked blocks to the journal
- * 
+ *
  * + Recovery: during recovery we record the transaction ID of all
  *   revoked blocks.  If there are multiple revoke records in the log
  *   for a single block, only the last one counts, and if there is a log
@@ -29,7 +29,7 @@
  * single transaction:
  *
  * Block is revoked and then journaled:
- *   The desired end result is the journaling of the new block, so we 
+ *   The desired end result is the journaling of the new block, so we
  *   cancel the revoke before the transaction commits.
  *
  * Block is journaled and then revoked:
@@ -41,7 +41,7 @@
  *   transaction must have happened after the block was journaled and so
  *   the revoke must take precedence.
  *
- * Block is revoked and then written as data: 
+ * Block is revoked and then written as data:
  *   The data write is allowed to succeed, but the revoke is _not_
  *   cancelled.  We still need to prevent old log records from
  *   overwriting the new data.  We don't even need to clear the revoke
@@ -54,7 +54,7 @@
  *                     buffer has not been revoked, and cancel_revoke
  *                     need do nothing.
  * RevokeValid set, Revoked set:
- *                     buffer has been revoked.  
+ *                     buffer has been revoked.
  */
 
 #ifndef __KERNEL__
@@ -77,7 +77,7 @@ static kmem_cache_t *revoke_table_cache;
    journal replay, this involves recording the transaction ID of the
    last transaction to revoke this block. */
 
-struct jbd_revoke_record_s 
+struct jbd_revoke_record_s
 {
        struct list_head  hash;
        tid_t             sequence;     /* Used for recovery only */
@@ -90,8 +90,8 @@ struct jbd_revoke_table_s
 {
        /* It is conceivable that we might want a larger hash table
         * for recovery.  Must be a power of two. */
-       int               hash_size; 
-       int               hash_shift; 
+       int               hash_size;
+       int               hash_shift;
        struct list_head *hash_table;
 };
 
@@ -301,22 +301,22 @@ void journal_destroy_revoke(journal_t *journal)
 
 #ifdef __KERNEL__
 
-/* 
+/*
  * journal_revoke: revoke a given buffer_head from the journal.  This
  * prevents the block from being replayed during recovery if we take a
  * crash after this current transaction commits.  Any subsequent
  * metadata writes of the buffer in this transaction cancel the
- * revoke.  
+ * revoke.
  *
  * Note that this call may block --- it is up to the caller to make
  * sure that there are no further calls to journal_write_metadata
  * before the revoke is complete.  In ext3, this implies calling the
  * revoke before clearing the block bitmap when we are deleting
- * metadata. 
+ * metadata.
  *
  * Revoke performs a journal_forget on any buffer_head passed in as a
  * parameter, but does _not_ forget the buffer_head if the bh was only
- * found implicitly. 
+ * found implicitly.
  *
  * bh_in may not be a journalled buffer - it may have come off
  * the hash tables without an attached journal_head.
@@ -325,7 +325,7 @@ void journal_destroy_revoke(journal_t *journal)
  * by one.
  */
 
-int journal_revoke(handle_t *handle, unsigned long blocknr, 
+int journal_revoke(handle_t *handle, unsigned long blocknr,
                   struct buffer_head *bh_in)
 {
        struct buffer_head *bh = NULL;
@@ -487,7 +487,7 @@ void journal_switch_revoke_table(journal_t *journal)
        else
                journal->j_revoke = journal->j_revoke_table[0];
 
-       for (i = 0; i < journal->j_revoke->hash_size; i++) 
+       for (i = 0; i < journal->j_revoke->hash_size; i++)
                INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]);
 }
 
@@ -498,7 +498,7 @@ void journal_switch_revoke_table(journal_t *journal)
  * Called with the journal lock held.
  */
 
-void journal_write_revoke_records(journal_t *journal, 
+void journal_write_revoke_records(journal_t *journal,
                                  transaction_t *transaction)
 {
        struct journal_head *descriptor;
@@ -507,7 +507,7 @@ void journal_write_revoke_records(journal_t *journal,
        struct list_head *hash_list;
        int i, offset, count;
 
-       descriptor = NULL; 
+       descriptor = NULL;
        offset = 0;
        count = 0;
 
@@ -519,10 +519,10 @@ void journal_write_revoke_records(journal_t *journal,
                hash_list = &revoke->hash_table[i];
 
                while (!list_empty(hash_list)) {
-                       record = (struct jbd_revoke_record_s *) 
+                       record = (struct jbd_revoke_record_s *)
                                hash_list->next;
                        write_one_revoke_record(journal, transaction,
-                                               &descriptor, &offset, 
+                                               &descriptor, &offset,
                                                record);
                        count++;
                        list_del(&record->hash);
@@ -534,14 +534,14 @@ void journal_write_revoke_records(journal_t *journal,
        jbd_debug(1, "Wrote %d revoke records\n", count);
 }
 
-/* 
+/*
  * Write out one revoke record.  We need to create a new descriptor
- * block if the old one is full or if we have not already created one.  
+ * block if the old one is full or if we have not already created one.
  */
 
-static void write_one_revoke_record(journal_t *journal, 
+static void write_one_revoke_record(journal_t *journal,
                                    transaction_t *transaction,
-                                   struct journal_head **descriptorp, 
+                                   struct journal_head **descriptorp,
                                    int *offsetp,
                                    struct jbd_revoke_record_s *record)
 {
@@ -584,21 +584,21 @@ static void write_one_revoke_record(journal_t *journal,
                *descriptorp = descriptor;
        }
 
-       * ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) = 
+       * ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) =
                cpu_to_be32(record->blocknr);
        offset += 4;
        *offsetp = offset;
 }
 
-/* 
+/*
  * Flush a revoke descriptor out to the journal.  If we are aborting,
  * this is a noop; otherwise we are generating a buffer which needs to
  * be waited for during commit, so it has to go onto the appropriate
  * journal buffer list.
  */
 
-static void flush_descriptor(journal_t *journal, 
-                            struct journal_head *descriptor, 
+static void flush_descriptor(journal_t *journal,
+                            struct journal_head *descriptor,
                             int offset)
 {
        journal_revoke_header_t *header;
@@ -618,7 +618,7 @@ static void flush_descriptor(journal_t *journal,
 }
 #endif
 
-/* 
+/*
  * Revoke support for recovery.
  *
  * Recovery needs to be able to:
@@ -629,7 +629,7 @@ static void flush_descriptor(journal_t *journal,
  *  check whether a given block in a given transaction should be replayed
  *  (ie. has not been revoked by a revoke record in that or a subsequent
  *  transaction)
- * 
+ *
  *  empty the revoke table after recovery.
  */
 
@@ -637,11 +637,11 @@ static void flush_descriptor(journal_t *journal,
  * First, setting revoke records.  We create a new revoke record for
  * every block ever revoked in the log as we scan it for recovery, and
  * we update the existing records if we find multiple revokes for a
- * single block. 
+ * single block.
  */
 
-int journal_set_revoke(journal_t *journal, 
-                      unsigned long blocknr, 
+int journal_set_revoke(journal_t *journal,
+                      unsigned long blocknr,
                       tid_t sequence)
 {
        struct jbd_revoke_record_s *record;
@@ -653,18 +653,18 @@ int journal_set_revoke(journal_t *journal,
                if (tid_gt(sequence, record->sequence))
                        record->sequence = sequence;
                return 0;
-       } 
+       }
        return insert_revoke_hash(journal, blocknr, sequence);
 }
 
-/* 
+/*
  * Test revoke records.  For a given block referenced in the log, has
  * that block been revoked?  A revoke record with a given transaction
  * sequence number revokes all blocks in that transaction and earlier
  * ones, but later transactions still need replayed.
  */
 
-int journal_test_revoke(journal_t *journal, 
+int journal_test_revoke(journal_t *journal,
                        unsigned long blocknr,
                        tid_t sequence)
 {
index f5169a96260edc9a95cd3fb61b8f188aa71c43df..e1b3c8af4d1767cd8b530e90cb482655f891fa6f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/transaction.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
  *
  * Copyright 1998 Red Hat corp --- All Rights Reserved
@@ -10,7 +10,7 @@
  * option, any later version, incorporated herein by reference.
  *
  * Generic filesystem transaction handling code; part of the ext2fs
- * journaling system.  
+ * journaling system.
  *
  * This file manages transactions (compound commits managed by the
  * journaling code) and handles (individual atomic operations by the
@@ -74,7 +74,7 @@ get_transaction(journal_t *journal, transaction_t *transaction)
  * start_this_handle: Given a handle, deal with any locking or stalling
  * needed to make sure that there is enough journal space for the handle
  * to begin.  Attach the handle to a transaction and set up the
- * transaction's buffer credits.  
+ * transaction's buffer credits.
  */
 
 static int start_this_handle(journal_t *journal, handle_t *handle)
@@ -117,7 +117,7 @@ repeat_locked:
        if (is_journal_aborted(journal) ||
            (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) {
                spin_unlock(&journal->j_state_lock);
-               ret = -EROFS; 
+               ret = -EROFS;
                goto out;
        }
 
@@ -182,7 +182,7 @@ repeat_locked:
                goto repeat;
        }
 
-       /* 
+       /*
         * The commit code assumes that it can get enough log space
         * without forcing a checkpoint.  This is *critical* for
         * correctness: a checkpoint of a buffer which is also
@@ -191,7 +191,7 @@ repeat_locked:
         *
         * We must therefore ensure the necessary space in the journal
         * *before* starting to dirty potentially checkpointed buffers
-        * in the new transaction. 
+        * in the new transaction.
         *
         * The worst part is, any transaction currently committing can
         * reduce the free space arbitrarily.  Be careful to account for
@@ -246,13 +246,13 @@ static handle_t *new_handle(int nblocks)
 }
 
 /**
- * handle_t *journal_start() - Obtain a new handle.  
+ * handle_t *journal_start() - Obtain a new handle.
  * @journal: Journal to start transaction on.
  * @nblocks: number of block buffer we might modify
  *
  * We make sure that the transaction can guarantee at least nblocks of
  * modified buffers in the log.  We block until the log can guarantee
- * that much space.  
+ * that much space.
  *
  * This function is visible to journal users (like ext3fs), so is not
  * called with the journal already locked.
@@ -292,11 +292,11 @@ handle_t *journal_start(journal_t *journal, int nblocks)
  * int journal_extend() - extend buffer credits.
  * @handle:  handle to 'extend'
  * @nblocks: nr blocks to try to extend by.
- * 
+ *
  * Some transactions, such as large extends and truncates, can be done
  * atomically all at once or in several stages.  The operation requests
  * a credit for a number of buffer modications in advance, but can
- * extend its credit if it needs more.  
+ * extend its credit if it needs more.
  *
  * journal_extend tries to give the running handle more buffer credits.
  * It does not guarantee that allocation - this is a best-effort only.
@@ -363,7 +363,7 @@ out:
  * int journal_restart() - restart a handle .
  * @handle:  handle to restart
  * @nblocks: nr credits requested
- * 
+ *
  * Restart a handle for a multi-transaction filesystem
  * operation.
  *
@@ -462,7 +462,7 @@ void journal_lock_updates(journal_t *journal)
 /**
  * void journal_unlock_updates (journal_t* journal) - release barrier
  * @journal:  Journal to release the barrier on.
- * 
+ *
  * Release a transaction barrier obtained with journal_lock_updates().
  *
  * Should be called without the journal lock held.
@@ -547,8 +547,8 @@ repeat:
        jbd_lock_bh_state(bh);
 
        /* We now hold the buffer lock so it is safe to query the buffer
-        * state.  Is the buffer dirty? 
-        * 
+        * state.  Is the buffer dirty?
+        *
         * If so, there are two possibilities.  The buffer may be
         * non-journaled, and undergoing a quite legitimate writeback.
         * Otherwise, it is journaled, and we don't expect dirty buffers
@@ -566,7 +566,7 @@ repeat:
                 */
                if (jh->b_transaction) {
                        J_ASSERT_JH(jh,
-                               jh->b_transaction == transaction || 
+                               jh->b_transaction == transaction ||
                                jh->b_transaction ==
                                        journal->j_committing_transaction);
                        if (jh->b_next_transaction)
@@ -580,7 +580,7 @@ repeat:
                 */
                JBUFFER_TRACE(jh, "Unexpected dirty buffer");
                jbd_unexpected_dirty_buffer(jh);
-       }
+       }
 
        unlock_buffer(bh);
 
@@ -653,7 +653,7 @@ repeat:
                 * buffer had better remain locked during the kmalloc,
                 * but that should be true --- we hold the journal lock
                 * still and the buffer is already on the BUF_JOURNAL
-                * list so won't be flushed. 
+                * list so won't be flushed.
                 *
                 * Subtle point, though: if this is a get_undo_access,
                 * then we will be relying on the frozen_data to contain
@@ -765,8 +765,8 @@ int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
  * manually rather than reading off disk), then we need to keep the
  * buffer_head locked until it has been completely filled with new
  * data.  In this case, we should be able to make the assertion that
- * the bh is not already part of an existing transaction.  
- * 
+ * the bh is not already part of an existing transaction.
+ *
  * The buffer should already be locked by the caller by this point.
  * There is no lock ranking violation: it was a newly created,
  * unlocked buffer beforehand. */
@@ -778,7 +778,7 @@ int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
  *
  * Call this if you create a new bh.
  */
-int journal_get_create_access(handle_t *handle, struct buffer_head *bh) 
+int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
 {
        transaction_t *transaction = handle->h_transaction;
        journal_t *journal = transaction->t_journal;
@@ -847,13 +847,13 @@ out:
  * do not reuse freed space until the deallocation has been committed,
  * since if we overwrote that space we would make the delete
  * un-rewindable in case of a crash.
- * 
+ *
  * To deal with that, journal_get_undo_access requests write access to a
  * buffer for parts of non-rewindable operations such as delete
  * operations on the bitmaps.  The journaling code must keep a copy of
  * the buffer's contents prior to the undo_access call until such time
  * as we know that the buffer has definitely been committed to disk.
- * 
+ *
  * We never need to know which transaction the committed data is part
  * of, buffers touched here are guaranteed to be dirtied later and so
  * will be committed to a new transaction in due course, at which point
@@ -911,13 +911,13 @@ out:
        return err;
 }
 
-/** 
+/**
  * int journal_dirty_data() -  mark a buffer as containing dirty data which
  *                             needs to be flushed before we can commit the
- *                             current transaction.  
+ *                             current transaction.
  * @handle: transaction
  * @bh: bufferhead to mark
- * 
+ *
  * The buffer is placed on the transaction's data list and is marked as
  * belonging to the transaction.
  *
@@ -946,15 +946,15 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 
        /*
         * What if the buffer is already part of a running transaction?
-        * 
+        *
         * There are two cases:
         * 1) It is part of the current running transaction.  Refile it,
         *    just in case we have allocated it as metadata, deallocated
-        *    it, then reallocated it as data. 
+        *    it, then reallocated it as data.
         * 2) It is part of the previous, still-committing transaction.
         *    If all we want to do is to guarantee that the buffer will be
         *    written to disk before this new transaction commits, then
-        *    being sure that the *previous* transaction has this same 
+        *    being sure that the *previous* transaction has this same
         *    property is sufficient for us!  Just leave it on its old
         *    transaction.
         *
@@ -1076,18 +1076,18 @@ no_journal:
        return 0;
 }
 
-/** 
+/**
  * int journal_dirty_metadata() -  mark a buffer as containing dirty metadata
  * @handle: transaction to add buffer to.
- * @bh: buffer to mark 
- * 
+ * @bh: buffer to mark
+ *
  * mark dirty metadata which needs to be journaled as part of the current
  * transaction.
  *
  * The buffer is placed on the transaction's metadata list and is marked
- * as belonging to the transaction.  
+ * as belonging to the transaction.
  *
- * Returns error number or 0 on success.  
+ * Returns error number or 0 on success.
  *
  * Special care needs to be taken if the buffer already belongs to the
  * current committing transaction (in which case we should have frozen
@@ -1135,11 +1135,11 @@ int journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
 
        set_buffer_jbddirty(bh);
 
-       /* 
+       /*
         * Metadata already on the current transaction list doesn't
         * need to be filed.  Metadata on another transaction's list must
         * be committing, and will be refiled once the commit completes:
-        * leave it alone for now. 
+        * leave it alone for now.
         */
        if (jh->b_transaction != transaction) {
                JBUFFER_TRACE(jh, "already on other transaction");
@@ -1165,7 +1165,7 @@ out:
        return 0;
 }
 
-/* 
+/*
  * journal_release_buffer: undo a get_write_access without any buffer
  * updates, if the update decided in the end that it didn't need access.
  *
@@ -1176,20 +1176,20 @@ journal_release_buffer(handle_t *handle, struct buffer_head *bh)
        BUFFER_TRACE(bh, "entry");
 }
 
-/** 
+/**
  * void journal_forget() - bforget() for potentially-journaled buffers.
  * @handle: transaction handle
  * @bh:     bh to 'forget'
  *
  * We can only do the bforget if there are no commits pending against the
  * buffer.  If the buffer is dirty in the current running transaction we
- * can safely unlink it. 
+ * can safely unlink it.
  *
  * bh may not be a journalled buffer at all - it may be a non-JBD
  * buffer which came off the hashtable.  Check for this.
  *
  * Decrements bh->b_count by one.
- * 
+ *
  * Allow this call even if the handle has aborted --- it may be part of
  * the caller's cleanup after an abort.
  */
@@ -1237,7 +1237,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
 
                drop_reserve = 1;
 
-               /* 
+               /*
                 * We are no longer going to journal this buffer.
                 * However, the commit of this transaction is still
                 * important to the buffer: the delete that we are now
@@ -1246,7 +1246,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
                 *
                 * So, if we have a checkpoint on the buffer, we should
                 * now refile the buffer on our BJ_Forget list so that
-                * we know to remove the checkpoint after we commit. 
+                * we know to remove the checkpoint after we commit.
                 */
 
                if (jh->b_cp_transaction) {
@@ -1264,7 +1264,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
                        }
                }
        } else if (jh->b_transaction) {
-               J_ASSERT_JH(jh, (jh->b_transaction == 
+               J_ASSERT_JH(jh, (jh->b_transaction ==
                                 journal->j_committing_transaction));
                /* However, if the buffer is still owned by a prior
                 * (committing) transaction, we can't drop it yet... */
@@ -1294,7 +1294,7 @@ drop:
 /**
  * int journal_stop() - complete a transaction
  * @handle: tranaction to complete.
- * 
+ *
  * All done for a particular handle.
  *
  * There is not much action needed here.  We just return any remaining
@@ -1303,7 +1303,7 @@ drop:
  * filesystem is marked for synchronous update.
  *
  * journal_stop itself will not usually return an error, but it may
- * do so in unusual circumstances.  In particular, expect it to 
+ * do so in unusual circumstances.  In particular, expect it to
  * return -EIO if a journal_abort has been executed since the
  * transaction began.
  */
@@ -1373,7 +1373,7 @@ int journal_stop(handle_t *handle)
        if (handle->h_sync ||
                        transaction->t_outstanding_credits >
                                journal->j_max_transaction_buffers ||
-                       time_after_eq(jiffies, transaction->t_expires)) {
+                       time_after_eq(jiffies, transaction->t_expires)) {
                /* Do this even for aborted journals: an abort still
                 * completes the commit thread, it just doesn't write
                 * anything to disk. */
@@ -1388,7 +1388,7 @@ int journal_stop(handle_t *handle)
 
                /*
                 * Special case: JFS_SYNC synchronous updates require us
-                * to wait for the commit to complete.  
+                * to wait for the commit to complete.
                 */
                if (handle->h_sync && !(current->flags & PF_MEMALLOC))
                        err = log_wait_commit(journal, tid);
@@ -1439,7 +1439,7 @@ int journal_force_commit(journal_t *journal)
  * jbd_lock_bh_state(jh2bh(jh)) is held.
  */
 
-static inline void 
+static inline void
 __blist_add_buffer(struct journal_head **list, struct journal_head *jh)
 {
        if (!*list) {
@@ -1454,7 +1454,7 @@ __blist_add_buffer(struct journal_head **list, struct journal_head *jh)
        }
 }
 
-/* 
+/*
  * Remove a buffer from a transaction list, given the transaction's list
  * head pointer.
  *
@@ -1475,7 +1475,7 @@ __blist_del_buffer(struct journal_head **list, struct journal_head *jh)
        jh->b_tnext->b_tprev = jh->b_tprev;
 }
 
-/* 
+/*
  * Remove a buffer from the appropriate transaction list.
  *
  * Note that this function can *change* the value of
@@ -1595,17 +1595,17 @@ out:
 }
 
 
-/** 
+/**
  * int journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
  * @page: to try and free
  * @unused_gfp_mask: unused
  *
- * 
+ *
  * For all the buffers on this page,
  * if they are fully written out ordered data, move them onto BUF_CLEAN
  * so try_to_free_buffers() can reap them.
- * 
+ *
  * This function returns non-zero if we wish try_to_free_buffers()
  * to be called. We do this if the page is releasable by try_to_free_buffers().
  * We also do it if the page has locked or dirty buffers and the caller wants
@@ -1629,7 +1629,7 @@ out:
  * cannot happen because we never reallocate freed data as metadata
  * while the data is part of a transaction.  Yes?
  */
-int journal_try_to_free_buffers(journal_t *journal, 
+int journal_try_to_free_buffers(journal_t *journal,
                                struct page *page, gfp_t unused_gfp_mask)
 {
        struct buffer_head *head;
@@ -1697,7 +1697,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
 }
 
 /*
- * journal_invalidatepage 
+ * journal_invalidatepage
  *
  * This code is tricky.  It has a number of cases to deal with.
  *
@@ -1705,15 +1705,15 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
  *
  * i_size must be updated on disk before we start calling invalidatepage on the
  * data.
- * 
+ *
  *  This is done in ext3 by defining an ext3_setattr method which
  *  updates i_size before truncate gets going.  By maintaining this
  *  invariant, we can be sure that it is safe to throw away any buffers
  *  attached to the current transaction: once the transaction commits,
  *  we know that the data will not be needed.
- * 
+ *
  *  Note however that we can *not* throw away data belonging to the
- *  previous, committing transaction!  
+ *  previous, committing transaction!
  *
  * Any disk blocks which *are* part of the previous, committing
  * transaction (and which therefore cannot be discarded immediately) are
@@ -1732,7 +1732,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
  * don't make guarantees about the order in which data hits disk --- in
  * particular we don't guarantee that new dirty data is flushed before
  * transaction commit --- so it is always safe just to discard data
- * immediately in that mode.  --sct 
+ * immediately in that mode.  --sct
  */
 
 /*
@@ -1876,9 +1876,9 @@ zap_buffer_unlocked:
        return may_free;
 }
 
-/** 
+/**
  * void journal_invalidatepage()
- * @journal: journal to use for flush... 
+ * @journal: journal to use for flush...
  * @page:    page to flush
  * @offset:  length of page to invalidate.
  *
@@ -1886,7 +1886,7 @@ zap_buffer_unlocked:
  *
  */
 void journal_invalidatepage(journal_t *journal,
-                     struct page *page, 
+                     struct page *page,
                      unsigned long offset)
 {
        struct buffer_head *head, *bh, *next;
@@ -1908,7 +1908,7 @@ void journal_invalidatepage(journal_t *journal,
                next = bh->b_this_page;
 
                if (offset <= curr_off) {
-                       /* This block is wholly outside the truncation point */
+                       /* This block is wholly outside the truncation point */
                        lock_buffer(bh);
                        may_free &= journal_unmap_buffer(journal, bh);
                        unlock_buffer(bh);
@@ -1924,8 +1924,8 @@ void journal_invalidatepage(journal_t *journal,
        }
 }
 
-/* 
- * File a buffer on the given transaction list. 
+/*
+ * File a buffer on the given transaction list.
  */
 void __journal_file_buffer(struct journal_head *jh,
                        transaction_t *transaction, int jlist)
@@ -1948,7 +1948,7 @@ void __journal_file_buffer(struct journal_head *jh,
         * with __jbd_unexpected_dirty_buffer()'s handling of dirty
         * state. */
 
-       if (jlist == BJ_Metadata || jlist == BJ_Reserved || 
+       if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
            jlist == BJ_Shadow || jlist == BJ_Forget) {
                if (test_clear_buffer_dirty(bh) ||
                    test_clear_buffer_jbddirty(bh))
@@ -2008,7 +2008,7 @@ void journal_file_buffer(struct journal_head *jh,
        jbd_unlock_bh_state(jh2bh(jh));
 }
 
-/* 
+/*
  * Remove a buffer from its current buffer list in preparation for
  * dropping it from its current transaction entirely.  If the buffer has
  * already started to be used by a subsequent transaction, refile the
@@ -2060,7 +2060,7 @@ void __journal_refile_buffer(struct journal_head *jh)
  * to the caller to remove the journal_head if necessary.  For the
  * unlocked journal_refile_buffer call, the caller isn't going to be
  * doing anything else to the buffer so we need to do the cleanup
- * ourselves to avoid a jh leak. 
+ * ourselves to avoid a jh leak.
  *
  * *** The journal_head may be freed by this call! ***
  */
index 93068697a9bf2cf5b8a438ea96cf72da2d59be1a..3f7899ea4cba9389742e6cb85d441ce9ff8c2535 100644 (file)
@@ -364,12 +364,11 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
        inode->i_ctime.tv_nsec = 0;
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = (inode->i_size + 511) >> 9;
 
        f = jffs_find_file(c, raw_inode->ino);
 
-       inode->u.generic_ip = (void *)f;
+       inode->i_private = (void *)f;
        insert_inode_hash(inode);
 
        return inode;
@@ -442,7 +441,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        });
 
        result = -ENOTDIR;
-       if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
+       if (!(old_dir_f = old_dir->i_private)) {
                D(printk("jffs_rename(): Old dir invalid.\n"));
                goto jffs_rename_end;
        }
@@ -456,7 +455,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        /* Find the new directory.  */
        result = -ENOTDIR;
-       if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
+       if (!(new_dir_f = new_dir->i_private)) {
                D(printk("jffs_rename(): New dir invalid.\n"));
                goto jffs_rename_end;
        }
@@ -593,7 +592,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                else {
                        ddino = ((struct jffs_file *)
-                                inode->u.generic_ip)->pino;
+                                inode->i_private)->pino;
                }
                D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
                if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
@@ -604,7 +603,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                filp->f_pos++;
        }
-       f = ((struct jffs_file *)inode->u.generic_ip)->children;
+       f = ((struct jffs_file *)inode->i_private)->children;
 
        j = 2;
        while(f && (f->deleted || j++ < filp->f_pos )) {
@@ -652,7 +651,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        lock_kernel();
 
        D3({
-               char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
+               char *s = kmalloc(len + 1, GFP_KERNEL);
                memcpy(s, name, len);
                s[len] = '\0';
                printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
@@ -668,7 +667,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        }
 
        r = -EACCES;
-       if (!(d = (struct jffs_file *)dir->u.generic_ip)) {
+       if (!(d = (struct jffs_file *)dir->i_private)) {
                D(printk("jffs_lookup(): No such inode! (%lu)\n",
                         dir->i_ino));
                goto jffs_lookup_end;
@@ -739,7 +738,7 @@ jffs_do_readpage_nolock(struct file *file, struct page *page)
        unsigned long read_len;
        int result;
        struct inode *inode = (struct inode*)page->mapping->host;
-       struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
+       struct jffs_file *f = (struct jffs_file *)inode->i_private;
        struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
        int r;
        loff_t offset;
@@ -828,7 +827,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        });
 
        lock_kernel();
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
 
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_mkdir(): No reference to a "
@@ -972,7 +971,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
                kfree(_name);
        });
 
-       dir_f = (struct jffs_file *) dir->u.generic_ip;
+       dir_f = dir->i_private;
        c = dir_f->c;
 
        result = -ENOENT;
@@ -1053,9 +1052,8 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
 
        dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        mark_inode_dirty(dir);
-       inode->i_nlink--;
        inode->i_ctime = dir->i_ctime;
-       mark_inode_dirty(inode);
+       inode_dec_link_count(inode);
 
        d_delete(dentry);       /* This also frees the inode */
 
@@ -1082,7 +1080,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
        if (!old_valid_dev(rdev))
                return -EINVAL;
        lock_kernel();
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
        c = dir_f->c;
 
        D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
@@ -1173,8 +1171,8 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        lock_kernel();
        D1({
                int len = dentry->d_name.len; 
-               char *_name = (char *)kmalloc(len + 1, GFP_KERNEL);
-               char *_symname = (char *)kmalloc(symname_len + 1, GFP_KERNEL);
+               char *_name = kmalloc(len + 1, GFP_KERNEL);
+               char *_symname = kmalloc(symname_len + 1, GFP_KERNEL);
                memcpy(_name, dentry->d_name.name, len);
                _name[len] = '\0';
                memcpy(_symname, symname, symname_len);
@@ -1186,7 +1184,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
                kfree(_symname);
        });
 
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_symlink(): No reference to a "
                       "jffs_file struct in inode.\n");
@@ -1282,14 +1280,14 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode,
        lock_kernel();
        D1({
                int len = dentry->d_name.len;
-               char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
+               char *s = kmalloc(len + 1, GFP_KERNEL);
                memcpy(s, dentry->d_name.name, len);
                s[len] = '\0';
                printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
                kfree(s);
        });
 
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_create(): No reference to a "
                       "jffs_file struct in inode.\n");
@@ -1403,9 +1401,9 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
                goto out_isem;
        }
 
-       if (!(f = (struct jffs_file *)inode->u.generic_ip)) {
-               D(printk("jffs_file_write(): inode->u.generic_ip = 0x%p\n",
-                               inode->u.generic_ip));
+       if (!(f = inode->i_private)) {
+               D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
+                               inode->i_private));
                goto out_isem;
        }
 
@@ -1633,8 +1631,10 @@ static const struct file_operations jffs_file_operations =
 {
        .open           = generic_file_open,
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .ioctl          = jffs_ioctl,
        .mmap           = generic_file_readonly_mmap,
        .fsync          = jffs_fsync,
@@ -1693,7 +1693,7 @@ jffs_read_inode(struct inode *inode)
                mutex_unlock(&c->fmc->biglock);
                return;
        }
-       inode->u.generic_ip = (void *)f;
+       inode->i_private = f;
        inode->i_mode = f->mode;
        inode->i_nlink = f->nlink;
        inode->i_uid = f->uid;
@@ -1706,7 +1706,6 @@ jffs_read_inode(struct inode *inode)
        inode->i_mtime.tv_nsec = 
        inode->i_ctime.tv_nsec = 0;
 
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = (inode->i_size + 511) >> 9;
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &jffs_file_inode_operations;
@@ -1748,7 +1747,7 @@ jffs_delete_inode(struct inode *inode)
        lock_kernel();
        inode->i_size = 0;
        inode->i_blocks = 0;
-       inode->u.generic_ip = NULL;
+       inode->i_private = NULL;
        clear_inode(inode);
        if (inode->i_nlink == 0) {
                c = (struct jffs_control *) inode->i_sb->s_fs_info;
index 9000f1effedf9523991c5692f0c61238e1645809..4a543e1149700b08141d6769814848ea9295e2c9 100644 (file)
@@ -488,13 +488,11 @@ jffs_create_file(struct jffs_control *c,
 {
        struct jffs_file *f;
 
-       if (!(f = (struct jffs_file *)kmalloc(sizeof(struct jffs_file),
-                                             GFP_KERNEL))) {
+       if (!(f = kzalloc(sizeof(*f), GFP_KERNEL))) {
                D(printk("jffs_create_file(): Failed!\n"));
                return NULL;
        }
        no_jffs_file++;
-       memset(f, 0, sizeof(struct jffs_file));
        f->ino = raw_inode->ino;
        f->pino = raw_inode->pino;
        f->nlink = raw_inode->nlink;
@@ -516,7 +514,7 @@ jffs_create_control(struct super_block *sb)
 
        D2(printk("jffs_create_control()\n"));
 
-       if (!(c = (struct jffs_control *)kmalloc(s, GFP_KERNEL))) {
+       if (!(c = kmalloc(s, GFP_KERNEL))) {
                goto fail_control;
        }
        DJM(no_jffs_control++);
@@ -524,7 +522,7 @@ jffs_create_control(struct super_block *sb)
        c->gc_task = NULL;
        c->hash_len = JFFS_HASH_SIZE;
        s = sizeof(struct list_head) * c->hash_len;
-       if (!(c->hash = (struct list_head *)kmalloc(s, GFP_KERNEL))) {
+       if (!(c->hash = kmalloc(s, GFP_KERNEL))) {
                goto fail_hash;
        }
        DJM(no_hash++);
@@ -593,8 +591,7 @@ jffs_add_virtual_root(struct jffs_control *c)
        D2(printk("jffs_add_virtual_root(): "
                  "Creating a virtual root directory.\n"));
 
-       if (!(root = (struct jffs_file *)kmalloc(sizeof(struct jffs_file),
-                                                GFP_KERNEL))) {
+       if (!(root = kmalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
                return -ENOMEM;
        }
        no_jffs_file++;
index 7d8ca1aeace2f85937384dba8b906fe4020d6de4..29b68d939bd9e9f6f9c8bd0572d1b157f2476dcd 100644 (file)
@@ -94,8 +94,7 @@ jffs_build_begin(struct jffs_control *c, int unit)
        struct mtd_info *mtd;
        
        D3(printk("jffs_build_begin()\n"));
-       fmc = (struct jffs_fmcontrol *)kmalloc(sizeof(struct jffs_fmcontrol),
-                                              GFP_KERNEL);
+       fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
        if (!fmc) {
                D(printk("jffs_build_begin(): Allocation of "
                         "struct jffs_fmcontrol failed!\n"));
@@ -486,8 +485,7 @@ jffs_add_node(struct jffs_node *node)
 
        D3(printk("jffs_add_node(): ino = %u\n", node->ino));
 
-       ref = (struct jffs_node_ref *)kmalloc(sizeof(struct jffs_node_ref),
-                                             GFP_KERNEL);
+       ref = kmalloc(sizeof(*ref), GFP_KERNEL);
        if (!ref)
                return -ENOMEM;
 
index edd8371fc6a5b0f6f3c4dc1e220fe245642c5871..9def6adf4a5dee6a0a0162e31ebdf475842d9305 100644 (file)
@@ -588,7 +588,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        }
 
        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
-       dir_i->i_nlink++;
+       inc_nlink(dir_i);
 
        jffs2_free_raw_dirent(rd);
 
@@ -615,7 +615,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
        }
        ret = jffs2_unlink(dir_i, dentry);
        if (!ret)
-               dir_i->i_nlink--;
+               drop_nlink(dir_i);
        return ret;
 }
 
@@ -823,7 +823,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 
        if (victim_f) {
                /* There was a victim. Kill it off nicely */
-               new_dentry->d_inode->i_nlink--;
+               drop_nlink(new_dentry->d_inode);
                /* Don't oops if the victim was a dirent pointing to an
                   inode which didn't exist. */
                if (victim_f->inocache) {
@@ -836,7 +836,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        /* If it was a directory we moved, and there was no victim,
           increase i_nlink on its new parent */
        if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f)
-               new_dir_i->i_nlink++;
+               inc_nlink(new_dir_i);
 
        /* Unlink the original */
        ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
@@ -848,7 +848,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
                /* Oh shit. We really ought to make a single node which can do both atomically */
                struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
                down(&f->sem);
-               old_dentry->d_inode->i_nlink++;
+               inc_nlink(old_dentry->d_inode);
                if (f->inocache)
                        f->inocache->nlink++;
                up(&f->sem);
@@ -862,7 +862,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        }
 
        if (S_ISDIR(old_dentry->d_inode->i_mode))
-               old_dir_i->i_nlink--;
+               drop_nlink(old_dir_i);
 
        new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
 
index 3ed6e3e120b602fb814051606dc7fc7f89edc430..242875f77cb38261fec2c2da5e35e3db08b15773 100644 (file)
@@ -42,8 +42,10 @@ const struct file_operations jffs2_file_operations =
 {
        .llseek =       generic_file_llseek,
        .open =         generic_file_open,
-       .read =         generic_file_read,
-       .write =        generic_file_write,
+       .read =         do_sync_read,
+       .aio_read =     generic_file_aio_read,
+       .write =        do_sync_write,
+       .aio_write =    generic_file_aio_write,
        .ioctl =        jffs2_ioctl,
        .mmap =         generic_file_readonly_mmap,
        .fsync =        jffs2_fsync,
index 4780f82825d6fc3bbea2562b0ab245c40088625f..7bc1a4201c0c233437dd5e60d45159620b39e57c 100644 (file)
@@ -263,7 +263,6 @@ void jffs2_read_inode (struct inode *inode)
 
        inode->i_nlink = f->inocache->nlink;
 
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = (inode->i_size + 511) >> 9;
 
        switch (inode->i_mode & S_IFMT) {
@@ -278,13 +277,13 @@ void jffs2_read_inode (struct inode *inode)
 
                for (fd=f->dents; fd; fd = fd->next) {
                        if (fd->type == DT_DIR && fd->ino)
-                               inode->i_nlink++;
+                               inc_nlink(inode);
                }
                /* and '..' */
-               inode->i_nlink++;
+               inc_nlink(inode);
                /* Root dir gets i_nlink 3 for some reason */
                if (inode->i_ino == 1)
-                       inode->i_nlink++;
+                       inc_nlink(inode);
 
                inode->i_op = &jffs2_dir_inode_operations;
                inode->i_fop = &jffs2_dir_operations;
@@ -449,7 +448,6 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
        inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
        ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
 
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = 0;
        inode->i_size = 0;
 
index 68e3953419b4324504cbe8723a9b62e1cb48b3da..6de374513c010790ab15e40f4103781f669d93c8 100644 (file)
@@ -119,10 +119,9 @@ static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
        struct jffs2_sb_info *c;
        int ret;
 
-       c = kmalloc(sizeof(*c), GFP_KERNEL);
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
        if (!c)
                return -ENOMEM;
-       memset(c, 0, sizeof(*c));
        c->mtd = mtd;
 
        sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
index 1c9745be5adab3db43fd2218b69b4e92884100f6..976e90dc2d1b52c33c82a3d5404b2043494ffb0d 100644 (file)
@@ -103,13 +103,11 @@ struct inode_operations jfs_file_inode_operations = {
 const struct file_operations jfs_file_operations = {
        .open           = jfs_open,
        .llseek         = generic_file_llseek,
-       .write          = generic_file_write,
-       .read           = generic_file_read,
+       .write          = do_sync_write,
+       .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
-       .readv          = generic_file_readv,
-       .writev         = generic_file_writev,
        .sendfile       = generic_file_sendfile,
        .fsync          = jfs_fsync,
        .release        = jfs_release,
index a223cf4faa9b59e61f14e2ffc57712b9469017be..a8cc169235d9b775f6aa7961d7b5d5dc011eea0d 100644 (file)
@@ -227,7 +227,7 @@ int jfs_get_block(struct inode *ip, sector_t lblock,
 #ifdef _JFS_4K
        if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad)))
                goto unlock;
-       rc = extAlloc(ip, xlen, lblock64, &xad, FALSE);
+       rc = extAlloc(ip, xlen, lblock64, &xad, false);
        if (rc)
                goto unlock;
 
index 67b3774820eb663086675ef4a057066e56e93e94..37db524882628dd3b4a4eed92b7a3243d6e61b60 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
 #include <linux/ctype.h>
 #include <linux/capability.h>
 #include <linux/time.h>
@@ -22,13 +21,13 @@ static struct {
        long jfs_flag;
        long ext2_flag;
 } jfs_map[] = {
-       {JFS_NOATIME_FL, EXT2_NOATIME_FL},
-       {JFS_DIRSYNC_FL, EXT2_DIRSYNC_FL},
-       {JFS_SYNC_FL, EXT2_SYNC_FL},
-       {JFS_SECRM_FL, EXT2_SECRM_FL},
-       {JFS_UNRM_FL, EXT2_UNRM_FL},
-       {JFS_APPEND_FL, EXT2_APPEND_FL},
-       {JFS_IMMUTABLE_FL, EXT2_IMMUTABLE_FL},
+       {JFS_NOATIME_FL,        FS_NOATIME_FL},
+       {JFS_DIRSYNC_FL,        FS_DIRSYNC_FL},
+       {JFS_SYNC_FL,           FS_SYNC_FL},
+       {JFS_SECRM_FL,          FS_SECRM_FL},
+       {JFS_UNRM_FL,           FS_UNRM_FL},
+       {JFS_APPEND_FL,         FS_APPEND_FL},
+       {JFS_IMMUTABLE_FL,      FS_IMMUTABLE_FL},
        {0, 0},
 };
 
index c161c98954e08b17afb7e849ef57c7b47bbd1b6f..f05ebb62918205a0a911e7668923acf0b6a9b054 100644 (file)
@@ -403,8 +403,8 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
  *
  * PARAMETERS:
  *      ipbmap -  pointer to in-core inode for the block map.
- *      free   - TRUE if block range is to be freed from the persistent
- *               map; FALSE if it is to   be allocated.
+ *      free   -  'true' if block range is to be freed from the persistent
+ *                map; 'false' if it is to   be allocated.
  *      blkno  -  starting block number of the range.
  *      nblocks        -  number of contiguous blocks in the range.
  *      tblk   -  transaction block;
@@ -2394,7 +2394,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
  *                requires the dmap control page to be adjusted.
  *      newval -  the new value of the lower level dmap or dmap control
  *                page root.
- *      alloc  -  TRUE if adjustment is due to an allocation.
+ *      alloc  -  'true' if adjustment is due to an allocation.
  *      level  -  current level of dmap control page (i.e. L0, L1, L2) to
  *                be adjusted.
  *
@@ -3290,7 +3290,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno,   s64 nblocks)
 {
        struct jfs_sb_info *sbi = JFS_SBI(ipbmap->i_sb);
        int nbperpage = sbi->nbperpage;
-       int i, i0 = TRUE, j, j0 = TRUE, k, n;
+       int i, i0 = true, j, j0 = true, k, n;
        s64 newsize;
        s64 p;
        struct metapage *mp, *l2mp, *l1mp = NULL, *l0mp = NULL;
@@ -3398,7 +3398,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno,   s64 nblocks)
                        j = (blkno & (MAXL1SIZE - 1)) >> L2MAXL0SIZE;
                        l1leaf = l1dcp->stree + CTLLEAFIND + j;
                        p = BLKTOL0(blkno, sbi->l2nbperpage);
-                       j0 = FALSE;
+                       j0 = false;
                } else {
                        /* assign/init L1 page */
                        l1mp = get_metapage(ipbmap, p, PSIZE, 0);
@@ -3432,7 +3432,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno,   s64 nblocks)
                                l0leaf = l0dcp->stree + CTLLEAFIND + i;
                                p = BLKTODMAP(blkno,
                                              sbi->l2nbperpage);
-                               i0 = FALSE;
+                               i0 = false;
                        } else {
                                /* assign/init L0 page */
                                l0mp = get_metapage(ipbmap, p, PSIZE, 0);
index 4d52593a5fc669a018cbd09066e52cb269f18a15..933b7457bfbd962334fd91209c0cd5d34243996c 100644 (file)
@@ -74,7 +74,7 @@ static s64 extRoundDown(s64 nb);
  *               extent that is used as an allocation hint if the
  *               xaddr of the xad is non-zero.  on successful exit,
  *               the xad describes the newly allocated extent.
- *     abnr    - boolean_t indicating whether the newly allocated extent
+ *     abnr    - bool indicating whether the newly allocated extent
  *               should be marked as allocated but not recorded.
  *
  * RETURN VALUES:
@@ -83,7 +83,7 @@ static s64 extRoundDown(s64 nb);
  *      -ENOSPC        - insufficient disk resources.
  */
 int
-extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
+extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
 {
        struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
        s64 nxlen, nxaddr, xoff, hint, xaddr = 0;
@@ -117,7 +117,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
                 * following the hint extent.
                 */
                if (offsetXAD(xp) + nxlen == xoff &&
-                   abnr == ((xp->flag & XAD_NOTRECORDED) ? TRUE : FALSE))
+                   abnr == ((xp->flag & XAD_NOTRECORDED) ? true : false))
                        xaddr = hint + nxlen;
 
                /* adjust the hint to the last block of the extent */
@@ -148,7 +148,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
        }
 
        /* determine the value of the extent flag */
-       xflag = (abnr == TRUE) ? XAD_NOTRECORDED : 0;
+       xflag = abnr ? XAD_NOTRECORDED : 0;
 
        /* if we can extend the hint extent to cover the current request, 
         * extend it.  otherwise, insert a new extent to
@@ -203,7 +203,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
  *     xlen    - request size of the resulting extent.
  *     xp      - pointer to an xad. on successful exit, the xad
  *               describes the newly allocated extent.
- *     abnr    - boolean_t indicating whether the newly allocated extent
+ *     abnr    - bool indicating whether the newly allocated extent
  *               should be marked as allocated but not recorded.
  *
  * RETURN VALUES:
@@ -211,7 +211,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
  *      -EIO   - i/o error.
  *      -ENOSPC        - insufficient disk resources.
  */
-int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
+int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr)
 {
        struct super_block *sb = ip->i_sb;
        s64 xaddr, xlen, nxaddr, delta, xoff;
@@ -468,7 +468,7 @@ int extRecord(struct inode *ip, xad_t * xp)
 int extFill(struct inode *ip, xad_t * xp)
 {
        int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
-       s64 blkno = offsetXAD(xp) >> ip->i_blksize;
+       s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
 
 //      assert(ISSPARSE(ip));
 
@@ -476,7 +476,7 @@ int extFill(struct inode *ip, xad_t * xp)
        XADaddress(xp, 0);
 
        /* allocate an extent to fill the hole */
-       if ((rc = extAlloc(ip, nbperpage, blkno, xp, FALSE)))
+       if ((rc = extAlloc(ip, nbperpage, blkno, xp, false)))
                return (rc);
 
        assert(lengthPXD(xp) == nbperpage);
index e80fc7ced87d96ddfa2ae5484130dcb34cbb7d29..3a7f3f22e989625c19e18ad693383ef18185b46c 100644 (file)
 #define        INOHINT(ip)     \
        (addressPXD(&(JFS_IP(ip)->ixpxd)) + lengthPXD(&(JFS_IP(ip)->ixpxd)) - 1)
 
-extern int     extAlloc(struct inode *, s64, s64, xad_t *, boolean_t);
+extern int     extAlloc(struct inode *, s64, s64, xad_t *, bool);
 extern int     extFill(struct inode *, xad_t *);
 extern int     extHint(struct inode *, s64, xad_t *);
-extern int     extRealloc(struct inode *, s64, xad_t *, boolean_t);
+extern int     extRealloc(struct inode *, s64, xad_t *, bool);
 extern int     extRecord(struct inode *, xad_t *);
 
 #endif /* _H_JFS_EXTENT */
index ccbe60aff83de64edddc27381e020c83240adb1b..a45ee2489580e234e2bf72bf2a74bdec681ec4f9 100644 (file)
@@ -78,8 +78,8 @@ static HLIST_HEAD(aggregate_hash);
 /*
  * forward references
  */
-static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
-static int diAllocAny(struct inomap *, int, boolean_t, struct inode *);
+static int diAllocAG(struct inomap *, int, bool, struct inode *);
+static int diAllocAny(struct inomap *, int, bool, struct inode *);
 static int diAllocBit(struct inomap *, struct iag *, int);
 static int diAllocExt(struct inomap *, int, struct inode *);
 static int diAllocIno(struct inomap *, int, struct inode *);
@@ -1345,7 +1345,7 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
  *
  * PARAMETERS:
  *      pip    - pointer to incore inode for the parent inode.
- *      dir    - TRUE if the new disk inode is for a directory.
+ *      dir    - 'true' if the new disk inode is for a directory.
  *      ip     - pointer to a new inode
  *
  * RETURN VALUES:
@@ -1353,7 +1353,7 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
  *      -ENOSPC        - insufficient disk resources.
  *      -EIO   - i/o error.
  */
-int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
+int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 {
        int rc, ino, iagno, addext, extno, bitno, sword;
        int nwords, rem, i, agno;
@@ -1375,7 +1375,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
        /* for a directory, the allocation policy is to start 
         * at the ag level using the preferred ag.
         */
-       if (dir == TRUE) {
+       if (dir) {
                agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);
                AG_LOCK(imap, agno);
                goto tryag;
@@ -1651,7 +1651,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
  * PARAMETERS:
  *      imap   - pointer to inode map control structure.
  *      agno   - allocation group to allocate from.
- *      dir    - TRUE if the new disk inode is for a directory.
+ *      dir    - 'true' if the new disk inode is for a directory.
  *      ip     - pointer to the new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
@@ -1662,7 +1662,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
  *      -EIO   - i/o error.
  */
 static int
-diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
+diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
 {
        int rc, addext, numfree, numinos;
 
@@ -1682,7 +1682,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
         * if there are a small number of free inodes or number of free
         * inodes is a small percentage of the number of backed inodes.
         */
-       if (dir == TRUE)
+       if (dir)
                addext = (numfree < 64 ||
                          (numfree < 256
                           && ((numfree * 100) / numinos) <= 20));
@@ -1721,7 +1721,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
  * PARAMETERS:
  *      imap   - pointer to inode map control structure.
  *      agno   - primary allocation group (to avoid).
- *      dir    - TRUE if the new disk inode is for a directory.
+ *      dir    - 'true' if the new disk inode is for a directory.
  *      ip     - pointer to a new inode to be filled in on successful return
  *               with the disk inode number allocated, its extent address
  *               and the start of the ag.
@@ -1732,7 +1732,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
  *      -EIO   - i/o error.
  */
 static int
-diAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
+diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
 {
        int ag, rc;
        int maxag = JFS_SBI(imap->im_ipimap->i_sb)->bmap->db_maxag;
@@ -2749,7 +2749,7 @@ static int diFindFree(u32 word, int start)
  * PARAMETERS:
  *     ipimap  - Incore inode map inode
  *     inum    - Number of inode to mark in permanent map
- *     is_free - If TRUE indicates inode should be marked freed, otherwise
+ *     is_free - If 'true' indicates inode should be marked freed, otherwise
  *               indicates inode should be marked allocated.
  *
  * RETURN VALUES: 
@@ -2757,7 +2757,7 @@ static int diFindFree(u32 word, int start)
  */
 int
 diUpdatePMap(struct inode *ipimap,
-            unsigned long inum, boolean_t is_free, struct tblock * tblk)
+            unsigned long inum, bool is_free, struct tblock * tblk)
 {
        int rc;
        struct iag *iagp;
@@ -2796,7 +2796,7 @@ diUpdatePMap(struct inode *ipimap,
        /* 
         * mark the inode free in persistent map:
         */
-       if (is_free == TRUE) {
+       if (is_free) {
                /* The inode should have been allocated both in working
                 * map and in persistent map;
                 * the inode will be freed from working map at the release
@@ -3115,7 +3115,6 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
        ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
        ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec);
        ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec);
-       ip->i_blksize = ip->i_sb->s_blocksize;
        ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
        ip->i_generation = le32_to_cpu(dip->di_gen);
 
index 6e24465f0f98d12cba1eb35bbe9b37ae0c8bcbee..e3b7db47db6bb31e6acd06b927e70a0a978bf112 100644 (file)
@@ -159,11 +159,11 @@ struct inomap {
 #define        im_maxag        im_imap.in_maxag
 
 extern int diFree(struct inode *);
-extern int diAlloc(struct inode *, boolean_t, struct inode *);
+extern int diAlloc(struct inode *, bool, struct inode *);
 extern int diSync(struct inode *);
 /* external references */
 extern int diUpdatePMap(struct inode *ipimap, unsigned long inum,
-                       boolean_t is_free, struct tblock * tblk);
+                       bool is_free, struct tblock * tblk);
 extern int diExtendFS(struct inode *ipimap, struct inode *ipbmap);
 extern int diMount(struct inode *);
 extern int diUnmount(struct inode *, int);
index 495df402916dbf5d3ff77415aec2085e9f50daf8..bffaca9ae3a20ef31e737485230b0836d666887a 100644 (file)
@@ -115,7 +115,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
        }
        jfs_inode->mode2 |= mode;
 
-       inode->i_blksize = sb->s_blocksize;
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        jfs_inode->otime = inode->i_ctime.tv_sec;
index e1e0a6e6ebdfb8d0e1c591a124a249e908fb2174..f5afc129d6b12d2c9483574441f7b7296fb15cac 100644 (file)
@@ -257,7 +257,7 @@ static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock,
        int rc = 0;
        int xflag;
        s64 xaddr;
-       sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >>
+       sector_t file_blocks = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
                               inode->i_blkbits;
 
        if (lblock >= file_blocks)
index d17a3290f5aab901253c0f2d43b136a237dc893d..01a5a455e012709d95b55f2a45e41e7bac5c879e 100644 (file)
@@ -65,10 +65,10 @@ extern struct metapage *__get_metapage(struct inode *inode,
                                  int absolute, unsigned long new);
 
 #define read_metapage(inode, lblock, size, absolute)\
-        __get_metapage(inode, lblock, size, absolute, FALSE)
+        __get_metapage(inode, lblock, size, absolute, false)
 
 #define get_metapage(inode, lblock, size, absolute)\
-        __get_metapage(inode, lblock, size, absolute, TRUE)
+        __get_metapage(inode, lblock, size, absolute, true)
 
 extern void release_metapage(struct metapage *);
 extern void grab_metapage(struct metapage *);
index efbb586bed4bcc25db3e8b270bae3720fe7d5ab1..ebfa6c061d78c5e7ff4755522291b38ca7278d38 100644 (file)
@@ -282,7 +282,7 @@ int txInit(void)
        TxLockVHWM = (nTxLock * 8) / 10;
 
        size = sizeof(struct tblock) * nTxBlock;
-       TxBlock = (struct tblock *) vmalloc(size);
+       TxBlock = vmalloc(size);
        if (TxBlock == NULL)
                return -ENOMEM;
 
@@ -307,7 +307,7 @@ int txInit(void)
         * tlock id = 0 is reserved.
         */
        size = sizeof(struct tlock) * nTxLock;
-       TxLock = (struct tlock *) vmalloc(size);
+       TxLock = vmalloc(size);
        if (TxLock == NULL) {
                vfree(TxBlock);
                return -ENOMEM;
@@ -2393,7 +2393,7 @@ static void txUpdateMap(struct tblock * tblk)
         * unlock mapper/write lock
         */
        if (tblk->xflag & COMMIT_CREATE) {
-               diUpdatePMap(ipimap, tblk->ino, FALSE, tblk);
+               diUpdatePMap(ipimap, tblk->ino, false, tblk);
                /* update persistent block allocation map
                 * for the allocation of inode extent;
                 */
@@ -2403,7 +2403,7 @@ static void txUpdateMap(struct tblock * tblk)
                txAllocPMap(ipimap, (struct maplock *) & pxdlock, tblk);
        } else if (tblk->xflag & COMMIT_DELETE) {
                ip = tblk->u.ip;
-               diUpdatePMap(ipimap, ip->i_ino, TRUE, tblk);
+               diUpdatePMap(ipimap, ip->i_ino, true, tblk);
                iput(ip);
        }
 }
@@ -2451,7 +2451,7 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
                        if (xad->flag & (XAD_NEW | XAD_EXTENDED)) {
                                xaddr = addressXAD(xad);
                                xlen = lengthXAD(xad);
-                               dbUpdatePMap(ipbmap, FALSE, xaddr,
+                               dbUpdatePMap(ipbmap, false, xaddr,
                                             (s64) xlen, tblk);
                                xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
                                jfs_info("allocPMap: xaddr:0x%lx xlen:%d",
@@ -2462,7 +2462,7 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
                pxdlock = (struct pxd_lock *) maplock;
                xaddr = addressPXD(&pxdlock->pxd);
                xlen = lengthPXD(&pxdlock->pxd);
-               dbUpdatePMap(ipbmap, FALSE, xaddr, (s64) xlen, tblk);
+               dbUpdatePMap(ipbmap, false, xaddr, (s64) xlen, tblk);
                jfs_info("allocPMap: xaddr:0x%lx xlen:%d", (ulong) xaddr, xlen);
        } else {                /* (maplock->flag & mlckALLOCPXDLIST) */
 
@@ -2471,7 +2471,7 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
                for (n = 0; n < pxdlistlock->count; n++, pxd++) {
                        xaddr = addressPXD(pxd);
                        xlen = lengthPXD(pxd);
-                       dbUpdatePMap(ipbmap, FALSE, xaddr, (s64) xlen,
+                       dbUpdatePMap(ipbmap, false, xaddr, (s64) xlen,
                                     tblk);
                        jfs_info("allocPMap: xaddr:0x%lx xlen:%d",
                                 (ulong) xaddr, xlen);
@@ -2513,7 +2513,7 @@ void txFreeMap(struct inode *ip,
                                if (!(xad->flag & XAD_NEW)) {
                                        xaddr = addressXAD(xad);
                                        xlen = lengthXAD(xad);
-                                       dbUpdatePMap(ipbmap, TRUE, xaddr,
+                                       dbUpdatePMap(ipbmap, true, xaddr,
                                                     (s64) xlen, tblk);
                                        jfs_info("freePMap: xaddr:0x%lx "
                                                 "xlen:%d",
@@ -2524,7 +2524,7 @@ void txFreeMap(struct inode *ip,
                        pxdlock = (struct pxd_lock *) maplock;
                        xaddr = addressPXD(&pxdlock->pxd);
                        xlen = lengthPXD(&pxdlock->pxd);
-                       dbUpdatePMap(ipbmap, TRUE, xaddr, (s64) xlen,
+                       dbUpdatePMap(ipbmap, true, xaddr, (s64) xlen,
                                     tblk);
                        jfs_info("freePMap: xaddr:0x%lx xlen:%d",
                                 (ulong) xaddr, xlen);
@@ -2535,7 +2535,7 @@ void txFreeMap(struct inode *ip,
                        for (n = 0; n < pxdlistlock->count; n++, pxd++) {
                                xaddr = addressPXD(pxd);
                                xlen = lengthPXD(pxd);
-                               dbUpdatePMap(ipbmap, TRUE, xaddr,
+                               dbUpdatePMap(ipbmap, true, xaddr,
                                             (s64) xlen, tblk);
                                jfs_info("freePMap: xaddr:0x%lx xlen:%d",
                                         (ulong) xaddr, xlen);
index 5bfad39a20787ef5b8721f1aa723f1c8a1e7b526..09b2529586874159c550978ea46410285738035a 100644 (file)
@@ -57,10 +57,6 @@ struct timestruc_t {
 #define        HIGHORDER       0x80000000u     /* high order bit on            */
 #define        ONES            0xffffffffu     /* all bit on                   */
 
-typedef int boolean_t;
-#define TRUE 1
-#define FALSE 0
-
 /*
  *     logical xd (lxd)
  */
index e72f4ebb6e9cd8058f0be8a656cb04d584feb238..c92307d3a57ea21480d9081586da1ca00da15011 100644 (file)
@@ -2964,7 +2964,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,    /* old XAD */
                        cmSetXD(ip, cp, pno, dxaddr, nblks);
 
                        /* release the cbuf, mark it as modified */
-                       cmPut(cp, TRUE);
+                       cmPut(cp, true);
 
                        dxaddr += nblks;
                        sxaddr += nblks;
index 295268ad231b5ec1f26c78cb43489d434122c907..b8d16a6aa88f0c7c11f4bb741f671bba40ac51c6 100644 (file)
@@ -292,7 +292,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
        mark_inode_dirty(ip);
 
        /* update parent directory inode */
-       dip->i_nlink++;         /* for '..' from child directory */
+       inc_nlink(dip);         /* for '..' from child directory */
        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
        mark_inode_dirty(dip);
 
@@ -393,9 +393,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
        /* update parent directory's link count corresponding
         * to ".." entry of the target directory deleted
         */
-       dip->i_nlink--;
        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
-       mark_inode_dirty(dip);
+       inode_dec_link_count(dip);
 
        /*
         * OS/2 could have created EA and/or ACL
@@ -415,7 +414,7 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
        JFS_IP(ip)->acl.flag = 0;
 
        /* mark the target directory as deleted */
-       ip->i_nlink = 0;
+       clear_nlink(ip);
        mark_inode_dirty(ip);
 
        rc = txCommit(tid, 2, &iplist[0], 0);
@@ -515,8 +514,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
        mark_inode_dirty(dip);
 
        /* update target's inode */
-       ip->i_nlink--;
-       mark_inode_dirty(ip);
+       inode_dec_link_count(ip);
 
        /*
         *      commit zero link count object
@@ -824,7 +822,7 @@ static int jfs_link(struct dentry *old_dentry,
                goto free_dname;
 
        /* update object inode */
-       ip->i_nlink++;          /* for new link */
+       inc_nlink(ip);          /* for new link */
        ip->i_ctime = CURRENT_TIME;
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        mark_inode_dirty(dir);
@@ -835,7 +833,7 @@ static int jfs_link(struct dentry *old_dentry,
        rc = txCommit(tid, 2, &iplist[0], 0);
 
        if (rc) {
-               ip->i_nlink--;
+               ip->i_nlink--; /* never instantiated */
                iput(ip);
        } else
                d_instantiate(dentry, ip);
@@ -1155,9 +1153,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                              old_ip->i_ino, JFS_RENAME);
                if (rc)
                        goto out4;
-               new_ip->i_nlink--;
+               drop_nlink(new_ip);
                if (S_ISDIR(new_ip->i_mode)) {
-                       new_ip->i_nlink--;
+                       drop_nlink(new_ip);
                        if (new_ip->i_nlink) {
                                mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
                                if (old_dir != new_dir)
@@ -1208,7 +1206,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        goto out4;
                }
                if (S_ISDIR(old_ip->i_mode))
-                       new_dir->i_nlink++;
+                       inc_nlink(new_dir);
        }
        /*
         * Remove old directory entry
@@ -1223,7 +1221,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                goto out4;
        }
        if (S_ISDIR(old_ip->i_mode)) {
-               old_dir->i_nlink--;
+               drop_nlink(old_dir);
                if (old_dir != new_dir) {
                        /*
                         * Change inode number of parent for moved directory
index 9bc5b7c055ce12ad015dc90df3d87fd72f42a7e7..7a10e19289611902f88d7286b17295d69f1e0861 100644 (file)
@@ -97,26 +97,26 @@ static inline int is_os2_xattr(struct jfs_ea *ea)
         */
        if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) &&
            !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
-               return FALSE;
+               return false;
        /*
         * Check for "user."
         */
        if ((ea->namelen >= XATTR_USER_PREFIX_LEN) &&
            !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
-               return FALSE;
+               return false;
        /*
         * Check for "security."
         */
        if ((ea->namelen >= XATTR_SECURITY_PREFIX_LEN) &&
            !strncmp(ea->name, XATTR_SECURITY_PREFIX,
                     XATTR_SECURITY_PREFIX_LEN))
-               return FALSE;
+               return false;
        /*
         * Check for "trusted."
         */
        if ((ea->namelen >= XATTR_TRUSTED_PREFIX_LEN) &&
            !strncmp(ea->name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
-               return FALSE;
+               return false;
        /*
         * Add any other valid namespace prefixes here
         */
@@ -124,7 +124,7 @@ static inline int is_os2_xattr(struct jfs_ea *ea)
        /*
         * We assume it's OS/2's flat namespace
         */
-       return TRUE;
+       return true;
 }
 
 static inline int name_size(struct jfs_ea *ea)
index ac02ea602c3df2d7194e21c87f133786731bf7ee..bd08e0e64a8caa8731c9ee5ccbd37962eb658298 100644 (file)
@@ -243,7 +243,7 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den
        struct inode *inode = old_dentry->d_inode;
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       inode->i_nlink++;
+       inc_nlink(inode);
        atomic_inc(&inode->i_count);
        dget(dentry);
        d_instantiate(dentry, inode);
@@ -275,7 +275,7 @@ int simple_unlink(struct inode *dir, struct dentry *dentry)
        struct inode *inode = dentry->d_inode;
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       inode->i_nlink--;
+       drop_nlink(inode);
        dput(dentry);
        return 0;
 }
@@ -285,9 +285,9 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
        if (!simple_empty(dentry))
                return -ENOTEMPTY;
 
-       dentry->d_inode->i_nlink--;
+       drop_nlink(dentry->d_inode);
        simple_unlink(dir, dentry);
-       dir->i_nlink--;
+       drop_nlink(dir);
        return 0;
 }
 
@@ -303,10 +303,10 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (new_dentry->d_inode) {
                simple_unlink(new_dir, new_dentry);
                if (they_are_dirs)
-                       old_dir->i_nlink--;
+                       drop_nlink(old_dir);
        } else if (they_are_dirs) {
-               old_dir->i_nlink--;
-               new_dir->i_nlink++;
+               drop_nlink(old_dir);
+               inc_nlink(new_dir);
        }
 
        old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
@@ -317,17 +317,9 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 int simple_readpage(struct file *file, struct page *page)
 {
-       void *kaddr;
-
-       if (PageUptodate(page))
-               goto out;
-
-       kaddr = kmap_atomic(page, KM_USER0);
-       memset(kaddr, 0, PAGE_CACHE_SIZE);
-       kunmap_atomic(kaddr, KM_USER0);
+       clear_highpage(page);
        flush_dcache_page(page);
        SetPageUptodate(page);
-out:
        unlock_page(page);
        return 0;
 }
@@ -383,7 +375,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
                return -ENOMEM;
        inode->i_mode = S_IFDIR | 0755;
        inode->i_uid = inode->i_gid = 0;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        inode->i_op = &simple_dir_inode_operations;
@@ -405,7 +396,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
                        goto out;
                inode->i_mode = S_IFREG | files->mode;
                inode->i_uid = inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_fop = files->ops;
@@ -547,7 +537,7 @@ int simple_attr_open(struct inode *inode, struct file *file,
 
        attr->get = get;
        attr->set = set;
-       attr->data = inode->u.generic_ip;
+       attr->data = inode->i_private;
        attr->fmt = fmt;
        mutex_init(&attr->mutex);
 
index 52774feab93f3c4736febeeca2146a7dad2b9dfc..f95cc3f3c42db4ff709cd2a4f203d78a619323b6 100644 (file)
@@ -160,7 +160,7 @@ static void nlmclnt_prepare_reclaim(struct nlm_host *host)
         */
        list_splice_init(&host->h_granted, &host->h_reclaim);
 
-       dprintk("NLM: reclaiming locks for host %s", host->h_name);
+       dprintk("NLM: reclaiming locks for host %s\n", host->h_name);
 }
 
 static void nlmclnt_finish_reclaim(struct nlm_host *host)
index 50dbb67ae0c4bb271d60784135dfc0bf7cd8e6e2..271e2165fff6ebf8577f4f5ab590a911ec9bedfe 100644 (file)
@@ -100,7 +100,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_
        res = __nlm_find_lockowner(host, owner);
        if (res == NULL) {
                spin_unlock(&host->h_lock);
-               new = (struct nlm_lockowner *)kmalloc(sizeof(*new), GFP_KERNEL);
+               new = kmalloc(sizeof(*new), GFP_KERNEL);
                spin_lock(&host->h_lock);
                res = __nlm_find_lockowner(host, owner);
                if (res == NULL && new != NULL) {
index 703fb038c813c352430295c3537b6a7cc32debf8..a0d0b58ce7a49968aa8ed942d00fbec3e9fc9539 100644 (file)
@@ -99,9 +99,9 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
        /* Ooops, no host found, create it */
        dprintk("lockd: creating host entry\n");
 
-       if (!(host = (struct nlm_host *) kmalloc(sizeof(*host), GFP_KERNEL)))
+       host = kzalloc(sizeof(*host), GFP_KERNEL);
+       if (!host)
                goto nohost;
-       memset(host, 0, sizeof(*host));
 
        addr = sin->sin_addr.s_addr;
        sprintf(host->h_name, "%u.%u.%u.%u", NIPQUAD(addr));
index 01b4db9e5466d51f98383c221e41a8ede824421c..a92dd98f84013dbece84aa0367f7ed869f487c92 100644 (file)
@@ -100,11 +100,10 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
        nlm_debug_print_fh("creating file for", f);
 
        nfserr = nlm_lck_denied_nolocks;
-       file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
+       file = kzalloc(sizeof(*file), GFP_KERNEL);
        if (!file)
                goto out_unlock;
 
-       memset(file, 0, sizeof(*file));
        memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
        file->f_hash = hash;
        init_MUTEX(&file->f_sema);
index d7c53392cac12cf5b907d0122e1e504ca7a26f0e..21dfadfca2bc1402613407215a807ee3bda44173 100644 (file)
@@ -314,13 +314,13 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
        off_t start, end;
 
        switch (l->l_whence) {
-       case 0: /*SEEK_SET*/
+       case SEEK_SET:
                start = 0;
                break;
-       case 1: /*SEEK_CUR*/
+       case SEEK_CUR:
                start = filp->f_pos;
                break;
-       case 2: /*SEEK_END*/
+       case SEEK_END:
                start = i_size_read(filp->f_dentry->d_inode);
                break;
        default:
@@ -364,13 +364,13 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
        loff_t start;
 
        switch (l->l_whence) {
-       case 0: /*SEEK_SET*/
+       case SEEK_SET:
                start = 0;
                break;
-       case 1: /*SEEK_CUR*/
+       case SEEK_CUR:
                start = filp->f_pos;
                break;
-       case 2: /*SEEK_END*/
+       case SEEK_END:
                start = i_size_read(filp->f_dentry->d_inode);
                break;
        default:
index e4fde1ab22cdb0a5af105cdea66cccf9473ac08e..0ff71256e65b4fb0d3a9fc4352c0a8c9b4b5e365 100644 (file)
@@ -160,6 +160,7 @@ __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
 
 static void
 __mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
+       __releases(mb_cache_spinlock)
 {
        /* Wake up all processes queuing for this cache entry. */
        if (ce->e_queued)
index 4a6abc49418ef9917106d3ed6077be25154e57e4..df6b1075b5494dd380dbe374e0be88239e8b93e8 100644 (file)
@@ -254,7 +254,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
        inode->i_ino = j;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u));
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
index 420b32882a10ce6f55c8cd6d396d5045f334d5d6..40eac2e60d25deb803bebfbd4712e5caae5a65b6 100644 (file)
@@ -17,8 +17,10 @@ int minix_sync_file(struct file *, struct dentry *, int);
 
 const struct file_operations minix_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .fsync          = minix_sync_file,
        .sendfile       = generic_file_sendfile,
index 330ff9fc7cf065eb0b41871be0ee9a542a6a92e3..c11a4b9fb863c5e10ae342b5637dd1ddd4dc1145 100644 (file)
@@ -90,8 +90,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(minix_inode_cachep))
-               printk(KERN_INFO "minix_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(minix_inode_cachep);
 }
 
 static struct super_operations minix_sops = {
@@ -145,11 +144,10 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        struct inode *root_inode;
        struct minix_sb_info *sbi;
 
-       sbi = kmalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct minix_sb_info));
 
        /* N.B. These should be compile-time tests.
           Unfortunately that is impossible. */
@@ -207,10 +205,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
                goto out_illegal_sb;
        i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
-       map = kmalloc(i, GFP_KERNEL);
+       map = kzalloc(i, GFP_KERNEL);
        if (!map)
                goto out_no_map;
-       memset(map, 0, i);
        sbi->s_imap = &map[0];
        sbi->s_zmap = &map[sbi->s_imap_blocks];
 
@@ -399,7 +396,7 @@ static void V1_minix_read_inode(struct inode * inode)
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        for (i = 0; i < 9; i++)
                minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
        minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
@@ -432,7 +429,7 @@ static void V2_minix_read_inode(struct inode * inode)
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        for (i = 0; i < 10; i++)
                minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
        minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
index 5b6a4540a05b61cf496d2f5b3bcbd2c3e9958fa0..299bb66e3bde55a880435c5dee0c315cfbdced0d 100644 (file)
@@ -249,7 +249,7 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
                minix_set_link(new_de, new_page, old_inode);
                new_inode->i_ctime = CURRENT_TIME_SEC;
                if (dir_de)
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                inode_dec_link_count(new_inode);
        } else {
                if (dir_de) {
index 1e4598247d0b962f02eca7f390bf6683c9df3e4e..692a3e578fc8f1102823548dbc5d49a1a1850953 100644 (file)
@@ -693,6 +693,8 @@ out:
  * the call was made get new I/O started against them.  If wbc->sync_mode is
  * WB_SYNC_ALL then we were called for data integrity and we must wait for
  * existing IO to complete.
+ *
+ * If you fix this you should check generic_writepages() also!
  */
 int
 mpage_writepages(struct address_space *mapping,
index 9e44158a7540d3c41e6324c89ea78ebfa68c016b..b0f01b3b0536de2dbe775a2d2d2988d255f7fba5 100644 (file)
@@ -280,7 +280,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
                        struct nameidata *nd)
 {
        struct super_block *sb = dir->i_sb;
-       struct inode *inode;
+       struct inode *inode = NULL;
        struct fat_slot_info sinfo;
        struct timespec ts;
        unsigned char msdos_name[MSDOS_NAME];
@@ -316,6 +316,8 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
        d_instantiate(dentry, inode);
 out:
        unlock_kernel();
+       if (!err)
+               err = fat_flush_inodes(sb, dir, inode);
        return err;
 }
 
@@ -341,13 +343,15 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
        err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
        if (err)
                goto out;
-       dir->i_nlink--;
+       drop_nlink(dir);
 
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
        unlock_kernel();
+       if (!err)
+               err = fat_flush_inodes(inode->i_sb, dir, inode);
 
        return err;
 }
@@ -385,7 +389,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
        if (err)
                goto out_free;
-       dir->i_nlink++;
+       inc_nlink(dir);
 
        inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
        brelse(sinfo.bh);
@@ -401,6 +405,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        d_instantiate(dentry, inode);
 
        unlock_kernel();
+       fat_flush_inodes(sb, dir, inode);
        return 0;
 
 out_free:
@@ -425,11 +430,13 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
        err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
        if (err)
                goto out;
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
        unlock_kernel();
+       if (!err)
+               err = fat_flush_inodes(inode->i_sb, dir, inode);
 
        return err;
 }
@@ -542,9 +549,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
                        if (err)
                                goto error_dotdot;
                }
-               old_dir->i_nlink--;
+               drop_nlink(old_dir);
                if (!new_inode)
-                       new_dir->i_nlink++;
+                       inc_nlink(new_dir);
        }
 
        err = fat_remove_entries(old_dir, &old_sinfo);  /* and releases bh */
@@ -559,10 +566,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
                mark_inode_dirty(old_dir);
 
        if (new_inode) {
+               drop_nlink(new_inode);
                if (is_dir)
-                       new_inode->i_nlink -= 2;
-               else
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                new_inode->i_ctime = ts;
        }
 out:
@@ -635,6 +641,8 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
                              new_dir, new_msdos_name, new_dentry, is_hid);
 out:
        unlock_kernel();
+       if (!err)
+               err = fat_flush_inodes(old_dir->i_sb, old_dir, new_dir);
        return err;
 }
 
index 6b591c01b09fcbff6775cbcb8ca7fc8a62c195ca..28d49b301d5516bbdfb5bf7651f3c51b8f370f31 100644 (file)
@@ -372,6 +372,30 @@ void release_open_intent(struct nameidata *nd)
                fput(nd->intent.open.file);
 }
 
+static inline struct dentry *
+do_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+       int status = dentry->d_op->d_revalidate(dentry, nd);
+       if (unlikely(status <= 0)) {
+               /*
+                * The dentry failed validation.
+                * If d_revalidate returned 0 attempt to invalidate
+                * the dentry otherwise d_revalidate is asking us
+                * to return a fail status.
+                */
+               if (!status) {
+                       if (!d_invalidate(dentry)) {
+                               dput(dentry);
+                               dentry = NULL;
+                       }
+               } else {
+                       dput(dentry);
+                       dentry = ERR_PTR(status);
+               }
+       }
+       return dentry;
+}
+
 /*
  * Internal lookup() using the new generic dcache.
  * SMP-safe
@@ -386,12 +410,9 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
        if (!dentry)
                dentry = d_lookup(parent, name);
 
-       if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
-               if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
-                       dput(dentry);
-                       dentry = NULL;
-               }
-       }
+       if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
+               dentry = do_revalidate(dentry, nd);
+
        return dentry;
 }
 
@@ -484,10 +505,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
         */
        mutex_unlock(&dir->i_mutex);
        if (result->d_op && result->d_op->d_revalidate) {
-               if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
-                       dput(result);
+               result = do_revalidate(result, nd);
+               if (!result)
                        result = ERR_PTR(-ENOENT);
-               }
        }
        return result;
 }
@@ -498,18 +518,20 @@ static int __emul_lookup_dentry(const char *, struct nameidata *);
 static __always_inline int
 walk_init_root(const char *name, struct nameidata *nd)
 {
-       read_lock(&current->fs->lock);
-       if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
-               nd->mnt = mntget(current->fs->altrootmnt);
-               nd->dentry = dget(current->fs->altroot);
-               read_unlock(&current->fs->lock);
+       struct fs_struct *fs = current->fs;
+
+       read_lock(&fs->lock);
+       if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+               nd->mnt = mntget(fs->altrootmnt);
+               nd->dentry = dget(fs->altroot);
+               read_unlock(&fs->lock);
                if (__emul_lookup_dentry(name,nd))
                        return 0;
-               read_lock(&current->fs->lock);
+               read_lock(&fs->lock);
        }
-       nd->mnt = mntget(current->fs->rootmnt);
-       nd->dentry = dget(current->fs->root);
-       read_unlock(&current->fs->lock);
+       nd->mnt = mntget(fs->rootmnt);
+       nd->dentry = dget(fs->root);
+       read_unlock(&fs->lock);
        return 1;
 }
 
@@ -704,17 +726,19 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
 
 static __always_inline void follow_dotdot(struct nameidata *nd)
 {
+       struct fs_struct *fs = current->fs;
+
        while(1) {
                struct vfsmount *parent;
                struct dentry *old = nd->dentry;
 
-                read_lock(&current->fs->lock);
-               if (nd->dentry == current->fs->root &&
-                   nd->mnt == current->fs->rootmnt) {
-                        read_unlock(&current->fs->lock);
+                read_lock(&fs->lock);
+               if (nd->dentry == fs->root &&
+                   nd->mnt == fs->rootmnt) {
+                        read_unlock(&fs->lock);
                        break;
                }
-                read_unlock(&current->fs->lock);
+                read_unlock(&fs->lock);
                spin_lock(&dcache_lock);
                if (nd->dentry != nd->mnt->mnt_root) {
                        nd->dentry = dget(nd->dentry->d_parent);
@@ -767,12 +791,12 @@ need_lookup:
        goto done;
 
 need_revalidate:
-       if (dentry->d_op->d_revalidate(dentry, nd))
-               goto done;
-       if (d_invalidate(dentry))
-               goto done;
-       dput(dentry);
-       goto need_lookup;
+       dentry = do_revalidate(dentry, nd);
+       if (!dentry)
+               goto need_lookup;
+       if (IS_ERR(dentry))
+               goto fail;
+       goto done;
 
 fail:
        return PTR_ERR(dentry);
@@ -1022,15 +1046,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
                struct vfsmount *old_mnt = nd->mnt;
                struct qstr last = nd->last;
                int last_type = nd->last_type;
+               struct fs_struct *fs = current->fs;
+
                /*
-                * NAME was not found in alternate root or it's a directory.  Try to find
-                * it in the normal root:
+                * NAME was not found in alternate root or it's a directory.
+                * Try to find it in the normal root:
                 */
                nd->last_type = LAST_ROOT;
-               read_lock(&current->fs->lock);
-               nd->mnt = mntget(current->fs->rootmnt);
-               nd->dentry = dget(current->fs->root);
-               read_unlock(&current->fs->lock);
+               read_lock(&fs->lock);
+               nd->mnt = mntget(fs->rootmnt);
+               nd->dentry = dget(fs->root);
+               read_unlock(&fs->lock);
                if (path_walk(name, nd) == 0) {
                        if (nd->dentry->d_inode) {
                                dput(old_dentry);
@@ -1054,6 +1080,7 @@ void set_fs_altroot(void)
        struct vfsmount *mnt = NULL, *oldmnt;
        struct dentry *dentry = NULL, *olddentry;
        int err;
+       struct fs_struct *fs = current->fs;
 
        if (!emul)
                goto set_it;
@@ -1063,12 +1090,12 @@ void set_fs_altroot(void)
                dentry = nd.dentry;
        }
 set_it:
-       write_lock(&current->fs->lock);
-       oldmnt = current->fs->altrootmnt;
-       olddentry = current->fs->altroot;
-       current->fs->altrootmnt = mnt;
-       current->fs->altroot = dentry;
-       write_unlock(&current->fs->lock);
+       write_lock(&fs->lock);
+       oldmnt = fs->altrootmnt;
+       olddentry = fs->altroot;
+       fs->altrootmnt = mnt;
+       fs->altroot = dentry;
+       write_unlock(&fs->lock);
        if (olddentry) {
                dput(olddentry);
                mntput(oldmnt);
@@ -1082,29 +1109,30 @@ static int fastcall do_path_lookup(int dfd, const char *name,
        int retval = 0;
        int fput_needed;
        struct file *file;
+       struct fs_struct *fs = current->fs;
 
        nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags;
        nd->depth = 0;
 
        if (*name=='/') {
-               read_lock(&current->fs->lock);
-               if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
-                       nd->mnt = mntget(current->fs->altrootmnt);
-                       nd->dentry = dget(current->fs->altroot);
-                       read_unlock(&current->fs->lock);
+               read_lock(&fs->lock);
+               if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+                       nd->mnt = mntget(fs->altrootmnt);
+                       nd->dentry = dget(fs->altroot);
+                       read_unlock(&fs->lock);
                        if (__emul_lookup_dentry(name,nd))
                                goto out; /* found in altroot */
-                       read_lock(&current->fs->lock);
+                       read_lock(&fs->lock);
                }
-               nd->mnt = mntget(current->fs->rootmnt);
-               nd->dentry = dget(current->fs->root);
-               read_unlock(&current->fs->lock);
+               nd->mnt = mntget(fs->rootmnt);
+               nd->dentry = dget(fs->root);
+               read_unlock(&fs->lock);
        } else if (dfd == AT_FDCWD) {
-               read_lock(&current->fs->lock);
-               nd->mnt = mntget(current->fs->pwdmnt);
-               nd->dentry = dget(current->fs->pwd);
-               read_unlock(&current->fs->lock);
+               read_lock(&fs->lock);
+               nd->mnt = mntget(fs->pwdmnt);
+               nd->dentry = dget(fs->pwd);
+               read_unlock(&fs->lock);
        } else {
                struct dentry *dentry;
 
@@ -1567,6 +1595,24 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
        return 0;
 }
 
+static int open_namei_create(struct nameidata *nd, struct path *path,
+                               int flag, int mode)
+{
+       int error;
+       struct dentry *dir = nd->dentry;
+
+       if (!IS_POSIXACL(dir->d_inode))
+               mode &= ~current->fs->umask;
+       error = vfs_create(dir->d_inode, path->dentry, mode, nd);
+       mutex_unlock(&dir->d_inode->i_mutex);
+       dput(nd->dentry);
+       nd->dentry = path->dentry;
+       if (error)
+               return error;
+       /* Don't check for write permission, don't truncate */
+       return may_open(nd, 0, flag & ~O_TRUNC);
+}
+
 /*
  *     open_namei()
  *
@@ -1648,18 +1694,10 @@ do_last:
 
        /* Negative dentry, just create the file */
        if (!path.dentry->d_inode) {
-               if (!IS_POSIXACL(dir->d_inode))
-                       mode &= ~current->fs->umask;
-               error = vfs_create(dir->d_inode, path.dentry, mode, nd);
-               mutex_unlock(&dir->d_inode->i_mutex);
-               dput(nd->dentry);
-               nd->dentry = path.dentry;
+               error = open_namei_create(nd, &path, flag, mode);
                if (error)
                        goto exit;
-               /* Don't check for write permission, don't truncate */
-               acc_mode = 0;
-               flag &= ~O_TRUNC;
-               goto ok;
+               return 0;
        }
 
        /*
@@ -1906,30 +1944,32 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
 {
        int error = 0;
        char * tmp;
+       struct dentry *dentry;
+       struct nameidata nd;
 
        tmp = getname(pathname);
        error = PTR_ERR(tmp);
-       if (!IS_ERR(tmp)) {
-               struct dentry *dentry;
-               struct nameidata nd;
+       if (IS_ERR(tmp))
+               goto out_err;
 
-               error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
-               if (error)
-                       goto out;
-               dentry = lookup_create(&nd, 1);
-               error = PTR_ERR(dentry);
-               if (!IS_ERR(dentry)) {
-                       if (!IS_POSIXACL(nd.dentry->d_inode))
-                               mode &= ~current->fs->umask;
-                       error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
-                       dput(dentry);
-               }
-               mutex_unlock(&nd.dentry->d_inode->i_mutex);
-               path_release(&nd);
-out:
-               putname(tmp);
-       }
+       error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
+       dentry = lookup_create(&nd, 1);
+       error = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
+               goto out_unlock;
 
+       if (!IS_POSIXACL(nd.dentry->d_inode))
+               mode &= ~current->fs->umask;
+       error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
+       dput(dentry);
+out_unlock:
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
+       path_release(&nd);
+out:
+       putname(tmp);
+out_err:
        return error;
 }
 
@@ -2028,10 +2068,11 @@ static long do_rmdir(int dfd, const char __user *pathname)
        mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
        dentry = lookup_hash(&nd);
        error = PTR_ERR(dentry);
-       if (!IS_ERR(dentry)) {
-               error = vfs_rmdir(nd.dentry->d_inode, dentry);
-               dput(dentry);
-       }
+       if (IS_ERR(dentry))
+               goto exit2;
+       error = vfs_rmdir(nd.dentry->d_inode, dentry);
+       dput(dentry);
+exit2:
        mutex_unlock(&nd.dentry->d_inode->i_mutex);
 exit1:
        path_release(&nd);
@@ -2171,30 +2212,33 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
        int error = 0;
        char * from;
        char * to;
+       struct dentry *dentry;
+       struct nameidata nd;
 
        from = getname(oldname);
        if(IS_ERR(from))
                return PTR_ERR(from);
        to = getname(newname);
        error = PTR_ERR(to);
-       if (!IS_ERR(to)) {
-               struct dentry *dentry;
-               struct nameidata nd;
+       if (IS_ERR(to))
+               goto out_putname;
 
-               error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
-               if (error)
-                       goto out;
-               dentry = lookup_create(&nd, 0);
-               error = PTR_ERR(dentry);
-               if (!IS_ERR(dentry)) {
-                       error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
-                       dput(dentry);
-               }
-               mutex_unlock(&nd.dentry->d_inode->i_mutex);
-               path_release(&nd);
+       error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
+       dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
+               goto out_unlock;
+
+       error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
+       dput(dentry);
+out_unlock:
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
+       path_release(&nd);
 out:
-               putname(to);
-       }
+       putname(to);
+out_putname:
        putname(from);
        return error;
 }
@@ -2280,10 +2324,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
                goto out_release;
        new_dentry = lookup_create(&nd, 0);
        error = PTR_ERR(new_dentry);
-       if (!IS_ERR(new_dentry)) {
-               error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-               dput(new_dentry);
-       }
+       if (IS_ERR(new_dentry))
+               goto out_unlock;
+       error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
+       dput(new_dentry);
+out_unlock:
        mutex_unlock(&nd.dentry->d_inode->i_mutex);
 out_release:
        path_release(&nd);
index 36d180858136fb46e256fcc6550baf7ea6c2dbed..66d921e14feebaa532bed7e6a041ba08e5057a8c 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/quotaops.h>
 #include <linux/acct.h>
 #include <linux/capability.h>
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/mount.h>
+#include <linux/ramfs.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include "pnode.h"
 
-extern int __init init_rootfs(void);
-
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
 
@@ -1813,6 +1813,7 @@ void __init mnt_init(unsigned long mempages)
        struct list_head *d;
        unsigned int nr_hash;
        int i;
+       int err;
 
        init_rwsem(&namespace_sem);
 
@@ -1853,8 +1854,14 @@ void __init mnt_init(unsigned long mempages)
                d++;
                i--;
        } while (i);
-       sysfs_init();
-       subsystem_register(&fs_subsys);
+       err = sysfs_init();
+       if (err)
+               printk(KERN_WARNING "%s: sysfs_init error: %d\n",
+                       __FUNCTION__, err);
+       err = subsystem_register(&fs_subsys);
+       if (err)
+               printk(KERN_WARNING "%s: subsystem_register error: %d\n",
+                       __FUNCTION__, err);
        init_rootfs();
        init_mount_tree();
 }
index b4ee89250e952047c20ec8f8d33919089bae46ab..458b3b785194e815a0081ed3dcd3cf2e116a6172 100644 (file)
@@ -53,6 +53,9 @@ const struct file_operations ncp_dir_operations =
        .read           = generic_read_dir,
        .readdir        = ncp_readdir,
        .ioctl          = ncp_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ncp_compat_ioctl,
+#endif
 };
 
 struct inode_operations ncp_dir_inode_operations =
index e6b7c67cf057765f86921cf2220fee385eaaee38..df37524b85db0a69f823935bdf666cda214f48e8 100644 (file)
@@ -289,6 +289,9 @@ const struct file_operations ncp_file_operations =
        .read           = ncp_file_read,
        .write          = ncp_file_write,
        .ioctl          = ncp_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ncp_compat_ioctl,
+#endif
        .mmap           = ncp_mmap,
        .release        = ncp_release,
        .fsync          = ncp_fsync,
index 1ddf77b0b825d08282944604e582b78244852704..42e3bef270c9d0c029475800fec5023229dfe512 100644 (file)
@@ -81,8 +81,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ncp_inode_cachep))
-               printk(KERN_INFO "ncp_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ncp_inode_cachep);
 }
 
 static int ncp_remount(struct super_block *sb, int *flags, char* data)
@@ -224,7 +223,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
        inode->i_nlink = 1;
        inode->i_uid = server->m.uid;
        inode->i_gid = server->m.gid;
-       inode->i_blksize = NCP_BLOCK_SIZE;
 
        ncp_update_dates(inode, &nwinfo->i);
        ncp_update_inode(inode, nwinfo);
@@ -411,11 +409,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 #endif
        struct ncp_entry_info finfo;
 
-       server = kmalloc(sizeof(struct ncp_server), GFP_KERNEL);
+       server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
        if (!server)
                return -ENOMEM;
        sb->s_fs_info = server;
-       memset(server, 0, sizeof(struct ncp_server));
 
        error = -EFAULT;
        if (raw_data == NULL)
index 42039fe0653c0c3afc546748e060b005ca882fd8..a89ac84a8241a53d4e260deda2ad7d7f8c675255 100644 (file)
@@ -7,19 +7,21 @@
  *
  */
 
-
-#include <asm/uaccess.h>
 #include <linux/capability.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/highuid.h>
+#include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 
 #include <linux/ncp_fs.h>
 
+#include <asm/uaccess.h>
+
 #include "ncplib_kernel.h"
 
 /* maximum limit for ncp_objectname_ioctl */
@@ -89,6 +91,82 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
        return 0;
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_ncp_objectname_ioctl
+{
+       s32             auth_type;
+       u32             object_name_len;
+       compat_caddr_t  object_name;    /* an userspace data, in most cases user name */
+};
+
+struct compat_ncp_fs_info_v2 {
+       s32 version;
+       u32 mounted_uid;
+       u32 connection;
+       u32 buffer_size;
+
+       u32 volume_number;
+       u32 directory_id;
+
+       u32 dummy1;
+       u32 dummy2;
+       u32 dummy3;
+};
+
+struct compat_ncp_ioctl_request {
+       u32 function;
+       u32 size;
+       compat_caddr_t data;
+};
+
+struct compat_ncp_privatedata_ioctl
+{
+       u32             len;
+       compat_caddr_t  data;           /* ~1000 for NDS */
+};
+
+#define NCP_IOC_GET_FS_INFO_V2_32      _IOWR('n', 4, struct compat_ncp_fs_info_v2)
+#define NCP_IOC_NCPREQUEST_32          _IOR('n', 1, struct compat_ncp_ioctl_request)
+#define NCP_IOC_GETOBJECTNAME_32       _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
+#define NCP_IOC_SETOBJECTNAME_32       _IOR('n', 9, struct compat_ncp_objectname_ioctl)
+#define NCP_IOC_GETPRIVATEDATA_32      _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
+#define NCP_IOC_SETPRIVATEDATA_32      _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
+
+static int
+ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
+                  struct compat_ncp_fs_info_v2 __user * arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       struct compat_ncp_fs_info_v2 info2;
+
+       if ((file_permission(file, MAY_WRITE) != 0)
+           && (current->uid != server->m.mounted_uid)) {
+               return -EACCES;
+       }
+       if (copy_from_user(&info2, arg, sizeof(info2)))
+               return -EFAULT;
+
+       if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
+               DPRINTK("info.version invalid: %d\n", info2.version);
+               return -EINVAL;
+       }
+       info2.mounted_uid   = server->m.mounted_uid;
+       info2.connection    = server->connection;
+       info2.buffer_size   = server->buffer_size;
+       info2.volume_number = NCP_FINFO(inode)->volNumber;
+       info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
+       info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
+
+       if (copy_to_user(arg, &info2, sizeof(info2)))
+               return -EFAULT;
+       return 0;
+}
+#endif
+
+#define NCP_IOC_GETMOUNTUID16          _IOW('n', 2, u16)
+#define NCP_IOC_GETMOUNTUID32          _IOW('n', 2, u32)
+#define NCP_IOC_GETMOUNTUID64          _IOW('n', 2, u64)
+
 #ifdef CONFIG_NCPFS_NLS
 /* Here we are select the iocharset and the codepage for NLS.
  * Thanks Petr Vandrovec for idea and many hints.
@@ -192,12 +270,24 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
        void __user *argp = (void __user *)arg;
 
        switch (cmd) {
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_NCPREQUEST_32:
+#endif
        case NCP_IOC_NCPREQUEST:
-
                if ((file_permission(filp, MAY_WRITE) != 0)
                    && (current->uid != server->m.mounted_uid)) {
                        return -EACCES;
                }
+#ifdef CONFIG_COMPAT
+               if (cmd == NCP_IOC_NCPREQUEST_32) {
+                       struct compat_ncp_ioctl_request request32;
+                       if (copy_from_user(&request32, argp, sizeof(request32)))
+                               return -EFAULT;
+                       request.function = request32.function;
+                       request.size = request32.size;
+                       request.data = compat_ptr(request32.data);
+               } else
+#endif
                if (copy_from_user(&request, argp, sizeof(request)))
                        return -EFAULT;
 
@@ -254,19 +344,35 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
        case NCP_IOC_GET_FS_INFO_V2:
                return ncp_get_fs_info_v2(server, filp, argp);
 
-       case NCP_IOC_GETMOUNTUID2:
-               {
-                       unsigned long tmp = server->m.mounted_uid;
-
-                       if ((file_permission(filp, MAY_READ) != 0)
-                           && (current->uid != server->m.mounted_uid))
-                       {
-                               return -EACCES;
-                       }
-                       if (put_user(tmp, (unsigned long __user *)argp)) 
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_GET_FS_INFO_V2_32:
+               return ncp_get_compat_fs_info_v2(server, filp, argp);
+#endif
+       /* we have too many combinations of CONFIG_COMPAT,
+        * CONFIG_64BIT and CONFIG_UID16, so just handle
+        * any of the possible ioctls */
+       case NCP_IOC_GETMOUNTUID16:
+       case NCP_IOC_GETMOUNTUID32:
+       case NCP_IOC_GETMOUNTUID64:
+               if ((file_permission(filp, MAY_READ) != 0)
+                       && (current->uid != server->m.mounted_uid)) {
+                       return -EACCES;
+               }
+               if (cmd == NCP_IOC_GETMOUNTUID16) {
+                       u16 uid;
+                       SET_UID(uid, server->m.mounted_uid);
+                       if (put_user(uid, (u16 __user *)argp))
+                               return -EFAULT;
+               } else if (cmd == NCP_IOC_GETMOUNTUID32) {
+                       if (put_user(server->m.mounted_uid,
+                                               (u32 __user *)argp))
+                               return -EFAULT;
+               } else {
+                       if (put_user(server->m.mounted_uid,
+                                               (u64 __user *)argp))
                                return -EFAULT;
-                       return 0;
                }
+               return 0;
 
        case NCP_IOC_GETROOT:
                {
@@ -476,6 +582,32 @@ outrel:
                }
 #endif /* CONFIG_NCPFS_IOCTL_LOCKING */
 
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_GETOBJECTNAME_32:
+               if (current->uid != server->m.mounted_uid) {
+                       return -EACCES;
+               }
+               {
+                       struct compat_ncp_objectname_ioctl user;
+                       size_t outl;
+
+                       if (copy_from_user(&user, argp, sizeof(user)))
+                               return -EFAULT;
+                       user.auth_type = server->auth.auth_type;
+                       outl = user.object_name_len;
+                       user.object_name_len = server->auth.object_name_len;
+                       if (outl > user.object_name_len)
+                               outl = user.object_name_len;
+                       if (outl) {
+                               if (copy_to_user(compat_ptr(user.object_name),
+                                                server->auth.object_name,
+                                                outl)) return -EFAULT;
+                       }
+                       if (copy_to_user(argp, &user, sizeof(user)))
+                               return -EFAULT;
+                       return 0;
+               }
+#endif
        case NCP_IOC_GETOBJECTNAME:
                if (current->uid != server->m.mounted_uid) {
                        return -EACCES;
@@ -500,6 +632,9 @@ outrel:
                                return -EFAULT;
                        return 0;
                }
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_SETOBJECTNAME_32:
+#endif
        case NCP_IOC_SETOBJECTNAME:
                if (current->uid != server->m.mounted_uid) {
                        return -EACCES;
@@ -512,8 +647,19 @@ outrel:
                        void* oldprivate;
                        size_t oldprivatelen;
 
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_SETOBJECTNAME_32) {
+                               struct compat_ncp_objectname_ioctl user32;
+                               if (copy_from_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                               user.auth_type = user32.auth_type;
+                               user.object_name_len = user32.object_name_len;
+                               user.object_name = compat_ptr(user32.object_name);
+                       } else
+#endif
                        if (copy_from_user(&user, argp, sizeof(user)))
                                return -EFAULT;
+
                        if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
                                return -ENOMEM;
                        if (user.object_name_len) {
@@ -544,6 +690,9 @@ outrel:
                        kfree(oldname);
                        return 0;
                }
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_GETPRIVATEDATA_32:
+#endif
        case NCP_IOC_GETPRIVATEDATA:
                if (current->uid != server->m.mounted_uid) {
                        return -EACCES;
@@ -552,8 +701,18 @@ outrel:
                        struct ncp_privatedata_ioctl user;
                        size_t outl;
 
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
+                               struct compat_ncp_privatedata_ioctl user32;
+                               if (copy_from_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                               user.len = user32.len;
+                               user.data = compat_ptr(user32.data);
+                       } else
+#endif
                        if (copy_from_user(&user, argp, sizeof(user)))
                                return -EFAULT;
+
                        outl = user.len;
                        user.len = server->priv.len;
                        if (outl > user.len) outl = user.len;
@@ -562,10 +721,23 @@ outrel:
                                                 server->priv.data,
                                                 outl)) return -EFAULT;
                        }
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
+                               struct compat_ncp_privatedata_ioctl user32;
+                               user32.len = user.len;
+                               user32.data = (unsigned long) user.data;
+                               if (copy_to_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                       } else
+#endif
                        if (copy_to_user(argp, &user, sizeof(user)))
                                return -EFAULT;
+
                        return 0;
                }
+#ifdef CONFIG_COMPAT
+       case NCP_IOC_SETPRIVATEDATA_32:
+#endif
        case NCP_IOC_SETPRIVATEDATA:
                if (current->uid != server->m.mounted_uid) {
                        return -EACCES;
@@ -576,8 +748,18 @@ outrel:
                        void* old;
                        size_t oldlen;
 
+#ifdef CONFIG_COMPAT
+                       if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
+                               struct compat_ncp_privatedata_ioctl user32;
+                               if (copy_from_user(&user32, argp, sizeof(user32)))
+                                       return -EFAULT;
+                               user.len = user32.len;
+                               user.data = compat_ptr(user32.data);
+                       } else
+#endif
                        if (copy_from_user(&user, argp, sizeof(user)))
                                return -EFAULT;
+
                        if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
                                return -ENOMEM;
                        if (user.len) {
@@ -636,20 +818,19 @@ outrel:
                }
 
        }
-/* #ifdef CONFIG_UID16 */
-       /* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
-           so we have this out of switch */
-       if (cmd == NCP_IOC_GETMOUNTUID) {
-               __kernel_uid_t uid = 0;
-               if ((file_permission(filp, MAY_READ) != 0)
-                   && (current->uid != server->m.mounted_uid)) {
-                       return -EACCES;
-               }
-               SET_UID(uid, server->m.mounted_uid);
-               if (put_user(uid, (__kernel_uid_t __user *)argp))
-                       return -EFAULT;
-               return 0;
-       }
-/* #endif */
        return -EINVAL;
 }
+
+#ifdef CONFIG_COMPAT
+long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       int ret;
+
+       lock_kernel();
+       arg = (unsigned long) compat_ptr(arg);
+       ret = ncp_ioctl(inode, file, cmd, arg);
+       unlock_kernel();
+       return ret;
+}
+#endif
index ca92c240663564c319627de827c58deed0a635ea..e3d26c1bd105a388cf032c3586b192e6b5e56907 100644 (file)
@@ -48,7 +48,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
        char *buf = kmap(page);
 
        error = -ENOMEM;
-       rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
+       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
        if (!rawlink)
                goto fail;
 
@@ -126,7 +126,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
        /* EPERM is returned by VFS if symlink procedure does not exist */
                return -EPERM;
   
-       rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
+       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
        if (!rawlink)
                return -ENOMEM;
 
index 57133678db1660a9599d5b724929a8886bcf97e0..841c99a9b11c84203cb5afbcb9d69f38f3682319 100644 (file)
 #include "delegation.h"
 #include "internal.h"
 
-static struct nfs_delegation *nfs_alloc_delegation(void)
-{
-       return (struct nfs_delegation *)kmalloc(sizeof(struct nfs_delegation), GFP_KERNEL);
-}
-
 static void nfs_free_delegation(struct nfs_delegation *delegation)
 {
        if (delegation->cred)
@@ -124,7 +119,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
        if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)))
                __nfs_revalidate_inode(NFS_SERVER(inode), inode);
 
-       delegation = nfs_alloc_delegation();
+       delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
        if (delegation == NULL)
                return -ENOMEM;
        memcpy(delegation->stateid.data, res->delegation.data,
index 7432f1a43f3d6bc66c3aee43366a3111a46b8ad8..481f8892a919489cb5705269834b0145b0d5c8f1 100644 (file)
@@ -843,7 +843,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
        nfs_inode_return_delegation(inode);
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
                lock_kernel();
-               inode->i_nlink--;
+               drop_nlink(inode);
                nfs_complete_unlink(dentry);
                unlock_kernel();
        }
@@ -1286,7 +1286,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
        error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
        /* Ensure the VFS deletes this inode */
        if (error == 0 && dentry->d_inode != NULL)
-               dentry->d_inode->i_nlink = 0;
+               clear_nlink(dentry->d_inode);
        nfs_end_data_update(dir);
        unlock_kernel();
 
@@ -1401,7 +1401,7 @@ static int nfs_safe_remove(struct dentry *dentry)
                error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
                /* The VFS may want to delete this inode */
                if (error == 0)
-                       inode->i_nlink--;
+                       drop_nlink(inode);
                nfs_mark_for_revalidate(inode);
                nfs_end_data_update(inode);
        } else
@@ -1639,7 +1639,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        goto out;
                }
        } else
-               new_inode->i_nlink--;
+               drop_nlink(new_inode);
 
 go_ahead:
        /*
index 76ca1cbc38f96e418f80ff69095480cef3b7b36c..9f7f8b9ea1e253b2e9614a658a7186720a5a80b1 100644 (file)
@@ -707,8 +707,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
 /**
  * nfs_file_direct_read - file direct read operation for NFS files
  * @iocb: target I/O control block
- * @buf: user's buffer into which to read data
- * @count: number of bytes to read
+ * @iov: vector of user buffers into which to read data
+ * @nr_segs: size of iov vector
  * @pos: byte offset in file where reading starts
  *
  * We use this function for direct reads instead of calling
@@ -725,17 +725,24 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
  * client must read the updated atime from the server back into its
  * cache.
  */
-ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos)
 {
        ssize_t retval = -EINVAL;
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
+       /* XXX: temporary */
+       const char __user *buf = iov[0].iov_base;
+       size_t count = iov[0].iov_len;
 
        dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
                file->f_dentry->d_parent->d_name.name,
                file->f_dentry->d_name.name,
                (unsigned long) count, (long long) pos);
 
+       if (nr_segs != 1)
+               return -EINVAL;
+
        if (count < 0)
                goto out;
        retval = -EFAULT;
@@ -760,8 +767,8 @@ out:
 /**
  * nfs_file_direct_write - file direct write operation for NFS files
  * @iocb: target I/O control block
- * @buf: user's buffer from which to write data
- * @count: number of bytes to write
+ * @iov: vector of user buffers from which to write data
+ * @nr_segs: size of iov vector
  * @pos: byte offset in file where writing starts
  *
  * We use this function for direct writes instead of calling
@@ -782,17 +789,24 @@ out:
  * Note that O_APPEND is not supported for NFS direct writes, as there
  * is no atomic O_APPEND write facility in the NFS protocol.
  */
-ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos)
 {
        ssize_t retval;
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
+       /* XXX: temporary */
+       const char __user *buf = iov[0].iov_base;
+       size_t count = iov[0].iov_len;
 
        dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
                file->f_dentry->d_parent->d_name.name,
                file->f_dentry->d_name.name,
                (unsigned long) count, (long long) pos);
 
+       if (nr_segs != 1)
+               return -EINVAL;
+
        retval = generic_write_checks(file, &pos, &count, 0);
        if (retval)
                goto out;
@@ -855,6 +869,5 @@ int __init nfs_init_directcache(void)
  */
 void nfs_destroy_directcache(void)
 {
-       if (kmem_cache_destroy(nfs_direct_cachep))
-               printk(KERN_INFO "nfs_direct_cache: not all structures were freed\n");
+       kmem_cache_destroy(nfs_direct_cachep);
 }
index be997d649127376d515193ec5460ab61ee46e4d8..cc93865cea932a4e9c78ea95e1c0165e575630d1 100644 (file)
@@ -41,8 +41,10 @@ static int nfs_file_release(struct inode *, struct file *);
 static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
 static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
-static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
-static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
+static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos);
+static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos);
 static int  nfs_file_flush(struct file *, fl_owner_t id);
 static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 static int nfs_check_flags(int flags);
@@ -53,8 +55,8 @@ const struct file_operations nfs_file_operations = {
        .llseek         = nfs_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
-       .aio_read               = nfs_file_read,
-       .aio_write              = nfs_file_write,
+       .aio_read       = nfs_file_read,
+       .aio_write      = nfs_file_write,
        .mmap           = nfs_file_mmap,
        .open           = nfs_file_open,
        .flush          = nfs_file_flush,
@@ -196,15 +198,17 @@ nfs_file_flush(struct file *file, fl_owner_t id)
 }
 
 static ssize_t
-nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
+nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t pos)
 {
        struct dentry * dentry = iocb->ki_filp->f_dentry;
        struct inode * inode = dentry->d_inode;
        ssize_t result;
+       size_t count = iov_length(iov, nr_segs);
 
 #ifdef CONFIG_NFS_DIRECTIO
        if (iocb->ki_filp->f_flags & O_DIRECT)
-               return nfs_file_direct_read(iocb, buf, count, pos);
+               return nfs_file_direct_read(iocb, iov, nr_segs, pos);
 #endif
 
        dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
@@ -214,7 +218,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
        result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
        nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
        if (!result)
-               result = generic_file_aio_read(iocb, buf, count, pos);
+               result = generic_file_aio_read(iocb, iov, nr_segs, pos);
        return result;
 }
 
@@ -336,24 +340,22 @@ const struct address_space_operations nfs_file_aops = {
 #endif
 };
 
-/* 
- * Write to a file (through the page cache).
- */
-static ssize_t
-nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos)
 {
        struct dentry * dentry = iocb->ki_filp->f_dentry;
        struct inode * inode = dentry->d_inode;
        ssize_t result;
+       size_t count = iov_length(iov, nr_segs);
 
 #ifdef CONFIG_NFS_DIRECTIO
        if (iocb->ki_filp->f_flags & O_DIRECT)
-               return nfs_file_direct_write(iocb, buf, count, pos);
+               return nfs_file_direct_write(iocb, iov, nr_segs, pos);
 #endif
 
-       dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
+       dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               inode->i_ino, (unsigned long) count, (unsigned long) pos);
+               inode->i_ino, (unsigned long) count, (long long) pos);
 
        result = -EBUSY;
        if (IS_SWAPFILE(inode))
@@ -372,7 +374,7 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
                goto out;
 
        nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
-       result = generic_file_aio_write(iocb, buf, count, pos);
+       result = generic_file_aio_write(iocb, iov, nr_segs, pos);
 out:
        return result;
 
index e8c143d182c4db83a8a352a05a0f58f777b947c8..bc9376ca86cd28ea645ea38b889ac455faf0b141 100644 (file)
@@ -277,10 +277,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                         * report the blocks in 512byte units
                         */
                        inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
-                       inode->i_blksize = inode->i_sb->s_blocksize;
                } else {
                        inode->i_blocks = fattr->du.nfs2.blocks;
-                       inode->i_blksize = fattr->du.nfs2.blocksize;
                }
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
                nfsi->attrtimeo_timestamp = jiffies;
@@ -443,7 +441,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
 {
        struct nfs_open_context *ctx;
 
-       ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
        if (ctx != NULL) {
                atomic_set(&ctx->count, 1);
                ctx->dentry = dget(dentry);
@@ -969,10 +967,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                 * report the blocks in 512byte units
                 */
                inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
-               inode->i_blksize = inode->i_sb->s_blocksize;
        } else {
                inode->i_blocks = fattr->du.nfs2.blocks;
-               inode->i_blksize = fattr->du.nfs2.blocksize;
        }
 
        if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
@@ -1134,8 +1130,7 @@ static int __init nfs_init_inodecache(void)
 
 static void nfs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(nfs_inode_cachep))
-               printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(nfs_inode_cachep);
 }
 
 /*
index 77b00684894d994cb6d38890906217fbb75be589..60408646176b9e7fdc1c9da0e7cc1c8986812024 100644 (file)
@@ -26,6 +26,11 @@ LIST_HEAD(nfs_automount_list);
 static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
+static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+                                       const struct dentry *dentry,
+                                       struct nfs_fh *fh,
+                                       struct nfs_fattr *fattr);
+
 /*
  * nfs_path - reconstruct the path given an arbitrary dentry
  * @base - arbitrary string to prepend to the path
@@ -209,9 +214,10 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
  * @fattr - attributes for new root inode
  *
  */
-struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-               const struct dentry *dentry, struct nfs_fh *fh,
-               struct nfs_fattr *fattr)
+static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+                                       const struct dentry *dentry,
+                                       struct nfs_fh *fh,
+                                       struct nfs_fattr *fattr)
 {
        struct nfs_clone_mount mountdata = {
                .sb = mnt_parent->mnt_sb,
index f8688eaa0001f2f9b376ac916e6ad0683402b3f9..3b234d4601e71ac51f45e71e409526aa96fcf14d 100644 (file)
@@ -449,7 +449,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr
                struct nfs_fattr res;
        } *ptr;
 
-       ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
+       ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
        if (!ptr)
                return -ENOMEM;
        ptr->arg.fh = NFS_FH(dir->d_inode);
index 36e902a88ca1b92bd9e81cee86317fa18a427d63..829af323f28862f2218ab1d3f5163b5953f6b623 100644 (file)
@@ -392,7 +392,6 @@ int __init nfs_init_nfspagecache(void)
 
 void nfs_destroy_nfspagecache(void)
 {
-       if (kmem_cache_destroy(nfs_page_cachep))
-               printk(KERN_INFO "nfs_page: not all structures were freed\n");
+       kmem_cache_destroy(nfs_page_cachep);
 }
 
index 630e50647bbbf02c90611f4ba7d63da613ebaccc..4529cc4f3f8fe427bb6b262718213f933b7ac6a1 100644 (file)
@@ -352,7 +352,7 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *
 {
        struct nfs_diropargs    *arg;
 
-       arg = (struct nfs_diropargs *)kmalloc(sizeof(*arg), GFP_KERNEL);
+       arg = kmalloc(sizeof(*arg), GFP_KERNEL);
        if (!arg)
                return -ENOMEM;
        arg->fh = NFS_FH(dir->d_inode);
index 69f1549da2b94d0fd4b3579f985eb545a8e88ddb..c2e49c397a27186ac9ba09ebd49710bb091935e8 100644 (file)
@@ -737,6 +737,5 @@ int __init nfs_init_readpagecache(void)
 void nfs_destroy_readpagecache(void)
 {
        mempool_destroy(nfs_rdata_mempool);
-       if (kmem_cache_destroy(nfs_rdata_cachep))
-               printk(KERN_INFO "nfs_read_data: not all structures were freed\n");
+       kmem_cache_destroy(nfs_rdata_cachep);
 }
index c12effb46fe50df5ff959455de5fcb1f2c75533e..f6675d2c386c29127a9e6bad4223f47a1dbd3e12 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
-#include <linux/mpage.h>
 #include <linux/writeback.h>
 
 #include <linux/sunrpc/clnt.h>
@@ -1565,7 +1564,6 @@ void nfs_destroy_writepagecache(void)
 {
        mempool_destroy(nfs_commit_mempool);
        mempool_destroy(nfs_wdata_mempool);
-       if (kmem_cache_destroy(nfs_wdata_cachep))
-               printk(KERN_INFO "nfs_write_data: not all structures were freed\n");
+       kmem_cache_destroy(nfs_wdata_cachep);
 }
 
index bea6b94781145e7707c59dcaaaabf4cb98ea8a3f..b1902ebaab4158d03cbe1482426d89de80f76fd7 100644 (file)
@@ -573,10 +573,9 @@ idmap_lookup(struct svc_rqst *rqstp,
        struct idmap_defer_req *mdr;
        int ret;
 
-       mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
+       mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
        if (!mdr)
                return -ENOMEM;
-       memset(mdr, 0, sizeof(*mdr));
        atomic_set(&mdr->count, 1);
        init_waitqueue_head(&mdr->waitq);
        mdr->req.defer = idmap_defer;
index 9daa0b9feb8d027e438ef39c846daee95cf2d6cf..ebcf226a9e4a1fb65d04baa8e6ac10dc7f845071 100644 (file)
@@ -339,8 +339,7 @@ alloc_client(struct xdr_netobj name)
 {
        struct nfs4_client *clp;
 
-       if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
-               memset(clp, 0, sizeof(*clp));
+       if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
                if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
                        memcpy(clp->cl_name.data, name.data, name.len);
                        clp->cl_name.len = name.len;
@@ -1006,13 +1005,10 @@ alloc_init_file(struct inode *ino)
 static void
 nfsd4_free_slab(kmem_cache_t **slab)
 {
-       int status;
-
        if (*slab == NULL)
                return;
-       status = kmem_cache_destroy(*slab);
+       kmem_cache_destroy(*slab);
        *slab = NULL;
-       WARN_ON(status);
 }
 
 static void
diff --git a/fs/no-block.c b/fs/no-block.c
new file mode 100644 (file)
index 0000000..d269a93
--- /dev/null
@@ -0,0 +1,22 @@
+/* no-block.c: implementation of routines required for non-BLOCK configuration
+ *
+ * Copyright (C) 2006 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/kernel.h>
+#include <linux/fs.h>
+
+static int no_blkdev_open(struct inode * inode, struct file * filp)
+{
+       return -ENODEV;
+}
+
+const struct file_operations def_blk_fops = {
+       .open           = no_blkdev_open,
+};
index bc579bfdfbd8ff0c09c701a849b8b61c362b0fa0..7b2c8f4f6a6f7aba6e5012f37e5e8836d0e04f0f 100644 (file)
@@ -254,7 +254,7 @@ static int ntfs_read_block(struct page *page)
                bh->b_bdev = vol->sb->s_bdev;
                /* Is the block within the allowed limits? */
                if (iblock < lblock) {
-                       BOOL is_retry = FALSE;
+                       bool is_retry = false;
 
                        /* Convert iblock into corresponding vcn and offset. */
                        vcn = (VCN)iblock << blocksize_bits >>
@@ -292,7 +292,7 @@ lock_retry_remap:
                                goto handle_hole;
                        /* If first try and runlist unmapped, map and retry. */
                        if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
-                               is_retry = TRUE;
+                               is_retry = true;
                                /*
                                 * Attempt to map runlist, dropping lock for
                                 * the duration.
@@ -558,7 +558,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
        unsigned long flags;
        unsigned int blocksize, vcn_ofs;
        int err;
-       BOOL need_end_writeback;
+       bool need_end_writeback;
        unsigned char blocksize_bits;
 
        vi = page->mapping->host;
@@ -626,7 +626,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
        rl = NULL;
        err = 0;
        do {
-               BOOL is_retry = FALSE;
+               bool is_retry = false;
 
                if (unlikely(block >= dblock)) {
                        /*
@@ -768,7 +768,7 @@ lock_retry_remap:
                }
                /* If first try and runlist unmapped, map and retry. */
                if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
-                       is_retry = TRUE;
+                       is_retry = true;
                        /*
                         * Attempt to map runlist, dropping lock for
                         * the duration.
@@ -874,12 +874,12 @@ lock_retry_remap:
        set_page_writeback(page);       /* Keeps try_to_free_buffers() away. */
 
        /* Submit the prepared buffers for i/o. */
-       need_end_writeback = TRUE;
+       need_end_writeback = true;
        do {
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
                        submit_bh(WRITE, bh);
-                       need_end_writeback = FALSE;
+                       need_end_writeback = false;
                }
                bh = next;
        } while (bh != head);
@@ -932,7 +932,7 @@ static int ntfs_write_mst_block(struct page *page,
        runlist_element *rl;
        int i, nr_locked_nis, nr_recs, nr_bhs, max_bhs, bhs_per_rec, err, err2;
        unsigned bh_size, rec_size_bits;
-       BOOL sync, is_mft, page_is_dirty, rec_is_dirty;
+       bool sync, is_mft, page_is_dirty, rec_is_dirty;
        unsigned char bh_size_bits;
 
        ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
@@ -975,10 +975,10 @@ static int ntfs_write_mst_block(struct page *page,
 
        rl = NULL;
        err = err2 = nr_bhs = nr_recs = nr_locked_nis = 0;
-       page_is_dirty = rec_is_dirty = FALSE;
+       page_is_dirty = rec_is_dirty = false;
        rec_start_bh = NULL;
        do {
-               BOOL is_retry = FALSE;
+               bool is_retry = false;
 
                if (likely(block < rec_block)) {
                        if (unlikely(block >= dblock)) {
@@ -1009,10 +1009,10 @@ static int ntfs_write_mst_block(struct page *page,
                        }
                        if (!buffer_dirty(bh)) {
                                /* Clean records are not written out. */
-                               rec_is_dirty = FALSE;
+                               rec_is_dirty = false;
                                continue;
                        }
-                       rec_is_dirty = TRUE;
+                       rec_is_dirty = true;
                        rec_start_bh = bh;
                }
                /* Need to map the buffer if it is not mapped already. */
@@ -1053,7 +1053,7 @@ lock_retry_remap:
                                 */
                                if (!is_mft && !is_retry &&
                                                lcn == LCN_RL_NOT_MAPPED) {
-                                       is_retry = TRUE;
+                                       is_retry = true;
                                        /*
                                         * Attempt to map runlist, dropping
                                         * lock for the duration.
@@ -1063,7 +1063,7 @@ lock_retry_remap:
                                        if (likely(!err2))
                                                goto lock_retry_remap;
                                        if (err2 == -ENOMEM)
-                                               page_is_dirty = TRUE;
+                                               page_is_dirty = true;
                                        lcn = err2;
                                } else {
                                        err2 = -EIO;
@@ -1145,7 +1145,7 @@ lock_retry_remap:
                                 * means we need to redirty the page before
                                 * returning.
                                 */
-                               page_is_dirty = TRUE;
+                               page_is_dirty = true;
                                /*
                                 * Remove the buffers in this mft record from
                                 * the list of buffers to write.
index 325ce261a107d3773040d463038ade0b34032256..9393f4b1e298faa9d84d2f6dcb3b771a8be7d4b0 100644 (file)
@@ -80,7 +80,7 @@ static inline void ntfs_unmap_page(struct page *page)
  *
  * The unlocked and uptodate page is returned on success or an encoded error
  * on failure. Caller has to test for error using the IS_ERR() macro on the
- * return value. If that evaluates to TRUE, the negative error code can be
+ * return value. If that evaluates to 'true', the negative error code can be
  * obtained using PTR_ERR() on the return value of ntfs_map_page().
  */
 static inline struct page *ntfs_map_page(struct address_space *mapping,
index 6708e1d68a9ed818902a40dec5a59cd002a56173..9f08e851cfb69ed9373344b7865b42b747451d0f 100644 (file)
@@ -67,7 +67,7 @@
  * the attribute has zero allocated size, i.e. there simply is no runlist.
  *
  * WARNING: If @ctx is supplied, regardless of whether success or failure is
- *         returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
+ *         returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx
  *         is no longer valid, i.e. you need to either call
  *         ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
  *         In that case PTR_ERR(@ctx->mrec) will give you the error code for
@@ -90,7 +90,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
        runlist_element *rl;
        struct page *put_this_page = NULL;
        int err = 0;
-       BOOL ctx_is_temporary, ctx_needs_reset;
+       bool ctx_is_temporary, ctx_needs_reset;
        ntfs_attr_search_ctx old_ctx = { NULL, };
 
        ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
@@ -100,7 +100,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
        else
                base_ni = ni->ext.base_ntfs_ino;
        if (!ctx) {
-               ctx_is_temporary = ctx_needs_reset = TRUE;
+               ctx_is_temporary = ctx_needs_reset = true;
                m = map_mft_record(base_ni);
                if (IS_ERR(m))
                        return PTR_ERR(m);
@@ -115,7 +115,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
                BUG_ON(IS_ERR(ctx->mrec));
                a = ctx->attr;
                BUG_ON(!a->non_resident);
-               ctx_is_temporary = FALSE;
+               ctx_is_temporary = false;
                end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn);
                read_lock_irqsave(&ni->size_lock, flags);
                allocated_size_vcn = ni->allocated_size >>
@@ -136,7 +136,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
                                ni->name, ni->name_len) &&
                                sle64_to_cpu(a->data.non_resident.lowest_vcn)
                                <= vcn && end_vcn >= vcn))
-                       ctx_needs_reset = FALSE;
+                       ctx_needs_reset = false;
                else {
                        /* Save the old search context. */
                        old_ctx = *ctx;
@@ -158,7 +158,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
                         * needed attribute extent.
                         */
                        ntfs_attr_reinit_search_ctx(ctx);
-                       ctx_needs_reset = TRUE;
+                       ctx_needs_reset = true;
                }
        }
        if (ctx_needs_reset) {
@@ -336,16 +336,16 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
  *  LCN_EIO    Critical error (runlist/file is corrupt, i/o error, etc).
  *
  * Locking: - The runlist must be locked on entry and is left locked on return.
- *         - If @write_locked is FALSE, i.e. the runlist is locked for reading,
+ *         - If @write_locked is 'false', i.e. the runlist is locked for reading,
  *           the lock may be dropped inside the function so you cannot rely on
  *           the runlist still being the same when this function returns.
  */
 LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
-               const BOOL write_locked)
+               const bool write_locked)
 {
        LCN lcn;
        unsigned long flags;
-       BOOL is_retry = FALSE;
+       bool is_retry = false;
 
        ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",
                        ni->mft_no, (unsigned long long)vcn,
@@ -390,7 +390,7 @@ retry_remap:
                        down_read(&ni->runlist.lock);
                }
                if (likely(!err)) {
-                       is_retry = TRUE;
+                       is_retry = true;
                        goto retry_remap;
                }
                if (err == -ENOENT)
@@ -449,7 +449,7 @@ retry_remap:
  *     -EIO    - Critical error (runlist/file is corrupt, i/o error, etc).
  *
  * WARNING: If @ctx is supplied, regardless of whether success or failure is
- *         returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
+ *         returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx
  *         is no longer valid, i.e. you need to either call
  *         ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
  *         In that case PTR_ERR(@ctx->mrec) will give you the error code for
@@ -469,7 +469,7 @@ runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
        unsigned long flags;
        runlist_element *rl;
        int err = 0;
-       BOOL is_retry = FALSE;
+       bool is_retry = false;
 
        ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, with%s ctx.",
                        ni->mft_no, (unsigned long long)vcn, ctx ? "" : "out");
@@ -518,7 +518,7 @@ retry_remap:
                         */
                        err = ntfs_map_runlist_nolock(ni, vcn, ctx);
                        if (likely(!err)) {
-                               is_retry = TRUE;
+                               is_retry = true;
                                goto retry_remap;
                        }
                }
@@ -558,8 +558,8 @@ retry_remap:
  * On actual error, ntfs_attr_find() returns -EIO.  In this case @ctx->attr is
  * undefined and in particular do not rely on it not changing.
  *
- * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself.  If it
- * is FALSE, the search begins after @ctx->attr.
+ * If @ctx->is_first is 'true', the search begins with @ctx->attr itself.  If it
+ * is 'false', the search begins after @ctx->attr.
  *
  * If @ic is IGNORE_CASE, the @name comparisson is not case sensitive and
  * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
@@ -599,11 +599,11 @@ static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name,
 
        /*
         * Iterate over attributes in mft record starting at @ctx->attr, or the
-        * attribute following that, if @ctx->is_first is TRUE.
+        * attribute following that, if @ctx->is_first is 'true'.
         */
        if (ctx->is_first) {
                a = ctx->attr;
-               ctx->is_first = FALSE;
+               ctx->is_first = false;
        } else
                a = (ATTR_RECORD*)((u8*)ctx->attr +
                                le32_to_cpu(ctx->attr->length));
@@ -890,11 +890,11 @@ static int ntfs_external_attr_find(const ATTR_TYPE type,
                ctx->al_entry = (ATTR_LIST_ENTRY*)al_start;
        /*
         * Iterate over entries in attribute list starting at @ctx->al_entry,
-        * or the entry following that, if @ctx->is_first is TRUE.
+        * or the entry following that, if @ctx->is_first is 'true'.
         */
        if (ctx->is_first) {
                al_entry = ctx->al_entry;
-               ctx->is_first = FALSE;
+               ctx->is_first = false;
        } else
                al_entry = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry +
                                le16_to_cpu(ctx->al_entry->length));
@@ -1127,7 +1127,7 @@ not_found:
        ctx->mrec = ctx->base_mrec;
        ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
                        le16_to_cpu(ctx->mrec->attrs_offset));
-       ctx->is_first = TRUE;
+       ctx->is_first = true;
        ctx->ntfs_ino = base_ni;
        ctx->base_ntfs_ino = NULL;
        ctx->base_mrec = NULL;
@@ -1224,7 +1224,7 @@ static inline void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
                /* Sanity checks are performed elsewhere. */
                .attr = (ATTR_RECORD*)((u8*)mrec +
                                le16_to_cpu(mrec->attrs_offset)),
-               .is_first = TRUE,
+               .is_first = true,
                .ntfs_ino = ni,
        };
 }
@@ -1243,7 +1243,7 @@ void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
 {
        if (likely(!ctx->base_ntfs_ino)) {
                /* No attribute list. */
-               ctx->is_first = TRUE;
+               ctx->is_first = true;
                /* Sanity checks are performed elsewhere. */
                ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
                                le16_to_cpu(ctx->mrec->attrs_offset));
@@ -1585,7 +1585,7 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
                        return -ENOMEM;
                /* Start by allocating clusters to hold the attribute value. */
                rl = ntfs_cluster_alloc(vol, 0, new_size >>
-                               vol->cluster_size_bits, -1, DATA_ZONE, TRUE);
+                               vol->cluster_size_bits, -1, DATA_ZONE, true);
                if (IS_ERR(rl)) {
                        err = PTR_ERR(rl);
                        ntfs_debug("Failed to allocate cluster%s, error code "
@@ -1919,7 +1919,7 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size,
        unsigned long flags;
        int err, mp_size;
        u32 attr_len = 0; /* Silence stupid gcc warning. */
-       BOOL mp_rebuilt;
+       bool mp_rebuilt;
 
 #ifdef NTFS_DEBUG
        read_lock_irqsave(&ni->size_lock, flags);
@@ -2222,7 +2222,7 @@ first_alloc:
        rl2 = ntfs_cluster_alloc(vol, allocated_size >> vol->cluster_size_bits,
                        (new_alloc_size - allocated_size) >>
                        vol->cluster_size_bits, (rl && (rl->lcn >= 0)) ?
-                       rl->lcn + rl->length : -1, DATA_ZONE, TRUE);
+                       rl->lcn + rl->length : -1, DATA_ZONE, true);
        if (IS_ERR(rl2)) {
                err = PTR_ERR(rl2);
                if (start < 0 || start >= allocated_size)
@@ -2265,7 +2265,7 @@ first_alloc:
        BUG_ON(!rl2);
        BUG_ON(!rl2->length);
        BUG_ON(rl2->lcn < LCN_HOLE);
-       mp_rebuilt = FALSE;
+       mp_rebuilt = false;
        /* Get the size for the new mapping pairs array for this extent. */
        mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1);
        if (unlikely(mp_size <= 0)) {
@@ -2300,7 +2300,7 @@ first_alloc:
                err = -EOPNOTSUPP;
                goto undo_alloc;
        }
-       mp_rebuilt = TRUE;
+       mp_rebuilt = true;
        /* Generate the mapping pairs array directly into the attr record. */
        err = ntfs_mapping_pairs_build(vol, (u8*)a +
                        le16_to_cpu(a->data.non_resident.mapping_pairs_offset),
index 9074886b44ba194d1c6cffed6f8bb838f2263f97..3c8b74c99b808f3bed9d48104b2c770c13edd4ec 100644 (file)
  * Structure must be initialized to zero before the first call to one of the
  * attribute search functions. Initialize @mrec to point to the mft record to
  * search, and @attr to point to the first attribute within @mrec (not necessary
- * if calling the _first() functions), and set @is_first to TRUE (not necessary
+ * if calling the _first() functions), and set @is_first to 'true' (not necessary
  * if calling the _first() functions).
  *
- * If @is_first is TRUE, the search begins with @attr. If @is_first is FALSE,
+ * If @is_first is 'true', the search begins with @attr. If @is_first is 'false',
  * the search begins after @attr. This is so that, after the first call to one
  * of the search attribute functions, we can call the function again, without
  * any modification of the search context, to automagically get the next
@@ -52,7 +52,7 @@
 typedef struct {
        MFT_RECORD *mrec;
        ATTR_RECORD *attr;
-       BOOL is_first;
+       bool is_first;
        ntfs_inode *ntfs_ino;
        ATTR_LIST_ENTRY *al_entry;
        ntfs_inode *base_ntfs_ino;
@@ -65,7 +65,7 @@ extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn,
 extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
 
 extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
-               const BOOL write_locked);
+               const bool write_locked);
 
 extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni,
                const VCN vcn, ntfs_attr_search_ctx *ctx);
index 7a190cdc60e2f4d403d157e2b5c912f182e4bf46..0809cf876098965fcd33d472201491bb7796403c 100644 (file)
  * @start_bit:         first bit to set
  * @count:             number of bits to set
  * @value:             value to set the bits to (i.e. 0 or 1)
- * @is_rollback:       if TRUE this is a rollback operation
+ * @is_rollback:       if 'true' this is a rollback operation
  *
  * Set @count bits starting at bit @start_bit in the bitmap described by the
  * vfs inode @vi to @value, where @value is either 0 or 1.
  *
- * @is_rollback should always be FALSE, it is for internal use to rollback
+ * @is_rollback should always be 'false', it is for internal use to rollback
  * errors.  You probably want to use ntfs_bitmap_set_bits_in_run() instead.
  *
  * Return 0 on success and -errno on error.
  */
 int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
-               const s64 count, const u8 value, const BOOL is_rollback)
+               const s64 count, const u8 value, const bool is_rollback)
 {
        s64 cnt = count;
        pgoff_t index, end_index;
@@ -172,7 +172,7 @@ rollback:
                return PTR_ERR(page);
        if (count != cnt)
                pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
-                               value ? 0 : 1, TRUE);
+                               value ? 0 : 1, true);
        else
                pos = 0;
        if (!pos) {
index bb50d6bc9212f88d611b5bfdf42102f6a2f439cf..72c9ad8be70d0b1d80b5e03d41737e9db10f20a9 100644 (file)
@@ -30,7 +30,7 @@
 #include "types.h"
 
 extern int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
-               const s64 count, const u8 value, const BOOL is_rollback);
+               const s64 count, const u8 value, const bool is_rollback);
 
 /**
  * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
@@ -48,7 +48,7 @@ static inline int ntfs_bitmap_set_bits_in_run(struct inode *vi,
                const s64 start_bit, const s64 count, const u8 value)
 {
        return __ntfs_bitmap_set_bits_in_run(vi, start_bit, count, value,
-                       FALSE);
+                       false);
 }
 
 /**
index e027f36fcc2f8f5b01193a194abdf44a124906e3..aba83347e5fe4fb0da406f76e3597e496d8ad1cb 100644 (file)
@@ -26,7 +26,7 @@
 #include "types.h"
 #include "volume.h"
 
-static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
+static inline bool ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
        int i;
 
        /*
@@ -35,12 +35,12 @@ static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
         * now.
         */
        if (unlikely(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG))
-               return FALSE;
+               return false;
        i = le32_to_cpu(cr);
        if (likely(((i >= 0) && (i <= 0x02)) ||
                        ((i >= 0x10) && (i <= 0x13))))
-               return TRUE;
-       return FALSE;
+               return true;
+       return false;
 }
 
 extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
index 68a607ff9fd36d2f7e62b76546392029ff1111a7..d98daf59e0b64ac91bf3c950594ba6685e6ca737 100644 (file)
@@ -600,7 +600,7 @@ do_next_cb:
        rl = NULL;
        for (vcn = start_vcn, start_vcn += cb_clusters; vcn < start_vcn;
                        vcn++) {
-               BOOL is_retry = FALSE;
+               bool is_retry = false;
 
                if (!rl) {
 lock_retry_remap:
@@ -626,7 +626,7 @@ lock_retry_remap:
                                break;
                        if (is_retry || lcn != LCN_RL_NOT_MAPPED)
                                goto rl_err;
-                       is_retry = TRUE;
+                       is_retry = true;
                        /*
                         * Attempt to map runlist, dropping lock for the
                         * duration.
index d1e2c6f9f05eed155e257b0524da8cc2ff5e4566..85c36b8ca452e828493fac9a2170f474e1b7e552 100644 (file)
@@ -1149,8 +1149,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
         * Allocate a buffer to store the current name being processed
         * converted to format determined by current NLS.
         */
-       name = (u8*)kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1,
-                       GFP_NOFS);
+       name = kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1, GFP_NOFS);
        if (unlikely(!name)) {
                err = -ENOMEM;
                goto err_out;
@@ -1191,7 +1190,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
         * map the mft record without deadlocking.
         */
        rc = le32_to_cpu(ctx->attr->data.resident.value_length);
-       ir = (INDEX_ROOT*)kmalloc(rc, GFP_NOFS);
+       ir = kmalloc(rc, GFP_NOFS);
        if (unlikely(!ir)) {
                err = -ENOMEM;
                goto err_out;
index 2e42c2dcae12310d123c13642809219c5cb51126..ae2fe0016d2c7be63adf1029f878b798fa1af7b6 100644 (file)
@@ -509,7 +509,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
        u32 attr_rec_len = 0;
        unsigned blocksize, u;
        int err, mp_size;
-       BOOL rl_write_locked, was_hole, is_retry;
+       bool rl_write_locked, was_hole, is_retry;
        unsigned char blocksize_bits;
        struct {
                u8 runlist_merged:1;
@@ -543,13 +543,13 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
                                return -ENOMEM;
                }
        } while (++u < nr_pages);
-       rl_write_locked = FALSE;
+       rl_write_locked = false;
        rl = NULL;
        err = 0;
        vcn = lcn = -1;
        vcn_len = 0;
        lcn_block = -1;
-       was_hole = FALSE;
+       was_hole = false;
        cpos = pos >> vol->cluster_size_bits;
        end = pos + bytes;
        cend = (end + vol->cluster_size - 1) >> vol->cluster_size_bits;
@@ -760,7 +760,7 @@ map_buffer_cached:
                        }
                        continue;
                }
-               is_retry = FALSE;
+               is_retry = false;
                if (!rl) {
                        down_read(&ni->runlist.lock);
 retry_remap:
@@ -776,7 +776,7 @@ retry_remap:
                                 * Successful remap, setup the map cache and
                                 * use that to deal with the buffer.
                                 */
-                               was_hole = FALSE;
+                               was_hole = false;
                                vcn = bh_cpos;
                                vcn_len = rl[1].vcn - vcn;
                                lcn_block = lcn << (vol->cluster_size_bits -
@@ -792,7 +792,7 @@ retry_remap:
                                if (likely(vcn + vcn_len >= cend)) {
                                        if (rl_write_locked) {
                                                up_write(&ni->runlist.lock);
-                                               rl_write_locked = FALSE;
+                                               rl_write_locked = false;
                                        } else
                                                up_read(&ni->runlist.lock);
                                        rl = NULL;
@@ -818,13 +818,13 @@ retry_remap:
                                         */
                                        up_read(&ni->runlist.lock);
                                        down_write(&ni->runlist.lock);
-                                       rl_write_locked = TRUE;
+                                       rl_write_locked = true;
                                        goto retry_remap;
                                }
                                err = ntfs_map_runlist_nolock(ni, bh_cpos,
                                                NULL);
                                if (likely(!err)) {
-                                       is_retry = TRUE;
+                                       is_retry = true;
                                        goto retry_remap;
                                }
                                /*
@@ -903,7 +903,7 @@ rl_not_mapped_enoent:
                if (!rl_write_locked) {
                        up_read(&ni->runlist.lock);
                        down_write(&ni->runlist.lock);
-                       rl_write_locked = TRUE;
+                       rl_write_locked = true;
                        goto retry_remap;
                }
                /* Find the previous last allocated cluster. */
@@ -917,7 +917,7 @@ rl_not_mapped_enoent:
                        }
                }
                rl2 = ntfs_cluster_alloc(vol, bh_cpos, 1, lcn, DATA_ZONE,
-                               FALSE);
+                               false);
                if (IS_ERR(rl2)) {
                        err = PTR_ERR(rl2);
                        ntfs_debug("Failed to allocate cluster, error code %i.",
@@ -1093,7 +1093,7 @@ rl_not_mapped_enoent:
                status.mft_attr_mapped = 0;
                status.mp_rebuilt = 0;
                /* Setup the map cache and use that to deal with the buffer. */
-               was_hole = TRUE;
+               was_hole = true;
                vcn = bh_cpos;
                vcn_len = 1;
                lcn_block = lcn << (vol->cluster_size_bits - blocksize_bits);
@@ -1105,7 +1105,7 @@ rl_not_mapped_enoent:
                 */
                if (likely(vcn + vcn_len >= cend)) {
                        up_write(&ni->runlist.lock);
-                       rl_write_locked = FALSE;
+                       rl_write_locked = false;
                        rl = NULL;
                }
                goto map_buffer_cached;
@@ -1117,7 +1117,7 @@ rl_not_mapped_enoent:
        if (likely(!err)) {
                if (unlikely(rl_write_locked)) {
                        up_write(&ni->runlist.lock);
-                       rl_write_locked = FALSE;
+                       rl_write_locked = false;
                } else if (unlikely(rl))
                        up_read(&ni->runlist.lock);
                rl = NULL;
@@ -1528,19 +1528,19 @@ static inline int ntfs_commit_pages_after_non_resident_write(
        do {
                s64 bh_pos;
                struct page *page;
-               BOOL partial;
+               bool partial;
 
                page = pages[u];
                bh_pos = (s64)page->index << PAGE_CACHE_SHIFT;
                bh = head = page_buffers(page);
-               partial = FALSE;
+               partial = false;
                do {
                        s64 bh_end;
 
                        bh_end = bh_pos + blocksize;
                        if (bh_end <= pos || bh_pos >= end) {
                                if (!buffer_uptodate(bh))
-                                       partial = TRUE;
+                                       partial = true;
                        } else {
                                set_buffer_uptodate(bh);
                                mark_buffer_dirty(bh);
@@ -1997,7 +1997,7 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
                                 */
                                down_read(&ni->runlist.lock);
                                lcn = ntfs_attr_vcn_to_lcn_nolock(ni, pos >>
-                                               vol->cluster_size_bits, FALSE);
+                                               vol->cluster_size_bits, false);
                                up_read(&ni->runlist.lock);
                                if (unlikely(lcn < LCN_HOLE)) {
                                        status = -EIO;
@@ -2176,20 +2176,18 @@ out:
 /**
  * ntfs_file_aio_write -
  */
-static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf,
-               size_t count, loff_t pos)
+static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        struct inode *inode = mapping->host;
        ssize_t ret;
-       struct iovec local_iov = { .iov_base = (void __user *)buf,
-                                  .iov_len = count };
 
        BUG_ON(iocb->ki_pos != pos);
 
        mutex_lock(&inode->i_mutex);
-       ret = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
+       ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
        mutex_unlock(&inode->i_mutex);
        if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
                int err = sync_page_range(inode, mapping, pos, ret);
@@ -2298,13 +2296,11 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
 
 const struct file_operations ntfs_file_ops = {
        .llseek         = generic_file_llseek,   /* Seek inside file. */
-       .read           = generic_file_read,     /* Read from file. */
+       .read           = do_sync_read,          /* Read from file. */
        .aio_read       = generic_file_aio_read, /* Async read from file. */
-       .readv          = generic_file_readv,    /* Read from file. */
 #ifdef NTFS_RW
        .write          = ntfs_file_write,       /* Write to file. */
        .aio_write      = ntfs_file_aio_write,   /* Async write to file. */
-       .writev         = ntfs_file_writev,      /* Write to file. */
        /*.release      = ,*/                    /* Last file is closed.  See
                                                    fs/ext2/file.c::
                                                    ext2_release_file() for
index 9f5427c2d1057d1652a60b1a0e3e317d48415518..e32cde486362bb21976d271fb02892effbeb2460 100644 (file)
@@ -204,7 +204,7 @@ int ntfs_index_lookup(const void *key, const int key_len,
                if ((key_len == le16_to_cpu(ie->key_length)) && !memcmp(key,
                                &ie->key, key_len)) {
 ir_done:
-                       ictx->is_in_root = TRUE;
+                       ictx->is_in_root = true;
                        ictx->ir = ir;
                        ictx->actx = actx;
                        ictx->base_ni = base_ni;
@@ -374,7 +374,7 @@ fast_descend_into_child_node:
                if ((key_len == le16_to_cpu(ie->key_length)) && !memcmp(key,
                                &ie->key, key_len)) {
 ia_done:
-                       ictx->is_in_root = FALSE;
+                       ictx->is_in_root = false;
                        ictx->actx = NULL;
                        ictx->base_ni = NULL;
                        ictx->ia = ia;
index 846a489e8692b23a93fcfcb47402f735a32b1857..8745469c3989d626b2ccf7aeddff01d5036ce8f2 100644 (file)
  * @entry:     index entry (points into @ir or @ia)
  * @data:      index entry data (points into @entry)
  * @data_len:  length in bytes of @data
- * @is_in_root:        TRUE if @entry is in @ir and FALSE if it is in @ia
+ * @is_in_root:        'true' if @entry is in @ir and 'false' if it is in @ia
  * @ir:                index root if @is_in_root and NULL otherwise
  * @actx:      attribute search context if @is_in_root and NULL otherwise
  * @base_ni:   base inode if @is_in_root and NULL otherwise
- * @ia:                index block if @is_in_root is FALSE and NULL otherwise
- * @page:      page if @is_in_root is FALSE and NULL otherwise
+ * @ia:                index block if @is_in_root is 'false' and NULL otherwise
+ * @page:      page if @is_in_root is 'false' and NULL otherwise
  *
  * @idx_ni is the index inode this context belongs to.
  *
  * are the index entry data and its length in bytes, respectively.  @data
  * simply points into @entry.  This is probably what the user is interested in.
  *
- * If @is_in_root is TRUE, @entry is in the index root attribute @ir described
+ * If @is_in_root is 'true', @entry is in the index root attribute @ir described
  * by the attribute search context @actx and the base inode @base_ni.  @ia and
  * @page are NULL in this case.
  *
- * If @is_in_root is FALSE, @entry is in the index allocation attribute and @ia
+ * If @is_in_root is 'false', @entry is in the index allocation attribute and @ia
  * and @page point to the index allocation block and the mapped, locked page it
  * is in, respectively.  @ir, @actx and @base_ni are NULL in this case.
  *
@@ -77,7 +77,7 @@ typedef struct {
        INDEX_ENTRY *entry;
        void *data;
        u16 data_len;
-       BOOL is_in_root;
+       bool is_in_root;
        INDEX_ROOT *ir;
        ntfs_attr_search_ctx *actx;
        ntfs_inode *base_ni;
index d313f356e66a9b8925ae75161cf182da08e79133..2d3de9c89818033a0c96f1a9f43afeb84132a285 100644 (file)
@@ -137,7 +137,7 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
 
                BUG_ON(!na->name);
                i = na->name_len * sizeof(ntfschar);
-               ni->name = (ntfschar*)kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
+               ni->name = kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
                if (!ni->name)
                        return -ENOMEM;
                memcpy(ni->name, na->name, i);
@@ -556,8 +556,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
 
        /* Setup the generic vfs inode parts now. */
 
-       /* This is the optimal IO size (for stat), not the fs block size. */
-       vi->i_blksize = PAGE_CACHE_SIZE;
        /*
         * This is for checking whether an inode has changed w.r.t. a file so
         * that the file can be updated if necessary (compare with f_version).
@@ -1234,7 +1232,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
        base_ni = NTFS_I(base_vi);
 
        /* Just mirror the values from the base inode. */
-       vi->i_blksize   = base_vi->i_blksize;
        vi->i_version   = base_vi->i_version;
        vi->i_uid       = base_vi->i_uid;
        vi->i_gid       = base_vi->i_gid;
@@ -1504,7 +1501,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
        ni      = NTFS_I(vi);
        base_ni = NTFS_I(base_vi);
        /* Just mirror the values from the base inode. */
-       vi->i_blksize   = base_vi->i_blksize;
        vi->i_version   = base_vi->i_version;
        vi->i_uid       = base_vi->i_uid;
        vi->i_gid       = base_vi->i_gid;
@@ -2305,7 +2301,7 @@ void ntfs_clear_big_inode(struct inode *vi)
        }
 #ifdef NTFS_RW
        if (NInoDirty(ni)) {
-               BOOL was_bad = (is_bad_inode(vi));
+               bool was_bad = (is_bad_inode(vi));
 
                /* Committing the inode also commits all extent inodes. */
                ntfs_commit_inode(vi);
@@ -3019,7 +3015,7 @@ int ntfs_write_inode(struct inode *vi, int sync)
        MFT_RECORD *m;
        STANDARD_INFORMATION *si;
        int err = 0;
-       BOOL modified = FALSE;
+       bool modified = false;
 
        ntfs_debug("Entering for %sinode 0x%lx.", NInoAttr(ni) ? "attr " : "",
                        vi->i_ino);
@@ -3061,7 +3057,7 @@ int ntfs_write_inode(struct inode *vi, int sync)
                                sle64_to_cpu(si->last_data_change_time),
                                (long long)sle64_to_cpu(nt));
                si->last_data_change_time = nt;
-               modified = TRUE;
+               modified = true;
        }
        nt = utc2ntfs(vi->i_ctime);
        if (si->last_mft_change_time != nt) {
@@ -3070,7 +3066,7 @@ int ntfs_write_inode(struct inode *vi, int sync)
                                sle64_to_cpu(si->last_mft_change_time),
                                (long long)sle64_to_cpu(nt));
                si->last_mft_change_time = nt;
-               modified = TRUE;
+               modified = true;
        }
        nt = utc2ntfs(vi->i_atime);
        if (si->last_access_time != nt) {
@@ -3079,7 +3075,7 @@ int ntfs_write_inode(struct inode *vi, int sync)
                                (long long)sle64_to_cpu(si->last_access_time),
                                (long long)sle64_to_cpu(nt));
                si->last_access_time = nt;
-               modified = TRUE;
+               modified = true;
        }
        /*
         * If we just modified the standard information attribute we need to
index d34b93cb8b48adc878fdddf1bc86892b42b274e7..1e383328eceb769c778b2694dbed5a86f200e150 100644 (file)
@@ -142,13 +142,13 @@ typedef le32 NTFS_RECORD_TYPE;
  * operator! (-8
  */
 
-static inline BOOL __ntfs_is_magic(le32 x, NTFS_RECORD_TYPE r)
+static inline bool __ntfs_is_magic(le32 x, NTFS_RECORD_TYPE r)
 {
        return (x == r);
 }
 #define ntfs_is_magic(x, m)    __ntfs_is_magic(x, magic_##m)
 
-static inline BOOL __ntfs_is_magicp(le32 *p, NTFS_RECORD_TYPE r)
+static inline bool __ntfs_is_magicp(le32 *p, NTFS_RECORD_TYPE r)
 {
        return (*p == r);
 }
@@ -323,7 +323,7 @@ typedef le64 leMFT_REF;
 #define MREF_LE(x)     ((unsigned long)(le64_to_cpu(x) & MFT_REF_MASK_CPU))
 #define MSEQNO_LE(x)   ((u16)((le64_to_cpu(x) >> 48) & 0xffff))
 
-#define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0)
+#define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? true : false)
 #define ERR_MREF(x)    ((u64)((s64)(x)))
 #define MREF_ERR(x)    ((int)((s64)(x)))
 
index 29cabf93d2d24ed66ffd0aff3a5478163e93f210..1711b710b641f40a0c8c5690a94c9681f2b5fa92 100644 (file)
@@ -76,7 +76,7 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
  * @count:     number of clusters to allocate
  * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
  * @zone:      zone from which to allocate the clusters
- * @is_extension:      if TRUE, this is an attribute extension
+ * @is_extension:      if 'true', this is an attribute extension
  *
  * Allocate @count clusters preferably starting at cluster @start_lcn or at the
  * current allocator position if @start_lcn is -1, on the mounted ntfs volume
@@ -87,11 +87,11 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
  * @start_vcn specifies the vcn of the first allocated cluster.  This makes
  * merging the resulting runlist with the old runlist easier.
  *
- * If @is_extension is TRUE, the caller is allocating clusters to extend an
- * attribute and if it is FALSE, the caller is allocating clusters to fill a
+ * If @is_extension is 'true', the caller is allocating clusters to extend an
+ * attribute and if it is 'false', the caller is allocating clusters to fill a
  * hole in an attribute.  Practically the difference is that if @is_extension
- * is TRUE the returned runlist will be terminated with LCN_ENOENT and if
- * @is_extension is FALSE the runlist will be terminated with
+ * is 'true' the returned runlist will be terminated with LCN_ENOENT and if
+ * @is_extension is 'false' the runlist will be terminated with
  * LCN_RL_NOT_MAPPED.
  *
  * You need to check the return value with IS_ERR().  If this is false, the
@@ -146,7 +146,7 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
 runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
                const s64 count, const LCN start_lcn,
                const NTFS_CLUSTER_ALLOCATION_ZONES zone,
-               const BOOL is_extension)
+               const bool is_extension)
 {
        LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
        LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
@@ -818,7 +818,7 @@ out:
  * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
  * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
  *
- * @is_rollback should always be FALSE, it is for internal use to rollback
+ * @is_rollback should always be 'false', it is for internal use to rollback
  * errors.  You probably want to use ntfs_cluster_free() instead.
  *
  * Note, __ntfs_cluster_free() does not modify the runlist, so you have to
@@ -828,7 +828,7 @@ out:
  * success and -errno on error.
  *
  * WARNING: If @ctx is supplied, regardless of whether success or failure is
- *         returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
+ *         returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx
  *         is no longer valid, i.e. you need to either call
  *         ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
  *         In that case PTR_ERR(@ctx->mrec) will give you the error code for
@@ -847,7 +847,7 @@ out:
  *           and it will be left mapped on return.
  */
 s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
-               ntfs_attr_search_ctx *ctx, const BOOL is_rollback)
+               ntfs_attr_search_ctx *ctx, const bool is_rollback)
 {
        s64 delta, to_free, total_freed, real_freed;
        ntfs_volume *vol;
@@ -999,7 +999,7 @@ err_out:
         * If rollback fails, set the volume errors flag, emit an error
         * message, and return the error code.
         */
-       delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, TRUE);
+       delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, true);
        if (delta < 0) {
                ntfs_error(vol->sb, "Failed to rollback (error %i).  Leaving "
                                "inconsistent metadata!  Unmount and run "
index 72cbca7003b2de3ee54ffe4a358efac9e767f090..2adb04316941017109ba85b893d504d06b230be0 100644 (file)
@@ -43,10 +43,10 @@ typedef enum {
 extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
                const VCN start_vcn, const s64 count, const LCN start_lcn,
                const NTFS_CLUSTER_ALLOCATION_ZONES zone,
-               const BOOL is_extension);
+               const bool is_extension);
 
 extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
-               s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback);
+               s64 count, ntfs_attr_search_ctx *ctx, const bool is_rollback);
 
 /**
  * ntfs_cluster_free - free clusters on an ntfs volume
@@ -86,7 +86,7 @@ extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
  * success and -errno on error.
  *
  * WARNING: If @ctx is supplied, regardless of whether success or failure is
- *         returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
+ *         returned, you need to check IS_ERR(@ctx->mrec) and if 'true' the @ctx
  *         is no longer valid, i.e. you need to either call
  *         ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
  *         In that case PTR_ERR(@ctx->mrec) will give you the error code for
@@ -107,7 +107,7 @@ extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
 static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
                s64 count, ntfs_attr_search_ctx *ctx)
 {
-       return __ntfs_cluster_free(ni, start_vcn, count, ctx, FALSE);
+       return __ntfs_cluster_free(ni, start_vcn, count, ctx, false);
 }
 
 extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
index 4af2ad1193ec374288f0f803ce7bf3b05ee9da62..acfed325f4ec17481099f505dc3dcb2a37751dd6 100644 (file)
  * @rp:                restart page header to check
  * @pos:       position in @vi at which the restart page header resides
  *
- * Check the restart page header @rp for consistency and return TRUE if it is
- * consistent and FALSE otherwise.
+ * Check the restart page header @rp for consistency and return 'true' if it is
+ * consistent and 'false' otherwise.
  *
  * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
  * require the full restart page.
  */
-static BOOL ntfs_check_restart_page_header(struct inode *vi,
+static bool ntfs_check_restart_page_header(struct inode *vi,
                RESTART_PAGE_HEADER *rp, s64 pos)
 {
        u32 logfile_system_page_size, logfile_log_page_size;
        u16 ra_ofs, usa_count, usa_ofs, usa_end = 0;
-       BOOL have_usa = TRUE;
+       bool have_usa = true;
 
        ntfs_debug("Entering.");
        /*
@@ -67,7 +67,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
                        (logfile_system_page_size - 1) ||
                        logfile_log_page_size & (logfile_log_page_size - 1)) {
                ntfs_error(vi->i_sb, "$LogFile uses unsupported page size.");
-               return FALSE;
+               return false;
        }
        /*
         * We must be either at !pos (1st restart page) or at pos = system page
@@ -76,7 +76,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
        if (pos && pos != logfile_system_page_size) {
                ntfs_error(vi->i_sb, "Found restart area in incorrect "
                                "position in $LogFile.");
-               return FALSE;
+               return false;
        }
        /* We only know how to handle version 1.1. */
        if (sle16_to_cpu(rp->major_ver) != 1 ||
@@ -85,14 +85,14 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
                                "supported.  (This driver supports version "
                                "1.1 only.)", (int)sle16_to_cpu(rp->major_ver),
                                (int)sle16_to_cpu(rp->minor_ver));
-               return FALSE;
+               return false;
        }
        /*
         * If chkdsk has been run the restart page may not be protected by an
         * update sequence array.
         */
        if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) {
-               have_usa = FALSE;
+               have_usa = false;
                goto skip_usa_checks;
        }
        /* Verify the size of the update sequence array. */
@@ -100,7 +100,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
        if (usa_count != le16_to_cpu(rp->usa_count)) {
                ntfs_error(vi->i_sb, "$LogFile restart page specifies "
                                "inconsistent update sequence array count.");
-               return FALSE;
+               return false;
        }
        /* Verify the position of the update sequence array. */
        usa_ofs = le16_to_cpu(rp->usa_ofs);
@@ -109,7 +109,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
                        usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) {
                ntfs_error(vi->i_sb, "$LogFile restart page specifies "
                                "inconsistent update sequence array offset.");
-               return FALSE;
+               return false;
        }
 skip_usa_checks:
        /*
@@ -124,7 +124,7 @@ skip_usa_checks:
                        ra_ofs > logfile_system_page_size) {
                ntfs_error(vi->i_sb, "$LogFile restart page specifies "
                                "inconsistent restart area offset.");
-               return FALSE;
+               return false;
        }
        /*
         * Only restart pages modified by chkdsk are allowed to have chkdsk_lsn
@@ -133,10 +133,10 @@ skip_usa_checks:
        if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) {
                ntfs_error(vi->i_sb, "$LogFile restart page is not modified "
                                "by chkdsk but a chkdsk LSN is specified.");
-               return FALSE;
+               return false;
        }
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 /**
@@ -145,7 +145,7 @@ skip_usa_checks:
  * @rp:                restart page whose restart area to check
  *
  * Check the restart area of the restart page @rp for consistency and return
- * TRUE if it is consistent and FALSE otherwise.
+ * 'true' if it is consistent and 'false' otherwise.
  *
  * This function assumes that the restart page header has already been
  * consistency checked.
@@ -153,7 +153,7 @@ skip_usa_checks:
  * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
  * require the full restart page.
  */
-static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
+static bool ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
 {
        u64 file_size;
        RESTART_AREA *ra;
@@ -172,7 +172,7 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
                        NTFS_BLOCK_SIZE - sizeof(u16)) {
                ntfs_error(vi->i_sb, "$LogFile restart area specifies "
                                "inconsistent file offset.");
-               return FALSE;
+               return false;
        }
        /*
         * Now that we can access ra->client_array_offset, make sure everything
@@ -186,7 +186,7 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
                        ra_ofs + ca_ofs > NTFS_BLOCK_SIZE - sizeof(u16)) {
                ntfs_error(vi->i_sb, "$LogFile restart area specifies "
                                "inconsistent client array offset.");
-               return FALSE;
+               return false;
        }
        /*
         * The restart area must end within the system page size both when
@@ -203,7 +203,7 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
                                "of the system page size specified by the "
                                "restart page header and/or the specified "
                                "restart area length is inconsistent.");
-               return FALSE;
+               return false;
        }
        /*
         * The ra->client_free_list and ra->client_in_use_list must be either
@@ -218,7 +218,7 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
                        le16_to_cpu(ra->log_clients))) {
                ntfs_error(vi->i_sb, "$LogFile restart area specifies "
                                "overflowing client free and/or in use lists.");
-               return FALSE;
+               return false;
        }
        /*
         * Check ra->seq_number_bits against ra->file_size for consistency.
@@ -233,24 +233,24 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
        if (le32_to_cpu(ra->seq_number_bits) != 67 - fs_bits) {
                ntfs_error(vi->i_sb, "$LogFile restart area specifies "
                                "inconsistent sequence number bits.");
-               return FALSE;
+               return false;
        }
        /* The log record header length must be a multiple of 8. */
        if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) !=
                        le16_to_cpu(ra->log_record_header_length)) {
                ntfs_error(vi->i_sb, "$LogFile restart area specifies "
                                "inconsistent log record header length.");
-               return FALSE;
+               return false;
        }
        /* Dito for the log page data offset. */
        if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) !=
                        le16_to_cpu(ra->log_page_data_offset)) {
                ntfs_error(vi->i_sb, "$LogFile restart area specifies "
                                "inconsistent log page data offset.");
-               return FALSE;
+               return false;
        }
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 /**
@@ -259,7 +259,7 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
  * @rp:                restart page whose log client array to check
  *
  * Check the log client array of the restart page @rp for consistency and
- * return TRUE if it is consistent and FALSE otherwise.
+ * return 'true' if it is consistent and 'false' otherwise.
  *
  * This function assumes that the restart page header and the restart area have
  * already been consistency checked.
@@ -268,13 +268,13 @@ static BOOL ntfs_check_restart_area(struct inode *vi, RESTART_PAGE_HEADER *rp)
  * function needs @rp->system_page_size bytes in @rp, i.e. it requires the full
  * restart page and the page must be multi sector transfer deprotected.
  */
-static BOOL ntfs_check_log_client_array(struct inode *vi,
+static bool ntfs_check_log_client_array(struct inode *vi,
                RESTART_PAGE_HEADER *rp)
 {
        RESTART_AREA *ra;
        LOG_CLIENT_RECORD *ca, *cr;
        u16 nr_clients, idx;
-       BOOL in_free_list, idx_is_first;
+       bool in_free_list, idx_is_first;
 
        ntfs_debug("Entering.");
        ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
@@ -290,9 +290,9 @@ static BOOL ntfs_check_log_client_array(struct inode *vi,
         */
        nr_clients = le16_to_cpu(ra->log_clients);
        idx = le16_to_cpu(ra->client_free_list);
-       in_free_list = TRUE;
+       in_free_list = true;
 check_list:
-       for (idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
+       for (idx_is_first = true; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
                        idx = le16_to_cpu(cr->next_client)) {
                if (!nr_clients || idx >= le16_to_cpu(ra->log_clients))
                        goto err_out;
@@ -302,20 +302,20 @@ check_list:
                if (idx_is_first) {
                        if (cr->prev_client != LOGFILE_NO_CLIENT)
                                goto err_out;
-                       idx_is_first = FALSE;
+                       idx_is_first = false;
                }
        }
        /* Switch to and check the in use list if we just did the free list. */
        if (in_free_list) {
-               in_free_list = FALSE;
+               in_free_list = false;
                idx = le16_to_cpu(ra->client_in_use_list);
                goto check_list;
        }
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 err_out:
        ntfs_error(vi->i_sb, "$LogFile log client array is corrupt.");
-       return FALSE;
+       return false;
 }
 
 /**
@@ -468,8 +468,8 @@ err_out:
  * @log_vi:    struct inode of loaded journal $LogFile to check
  * @rp:                [OUT] on success this is a copy of the current restart page
  *
- * Check the $LogFile journal for consistency and return TRUE if it is
- * consistent and FALSE if not.  On success, the current restart page is
+ * Check the $LogFile journal for consistency and return 'true' if it is
+ * consistent and 'false' if not.  On success, the current restart page is
  * returned in *@rp.  Caller must call ntfs_free(*@rp) when finished with it.
  *
  * At present we only check the two restart pages and ignore the log record
@@ -480,7 +480,7 @@ err_out:
  * if the $LogFile was created on a system with a different page size to ours
  * yet and mst deprotection would fail if our page size is smaller.
  */
-BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
+bool ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
 {
        s64 size, pos;
        LSN rstr1_lsn, rstr2_lsn;
@@ -491,7 +491,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
        RESTART_PAGE_HEADER *rstr1_ph = NULL;
        RESTART_PAGE_HEADER *rstr2_ph = NULL;
        int log_page_size, log_page_mask, err;
-       BOOL logfile_is_empty = TRUE;
+       bool logfile_is_empty = true;
        u8 log_page_bits;
 
        ntfs_debug("Entering.");
@@ -527,7 +527,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
        if (size < log_page_size * 2 || (size - log_page_size * 2) >>
                        log_page_bits < MinLogRecordPages) {
                ntfs_error(vol->sb, "$LogFile is too small.");
-               return FALSE;
+               return false;
        }
        /*
         * Read through the file looking for a restart page.  Since the restart
@@ -556,7 +556,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
                 * means we are done.
                 */
                if (!ntfs_is_empty_recordp((le32*)kaddr))
-                       logfile_is_empty = FALSE;
+                       logfile_is_empty = false;
                else if (!logfile_is_empty)
                        break;
                /*
@@ -615,13 +615,13 @@ BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
                NVolSetLogFileEmpty(vol);
 is_empty:
                ntfs_debug("Done.  ($LogFile is empty.)");
-               return TRUE;
+               return true;
        }
        if (!rstr1_ph) {
                BUG_ON(rstr2_ph);
                ntfs_error(vol->sb, "Did not find any restart pages in "
                                "$LogFile and it was not empty.");
-               return FALSE;
+               return false;
        }
        /* If both restart pages were found, use the more recent one. */
        if (rstr2_ph) {
@@ -648,11 +648,11 @@ is_empty:
        else
                ntfs_free(rstr1_ph);
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 err_out:
        if (rstr1_ph)
                ntfs_free(rstr1_ph);
-       return FALSE;
+       return false;
 }
 
 /**
@@ -660,8 +660,8 @@ err_out:
  * @log_vi:    struct inode of loaded journal $LogFile to check
  * @rp:                copy of the current restart page
  *
- * Analyze the $LogFile journal and return TRUE if it indicates the volume was
- * shutdown cleanly and FALSE if not.
+ * Analyze the $LogFile journal and return 'true' if it indicates the volume was
+ * shutdown cleanly and 'false' if not.
  *
  * At present we only look at the two restart pages and ignore the log record
  * pages.  This is a little bit crude in that there will be a very small number
@@ -675,7 +675,7 @@ err_out:
  * is empty this function requires that NVolLogFileEmpty() is true otherwise an
  * empty volume will be reported as dirty.
  */
-BOOL ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp)
+bool ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp)
 {
        ntfs_volume *vol = NTFS_SB(log_vi->i_sb);
        RESTART_AREA *ra;
@@ -684,7 +684,7 @@ BOOL ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp)
        /* An empty $LogFile must have been clean before it got emptied. */
        if (NVolLogFileEmpty(vol)) {
                ntfs_debug("Done.  ($LogFile is empty.)");
-               return TRUE;
+               return true;
        }
        BUG_ON(!rp);
        if (!ntfs_is_rstr_record(rp->magic) &&
@@ -693,7 +693,7 @@ BOOL ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp)
                                "probably a bug in that the $LogFile should "
                                "have been consistency checked before calling "
                                "this function.");
-               return FALSE;
+               return false;
        }
        ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
        /*
@@ -704,25 +704,25 @@ BOOL ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp)
        if (ra->client_in_use_list != LOGFILE_NO_CLIENT &&
                        !(ra->flags & RESTART_VOLUME_IS_CLEAN)) {
                ntfs_debug("Done.  $LogFile indicates a dirty shutdown.");
-               return FALSE;
+               return false;
        }
        /* $LogFile indicates a clean shutdown. */
        ntfs_debug("Done.  $LogFile indicates a clean shutdown.");
-       return TRUE;
+       return true;
 }
 
 /**
  * ntfs_empty_logfile - empty the contents of the $LogFile journal
  * @log_vi:    struct inode of loaded journal $LogFile to empty
  *
- * Empty the contents of the $LogFile journal @log_vi and return TRUE on
- * success and FALSE on error.
+ * Empty the contents of the $LogFile journal @log_vi and return 'true' on
+ * success and 'false' on error.
  *
  * This function assumes that the $LogFile journal has already been consistency
  * checked by a call to ntfs_check_logfile() and that ntfs_is_logfile_clean()
  * has been used to ensure that the $LogFile is clean.
  */
-BOOL ntfs_empty_logfile(struct inode *log_vi)
+bool ntfs_empty_logfile(struct inode *log_vi)
 {
        ntfs_volume *vol = NTFS_SB(log_vi->i_sb);
 
@@ -735,13 +735,13 @@ BOOL ntfs_empty_logfile(struct inode *log_vi)
                if (unlikely(err)) {
                        ntfs_error(vol->sb, "Failed to fill $LogFile with "
                                        "0xff bytes (error code %i).", err);
-                       return FALSE;
+                       return false;
                }
                /* Set the flag so we do not have to do it again on remount. */
                NVolSetLogFileEmpty(vol);
        }
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 #endif /* NTFS_RW */
index a51f3dd0e9eb56c106f3935b14c4d2d7ed76cbc7..9468e1c45ae305dae0a5a626d38de952da914d7b 100644 (file)
@@ -296,13 +296,13 @@ typedef struct {
 /* sizeof() = 160 (0xa0) bytes */
 } __attribute__ ((__packed__)) LOG_CLIENT_RECORD;
 
-extern BOOL ntfs_check_logfile(struct inode *log_vi,
+extern bool ntfs_check_logfile(struct inode *log_vi,
                RESTART_PAGE_HEADER **rp);
 
-extern BOOL ntfs_is_logfile_clean(struct inode *log_vi,
+extern bool ntfs_is_logfile_clean(struct inode *log_vi,
                const RESTART_PAGE_HEADER *rp);
 
-extern BOOL ntfs_empty_logfile(struct inode *log_vi);
+extern bool ntfs_empty_logfile(struct inode *log_vi);
 
 #endif /* NTFS_RW */
 
index 2438c00ec0cee309a7f52f23a584fbb2e1769bf1..2ad5c8b104b934c9177e162d2c20c6da211ed0d9 100644 (file)
@@ -251,7 +251,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
        int i;
        unsigned long mft_no = MREF(mref);
        u16 seq_no = MSEQNO(mref);
-       BOOL destroy_ni = FALSE;
+       bool destroy_ni = false;
 
        ntfs_debug("Mapping extent mft record 0x%lx (base mft record 0x%lx).",
                        mft_no, base_ni->mft_no);
@@ -322,7 +322,7 @@ map_err_out:
        if (seq_no && (le16_to_cpu(m->sequence_number) != seq_no)) {
                ntfs_error(base_ni->vol->sb, "Found stale extent mft "
                                "reference! Corrupt filesystem. Run chkdsk.");
-               destroy_ni = TRUE;
+               destroy_ni = true;
                m = ERR_PTR(-EIO);
                goto unm_err_out;
        }
@@ -331,11 +331,11 @@ map_err_out:
                ntfs_inode **tmp;
                int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
 
-               tmp = (ntfs_inode **)kmalloc(new_size, GFP_NOFS);
+               tmp = kmalloc(new_size, GFP_NOFS);
                if (unlikely(!tmp)) {
                        ntfs_error(base_ni->vol->sb, "Failed to allocate "
                                        "internal buffer.");
-                       destroy_ni = TRUE;
+                       destroy_ni = true;
                        m = ERR_PTR(-ENOMEM);
                        goto unm_err_out;
                }
@@ -857,7 +857,7 @@ err_out:
  * caller is responsible for unlocking the ntfs inode and unpinning the base
  * vfs inode.
  *
- * Return TRUE if the mft record may be written out and FALSE if not.
+ * Return 'true' if the mft record may be written out and 'false' if not.
  *
  * The caller has locked the page and cleared the uptodate flag on it which
  * means that we can safely write out any dirty mft records that do not have
@@ -868,7 +868,7 @@ err_out:
  * Here is a description of the tests we perform:
  *
  * If the inode is found in icache we know the mft record must be a base mft
- * record.  If it is dirty, we do not write it and return FALSE as the vfs
+ * record.  If it is dirty, we do not write it and return 'false' as the vfs
  * inode write paths will result in the access times being updated which would
  * cause the base mft record to be redirtied and written out again.  (We know
  * the access time update will modify the base mft record because Windows
@@ -877,11 +877,11 @@ err_out:
  *
  * If the inode is in icache and not dirty, we attempt to lock the mft record
  * and if we find the lock was already taken, it is not safe to write the mft
- * record and we return FALSE.
+ * record and we return 'false'.
  *
  * If we manage to obtain the lock we have exclusive access to the mft record,
  * which also allows us safe writeout of the mft record.  We then set
- * @locked_ni to the locked ntfs inode and return TRUE.
+ * @locked_ni to the locked ntfs inode and return 'true'.
  *
  * Note we cannot just lock the mft record and sleep while waiting for the lock
  * because this would deadlock due to lock reversal (normally the mft record is
@@ -891,24 +891,24 @@ err_out:
  * If the inode is not in icache we need to perform further checks.
  *
  * If the mft record is not a FILE record or it is a base mft record, we can
- * safely write it and return TRUE.
+ * safely write it and return 'true'.
  *
  * We now know the mft record is an extent mft record.  We check if the inode
  * corresponding to its base mft record is in icache and obtain a reference to
- * it if it is.  If it is not, we can safely write it and return TRUE.
+ * it if it is.  If it is not, we can safely write it and return 'true'.
  *
  * We now have the base inode for the extent mft record.  We check if it has an
  * ntfs inode for the extent mft record attached and if not it is safe to write
- * the extent mft record and we return TRUE.
+ * the extent mft record and we return 'true'.
  *
  * The ntfs inode for the extent mft record is attached to the base inode so we
  * attempt to lock the extent mft record and if we find the lock was already
- * taken, it is not safe to write the extent mft record and we return FALSE.
+ * taken, it is not safe to write the extent mft record and we return 'false'.
  *
  * If we manage to obtain the lock we have exclusive access to the extent mft
  * record, which also allows us safe writeout of the extent mft record.  We
  * set the ntfs inode of the extent mft record clean and then set @locked_ni to
- * the now locked ntfs inode and return TRUE.
+ * the now locked ntfs inode and return 'true'.
  *
  * Note, the reason for actually writing dirty mft records here and not just
  * relying on the vfs inode dirty code paths is that we can have mft records
@@ -922,7 +922,7 @@ err_out:
  * appear if the mft record is reused for a new inode before it got written
  * out.
  */
-BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
+bool ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                const MFT_RECORD *m, ntfs_inode **locked_ni)
 {
        struct super_block *sb = vol->sb;
@@ -977,7 +977,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                                        mft_no);
                        atomic_dec(&ni->count);
                        iput(vi);
-                       return FALSE;
+                       return false;
                }
                ntfs_debug("Inode 0x%lx is not dirty.", mft_no);
                /* The inode is not dirty, try to take the mft record lock. */
@@ -986,7 +986,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                                        "not write it.", mft_no);
                        atomic_dec(&ni->count);
                        iput(vi);
-                       return FALSE;
+                       return false;
                }
                ntfs_debug("Managed to lock mft record 0x%lx, write it.",
                                mft_no);
@@ -995,7 +995,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                 * return the locked ntfs inode.
                 */
                *locked_ni = ni;
-               return TRUE;
+               return true;
        }
        ntfs_debug("Inode 0x%lx is not in icache.", mft_no);
        /* The inode is not in icache. */
@@ -1003,13 +1003,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
        if (!ntfs_is_mft_record(m->magic)) {
                ntfs_debug("Mft record 0x%lx is not a FILE record, write it.",
                                mft_no);
-               return TRUE;
+               return true;
        }
        /* Write the mft record if it is a base inode. */
        if (!m->base_mft_record) {
                ntfs_debug("Mft record 0x%lx is a base record, write it.",
                                mft_no);
-               return TRUE;
+               return true;
        }
        /*
         * This is an extent mft record.  Check if the inode corresponding to
@@ -1033,7 +1033,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                 */
                ntfs_debug("Base inode 0x%lx is not in icache, write the "
                                "extent record.", na.mft_no);
-               return TRUE;
+               return true;
        }
        ntfs_debug("Base inode 0x%lx is in icache.", na.mft_no);
        /*
@@ -1051,7 +1051,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                iput(vi);
                ntfs_debug("Base inode 0x%lx has no attached extent inodes, "
                                "write the extent record.", na.mft_no);
-               return TRUE;
+               return true;
        }
        /* Iterate over the attached extent inodes. */
        extent_nis = ni->ext.extent_ntfs_inos;
@@ -1075,7 +1075,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                ntfs_debug("Extent inode 0x%lx is not attached to its base "
                                "inode 0x%lx, write the extent record.",
                                mft_no, na.mft_no);
-               return TRUE;
+               return true;
        }
        ntfs_debug("Extent inode 0x%lx is attached to its base inode 0x%lx.",
                        mft_no, na.mft_no);
@@ -1091,7 +1091,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
                iput(vi);
                ntfs_debug("Extent mft record 0x%lx is already locked, do "
                                "not write it.", mft_no);
-               return FALSE;
+               return false;
        }
        ntfs_debug("Managed to lock extent mft record 0x%lx, write it.",
                        mft_no);
@@ -1103,7 +1103,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
         * the locked extent ntfs inode.
         */
        *locked_ni = eni;
-       return TRUE;
+       return true;
 }
 
 static const char *es = "  Leaving inconsistent metadata.  Unmount and run "
@@ -1354,7 +1354,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
                ntfs_unmap_page(page);
                /* Allocate a cluster from the DATA_ZONE. */
                rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE,
-                               TRUE);
+                               true);
                if (IS_ERR(rl2)) {
                        up_write(&mftbmp_ni->runlist.lock);
                        ntfs_error(vol->sb, "Failed to allocate a cluster for "
@@ -1724,7 +1724,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
        ATTR_RECORD *a = NULL;
        int ret, mp_size;
        u32 old_alen = 0;
-       BOOL mp_rebuilt = FALSE;
+       bool mp_rebuilt = false;
 
        ntfs_debug("Extending mft data allocation.");
        mft_ni = NTFS_I(vol->mft_ino);
@@ -1780,7 +1780,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
        old_last_vcn = rl[1].vcn;
        do {
                rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE,
-                               TRUE);
+                               true);
                if (likely(!IS_ERR(rl2)))
                        break;
                if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) {
@@ -1884,7 +1884,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
                ret = -EOPNOTSUPP;
                goto undo_alloc;
        }
-       mp_rebuilt = TRUE;
+       mp_rebuilt = true;
        /* Generate the mapping pairs array directly into the attr record. */
        ret = ntfs_mapping_pairs_build(vol, (u8*)a +
                        le16_to_cpu(a->data.non_resident.mapping_pairs_offset),
@@ -2255,7 +2255,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode,
        unsigned int ofs;
        int err;
        le16 seq_no, usn;
-       BOOL record_formatted = FALSE;
+       bool record_formatted = false;
 
        if (base_ni) {
                ntfs_debug("Entering (allocating an extent mft record for "
@@ -2454,7 +2454,7 @@ have_alloc_rec:
                mft_ni->initialized_size = new_initialized_size;
        }
        write_unlock_irqrestore(&mft_ni->size_lock, flags);
-       record_formatted = TRUE;
+       record_formatted = true;
        /* Update the mft data attribute record to reflect the new sizes. */
        m = map_mft_record(mft_ni);
        if (IS_ERR(m)) {
@@ -2637,11 +2637,6 @@ mft_rec_already_initialized:
                        goto undo_mftbmp_alloc;
                }
                vi->i_ino = bit;
-               /*
-                * This is the optimal IO size (for stat), not the fs block
-                * size.
-                */
-               vi->i_blksize = PAGE_CACHE_SIZE;
                /*
                 * This is for checking whether an inode has changed w.r.t. a
                 * file so that the file can be updated if necessary (compare
@@ -2893,7 +2888,7 @@ rollback:
        if (!(base_ni->nr_extents & 3)) {
                int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode*);
 
-               extent_nis = (ntfs_inode**)kmalloc(new_size, GFP_NOFS);
+               extent_nis = kmalloc(new_size, GFP_NOFS);
                if (unlikely(!extent_nis)) {
                        ntfs_error(vol->sb, "Failed to allocate internal "
                                        "buffer during rollback.%s", es);
index 639cd1bab08b7919c3307964faaf75f525717950..b52bf87b99de90ecf1a40adcd2c602ac87fbae7e 100644 (file)
@@ -111,7 +111,7 @@ static inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync)
        return err;
 }
 
-extern BOOL ntfs_may_write_mft_record(ntfs_volume *vol,
+extern bool ntfs_may_write_mft_record(ntfs_volume *vol,
                const unsigned long mft_no, const MFT_RECORD *m,
                ntfs_inode **locked_ni);
 
index ddd3d503097c081e42176abb5fd494864fcf56c4..a12847ae467d3a595dc020d646b7912b5f2cbc4e 100644 (file)
@@ -105,7 +105,7 @@ extern int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size);
 extern void post_write_mst_fixup(NTFS_RECORD *b);
 
 /* From fs/ntfs/unistr.c */
-extern BOOL ntfs_are_names_equal(const ntfschar *s1, size_t s1_len,
+extern bool ntfs_are_names_equal(const ntfschar *s1, size_t s1_len,
                const ntfschar *s2, size_t s2_len,
                const IGNORE_CASE_BOOL ic,
                const ntfschar *upcase, const u32 upcase_size);
index d0ef4182147be0a02550335baca0ed5751ffaeb9..d80e3315cab0ec73cfdd9b668594d588f559273e 100644 (file)
  * ntfs_mark_quotas_out_of_date - mark the quotas out of date on an ntfs volume
  * @vol:       ntfs volume on which to mark the quotas out of date
  *
- * Mark the quotas out of date on the ntfs volume @vol and return TRUE on
- * success and FALSE on error.
+ * Mark the quotas out of date on the ntfs volume @vol and return 'true' on
+ * success and 'false' on error.
  */
-BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
+bool ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
 {
        ntfs_index_context *ictx;
        QUOTA_CONTROL_ENTRY *qce;
@@ -46,7 +46,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
                goto done;
        if (!vol->quota_ino || !vol->quota_q_ino) {
                ntfs_error(vol->sb, "Quota inodes are not open.");
-               return FALSE;
+               return false;
        }
        mutex_lock(&vol->quota_q_ino->i_mutex);
        ictx = ntfs_index_ctx_get(NTFS_I(vol->quota_q_ino));
@@ -106,12 +106,12 @@ set_done:
        NVolSetQuotaOutOfDate(vol);
 done:
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 err_out:
        if (ictx)
                ntfs_index_ctx_put(ictx);
        mutex_unlock(&vol->quota_q_ino->i_mutex);
-       return FALSE;
+       return false;
 }
 
 #endif /* NTFS_RW */
index 40e4763aa2221d1f6f15afcddbddee9ac9070994..4cbe5594c0b077f8fe795a39ff217cb0c6ac8ef0 100644 (file)
@@ -28,7 +28,7 @@
 #include "types.h"
 #include "volume.h"
 
-extern BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol);
+extern bool ntfs_mark_quotas_out_of_date(ntfs_volume *vol);
 
 #endif /* NTFS_RW */
 
index eb52b801512bc8027d2def23cd2359cd9f96a1ca..9afd72c7ad0db7c81f4487302971c2340cabecf0 100644 (file)
@@ -149,10 +149,10 @@ static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
  *
  * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * Return: TRUE   Success, the runlists can be merged.
- *        FALSE  Failure, the runlists cannot be merged.
+ * Return: true   Success, the runlists can be merged.
+ *        false  Failure, the runlists cannot be merged.
  */
-static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
+static inline bool ntfs_are_rl_mergeable(runlist_element *dst,
                runlist_element *src)
 {
        BUG_ON(!dst);
@@ -160,19 +160,19 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
 
        /* We can merge unmapped regions even if they are misaligned. */
        if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
-               return TRUE;
+               return true;
        /* If the runs are misaligned, we cannot merge them. */
        if ((dst->vcn + dst->length) != src->vcn)
-               return FALSE;
+               return false;
        /* If both runs are non-sparse and contiguous, we can merge them. */
        if ((dst->lcn >= 0) && (src->lcn >= 0) &&
                        ((dst->lcn + dst->length) == src->lcn))
-               return TRUE;
+               return true;
        /* If we are merging two holes, we can merge them. */
        if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
-               return TRUE;
+               return true;
        /* Cannot merge. */
-       return FALSE;
+       return false;
 }
 
 /**
@@ -218,7 +218,7 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
 static inline runlist_element *ntfs_rl_append(runlist_element *dst,
                int dsize, runlist_element *src, int ssize, int loc)
 {
-       BOOL right = FALSE;     /* Right end of @src needs merging. */
+       bool right = false;     /* Right end of @src needs merging. */
        int marker;             /* End of the inserted runs. */
 
        BUG_ON(!dst);
@@ -285,8 +285,8 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst,
 static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
                int dsize, runlist_element *src, int ssize, int loc)
 {
-       BOOL left = FALSE;      /* Left end of @src needs merging. */
-       BOOL disc = FALSE;      /* Discontinuity between @dst and @src. */
+       bool left = false;      /* Left end of @src needs merging. */
+       bool disc = false;      /* Discontinuity between @dst and @src. */
        int marker;             /* End of the inserted runs. */
 
        BUG_ON(!dst);
@@ -382,8 +382,8 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
                int dsize, runlist_element *src, int ssize, int loc)
 {
        signed delta;
-       BOOL left = FALSE;      /* Left end of @src needs merging. */
-       BOOL right = FALSE;     /* Right end of @src needs merging. */
+       bool left = false;      /* Left end of @src needs merging. */
+       bool right = false;     /* Right end of @src needs merging. */
        int tail;               /* Start of tail of @dst. */
        int marker;             /* End of the inserted runs. */
 
@@ -620,8 +620,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
                ;
 
        {
-       BOOL start;
-       BOOL finish;
+       bool start;
+       bool finish;
        int ds = dend + 1;              /* Number of elements in drl & srl */
        int ss = sfinal - sstart + 1;
 
@@ -635,7 +635,7 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
        if (finish && !drl[dins].length)
                ss++;
        if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
-               finish = FALSE;
+               finish = false;
 #if 0
        ntfs_debug("dfinal = %i, dend = %i", dfinal, dend);
        ntfs_debug("sstart = %i, sfinal = %i, send = %i", sstart, sfinal, send);
@@ -1134,7 +1134,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
 {
        LCN prev_lcn;
        int rls;
-       BOOL the_end = FALSE;
+       bool the_end = false;
 
        BUG_ON(first_vcn < 0);
        BUG_ON(last_vcn < -1);
@@ -1168,7 +1168,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
                        s64 s1 = last_vcn + 1;
                        if (unlikely(rl[1].vcn > s1))
                                length = s1 - rl->vcn;
-                       the_end = TRUE;
+                       the_end = true;
                }
                delta = first_vcn - rl->vcn;
                /* Header byte + length. */
@@ -1204,7 +1204,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
                        s64 s1 = last_vcn + 1;
                        if (unlikely(rl[1].vcn > s1))
                                length = s1 - rl->vcn;
-                       the_end = TRUE;
+                       the_end = true;
                }
                /* Header byte + length. */
                rls += 1 + ntfs_get_nr_significant_bytes(length);
@@ -1327,7 +1327,7 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
        LCN prev_lcn;
        s8 *dst_max, *dst_next;
        int err = -ENOSPC;
-       BOOL the_end = FALSE;
+       bool the_end = false;
        s8 len_len, lcn_len;
 
        BUG_ON(first_vcn < 0);
@@ -1370,7 +1370,7 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
                        s64 s1 = last_vcn + 1;
                        if (unlikely(rl[1].vcn > s1))
                                length = s1 - rl->vcn;
-                       the_end = TRUE;
+                       the_end = true;
                }
                delta = first_vcn - rl->vcn;
                /* Write length. */
@@ -1422,7 +1422,7 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
                        s64 s1 = last_vcn + 1;
                        if (unlikely(rl[1].vcn > s1))
                                length = s1 - rl->vcn;
-                       the_end = TRUE;
+                       the_end = true;
                }
                /* Write length. */
                len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
@@ -1541,7 +1541,7 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
         */
        if (rl->length) {
                runlist_element *trl;
-               BOOL is_end;
+               bool is_end;
 
                ntfs_debug("Shrinking runlist.");
                /* Determine the runlist size. */
@@ -1555,11 +1555,11 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
                 * If a run was partially truncated, make the following runlist
                 * element a terminator.
                 */
-               is_end = FALSE;
+               is_end = false;
                if (rl->length) {
                        rl++;
                        if (!rl->length)
-                               is_end = TRUE;
+                               is_end = true;
                        rl->vcn = new_length;
                        rl->length = 0;
                }
@@ -1648,7 +1648,7 @@ int ntfs_rl_punch_nolock(const ntfs_volume *vol, runlist *const runlist,
        s64 delta;
        runlist_element *rl, *rl_end, *rl_real_end, *trl;
        int old_size;
-       BOOL lcn_fixup = FALSE;
+       bool lcn_fixup = false;
 
        ntfs_debug("Entering for start 0x%llx, length 0x%llx.",
                        (long long)start, (long long)length);
@@ -1862,7 +1862,7 @@ split_end:
                if (rl->lcn >= 0) {
                        rl->lcn -= delta;
                        /* Need this in case the lcn just became negative. */
-                       lcn_fixup = TRUE;
+                       lcn_fixup = true;
                }
                rl->length += delta;
                goto split_end;
index 74e0ee8fce721ec8326a090b62a4ad79cb5d0156..03a391ac71457a282aeb1703c5585877d93533f9 100644 (file)
@@ -74,18 +74,18 @@ const option_t on_errors_arr[] = {
  *
  * Copied from old ntfs driver (which copied from vfat driver).
  */
-static int simple_getbool(char *s, BOOL *setval)
+static int simple_getbool(char *s, bool *setval)
 {
        if (s) {
                if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true"))
-                       *setval = TRUE;
+                       *setval = true;
                else if (!strcmp(s, "0") || !strcmp(s, "no") ||
                                                        !strcmp(s, "false"))
-                       *setval = FALSE;
+                       *setval = false;
                else
                        return 0;
        } else
-               *setval = TRUE;
+               *setval = true;
        return 1;
 }
 
@@ -96,7 +96,7 @@ static int simple_getbool(char *s, BOOL *setval)
  *
  * Parse the recognized options in @opt for the ntfs volume described by @vol.
  */
-static BOOL parse_options(ntfs_volume *vol, char *opt)
+static bool parse_options(ntfs_volume *vol, char *opt)
 {
        char *p, *v, *ov;
        static char *utf8 = "utf8";
@@ -137,7 +137,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
        }
 #define NTFS_GETOPT_BOOL(option, variable)                             \
        if (!strcmp(p, option)) {                                       \
-               BOOL val;                                               \
+               bool val;                                               \
                if (!simple_getbool(v, &val))                           \
                        goto needs_bool;                                \
                variable = val;                                         \
@@ -170,7 +170,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
                else NTFS_GETOPT_OCTAL("fmask", fmask)
                else NTFS_GETOPT_OCTAL("dmask", dmask)
                else NTFS_GETOPT("mft_zone_multiplier", mft_zone_multiplier)
-               else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, TRUE)
+               else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, true)
                else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files)
                else NTFS_GETOPT_BOOL("case_sensitive", case_sensitive)
                else NTFS_GETOPT_BOOL("disable_sparse", disable_sparse)
@@ -194,7 +194,7 @@ use_utf8:
                                if (!old_nls) {
                                        ntfs_error(vol->sb, "NLS character set "
                                                        "%s not found.", v);
-                                       return FALSE;
+                                       return false;
                                }
                                ntfs_error(vol->sb, "NLS character set %s not "
                                                "found. Using previous one %s.",
@@ -205,14 +205,14 @@ use_utf8:
                                        unload_nls(old_nls);
                        }
                } else if (!strcmp(p, "utf8")) {
-                       BOOL val = FALSE;
+                       bool val = false;
                        ntfs_warning(vol->sb, "Option utf8 is no longer "
                                   "supported, using option nls=utf8. Please "
                                   "use option nls=utf8 in the future and "
                                   "make sure utf8 is compiled either as a "
                                   "module or into the kernel.");
                        if (!v || !*v)
-                               val = TRUE;
+                               val = true;
                        else if (!simple_getbool(v, &val))
                                goto needs_bool;
                        if (val) {
@@ -231,7 +231,7 @@ use_utf8:
        }
 no_mount_options:
        if (errors && !sloppy)
-               return FALSE;
+               return false;
        if (sloppy)
                ntfs_warning(vol->sb, "Sloppy option given. Ignoring "
                                "unrecognized mount option(s) and continuing.");
@@ -240,14 +240,14 @@ no_mount_options:
                if (!on_errors) {
                        ntfs_error(vol->sb, "Invalid errors option argument "
                                        "or bug in options parser.");
-                       return FALSE;
+                       return false;
                }
        }
        if (nls_map) {
                if (vol->nls_map && vol->nls_map != nls_map) {
                        ntfs_error(vol->sb, "Cannot change NLS character set "
                                        "on remount.");
-                       return FALSE;
+                       return false;
                } /* else (!vol->nls_map) */
                ntfs_debug("Using NLS character set %s.", nls_map->charset);
                vol->nls_map = nls_map;
@@ -257,7 +257,7 @@ no_mount_options:
                        if (!vol->nls_map) {
                                ntfs_error(vol->sb, "Failed to load default "
                                                "NLS character set.");
-                               return FALSE;
+                               return false;
                        }
                        ntfs_debug("Using default NLS character set (%s).",
                                        vol->nls_map->charset);
@@ -268,7 +268,7 @@ no_mount_options:
                                mft_zone_multiplier) {
                        ntfs_error(vol->sb, "Cannot change mft_zone_multiplier "
                                        "on remount.");
-                       return FALSE;
+                       return false;
                }
                if (mft_zone_multiplier < 1 || mft_zone_multiplier > 4) {
                        ntfs_error(vol->sb, "Invalid mft_zone_multiplier. "
@@ -318,16 +318,16 @@ no_mount_options:
                                NVolSetSparseEnabled(vol);
                }
        }
-       return TRUE;
+       return true;
 needs_arg:
        ntfs_error(vol->sb, "The %s option requires an argument.", p);
-       return FALSE;
+       return false;
 needs_bool:
        ntfs_error(vol->sb, "The %s option requires a boolean argument.", p);
-       return FALSE;
+       return false;
 needs_val:
        ntfs_error(vol->sb, "Invalid %s option argument: %s", p, ov);
-       return FALSE;
+       return false;
 }
 
 #ifdef NTFS_RW
@@ -543,16 +543,16 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
  * is_boot_sector_ntfs - check whether a boot sector is a valid NTFS boot sector
  * @sb:                Super block of the device to which @b belongs.
  * @b:         Boot sector of device @sb to check.
- * @silent:    If TRUE, all output will be silenced.
+ * @silent:    If 'true', all output will be silenced.
  *
  * is_boot_sector_ntfs() checks whether the boot sector @b is a valid NTFS boot
- * sector. Returns TRUE if it is valid and FALSE if not.
+ * sector. Returns 'true' if it is valid and 'false' if not.
  *
  * @sb is only needed for warning/error output, i.e. it can be NULL when silent
- * is TRUE.
+ * is 'true'.
  */
-static BOOL is_boot_sector_ntfs(const struct super_block *sb,
-               const NTFS_BOOT_SECTOR *b, const BOOL silent)
+static bool is_boot_sector_ntfs(const struct super_block *sb,
+               const NTFS_BOOT_SECTOR *b, const bool silent)
 {
        /*
         * Check that checksum == sum of u32 values from b to the checksum
@@ -620,9 +620,9 @@ static BOOL is_boot_sector_ntfs(const struct super_block *sb,
         */
        if (!silent && b->end_of_sector_marker != const_cpu_to_le16(0xaa55))
                ntfs_warning(sb, "Invalid end of sector marker.");
-       return TRUE;
+       return true;
 not_ntfs:
-       return FALSE;
+       return false;
 }
 
 /**
@@ -732,9 +732,9 @@ hotfix_primary_boot_sector:
  * @b:         boot sector to parse
  *
  * Parse the ntfs boot sector @b and store all imporant information therein in
- * the ntfs super block @vol.  Return TRUE on success and FALSE on error.
+ * the ntfs super block @vol.  Return 'true' on success and 'false' on error.
  */
-static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
+static bool parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
 {
        unsigned int sectors_per_cluster_bits, nr_hidden_sects;
        int clusters_per_mft_record, clusters_per_index_record;
@@ -751,7 +751,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                                "device block size (%lu).  This is not "
                                "supported.  Sorry.", vol->sector_size,
                                vol->sb->s_blocksize);
-               return FALSE;
+               return false;
        }
        ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster);
        sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1;
@@ -770,7 +770,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                ntfs_error(vol->sb, "Cluster size (%i) is smaller than the "
                                "sector size (%i).  This is not supported.  "
                                "Sorry.", vol->cluster_size, vol->sector_size);
-               return FALSE;
+               return false;
        }
        clusters_per_mft_record = b->clusters_per_mft_record;
        ntfs_debug("clusters_per_mft_record = %i (0x%x)",
@@ -802,7 +802,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                                "PAGE_CACHE_SIZE on your system (%lu).  "
                                "This is not supported.  Sorry.",
                                vol->mft_record_size, PAGE_CACHE_SIZE);
-               return FALSE;
+               return false;
        }
        /* We cannot support mft record sizes below the sector size. */
        if (vol->mft_record_size < vol->sector_size) {
@@ -810,7 +810,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                                "sector size (%i).  This is not supported.  "
                                "Sorry.", vol->mft_record_size,
                                vol->sector_size);
-               return FALSE;
+               return false;
        }
        clusters_per_index_record = b->clusters_per_index_record;
        ntfs_debug("clusters_per_index_record = %i (0x%x)",
@@ -841,7 +841,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                                "the sector size (%i).  This is not "
                                "supported.  Sorry.", vol->index_record_size,
                                vol->sector_size);
-               return FALSE;
+               return false;
        }
        /*
         * Get the size of the volume in clusters and check for 64-bit-ness.
@@ -851,7 +851,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
        ll = sle64_to_cpu(b->number_of_sectors) >> sectors_per_cluster_bits;
        if ((u64)ll >= 1ULL << 32) {
                ntfs_error(vol->sb, "Cannot handle 64-bit clusters.  Sorry.");
-               return FALSE;
+               return false;
        }
        vol->nr_clusters = ll;
        ntfs_debug("vol->nr_clusters = 0x%llx", (long long)vol->nr_clusters);
@@ -867,7 +867,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                                        "Maximum supported is 2TiB.  Sorry.",
                                        (unsigned long long)ll >> (40 -
                                        vol->cluster_size_bits));
-                       return FALSE;
+                       return false;
                }
        }
        ll = sle64_to_cpu(b->mft_lcn);
@@ -875,7 +875,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                ntfs_error(vol->sb, "MFT LCN (%lli, 0x%llx) is beyond end of "
                                "volume.  Weird.", (unsigned long long)ll,
                                (unsigned long long)ll);
-               return FALSE;
+               return false;
        }
        vol->mft_lcn = ll;
        ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn);
@@ -884,7 +884,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
                ntfs_error(vol->sb, "MFTMirr LCN (%lli, 0x%llx) is beyond end "
                                "of volume.  Weird.", (unsigned long long)ll,
                                (unsigned long long)ll);
-               return FALSE;
+               return false;
        }
        vol->mftmirr_lcn = ll;
        ntfs_debug("vol->mftmirr_lcn = 0x%llx", (long long)vol->mftmirr_lcn);
@@ -907,7 +907,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
        vol->serial_no = le64_to_cpu(b->volume_serial_number);
        ntfs_debug("vol->serial_no = 0x%llx",
                        (unsigned long long)vol->serial_no);
-       return TRUE;
+       return true;
 }
 
 /**
@@ -1000,9 +1000,9 @@ static void ntfs_setup_allocators(ntfs_volume *vol)
  * load_and_init_mft_mirror - load and setup the mft mirror inode for a volume
  * @vol:       ntfs super block describing device whose mft mirror to load
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  */
-static BOOL load_and_init_mft_mirror(ntfs_volume *vol)
+static bool load_and_init_mft_mirror(ntfs_volume *vol)
 {
        struct inode *tmp_ino;
        ntfs_inode *tmp_ni;
@@ -1014,7 +1014,7 @@ static BOOL load_and_init_mft_mirror(ntfs_volume *vol)
                if (!IS_ERR(tmp_ino))
                        iput(tmp_ino);
                /* Caller will display error message. */
-               return FALSE;
+               return false;
        }
        /*
         * Re-initialize some specifics about $MFTMirr's inode as
@@ -1041,20 +1041,20 @@ static BOOL load_and_init_mft_mirror(ntfs_volume *vol)
        tmp_ni->itype.index.block_size_bits = vol->mft_record_size_bits;
        vol->mftmirr_ino = tmp_ino;
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 /**
  * check_mft_mirror - compare contents of the mft mirror with the mft
  * @vol:       ntfs super block describing device whose mft mirror to check
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  *
  * Note, this function also results in the mft mirror runlist being completely
  * mapped into memory.  The mft mirror write code requires this and will BUG()
  * should it find an unmapped runlist element.
  */
-static BOOL check_mft_mirror(ntfs_volume *vol)
+static bool check_mft_mirror(ntfs_volume *vol)
 {
        struct super_block *sb = vol->sb;
        ntfs_inode *mirr_ni;
@@ -1086,7 +1086,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
                                        index);
                        if (IS_ERR(mft_page)) {
                                ntfs_error(sb, "Failed to read $MFT.");
-                               return FALSE;
+                               return false;
                        }
                        kmft = page_address(mft_page);
                        /* Get the $MFTMirr page. */
@@ -1110,7 +1110,7 @@ mm_unmap_out:
                                ntfs_unmap_page(mirr_page);
 mft_unmap_out:
                                ntfs_unmap_page(mft_page);
-                               return FALSE;
+                               return false;
                        }
                }
                /* Do not check the mirror record if it is not in use. */
@@ -1169,21 +1169,21 @@ mft_unmap_out:
                        ntfs_error(sb, "$MFTMirr location mismatch.  "
                                        "Run chkdsk.");
                        up_read(&mirr_ni->runlist.lock);
-                       return FALSE;
+                       return false;
                }
        } while (rl2[i++].length);
        up_read(&mirr_ni->runlist.lock);
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 /**
  * load_and_check_logfile - load and check the logfile inode for a volume
  * @vol:       ntfs super block describing device whose logfile to load
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  */
-static BOOL load_and_check_logfile(ntfs_volume *vol,
+static bool load_and_check_logfile(ntfs_volume *vol,
                RESTART_PAGE_HEADER **rp)
 {
        struct inode *tmp_ino;
@@ -1194,17 +1194,17 @@ static BOOL load_and_check_logfile(ntfs_volume *vol,
                if (!IS_ERR(tmp_ino))
                        iput(tmp_ino);
                /* Caller will display error message. */
-               return FALSE;
+               return false;
        }
        if (!ntfs_check_logfile(tmp_ino, rp)) {
                iput(tmp_ino);
                /* ntfs_check_logfile() will have displayed error output. */
-               return FALSE;
+               return false;
        }
        NInoSetSparseDisabled(NTFS_I(tmp_ino));
        vol->logfile_ino = tmp_ino;
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 #define NTFS_HIBERFIL_HEADER_SIZE      4096
@@ -1329,10 +1329,10 @@ iput_out:
  * load_and_init_quota - load and setup the quota file for a volume if present
  * @vol:       ntfs super block describing device whose quota file to load
  *
- * Return TRUE on success or FALSE on error.  If $Quota is not present, we
+ * Return 'true' on success or 'false' on error.  If $Quota is not present, we
  * leave vol->quota_ino as NULL and return success.
  */
-static BOOL load_and_init_quota(ntfs_volume *vol)
+static bool load_and_init_quota(ntfs_volume *vol)
 {
        MFT_REF mref;
        struct inode *tmp_ino;
@@ -1366,11 +1366,11 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
                         * not enabled.
                         */
                        NVolSetQuotaOutOfDate(vol);
-                       return TRUE;
+                       return true;
                }
                /* A real error occured. */
                ntfs_error(vol->sb, "Failed to find inode number for $Quota.");
-               return FALSE;
+               return false;
        }
        /* We do not care for the type of match that was found. */
        kfree(name);
@@ -1380,25 +1380,25 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
                if (!IS_ERR(tmp_ino))
                        iput(tmp_ino);
                ntfs_error(vol->sb, "Failed to load $Quota.");
-               return FALSE;
+               return false;
        }
        vol->quota_ino = tmp_ino;
        /* Get the $Q index allocation attribute. */
        tmp_ino = ntfs_index_iget(vol->quota_ino, Q, 2);
        if (IS_ERR(tmp_ino)) {
                ntfs_error(vol->sb, "Failed to load $Quota/$Q index.");
-               return FALSE;
+               return false;
        }
        vol->quota_q_ino = tmp_ino;
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 /**
  * load_and_init_usnjrnl - load and setup the transaction log if present
  * @vol:       ntfs super block describing device whose usnjrnl file to load
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  *
  * If $UsnJrnl is not present or in the process of being disabled, we set
  * NVolUsnJrnlStamped() and return success.
@@ -1408,7 +1408,7 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
  * stamped and nothing has been logged since, we also set NVolUsnJrnlStamped()
  * and return success.
  */
-static BOOL load_and_init_usnjrnl(ntfs_volume *vol)
+static bool load_and_init_usnjrnl(ntfs_volume *vol)
 {
        MFT_REF mref;
        struct inode *tmp_ino;
@@ -1450,12 +1450,12 @@ not_enabled:
                         * transaction logging is not enabled.
                         */
                        NVolSetUsnJrnlStamped(vol);
-                       return TRUE;
+                       return true;
                }
                /* A real error occured. */
                ntfs_error(vol->sb, "Failed to find inode number for "
                                "$UsnJrnl.");
-               return FALSE;
+               return false;
        }
        /* We do not care for the type of match that was found. */
        kfree(name);
@@ -1465,7 +1465,7 @@ not_enabled:
                if (!IS_ERR(tmp_ino))
                        iput(tmp_ino);
                ntfs_error(vol->sb, "Failed to load $UsnJrnl.");
-               return FALSE;
+               return false;
        }
        vol->usnjrnl_ino = tmp_ino;
        /*
@@ -1483,7 +1483,7 @@ not_enabled:
        if (IS_ERR(tmp_ino)) {
                ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$Max "
                                "attribute.");
-               return FALSE;
+               return false;
        }
        vol->usnjrnl_max_ino = tmp_ino;
        if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) {
@@ -1491,14 +1491,14 @@ not_enabled:
                                "attribute (size is 0x%llx but should be at "
                                "least 0x%zx bytes).", i_size_read(tmp_ino),
                                sizeof(USN_HEADER));
-               return FALSE;
+               return false;
        }
        /* Get the $DATA/$J attribute. */
        tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, J, 2);
        if (IS_ERR(tmp_ino)) {
                ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$J "
                                "attribute.");
-               return FALSE;
+               return false;
        }
        vol->usnjrnl_j_ino = tmp_ino;
        /* Verify $J is non-resident and sparse. */
@@ -1506,14 +1506,14 @@ not_enabled:
        if (unlikely(!NInoNonResident(tmp_ni) || !NInoSparse(tmp_ni))) {
                ntfs_error(vol->sb, "$UsnJrnl/$DATA/$J attribute is resident "
                                "and/or not sparse.");
-               return FALSE;
+               return false;
        }
        /* Read the USN_HEADER from $DATA/$Max. */
        page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0);
        if (IS_ERR(page)) {
                ntfs_error(vol->sb, "Failed to read from $UsnJrnl/$DATA/$Max "
                                "attribute.");
-               return FALSE;
+               return false;
        }
        uh = (USN_HEADER*)page_address(page);
        /* Sanity check the $Max. */
@@ -1524,7 +1524,7 @@ not_enabled:
                                (long long)sle64_to_cpu(uh->allocation_delta),
                                (long long)sle64_to_cpu(uh->maximum_size));
                ntfs_unmap_page(page);
-               return FALSE;
+               return false;
        }
        /*
         * If the transaction log has been stamped and nothing has been written
@@ -1548,20 +1548,20 @@ not_enabled:
                                (long long)sle64_to_cpu(uh->lowest_valid_usn),
                                i_size_read(vol->usnjrnl_j_ino));
                ntfs_unmap_page(page);
-               return FALSE;
+               return false;
        }
        ntfs_unmap_page(page);
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 /**
  * load_and_init_attrdef - load the attribute definitions table for a volume
  * @vol:       ntfs super block describing device whose attrdef to load
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  */
-static BOOL load_and_init_attrdef(ntfs_volume *vol)
+static bool load_and_init_attrdef(ntfs_volume *vol)
 {
        loff_t i_size;
        struct super_block *sb = vol->sb;
@@ -1607,7 +1607,7 @@ read_partial_attrdef_page:
        vol->attrdef_size = i_size;
        ntfs_debug("Read %llu bytes from $AttrDef.", i_size);
        iput(ino);
-       return TRUE;
+       return true;
 free_iput_failed:
        ntfs_free(vol->attrdef);
        vol->attrdef = NULL;
@@ -1615,7 +1615,7 @@ iput_failed:
        iput(ino);
 failed:
        ntfs_error(sb, "Failed to initialize attribute definition table.");
-       return FALSE;
+       return false;
 }
 
 #endif /* NTFS_RW */
@@ -1624,9 +1624,9 @@ failed:
  * load_and_init_upcase - load the upcase table for an ntfs volume
  * @vol:       ntfs super block describing device whose upcase to load
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  */
-static BOOL load_and_init_upcase(ntfs_volume *vol)
+static bool load_and_init_upcase(ntfs_volume *vol)
 {
        loff_t i_size;
        struct super_block *sb = vol->sb;
@@ -1682,7 +1682,7 @@ read_partial_upcase_page:
                ntfs_debug("Using volume specified $UpCase since default is "
                                "not present.");
                mutex_unlock(&ntfs_lock);
-               return TRUE;
+               return true;
        }
        max = default_upcase_len;
        if (max > vol->upcase_len)
@@ -1698,12 +1698,12 @@ read_partial_upcase_page:
                mutex_unlock(&ntfs_lock);
                ntfs_debug("Volume specified $UpCase matches default. Using "
                                "default.");
-               return TRUE;
+               return true;
        }
        mutex_unlock(&ntfs_lock);
        ntfs_debug("Using volume specified $UpCase since it does not match "
                        "the default.");
-       return TRUE;
+       return true;
 iput_upcase_failed:
        iput(ino);
        ntfs_free(vol->upcase);
@@ -1717,11 +1717,11 @@ upcase_failed:
                mutex_unlock(&ntfs_lock);
                ntfs_error(sb, "Failed to load $UpCase from the volume. Using "
                                "default.");
-               return TRUE;
+               return true;
        }
        mutex_unlock(&ntfs_lock);
        ntfs_error(sb, "Failed to initialize upcase table.");
-       return FALSE;
+       return false;
 }
 
 /*
@@ -1739,9 +1739,9 @@ static struct lock_class_key
  * Open the system files with normal access functions and complete setting up
  * the ntfs super block @vol.
  *
- * Return TRUE on success or FALSE on error.
+ * Return 'true' on success or 'false' on error.
  */
-static BOOL load_system_files(ntfs_volume *vol)
+static bool load_system_files(ntfs_volume *vol)
 {
        struct super_block *sb = vol->sb;
        MFT_RECORD *m;
@@ -2067,7 +2067,7 @@ get_ctx_vol_failed:
 #endif /* NTFS_RW */
        /* If on NTFS versions before 3.0, we are done. */
        if (unlikely(vol->major_ver < 3))
-               return TRUE;
+               return true;
        /* NTFS 3.0+ specific initialization. */
        /* Get the security descriptors inode. */
        vol->secure_ino = ntfs_iget(sb, FILE_Secure);
@@ -2173,7 +2173,7 @@ get_ctx_vol_failed:
                NVolSetErrors(vol);
        }
 #endif /* NTFS_RW */
-       return TRUE;
+       return true;
 #ifdef NTFS_RW
 iput_usnjrnl_err_out:
        if (vol->usnjrnl_j_ino)
@@ -2229,7 +2229,7 @@ iput_mirr_err_out:
        if (vol->mftmirr_ino)
                iput(vol->mftmirr_ino);
 #endif /* NTFS_RW */
-       return FALSE;
+       return false;
 }
 
 /**
@@ -3248,32 +3248,14 @@ ictx_err_out:
 
 static void __exit exit_ntfs_fs(void)
 {
-       int err = 0;
-
        ntfs_debug("Unregistering NTFS driver.");
 
        unregister_filesystem(&ntfs_fs_type);
-
-       if (kmem_cache_destroy(ntfs_big_inode_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_big_inode_cache_name);
-       if (kmem_cache_destroy(ntfs_inode_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_inode_cache_name);
-       if (kmem_cache_destroy(ntfs_name_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_name_cache_name);
-       if (kmem_cache_destroy(ntfs_attr_ctx_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_attr_ctx_cache_name);
-       if (kmem_cache_destroy(ntfs_index_ctx_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_index_ctx_cache_name);
-       if (err)
-               printk(KERN_CRIT "NTFS: This causes memory to leak! There is "
-                               "probably a BUG in the driver! Please report "
-                               "you saw this message to "
-                               "linux-ntfs-dev@lists.sourceforge.net\n");
+       kmem_cache_destroy(ntfs_big_inode_cache);
+       kmem_cache_destroy(ntfs_inode_cache);
+       kmem_cache_destroy(ntfs_name_cache);
+       kmem_cache_destroy(ntfs_attr_ctx_cache);
+       kmem_cache_destroy(ntfs_index_ctx_cache);
        /* Unregister the ntfs sysctls. */
        ntfs_sysctl(0);
 }
index 6e4a7e3343f22d268c80dccbf2a2ee9d3857f852..8c8053b66984222fd3c4c744cc63c81e40124b7f 100644 (file)
@@ -61,11 +61,6 @@ typedef sle64 leLSN;
 typedef s64 USN;
 typedef sle64 leUSN;
 
-typedef enum {
-       FALSE = 0,
-       TRUE = 1
-} BOOL;
-
 typedef enum {
        CASE_SENSITIVE = 0,
        IGNORE_CASE = 1,
index b123c0fa6bf6a4d7b10ad1c7cda1dcd1ec0ddf9c..6a495f7369f9e7fbd170d0802014f4d750d6c6ae 100644 (file)
@@ -61,16 +61,16 @@ static const u8 legal_ansi_char_array[0x40] = {
  * @upcase:            upcase table (only if @ic == IGNORE_CASE)
  * @upcase_size:       length in Unicode characters of @upcase (if present)
  *
- * Compare the names @s1 and @s2 and return TRUE (1) if the names are
- * identical, or FALSE (0) if they are not identical. If @ic is IGNORE_CASE,
+ * Compare the names @s1 and @s2 and return 'true' (1) if the names are
+ * identical, or 'false' (0) if they are not identical. If @ic is IGNORE_CASE,
  * the @upcase table is used to performa a case insensitive comparison.
  */
-BOOL ntfs_are_names_equal(const ntfschar *s1, size_t s1_len,
+bool ntfs_are_names_equal(const ntfschar *s1, size_t s1_len,
                const ntfschar *s2, size_t s2_len, const IGNORE_CASE_BOOL ic,
                const ntfschar *upcase, const u32 upcase_size)
 {
        if (s1_len != s2_len)
-               return FALSE;
+               return false;
        if (ic == CASE_SENSITIVE)
                return !ntfs_ucsncmp(s1, s2, s1_len);
        return !ntfs_ucsncasecmp(s1, s2, s1_len, upcase, upcase_size);
@@ -350,7 +350,7 @@ int ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins,
                }
                if (!ns) {
                        ns_len = ins_len * NLS_MAX_CHARSET_SIZE;
-                       ns = (unsigned char*)kmalloc(ns_len + 1, GFP_NOFS);
+                       ns = kmalloc(ns_len + 1, GFP_NOFS);
                        if (!ns)
                                goto mem_err_out;
                }
@@ -365,7 +365,7 @@ retry:                      wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o,
                        else if (wc == -ENAMETOOLONG && ns != *outs) {
                                unsigned char *tc;
                                /* Grow in multiples of 64 bytes. */
-                               tc = (unsigned char*)kmalloc((ns_len + 64) &
+                               tc = kmalloc((ns_len + 64) &
                                                ~63, GFP_NOFS);
                                if (tc) {
                                        memcpy(tc, ns, ns_len);
index 77773240d13980a403ccf7ee3f4cecb2a3550e6b..b2bc0d55b0365b854173b1c2802ce2f78e99bc7a 100644 (file)
  * @vol:       ntfs volume on which to stamp the transaction log
  *
  * Stamp the transaction log ($UsnJrnl) on the ntfs volume @vol and return
- * TRUE on success and FALSE on error.
+ * 'true' on success and 'false' on error.
  *
  * This function assumes that the transaction log has already been loaded and
  * consistency checked by a call to fs/ntfs/super.c::load_and_init_usnjrnl().
  */
-BOOL ntfs_stamp_usnjrnl(ntfs_volume *vol)
+bool ntfs_stamp_usnjrnl(ntfs_volume *vol)
 {
        ntfs_debug("Entering.");
        if (likely(!NVolUsnJrnlStamped(vol))) {
@@ -56,7 +56,7 @@ BOOL ntfs_stamp_usnjrnl(ntfs_volume *vol)
                if (IS_ERR(page)) {
                        ntfs_error(vol->sb, "Failed to read from "
                                        "$UsnJrnl/$DATA/$Max attribute.");
-                       return FALSE;
+                       return false;
                }
                uh = (USN_HEADER*)page_address(page);
                stamp = get_current_ntfs_time();
@@ -78,7 +78,7 @@ BOOL ntfs_stamp_usnjrnl(ntfs_volume *vol)
                NVolSetUsnJrnlStamped(vol);
        }
        ntfs_debug("Done.");
-       return TRUE;
+       return true;
 }
 
 #endif /* NTFS_RW */
index ff988b0deb45d46aea455a55e338ce2d49ba7bfe..3a8af75351e8662235eff32b67f9810f1c717248 100644 (file)
@@ -198,7 +198,7 @@ typedef struct {
 /* sizeof() = 60 (0x3c) bytes */
 } __attribute__ ((__packed__)) USN_RECORD;
 
-extern BOOL ntfs_stamp_usnjrnl(ntfs_volume *vol);
+extern bool ntfs_stamp_usnjrnl(ntfs_volume *vol);
 
 #endif /* NTFS_RW */
 
index 033ad17012325dcc19d1bfe1f38cca44b8feeb21..16b8d1ba706662c15ee99db4fc20f07f20b10e1f 100644 (file)
@@ -335,11 +335,10 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-               inode->i_nlink++;
+               inc_nlink(inode);
 
                inode->i_fop = &simple_dir_operations;
                inode->i_op = &dlmfs_root_inode_operations;
@@ -362,7 +361,6 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
        inode->i_mode = mode;
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -397,7 +395,7 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
 
                /* directory inodes start off with i_nlink ==
                 * 2 (for "." entry) */
-               inode->i_nlink++;
+               inc_nlink(inode);
                break;
        }
 
@@ -451,7 +449,7 @@ static int dlmfs_mkdir(struct inode * dir,
        }
        ip->ip_dlm = dlm;
 
-       dir->i_nlink++;
+       inc_nlink(dir);
        d_instantiate(dentry, inode);
        dget(dentry);   /* Extra count - pin the dentry in core */
 
@@ -629,9 +627,7 @@ static void __exit exit_dlmfs_fs(void)
        flush_workqueue(user_dlm_worker);
        destroy_workqueue(user_dlm_worker);
 
-       if (kmem_cache_destroy(dlmfs_inode_cache))
-               printk(KERN_INFO "dlmfs_inode_cache: not all structures "
-                      "were freed\n");
+       kmem_cache_destroy(dlmfs_inode_cache);
 }
 
 MODULE_AUTHOR("Oracle");
index de887063dcfc7542989e2e30641d75ad963fc18d..8801e41afe8092ad9db9c8c469b5ff1cbfb94fbb 100644 (file)
@@ -2052,7 +2052,7 @@ static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file)
                mlog_errno(ret);
                goto out;
        }
-       osb = (struct ocfs2_super *) inode->u.generic_ip;
+       osb = inode->i_private;
        ocfs2_get_dlm_debug(osb->osb_dlm_debug);
        priv->p_dlm_debug = osb->osb_dlm_debug;
        INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list);
index 2bbfa17090cfd3f5071ad9a17fc86b6af4280ea3..d9ba0a931a03b89aa5c9a894b040470db459e05b 100644 (file)
@@ -961,25 +961,23 @@ static inline int ocfs2_write_should_remove_suid(struct inode *inode)
 }
 
 static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
-                                   const char __user *buf,
-                                   size_t count,
+                                   const struct iovec *iov,
+                                   unsigned long nr_segs,
                                    loff_t pos)
 {
-       struct iovec local_iov = { .iov_base = (void __user *)buf,
-                                  .iov_len = count };
        int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0;
        u32 clusters;
        struct file *filp = iocb->ki_filp;
        struct inode *inode = filp->f_dentry->d_inode;
        loff_t newsize, saved_pos;
 
-       mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
-                  (unsigned int)count,
+       mlog_entry("(0x%p, %u, '%.*s')\n", filp,
+                  (unsigned int)nr_segs,
                   filp->f_dentry->d_name.len,
                   filp->f_dentry->d_name.name);
 
        /* happy write of zero bytes */
-       if (count == 0)
+       if (iocb->ki_left == 0)
                return 0;
 
        if (!inode) {
@@ -1048,7 +1046,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
                } else {
                        saved_pos = iocb->ki_pos;
                }
-               newsize = count + saved_pos;
+               newsize = iocb->ki_left + saved_pos;
 
                mlog(0, "pos=%lld newsize=%lld cursize=%lld\n",
                     (long long) saved_pos, (long long) newsize,
@@ -1081,7 +1079,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
                if (!clusters)
                        break;
 
-               ret = ocfs2_extend_file(inode, NULL, newsize, count);
+               ret = ocfs2_extend_file(inode, NULL, newsize, iocb->ki_left);
                if (ret < 0) {
                        if (ret != -ENOSPC)
                                mlog_errno(ret);
@@ -1098,7 +1096,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
        /* communicate with ocfs2_dio_end_io */
        ocfs2_iocb_set_rw_locked(iocb);
 
-       ret = generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
+       ret = generic_file_aio_write_nolock(iocb, iov, nr_segs, iocb->ki_pos);
 
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
@@ -1132,16 +1130,16 @@ out:
 }
 
 static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
-                                  char __user *buf,
-                                  size_t count,
+                                  const struct iovec *iov,
+                                  unsigned long nr_segs,
                                   loff_t pos)
 {
        int ret = 0, rw_level = -1, have_alloc_sem = 0;
        struct file *filp = iocb->ki_filp;
        struct inode *inode = filp->f_dentry->d_inode;
 
-       mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
-                  (unsigned int)count,
+       mlog_entry("(0x%p, %u, '%.*s')\n", filp,
+                  (unsigned int)nr_segs,
                   filp->f_dentry->d_name.len,
                   filp->f_dentry->d_name.name);
 
@@ -1185,7 +1183,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
        }
        ocfs2_meta_unlock(inode, 0);
 
-       ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos);
+       ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos);
        if (ret == -EINVAL)
                mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
 
index 69d3db5691660a3bca977f77627abe4a46498f25..16e8e74dc966d452401d55a8381e5d89afa64737 100644 (file)
@@ -269,7 +269,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        inode->i_mode = le16_to_cpu(fe->i_mode);
        inode->i_uid = le32_to_cpu(fe->i_uid);
        inode->i_gid = le32_to_cpu(fe->i_gid);
-       inode->i_blksize = (u32)osb->s_clustersize;
 
        /* Fast symlinks will have i_size but no allocated clusters. */
        if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
@@ -1258,8 +1257,6 @@ leave:
 void ocfs2_refresh_inode(struct inode *inode,
                         struct ocfs2_dinode *fe)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-
        spin_lock(&OCFS2_I(inode)->ip_lock);
 
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
@@ -1270,7 +1267,6 @@ void ocfs2_refresh_inode(struct inode *inode,
        inode->i_uid = le32_to_cpu(fe->i_uid);
        inode->i_gid = le32_to_cpu(fe->i_gid);
        inode->i_mode = le16_to_cpu(fe->i_mode);
-       inode->i_blksize = (u32) osb->s_clustersize;
        if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0)
                inode->i_blocks = 0;
        else
index 849c3b4bb94a12d1e856df92e3c47d8e08dd3b43..259155f0eb2e97ce20a39b7d990ee497b59a5725 100644 (file)
@@ -429,7 +429,7 @@ static int ocfs2_mknod(struct inode *dir,
                        mlog_errno(status);
                        goto leave;
                }
-               dir->i_nlink++;
+               inc_nlink(dir);
        }
 
        status = ocfs2_add_entry(handle, dentry, inode,
@@ -730,7 +730,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto bail;
        }
 
-       inode->i_nlink++;
+       inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME;
        fe->i_links_count = cpu_to_le16(inode->i_nlink);
        fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
@@ -739,7 +739,7 @@ static int ocfs2_link(struct dentry *old_dentry,
        err = ocfs2_journal_dirty(handle, fe_bh);
        if (err < 0) {
                le16_add_cpu(&fe->i_links_count, -1);
-               inode->i_nlink--;
+               drop_nlink(inode);
                mlog_errno(err);
                goto bail;
        }
@@ -749,7 +749,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                              parent_fe_bh, de_bh);
        if (err) {
                le16_add_cpu(&fe->i_links_count, -1);
-               inode->i_nlink--;
+               drop_nlink(inode);
                mlog_errno(err);
                goto bail;
        }
@@ -795,11 +795,23 @@ static int ocfs2_remote_dentry_delete(struct dentry *dentry)
        return ret;
 }
 
+static inline int inode_is_unlinkable(struct inode *inode)
+{
+       if (S_ISDIR(inode->i_mode)) {
+               if (inode->i_nlink == 2)
+                       return 1;
+               return 0;
+       }
+
+       if (inode->i_nlink == 1)
+               return 1;
+       return 0;
+}
+
 static int ocfs2_unlink(struct inode *dir,
                        struct dentry *dentry)
 {
        int status;
-       unsigned int saved_nlink = 0;
        struct inode *inode = dentry->d_inode;
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        u64 blkno;
@@ -874,16 +886,6 @@ static int ocfs2_unlink(struct inode *dir,
                }
        }
 
-       /* There are still a few steps left until we can consider the
-        * unlink to have succeeded. Save off nlink here before
-        * modification so we can set it back in case we hit an issue
-        * before commit. */
-       saved_nlink = inode->i_nlink;
-       if (S_ISDIR(inode->i_mode))
-               inode->i_nlink = 0;
-       else
-               inode->i_nlink--;
-
        status = ocfs2_remote_dentry_delete(dentry);
        if (status < 0) {
                /* This vote should succeed under all normal
@@ -892,7 +894,7 @@ static int ocfs2_unlink(struct inode *dir,
                goto leave;
        }
 
-       if (!inode->i_nlink) {
+       if (inode_is_unlinkable(inode)) {
                status = ocfs2_prepare_orphan_dir(osb, handle, inode,
                                                  orphan_name,
                                                  &orphan_entry_bh);
@@ -919,7 +921,7 @@ static int ocfs2_unlink(struct inode *dir,
 
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
-       if (!inode->i_nlink) {
+       if (inode_is_unlinkable(inode)) {
                status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
                                          orphan_entry_bh);
                if (status < 0) {
@@ -935,10 +937,10 @@ static int ocfs2_unlink(struct inode *dir,
                goto leave;
        }
 
-       /* We can set nlink on the dinode now. clear the saved version
-        * so that it doesn't get set later. */
+       if (S_ISDIR(inode->i_mode))
+               drop_nlink(inode);
+       drop_nlink(inode);
        fe->i_links_count = cpu_to_le16(inode->i_nlink);
-       saved_nlink = 0;
 
        status = ocfs2_journal_dirty(handle, fe_bh);
        if (status < 0) {
@@ -947,19 +949,16 @@ static int ocfs2_unlink(struct inode *dir,
        }
 
        if (S_ISDIR(inode->i_mode)) {
-               dir->i_nlink--;
+               drop_nlink(dir);
                status = ocfs2_mark_inode_dirty(handle, dir,
                                                parent_node_bh);
                if (status < 0) {
                        mlog_errno(status);
-                       dir->i_nlink++;
+                       inc_nlink(dir);
                }
        }
 
 leave:
-       if (status < 0 && saved_nlink)
-               inode->i_nlink = saved_nlink;
-
        if (handle)
                ocfs2_commit_trans(handle);
 
@@ -1382,7 +1381,7 @@ static int ocfs2_rename(struct inode *old_dir,
                if (new_inode) {
                        new_inode->i_nlink--;
                } else {
-                       new_dir->i_nlink++;
+                       inc_nlink(new_dir);
                        mark_inode_dirty(new_dir);
                }
        }
index 303f06d2a7b92e8e001489cf2b1db17bdae6bd0c..89e0c237a636987d5b131e5816e8d9d9f238f210 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -6,7 +6,6 @@
 
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/utime.h>
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/quotaops.h>
@@ -29,8 +28,6 @@
 #include <linux/rcupdate.h>
 #include <linux/audit.h>
 
-#include <asm/unistd.h>
-
 int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        int retval = -ENODEV;
@@ -353,137 +350,6 @@ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
 }
 #endif
 
-#ifdef __ARCH_WANT_SYS_UTIME
-
-/*
- * sys_utime() can be implemented in user-level using sys_utimes().
- * Is this for backwards compatibility?  If so, why not move it
- * into the appropriate arch directory (for those architectures that
- * need it).
- */
-
-/* If times==NULL, set access and modification to current time,
- * 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)
-{
-       int error;
-       struct nameidata nd;
-       struct inode * inode;
-       struct iattr newattrs;
-
-       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;
-       }
-       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;
-}
-
-#endif
-
-/* If times==NULL, set access and modification to current time,
- * 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)
-{
-       int error;
-       struct nameidata nd;
-       struct inode * inode;
-       struct iattr newattrs;
-
-       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &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;
-
-               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;
-       } 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;
-       }
-       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;
-}
-
-asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
-{
-       struct timeval times[2];
-
-       if (utimes && copy_from_user(&times, utimes, sizeof(times)))
-               return -EFAULT;
-       return do_utimes(dfd, filename, utimes ? times : NULL);
-}
-
-asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
-{
-       return sys_futimesat(AT_FDCWD, filename, utimes);
-}
-
-
 /*
  * access() needs to use the real uid/gid, not the effective uid/gid.
  * We do this by temporarily clearing all FS-related capabilities and
@@ -520,15 +386,21 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
                current->cap_effective = current->cap_permitted;
 
        res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
-       if (!res) {
-               res = vfs_permission(&nd, mode);
-               /* SuS v2 requires we report a read only fs too */
-               if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
-                  && !special_file(nd.dentry->d_inode->i_mode))
-                       res = -EROFS;
-               path_release(&nd);
-       }
+       if (res)
+               goto out;
+
+       res = vfs_permission(&nd, mode);
+       /* SuS v2 requires we report a read only fs too */
+       if(res || !(mode & S_IWOTH) ||
+          special_file(nd.dentry->d_inode->i_mode))
+               goto out_path_release;
+
+       if(IS_RDONLY(nd.dentry->d_inode))
+               res = -EROFS;
 
+out_path_release:
+       path_release(&nd);
+out:
        current->fsuid = old_fsuid;
        current->fsgid = old_fsgid;
        current->cap_effective = old_cap;
@@ -546,7 +418,8 @@ asmlinkage long sys_chdir(const char __user * filename)
        struct nameidata nd;
        int error;
 
-       error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
+       error = __user_walk(filename,
+                           LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
        if (error)
                goto out;
 
@@ -736,10 +609,11 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
        int error;
 
        error = user_path_walk(filename, &nd);
-       if (!error) {
-               error = chown_common(nd.dentry, user, group);
-               path_release(&nd);
-       }
+       if (error)
+               goto out;
+       error = chown_common(nd.dentry, user, group);
+       path_release(&nd);
+out:
        return error;
 }
 
@@ -755,10 +629,10 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
 
        follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
        error = __user_walk_fd(dfd, filename, follow, &nd);
-       if (!error) {
-               error = chown_common(nd.dentry, user, group);
-               path_release(&nd);
-       }
+       if (error)
+               goto out;
+       error = chown_common(nd.dentry, user, group);
+       path_release(&nd);
 out:
        return error;
 }
@@ -769,10 +643,11 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group
        int error;
 
        error = user_path_walk_link(filename, &nd);
-       if (!error) {
-               error = chown_common(nd.dentry, user, group);
-               path_release(&nd);
-       }
+       if (error)
+               goto out;
+       error = chown_common(nd.dentry, user, group);
+       path_release(&nd);
+out:
        return error;
 }
 
@@ -781,15 +656,17 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
 {
        struct file * file;
        int error = -EBADF;
+       struct dentry * dentry;
 
        file = fget(fd);
-       if (file) {
-               struct dentry * dentry;
-               dentry = file->f_dentry;
-               audit_inode(NULL, dentry->d_inode);
-               error = chown_common(dentry, user, group);
-               fput(file);
-       }
+       if (!file)
+               goto out;
+
+       dentry = file->f_dentry;
+       audit_inode(NULL, dentry->d_inode);
+       error = chown_common(dentry, user, group);
+       fput(file);
+out:
        return error;
 }
 
@@ -1172,6 +1049,7 @@ asmlinkage long sys_close(unsigned int fd)
        struct file * filp;
        struct files_struct *files = current->files;
        struct fdtable *fdt;
+       int retval;
 
        spin_lock(&files->file_lock);
        fdt = files_fdtable(files);
@@ -1184,7 +1062,16 @@ asmlinkage long sys_close(unsigned int fd)
        FD_CLR(fd, fdt->close_on_exec);
        __put_unused_fd(files, fd);
        spin_unlock(&files->file_lock);
-       return filp_close(filp, files);
+       retval = filp_close(filp, files);
+
+       /* can't restart close syscall because file table entry was cleared */
+       if (unlikely(retval == -ERESTARTSYS ||
+                    retval == -ERESTARTNOINTR ||
+                    retval == -ERESTARTNOHAND ||
+                    retval == -ERESTART_RESTARTBLOCK))
+               retval = -EINTR;
+
+       return retval;
 
 out_unlock:
        spin_unlock(&files->file_lock);
index d713ce6b3e12935891bda7e21d301ec3d53038f8..67e665fdb7fccbde923238532d49f192931d43f9 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y := check.o
+obj-$(CONFIG_BLOCK) := check.o
 
 obj-$(CONFIG_ACORN_PARTITION) += acorn.o
 obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
index 63730282ad813688410809c25d22055c5cb38570..1bea610078b35c34808245cc2214947bd369d672 100644 (file)
@@ -238,10 +238,9 @@ alloc_read_gpt_entries(struct block_device *bdev, gpt_header *gpt)
                 le32_to_cpu(gpt->sizeof_partition_entry);
        if (!count)
                return NULL;
-       pte = kmalloc(count, GFP_KERNEL);
+       pte = kzalloc(count, GFP_KERNEL);
        if (!pte)
                return NULL;
-       memset(pte, 0, count);
 
        if (read_lba(bdev, le64_to_cpu(gpt->partition_entry_lba),
                      (u8 *) pte,
@@ -269,10 +268,9 @@ alloc_read_gpt_header(struct block_device *bdev, u64 lba)
        if (!bdev)
                return NULL;
 
-       gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL);
+       gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL);
        if (!gpt)
                return NULL;
-       memset(gpt, 0, sizeof (gpt_header));
 
        if (read_lba(bdev, lba, (u8 *) gpt,
                     sizeof (gpt_header)) < sizeof (gpt_header)) {
@@ -526,9 +524,8 @@ find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes)
        lastlba = last_lba(bdev);
         if (!force_gpt) {
                 /* This will be added to the EFI Spec. per Intel after v1.02. */
-                legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
+                legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL);
                 if (legacymbr) {
-                        memset(legacymbr, 0, sizeof (*legacymbr));
                         read_lba(bdev, 0, (u8 *) legacymbr,
                                  sizeof (*legacymbr));
                         good_pmbr = is_pmbr_valid(legacymbr, lastlba);
index 7ab1c11dca4efb9f06a63827cb43c6a806c59f96..1a60926a4ccd5908587555e84235fa0ba8e90e36 100644 (file)
 #include "check.h"
 #include "msdos.h"
 
-typedef enum {
-       FALSE = 0,
-       TRUE  = 1
-} BOOL;
-
 /**
  * ldm_debug/info/error/crit - Output an error message
  * @f:    A printf format string containing the message
@@ -103,24 +98,24 @@ static int ldm_parse_hexbyte (const u8 *src)
  *
  * N.B. The GUID need not be NULL terminated.
  *
- * Return:  TRUE   @dest contains binary GUID
- *          FALSE  @dest contents are undefined
+ * Return:  'true'   @dest contains binary GUID
+ *          'false'  @dest contents are undefined
  */
-static BOOL ldm_parse_guid (const u8 *src, u8 *dest)
+static bool ldm_parse_guid (const u8 *src, u8 *dest)
 {
        static const int size[] = { 4, 2, 2, 2, 6 };
        int i, j, v;
 
        if (src[8]  != '-' || src[13] != '-' ||
            src[18] != '-' || src[23] != '-')
-               return FALSE;
+               return false;
 
        for (j = 0; j < 5; j++, src++)
                for (i = 0; i < size[j]; i++, src+=2, *dest++ = v)
                        if ((v = ldm_parse_hexbyte (src)) < 0)
-                               return FALSE;
+                               return false;
 
-       return TRUE;
+       return true;
 }
 
 
@@ -132,17 +127,17 @@ static BOOL ldm_parse_guid (const u8 *src, u8 *dest)
  * This parses the LDM database PRIVHEAD structure supplied in @data and
  * sets up the in-memory privhead structure @ph with the obtained information.
  *
- * Return:  TRUE   @ph contains the PRIVHEAD data
- *          FALSE  @ph contents are undefined
+ * Return:  'true'   @ph contains the PRIVHEAD data
+ *          'false'  @ph contents are undefined
  */
-static BOOL ldm_parse_privhead (const u8 *data, struct privhead *ph)
+static bool ldm_parse_privhead (const u8 *data, struct privhead *ph)
 {
        BUG_ON (!data || !ph);
 
        if (MAGIC_PRIVHEAD != BE64 (data)) {
                ldm_error ("Cannot find PRIVHEAD structure. LDM database is"
                        " corrupt. Aborting.");
-               return FALSE;
+               return false;
        }
 
        ph->ver_major          = BE16 (data + 0x000C);
@@ -155,7 +150,7 @@ static BOOL ldm_parse_privhead (const u8 *data, struct privhead *ph)
        if ((ph->ver_major != 2) || (ph->ver_minor != 11)) {
                ldm_error ("Expected PRIVHEAD version %d.%d, got %d.%d."
                        " Aborting.", 2, 11, ph->ver_major, ph->ver_minor);
-               return FALSE;
+               return false;
        }
        if (ph->config_size != LDM_DB_SIZE) {   /* 1 MiB in sectors. */
                /* Warn the user and continue, carefully */
@@ -166,16 +161,16 @@ static BOOL ldm_parse_privhead (const u8 *data, struct privhead *ph)
        if ((ph->logical_disk_size == 0) ||
            (ph->logical_disk_start + ph->logical_disk_size > ph->config_start)) {
                ldm_error ("PRIVHEAD disk size doesn't match real disk size");
-               return FALSE;
+               return false;
        }
 
        if (!ldm_parse_guid (data + 0x0030, ph->disk_id)) {
                ldm_error ("PRIVHEAD contains an invalid GUID.");
-               return FALSE;
+               return false;
        }
 
        ldm_debug ("Parsed PRIVHEAD successfully.");
-       return TRUE;
+       return true;
 }
 
 /**
@@ -189,16 +184,16 @@ static BOOL ldm_parse_privhead (const u8 *data, struct privhead *ph)
  *
  * N.B.  The *_start and *_size values returned in @toc are not range-checked.
  *
- * Return:  TRUE   @toc contains the TOCBLOCK data
- *          FALSE  @toc contents are undefined
+ * Return:  'true'   @toc contains the TOCBLOCK data
+ *          'false'  @toc contents are undefined
  */
-static BOOL ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
+static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
 {
        BUG_ON (!data || !toc);
 
        if (MAGIC_TOCBLOCK != BE64 (data)) {
                ldm_crit ("Cannot find TOCBLOCK, database may be corrupt.");
-               return FALSE;
+               return false;
        }
        strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name));
        toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0;
@@ -209,7 +204,7 @@ static BOOL ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
                        sizeof (toc->bitmap1_name)) != 0) {
                ldm_crit ("TOCBLOCK's first bitmap is '%s', should be '%s'.",
                                TOC_BITMAP1, toc->bitmap1_name);
-               return FALSE;
+               return false;
        }
        strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name));
        toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0;
@@ -219,10 +214,10 @@ static BOOL ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
                        sizeof (toc->bitmap2_name)) != 0) {
                ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.",
                                TOC_BITMAP2, toc->bitmap2_name);
-               return FALSE;
+               return false;
        }
        ldm_debug ("Parsed TOCBLOCK successfully.");
-       return TRUE;
+       return true;
 }
 
 /**
@@ -235,16 +230,16 @@ static BOOL ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
  *
  * N.B.  The *_start, *_size and *_seq values will be range-checked later.
  *
- * Return:  TRUE   @vm contains VMDB info
- *          FALSE  @vm contents are undefined
+ * Return:  'true'   @vm contains VMDB info
+ *          'false'  @vm contents are undefined
  */
-static BOOL ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
+static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
 {
        BUG_ON (!data || !vm);
 
        if (MAGIC_VMDB != BE32 (data)) {
                ldm_crit ("Cannot find the VMDB, database may be corrupt.");
-               return FALSE;
+               return false;
        }
 
        vm->ver_major = BE16 (data + 0x12);
@@ -252,7 +247,7 @@ static BOOL ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
        if ((vm->ver_major != 4) || (vm->ver_minor != 10)) {
                ldm_error ("Expected VMDB version %d.%d, got %d.%d. "
                        "Aborting.", 4, 10, vm->ver_major, vm->ver_minor);
-               return FALSE;
+               return false;
        }
 
        vm->vblk_size     = BE32 (data + 0x08);
@@ -260,7 +255,7 @@ static BOOL ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
        vm->last_vblk_seq = BE32 (data + 0x04);
 
        ldm_debug ("Parsed VMDB successfully.");
-       return TRUE;
+       return true;
 }
 
 /**
@@ -270,10 +265,10 @@ static BOOL ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
  *
  * This compares the two privhead structures @ph1 and @ph2.
  *
- * Return:  TRUE   Identical
- *          FALSE  Different
+ * Return:  'true'   Identical
+ *          'false'  Different
  */
-static BOOL ldm_compare_privheads (const struct privhead *ph1,
+static bool ldm_compare_privheads (const struct privhead *ph1,
                                   const struct privhead *ph2)
 {
        BUG_ON (!ph1 || !ph2);
@@ -294,10 +289,10 @@ static BOOL ldm_compare_privheads (const struct privhead *ph1,
  *
  * This compares the two tocblock structures @toc1 and @toc2.
  *
- * Return:  TRUE   Identical
- *          FALSE  Different
+ * Return:  'true'   Identical
+ *          'false'  Different
  */
-static BOOL ldm_compare_tocblocks (const struct tocblock *toc1,
+static bool ldm_compare_tocblocks (const struct tocblock *toc1,
                                   const struct tocblock *toc2)
 {
        BUG_ON (!toc1 || !toc2);
@@ -323,17 +318,17 @@ static BOOL ldm_compare_tocblocks (const struct tocblock *toc1,
  * the configuration area (the database).  The values are range-checked against
  * @hd, which contains the real size of the disk.
  *
- * Return:  TRUE   Success
- *          FALSE  Error
+ * Return:  'true'   Success
+ *          'false'  Error
  */
-static BOOL ldm_validate_privheads (struct block_device *bdev,
+static bool ldm_validate_privheads (struct block_device *bdev,
                                    struct privhead *ph1)
 {
        static const int off[3] = { OFF_PRIV1, OFF_PRIV2, OFF_PRIV3 };
        struct privhead *ph[3] = { ph1 };
        Sector sect;
        u8 *data;
-       BOOL result = FALSE;
+       bool result = false;
        long num_sects;
        int i;
 
@@ -393,7 +388,7 @@ static BOOL ldm_validate_privheads (struct block_device *bdev,
                goto out;
        }*/
        ldm_debug ("Validated PRIVHEADs successfully.");
-       result = TRUE;
+       result = true;
 out:
        kfree (ph[1]);
        kfree (ph[2]);
@@ -411,10 +406,10 @@ out:
  *
  * The offsets and sizes of the configs are range-checked against a privhead.
  *
- * Return:  TRUE   @toc1 contains validated TOCBLOCK info
- *          FALSE  @toc1 contents are undefined
+ * Return:  'true'   @toc1 contains validated TOCBLOCK info
+ *          'false'  @toc1 contents are undefined
  */
-static BOOL ldm_validate_tocblocks (struct block_device *bdev,
+static bool ldm_validate_tocblocks (struct block_device *bdev,
        unsigned long base, struct ldmdb *ldb)
 {
        static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4};
@@ -422,7 +417,7 @@ static BOOL ldm_validate_tocblocks (struct block_device *bdev,
        struct privhead *ph;
        Sector sect;
        u8 *data;
-       BOOL result = FALSE;
+       bool result = false;
        int i;
 
        BUG_ON (!bdev || !ldb);
@@ -465,7 +460,7 @@ static BOOL ldm_validate_tocblocks (struct block_device *bdev,
        }
 
        ldm_debug ("Validated TOCBLOCKs successfully.");
-       result = TRUE;
+       result = true;
 out:
        kfree (tb[1]);
        kfree (tb[2]);
@@ -482,15 +477,15 @@ out:
  * Find the vmdb of the LDM Database stored on @bdev and return the parsed
  * information in @ldb.
  *
- * Return:  TRUE   @ldb contains validated VBDB info
- *          FALSE  @ldb contents are undefined
+ * Return:  'true'   @ldb contains validated VBDB info
+ *          'false'  @ldb contents are undefined
  */
-static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
+static bool ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
                               struct ldmdb *ldb)
 {
        Sector sect;
        u8 *data;
-       BOOL result = FALSE;
+       bool result = false;
        struct vmdb *vm;
        struct tocblock *toc;
 
@@ -502,7 +497,7 @@ static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
        data = read_dev_sector (bdev, base + OFF_VMDB, &sect);
        if (!data) {
                ldm_crit ("Disk read failed.");
-               return FALSE;
+               return false;
        }
 
        if (!ldm_parse_vmdb (data, vm))
@@ -527,7 +522,7 @@ static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
                goto out;
        }
 
-       result = TRUE;
+       result = true;
 out:
        put_dev_sector (sect);
        return result;
@@ -547,23 +542,23 @@ out:
  *       only likely to happen if the underlying device is strange.  If that IS
  *       the case we should return zero to let someone else try.
  *
- * Return:  TRUE   @bdev is a dynamic disk
- *          FALSE  @bdev is not a dynamic disk, or an error occurred
+ * Return:  'true'   @bdev is a dynamic disk
+ *          'false'  @bdev is not a dynamic disk, or an error occurred
  */
-static BOOL ldm_validate_partition_table (struct block_device *bdev)
+static bool ldm_validate_partition_table (struct block_device *bdev)
 {
        Sector sect;
        u8 *data;
        struct partition *p;
        int i;
-       BOOL result = FALSE;
+       bool result = false;
 
        BUG_ON (!bdev);
 
        data = read_dev_sector (bdev, 0, &sect);
        if (!data) {
                ldm_crit ("Disk read failed.");
-               return FALSE;
+               return false;
        }
 
        if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
@@ -572,7 +567,7 @@ static BOOL ldm_validate_partition_table (struct block_device *bdev)
        p = (struct partition*)(data + 0x01BE);
        for (i = 0; i < 4; i++, p++)
                if (SYS_IND (p) == WIN2K_DYNAMIC_PARTITION) {
-                       result = TRUE;
+                       result = true;
                        break;
                }
 
@@ -625,10 +620,10 @@ static struct vblk * ldm_get_disk_objid (const struct ldmdb *ldb)
  * N.B.  This function creates the partitions in the order it finds partition
  *       objects in the linked list.
  *
- * Return:  TRUE   Partition created
- *          FALSE  Error, probably a range checking problem
+ * Return:  'true'   Partition created
+ *          'false'  Error, probably a range checking problem
  */
-static BOOL ldm_create_data_partitions (struct parsed_partitions *pp,
+static bool ldm_create_data_partitions (struct parsed_partitions *pp,
                                        const struct ldmdb *ldb)
 {
        struct list_head *item;
@@ -642,7 +637,7 @@ static BOOL ldm_create_data_partitions (struct parsed_partitions *pp,
        disk = ldm_get_disk_objid (ldb);
        if (!disk) {
                ldm_crit ("Can't find the ID of this disk in the database.");
-               return FALSE;
+               return false;
        }
 
        printk (" [LDM]");
@@ -661,7 +656,7 @@ static BOOL ldm_create_data_partitions (struct parsed_partitions *pp,
        }
 
        printk ("\n");
-       return TRUE;
+       return true;
 }
 
 
@@ -766,10 +761,10 @@ static int ldm_get_vstr (const u8 *block, u8 *buffer, int buflen)
  *
  * Read a raw VBLK Component object (version 3) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Component VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Component VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
 {
        int r_objid, r_name, r_vstate, r_child, r_parent, r_stripe, r_cols, len;
        struct vblk_comp *comp;
@@ -792,11 +787,11 @@ static BOOL ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
                len = r_parent;
        }
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_CMP3;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        comp = &vb->vblk.comp;
        ldm_get_vstr (buffer + 0x18 + r_name, comp->state,
@@ -806,7 +801,7 @@ static BOOL ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
        comp->parent_id = ldm_get_vnum (buffer + 0x2D + r_child);
        comp->chunksize = r_stripe ? ldm_get_vnum (buffer+r_parent+0x2E) : 0;
 
-       return TRUE;
+       return true;
 }
 
 /**
@@ -817,8 +812,8 @@ static BOOL ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
  *
  * Read a raw VBLK Disk Group object (version 3) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Disk Group VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Disk Group VBLK
+ *          'false'  @vb contents are not defined
  */
 static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
 {
@@ -841,16 +836,16 @@ static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
                len = r_diskid;
        }
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_DGR3;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        dgrp = &vb->vblk.dgrp;
        ldm_get_vstr (buffer + 0x18 + r_name, dgrp->disk_id,
                sizeof (dgrp->disk_id));
-       return TRUE;
+       return true;
 }
 
 /**
@@ -861,10 +856,10 @@ static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
  *
  * Read a raw VBLK Disk Group object (version 4) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Disk Group VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Disk Group VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
 {
        char buf[64];
        int r_objid, r_name, r_id1, r_id2, len;
@@ -885,16 +880,16 @@ static BOOL ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
                len = r_name;
        }
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_DGR4;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        dgrp = &vb->vblk.dgrp;
 
        ldm_get_vstr (buffer + 0x18 + r_objid, buf, sizeof (buf));
-       return TRUE;
+       return true;
 }
 
 /**
@@ -905,10 +900,10 @@ static BOOL ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
  *
  * Read a raw VBLK Disk object (version 3) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Disk VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Disk VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
 {
        int r_objid, r_name, r_diskid, r_altname, len;
        struct vblk_disk *disk;
@@ -921,19 +916,19 @@ static BOOL ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
        r_altname = ldm_relative (buffer, buflen, 0x18, r_diskid);
        len = r_altname;
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_DSK3;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        disk = &vb->vblk.disk;
        ldm_get_vstr (buffer + 0x18 + r_diskid, disk->alt_name,
                sizeof (disk->alt_name));
        if (!ldm_parse_guid (buffer + 0x19 + r_name, disk->disk_id))
-               return FALSE;
+               return false;
 
-       return TRUE;
+       return true;
 }
 
 /**
@@ -944,10 +939,10 @@ static BOOL ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
  *
  * Read a raw VBLK Disk object (version 4) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Disk VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Disk VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
 {
        int r_objid, r_name, len;
        struct vblk_disk *disk;
@@ -958,15 +953,15 @@ static BOOL ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
        r_name  = ldm_relative (buffer, buflen, 0x18, r_objid);
        len     = r_name;
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_DSK4;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        disk = &vb->vblk.disk;
        memcpy (disk->disk_id, buffer + 0x18 + r_name, GUID_SIZE);
-       return TRUE;
+       return true;
 }
 
 /**
@@ -977,10 +972,10 @@ static BOOL ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
  *
  * Read a raw VBLK Partition object (version 3) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Partition VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Partition VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
 {
        int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len;
        struct vblk_part *part;
@@ -1001,11 +996,11 @@ static BOOL ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
                len = r_diskid;
        }
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_PRT3;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        part = &vb->vblk.part;
        part->start         = BE64         (buffer + 0x24 + r_name);
@@ -1018,7 +1013,7 @@ static BOOL ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
        else
                part->partnum = 0;
 
-       return TRUE;
+       return true;
 }
 
 /**
@@ -1029,10 +1024,10 @@ static BOOL ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
  *
  * Read a raw VBLK Volume object (version 5) into a vblk structure.
  *
- * Return:  TRUE   @vb contains a Volume VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a Volume VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
 {
        int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2;
        int r_drive, len;
@@ -1068,11 +1063,11 @@ static BOOL ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
 
        len = r_drive;
        if (len < 0)
-               return FALSE;
+               return false;
 
        len += VBLK_SIZE_VOL5;
        if (len != BE32 (buffer + 0x14))
-               return FALSE;
+               return false;
 
        volu = &vb->vblk.volu;
 
@@ -1087,7 +1082,7 @@ static BOOL ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
                ldm_get_vstr (buffer + 0x53 + r_size,  volu->drive_hint,
                        sizeof (volu->drive_hint));
        }
-       return TRUE;
+       return true;
 }
 
 /**
@@ -1100,12 +1095,12 @@ static BOOL ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
  * information common to all VBLK types, then delegates the rest of the work to
  * helper functions: ldm_parse_*.
  *
- * Return:  TRUE   @vb contains a VBLK
- *          FALSE  @vb contents are not defined
+ * Return:  'true'   @vb contains a VBLK
+ *          'false'  @vb contents are not defined
  */
-static BOOL ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
+static bool ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
 {
-       BOOL result = FALSE;
+       bool result = false;
        int r_objid;
 
        BUG_ON (!buf || !vb);
@@ -1113,7 +1108,7 @@ static BOOL ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
        r_objid = ldm_relative (buf, len, 0x18, 0);
        if (r_objid < 0) {
                ldm_error ("VBLK header is corrupt.");
-               return FALSE;
+               return false;
        }
 
        vb->flags  = buf[0x12];
@@ -1152,10 +1147,10 @@ static BOOL ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
  *
  * N.B.  This function does not check the validity of the VBLKs.
  *
- * Return:  TRUE   The VBLK was added
- *          FALSE  An error occurred
+ * Return:  'true'   The VBLK was added
+ *          'false'  An error occurred
  */
-static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
+static bool ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
 {
        struct vblk *vb;
        struct list_head *item;
@@ -1165,12 +1160,12 @@ static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
        vb = kmalloc (sizeof (*vb), GFP_KERNEL);
        if (!vb) {
                ldm_crit ("Out of memory.");
-               return FALSE;
+               return false;
        }
 
        if (!ldm_parse_vblk (data, len, vb)) {
                kfree(vb);
-               return FALSE;                   /* Already logged */
+               return false;                   /* Already logged */
        }
 
        /* Put vblk into the correct list. */
@@ -1196,13 +1191,13 @@ static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
                        if ((v->vblk.part.disk_id == vb->vblk.part.disk_id) &&
                            (v->vblk.part.start > vb->vblk.part.start)) {
                                list_add_tail (&vb->list, &v->list);
-                               return TRUE;
+                               return true;
                        }
                }
                list_add_tail (&vb->list, &ldb->v_part);
                break;
        }
-       return TRUE;
+       return true;
 }
 
 /**
@@ -1214,10 +1209,10 @@ static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
  * Fragmented VBLKs may not be consecutive in the database, so they are placed
  * in a list so they can be pieced together later.
  *
- * Return:  TRUE   Success, the VBLK was added to the list
- *          FALSE  Error, a problem occurred
+ * Return:  'true'   Success, the VBLK was added to the list
+ *          'false'  Error, a problem occurred
  */
-static BOOL ldm_frag_add (const u8 *data, int size, struct list_head *frags)
+static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
 {
        struct frag *f;
        struct list_head *item;
@@ -1230,7 +1225,7 @@ static BOOL ldm_frag_add (const u8 *data, int size, struct list_head *frags)
        num   = BE16 (data + 0x0E);
        if ((num < 1) || (num > 4)) {
                ldm_error ("A VBLK claims to have %d parts.", num);
-               return FALSE;
+               return false;
        }
 
        list_for_each (item, frags) {
@@ -1242,7 +1237,7 @@ static BOOL ldm_frag_add (const u8 *data, int size, struct list_head *frags)
        f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL);
        if (!f) {
                ldm_crit ("Out of memory.");
-               return FALSE;
+               return false;
        }
 
        f->group = group;
@@ -1255,7 +1250,7 @@ found:
        if (f->map & (1 << rec)) {
                ldm_error ("Duplicate VBLK, part %d.", rec);
                f->map &= 0x7F;                 /* Mark the group as broken */
-               return FALSE;
+               return false;
        }
 
        f->map |= (1 << rec);
@@ -1266,7 +1261,7 @@ found:
        }
        memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
 
-       return TRUE;
+       return true;
 }
 
 /**
@@ -1295,10 +1290,10 @@ static void ldm_frag_free (struct list_head *list)
  * Now that all the fragmented VBLKs have been collected, they must be added to
  * the database for later use.
  *
- * Return:  TRUE   All the fragments we added successfully
- *          FALSE  One or more of the fragments we invalid
+ * Return:  'true'   All the fragments we added successfully
+ *          'false'  One or more of the fragments we invalid
  */
-static BOOL ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
+static bool ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
 {
        struct frag *f;
        struct list_head *item;
@@ -1311,13 +1306,13 @@ static BOOL ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
                if (f->map != 0xFF) {
                        ldm_error ("VBLK group %d is incomplete (0x%02x).",
                                f->group, f->map);
-                       return FALSE;
+                       return false;
                }
 
                if (!ldm_ldmdb_add (f->data, f->num*ldb->vm.vblk_size, ldb))
-                       return FALSE;           /* Already logged */
+                       return false;           /* Already logged */
        }
-       return TRUE;
+       return true;
 }
 
 /**
@@ -1329,16 +1324,16 @@ static BOOL ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
  * To use the information from the VBLKs, they need to be read from the disk,
  * unpacked and validated.  We cache them in @ldb according to their type.
  *
- * Return:  TRUE   All the VBLKs were read successfully
- *          FALSE  An error occurred
+ * Return:  'true'   All the VBLKs were read successfully
+ *          'false'  An error occurred
  */
-static BOOL ldm_get_vblks (struct block_device *bdev, unsigned long base,
+static bool ldm_get_vblks (struct block_device *bdev, unsigned long base,
                           struct ldmdb *ldb)
 {
        int size, perbuf, skip, finish, s, v, recs;
        u8 *data = NULL;
        Sector sect;
-       BOOL result = FALSE;
+       bool result = false;
        LIST_HEAD (frags);
 
        BUG_ON (!bdev || !ldb);
index 8f12587c3129731fcd92392b41f8c86a9be3c646..4f8df71e49d330038614c4f81a300f477b6f9a95 100644 (file)
@@ -58,6 +58,31 @@ msdos_magic_present(unsigned char *p)
        return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
 }
 
+/* Value is EBCDIC 'IBMA' */
+#define AIX_LABEL_MAGIC1       0xC9
+#define AIX_LABEL_MAGIC2       0xC2
+#define AIX_LABEL_MAGIC3       0xD4
+#define AIX_LABEL_MAGIC4       0xC1
+static int aix_magic_present(unsigned char *p, struct block_device *bdev)
+{
+       Sector sect;
+       unsigned char *d;
+       int ret = 0;
+
+       if (p[0] != AIX_LABEL_MAGIC1 &&
+               p[1] != AIX_LABEL_MAGIC2 &&
+               p[2] != AIX_LABEL_MAGIC3 &&
+               p[3] != AIX_LABEL_MAGIC4)
+               return 0;
+       d = read_dev_sector(bdev, 7, &sect);
+       if (d) {
+               if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
+                       ret = 1;
+               put_dev_sector(sect);
+       };
+       return ret;
+}
+
 /*
  * Create devices for each logical partition in an extended partition.
  * The logical partitions form a linked list, with each entry being
@@ -393,6 +418,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
                return 0;
        }
 
+       if (aix_magic_present(data, bdev)) {
+               put_dev_sector(sect);
+               printk( " [AIX]");
+               return 0;
+       }
+
        /*
         * Now that the 55aa signature is present, this is probably
         * either the boot sector of a FAT filesystem or a DOS-type
index 20352573e025f0fe2574b6ffb300c44fc3605fa9..b1626f269a3445e38f34c1bc338734e0893bbd32 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -218,9 +218,10 @@ static struct pipe_buf_operations anon_pipe_buf_ops = {
 };
 
 static ssize_t
-pipe_readv(struct file *filp, const struct iovec *_iov,
-          unsigned long nr_segs, loff_t *ppos)
+pipe_read(struct kiocb *iocb, const struct iovec *_iov,
+          unsigned long nr_segs, loff_t pos)
 {
+       struct file *filp = iocb->ki_filp;
        struct inode *inode = filp->f_dentry->d_inode;
        struct pipe_inode_info *pipe;
        int do_wakeup;
@@ -330,17 +331,10 @@ redo:
 }
 
 static ssize_t
-pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
-       struct iovec iov = { .iov_base = buf, .iov_len = count };
-
-       return pipe_readv(filp, &iov, 1, ppos);
-}
-
-static ssize_t
-pipe_writev(struct file *filp, const struct iovec *_iov,
-           unsigned long nr_segs, loff_t *ppos)
+pipe_write(struct kiocb *iocb, const struct iovec *_iov,
+           unsigned long nr_segs, loff_t ppos)
 {
+       struct file *filp = iocb->ki_filp;
        struct inode *inode = filp->f_dentry->d_inode;
        struct pipe_inode_info *pipe;
        ssize_t ret;
@@ -509,15 +503,6 @@ out:
        return ret;
 }
 
-static ssize_t
-pipe_write(struct file *filp, const char __user *buf,
-          size_t count, loff_t *ppos)
-{
-       struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
-       return pipe_writev(filp, &iov, 1, ppos);
-}
-
 static ssize_t
 bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
 {
@@ -736,8 +721,8 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
  */
 const struct file_operations read_fifo_fops = {
        .llseek         = no_llseek,
-       .read           = pipe_read,
-       .readv          = pipe_readv,
+       .read           = do_sync_read,
+       .aio_read       = pipe_read,
        .write          = bad_pipe_w,
        .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
@@ -749,8 +734,8 @@ const struct file_operations read_fifo_fops = {
 const struct file_operations write_fifo_fops = {
        .llseek         = no_llseek,
        .read           = bad_pipe_r,
-       .write          = pipe_write,
-       .writev         = pipe_writev,
+       .write          = do_sync_write,
+       .aio_write      = pipe_write,
        .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_write_open,
@@ -760,10 +745,10 @@ const struct file_operations write_fifo_fops = {
 
 const struct file_operations rdwr_fifo_fops = {
        .llseek         = no_llseek,
-       .read           = pipe_read,
-       .readv          = pipe_readv,
-       .write          = pipe_write,
-       .writev         = pipe_writev,
+       .read           = do_sync_read,
+       .aio_read       = pipe_read,
+       .write          = do_sync_write,
+       .aio_write      = pipe_write,
        .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_rdwr_open,
@@ -773,8 +758,8 @@ const struct file_operations rdwr_fifo_fops = {
 
 static struct file_operations read_pipe_fops = {
        .llseek         = no_llseek,
-       .read           = pipe_read,
-       .readv          = pipe_readv,
+       .read           = do_sync_read,
+       .aio_read       = pipe_read,
        .write          = bad_pipe_w,
        .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
@@ -786,8 +771,8 @@ static struct file_operations read_pipe_fops = {
 static struct file_operations write_pipe_fops = {
        .llseek         = no_llseek,
        .read           = bad_pipe_r,
-       .write          = pipe_write,
-       .writev         = pipe_writev,
+       .write          = do_sync_write,
+       .aio_write      = pipe_write,
        .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_write_open,
@@ -797,10 +782,10 @@ static struct file_operations write_pipe_fops = {
 
 static struct file_operations rdwr_pipe_fops = {
        .llseek         = no_llseek,
-       .read           = pipe_read,
-       .readv          = pipe_readv,
-       .write          = pipe_write,
-       .writev         = pipe_writev,
+       .read           = do_sync_read,
+       .aio_read       = pipe_read,
+       .write          = do_sync_write,
+       .aio_write      = pipe_write,
        .poll           = pipe_poll,
        .ioctl          = pipe_ioctl,
        .open           = pipe_rdwr_open,
@@ -879,7 +864,6 @@ static struct inode * get_pipe_inode(void)
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blksize = PAGE_SIZE;
 
        return inode;
 
@@ -890,87 +874,118 @@ fail_inode:
        return NULL;
 }
 
-int do_pipe(int *fd)
+struct file *create_write_pipe(void)
 {
-       struct qstr this;
-       char name[32];
+       int err;
+       struct inode *inode;
+       struct file *f;
        struct dentry *dentry;
-       struct inode * inode;
-       struct file *f1, *f2;
-       int error;
-       int i, j;
-
-       error = -ENFILE;
-       f1 = get_empty_filp();
-       if (!f1)
-               goto no_files;
-
-       f2 = get_empty_filp();
-       if (!f2)
-               goto close_f1;
+       char name[32];
+       struct qstr this;
 
+       f = get_empty_filp();
+       if (!f)
+               return ERR_PTR(-ENFILE);
+       err = -ENFILE;
        inode = get_pipe_inode();
        if (!inode)
-               goto close_f12;
-
-       error = get_unused_fd();
-       if (error < 0)
-               goto close_f12_inode;
-       i = error;
-
-       error = get_unused_fd();
-       if (error < 0)
-               goto close_f12_inode_i;
-       j = error;
+               goto err_file;
 
-       error = -ENOMEM;
        sprintf(name, "[%lu]", inode->i_ino);
        this.name = name;
        this.len = strlen(name);
        this.hash = inode->i_ino; /* will go */
+       err = -ENOMEM;
        dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
        if (!dentry)
-               goto close_f12_inode_i_j;
+               goto err_inode;
 
        dentry->d_op = &pipefs_dentry_operations;
        d_add(dentry, inode);
-       f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
-       f1->f_dentry = f2->f_dentry = dget(dentry);
-       f1->f_mapping = f2->f_mapping = inode->i_mapping;
-
-       /* read file */
-       f1->f_pos = f2->f_pos = 0;
-       f1->f_flags = O_RDONLY;
-       f1->f_op = &read_pipe_fops;
-       f1->f_mode = FMODE_READ;
-       f1->f_version = 0;
-
-       /* write file */
-       f2->f_flags = O_WRONLY;
-       f2->f_op = &write_pipe_fops;
-       f2->f_mode = FMODE_WRITE;
-       f2->f_version = 0;
-
-       fd_install(i, f1);
-       fd_install(j, f2);
-       fd[0] = i;
-       fd[1] = j;
+       f->f_vfsmnt = mntget(pipe_mnt);
+       f->f_dentry = dentry;
+       f->f_mapping = inode->i_mapping;
 
-       return 0;
+       f->f_flags = O_WRONLY;
+       f->f_op = &write_pipe_fops;
+       f->f_mode = FMODE_WRITE;
+       f->f_version = 0;
+
+       return f;
 
-close_f12_inode_i_j:
-       put_unused_fd(j);
-close_f12_inode_i:
-       put_unused_fd(i);
-close_f12_inode:
+ err_inode:
        free_pipe_info(inode);
        iput(inode);
-close_f12:
-       put_filp(f2);
-close_f1:
-       put_filp(f1);
-no_files:
-       return error;   
+ err_file:
+       put_filp(f);
+       return ERR_PTR(err);
+}
+
+void free_write_pipe(struct file *f)
+{
+       mntput(f->f_vfsmnt);
+       dput(f->f_dentry);
+       put_filp(f);
+}
+
+struct file *create_read_pipe(struct file *wrf)
+{
+       struct file *f = get_empty_filp();
+       if (!f)
+               return ERR_PTR(-ENFILE);
+
+       /* Grab pipe from the writer */
+       f->f_vfsmnt = mntget(wrf->f_vfsmnt);
+       f->f_dentry = dget(wrf->f_dentry);
+       f->f_mapping = wrf->f_dentry->d_inode->i_mapping;
+
+       f->f_pos = 0;
+       f->f_flags = O_RDONLY;
+       f->f_op = &read_pipe_fops;
+       f->f_mode = FMODE_READ;
+       f->f_version = 0;
+
+       return f;
+}
+
+int do_pipe(int *fd)
+{
+       struct file *fw, *fr;
+       int error;
+       int fdw, fdr;
+
+       fw = create_write_pipe();
+       if (IS_ERR(fw))
+               return PTR_ERR(fw);
+       fr = create_read_pipe(fw);
+       error = PTR_ERR(fr);
+       if (IS_ERR(fr))
+               goto err_write_pipe;
+
+       error = get_unused_fd();
+       if (error < 0)
+               goto err_read_pipe;
+       fdr = error;
+
+       error = get_unused_fd();
+       if (error < 0)
+               goto err_fdr;
+       fdw = error;
+
+       fd_install(fdr, fr);
+       fd_install(fdw, fw);
+       fd[0] = fdr;
+       fd[1] = fdw;
+
+       return 0;
+
+ err_fdr:
+       put_unused_fd(fdr);
+ err_read_pipe:
+       put_filp(fr);
+ err_write_pipe:
+       free_write_pipe(fw);
+       return error;
 }
 
 /*
index 6c8dcf7613fd89bf903a95b311af8a1eee2bf8ce..aec931e09973716240bf55441622dccf95cf3c74 100644 (file)
@@ -58,11 +58,9 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
        if (acl) {
                int size = sizeof(struct posix_acl) + acl->a_count *
                           sizeof(struct posix_acl_entry);
-               clone = kmalloc(size, flags);
-               if (clone) {
-                       memcpy(clone, acl, size);
+               clone = kmemdup(acl, size, flags);
+               if (clone)
                        atomic_set(&clone->a_refcount, 1);
-               }
        }
        return clone;
 }
index 0b615d62a159b16eb8da4a593b52f4a469f46cc4..c0e554971df01dbac80e057bde18b94e6648faa9 100644 (file)
@@ -347,6 +347,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
        sigemptyset(&sigign);
        sigemptyset(&sigcatch);
        cutime = cstime = utime = stime = cputime_zero;
+
+       mutex_lock(&tty_mutex);
        read_lock(&tasklist_lock);
        if (task->sighand) {
                spin_lock_irq(&task->sighand->siglock);
@@ -388,6 +390,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
        }
        ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
        read_unlock(&tasklist_lock);
+       mutex_unlock(&tty_mutex);
 
        if (!whole || num_threads<2)
                wchan = get_wchan(task);
index fe8d55fb17cc37da251cfd524dfc14dfb1711c72..89c20d9d50bfbf09c77aca8ca921885bb7eb0084 100644 (file)
@@ -797,7 +797,7 @@ out_no_task:
 static ssize_t mem_write(struct file * file, const char * buf,
                         size_t count, loff_t *ppos)
 {
-       int copied = 0;
+       int copied;
        char *page;
        struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
        unsigned long dst = *ppos;
@@ -814,6 +814,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
        if (!page)
                goto out;
 
+       copied = 0;
        while (count > 0) {
                int this_len, retval;
 
index 146a434ba944a89aaf026094755bc3818ba146c4..987c773dbb20a04f002ac03ae5f8ee522ba57cce 100644 (file)
@@ -28,6 +28,7 @@ do {                                          \
        (vmi)->largest_chunk = 0;               \
 } while(0)
 
+extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *);
 #endif
 
 extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f);
index 6a984f64edd7179893887528f07a63f90bf7b15c..1294eda4acaeefc5739bd4ad267a7fca2dd679dd 100644 (file)
@@ -100,7 +100,7 @@ static int notesize(struct memelfnote *en)
        int sz;
 
        sz = sizeof(struct elf_note);
-       sz += roundup(strlen(en->name), 4);
+       sz += roundup((strlen(en->name) + 1), 4);
        sz += roundup(en->datasz, 4);
 
        return sz;
@@ -116,7 +116,7 @@ static char *storenote(struct memelfnote *men, char *bufp)
 
 #define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)
 
-       en.n_namesz = strlen(men->name);
+       en.n_namesz = strlen(men->name) + 1;
        en.n_descsz = men->datasz;
        en.n_type = men->type;
 
@@ -279,12 +279,11 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                tsz = elf_buflen - *fpos;
                if (buflen < tsz)
                        tsz = buflen;
-               elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
+               elf_buf = kzalloc(elf_buflen, GFP_ATOMIC);
                if (!elf_buf) {
                        read_unlock(&kclist_lock);
                        return -ENOMEM;
                }
-               memset(elf_buf, 0, elf_buflen);
                elf_kcore_store_hdr(elf_buf, nphdr, elf_buflen);
                read_unlock(&kclist_lock);
                if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
@@ -330,10 +329,9 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                        unsigned long curstart = start;
                        unsigned long cursize = tsz;
 
-                       elf_buf = kmalloc(tsz, GFP_KERNEL);
+                       elf_buf = kzalloc(tsz, GFP_KERNEL);
                        if (!elf_buf)
                                return -ENOMEM;
-                       memset(elf_buf, 0, tsz);
 
                        read_lock(&vmlist_lock);
                        for (m=vmlist; m && cursize; m=m->next) {
index cff10ab1af630c69aa8d3a9af4f450834f120247..d7dbdf9e0f496adfa70facf0612ca382e41a3462 100644 (file)
 #include "internal.h"
 
 /*
- * display a list of all the VMAs the kernel knows about
- * - nommu kernals have a single flat list
+ * display a single VMA to a sequenced file
  */
-static int nommu_vma_list_show(struct seq_file *m, void *v)
+int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 {
-       struct vm_area_struct *vma;
        unsigned long ino = 0;
        struct file *file;
        dev_t dev = 0;
        int flags, len;
 
-       vma = rb_entry((struct rb_node *) v, struct vm_area_struct, vm_rb);
-
        flags = vma->vm_flags;
        file = vma->vm_file;
 
@@ -78,6 +74,18 @@ static int nommu_vma_list_show(struct seq_file *m, void *v)
        return 0;
 }
 
+/*
+ * display a list of all the VMAs the kernel knows about
+ * - nommu kernals have a single flat list
+ */
+static int nommu_vma_list_show(struct seq_file *m, void *v)
+{
+       struct vm_area_struct *vma;
+
+       vma = rb_entry((struct rb_node *) v, struct vm_area_struct, vm_rb);
+       return nommu_vma_show(m, vma);
+}
+
 static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos)
 {
        struct rb_node *_rb;
index 5bbd60896050545759f4aa603e12cfee9cd63295..66bc425f2f3db467344dd81c841442c5806b985e 100644 (file)
@@ -277,12 +277,15 @@ static int devinfo_show(struct seq_file *f, void *v)
                if (i == 0)
                        seq_printf(f, "Character devices:\n");
                chrdev_show(f, i);
-       } else {
+       }
+#ifdef CONFIG_BLOCK
+       else {
                i -= CHRDEV_MAJOR_HASH_SIZE;
                if (i == 0)
                        seq_printf(f, "\nBlock devices:\n");
                blkdev_show(f, i);
        }
+#endif
        return 0;
 }
 
@@ -355,6 +358,7 @@ static int stram_read_proc(char *page, char **start, off_t off,
 }
 #endif
 
+#ifdef CONFIG_BLOCK
 extern struct seq_operations partitions_op;
 static int partitions_open(struct inode *inode, struct file *file)
 {
@@ -378,6 +382,7 @@ static struct file_operations proc_diskstats_operations = {
        .llseek         = seq_lseek,
        .release        = seq_release,
 };
+#endif
 
 #ifdef CONFIG_MODULES
 extern struct seq_operations modules_op;
@@ -695,7 +700,9 @@ void __init proc_misc_init(void)
                entry->proc_fops = &proc_kmsg_operations;
        create_seq_entry("devices", 0, &proc_devinfo_operations);
        create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+#ifdef CONFIG_BLOCK
        create_seq_entry("partitions", 0, &proc_partitions_operations);
+#endif
        create_seq_entry("stat", 0, &proc_stat_operations);
        create_seq_entry("interrupts", 0, &proc_interrupts_operations);
 #ifdef CONFIG_SLAB
@@ -707,7 +714,9 @@ void __init proc_misc_init(void)
        create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
        create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
        create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
+#ifdef CONFIG_BLOCK
        create_seq_entry("diskstats", 0, &proc_diskstats_operations);
+#endif
 #ifdef CONFIG_MODULES
        create_seq_entry("modules", 0, &proc_modules_operations);
 #endif
index 0a163a4f7764059f7401c8b43cae42ca9c2bef43..6b769afac55a18ff274ef8ed90b2d0510a86804b 100644 (file)
@@ -122,11 +122,6 @@ struct mem_size_stats
        unsigned long private_dirty;
 };
 
-__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
-{
-       return NULL;
-}
-
 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
 {
        struct proc_maps_private *priv = m->private;
index 4616ed50ffcdea037a49111cf3d5f0d53af994c6..091aa8e48e0285f825f513a3ca9daa760edc56d6 100644 (file)
@@ -138,25 +138,63 @@ out:
 }
 
 /*
- * Albert D. Cahalan suggested to fake entries for the traditional
- * sections here.  This might be worth investigating.
+ * display mapping lines for a particular process's /proc/pid/maps
  */
-static int show_map(struct seq_file *m, void *v)
+static int show_map(struct seq_file *m, void *_vml)
 {
-       return 0;
+       struct vm_list_struct *vml = _vml;
+       return nommu_vma_show(m, vml->vma);
 }
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
+       struct proc_maps_private *priv = m->private;
+       struct vm_list_struct *vml;
+       struct mm_struct *mm;
+       loff_t n = *pos;
+
+       /* pin the task and mm whilst we play with them */
+       priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+       if (!priv->task)
+               return NULL;
+
+       mm = get_task_mm(priv->task);
+       if (!mm) {
+               put_task_struct(priv->task);
+               priv->task = NULL;
+               return NULL;
+       }
+
+       down_read(&mm->mmap_sem);
+
+       /* start from the Nth VMA */
+       for (vml = mm->context.vmlist; vml; vml = vml->next)
+               if (n-- == 0)
+                       return vml;
        return NULL;
 }
-static void m_stop(struct seq_file *m, void *v)
+
+static void m_stop(struct seq_file *m, void *_vml)
 {
+       struct proc_maps_private *priv = m->private;
+
+       if (priv->task) {
+               struct mm_struct *mm = priv->task->mm;
+               up_read(&mm->mmap_sem);
+               mmput(mm);
+               put_task_struct(priv->task);
+       }
 }
-static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+
+static void *m_next(struct seq_file *m, void *_vml, loff_t *pos)
 {
-       return NULL;
+       struct vm_list_struct *vml = _vml;
+
+       (*pos)++;
+       return vml ? vml->next : NULL;
 }
-static struct seq_operations proc_pid_maps_op = {
+
+static struct seq_operations proc_pid_maps_ops = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
@@ -165,11 +203,19 @@ static struct seq_operations proc_pid_maps_op = {
 
 static int maps_open(struct inode *inode, struct file *file)
 {
-       int ret;
-       ret = seq_open(file, &proc_pid_maps_op);
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-               m->private = NULL;
+       struct proc_maps_private *priv;
+       int ret = -ENOMEM;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (priv) {
+               priv->pid = proc_pid(inode);
+               ret = seq_open(file, &proc_pid_maps_ops);
+               if (!ret) {
+                       struct seq_file *m = file->private_data;
+                       m->private = priv;
+               } else {
+                       kfree(priv);
+               }
        }
        return ret;
 }
@@ -178,6 +224,6 @@ struct file_operations proc_maps_operations = {
        .open           = maps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_private,
 };
 
index 62af4b1348bda336cfcc90420a6f1b208f7f807f..467e5ac7280e739eb65a3ee63267ef5e46fbef20 100644 (file)
 const struct file_operations qnx4_file_operations =
 {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
        .mmap           = generic_file_mmap,
        .sendfile       = generic_file_sendfile,
 #ifdef CONFIG_QNX4FS_RW
-       .write          = generic_file_write,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .fsync          = qnx4_sync_file,
 #endif
 };
index 5a903491e6972577ef38ee98a1d1c5fb1ddfc1e7..5a41db2a218dedccfad415885fd54727d0c2fade 100644 (file)
@@ -358,11 +358,10 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
        const char *errmsg;
        struct qnx4_sb_info *qs;
 
-       qs = kmalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
+       qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
        if (!qs)
                return -ENOMEM;
        s->s_fs_info = qs;
-       memset(qs, 0, sizeof(struct qnx4_sb_info));
 
        sb_set_blocksize(s, QNX4_BLOCK_SIZE);
 
@@ -497,7 +496,6 @@ static void qnx4_read_inode(struct inode *inode)
        inode->i_ctime.tv_sec   = le32_to_cpu(raw_inode->di_ctime);
        inode->i_ctime.tv_nsec = 0;
        inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);
-       inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
 
        memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE);
        if (S_ISREG(inode->i_mode)) {
@@ -557,9 +555,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(qnx4_inode_cachep))
-               printk(KERN_INFO
-                      "qnx4_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(qnx4_inode_cachep);
 }
 
 static int qnx4_get_sb(struct file_system_type *fs_type,
index c3d83f67154a61c2fe39421d7809a04d4769577b..733cdf01d645365a204f57fbd83ddcdee292e608 100644 (file)
@@ -186,11 +186,10 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
        memset(de->di_fname, 0, sizeof de->di_fname);
        de->di_mode = 0;
        mark_buffer_dirty(bh);
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        mark_inode_dirty(inode);
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-       dir->i_nlink--;
-       mark_inode_dirty(dir);
+       inode_dec_link_count(dir);
        retval = 0;
 
       end_rmdir:
@@ -234,9 +233,8 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry)
        mark_buffer_dirty(bh);
        dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        mark_inode_dirty(dir);
-       inode->i_nlink--;
        inode->i_ctime = dir->i_ctime;
-       mark_inode_dirty(inode);
+       inode_dec_link_count(inode);
        retval = 0;
 
 end_unlink:
index d6a2be826e29880abd0f6873caa2344f88f2c5f8..b9dae76a0b6e2212083efa9ca0281e31661c0375 100644 (file)
@@ -337,6 +337,34 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
        return 0;
 }
 
+/*
+ * look up a superblock on which quota ops will be performed
+ * - use the name of a block device to find the superblock thereon
+ */
+static inline struct super_block *quotactl_block(const char __user *special)
+{
+#ifdef CONFIG_BLOCK
+       struct block_device *bdev;
+       struct super_block *sb;
+       char *tmp = getname(special);
+
+       if (IS_ERR(tmp))
+               return ERR_PTR(PTR_ERR(tmp));
+       bdev = lookup_bdev(tmp);
+       putname(tmp);
+       if (IS_ERR(bdev))
+               return ERR_PTR(PTR_ERR(bdev));
+       sb = get_super(bdev);
+       bdput(bdev);
+       if (!sb)
+               return ERR_PTR(-ENODEV);
+
+       return sb;
+#else
+       return ERR_PTR(-ENODEV);
+#endif
+}
+
 /*
  * This is the system call interface. This communicates with
  * the user-level programs. Currently this only supports diskquota
@@ -347,25 +375,15 @@ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t
 {
        uint cmds, type;
        struct super_block *sb = NULL;
-       struct block_device *bdev;
-       char *tmp;
        int ret;
 
        cmds = cmd >> SUBCMDSHIFT;
        type = cmd & SUBCMDMASK;
 
        if (cmds != Q_SYNC || special) {
-               tmp = getname(special);
-               if (IS_ERR(tmp))
-                       return PTR_ERR(tmp);
-               bdev = lookup_bdev(tmp);
-               putname(tmp);
-               if (IS_ERR(bdev))
-                       return PTR_ERR(bdev);
-               sb = get_super(bdev);
-               bdput(bdev);
-               if (!sb)
-                       return -ENODEV;
+               sb = quotactl_block(special);
+               if (IS_ERR(sb))
+                       return PTR_ERR(sb);
        }
 
        ret = check_quotactl_valid(sb, type, cmds, id);
index 86f14cacf64120569f2fd0ad8e6ee573de98eb4e..0947fb57dcf3425bb4952eb947dd9d3af05bfe2e 100644 (file)
@@ -33,8 +33,10 @@ const struct address_space_operations ramfs_aops = {
 };
 
 const struct file_operations ramfs_file_operations = {
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .fsync          = simple_sync_file,
        .sendfile       = generic_file_sendfile,
index 677139b48e000d0d98100122c851eff5572aa14a..bfe5dbf1002e597a5b0b5ca25cfb9ea411b1c36e 100644 (file)
@@ -36,8 +36,10 @@ const struct address_space_operations ramfs_aops = {
 const struct file_operations ramfs_file_operations = {
        .mmap                   = ramfs_nommu_mmap,
        .get_unmapped_area      = ramfs_nommu_get_unmapped_area,
-       .read                   = generic_file_read,
-       .write                  = generic_file_write,
+       .read                   = do_sync_read,
+       .aio_read               = generic_file_aio_read,
+       .write                  = do_sync_write,
+       .aio_write              = generic_file_aio_write,
        .fsync                  = simple_sync_file,
        .sendfile               = generic_file_sendfile,
        .llseek                 = generic_file_llseek,
index b9677335cc8d8c146c92daaf4e81b308a11121e8..2faf4cdf61b0d126713eb7b7eddb692517730504 100644 (file)
@@ -58,7 +58,6 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &ramfs_aops;
                inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
@@ -76,7 +75,7 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
                        inode->i_fop = &simple_dir_operations;
 
                        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        break;
                case S_IFLNK:
                        inode->i_op = &page_symlink_inode_operations;
@@ -114,7 +113,7 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
        int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
        if (!retval)
-               dir->i_nlink++;
+               inc_nlink(dir);
        return retval;
 }
 
index d4cb3183c99cb9c89ccb5b1bc2f98c4e976087d8..f792000a28e63179ce88fea9bbeba93f48b9dc94 100644 (file)
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/pagemap.h>
+#include "read_write.h"
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
 const struct file_operations generic_ro_fops = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
        .mmap           = generic_file_readonly_mmap,
        .sendfile       = generic_file_sendfile,
 };
@@ -227,14 +229,20 @@ static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
 
 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
 {
+       struct iovec iov = { .iov_base = buf, .iov_len = len };
        struct kiocb kiocb;
        ssize_t ret;
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       while (-EIOCBRETRY ==
-               (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
+       kiocb.ki_left = len;
+
+       for (;;) {
+               ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
+               if (ret != -EIOCBRETRY)
+                       break;
                wait_on_retry_sync_kiocb(&kiocb);
+       }
 
        if (-EIOCBQUEUED == ret)
                ret = wait_on_sync_kiocb(&kiocb);
@@ -279,14 +287,20 @@ EXPORT_SYMBOL(vfs_read);
 
 ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
 {
+       struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
        struct kiocb kiocb;
        ssize_t ret;
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       while (-EIOCBRETRY ==
-              (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
+       kiocb.ki_left = len;
+
+       for (;;) {
+               ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
+               if (ret != -EIOCBRETRY)
+                       break;
                wait_on_retry_sync_kiocb(&kiocb);
+       }
 
        if (-EIOCBQUEUED == ret)
                ret = wait_on_sync_kiocb(&kiocb);
@@ -438,78 +452,155 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
 
 EXPORT_UNUSED_SYMBOL(iov_shorten);  /*  June 2006  */
 
+ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+               unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
+{
+       struct kiocb kiocb;
+       ssize_t ret;
+
+       init_sync_kiocb(&kiocb, filp);
+       kiocb.ki_pos = *ppos;
+       kiocb.ki_left = len;
+       kiocb.ki_nbytes = len;
+
+       for (;;) {
+               ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
+               if (ret != -EIOCBRETRY)
+                       break;
+               wait_on_retry_sync_kiocb(&kiocb);
+       }
+
+       if (ret == -EIOCBQUEUED)
+               ret = wait_on_sync_kiocb(&kiocb);
+       *ppos = kiocb.ki_pos;
+       return ret;
+}
+
+/* Do it by hand, with file-ops */
+ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+               unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
+{
+       struct iovec *vector = iov;
+       ssize_t ret = 0;
+
+       while (nr_segs > 0) {
+               void __user *base;
+               size_t len;
+               ssize_t nr;
+
+               base = vector->iov_base;
+               len = vector->iov_len;
+               vector++;
+               nr_segs--;
+
+               nr = fn(filp, base, len, ppos);
+
+               if (nr < 0) {
+                       if (!ret)
+                               ret = nr;
+                       break;
+               }
+               ret += nr;
+               if (nr != len)
+                       break;
+       }
+
+       return ret;
+}
+
 /* A write operation does a read from user space and vice versa */
 #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
 
+ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
+                             unsigned long nr_segs, unsigned long fast_segs,
+                             struct iovec *fast_pointer,
+                             struct iovec **ret_pointer)
+  {
+       unsigned long seg;
+       ssize_t ret;
+       struct iovec *iov = fast_pointer;
+
+       /*
+        * SuS says "The readv() function *may* fail if the iovcnt argument
+        * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
+        * traditionally returned zero for zero segments, so...
+        */
+       if (nr_segs == 0) {
+               ret = 0;
+               goto out;
+       }
+
+       /*
+        * First get the "struct iovec" from user memory and
+        * verify all the pointers
+        */
+       if (nr_segs > UIO_MAXIOV) {
+               ret = -EINVAL;
+               goto out;
+       }
+       if (nr_segs > fast_segs) {
+               iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+               if (iov == NULL) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+       }
+       if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       /*
+        * According to the Single Unix Specification we should return EINVAL
+        * if an element length is < 0 when cast to ssize_t or if the
+        * total length would overflow the ssize_t return value of the
+        * system call.
+        */
+       ret = 0;
+       for (seg = 0; seg < nr_segs; seg++) {
+               void __user *buf = iov[seg].iov_base;
+               ssize_t len = (ssize_t)iov[seg].iov_len;
+
+               /* see if we we're about to use an invalid len or if
+                * it's about to overflow ssize_t */
+               if (len < 0 || (ret + len < ret)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+               if (unlikely(!access_ok(vrfy_dir(type), buf, len))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret += len;
+       }
+out:
+       *ret_pointer = iov;
+       return ret;
+}
+
 static ssize_t do_readv_writev(int type, struct file *file,
                               const struct iovec __user * uvector,
                               unsigned long nr_segs, loff_t *pos)
 {
-       typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
-       typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
-
        size_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
-       struct iovec *iov=iovstack, *vector;
+       struct iovec *iov = iovstack;
        ssize_t ret;
-       int seg;
        io_fn_t fn;
        iov_fn_t fnv;
 
-       /*
-        * SuS says "The readv() function *may* fail if the iovcnt argument
-        * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
-        * traditionally returned zero for zero segments, so...
-        */
-       ret = 0;
-       if (nr_segs == 0)
+       if (!file->f_op) {
+               ret = -EINVAL;
                goto out;
+       }
 
-       /*
-        * First get the "struct iovec" from user memory and
-        * verify all the pointers
-        */
-       ret = -EINVAL;
-       if (nr_segs > UIO_MAXIOV)
-               goto out;
-       if (!file->f_op)
-               goto out;
-       if (nr_segs > UIO_FASTIOV) {
-               ret = -ENOMEM;
-               iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
-               if (!iov)
-                       goto out;
-       }
-       ret = -EFAULT;
-       if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector)))
+       ret = rw_copy_check_uvector(type, uvector, nr_segs,
+                       ARRAY_SIZE(iovstack), iovstack, &iov);
+       if (ret <= 0)
                goto out;
 
-       /*
-        * Single unix specification:
-        * We should -EINVAL if an element length is not >= 0 and fitting an
-        * ssize_t.  The total length is fitting an ssize_t
-        *
-        * Be careful here because iov_len is a size_t not an ssize_t
-        */
-       tot_len = 0;
-       ret = -EINVAL;
-       for (seg = 0; seg < nr_segs; seg++) {
-               void __user *buf = iov[seg].iov_base;
-               ssize_t len = (ssize_t)iov[seg].iov_len;
-
-               if (len < 0)    /* size_t not fitting an ssize_t .. */
-                       goto out;
-               if (unlikely(!access_ok(vrfy_dir(type), buf, len)))
-                       goto Efault;
-               tot_len += len;
-               if ((ssize_t)tot_len < 0) /* maths overflow on the ssize_t */
-                       goto out;
-       }
-       if (tot_len == 0) {
-               ret = 0;
-               goto out;
-       }
-
+       tot_len = ret;
        ret = rw_verify_area(type, file, pos, tot_len);
        if (ret < 0)
                goto out;
@@ -520,39 +611,18 @@ static ssize_t do_readv_writev(int type, struct file *file,
        fnv = NULL;
        if (type == READ) {
                fn = file->f_op->read;
-               fnv = file->f_op->readv;
+               fnv = file->f_op->aio_read;
        } else {
                fn = (io_fn_t)file->f_op->write;
-               fnv = file->f_op->writev;
+               fnv = file->f_op->aio_write;
        }
-       if (fnv) {
-               ret = fnv(file, iov, nr_segs, pos);
-               goto out;
-       }
-
-       /* Do it by hand, with file-ops */
-       ret = 0;
-       vector = iov;
-       while (nr_segs > 0) {
-               void __user * base;
-               size_t len;
-               ssize_t nr;
 
-               base = vector->iov_base;
-               len = vector->iov_len;
-               vector++;
-               nr_segs--;
-
-               nr = fn(file, base, len, pos);
+       if (fnv)
+               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
+                                               pos, fnv);
+       else
+               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
 
-               if (nr < 0) {
-                       if (!ret) ret = nr;
-                       break;
-               }
-               ret += nr;
-               if (nr != len)
-                       break;
-       }
 out:
        if (iov != iovstack)
                kfree(iov);
@@ -563,9 +633,6 @@ out:
                        fsnotify_modify(file->f_dentry);
        }
        return ret;
-Efault:
-       ret = -EFAULT;
-       goto out;
 }
 
 ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
@@ -573,7 +640,7 @@ ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
 {
        if (!(file->f_mode & FMODE_READ))
                return -EBADF;
-       if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
+       if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
                return -EINVAL;
 
        return do_readv_writev(READ, file, vec, vlen, pos);
@@ -586,7 +653,7 @@ ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
 {
        if (!(file->f_mode & FMODE_WRITE))
                return -EBADF;
-       if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
+       if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
                return -EINVAL;
 
        return do_readv_writev(WRITE, file, vec, vlen, pos);
diff --git a/fs/read_write.h b/fs/read_write.h
new file mode 100644 (file)
index 0000000..d07b954
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file is only for sharing some helpers from read_write.c with compat.c.
+ * Don't use anywhere else.
+ */
+
+
+typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
+               unsigned long, loff_t);
+
+ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+               unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn);
+ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+               unsigned long nr_segs, loff_t *ppos, io_fn_t fn);
index 3a59309f3ca90d9c0a96a834abb7255ecf92de2c..0eb7ac08048471ac4f34a81cd50c1b4ccc32e81d 100644 (file)
@@ -28,7 +28,7 @@ endif
 # will work around it. If any other architecture displays this behavior,
 # add it here.
 ifeq ($(CONFIG_PPC32),y)
-EXTRA_CFLAGS := -O1
+EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1)
 endif
 
 TAGS:
index 4a7dbdee1b6d73f1d1ae8fb44becb0410c6e58d1..1bfae42117ca714d1951a179d26d037f12226767 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
+#include <linux/vmalloc.h>
 #include <linux/reiserfs_fs_sb.h>
 #include <linux/reiserfs_fs_i.h>
 #include <linux/quotaops.h>
@@ -50,16 +51,15 @@ static inline void get_bit_address(struct super_block *s,
 {
        /* It is in the bitmap block number equal to the block
         * number divided by the number of bits in a block. */
-       *bmap_nr = block / (s->s_blocksize << 3);
+       *bmap_nr = block >> (s->s_blocksize_bits + 3);
        /* Within that bitmap block it is located at bit offset *offset. */
        *offset = block & ((s->s_blocksize << 3) - 1);
-       return;
 }
 
 #ifdef CONFIG_REISERFS_CHECK
 int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
 {
-       int i, j;
+       int bmap, offset;
 
        if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
                reiserfs_warning(s,
@@ -68,36 +68,32 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
                return 0;
        }
 
-       /* it can't be one of the bitmap blocks */
-       for (i = 0; i < SB_BMAP_NR(s); i++)
-               if (block == SB_AP_BITMAP(s)[i].bh->b_blocknr) {
+       get_bit_address(s, block, &bmap, &offset);
+
+       /* Old format filesystem? Unlikely, but the bitmaps are all up front so
+        * we need to account for it. */
+       if (unlikely(test_bit(REISERFS_OLD_FORMAT,
+                             &(REISERFS_SB(s)->s_properties)))) {
+               b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1;
+               if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) {
+                       reiserfs_warning(s, "vs: 4019: is_reusable: "
+                                        "bitmap block %lu(%u) can't be freed or reused",
+                                        block, SB_BMAP_NR(s));
+                       return 0;
+               }
+       } else {
+               if (offset == 0) {
                        reiserfs_warning(s, "vs: 4020: is_reusable: "
                                         "bitmap block %lu(%u) can't be freed or reused",
                                         block, SB_BMAP_NR(s));
                        return 0;
                }
-
-       get_bit_address(s, block, &i, &j);
-
-       if (i >= SB_BMAP_NR(s)) {
-               reiserfs_warning(s,
-                                "vs-4030: is_reusable: there is no so many bitmap blocks: "
-                                "block=%lu, bitmap_nr=%d", block, i);
-               return 0;
        }
 
-       if ((bit_value == 0 &&
-            reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) ||
-           (bit_value == 1 &&
-            reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data) == 0)) {
+       if (bmap >= SB_BMAP_NR(s)) {
                reiserfs_warning(s,
-                                "vs-4040: is_reusable: corresponding bit of block %lu does not "
-                                "match required value (i==%d, j==%d) test_bit==%d",
-                                block, i, j, reiserfs_test_le_bit(j,
-                                                                  SB_AP_BITMAP
-                                                                  (s)[i].bh->
-                                                                  b_data));
-
+                                "vs-4030: is_reusable: there is no so many bitmap blocks: "
+                                "block=%lu, bitmap_nr=%d", block, bmap);
                return 0;
        }
 
@@ -141,6 +137,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
 {
        struct super_block *s = th->t_super;
        struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n];
+       struct buffer_head *bh;
        int end, next;
        int org = *beg;
 
@@ -159,22 +156,25 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
                                 bmap_n);
                return 0;
        }
-       if (buffer_locked(bi->bh)) {
-               PROC_INFO_INC(s, scan_bitmap.wait);
-               __wait_on_buffer(bi->bh);
-       }
+
+       bh = reiserfs_read_bitmap_block(s, bmap_n);
+       if (bh == NULL)
+               return 0;
 
        while (1) {
              cont:
-               if (bi->free_count < min)
+               if (bi->free_count < min) {
+                       brelse(bh);
                        return 0;       // No free blocks in this bitmap
+               }
 
                /* search for a first zero bit -- beggining of a window */
                *beg = reiserfs_find_next_zero_le_bit
-                   ((unsigned long *)(bi->bh->b_data), boundary, *beg);
+                   ((unsigned long *)(bh->b_data), boundary, *beg);
 
                if (*beg + min > boundary) {    /* search for a zero bit fails or the rest of bitmap block
                                                 * cannot contain a zero window of minimum size */
+                       brelse(bh);
                        return 0;
                }
 
@@ -183,7 +183,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
                /* first zero bit found; we check next bits */
                for (end = *beg + 1;; end++) {
                        if (end >= *beg + max || end >= boundary
-                           || reiserfs_test_le_bit(end, bi->bh->b_data)) {
+                           || reiserfs_test_le_bit(end, bh->b_data)) {
                                next = end;
                                break;
                        }
@@ -197,12 +197,12 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
                 * (end) points to one bit after the window end */
                if (end - *beg >= min) {        /* it seems we have found window of proper size */
                        int i;
-                       reiserfs_prepare_for_journal(s, bi->bh, 1);
+                       reiserfs_prepare_for_journal(s, bh, 1);
                        /* try to set all blocks used checking are they still free */
                        for (i = *beg; i < end; i++) {
                                /* It seems that we should not check in journal again. */
                                if (reiserfs_test_and_set_le_bit
-                                   (i, bi->bh->b_data)) {
+                                   (i, bh->b_data)) {
                                        /* bit was set by another process
                                         * while we slept in prepare_for_journal() */
                                        PROC_INFO_INC(s, scan_bitmap.stolen);
@@ -214,17 +214,16 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
                                        /* otherwise we clear all bit were set ... */
                                        while (--i >= *beg)
                                                reiserfs_test_and_clear_le_bit
-                                                   (i, bi->bh->b_data);
-                                       reiserfs_restore_prepared_buffer(s,
-                                                                        bi->
-                                                                        bh);
+                                                   (i, bh->b_data);
+                                       reiserfs_restore_prepared_buffer(s, bh);
                                        *beg = org;
                                        /* ... and search again in current block from beginning */
                                        goto cont;
                                }
                        }
                        bi->free_count -= (end - *beg);
-                       journal_mark_dirty(th, s, bi->bh);
+                       journal_mark_dirty(th, s, bh);
+                       brelse(bh);
 
                        /* free block count calculation */
                        reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
@@ -266,9 +265,20 @@ static int bmap_hash_id(struct super_block *s, u32 id)
  */
 static inline int block_group_used(struct super_block *s, u32 id)
 {
-       int bm;
-       bm = bmap_hash_id(s, id);
-       if (SB_AP_BITMAP(s)[bm].free_count > ((s->s_blocksize << 3) * 60 / 100)) {
+       int bm = bmap_hash_id(s, id);
+       struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm];
+
+       /* If we don't have cached information on this bitmap block, we're
+        * going to have to load it later anyway. Loading it here allows us
+        * to make a better decision. This favors long-term performace gain
+        * with a better on-disk layout vs. a short term gain of skipping the
+        * read and potentially having a bad placement. */
+       if (info->first_zero_hint == 0) {
+               struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm);
+               brelse(bh);
+       }
+
+       if (info->free_count > ((s->s_blocksize << 3) * 60 / 100)) {
                return 0;
        }
        return 1;
@@ -373,7 +383,7 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
 {
        struct super_block *s = th->t_super;
        struct reiserfs_super_block *rs;
-       struct buffer_head *sbh;
+       struct buffer_head *sbh, *bmbh;
        struct reiserfs_bitmap_info *apbi;
        int nr, offset;
 
@@ -394,16 +404,21 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
                return;
        }
 
-       reiserfs_prepare_for_journal(s, apbi[nr].bh, 1);
+       bmbh = reiserfs_read_bitmap_block(s, nr);
+       if (!bmbh)
+               return;
+
+       reiserfs_prepare_for_journal(s, bmbh, 1);
 
        /* clear bit for the given block in bit map */
-       if (!reiserfs_test_and_clear_le_bit(offset, apbi[nr].bh->b_data)) {
+       if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) {
                reiserfs_warning(s, "vs-4080: reiserfs_free_block: "
                                 "free_block (%s:%lu)[dev:blocknr]: bit already cleared",
                                 reiserfs_bdevname(s), block);
        }
        apbi[nr].free_count++;
-       journal_mark_dirty(th, s, apbi[nr].bh);
+       journal_mark_dirty(th, s, bmbh);
+       brelse(bmbh);
 
        reiserfs_prepare_for_journal(s, sbh, 1);
        /* update super block */
@@ -1019,7 +1034,6 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
        b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
        int passno = 0;
        int nr_allocated = 0;
-       int bigalloc = 0;
 
        determine_prealloc_size(hint);
        if (!hint->formatted_node) {
@@ -1046,28 +1060,9 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
                                hint->preallocate = hint->prealloc_size = 0;
                }
                /* for unformatted nodes, force large allocations */
-               bigalloc = amount_needed;
        }
 
        do {
-               /* in bigalloc mode, nr_allocated should stay zero until
-                * the entire allocation is filled
-                */
-               if (unlikely(bigalloc && nr_allocated)) {
-                       reiserfs_warning(s, "bigalloc is %d, nr_allocated %d\n",
-                                        bigalloc, nr_allocated);
-                       /* reset things to a sane value */
-                       bigalloc = amount_needed - nr_allocated;
-               }
-               /*
-                * try pass 0 and pass 1 looking for a nice big
-                * contiguous allocation.  Then reset and look
-                * for anything you can find.
-                */
-               if (passno == 2 && bigalloc) {
-                       passno = 0;
-                       bigalloc = 0;
-               }
                switch (passno++) {
                case 0: /* Search from hint->search_start to end of disk */
                        start = hint->search_start;
@@ -1105,8 +1100,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
                                                                 new_blocknrs +
                                                                 nr_allocated,
                                                                 start, finish,
-                                                                bigalloc ?
-                                                                bigalloc : 1,
+                                                                1,
                                                                 amount_needed -
                                                                 nr_allocated,
                                                                 hint->
@@ -1263,3 +1257,89 @@ int reiserfs_can_fit_pages(struct super_block *sb        /* superblock of filesystem
 
        return space > 0 ? space : 0;
 }
+
+void reiserfs_cache_bitmap_metadata(struct super_block *sb,
+                                    struct buffer_head *bh,
+                                    struct reiserfs_bitmap_info *info)
+{
+       unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size);
+
+       info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3);
+
+       while (--cur >= (unsigned long *)bh->b_data) {
+               int base = ((char *)cur - bh->b_data) << 3;
+
+               /* 0 and ~0 are special, we can optimize for them */
+               if (*cur == 0) {
+                       info->first_zero_hint = base;
+                       info->free_count += BITS_PER_LONG;
+               } else if (*cur != ~0L) {       /* A mix, investigate */
+                       int b;
+                       for (b = BITS_PER_LONG - 1; b >= 0; b--) {
+                               if (!reiserfs_test_le_bit(b, cur)) {
+                                       info->first_zero_hint = base + b;
+                                       info->free_count++;
+                               }
+                       }
+               }
+       }
+       /* The first bit must ALWAYS be 1 */
+       BUG_ON(info->first_zero_hint == 0);
+}
+
+struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
+                                               unsigned int bitmap)
+{
+       b_blocknr_t block = (sb->s_blocksize << 3) * bitmap;
+       struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap;
+       struct buffer_head *bh;
+
+       /* Way old format filesystems had the bitmaps packed up front.
+        * I doubt there are any of these left, but just in case... */
+       if (unlikely(test_bit(REISERFS_OLD_FORMAT,
+                             &(REISERFS_SB(sb)->s_properties))))
+               block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap;
+       else if (bitmap == 0)
+               block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
+
+       bh = sb_bread(sb, block);
+       if (bh == NULL)
+               reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%lu) "
+                                "reading failed", __FUNCTION__, bh->b_blocknr);
+       else {
+               if (buffer_locked(bh)) {
+                       PROC_INFO_INC(sb, scan_bitmap.wait);
+                       __wait_on_buffer(bh);
+               }
+               BUG_ON(!buffer_uptodate(bh));
+               BUG_ON(atomic_read(&bh->b_count) == 0);
+
+               if (info->first_zero_hint == 0)
+                       reiserfs_cache_bitmap_metadata(sb, bh, info);
+       }
+
+       return bh;
+}
+
+int reiserfs_init_bitmap_cache(struct super_block *sb)
+{
+       struct reiserfs_bitmap_info *bitmap;
+
+       bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb));
+       if (bitmap == NULL)
+               return -ENOMEM;
+
+       memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb));
+
+       SB_AP_BITMAP(sb) = bitmap;
+
+       return 0;
+}
+
+void reiserfs_free_bitmap_cache(struct super_block *sb)
+{
+       if (SB_AP_BITMAP(sb)) {
+               vfree(SB_AP_BITMAP(sb));
+               SB_AP_BITMAP(sb) = NULL;
+       }
+}
index 9aabcc0ccd2d002401e7611a93f5f6b8458136c0..657050ad7430e68777a326c18fad5a4d8a04cefb 100644 (file)
@@ -22,6 +22,9 @@ const struct file_operations reiserfs_dir_operations = {
        .readdir = reiserfs_readdir,
        .fsync = reiserfs_dir_fsync,
        .ioctl = reiserfs_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = reiserfs_compat_ioctl,
+#endif
 };
 
 static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
index 1627edd50810b94df2f4003479092022c9952d9d..41f24369e47a0945e67fd52a10fa3bcabc357943 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
+#include <linux/config.h>
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
@@ -130,7 +131,7 @@ static int reiserfs_sync_file(struct file *p_s_filp,
        reiserfs_write_lock(p_s_inode->i_sb);
        barrier_done = reiserfs_commit_for_inode(p_s_inode);
        reiserfs_write_unlock(p_s_inode->i_sb);
-       if (barrier_done != 1)
+       if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb))
                blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
        if (barrier_done < 0)
                return barrier_done;
@@ -1333,7 +1334,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
                        if (err)
                                return err;
                }
-               result = generic_file_write(file, buf, count, ppos);
+               result = do_sync_write(file, buf, count, ppos);
 
                if (after_file_end) {   /* Now update i_size and remove the savelink */
                        struct reiserfs_transaction_handle th;
@@ -1565,10 +1566,14 @@ static ssize_t reiserfs_file_write(struct file *file,   /* the file we are going t
 }
 
 const struct file_operations reiserfs_file_operations = {
-       .read = generic_file_read,
+       .read = do_sync_read,
        .write = reiserfs_file_write,
        .ioctl = reiserfs_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = reiserfs_compat_ioctl,
+#endif
        .mmap = generic_file_mmap,
+       .open = generic_file_open,
        .release = reiserfs_file_release,
        .fsync = reiserfs_sync_file,
        .sendfile = generic_file_sendfile,
index 52f1e2136546f215f7bd13ea403735222a621e46..7e5a2f5ebeb0fc19e120a5d9f29c00c37b89624f 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/writeback.h>
 #include <linux/quotaops.h>
 
-extern int reiserfs_default_io_size;   /* default io size devuned in super.c */
-
 static int reiserfs_commit_write(struct file *f, struct page *page,
                                 unsigned from, unsigned to);
 static int reiserfs_prepare_write(struct file *f, struct page *page,
@@ -1122,7 +1120,6 @@ static void init_inode(struct inode *inode, struct path *path)
        ih = PATH_PITEM_HEAD(path);
 
        copy_key(INODE_PKEY(inode), &(ih->ih_key));
-       inode->i_blksize = reiserfs_default_io_size;
 
        INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list));
        REISERFS_I(inode)->i_flags = 0;
@@ -1130,9 +1127,9 @@ static void init_inode(struct inode *inode, struct path *path)
        REISERFS_I(inode)->i_prealloc_count = 0;
        REISERFS_I(inode)->i_trans_id = 0;
        REISERFS_I(inode)->i_jl = NULL;
-       REISERFS_I(inode)->i_acl_access = NULL;
-       REISERFS_I(inode)->i_acl_default = NULL;
-       init_rwsem(&REISERFS_I(inode)->xattr_sem);
+       reiserfs_init_acl_access(inode);
+       reiserfs_init_acl_default(inode);
+       reiserfs_init_xattr_rwsem(inode);
 
        if (stat_data_v1(ih)) {
                struct stat_data_v1 *sd =
@@ -1837,9 +1834,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        REISERFS_I(inode)->i_attrs =
            REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
        sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
-       REISERFS_I(inode)->i_acl_access = NULL;
-       REISERFS_I(inode)->i_acl_default = NULL;
-       init_rwsem(&REISERFS_I(inode)->xattr_sem);
+       reiserfs_init_acl_access(inode);
+       reiserfs_init_acl_default(inode);
+       reiserfs_init_xattr_rwsem(inode);
 
        if (old_format_only(sb))
                make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET,
@@ -1877,7 +1874,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        }
        // these do not go to on-disk stat data
        inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid);
-       inode->i_blksize = reiserfs_default_io_size;
 
        // store in in-core inode the key of stat data and version all
        // object items will have (directory items will have old offset
@@ -1978,11 +1974,13 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
         * iput doesn't deadlock in reiserfs_delete_xattrs. The locking
         * code really needs to be reworked, but this will take care of it
         * for now. -jeffm */
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
        if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) {
                reiserfs_write_unlock_xattrs(dir->i_sb);
                iput(inode);
                reiserfs_write_lock_xattrs(dir->i_sb);
        } else
+#endif
                iput(inode);
        return err;
 }
index a986b5e1e288c8dd47eca5ea525c9cfe2fc26b77..9c57578cb831a2f869c7e277896b04b06a369c80 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/uaccess.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
+#include <linux/compat.h>
 
 static int reiserfs_unpack(struct inode *inode, struct file *filp);
 
@@ -94,6 +95,40 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        }
 }
 
+#ifdef CONFIG_COMPAT
+long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       int ret;
+
+       /* These are just misnamed, they actually get/put from/to user an int */
+       switch (cmd) {
+       case REISERFS_IOC32_UNPACK:
+               cmd = REISERFS_IOC_UNPACK;
+               break;
+       case REISERFS_IOC32_GETFLAGS:
+               cmd = REISERFS_IOC_GETFLAGS;
+               break;
+       case REISERFS_IOC32_SETFLAGS:
+               cmd = REISERFS_IOC_SETFLAGS;
+               break;
+       case REISERFS_IOC32_GETVERSION:
+               cmd = REISERFS_IOC_GETVERSION;
+               break;
+       case REISERFS_IOC32_SETVERSION:
+               cmd = REISERFS_IOC_SETVERSION;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       lock_kernel();
+       ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+       unlock_kernel();
+       return ret;
+}
+#endif
+
 /*
 ** reiserfs_unpack
 ** Function try to convert tail from direct item into indirect.
index 9b3672d69367251b6109c6550c5e8e7f81986634..e6b5ccf23f152178eb2981423ae3218f1abab6c0 100644 (file)
@@ -1186,6 +1186,21 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct
        return NULL;
 }
 
+static int newer_jl_done(struct reiserfs_journal_cnode *cn)
+{
+       struct super_block *sb = cn->sb;
+       b_blocknr_t blocknr = cn->blocknr;
+
+       cn = cn->hprev;
+       while (cn) {
+               if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist &&
+                   atomic_read(&cn->jlist->j_commit_left) != 0)
+                                   return 0;
+               cn = cn->hprev;
+       }
+       return 1;
+}
+
 static void remove_journal_hash(struct super_block *,
                                struct reiserfs_journal_cnode **,
                                struct reiserfs_journal_list *, unsigned long,
@@ -1604,6 +1619,31 @@ static int flush_journal_list(struct super_block *s,
        return err;
 }
 
+static int test_transaction(struct super_block *s,
+                            struct reiserfs_journal_list *jl)
+{
+       struct reiserfs_journal_cnode *cn;
+
+       if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0)
+               return 1;
+
+       cn = jl->j_realblock;
+       while (cn) {
+               /* if the blocknr == 0, this has been cleared from the hash,
+                ** skip it
+                */
+               if (cn->blocknr == 0) {
+                       goto next;
+               }
+               if (cn->bh && !newer_jl_done(cn))
+                       return 0;
+             next:
+               cn = cn->next;
+               cond_resched();
+       }
+       return 0;
+}
+
 static int write_one_transaction(struct super_block *s,
                                 struct reiserfs_journal_list *jl,
                                 struct buffer_chunk *chunk)
@@ -3433,16 +3473,6 @@ static void flush_async_commits(void *p)
                flush_commit_list(p_s_sb, jl, 1);
        }
        unlock_kernel();
-       /*
-        * this is a little racey, but there's no harm in missing
-        * the filemap_fdata_write
-        */
-       if (!atomic_read(&journal->j_async_throttle)
-           && !reiserfs_is_journal_aborted(journal)) {
-               atomic_inc(&journal->j_async_throttle);
-               filemap_fdatawrite(p_s_sb->s_bdev->bd_inode->i_mapping);
-               atomic_dec(&journal->j_async_throttle);
-       }
 }
 
 /*
@@ -3844,7 +3874,9 @@ static void flush_old_journal_lists(struct super_block *s)
                entry = journal->j_journal_list.next;
                jl = JOURNAL_LIST_ENTRY(entry);
                /* this check should always be run, to send old lists to disk */
-               if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4))) {
+               if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) &&
+                   atomic_read(&jl->j_commit_left) == 0 &&
+                   test_transaction(s, jl)) {
                        flush_used_journal_lists(s, jl);
                } else {
                        break;
index c61710e49c6244e9559cb0f1b0fb92e24442d59f..16e9cff8f15de9e2884079adb426a3f476445be8 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/smp_lock.h>
 #include <linux/quotaops.h>
 
-#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
-#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) i->i_nlink--;
+#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; }
+#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
 
 // directory item contains array of entry headers. This performs
 // binary search through that array
@@ -913,7 +913,7 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
                reiserfs_warning(inode->i_sb, "%s: empty directory has nlink "
                                 "!= 2 (%d)", __FUNCTION__, inode->i_nlink);
 
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
        reiserfs_update_sd(&th, inode);
 
@@ -994,7 +994,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
                inode->i_nlink = 1;
        }
 
-       inode->i_nlink--;
+       drop_nlink(inode);
 
        /*
         * we schedule before doing the add_save_link call, save the link
@@ -1006,7 +1006,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
            reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL,
                                   0);
        if (retval < 0) {
-               inode->i_nlink++;
+               inc_nlink(inode);
                goto end_unlink;
        }
        inode->i_ctime = CURRENT_TIME_SEC;
@@ -1143,7 +1143,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
        }
 
        /* inc before scheduling so reiserfs_unlink knows we are here */
-       inode->i_nlink++;
+       inc_nlink(inode);
 
        retval = journal_begin(&th, dir->i_sb, jbegin_count);
        if (retval) {
@@ -1473,9 +1473,9 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (new_dentry_inode) {
                // adjust link number of the victim
                if (S_ISDIR(new_dentry_inode->i_mode)) {
-                       new_dentry_inode->i_nlink = 0;
+                       clear_nlink(new_dentry_inode);
                } else {
-                       new_dentry_inode->i_nlink--;
+                       drop_nlink(new_dentry_inode);
                }
                new_dentry_inode->i_ctime = ctime;
                savelink = new_dentry_inode->i_nlink;
index 39cc7f47f5dc57686469302c9ba75e3289d1360f..315684793d1d8d0ff6b61ec08c4e9a5e4dc75d22 100644 (file)
@@ -22,6 +22,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
        int err = 0;
        struct reiserfs_super_block *sb;
        struct reiserfs_bitmap_info *bitmap;
+       struct reiserfs_bitmap_info *info;
        struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s);
        struct buffer_head *bh;
        struct reiserfs_transaction_handle th;
@@ -127,16 +128,20 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
                 * transaction begins, and the new bitmaps don't matter if the
                 * transaction fails. */
                for (i = bmap_nr; i < bmap_nr_new; i++) {
-                       bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8);
-                       memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb));
-                       reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data);
-
-                       set_buffer_uptodate(bitmap[i].bh);
-                       mark_buffer_dirty(bitmap[i].bh);
-                       sync_dirty_buffer(bitmap[i].bh);
+                       /* don't use read_bitmap_block since it will cache
+                        * the uninitialized bitmap */
+                       bh = sb_bread(s, i * s->s_blocksize * 8);
+                       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);
+
+                       set_buffer_uptodate(bh);
+                       mark_buffer_dirty(bh);
+                       sync_dirty_buffer(bh);
                        // update bitmap_info stuff
                        bitmap[i].first_zero_hint = 1;
                        bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
+                       brelse(bh);
                }
                /* free old bitmap blocks array */
                SB_AP_BITMAP(s) = bitmap;
@@ -150,30 +155,46 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
        if (err)
                return err;
 
-       /* correct last bitmap blocks in old and new disk layout */
-       reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1);
+       /* Extend old last bitmap block - new blocks have been made available */
+       info = SB_AP_BITMAP(s) + bmap_nr - 1;
+       bh = reiserfs_read_bitmap_block(s, bmap_nr - 1);
+       if (!bh) {
+               int jerr = journal_end(&th, s, 10);
+               if (jerr)
+                       return jerr;
+               return -EIO;
+       }
+
+       reiserfs_prepare_for_journal(s, bh, 1);
        for (i = block_r; i < s->s_blocksize * 8; i++)
-               reiserfs_test_and_clear_le_bit(i,
-                                              SB_AP_BITMAP(s)[bmap_nr -
-                                                              1].bh->b_data);
-       SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r;
-       if (!SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint)
-               SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r;
+               reiserfs_test_and_clear_le_bit(i, bh->b_data);
+       info->free_count += s->s_blocksize * 8 - block_r;
+       if (!info->first_zero_hint)
+               info->first_zero_hint = block_r;
 
-       journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh);
+       journal_mark_dirty(&th, s, bh);
+       brelse(bh);
+
+       /* Correct new last bitmap block - It may not be full */
+       info = SB_AP_BITMAP(s) + bmap_nr_new - 1;
+       bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1);
+       if (!bh) {
+               int jerr = journal_end(&th, s, 10);
+               if (jerr)
+                       return jerr;
+               return -EIO;
+       }
 
-       reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1);
+       reiserfs_prepare_for_journal(s, bh, 1);
        for (i = block_r_new; i < s->s_blocksize * 8; i++)
-               reiserfs_test_and_set_le_bit(i,
-                                            SB_AP_BITMAP(s)[bmap_nr_new -
-                                                            1].bh->b_data);
-       journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh);
+               reiserfs_test_and_set_le_bit(i, bh->b_data);
+       journal_mark_dirty(&th, s, bh);
+       brelse(bh);
 
-       SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -=
-           s->s_blocksize * 8 - block_r_new;
+       info->free_count -= s->s_blocksize * 8 - block_r_new;
        /* Extreme case where last bitmap is the only valid block in itself. */
-       if (!SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count)
-               SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0;
+       if (!info->free_count)
+               info->first_zero_hint = 0;
        /* update super */
        reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
        free_blocks = SB_FREE_BLOCKS(s);
index 5567328f10415c85fbbe068672ed85a5f7ad0ead..c89aa2338191af86e6299496e18882756ccb78d2 100644 (file)
@@ -432,7 +432,6 @@ int remove_save_link(struct inode *inode, int truncate)
 
 static void reiserfs_put_super(struct super_block *s)
 {
-       int i;
        struct reiserfs_transaction_handle th;
        th.t_trans_id = 0;
 
@@ -462,10 +461,7 @@ static void reiserfs_put_super(struct super_block *s)
         */
        journal_release(&th, s);
 
-       for (i = 0; i < SB_BMAP_NR(s); i++)
-               brelse(SB_AP_BITMAP(s)[i].bh);
-
-       vfree(SB_AP_BITMAP(s));
+       reiserfs_free_bitmap_cache(s);
 
        brelse(SB_BUFFER_WITH_SB(s));
 
@@ -510,8 +506,10 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
            SLAB_CTOR_CONSTRUCTOR) {
                INIT_LIST_HEAD(&ei->i_prealloc_list);
                inode_init_once(&ei->vfs_inode);
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
                ei->i_acl_access = NULL;
                ei->i_acl_default = NULL;
+#endif
        }
 }
 
@@ -530,9 +528,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(reiserfs_inode_cachep))
-               reiserfs_warning(NULL,
-                                "reiserfs_inode_cache: not all structures were freed");
+       kmem_cache_destroy(reiserfs_inode_cachep);
 }
 
 /* we don't mark inodes dirty, we just log them */
@@ -562,6 +558,7 @@ static void reiserfs_dirty_inode(struct inode *inode)
        reiserfs_write_unlock(inode->i_sb);
 }
 
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 static void reiserfs_clear_inode(struct inode *inode)
 {
        struct posix_acl *acl;
@@ -576,6 +573,9 @@ static void reiserfs_clear_inode(struct inode *inode)
                posix_acl_release(acl);
        REISERFS_I(inode)->i_acl_default = NULL;
 }
+#else
+#define reiserfs_clear_inode NULL
+#endif
 
 #ifdef CONFIG_QUOTA
 static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
@@ -725,12 +725,6 @@ static const arg_desc_t error_actions[] = {
        {NULL, 0, 0},
 };
 
-int reiserfs_default_io_size = 128 * 1024;     /* Default recommended I/O size is 128k.
-                                                  There might be broken applications that are
-                                                  confused by this. Use nolargeio mount option
-                                                  to get usual i/o size = PAGE_SIZE.
-                                                */
-
 /* proceed only one option from a list *cur - string containing of mount options
    opts - array of options which are accepted
    opt_arg - if option is found and requires an argument and if it is specifed
@@ -959,19 +953,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options,    /* strin
                }
 
                if (c == 'w') {
-                       char *p = NULL;
-                       int val = simple_strtoul(arg, &p, 0);
-
-                       if (*p != '\0') {
-                               reiserfs_warning(s,
-                                                "reiserfs_parse_options: non-numeric value %s for nolargeio option",
-                                                arg);
-                               return 0;
-                       }
-                       if (val)
-                               reiserfs_default_io_size = PAGE_SIZE;
-                       else
-                               reiserfs_default_io_size = 128 * 1024;
+                       reiserfs_warning(s, "reiserfs: nolargeio option is no longer supported");
+                       return 0;
                }
 
                if (c == 'j') {
@@ -1256,118 +1239,6 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        return 0;
 }
 
-/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
- * @sb - superblock for this filesystem
- * @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
- *
- * This routine counts how many free bits there are, finding the first zero
- * as a side effect. Could also be implemented as a loop of test_bit() calls, or
- * a loop of find_first_zero_bit() calls. This implementation is similar to
- * find_first_zero_bit(), but doesn't return after it finds the first bit.
- * Should only be called on fs mount, but should be fairly efficient anyways.
- *
- * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
- * will * invariably occupt block 0 represented in the bitmap. The only
- * exception to this is when free_count also == 0, since there will be no
- * free blocks at all.
- */
-
-static void load_bitmap_info_data(struct super_block *sb,
-                                 struct reiserfs_bitmap_info *bi)
-{
-       unsigned long *cur = (unsigned long *)bi->bh->b_data;
-
-       while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
-
-               /* No need to scan if all 0's or all 1's.
-                * Since we're only counting 0's, we can simply ignore all 1's */
-               if (*cur == 0) {
-                       if (bi->first_zero_hint == 0) {
-                               bi->first_zero_hint =
-                                   ((char *)cur - bi->bh->b_data) << 3;
-                       }
-                       bi->free_count += sizeof(unsigned long) * 8;
-               } else if (*cur != ~0L) {
-                       int b;
-                       for (b = 0; b < sizeof(unsigned long) * 8; b++) {
-                               if (!reiserfs_test_le_bit(b, cur)) {
-                                       bi->free_count++;
-                                       if (bi->first_zero_hint == 0)
-                                               bi->first_zero_hint =
-                                                   (((char *)cur -
-                                                     bi->bh->b_data) << 3) + b;
-                               }
-                       }
-               }
-               cur++;
-       }
-
-#ifdef CONFIG_REISERFS_CHECK
-// This outputs a lot of unneded info on big FSes
-//    reiserfs_warning ("bitmap loaded from block %d: %d free blocks",
-//                    bi->bh->b_blocknr, bi->free_count);
-#endif
-}
-
-static int read_bitmaps(struct super_block *s)
-{
-       int i, bmap_nr;
-
-       SB_AP_BITMAP(s) =
-           vmalloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
-       if (SB_AP_BITMAP(s) == 0)
-               return 1;
-       memset(SB_AP_BITMAP(s), 0,
-              sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
-       for (i = 0, bmap_nr =
-            REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
-            i < SB_BMAP_NR(s); i++, bmap_nr = s->s_blocksize * 8 * i) {
-               SB_AP_BITMAP(s)[i].bh = sb_getblk(s, bmap_nr);
-               if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
-                       ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);
-       }
-       for (i = 0; i < SB_BMAP_NR(s); i++) {
-               wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
-               if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
-                       reiserfs_warning(s, "sh-2029: reiserfs read_bitmaps: "
-                                        "bitmap block (#%lu) reading failed",
-                                        SB_AP_BITMAP(s)[i].bh->b_blocknr);
-                       for (i = 0; i < SB_BMAP_NR(s); i++)
-                               brelse(SB_AP_BITMAP(s)[i].bh);
-                       vfree(SB_AP_BITMAP(s));
-                       SB_AP_BITMAP(s) = NULL;
-                       return 1;
-               }
-               load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
-       }
-       return 0;
-}
-
-static int read_old_bitmaps(struct super_block *s)
-{
-       int i;
-       struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
-       int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1;    /* first of bitmap blocks */
-
-       /* read true bitmap */
-       SB_AP_BITMAP(s) =
-           vmalloc(sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
-       if (SB_AP_BITMAP(s) == 0)
-               return 1;
-
-       memset(SB_AP_BITMAP(s), 0,
-              sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
-
-       for (i = 0; i < sb_bmap_nr(rs); i++) {
-               SB_AP_BITMAP(s)[i].bh = sb_bread(s, bmp1 + i);
-               if (!SB_AP_BITMAP(s)[i].bh)
-                       return 1;
-               load_bitmap_info_data(s, SB_AP_BITMAP(s) + i);
-       }
-
-       return 0;
-}
-
 static int read_super_block(struct super_block *s, int offset)
 {
        struct buffer_head *bh;
@@ -1469,7 +1340,6 @@ static int read_super_block(struct super_block *s, int offset)
 /* after journal replay, reread all bitmap and super blocks */
 static int reread_meta_blocks(struct super_block *s)
 {
-       int i;
        ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
        wait_on_buffer(SB_BUFFER_WITH_SB(s));
        if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
@@ -1478,20 +1348,7 @@ static int reread_meta_blocks(struct super_block *s)
                return 1;
        }
 
-       for (i = 0; i < SB_BMAP_NR(s); i++) {
-               ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh));
-               wait_on_buffer(SB_AP_BITMAP(s)[i].bh);
-               if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
-                       reiserfs_warning(s,
-                                        "reread_meta_blocks, error reading bitmap block number %d at %llu",
-                                        i,
-                                        (unsigned long long)SB_AP_BITMAP(s)[i].
-                                        bh->b_blocknr);
-                       return 1;
-               }
-       }
        return 0;
-
 }
 
 /////////////////////////////////////////////////////
@@ -1672,7 +1529,6 @@ static int function2code(hashf_t func)
 static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 {
        struct inode *root_inode;
-       int j;
        struct reiserfs_transaction_handle th;
        int old_format = 0;
        unsigned long blocks;
@@ -1749,7 +1605,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        sbi->s_mount_state = SB_REISERFS_STATE(s);
        sbi->s_mount_state = REISERFS_VALID_FS;
 
-       if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) {
+       if ((errval = reiserfs_init_bitmap_cache(s))) {
                SWARN(silent, s,
                      "jmacd-8: reiserfs_fill_super: unable to read bitmap");
                goto error;
@@ -1831,6 +1687,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        if (is_reiserfs_3_5(rs)
            || (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1))
                set_bit(REISERFS_3_5, &(sbi->s_properties));
+       else if (old_format)
+               set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties));
        else
                set_bit(REISERFS_3_6, &(sbi->s_properties));
 
@@ -1916,19 +1774,17 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        if (jinit_done) {       /* kill the commit thread, free journal ram */
                journal_release_error(NULL, s);
        }
-       if (SB_DISK_SUPER_BLOCK(s)) {
-               for (j = 0; j < SB_BMAP_NR(s); j++) {
-                       if (SB_AP_BITMAP(s))
-                               brelse(SB_AP_BITMAP(s)[j].bh);
-               }
-               vfree(SB_AP_BITMAP(s));
-       }
+
+       reiserfs_free_bitmap_cache(s);
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
 #ifdef CONFIG_QUOTA
-       for (j = 0; j < MAXQUOTAS; j++) {
-               kfree(sbi->s_qf_names[j]);
-               sbi->s_qf_names[j] = NULL;
+       {
+               int j;
+               for (j = 0; j < MAXQUOTAS; j++) {
+                       kfree(sbi->s_qf_names[j]);
+                       sbi->s_qf_names[j] = NULL;
+               }
        }
 #endif
        kfree(sbi);
index 22eed61ebf693dd70c51c1bebe1938d2ffb0f528..ddcd9e1ef2828a52e91e1d5a71754509dc5f8dbb 100644 (file)
@@ -589,8 +589,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(romfs_inode_cachep))
-               printk(KERN_INFO "romfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(romfs_inode_cachep);
 }
 
 static int romfs_remount(struct super_block *sb, int *flags, char *data)
index 33b72ba0f86f45790bd7661053266cd8336c9757..dcbc1112b7ec214c063eaf5786bb17d5f208e6b0 100644 (file)
@@ -658,8 +658,6 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
        unsigned int i;
        struct poll_list *head;
        struct poll_list *walk;
-       struct fdtable *fdt;
-       int max_fdset;
        /* Allocate small arguments on the stack to save memory and be
           faster - use long to make sure the buffer is aligned properly
           on 64 bit archs to avoid unaligned access */
@@ -667,11 +665,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
        struct poll_list *stack_pp = NULL;
 
        /* Do a sanity check on nfds ... */
-       rcu_read_lock();
-       fdt = files_fdtable(current->files);
-       max_fdset = fdt->max_fdset;
-       rcu_read_unlock();
-       if (nfds > max_fdset && nfds > OPEN_MAX)
+       if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
                return -EINVAL;
 
        poll_initwait(&table);
index dae67048baba345fcbd6358e4a84fd890f834633..50784d13c87b55a542d9db3dce156ede054b5a1a 100644 (file)
@@ -214,13 +214,15 @@ smb_updatepage(struct file *file, struct page *page, unsigned long offset,
 }
 
 static ssize_t
-smb_file_read(struct file * file, char __user * buf, size_t count, loff_t *ppos)
+smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                       unsigned long nr_segs, loff_t pos)
 {
+       struct file * file = iocb->ki_filp;
        struct dentry * dentry = file->f_dentry;
        ssize_t status;
 
        VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
-               (unsigned long) count, (unsigned long) *ppos);
+               (unsigned long) iocb->ki_left, (unsigned long) pos);
 
        status = smb_revalidate_inode(dentry);
        if (status) {
@@ -233,7 +235,7 @@ smb_file_read(struct file * file, char __user * buf, size_t count, loff_t *ppos)
                (long)dentry->d_inode->i_size,
                dentry->d_inode->i_flags, dentry->d_inode->i_atime);
 
-       status = generic_file_read(file, buf, count, ppos);
+       status = generic_file_aio_read(iocb, iov, nr_segs, pos);
 out:
        return status;
 }
@@ -317,14 +319,16 @@ const struct address_space_operations smb_file_aops = {
  * Write to a file (through the page cache).
  */
 static ssize_t
-smb_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                              unsigned long nr_segs, loff_t pos)
 {
+       struct file * file = iocb->ki_filp;
        struct dentry * dentry = file->f_dentry;
        ssize_t result;
 
        VERBOSE("file %s/%s, count=%lu@%lu\n",
                DENTRY_PATH(dentry),
-               (unsigned long) count, (unsigned long) *ppos);
+               (unsigned long) iocb->ki_left, (unsigned long) pos);
 
        result = smb_revalidate_inode(dentry);
        if (result) {
@@ -337,8 +341,8 @@ smb_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
        if (result)
                goto out;
 
-       if (count > 0) {
-               result = generic_file_write(file, buf, count, ppos);
+       if (iocb->ki_left > 0) {
+               result = generic_file_aio_write(iocb, iov, nr_segs, pos);
                VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
                        (long) file->f_pos, (long) dentry->d_inode->i_size,
                        dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
@@ -402,8 +406,10 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
 const struct file_operations smb_file_operations =
 {
        .llseek         = remote_llseek,
-       .read           = smb_file_read,
-       .write          = smb_file_write,
+       .read           = do_sync_read,
+       .aio_read       = smb_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = smb_file_aio_write,
        .ioctl          = smb_ioctl,
        .mmap           = smb_file_mmap,
        .open           = smb_file_open,
index a1ed657c3c84323037f526cc341bb63fd44336cf..2c122ee83adbdd3d693c2c8a4fb671aeca4b85f3 100644 (file)
@@ -89,8 +89,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(smb_inode_cachep))
-               printk(KERN_INFO "smb_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(smb_inode_cachep);
 }
 
 static int smb_remount(struct super_block *sb, int *flags, char *data)
@@ -167,7 +166,6 @@ smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
        fattr->f_mtime  = inode->i_mtime;
        fattr->f_ctime  = inode->i_ctime;
        fattr->f_atime  = inode->i_atime;
-       fattr->f_blksize= inode->i_blksize;
        fattr->f_blocks = inode->i_blocks;
 
        fattr->attr     = SMB_I(inode)->attr;
@@ -201,7 +199,6 @@ smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
        inode->i_uid    = fattr->f_uid;
        inode->i_gid    = fattr->f_gid;
        inode->i_ctime  = fattr->f_ctime;
-       inode->i_blksize= fattr->f_blksize;
        inode->i_blocks = fattr->f_blocks;
        inode->i_size   = fattr->f_size;
        inode->i_mtime  = fattr->f_mtime;
index c3495059889df1958ce08ad570730d4921f429ca..40e174db9872fb0a915e83ba77d0b08975a708ff 100644 (file)
@@ -1826,7 +1826,6 @@ smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
        fattr->f_nlink = 1;
        fattr->f_uid = server->mnt->uid;
        fattr->f_gid = server->mnt->gid;
-       fattr->f_blksize = SMB_ST_BLKSIZE;
        fattr->f_unix = 0;
 }
 
index c8e96195b96ee29c52b931b4c2b47c9e1f90e8e0..0fb74697abc401694ea0a0e9aed4f8352a5213c5 100644 (file)
@@ -49,8 +49,7 @@ int smb_init_request_cache(void)
 
 void smb_destroy_request_cache(void)
 {
-       if (kmem_cache_destroy(req_cachep))
-               printk(KERN_INFO "smb_destroy_request_cache: not all structures were freed\n");
+       kmem_cache_destroy(req_cachep);
 }
 
 /*
index 684bca3d3a107c021715f8394a1f1d23a1913aaa..13e92dd19fbb1b9165f6cd05e02128c2a0a39cd8 100644 (file)
@@ -12,7 +12,7 @@
  * Jens to support splicing to files, network, direct splicing, etc and
  * fixing lots of bugs.
  *
- * Copyright (C) 2005-2006 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005-2006 Jens Axboe <axboe@kernel.dk>
  * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org>
  * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu>
  *
index 3a44dcf97da23d1704b599527db4a50edcbc04a6..60a31d5e5966a03ba0a3e009ae521bf02ade2adb 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -14,6 +14,7 @@
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -32,7 +33,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
        stat->ctime = inode->i_ctime;
        stat->size = i_size_read(inode);
        stat->blocks = inode->i_blocks;
-       stat->blksize = inode->i_blksize;
+       stat->blksize = (1 << inode->i_blkbits);
 }
 
 EXPORT_SYMBOL(generic_fillattr);
index 5c4c94d5495e42588c9aef5a9fe4271d54f1da24..aec99ddbe53f726a526d4cd0b02abb9f55179e0b 100644 (file)
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(deactivate_super);
  *     success, 0 if we had failed (superblock contents was already dead or
  *     dying when grab_super() had been called).
  */
-static int grab_super(struct super_block *s)
+static int grab_super(struct super_block *s) __releases(sb_lock)
 {
        s->s_count++;
        spin_unlock(&sb_lock);
@@ -220,6 +220,37 @@ static int grab_super(struct super_block *s)
        return 0;
 }
 
+/*
+ * Write out and wait upon all dirty data associated with this
+ * superblock.  Filesystem data as well as the underlying block
+ * device.  Takes the superblock lock.  Requires a second blkdev
+ * flush by the caller to complete the operation.
+ */
+void __fsync_super(struct super_block *sb)
+{
+       sync_inodes_sb(sb, 0);
+       DQUOT_SYNC(sb);
+       lock_super(sb);
+       if (sb->s_dirt && sb->s_op->write_super)
+               sb->s_op->write_super(sb);
+       unlock_super(sb);
+       if (sb->s_op->sync_fs)
+               sb->s_op->sync_fs(sb, 1);
+       sync_blockdev(sb->s_bdev);
+       sync_inodes_sb(sb, 1);
+}
+
+/*
+ * Write out and wait upon all dirty data associated with this
+ * superblock.  Filesystem data as well as the underlying block
+ * device.  Takes the superblock lock.
+ */
+int fsync_super(struct super_block *sb)
+{
+       __fsync_super(sb);
+       return sync_blockdev(sb->s_bdev);
+}
+
 /**
  *     generic_shutdown_super  -       common helper for ->kill_sb()
  *     @sb: superblock to kill
@@ -540,8 +571,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 {
        int retval;
        
+#ifdef CONFIG_BLOCK
        if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
                return -EACCES;
+#endif
        if (flags & MS_RDONLY)
                acct_auto_close(sb);
        shrink_dcache_sb(sb);
@@ -661,6 +694,7 @@ void kill_litter_super(struct super_block *sb)
 
 EXPORT_SYMBOL(kill_litter_super);
 
+#ifdef CONFIG_BLOCK
 static int set_bdev_super(struct super_block *s, void *data)
 {
        s->s_bdev = data;
@@ -756,6 +790,7 @@ void kill_block_super(struct super_block *sb)
 }
 
 EXPORT_SYMBOL(kill_block_super);
+#endif
 
 int get_sb_nodev(struct file_system_type *fs_type,
        int flags, void *data,
index 955aef04da289fecb80f51981ae98f538e6bcdc2..1de747b5ddb9dcaf12ac0dc164f9a614db7b6d13 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
 #include <linux/syscalls.h>
 #include <linux/linkage.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/buffer_head.h>
 
 #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
                        SYNC_FILE_RANGE_WAIT_AFTER)
 
+/*
+ * sync everything.  Start out by waking pdflush, because that writes back
+ * all queues in parallel.
+ */
+static void do_sync(unsigned long wait)
+{
+       wakeup_pdflush(0);
+       sync_inodes(0);         /* All mappings, inodes and their blockdevs */
+       DQUOT_SYNC(NULL);
+       sync_supers();          /* Write the superblocks */
+       sync_filesystems(0);    /* Start syncing the filesystems */
+       sync_filesystems(wait); /* Waitingly sync the filesystems */
+       sync_inodes(wait);      /* Mappings, inodes and blockdevs, again. */
+       if (!wait)
+               printk("Emergency Sync complete\n");
+       if (unlikely(laptop_mode))
+               laptop_sync_completion();
+}
+
+asmlinkage long sys_sync(void)
+{
+       do_sync(1);
+       return 0;
+}
+
+void emergency_sync(void)
+{
+       pdflush_operation(do_sync, 0);
+}
+
+/*
+ * Generic function to fsync a file.
+ *
+ * filp may be NULL if called via the msync of a vma.
+ */
+int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
+{
+       struct inode * inode = dentry->d_inode;
+       struct super_block * sb;
+       int ret, err;
+
+       /* sync the inode to buffers */
+       ret = write_inode_now(inode, 0);
+
+       /* sync the superblock to buffers */
+       sb = inode->i_sb;
+       lock_super(sb);
+       if (sb->s_op->write_super)
+               sb->s_op->write_super(sb);
+       unlock_super(sb);
+
+       /* .. finally sync the buffers to disk */
+       err = sync_blockdev(sb->s_bdev);
+       if (!ret)
+               ret = err;
+       return ret;
+}
+
+long do_fsync(struct file *file, int datasync)
+{
+       int ret;
+       int err;
+       struct address_space *mapping = file->f_mapping;
+
+       if (!file->f_op || !file->f_op->fsync) {
+               /* Why?  We can still call filemap_fdatawrite */
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = filemap_fdatawrite(mapping);
+
+       /*
+        * We need to protect against concurrent writers, which could cause
+        * livelocks in fsync_buffers_list().
+        */
+       mutex_lock(&mapping->host->i_mutex);
+       err = file->f_op->fsync(file, file->f_dentry, datasync);
+       if (!ret)
+               ret = err;
+       mutex_unlock(&mapping->host->i_mutex);
+       err = filemap_fdatawait(mapping);
+       if (!ret)
+               ret = err;
+out:
+       return ret;
+}
+
+static long __do_fsync(unsigned int fd, int datasync)
+{
+       struct file *file;
+       int ret = -EBADF;
+
+       file = fget(fd);
+       if (file) {
+               ret = do_fsync(file, datasync);
+               fput(file);
+       }
+       return ret;
+}
+
+asmlinkage long sys_fsync(unsigned int fd)
+{
+       return __do_fsync(fd, 0);
+}
+
+asmlinkage long sys_fdatasync(unsigned int fd)
+{
+       return __do_fsync(fd, 1);
+}
+
 /*
  * sys_sync_file_range() permits finely controlled syncing over a segment of
  * a file in the range offset .. (offset+nbytes-1) inclusive.  If nbytes is
index 5f3d725d11251487481c57599bc0f0ddedcfe904..3aa3434621ca89296b3c0b0598a663807977f1eb 100644 (file)
@@ -103,7 +103,7 @@ static int init_dir(struct inode * inode)
        inode->i_fop = &sysfs_dir_operations;
 
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-       inode->i_nlink++;
+       inc_nlink(inode);
        return 0;
 }
 
@@ -137,7 +137,7 @@ static int create_dir(struct kobject * k, struct dentry * p,
                if (!error) {
                        error = sysfs_create(*d, mode, init_dir);
                        if (!error) {
-                               p->d_inode->i_nlink++;
+                               inc_nlink(p->d_inode);
                                (*d)->d_op = &sysfs_dentry_ops;
                                d_rehash(*d);
                        }
index fd7cd5f843d2764b08bf42a8f60644a9f8b56d3a..e79e38d52c0067185ba5fabf29a1f0c3e474172b 100644 (file)
@@ -125,7 +125,6 @@ struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
 {
        struct inode * inode = new_inode(sysfs_sb);
        if (inode) {
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &sysfs_aops;
                inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
index 40190c4892715502b286c3e491c114af1c0b97bd..20551a1b8a56494ffb7ea2b0a10c01f8f7f99a78 100644 (file)
@@ -49,7 +49,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
                inode->i_op = &sysfs_dir_inode_operations;
                inode->i_fop = &sysfs_dir_operations;
                /* directory inodes start off with i_nlink == 2 (for "." entry) */
-               inode->i_nlink++;       
+               inc_nlink(inode);
        } else {
                pr_debug("sysfs: could not get root inode\n");
                return -ENOMEM;
index a59e303135fa02feca937e45706c87b14f8d0c5b..47a4b728f15b49bfdf84d7b30d17568e08a13b1c 100644 (file)
  */
 const struct file_operations sysv_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .fsync          = sysv_sync_file,
        .sendfile       = generic_file_sendfile,
index 9b585d1081c0d142664e064f82c5a5669ea4d2ca..115ab0d6f4bcab86b06243cd107f92c082285c00 100644 (file)
@@ -170,7 +170,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        inode->i_uid = current->fsuid;
        inode->i_ino = fs16_to_cpu(sbi, ino);
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
        SYSV_I(inode)->i_dir_start_lookup = 0;
        insert_inode_hash(inode);
index 58b2d22142ba67dc81aa8d9bff0f909808d4c250..d63c5e48b050e0865c19d086e9e6346fc59a8f47 100644 (file)
@@ -201,7 +201,7 @@ static void sysv_read_inode(struct inode *inode)
        inode->i_ctime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_mtime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
 
        si = SYSV_I(inode);
        for (block = 0; block < 10+1+1+1; block++)
index b8a73f716fbe35c5a0683017db96fc3c2d1136cd..f7c08db8e34c80225000cd10b7722e5d8ef82eb6 100644 (file)
@@ -250,7 +250,7 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
                sysv_set_link(new_de, new_page, old_inode);
                new_inode->i_ctime = CURRENT_TIME_SEC;
                if (dir_de)
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                inode_dec_link_count(new_inode);
        } else {
                if (dir_de) {
index 876639b93321b42ac37336fa6a336ca6bb946a56..350cba5d68034f8dd4bdbb2732e2d5bc0cc17f9a 100644 (file)
@@ -369,10 +369,9 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
        if (64 != sizeof (struct sysv_inode))
                panic("sysv fs: bad inode size");
 
-       sbi = kmalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
-       memset(sbi, 0, sizeof(struct sysv_sb_info));
 
        sbi->s_sb = sb;
        sbi->s_block_base = 0;
@@ -453,10 +452,9 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
        if (64 != sizeof (struct sysv_inode))
                panic("sysv fs: bad i-node size");
 
-       sbi = kmalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
-       memset(sbi, 0, sizeof(struct sysv_sb_info));
 
        sbi->s_sb = sb;
        sbi->s_block_base = 0;
index a59e5f33daf6f7ed5225d8f85c349acbf29f05ab..7aedd552cba12c205706fb921dd0bde45ec68e11 100644 (file)
@@ -103,19 +103,21 @@ const struct address_space_operations udf_adinicb_aops = {
        .commit_write           = udf_adinicb_commit_write,
 };
 
-static ssize_t udf_file_write(struct file * file, const char __user * buf,
-       size_t count, loff_t *ppos)
+static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                             unsigned long nr_segs, loff_t ppos)
 {
        ssize_t retval;
+       struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_dentry->d_inode;
        int err, pos;
+       size_t count = iocb->ki_left;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
        {
                if (file->f_flags & O_APPEND)
                        pos = inode->i_size;
                else
-                       pos = *ppos;
+                       pos = ppos;
 
                if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
                        pos + count))
@@ -136,7 +138,7 @@ static ssize_t udf_file_write(struct file * file, const char __user * buf,
                }
        }
 
-       retval = generic_file_write(file, buf, count, ppos);
+       retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
 
        if (retval > 0)
                mark_inode_dirty(inode);
@@ -249,11 +251,13 @@ static int udf_release_file(struct inode * inode, struct file * filp)
 }
 
 const struct file_operations udf_file_operations = {
-       .read                   = generic_file_read,
+       .read                   = do_sync_read,
+       .aio_read               = generic_file_aio_read,
        .ioctl                  = udf_ioctl,
        .open                   = generic_file_open,
        .mmap                   = generic_file_mmap,
-       .write                  = udf_file_write,
+       .write                  = do_sync_write,
+       .aio_write              = udf_file_aio_write,
        .release                = udf_release_file,
        .fsync                  = udf_fsync_file,
        .sendfile               = generic_file_sendfile,
index 33323473e3c43edfbd53a16014f3bf313d580ac4..8206983f2ebf924c1bf91629206fbc518d014c69 100644 (file)
@@ -121,7 +121,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
        UDF_I_LOCATION(inode).logicalBlockNum = block;
        UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
        inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = 0;
        UDF_I_LENEATTR(inode) = 0;
        UDF_I_LENALLOC(inode) = 0;
@@ -130,14 +129,12 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
        {
                UDF_I_EFE(inode) = 1;
                UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
-               memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
+               UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
        }
        else
        {
                UDF_I_EFE(inode) = 0;
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
-               memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+               UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
        }
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
                UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
index 605f5111b6d86a100430897877f170c2b59248e7..ae21a0e59e9569b09234f57fd1a910baf9928059 100644 (file)
@@ -916,8 +916,6 @@ __udf_read_inode(struct inode *inode)
         *      i_nlink = 1
         *      i_op = NULL;
         */
-       inode->i_blksize = PAGE_SIZE;
-
        bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
 
        if (!bh)
@@ -1167,7 +1165,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                        inode->i_op = &udf_dir_inode_operations;
                        inode->i_fop = &udf_dir_operations;
                        inode->i_mode |= S_IFDIR;
-                       inode->i_nlink ++;
+                       inc_nlink(inode);
                        break;
                }
                case ICBTAG_FILE_TYPE_REALTIME:
index ab9a7629d23e82c094e8b7db9606a57af007e294..73163325e5ec36ba628209cc146cf808d3f94abc 100644 (file)
@@ -762,7 +762,7 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
        cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
-       dir->i_nlink++;
+       inc_nlink(dir);
        mark_inode_dirty(dir);
        d_instantiate(dentry, inode);
        if (fibh.sbh != fibh.ebh)
@@ -876,10 +876,9 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
                udf_warning(inode->i_sb, "udf_rmdir",
                        "empty directory has nlink != 2 (%d)",
                        inode->i_nlink);
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_size = 0;
-       mark_inode_dirty(inode);
-       dir->i_nlink --;
+       inode_dec_link_count(inode);
        inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
        mark_inode_dirty(dir);
 
@@ -923,8 +922,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
                goto end_unlink;
        dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
        mark_inode_dirty(dir);
-       inode->i_nlink--;
-       mark_inode_dirty(inode);
+       inode_dec_link_count(inode);
        inode->i_ctime = dir->i_ctime;
        retval = 0;
 
@@ -1101,8 +1099,7 @@ out:
        return err;
 
 out_no_entry:
-       inode->i_nlink--;
-       mark_inode_dirty(inode);
+       inode_dec_link_count(inode);
        iput(inode);
        goto out;
 }
@@ -1150,7 +1147,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
        if (fibh.sbh != fibh.ebh)
                udf_release_data(fibh.ebh);
        udf_release_data(fibh.sbh);
-       inode->i_nlink ++;
+       inc_nlink(inode);
        inode->i_ctime = current_fs_time(inode->i_sb);
        mark_inode_dirty(inode);
        atomic_inc(&inode->i_count);
@@ -1261,9 +1258,8 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
 
        if (new_inode)
        {
-               new_inode->i_nlink--;
                new_inode->i_ctime = current_fs_time(new_inode->i_sb);
-               mark_inode_dirty(new_inode);
+               inode_dec_link_count(new_inode);
        }
        old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
        mark_inode_dirty(old_dir);
@@ -1279,16 +1275,14 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
                }
                else
                        mark_buffer_dirty_inode(dir_bh, old_inode);
-               old_dir->i_nlink --;
-               mark_inode_dirty(old_dir);
+               inode_dec_link_count(old_dir);
                if (new_inode)
                {
-                       new_inode->i_nlink --;
-                       mark_inode_dirty(new_inode);
+                       inode_dec_link_count(new_inode);
                }
                else
                {
-                       new_dir->i_nlink ++;
+                       inc_nlink(new_dir);
                        mark_inode_dirty(new_dir);
                }
        }
index fcce1a21a51bdc1c0a095ccc815d35bd6399bf0f..1d3b5d2070e5474cbf2b212b457166487e32fbde 100644 (file)
@@ -156,8 +156,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(udf_inode_cachep))
-               printk(KERN_INFO "udf_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(udf_inode_cachep);
 }
 
 /* Superblock operations */
@@ -1622,6 +1621,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                goto error_out;
        }
 
+       if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_READ_ONLY)
+               printk("UDF-fs: Partition marked readonly; forcing readonly mount\n");
+               sb->s_flags |= MS_RDONLY;
+
        if ( udf_find_fileset(sb, &fileset, &rootdir) )
        {
                printk("UDF-fs: No fileset found\n");
index a9c6e5f04faea080ddc271602cab79f829295548..1e096323bad47f240bdbc30191922d46638a5612 100644 (file)
@@ -53,8 +53,10 @@ static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
  
 const struct file_operations ufs_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .open           = generic_file_open,
        .fsync          = ufs_sync_file,
index 9501dcd3b2132b4c0235fd0e187cb11648fc0708..2ad1259c6ecaacd7f6130859c42cb8654fb0e991 100644 (file)
@@ -255,7 +255,6 @@ cg_found:
                inode->i_gid = current->fsgid;
 
        inode->i_ino = cg * uspi->s_ipg + bit;
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
        ufsi->i_flags = UFS_I(dir)->i_flags;
index 30c6e8a9446c20382147423d97cc77af2a4ac137..ee1eaa6f4ec2187f0f669324d2aaa7253932318a 100644 (file)
@@ -741,7 +741,6 @@ void ufs_read_inode(struct inode * inode)
                ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
        }
 
-       inode->i_blksize = PAGE_SIZE;/*This is the optimal IO size (for stat)*/
        inode->i_version++;
        ufsi->i_lastfrag =
                (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
index d344b411e2617eca708d104a7b8dc5266e26ab7b..e84c0ecf07304f0f8222e3c438f4e1b8bb5bed34 100644 (file)
@@ -308,7 +308,7 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
                ufs_set_link(new_dir, new_de, new_page, old_inode);
                new_inode->i_ctime = CURRENT_TIME_SEC;
                if (dir_de)
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                inode_dec_link_count(new_inode);
        } else {
                if (dir_de) {
index 992ee0b87cc3f7835fa376c75733822d9ddfbdc6..ec79e3091d1bc7f647905edc7c410c94dcb10a3a 100644 (file)
@@ -611,11 +611,10 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        
        UFSD("ENTER\n");
                
-       sbi = kmalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
        if (!sbi)
                goto failed_nomem;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct ufs_sb_info));
 
        UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY));
        
@@ -1245,8 +1244,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ufs_inode_cachep))
-               printk(KERN_INFO "ufs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ufs_inode_cachep);
 }
 
 #ifdef CONFIG_QUOTA
diff --git a/fs/utimes.c b/fs/utimes.c
new file mode 100644 (file)
index 0000000..1bcd852
--- /dev/null
@@ -0,0 +1,137 @@
+#include <linux/compiler.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/namei.h>
+#include <linux/utime.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+#ifdef __ARCH_WANT_SYS_UTIME
+
+/*
+ * sys_utime() can be implemented in user-level using sys_utimes().
+ * Is this for backwards compatibility?  If so, why not move it
+ * into the appropriate arch directory (for those architectures that
+ * need it).
+ */
+
+/* If times==NULL, set access and modification to current time,
+ * 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)
+{
+       int error;
+       struct nameidata nd;
+       struct inode * inode;
+       struct iattr newattrs;
+
+       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;
+       }
+       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;
+}
+
+#endif
+
+/* If times==NULL, set access and modification to current time,
+ * 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)
+{
+       int error;
+       struct nameidata nd;
+       struct inode * inode;
+       struct iattr newattrs;
+
+       error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &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;
+
+               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;
+       } 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;
+       }
+       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;
+}
+
+asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
+{
+       struct timeval times[2];
+
+       if (utimes && copy_from_user(&times, utimes, sizeof(times)))
+               return -EFAULT;
+       return do_utimes(dfd, filename, utimes ? times : NULL);
+}
+
+asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
+{
+       return sys_futimesat(AT_FDCWD, filename, utimes);
+}
index 9a8f48bae95626b739b34867713fc2d7d367f649..edb711ff7b05781b624b310dcf7b360f2c683745 100644 (file)
@@ -782,9 +782,9 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
        err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
        if (err)
                goto out;
-       dir->i_nlink--;
+       drop_nlink(dir);
 
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
@@ -808,7 +808,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
        err = fat_remove_entries(dir, &sinfo);  /* and releases bh */
        if (err)
                goto out;
-       inode->i_nlink = 0;
+       clear_nlink(inode);
        inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
        fat_detach(inode);
 out:
@@ -837,7 +837,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (err)
                goto out_free;
        dir->i_version++;
-       dir->i_nlink++;
+       inc_nlink(dir);
 
        inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
        brelse(sinfo.bh);
@@ -930,9 +930,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
                        if (err)
                                goto error_dotdot;
                }
-               old_dir->i_nlink--;
+               drop_nlink(old_dir);
                if (!new_inode)
-                       new_dir->i_nlink++;
+                       inc_nlink(new_dir);
        }
 
        err = fat_remove_entries(old_dir, &old_sinfo);  /* and releases bh */
@@ -947,10 +947,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
                mark_inode_dirty(old_dir);
 
        if (new_inode) {
+               drop_nlink(new_inode);
                if (is_dir)
-                       new_inode->i_nlink -= 2;
-               else
-                       new_inode->i_nlink--;
+                       drop_nlink(new_inode);
                new_inode->i_ctime = ts;
        }
 out:
index 26b364c9d62c67226de54101ae6f7faa31f33251..35115bca036e01d5363c6103100a875c232784e0 100644 (file)
@@ -1,5 +1,6 @@
 config XFS_FS
        tristate "XFS filesystem support"
+       depends on BLOCK
        help
          XFS is a high performance journaling filesystem which originated
          on the SGI IRIX platform.  It is completely multi-threaded, can
index 9e7f85986d0de3d766a6cc5ee783bb7cd5a9bdb9..291948d5085a08ebac04c8f725c152d80a392805 100644 (file)
@@ -30,7 +30,6 @@ ifeq ($(CONFIG_XFS_TRACE),y)
        EXTRA_CFLAGS += -DXFS_BLI_TRACE
        EXTRA_CFLAGS += -DXFS_BMAP_TRACE
        EXTRA_CFLAGS += -DXFS_BMBT_TRACE
-       EXTRA_CFLAGS += -DXFS_DIR_TRACE
        EXTRA_CFLAGS += -DXFS_DIR2_TRACE
        EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
        EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
index aba7fcf881a217d209d7c0c89fb9a573156e21ba..d59737589815c8048c00d432867606a719d0fa31 100644 (file)
@@ -34,6 +34,14 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
        gfp_t   lflags = kmem_flags_convert(flags);
        void    *ptr;
 
+#ifdef DEBUG
+       if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
+               printk(KERN_WARNING "Large %s attempt, size=%ld\n",
+                       __FUNCTION__, (long)size);
+               dump_stack();
+       }
+#endif
+
        do {
                if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
                        ptr = kmalloc(size, lflags);
@@ -60,6 +68,27 @@ kmem_zalloc(size_t size, unsigned int __nocast flags)
        return ptr;
 }
 
+void *
+kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
+                  unsigned int __nocast flags)
+{
+       void            *ptr;
+       size_t          kmsize = maxsize;
+       unsigned int    kmflags = (flags & ~KM_SLEEP) | KM_NOSLEEP;
+
+       while (!(ptr = kmem_zalloc(kmsize, kmflags))) {
+               if ((kmsize <= minsize) && (flags & KM_NOSLEEP))
+                       break;
+               if ((kmsize >>= 1) <= minsize) {
+                       kmsize = minsize;
+                       kmflags = flags;
+               }
+       }
+       if (ptr)
+               *size = kmsize;
+       return ptr;
+}
+
 void
 kmem_free(void *ptr, size_t size)
 {
index 939bd84bc7ee3c0b137ad10a0353883e03f82946..9ebabdf7829c3a5c5dc2fe08caefde56fb8dfe2c 100644 (file)
@@ -30,6 +30,7 @@
 #define KM_NOSLEEP     0x0002u
 #define KM_NOFS                0x0004u
 #define KM_MAYFAIL     0x0008u
+#define KM_LARGE       0x0010u
 
 /*
  * We use a special process flag to avoid recursive callbacks into
@@ -41,7 +42,7 @@ kmem_flags_convert(unsigned int __nocast flags)
 {
        gfp_t   lflags;
 
-       BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL));
+       BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_LARGE));
 
        if (flags & KM_NOSLEEP) {
                lflags = GFP_ATOMIC | __GFP_NOWARN;
@@ -54,8 +55,9 @@ kmem_flags_convert(unsigned int __nocast flags)
 }
 
 extern void *kmem_alloc(size_t, unsigned int __nocast);
-extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast);
 extern void *kmem_zalloc(size_t, unsigned int __nocast);
+extern void *kmem_zalloc_greedy(size_t *, size_t, size_t, unsigned int __nocast);
+extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast);
 extern void  kmem_free(void *, size_t);
 
 /*
@@ -91,8 +93,8 @@ kmem_zone_free(kmem_zone_t *zone, void *ptr)
 static inline void
 kmem_zone_destroy(kmem_zone_t *zone)
 {
-       if (zone && kmem_cache_destroy(zone))
-               BUG();
+       if (zone)
+               kmem_cache_destroy(zone);
 }
 
 extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
index b25090094cca73d97a350b141f12114327fc3405..2009e6d922ce5161304813b82a7ea7ca47c2351a 100644 (file)
@@ -29,8 +29,6 @@
 
 typedef struct semaphore sema_t;
 
-#define init_sema(sp, val, c, d)       sema_init(sp, val)
-#define initsema(sp, val)              sema_init(sp, val)
 #define initnsema(sp, val, name)       sema_init(sp, val)
 #define psema(sp, b)                   down(sp)
 #define vsema(sp)                      up(sp)
index 9a8ad481b0086e72b69d9643d3df70e936880ecb..351a8f454bd1adfdcffb91e8299324da77a8878c 100644 (file)
@@ -53,8 +53,6 @@ static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state,
        remove_wait_queue(&sv->waiters, &wait);
 }
 
-#define init_sv(sv,type,name,flag) \
-       init_waitqueue_head(&(sv)->waiters)
 #define sv_init(sv,flag,name) \
        init_waitqueue_head(&(sv)->waiters)
 #define sv_destroy(sv) \
index 34dcb43a7837d8d9b602ba23199c8f6bbe429400..09360cf1e1f277cb5b35233aa4ef0d81edcaa38d 100644 (file)
@@ -71,7 +71,7 @@ xfs_page_trace(
        int             tag,
        struct inode    *inode,
        struct page     *page,
-       int             mask)
+       unsigned long   pgoff)
 {
        xfs_inode_t     *ip;
        bhv_vnode_t     *vp = vn_from_inode(inode);
@@ -91,7 +91,7 @@ xfs_page_trace(
                (void *)ip,
                (void *)inode,
                (void *)page,
-               (void *)((unsigned long)mask),
+               (void *)pgoff,
                (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
                (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
                (void *)((unsigned long)((isize >> 32) & 0xffffffff)),
@@ -105,7 +105,7 @@ xfs_page_trace(
                (void *)NULL);
 }
 #else
-#define xfs_page_trace(tag, inode, page, mask)
+#define xfs_page_trace(tag, inode, page, pgoff)
 #endif
 
 /*
@@ -1197,7 +1197,7 @@ xfs_vm_releasepage(
                .nr_to_write = 1,
        };
 
-       xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask);
+       xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, 0);
 
        if (!page_has_buffers(page))
                return 0;
@@ -1356,7 +1356,6 @@ xfs_end_io_direct(
                ioend->io_size = size;
                xfs_finish_ioend(ioend);
        } else {
-               ASSERT(size >= 0);
                xfs_destroy_ioend(ioend);
        }
 
index 2af528dcfb0428ca93f2a5dced879e400682b876..9bbadafdcb00285a8644a350a0ef033c7889f139 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -318,8 +318,12 @@ xfs_buf_free(
                if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
                        free_address(bp->b_addr - bp->b_offset);
 
-               for (i = 0; i < bp->b_page_count; i++)
-                       page_cache_release(bp->b_pages[i]);
+               for (i = 0; i < bp->b_page_count; i++) {
+                       struct page     *page = bp->b_pages[i];
+
+                       ASSERT(!PagePrivate(page));
+                       page_cache_release(page);
+               }
                _xfs_buf_free_pages(bp);
        } else if (bp->b_flags & _XBF_KMEM_ALLOC) {
                 /*
@@ -400,6 +404,7 @@ _xfs_buf_lookup_pages(
                nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset);
                size -= nbytes;
 
+               ASSERT(!PagePrivate(page));
                if (!PageUptodate(page)) {
                        page_count--;
                        if (blocksize >= PAGE_CACHE_SIZE) {
@@ -768,7 +773,7 @@ xfs_buf_get_noaddr(
        _xfs_buf_initialize(bp, target, 0, len, 0);
 
  try_again:
-       data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL);
+       data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE);
        if (unlikely(data == NULL))
                goto fail_free_buf;
 
@@ -1117,10 +1122,10 @@ xfs_buf_bio_end_io(
        do {
                struct page     *page = bvec->bv_page;
 
+               ASSERT(!PagePrivate(page));
                if (unlikely(bp->b_error)) {
                        if (bp->b_flags & XBF_READ)
                                ClearPageUptodate(page);
-                       SetPageError(page);
                } else if (blocksize >= PAGE_CACHE_SIZE) {
                        SetPageUptodate(page);
                } else if (!PagePrivate(page) &&
@@ -1156,16 +1161,16 @@ _xfs_buf_ioapply(
        total_nr_pages = bp->b_page_count;
        map_i = 0;
 
-       if (bp->b_flags & _XBF_RUN_QUEUES) {
-               bp->b_flags &= ~_XBF_RUN_QUEUES;
-               rw = (bp->b_flags & XBF_READ) ? READ_SYNC : WRITE_SYNC;
-       } else {
-               rw = (bp->b_flags & XBF_READ) ? READ : WRITE;
-       }
-
        if (bp->b_flags & XBF_ORDERED) {
                ASSERT(!(bp->b_flags & XBF_READ));
                rw = WRITE_BARRIER;
+       } else if (bp->b_flags & _XBF_RUN_QUEUES) {
+               ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
+               bp->b_flags &= ~_XBF_RUN_QUEUES;
+               rw = (bp->b_flags & XBF_WRITE) ? WRITE_SYNC : READ_SYNC;
+       } else {
+               rw = (bp->b_flags & XBF_WRITE) ? WRITE :
+                    (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
        }
 
        /* Special code path for reading a sub page size buffer in --
@@ -1681,6 +1686,7 @@ xfsbufd(
        xfs_buf_t               *bp, *n;
        struct list_head        *dwq = &target->bt_delwrite_queue;
        spinlock_t              *dwlk = &target->bt_delwrite_lock;
+       int                     count;
 
        current->flags |= PF_MEMALLOC;
 
@@ -1696,6 +1702,7 @@ xfsbufd(
                schedule_timeout_interruptible(
                        xfs_buf_timer_centisecs * msecs_to_jiffies(10));
 
+               count = 0;
                age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
                spin_lock(dwlk);
                list_for_each_entry_safe(bp, n, dwq, b_list) {
@@ -1711,9 +1718,11 @@ xfsbufd(
                                        break;
                                }
 
-                               bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+                               bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
+                                                _XBF_RUN_QUEUES);
                                bp->b_flags |= XBF_WRITE;
-                               list_move(&bp->b_list, &tmp);
+                               list_move_tail(&bp->b_list, &tmp);
+                               count++;
                        }
                }
                spin_unlock(dwlk);
@@ -1724,12 +1733,12 @@ xfsbufd(
 
                        list_del_init(&bp->b_list);
                        xfs_buf_iostrategy(bp);
-
-                       blk_run_address_space(target->bt_mapping);
                }
 
                if (as_list_len > 0)
                        purge_addresses();
+               if (count)
+                       blk_run_address_space(target->bt_mapping);
 
                clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
        } while (!kthread_should_stop());
@@ -1767,7 +1776,7 @@ xfs_flush_buftarg(
                        continue;
                }
 
-               list_move(&bp->b_list, &tmp);
+               list_move_tail(&bp->b_list, &tmp);
        }
        spin_unlock(dwlk);
 
@@ -1776,7 +1785,7 @@ xfs_flush_buftarg(
         */
        list_for_each_entry_safe(bp, n, &tmp, b_list) {
                xfs_buf_lock(bp);
-               bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+               bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|_XBF_RUN_QUEUES);
                bp->b_flags |= XBF_WRITE;
                if (wait)
                        bp->b_flags &= ~XBF_ASYNC;
@@ -1786,6 +1795,9 @@ xfs_flush_buftarg(
                xfs_buf_iostrategy(bp);
        }
 
+       if (wait)
+               blk_run_address_space(target->bt_mapping);
+
        /*
         * Remaining list items must be flushed before returning
         */
@@ -1797,9 +1809,6 @@ xfs_flush_buftarg(
                xfs_buf_relse(bp);
        }
 
-       if (wait)
-               blk_run_address_space(target->bt_mapping);
-
        return pincount;
 }
 
index 7858703ed84cf42130de0bf5444eac74111c4c82..9dd235cb01070623795c7e880c58636465ae17b6 100644 (file)
@@ -298,11 +298,6 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *);
 #define XFS_BUF_UNWRITE(bp)    ((bp)->b_flags &= ~XBF_WRITE)
 #define XFS_BUF_ISWRITE(bp)    ((bp)->b_flags & XBF_WRITE)
 
-#define XFS_BUF_ISUNINITIAL(bp)        (0)
-#define XFS_BUF_UNUNINITIAL(bp)        (0)
-
-#define XFS_BUF_BP_ISMAPPED(bp)        (1)
-
 #define XFS_BUF_IODONE_FUNC(bp)                        ((bp)->b_iodone)
 #define XFS_BUF_SET_IODONE_FUNC(bp, func)      ((bp)->b_iodone = (func))
 #define XFS_BUF_CLR_IODONE_FUNC(bp)            ((bp)->b_iodone = NULL)
@@ -393,8 +388,6 @@ static inline int XFS_bwrite(xfs_buf_t *bp)
        return error;
 }
 
-#define XFS_bdwrite(bp)                xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC)
-
 static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
 {
        bp->b_strat = xfs_bdstrat_cb;
index 3d4f6dff21134a26b622d4450b0e763906ccba1e..d93d8dd1958d3fcb5cc597d44fdda345ac522fac 100644 (file)
@@ -49,50 +49,49 @@ static struct vm_operations_struct xfs_dmapi_file_vm_ops;
 STATIC inline ssize_t
 __xfs_file_read(
        struct kiocb            *iocb,
-       char                    __user *buf,
+       const struct iovec      *iov,
+       unsigned long           nr_segs,
        int                     ioflags,
-       size_t                  count,
        loff_t                  pos)
 {
-       struct iovec            iov = {buf, count};
        struct file             *file = iocb->ki_filp;
        bhv_vnode_t             *vp = vn_from_inode(file->f_dentry->d_inode);
 
        BUG_ON(iocb->ki_pos != pos);
        if (unlikely(file->f_flags & O_DIRECT))
                ioflags |= IO_ISDIRECT;
-       return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
+       return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos,
+                               ioflags, NULL);
 }
 
 STATIC ssize_t
 xfs_file_aio_read(
        struct kiocb            *iocb,
-       char                    __user *buf,
-       size_t                  count,
+       const struct iovec      *iov,
+       unsigned long           nr_segs,
        loff_t                  pos)
 {
-       return __xfs_file_read(iocb, buf, IO_ISAIO, count, pos);
+       return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO, pos);
 }
 
 STATIC ssize_t
 xfs_file_aio_read_invis(
        struct kiocb            *iocb,
-       char                    __user *buf,
-       size_t                  count,
+       const struct iovec      *iov,
+       unsigned long           nr_segs,
        loff_t                  pos)
 {
-       return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+       return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
 }
 
 STATIC inline ssize_t
 __xfs_file_write(
-       struct kiocb    *iocb,
-       const char      __user *buf,
-       int             ioflags,
-       size_t          count,
-       loff_t          pos)
+       struct kiocb            *iocb,
+       const struct iovec      *iov,
+       unsigned long           nr_segs,
+       int                     ioflags,
+       loff_t                  pos)
 {
-       struct iovec    iov = {(void __user *)buf, count};
        struct file     *file = iocb->ki_filp;
        struct inode    *inode = file->f_mapping->host;
        bhv_vnode_t     *vp = vn_from_inode(inode);
@@ -100,117 +99,28 @@ __xfs_file_write(
        BUG_ON(iocb->ki_pos != pos);
        if (unlikely(file->f_flags & O_DIRECT))
                ioflags |= IO_ISDIRECT;
-       return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
+       return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos,
+                               ioflags, NULL);
 }
 
 STATIC ssize_t
 xfs_file_aio_write(
        struct kiocb            *iocb,
-       const char              __user *buf,
-       size_t                  count,
+       const struct iovec      *iov,
+       unsigned long           nr_segs,
        loff_t                  pos)
 {
-       return __xfs_file_write(iocb, buf, IO_ISAIO, count, pos);
+       return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO, pos);
 }
 
 STATIC ssize_t
 xfs_file_aio_write_invis(
        struct kiocb            *iocb,
-       const char              __user *buf,
-       size_t                  count,
-       loff_t                  pos)
-{
-       return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
-}
-
-STATIC inline ssize_t
-__xfs_file_readv(
-       struct file             *file,
-       const struct iovec      *iov,
-       int                     ioflags,
-       unsigned long           nr_segs,
-       loff_t                  *ppos)
-{
-       struct inode    *inode = file->f_mapping->host;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
-       struct kiocb    kiocb;
-       ssize_t         rval;
-
-       init_sync_kiocb(&kiocb, file);
-       kiocb.ki_pos = *ppos;
-
-       if (unlikely(file->f_flags & O_DIRECT))
-               ioflags |= IO_ISDIRECT;
-       rval = bhv_vop_read(vp, &kiocb, iov, nr_segs,
-                               &kiocb.ki_pos, ioflags, NULL);
-
-       *ppos = kiocb.ki_pos;
-       return rval;
-}
-
-STATIC ssize_t
-xfs_file_readv(
-       struct file             *file,
-       const struct iovec      *iov,
-       unsigned long           nr_segs,
-       loff_t                  *ppos)
-{
-       return __xfs_file_readv(file, iov, 0, nr_segs, ppos);
-}
-
-STATIC ssize_t
-xfs_file_readv_invis(
-       struct file             *file,
-       const struct iovec      *iov,
-       unsigned long           nr_segs,
-       loff_t                  *ppos)
-{
-       return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
-}
-
-STATIC inline ssize_t
-__xfs_file_writev(
-       struct file             *file,
-       const struct iovec      *iov,
-       int                     ioflags,
-       unsigned long           nr_segs,
-       loff_t                  *ppos)
-{
-       struct inode    *inode = file->f_mapping->host;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
-       struct kiocb    kiocb;
-       ssize_t         rval;
-
-       init_sync_kiocb(&kiocb, file);
-       kiocb.ki_pos = *ppos;
-       if (unlikely(file->f_flags & O_DIRECT))
-               ioflags |= IO_ISDIRECT;
-
-       rval = bhv_vop_write(vp, &kiocb, iov, nr_segs,
-                                &kiocb.ki_pos, ioflags, NULL);
-
-       *ppos = kiocb.ki_pos;
-       return rval;
-}
-
-STATIC ssize_t
-xfs_file_writev(
-       struct file             *file,
-       const struct iovec      *iov,
+       const struct iovec      *iov,
        unsigned long           nr_segs,
-       loff_t                  *ppos)
-{
-       return __xfs_file_writev(file, iov, 0, nr_segs, ppos);
-}
-
-STATIC ssize_t
-xfs_file_writev_invis(
-       struct file             *file,
-       const struct iovec      *iov,
-       unsigned long           nr_segs,
-       loff_t                  *ppos)
+       loff_t                  pos)
 {
-       return __xfs_file_writev(file, iov, IO_INVIS, nr_segs, ppos);
+       return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
 }
 
 STATIC ssize_t
@@ -370,7 +280,7 @@ xfs_file_readdir(
 
        /* Try fairly hard to get memory */
        do {
-               if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
+               if ((read_buf = kmalloc(rlen, GFP_KERNEL)))
                        break;
                rlen >>= 1;
        } while (rlen >= 1024);
@@ -540,8 +450,6 @@ const struct file_operations xfs_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
-       .readv          = xfs_file_readv,
-       .writev         = xfs_file_writev,
        .aio_read       = xfs_file_aio_read,
        .aio_write      = xfs_file_aio_write,
        .sendfile       = xfs_file_sendfile,
@@ -565,8 +473,6 @@ const struct file_operations xfs_invis_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
-       .readv          = xfs_file_readv_invis,
-       .writev         = xfs_file_writev_invis,
        .aio_read       = xfs_file_aio_read_invis,
        .aio_write      = xfs_file_aio_write_invis,
        .sendfile       = xfs_file_sendfile_invis,
index 6c162c3dde7efb44ee4f1abbb430591974244b82..ed3a5e1b4b6777490a7d8c6738a1959a15796543 100644 (file)
@@ -34,7 +34,7 @@ xfs_param_t xfs_params = {
        .restrict_chown = {     0,              1,              1       },
        .sgid_inherit   = {     0,              0,              1       },
        .symlink_mode   = {     0,              0,              1       },
-       .panic_mask     = {     0,              0,              127     },
+       .panic_mask     = {     0,              0,              255     },
        .error_level    = {     0,              3,              11      },
        .syncd_timer    = {     1*100,          30*100,         7200*100},
        .stats_clear    = {     0,              0,              1       },
index 6e52a5dd38d86333cd50ede6dfbe4a9c74e9c2f1..a74f854d91e6afe1d86ba2da278a733a5afa48e5 100644 (file)
@@ -653,7 +653,7 @@ xfs_attrmulti_by_handle(
 STATIC int
 xfs_ioc_space(
        bhv_desc_t              *bdp,
-       bhv_vnode_t             *vp,
+       struct inode            *inode,
        struct file             *filp,
        int                     flags,
        unsigned int            cmd,
@@ -735,7 +735,7 @@ xfs_ioctl(
                    !capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg);
+               return xfs_ioc_space(bdp, inode, filp, ioflags, cmd, arg);
 
        case XFS_IOC_DIOINFO: {
                struct dioattr  da;
@@ -763,6 +763,8 @@ xfs_ioctl(
                return xfs_ioc_fsgeometry(mp, arg);
 
        case XFS_IOC_GETVERSION:
+               return put_user(inode->i_generation, (int __user *)arg);
+
        case XFS_IOC_GETXFLAGS:
        case XFS_IOC_SETXFLAGS:
        case XFS_IOC_FSGETXATTR:
@@ -957,7 +959,7 @@ xfs_ioctl(
 STATIC int
 xfs_ioc_space(
        bhv_desc_t              *bdp,
-       bhv_vnode_t             *vp,
+       struct inode            *inode,
        struct file             *filp,
        int                     ioflags,
        unsigned int            cmd,
@@ -967,13 +969,13 @@ xfs_ioc_space(
        int                     attr_flags = 0;
        int                     error;
 
-       if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
+       if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
                return -XFS_ERROR(EPERM);
 
        if (!(filp->f_mode & FMODE_WRITE))
                return -XFS_ERROR(EBADF);
 
-       if (!VN_ISREG(vp))
+       if (!S_ISREG(inode->i_mode))
                return -XFS_ERROR(EINVAL);
 
        if (copy_from_user(&bf, arg, sizeof(bf)))
@@ -1264,13 +1266,6 @@ xfs_ioc_xattr(
                break;
        }
 
-       case XFS_IOC_GETVERSION: {
-               flags = vn_to_inode(vp)->i_generation;
-               if (copy_to_user(arg, &flags, sizeof(flags)))
-                       error = -EFAULT;
-               break;
-       }
-
        default:
                error = -ENOTTY;
                break;
index d9180020de6328fa8dbbeb17f68027805d368fae..3ba814ae3bba536c2eaeb99e2e530ffc4239e7b1 100644 (file)
@@ -553,13 +553,13 @@ xfs_vn_follow_link(
        ASSERT(dentry);
        ASSERT(nd);
 
-       link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+       link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
        if (!link) {
                nd_set_link(nd, ERR_PTR(-ENOMEM));
                return NULL;
        }
 
-       uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
+       uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
        if (!uio) {
                kfree(link);
                nd_set_link(nd, ERR_PTR(-ENOMEM));
@@ -623,12 +623,27 @@ xfs_vn_getattr(
 {
        struct inode    *inode = dentry->d_inode;
        bhv_vnode_t     *vp = vn_from_inode(inode);
-       int             error = 0;
+       bhv_vattr_t     vattr = { .va_mask = XFS_AT_STAT };
+       int             error;
 
-       if (unlikely(vp->v_flag & VMODIFIED))
-               error = vn_revalidate(vp);
-       if (!error)
-               generic_fillattr(inode, stat);
+       error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL);
+       if (likely(!error)) {
+               stat->size = i_size_read(inode);
+               stat->dev = inode->i_sb->s_dev;
+               stat->rdev = (vattr.va_rdev == 0) ? 0 :
+                               MKDEV(sysv_major(vattr.va_rdev) & 0x1ff,
+                                     sysv_minor(vattr.va_rdev));
+               stat->mode = vattr.va_mode;
+               stat->nlink = vattr.va_nlink;
+               stat->uid = vattr.va_uid;
+               stat->gid = vattr.va_gid;
+               stat->ino = vattr.va_nodeid;
+               stat->atime = vattr.va_atime;
+               stat->mtime = vattr.va_mtime;
+               stat->ctime = vattr.va_ctime;
+               stat->blocks = vattr.va_nblocks;
+               stat->blksize = vattr.va_blocksize;
+       }
        return -error;
 }
 
index a13f75c1a936a7f2c0b3ab1d74fc75fc2a146b51..2b0e0018738a09ab31a19b89152b63ac8e804053 100644 (file)
@@ -148,11 +148,7 @@ BUFFER_FNS(PrivateStart, unwritten);
                (current->flags = ((current->flags & ~(f)) | (*(sp) & (f))))
 
 #define NBPP           PAGE_SIZE
-#define DPPSHFT                (PAGE_SHIFT - 9)
 #define NDPP           (1 << (PAGE_SHIFT - 9))
-#define dtop(DD)       (((DD) + NDPP - 1) >> DPPSHFT)
-#define dtopt(DD)      ((DD) >> DPPSHFT)
-#define dpoff(DD)      ((DD) & (NDPP-1))
 
 #define NBBY           8               /* number of bits per byte */
 #define        NBPC            PAGE_SIZE       /* Number of bytes per click */
@@ -172,8 +168,6 @@ BUFFER_FNS(PrivateStart, unwritten);
 #define        btoct(x)        ((__psunsigned_t)(x)>>BPCSHIFT)
 #define        btoc64(x)       (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
 #define        btoct64(x)      ((__uint64_t)(x)>>BPCSHIFT)
-#define        io_btoc(x)      (((__psunsigned_t)(x)+(IO_NBPC-1))>>IO_BPCSHIFT)
-#define        io_btoct(x)     ((__psunsigned_t)(x)>>IO_BPCSHIFT)
 
 /* off_t bytes to clicks */
 #define offtoc(x)       (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
@@ -186,7 +180,6 @@ BUFFER_FNS(PrivateStart, unwritten);
 #define        ctob(x)         ((__psunsigned_t)(x)<<BPCSHIFT)
 #define btoct(x)        ((__psunsigned_t)(x)>>BPCSHIFT)
 #define        ctob64(x)       ((__uint64_t)(x)<<BPCSHIFT)
-#define        io_ctob(x)      ((__psunsigned_t)(x)<<IO_BPCSHIFT)
 
 /* bytes to clicks */
 #define btoc(x)         (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT)
@@ -339,4 +332,11 @@ static inline __uint64_t roundup_64(__uint64_t x, __uint32_t y)
        return(x * y);
 }
 
+static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
+{
+       x += y - 1;
+       do_div(x, y);
+       return x;
+}
+
 #endif /* __XFS_LINUX__ */
index ee788b1cb3641a355219183f9217037d04df2a94..fa842f1c9fa27b3511c86725a1cad2f3334f4b9c 100644 (file)
@@ -270,16 +270,18 @@ xfs_read(
                }
        }
 
-       if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp)))
-               bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
-                                               -1, FI_REMAPF_LOCKED);
-
-       if (unlikely(ioflags & IO_ISDIRECT))
+       if (unlikely(ioflags & IO_ISDIRECT)) {
+               if (VN_CACHED(vp))
+                       bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
+                                                -1, FI_REMAPF_LOCKED);
                mutex_unlock(&inode->i_mutex);
+       }
 
        xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
                                (void *)iovp, segs, *offset, ioflags);
-       ret = __generic_file_aio_read(iocb, iovp, segs, offset);
+
+       iocb->ki_pos = *offset;
+       ret = generic_file_aio_read(iocb, iovp, segs, *offset);
        if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO))
                ret = wait_on_sync_kiocb(iocb);
        if (ret > 0)
index 4754f342a5d3b0cf8f9f57790fa63ed1012ee92a..38c4d128a8c0c8675f05f6672fefd3f058dd85c2 100644 (file)
@@ -171,7 +171,6 @@ xfs_revalidate_inode(
                break;
        }
 
-       inode->i_blksize = xfs_preferred_iosize(mp);
        inode->i_generation = ip->i_d.di_gen;
        i_size_write(inode, ip->i_d.di_size);
        inode->i_blocks =
@@ -228,7 +227,9 @@ xfs_initialize_vnode(
                xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
                xfs_set_inodeops(inode);
 
+               spin_lock(&ip->i_flags_lock);
                ip->i_flags &= ~XFS_INEW;
+               spin_unlock(&ip->i_flags_lock);
                barrier();
 
                unlock_new_inode(inode);
index 91fc2c4b3353f1f4ea96ed51de25ade3f4304f76..da255bdf526036995fcb50340c96f89aff8f81e6 100644 (file)
@@ -79,7 +79,7 @@ typedef enum {
 #define VFS_RDONLY             0x0001  /* read-only vfs */
 #define VFS_GRPID              0x0002  /* group-ID assigned from directory */
 #define VFS_DMI                        0x0004  /* filesystem has the DMI enabled */
-#define VFS_UMOUNT             0x0008  /* unmount in progress */
+/* ---- VFS_UMOUNT ----                0x0008  -- unneeded, fixed via kthread APIs */
 #define VFS_32BITINODES                0x0010  /* do not use inums above 32 bits */
 #define VFS_END                        0x0010  /* max flag */
 
index 6628d96b6fd6a02cfba135c50976ff154def34bc..553fa731ade5e5320a5cf85d73450ef5b10c69f1 100644 (file)
@@ -122,7 +122,6 @@ vn_revalidate_core(
        inode->i_blocks     = vap->va_nblocks;
        inode->i_mtime      = vap->va_mtime;
        inode->i_ctime      = vap->va_ctime;
-       inode->i_blksize    = vap->va_blocksize;
        if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
                inode->i_flags |= S_IMMUTABLE;
        else
index c42b3221b20cb95a0a1303b2d6c51a4aff071148..515f5fdea57a0af1317bf4d03827685dfbd2fb00 100644 (file)
@@ -85,8 +85,6 @@ typedef enum {
 #define VN_BHV_HEAD(vp)                        ((bhv_head_t *)(&((vp)->v_bh)))
 #define vn_bhv_head_init(bhp,name)     bhv_head_init(bhp,name)
 #define vn_bhv_remove(bhp,bdp)         bhv_remove(bhp,bdp)
-#define vn_bhv_lookup(bhp,ops)         bhv_lookup(bhp,ops)
-#define vn_bhv_lookup_unlocked(bhp,ops) bhv_lookup_unlocked(bhp,ops)
 
 /*
  * Vnode to Linux inode mapping.
index 5b2dcc58b24430105bcca1860d7a589e811a3228..33ad5af386e03ed21cfee5b747341af6e5fd8d3e 100644 (file)
@@ -381,18 +381,6 @@ xfs_qm_dquot_logitem_unlock(
 }
 
 
-/*
- * The transaction with the dquot locked has aborted.  The dquot
- * must not be dirty within the transaction.  We simply unlock just
- * as if the transaction had been cancelled.
- */
-STATIC void
-xfs_qm_dquot_logitem_abort(
-       xfs_dq_logitem_t    *ql)
-{
-       xfs_qm_dquot_logitem_unlock(ql);
-}
-
 /*
  * this needs to stamp an lsn into the dquot, I think.
  * rpc's that look at user dquot's would then have to
@@ -426,7 +414,6 @@ STATIC struct xfs_item_ops xfs_dquot_item_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_qm_dquot_logitem_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_abort,
        .iop_pushbuf    = (void(*)(xfs_log_item_t*))
                                        xfs_qm_dquot_logitem_pushbuf,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
@@ -558,17 +545,6 @@ xfs_qm_qoff_logitem_committed(xfs_qoff_logitem_t *qf, xfs_lsn_t lsn)
        return (lsn);
 }
 
-/*
- * The transaction of which this QUOTAOFF is a part has been aborted.
- * Just clean up after ourselves.
- * Shouldn't this never happen in the case of qoffend logitems? XXX
- */
-STATIC void
-xfs_qm_qoff_logitem_abort(xfs_qoff_logitem_t *qf)
-{
-       kmem_free(qf, sizeof(xfs_qoff_logitem_t));
-}
-
 /*
  * There isn't much you can do to push on an quotaoff item.  It is simply
  * stuck waiting for the log to be flushed to disk.
@@ -644,7 +620,6 @@ STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_qm_qoffend_logitem_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_abort,
        .iop_pushbuf    = NULL,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_qm_qoffend_logitem_committing
@@ -667,7 +642,6 @@ STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_qm_qoff_logitem_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_abort,
        .iop_pushbuf    = NULL,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_qm_qoff_logitem_committing
index e23e45535c48219855daa75be9aa60d2f977c790..7c6a3a50379e2a543fac68acf60774909fc9097c 100644 (file)
@@ -112,17 +112,17 @@ xfs_Gqm_init(void)
 {
        xfs_dqhash_t    *udqhash, *gdqhash;
        xfs_qm_t        *xqm;
-       uint            i, hsize, flags = KM_SLEEP | KM_MAYFAIL;
+       size_t          hsize;
+       uint            i;
 
        /*
         * Initialize the dquot hash tables.
         */
-       hsize = XFS_QM_HASHSIZE_HIGH;
-       while (!(udqhash = kmem_zalloc(hsize * sizeof(xfs_dqhash_t), flags))) {
-               if ((hsize >>= 1) <= XFS_QM_HASHSIZE_LOW)
-                       flags = KM_SLEEP;
-       }
-       gdqhash = kmem_zalloc(hsize * sizeof(xfs_dqhash_t), KM_SLEEP);
+       udqhash = kmem_zalloc_greedy(&hsize,
+                                    XFS_QM_HASHSIZE_LOW, XFS_QM_HASHSIZE_HIGH,
+                                    KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+       gdqhash = kmem_zalloc(hsize, KM_SLEEP | KM_LARGE);
+       hsize /= sizeof(xfs_dqhash_t);
        ndquot = hsize << 8;
 
        xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
index 4568deb6da867dcae2c446d034b8dbe5dba95fb3..689407de0a20684ad71513fca7873712ac50648d 100644 (file)
@@ -55,12 +55,6 @@ extern kmem_zone_t   *qm_dqtrxzone;
 #define XFS_QM_HASHSIZE_LOW            (NBPP / sizeof(xfs_dqhash_t))
 #define XFS_QM_HASHSIZE_HIGH           ((NBPP * 4) / sizeof(xfs_dqhash_t))
 
-/*
- * We output a cmn_err when quotachecking a quota file with more than
- * this many fsbs.
- */
-#define XFS_QM_BIG_QCHECK_NBLKS                500
-
 /*
  * This defines the unit of allocation of dquots.
  * Currently, it is just one file system block, and a 4K blk contains 30
index b7ddd04aae327b1cd6f7c4df66844879de765fca..a8b85e2be9d5cf34d10ecaa332d4b9257a82efd1 100644 (file)
@@ -75,7 +75,6 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
 
 #define xfs_qm_freelist_lock(qm)       XQMLCK(&((qm)->qm_dqfreelist))
 #define xfs_qm_freelist_unlock(qm)     XQMUNLCK(&((qm)->qm_dqfreelist))
-#define XFS_QM_IS_FREELIST_LOCKED(qm)  XQMISLCKD(&((qm)->qm_dqfreelist))
 
 /*
  * Hash into a bucket in the dquot hash table, based on <mp, id>.
@@ -170,6 +169,5 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
 #define DQFLAGTO_TYPESTR(d)    (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
                                 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
                                 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
-#define DQFLAGTO_DIRTYSTR(d)   (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
 
 #endif /* __XFS_QUOTA_PRIV_H__ */
index addf5a7ea06c40f879d40d1e8117c15cf01e21c5..5cf2e86caa7198653b37f086bf02335d2599fad6 100644 (file)
@@ -75,7 +75,7 @@ ktrace_alloc(int nentries, unsigned int __nocast sleep)
                                                            sleep);
        } else {
                ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
-                                                           sleep);
+                                                           sleep | KM_LARGE);
        }
 
        if (ktep == NULL) {
index dc2361dd740aedbc3ee1695e30ef50094a6b8f6d..9ece7f87ec5b29b62d28e2cb756a88028240c7b1 100644 (file)
@@ -150,7 +150,7 @@ typedef struct xfs_agi {
 #define        XFS_BUF_TO_AGFL(bp)     ((xfs_agfl_t *)XFS_BUF_PTR(bp))
 
 typedef struct xfs_agfl {
-       xfs_agblock_t   agfl_bno[1];    /* actually XFS_AGFL_SIZE(mp) */
+       __be32          agfl_bno[1];    /* actually XFS_AGFL_SIZE(mp) */
 } xfs_agfl_t;
 
 /*
index d2bbcd882a69578174110f3655e4aadf190a52f4..e80dda3437d196345b0d19cded4cac518b4e0eda 100644 (file)
@@ -1477,8 +1477,10 @@ xfs_alloc_ag_vextent_small(
        /*
         * Can't allocate from the freelist for some reason.
         */
-       else
+       else {
+               fbno = NULLAGBLOCK;
                flen = 0;
+       }
        /*
         * Can't do the allocation, give up.
         */
@@ -2021,7 +2023,7 @@ xfs_alloc_get_freelist(
        /*
         * Get the block number and update the data structures.
         */
-       bno = INT_GET(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)], ARCH_CONVERT);
+       bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
        be32_add(&agf->agf_flfirst, 1);
        xfs_trans_brelse(tp, agflbp);
        if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
@@ -2108,7 +2110,7 @@ xfs_alloc_put_freelist(
 {
        xfs_agf_t               *agf;   /* a.g. freespace structure */
        xfs_agfl_t              *agfl;  /* a.g. free block array */
-       xfs_agblock_t           *blockp;/* pointer to array entry */
+       __be32                  *blockp;/* pointer to array entry */
        int                     error;
 #ifdef XFS_ALLOC_TRACE
        static char             fname[] = "xfs_alloc_put_freelist";
@@ -2132,7 +2134,7 @@ xfs_alloc_put_freelist(
        pag->pagf_flcount++;
        ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
        blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
-       INT_SET(*blockp, ARCH_CONVERT, bno);
+       *blockp = cpu_to_be32(bno);
        TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
        xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
        xfs_trans_log_buf(tp, agflbp,
index 7446556e8021092cecbba838bf9fa9214cf2ed01..74cadf95d4e84de19879cbcfea33e6d41433f9fb 100644 (file)
@@ -92,6 +92,7 @@ xfs_alloc_delrec(
        xfs_alloc_key_t         *rkp;   /* right block key pointer */
        xfs_alloc_ptr_t         *rpp;   /* right block address pointer */
        int                     rrecs=0;        /* number of records in right block */
+       int                     numrecs;
        xfs_alloc_rec_t         *rrp;   /* right block record pointer */
        xfs_btree_cur_t         *tcur;  /* temporary btree cursor */
 
@@ -115,7 +116,8 @@ xfs_alloc_delrec(
        /*
         * Fail if we're off the end of the block.
         */
-       if (ptr > be16_to_cpu(block->bb_numrecs)) {
+       numrecs = be16_to_cpu(block->bb_numrecs);
+       if (ptr > numrecs) {
                *stat = 0;
                return 0;
        }
@@ -129,18 +131,18 @@ xfs_alloc_delrec(
                lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
                lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 #ifdef DEBUG
-               for (i = ptr; i < be16_to_cpu(block->bb_numrecs); i++) {
+               for (i = ptr; i < numrecs; i++) {
                        if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level)))
                                return error;
                }
 #endif
-               if (ptr < be16_to_cpu(block->bb_numrecs)) {
+               if (ptr < numrecs) {
                        memmove(&lkp[ptr - 1], &lkp[ptr],
-                               (be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lkp));
+                               (numrecs - ptr) * sizeof(*lkp));
                        memmove(&lpp[ptr - 1], &lpp[ptr],
-                               (be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lpp));
-                       xfs_alloc_log_ptrs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
-                       xfs_alloc_log_keys(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
+                               (numrecs - ptr) * sizeof(*lpp));
+                       xfs_alloc_log_ptrs(cur, bp, ptr, numrecs - 1);
+                       xfs_alloc_log_keys(cur, bp, ptr, numrecs - 1);
                }
        }
        /*
@@ -149,10 +151,10 @@ xfs_alloc_delrec(
         */
        else {
                lrp = XFS_ALLOC_REC_ADDR(block, 1, cur);
-               if (ptr < be16_to_cpu(block->bb_numrecs)) {
+               if (ptr < numrecs) {
                        memmove(&lrp[ptr - 1], &lrp[ptr],
-                               (be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lrp));
-                       xfs_alloc_log_recs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
+                               (numrecs - ptr) * sizeof(*lrp));
+                       xfs_alloc_log_recs(cur, bp, ptr, numrecs - 1);
                }
                /*
                 * If it's the first record in the block, we'll need a key
@@ -167,7 +169,8 @@ xfs_alloc_delrec(
        /*
         * Decrement and log the number of entries in the block.
         */
-       be16_add(&block->bb_numrecs, -1);
+       numrecs--;
+       block->bb_numrecs = cpu_to_be16(numrecs);
        xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
        /*
         * See if the longest free extent in the allocation group was
@@ -181,14 +184,14 @@ xfs_alloc_delrec(
        if (level == 0 &&
            cur->bc_btnum == XFS_BTNUM_CNT &&
            be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&
-           ptr > be16_to_cpu(block->bb_numrecs)) {
-               ASSERT(ptr == be16_to_cpu(block->bb_numrecs) + 1);
+           ptr > numrecs) {
+               ASSERT(ptr == numrecs + 1);
                /*
                 * There are still records in the block.  Grab the size
                 * from the last one.
                 */
-               if (be16_to_cpu(block->bb_numrecs)) {
-                       rrp = XFS_ALLOC_REC_ADDR(block, be16_to_cpu(block->bb_numrecs), cur);
+               if (numrecs) {
+                       rrp = XFS_ALLOC_REC_ADDR(block, numrecs, cur);
                        agf->agf_longest = rrp->ar_blockcount;
                }
                /*
@@ -211,7 +214,7 @@ xfs_alloc_delrec(
                 * and it's NOT the leaf level,
                 * then we can get rid of this level.
                 */
-               if (be16_to_cpu(block->bb_numrecs) == 1 && level > 0) {
+               if (numrecs == 1 && level > 0) {
                        /*
                         * lpp is still set to the first pointer in the block.
                         * Make it the new root of the btree.
@@ -267,7 +270,7 @@ xfs_alloc_delrec(
         * If the number of records remaining in the block is at least
         * the minimum, we're done.
         */
-       if (be16_to_cpu(block->bb_numrecs) >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
+       if (numrecs >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
                if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
                        return error;
                *stat = 1;
@@ -419,19 +422,21 @@ xfs_alloc_delrec(
         * See if we can join with the left neighbor block.
         */
        if (lbno != NULLAGBLOCK &&
-           lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
+           lrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
                /*
                 * Set "right" to be the starting block,
                 * "left" to be the left neighbor.
                 */
                rbno = bno;
                right = block;
+               rrecs = be16_to_cpu(right->bb_numrecs);
                rbp = bp;
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
                                cur->bc_private.a.agno, lbno, 0, &lbp,
                                XFS_ALLOC_BTREE_REF)))
                        return error;
                left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
+               lrecs = be16_to_cpu(left->bb_numrecs);
                if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
                        return error;
        }
@@ -439,20 +444,21 @@ xfs_alloc_delrec(
         * If that won't work, see if we can join with the right neighbor block.
         */
        else if (rbno != NULLAGBLOCK &&
-                rrecs + be16_to_cpu(block->bb_numrecs) <=
-                 XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
+                rrecs + numrecs <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
                /*
                 * Set "left" to be the starting block,
                 * "right" to be the right neighbor.
                 */
                lbno = bno;
                left = block;
+               lrecs = be16_to_cpu(left->bb_numrecs);
                lbp = bp;
                if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
                                cur->bc_private.a.agno, rbno, 0, &rbp,
                                XFS_ALLOC_BTREE_REF)))
                        return error;
                right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
+               rrecs = be16_to_cpu(right->bb_numrecs);
                if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
                        return error;
        }
@@ -474,34 +480,28 @@ xfs_alloc_delrec(
                /*
                 * It's a non-leaf.  Move keys and pointers.
                 */
-               lkp = XFS_ALLOC_KEY_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
-               lpp = XFS_ALLOC_PTR_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
+               lkp = XFS_ALLOC_KEY_ADDR(left, lrecs + 1, cur);
+               lpp = XFS_ALLOC_PTR_ADDR(left, lrecs + 1, cur);
                rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
                rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
 #ifdef DEBUG
-               for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
+               for (i = 0; i < rrecs; i++) {
                        if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
                                return error;
                }
 #endif
-               memcpy(lkp, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*lkp));
-               memcpy(lpp, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*lpp));
-               xfs_alloc_log_keys(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
-                                  be16_to_cpu(left->bb_numrecs) +
-                                  be16_to_cpu(right->bb_numrecs));
-               xfs_alloc_log_ptrs(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
-                                  be16_to_cpu(left->bb_numrecs) +
-                                  be16_to_cpu(right->bb_numrecs));
+               memcpy(lkp, rkp, rrecs * sizeof(*lkp));
+               memcpy(lpp, rpp, rrecs * sizeof(*lpp));
+               xfs_alloc_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs);
+               xfs_alloc_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs);
        } else {
                /*
                 * It's a leaf.  Move records.
                 */
-               lrp = XFS_ALLOC_REC_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
+               lrp = XFS_ALLOC_REC_ADDR(left, lrecs + 1, cur);
                rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
-               memcpy(lrp, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*lrp));
-               xfs_alloc_log_recs(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
-                                  be16_to_cpu(left->bb_numrecs) +
-                                  be16_to_cpu(right->bb_numrecs));
+               memcpy(lrp, rrp, rrecs * sizeof(*lrp));
+               xfs_alloc_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs);
        }
        /*
         * If we joined with the left neighbor, set the buffer in the
@@ -509,7 +509,7 @@ xfs_alloc_delrec(
         */
        if (bp != lbp) {
                xfs_btree_setbuf(cur, level, lbp);
-               cur->bc_ptrs[level] += be16_to_cpu(left->bb_numrecs);
+               cur->bc_ptrs[level] += lrecs;
        }
        /*
         * If we joined with the right neighbor and there's a level above
@@ -521,7 +521,8 @@ xfs_alloc_delrec(
        /*
         * Fix up the number of records in the surviving block.
         */
-       be16_add(&left->bb_numrecs, be16_to_cpu(right->bb_numrecs));
+       lrecs += rrecs;
+       left->bb_numrecs = cpu_to_be16(lrecs);
        /*
         * Fix up the right block pointer in the surviving block, and log it.
         */
@@ -608,6 +609,7 @@ xfs_alloc_insrec(
        xfs_btree_cur_t         *ncur;  /* new cursor to be used at next lvl */
        xfs_alloc_key_t         nkey;   /* new key value, from split */
        xfs_alloc_rec_t         nrec;   /* new record value, for caller */
+       int                     numrecs;
        int                     optr;   /* old ptr value */
        xfs_alloc_ptr_t         *pp;    /* pointer to btree addresses */
        int                     ptr;    /* index in btree block for this rec */
@@ -653,13 +655,14 @@ xfs_alloc_insrec(
         */
        bp = cur->bc_bufs[level];
        block = XFS_BUF_TO_ALLOC_BLOCK(bp);
+       numrecs = be16_to_cpu(block->bb_numrecs);
 #ifdef DEBUG
        if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
                return error;
        /*
         * Check that the new entry is being inserted in the right place.
         */
-       if (ptr <= be16_to_cpu(block->bb_numrecs)) {
+       if (ptr <= numrecs) {
                if (level == 0) {
                        rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
                        xfs_btree_check_rec(cur->bc_btnum, recp, rp);
@@ -670,12 +673,12 @@ xfs_alloc_insrec(
        }
 #endif
        nbno = NULLAGBLOCK;
-       ncur = (xfs_btree_cur_t *)0;
+       ncur = NULL;
        /*
         * If the block is full, we can't insert the new entry until we
         * make the block un-full.
         */
-       if (be16_to_cpu(block->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
+       if (numrecs == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
                /*
                 * First, try shifting an entry to the right neighbor.
                 */
@@ -729,6 +732,7 @@ xfs_alloc_insrec(
         * At this point we know there's room for our new entry in the block
         * we're pointing at.
         */
+       numrecs = be16_to_cpu(block->bb_numrecs);
        if (level > 0) {
                /*
                 * It's a non-leaf entry.  Make a hole for the new data
@@ -737,15 +741,15 @@ xfs_alloc_insrec(
                kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
                pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
 #ifdef DEBUG
-               for (i = be16_to_cpu(block->bb_numrecs); i >= ptr; i--) {
+               for (i = numrecs; i >= ptr; i--) {
                        if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level)))
                                return error;
                }
 #endif
                memmove(&kp[ptr], &kp[ptr - 1],
-                       (be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*kp));
+                       (numrecs - ptr + 1) * sizeof(*kp));
                memmove(&pp[ptr], &pp[ptr - 1],
-                       (be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*pp));
+                       (numrecs - ptr + 1) * sizeof(*pp));
 #ifdef DEBUG
                if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
                        return error;
@@ -755,11 +759,12 @@ xfs_alloc_insrec(
                 */
                kp[ptr - 1] = key;
                pp[ptr - 1] = cpu_to_be32(*bnop);
-               be16_add(&block->bb_numrecs, 1);
-               xfs_alloc_log_keys(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
-               xfs_alloc_log_ptrs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
+               numrecs++;
+               block->bb_numrecs = cpu_to_be16(numrecs);
+               xfs_alloc_log_keys(cur, bp, ptr, numrecs);
+               xfs_alloc_log_ptrs(cur, bp, ptr, numrecs);
 #ifdef DEBUG
-               if (ptr < be16_to_cpu(block->bb_numrecs))
+               if (ptr < numrecs)
                        xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
                                kp + ptr);
 #endif
@@ -769,16 +774,17 @@ xfs_alloc_insrec(
                 */
                rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
                memmove(&rp[ptr], &rp[ptr - 1],
-                       (be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*rp));
+                       (numrecs - ptr + 1) * sizeof(*rp));
                /*
                 * Now stuff the new record in, bump numrecs
                 * and log the new data.
                 */
-               rp[ptr - 1] = *recp; /* INT_: struct copy */
-               be16_add(&block->bb_numrecs, 1);
-               xfs_alloc_log_recs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
+               rp[ptr - 1] = *recp;
+               numrecs++;
+               block->bb_numrecs = cpu_to_be16(numrecs);
+               xfs_alloc_log_recs(cur, bp, ptr, numrecs);
 #ifdef DEBUG
-               if (ptr < be16_to_cpu(block->bb_numrecs))
+               if (ptr < numrecs)
                        xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
                                rp + ptr);
 #endif
@@ -819,8 +825,8 @@ xfs_alloc_insrec(
         */
        *bnop = nbno;
        if (nbno != NULLAGBLOCK) {
-               *recp = nrec; /* INT_: struct copy */
-               *curp = ncur; /* INT_: struct copy */
+               *recp = nrec;
+               *curp = ncur;
        }
        *stat = 1;
        return 0;
@@ -981,7 +987,7 @@ xfs_alloc_lookup(
                 */
                bp = cur->bc_bufs[level];
                if (bp && XFS_BUF_ADDR(bp) != d)
-                       bp = (xfs_buf_t *)0;
+                       bp = NULL;
                if (!bp) {
                        /*
                         * Need to get a new buffer.  Read it, then
@@ -1229,7 +1235,7 @@ xfs_alloc_lshift(
                if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level)))
                        return error;
 #endif
-               *lpp = *rpp; /* INT_: copy */
+               *lpp = *rpp;
                xfs_alloc_log_ptrs(cur, lbp, nrec, nrec);
                xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
        }
@@ -1406,8 +1412,8 @@ xfs_alloc_newroot(
 
                kp = XFS_ALLOC_KEY_ADDR(new, 1, cur);
                if (be16_to_cpu(left->bb_level) > 0) {
-                       kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); /* INT_: structure copy */
-                       kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);/* INT_: structure copy */
+                       kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur);
+                       kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);
                } else {
                        xfs_alloc_rec_t *rp;    /* btree record pointer */
 
@@ -1527,8 +1533,8 @@ xfs_alloc_rshift(
                if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*lpp), level)))
                        return error;
 #endif
-               *rkp = *lkp; /* INT_: copy */
-               *rpp = *lpp; /* INT_: copy */
+               *rkp = *lkp;
+               *rpp = *lpp;
                xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
                xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
                xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
@@ -2044,7 +2050,7 @@ xfs_alloc_insert(
        nbno = NULLAGBLOCK;
        nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
        nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
-       ncur = (xfs_btree_cur_t *)0;
+       ncur = NULL;
        pcur = cur;
        /*
         * Loop going up the tree, starting at the leaf level.
@@ -2076,7 +2082,7 @@ xfs_alloc_insert(
                 */
                if (ncur) {
                        pcur = ncur;
-                       ncur = (xfs_btree_cur_t *)0;
+                       ncur = NULL;
                }
        } while (nbno != NULLAGBLOCK);
        *stat = i;
index 1a210104327547b77768e6fd6cd58f7618bac090..9ada7bdbae5219a0803aac3b8c5f55a8d2f095c1 100644 (file)
@@ -91,7 +91,6 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
 /*
  * Routines to manipulate out-of-line attribute values.
  */
-STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args);
 STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
 STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
 
@@ -180,7 +179,7 @@ xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
        return(error);
 }
 
-STATIC int
+int
 xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
                 char *value, int valuelen, int flags)
 {
@@ -440,7 +439,7 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f
  * Generic handler routine to remove a name from an attribute list.
  * Transitions attribute list from Btree to shortform as necessary.
  */
-STATIC int
+int
 xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
 {
        xfs_da_args_t   args;
@@ -591,6 +590,110 @@ xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
        return xfs_attr_remove_int(dp, name, namelen, flags);
 }
 
+int                                                            /* error */
+xfs_attr_list_int(xfs_attr_list_context_t *context)
+{
+       int error;
+       xfs_inode_t *dp = context->dp;
+
+       /*
+        * Decide on what work routines to call based on the inode size.
+        */
+       if (XFS_IFORK_Q(dp) == 0 ||
+           (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+            dp->i_d.di_anextents == 0)) {
+               error = 0;
+       } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+               error = xfs_attr_shortform_list(context);
+       } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
+               error = xfs_attr_leaf_list(context);
+       } else {
+               error = xfs_attr_node_list(context);
+       }
+       return error;
+}
+
+#define        ATTR_ENTBASESIZE                /* minimum bytes used by an attr */ \
+       (((struct attrlist_ent *) 0)->a_name - (char *) 0)
+#define        ATTR_ENTSIZE(namelen)           /* actual bytes used by an attr */ \
+       ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
+        & ~(sizeof(u_int32_t)-1))
+
+/*
+ * Format an attribute and copy it out to the user's buffer.
+ * Take care to check values and protect against them changing later,
+ * we may be reading them directly out of a user buffer.
+ */
+/*ARGSUSED*/
+STATIC int
+xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp,
+                    char *name, int namelen,
+                    int valuelen, char *value)
+{
+       attrlist_ent_t *aep;
+       int arraytop;
+
+       ASSERT(!(context->flags & ATTR_KERNOVAL));
+       ASSERT(context->count >= 0);
+       ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
+       ASSERT(context->firstu >= sizeof(*context->alist));
+       ASSERT(context->firstu <= context->bufsize);
+
+       arraytop = sizeof(*context->alist) +
+                       context->count * sizeof(context->alist->al_offset[0]);
+       context->firstu -= ATTR_ENTSIZE(namelen);
+       if (context->firstu < arraytop) {
+               xfs_attr_trace_l_c("buffer full", context);
+               context->alist->al_more = 1;
+               context->seen_enough = 1;
+               return 1;
+       }
+
+       aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
+       aep->a_valuelen = valuelen;
+       memcpy(aep->a_name, name, namelen);
+       aep->a_name[ namelen ] = 0;
+       context->alist->al_offset[ context->count++ ] = context->firstu;
+       context->alist->al_count = context->count;
+       xfs_attr_trace_l_c("add", context);
+       return 0;
+}
+
+STATIC int
+xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp,
+                    char *name, int namelen,
+                    int valuelen, char *value)
+{
+       char *offset;
+       int arraytop;
+
+       ASSERT(context->count >= 0);
+
+       arraytop = context->count + namesp->attr_namelen + namelen + 1;
+       if (arraytop > context->firstu) {
+               context->count = -1;    /* insufficient space */
+               return 1;
+       }
+       offset = (char *)context->alist + context->count;
+       strncpy(offset, namesp->attr_name, namesp->attr_namelen);
+       offset += namesp->attr_namelen;
+       strncpy(offset, name, namelen);                 /* real name */
+       offset += namelen;
+       *offset = '\0';
+       context->count += namesp->attr_namelen + namelen + 1;
+       return 0;
+}
+
+/*ARGSUSED*/
+STATIC int
+xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
+                    char *name, int namelen,
+                    int valuelen, char *value)
+{
+       context->count += namesp->attr_namelen + namelen + 1;
+       return 0;
+}
+
 /*
  * Generate a list of extended attribute names and optionally
  * also value lengths.  Positive return value follows the XFS
@@ -615,13 +718,13 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
                return(XFS_ERROR(EINVAL));
        if ((cursor->initted == 0) &&
            (cursor->hashval || cursor->blkno || cursor->offset))
-               return(XFS_ERROR(EINVAL));
+               return XFS_ERROR(EINVAL);
 
        /*
         * Check for a properly aligned buffer.
         */
        if (((long)buffer) & (sizeof(int)-1))
-               return(XFS_ERROR(EFAULT));
+               return XFS_ERROR(EFAULT);
        if (flags & ATTR_KERNOVAL)
                bufsize = 0;
 
@@ -634,53 +737,47 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
        context.dupcnt = 0;
        context.resynch = 1;
        context.flags = flags;
-       if (!(flags & ATTR_KERNAMELS)) {
+       context.seen_enough = 0;
+       context.alist = (attrlist_t *)buffer;
+       context.put_value = 0;
+
+       if (flags & ATTR_KERNAMELS) {
+               context.bufsize = bufsize;
+               context.firstu = context.bufsize;
+               if (flags & ATTR_KERNOVAL)
+                       context.put_listent = xfs_attr_kern_list_sizes;
+               else
+                       context.put_listent = xfs_attr_kern_list;
+       } else {
                context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
                context.firstu = context.bufsize;
-               context.alist = (attrlist_t *)buffer;
                context.alist->al_count = 0;
                context.alist->al_more = 0;
                context.alist->al_offset[0] = context.bufsize;
-       }
-       else {
-               context.bufsize = bufsize;
-               context.firstu = context.bufsize;
-               context.alist = (attrlist_t *)buffer;
+               context.put_listent = xfs_attr_put_listent;
        }
 
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
-               return (EIO);
+               return EIO;
 
        xfs_ilock(dp, XFS_ILOCK_SHARED);
-       /*
-        * Decide on what work routines to call based on the inode size.
-        */
        xfs_attr_trace_l_c("syscall start", &context);
-       if (XFS_IFORK_Q(dp) == 0 ||
-           (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
-            dp->i_d.di_anextents == 0)) {
-               error = 0;
-       } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
-               error = xfs_attr_shortform_list(&context);
-       } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
-               error = xfs_attr_leaf_list(&context);
-       } else {
-               error = xfs_attr_node_list(&context);
-       }
+
+       error = xfs_attr_list_int(&context);
+
        xfs_iunlock(dp, XFS_ILOCK_SHARED);
        xfs_attr_trace_l_c("syscall end", &context);
 
-       if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) {
-               ASSERT(error >= 0);
-       }
-       else {  /* must return negated buffer size or the error */
+       if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) {
+               /* must return negated buffer size or the error */
                if (context.count < 0)
                        error = XFS_ERROR(ERANGE);
                else
                        error = -context.count;
-       }
+       } else
+               ASSERT(error >= 0);
 
-       return(error);
+       return error;
 }
 
 int                                                            /* error */
@@ -1122,19 +1219,19 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
        context->cursor->blkno = 0;
        error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
        if (error)
-               return(error);
+               return XFS_ERROR(error);
        ASSERT(bp != NULL);
        leaf = bp->data;
        if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) {
                XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
                                     context->dp->i_mount, leaf);
                xfs_da_brelse(NULL, bp);
-               return(XFS_ERROR(EFSCORRUPTED));
+               return XFS_ERROR(EFSCORRUPTED);
        }
 
-       (void)xfs_attr_leaf_list_int(bp, context);
+       error = xfs_attr_leaf_list_int(bp, context);
        xfs_da_brelse(NULL, bp);
-       return(0);
+       return XFS_ERROR(error);
 }
 
 
@@ -1858,8 +1955,12 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
                        return(XFS_ERROR(EFSCORRUPTED));
                }
                error = xfs_attr_leaf_list_int(bp, context);
-               if (error || !leaf->hdr.info.forw)
-                       break;  /* not really an error, buffer full or EOF */
+               if (error) {
+                       xfs_da_brelse(NULL, bp);
+                       return error;
+               }
+               if (context->seen_enough || leaf->hdr.info.forw == 0)
+                       break;
                cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
                xfs_da_brelse(NULL, bp);
                error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
@@ -1886,7 +1987,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
  * Read the value associated with an attribute from the out-of-line buffer
  * that we stored it in.
  */
-STATIC int
+int
 xfs_attr_rmtval_get(xfs_da_args_t *args)
 {
        xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
index 981633f6c077cb96128bbe730b3deb7809f16bc4..783977d3ea7192cdd8109aac8f7b05895964b6dd 100644 (file)
@@ -37,6 +37,7 @@
 
 struct cred;
 struct bhv_vnode;
+struct xfs_attr_list_context;
 
 typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
 typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
@@ -160,13 +161,16 @@ struct xfs_da_args;
  */
 int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
 int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
+int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
 int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
-int xfs_attr_list(bhv_desc_t *, char *, int, int,
-                        struct attrlist_cursor_kern *, struct cred *);
+int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
+int xfs_attr_list(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *);
+int xfs_attr_list_int(struct xfs_attr_list_context *);
 int xfs_attr_inactive(struct xfs_inode *dp);
 
 int xfs_attr_shortform_getvalue(struct xfs_da_args *);
 int xfs_attr_fetch(struct xfs_inode *, const char *, int,
                        char *, int *, int, struct cred *);
+int xfs_attr_rmtval_get(struct xfs_da_args *args);
 
 #endif /* __XFS_ATTR_H__ */
index 9455051f01208e61ae7d32cf9ab2cbad858d5fe7..9719bbef122ce355c20894a51d424e4b264be933 100644 (file)
@@ -89,9 +89,46 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
                                         int dst_start, int move_count,
                                         xfs_mount_t *mp);
 STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
-STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
-                            attrnames_t *, char *name, int namelen,
-                            int valuelen);
+
+/*========================================================================
+ * Namespace helper routines
+ *========================================================================*/
+
+STATIC inline attrnames_t *
+xfs_attr_flags_namesp(int flags)
+{
+       return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
+                 ((flags & XFS_ATTR_ROOT) ? &attr_trusted : &attr_user));
+}
+
+/*
+ * If namespace bits don't match return 0.
+ * If all match then return 1.
+ */
+STATIC inline int
+xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
+{
+       return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
+}
+
+/*
+ * If namespace bits don't match and we don't have an override for it
+ * then return 0.
+ * If all match or are overridable then return 1.
+ */
+STATIC inline int
+xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
+{
+       if (((arg_flags & ATTR_SECURE) == 0) !=
+           ((ondisk_flags & XFS_ATTR_SECURE) == 0) &&
+           !(arg_flags & ATTR_KERNORMALS))
+               return 0;
+       if (((arg_flags & ATTR_ROOT) == 0) !=
+           ((ondisk_flags & XFS_ATTR_ROOT) == 0) &&
+           !(arg_flags & ATTR_KERNROOTLS))
+               return 0;
+       return 1;
+}
 
 
 /*========================================================================
@@ -228,11 +265,7 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
                        continue;
                if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
                        continue;
-               if (((args->flags & ATTR_SECURE) != 0) !=
-                   ((sfe->flags & XFS_ATTR_SECURE) != 0))
-                       continue;
-               if (((args->flags & ATTR_ROOT) != 0) !=
-                   ((sfe->flags & XFS_ATTR_ROOT) != 0))
+               if (!xfs_attr_namesp_match(args->flags, sfe->flags))
                        continue;
                ASSERT(0);
 #endif
@@ -246,8 +279,7 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
 
        sfe->namelen = args->namelen;
        sfe->valuelen = args->valuelen;
-       sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
-                       ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
+       sfe->flags = XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
        memcpy(sfe->nameval, args->name, args->namelen);
        memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
        sf->hdr.count++;
@@ -282,11 +314,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
                        continue;
                if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
                        continue;
-               if (((args->flags & ATTR_SECURE) != 0) !=
-                   ((sfe->flags & XFS_ATTR_SECURE) != 0))
-                       continue;
-               if (((args->flags & ATTR_ROOT) != 0) !=
-                   ((sfe->flags & XFS_ATTR_ROOT) != 0))
+               if (!xfs_attr_namesp_match(args->flags, sfe->flags))
                        continue;
                break;
        }
@@ -363,11 +391,7 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args)
                        continue;
                if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
                        continue;
-               if (((args->flags & ATTR_SECURE) != 0) !=
-                   ((sfe->flags & XFS_ATTR_SECURE) != 0))
-                       continue;
-               if (((args->flags & ATTR_ROOT) != 0) !=
-                   ((sfe->flags & XFS_ATTR_ROOT) != 0))
+               if (!xfs_attr_namesp_match(args->flags, sfe->flags))
                        continue;
                return(XFS_ERROR(EEXIST));
        }
@@ -394,11 +418,7 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args)
                        continue;
                if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
                        continue;
-               if (((args->flags & ATTR_SECURE) != 0) !=
-                   ((sfe->flags & XFS_ATTR_SECURE) != 0))
-                       continue;
-               if (((args->flags & ATTR_ROOT) != 0) !=
-                   ((sfe->flags & XFS_ATTR_ROOT) != 0))
+               if (!xfs_attr_namesp_match(args->flags, sfe->flags))
                        continue;
                if (args->flags & ATTR_KERNOVAL) {
                        args->valuelen = sfe->valuelen;
@@ -485,8 +505,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
                nargs.valuelen = sfe->valuelen;
                nargs.hashval = xfs_da_hashname((char *)sfe->nameval,
                                                sfe->namelen);
-               nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
-                               ((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
+               nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags);
                error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */
                ASSERT(error == ENOATTR);
                error = xfs_attr_leaf_add(bp, &nargs);
@@ -520,6 +539,10 @@ xfs_attr_shortform_compare(const void *a, const void *b)
        }
 }
 
+
+#define XFS_ISRESET_CURSOR(cursor) \
+       (!((cursor)->initted) && !((cursor)->hashval) && \
+        !((cursor)->blkno) && !((cursor)->offset))
 /*
  * Copy out entries of shortform attribute lists for attr_list().
  * Shortform attribute lists are not stored in hashval sorted order.
@@ -537,6 +560,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
        xfs_attr_sf_entry_t *sfe;
        xfs_inode_t *dp;
        int sbsize, nsbuf, count, i;
+       int error;
 
        ASSERT(context != NULL);
        dp = context->dp;
@@ -552,46 +576,51 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
        xfs_attr_trace_l_c("sf start", context);
 
        /*
-        * If the buffer is large enough, do not bother with sorting.
+        * If the buffer is large enough and the cursor is at the start,
+        * do not bother with sorting since we will return everything in
+        * one buffer and another call using the cursor won't need to be
+        * made.
         * Note the generous fudge factor of 16 overhead bytes per entry.
+        * If bufsize is zero then put_listent must be a search function
+        * and can just scan through what we have.
         */
-       if ((dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize) {
+       if (context->bufsize == 0 ||
+           (XFS_ISRESET_CURSOR(cursor) &&
+             (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
                for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
                        attrnames_t     *namesp;
 
-                       if (((context->flags & ATTR_SECURE) != 0) !=
-                           ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
-                           !(context->flags & ATTR_KERNORMALS)) {
-                               sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
-                               continue;
-                       }
-                       if (((context->flags & ATTR_ROOT) != 0) !=
-                           ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-                           !(context->flags & ATTR_KERNROOTLS)) {
+                       if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
                                sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
                                continue;
                        }
-                       namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure:
-                               ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-                                 &attr_user);
-                       if (context->flags & ATTR_KERNOVAL) {
-                               ASSERT(context->flags & ATTR_KERNAMELS);
-                               context->count += namesp->attr_namelen +
-                                       sfe->namelen + 1;
-                       }
-                       else {
-                               if (xfs_attr_put_listent(context, namesp,
-                                                  (char *)sfe->nameval,
-                                                  (int)sfe->namelen,
-                                                  (int)sfe->valuelen))
-                                       break;
-                       }
+                       namesp = xfs_attr_flags_namesp(sfe->flags);
+                       error = context->put_listent(context,
+                                          namesp,
+                                          (char *)sfe->nameval,
+                                          (int)sfe->namelen,
+                                          (int)sfe->valuelen,
+                                          (char*)&sfe->nameval[sfe->namelen]);
+
+                       /*
+                        * Either search callback finished early or
+                        * didn't fit it all in the buffer after all.
+                        */
+                       if (context->seen_enough)
+                               break;
+
+                       if (error)
+                               return error;
                        sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
                }
                xfs_attr_trace_l_c("sf big-gulp", context);
                return(0);
        }
 
+       /* do no more for a search callback */
+       if (context->bufsize == 0)
+               return 0;
+
        /*
         * It didn't all fit, so we have to sort everything on hashval.
         */
@@ -614,15 +643,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
                        kmem_free(sbuf, sbsize);
                        return XFS_ERROR(EFSCORRUPTED);
                }
-               if (((context->flags & ATTR_SECURE) != 0) !=
-                   ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
-                   !(context->flags & ATTR_KERNORMALS)) {
-                       sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
-                       continue;
-               }
-               if (((context->flags & ATTR_ROOT) != 0) !=
-                   ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-                   !(context->flags & ATTR_KERNROOTLS)) {
+               if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
                        sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
                        continue;
                }
@@ -671,24 +692,22 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
        for ( ; i < nsbuf; i++, sbp++) {
                attrnames_t     *namesp;
 
-               namesp = (sbp->flags & XFS_ATTR_SECURE) ? &attr_secure :
-                       ((sbp->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-                         &attr_user);
+               namesp = xfs_attr_flags_namesp(sbp->flags);
 
                if (cursor->hashval != sbp->hash) {
                        cursor->hashval = sbp->hash;
                        cursor->offset = 0;
                }
-               if (context->flags & ATTR_KERNOVAL) {
-                       ASSERT(context->flags & ATTR_KERNAMELS);
-                       context->count += namesp->attr_namelen +
-                                               sbp->namelen + 1;
-               } else {
-                       if (xfs_attr_put_listent(context, namesp,
-                                       sbp->name, sbp->namelen,
-                                       sbp->valuelen))
-                               break;
-               }
+               error = context->put_listent(context,
+                                       namesp,
+                                       sbp->name,
+                                       sbp->namelen,
+                                       sbp->valuelen,
+                                       &sbp->name[sbp->namelen]);
+               if (error)
+                       return error;
+               if (context->seen_enough)
+                       break;
                cursor->offset++;
        }
 
@@ -810,8 +829,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
                nargs.value = (char *)&name_loc->nameval[nargs.namelen];
                nargs.valuelen = be16_to_cpu(name_loc->valuelen);
                nargs.hashval = be32_to_cpu(entry->hashval);
-               nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
-                             ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
+               nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);
                xfs_attr_shortform_add(&nargs, forkoff);
        }
        error = 0;
@@ -1098,8 +1116,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
                                     be16_to_cpu(map->size));
        entry->hashval = cpu_to_be32(args->hashval);
        entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
-       entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
-                       ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
+       entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags);
        if (args->rename) {
                entry->flags |= XFS_ATTR_INCOMPLETE;
                if ((args->blkno2 == args->blkno) &&
@@ -1926,7 +1943,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
                else
                        break;
        }
-       ASSERT((probe >= 0) && 
+       ASSERT((probe >= 0) &&
               (!leaf->hdr.count
               || (probe < be16_to_cpu(leaf->hdr.count))));
        ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval));
@@ -1971,14 +1988,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
                        name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, probe);
                        if (name_loc->namelen != args->namelen)
                                continue;
-                       if (memcmp(args->name, (char *)name_loc->nameval,
-                                            args->namelen) != 0)
+                       if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0)
                                continue;
-                       if (((args->flags & ATTR_SECURE) != 0) !=
-                           ((entry->flags & XFS_ATTR_SECURE) != 0))
-                               continue;
-                       if (((args->flags & ATTR_ROOT) != 0) !=
-                           ((entry->flags & XFS_ATTR_ROOT) != 0))
+                       if (!xfs_attr_namesp_match(args->flags, entry->flags))
                                continue;
                        args->index = probe;
                        return(XFS_ERROR(EEXIST));
@@ -1989,11 +2001,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
                        if (memcmp(args->name, (char *)name_rmt->name,
                                             args->namelen) != 0)
                                continue;
-                       if (((args->flags & ATTR_SECURE) != 0) !=
-                           ((entry->flags & XFS_ATTR_SECURE) != 0))
-                               continue;
-                       if (((args->flags & ATTR_ROOT) != 0) !=
-                           ((entry->flags & XFS_ATTR_ROOT) != 0))
+                       if (!xfs_attr_namesp_match(args->flags, entry->flags))
                                continue;
                        args->index = probe;
                        args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
@@ -2312,8 +2320,6 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
        attrlist_cursor_kern_t *cursor;
        xfs_attr_leafblock_t *leaf;
        xfs_attr_leaf_entry_t *entry;
-       xfs_attr_leaf_name_local_t *name_loc;
-       xfs_attr_leaf_name_remote_t *name_rmt;
        int retval, i;
 
        ASSERT(bp != NULL);
@@ -2355,9 +2361,8 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
         * We have found our place, start copying out the new attributes.
         */
        retval = 0;
-       for (  ; (i < be16_to_cpu(leaf->hdr.count))
-            && (retval == 0); entry++, i++) {
-               attrnames_t     *namesp;
+       for (  ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) {
+               attrnames_t *namesp;
 
                if (be32_to_cpu(entry->hashval) != cursor->hashval) {
                        cursor->hashval = be32_to_cpu(entry->hashval);
@@ -2366,115 +2371,69 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
 
                if (entry->flags & XFS_ATTR_INCOMPLETE)
                        continue;               /* skip incomplete entries */
-               if (((context->flags & ATTR_SECURE) != 0) !=
-                   ((entry->flags & XFS_ATTR_SECURE) != 0) &&
-                   !(context->flags & ATTR_KERNORMALS))
-                       continue;               /* skip non-matching entries */
-               if (((context->flags & ATTR_ROOT) != 0) !=
-                   ((entry->flags & XFS_ATTR_ROOT) != 0) &&
-                   !(context->flags & ATTR_KERNROOTLS))
-                       continue;               /* skip non-matching entries */
-
-               namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
-                       ((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
-                         &attr_user);
+               if (!xfs_attr_namesp_match_overrides(context->flags, entry->flags))
+                       continue;
+
+               namesp = xfs_attr_flags_namesp(entry->flags);
 
                if (entry->flags & XFS_ATTR_LOCAL) {
-                       name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
-                       if (context->flags & ATTR_KERNOVAL) {
-                               ASSERT(context->flags & ATTR_KERNAMELS);
-                               context->count += namesp->attr_namelen +
-                                               (int)name_loc->namelen + 1;
-                       } else {
-                               retval = xfs_attr_put_listent(context, namesp,
-                                       (char *)name_loc->nameval,
-                                       (int)name_loc->namelen,
-                                       be16_to_cpu(name_loc->valuelen));
-                       }
+                       xfs_attr_leaf_name_local_t *name_loc =
+                               XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
+
+                       retval = context->put_listent(context,
+                                               namesp,
+                                               (char *)name_loc->nameval,
+                                               (int)name_loc->namelen,
+                                               be16_to_cpu(name_loc->valuelen),
+                                               (char *)&name_loc->nameval[name_loc->namelen]);
+                       if (retval)
+                               return retval;
                } else {
-                       name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
-                       if (context->flags & ATTR_KERNOVAL) {
-                               ASSERT(context->flags & ATTR_KERNAMELS);
-                               context->count += namesp->attr_namelen +
-                                               (int)name_rmt->namelen + 1;
-                       } else {
-                               retval = xfs_attr_put_listent(context, namesp,
-                                       (char *)name_rmt->name,
-                                       (int)name_rmt->namelen,
-                                       be32_to_cpu(name_rmt->valuelen));
+                       xfs_attr_leaf_name_remote_t *name_rmt =
+                               XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
+
+                       int valuelen = be32_to_cpu(name_rmt->valuelen);
+
+                       if (context->put_value) {
+                               xfs_da_args_t args;
+
+                               memset((char *)&args, 0, sizeof(args));
+                               args.dp = context->dp;
+                               args.whichfork = XFS_ATTR_FORK;
+                               args.valuelen = valuelen;
+                               args.value = kmem_alloc(valuelen, KM_SLEEP);
+                               args.rmtblkno = be32_to_cpu(name_rmt->valueblk);
+                               args.rmtblkcnt = XFS_B_TO_FSB(args.dp->i_mount, valuelen);
+                               retval = xfs_attr_rmtval_get(&args);
+                               if (retval)
+                                       return retval;
+                               retval = context->put_listent(context,
+                                               namesp,
+                                               (char *)name_rmt->name,
+                                               (int)name_rmt->namelen,
+                                               valuelen,
+                                               (char*)args.value);
+                               kmem_free(args.value, valuelen);
                        }
+                       else {
+                               retval = context->put_listent(context,
+                                               namesp,
+                                               (char *)name_rmt->name,
+                                               (int)name_rmt->namelen,
+                                               valuelen,
+                                               NULL);
+                       }
+                       if (retval)
+                               return retval;
                }
-               if (retval == 0) {
-                       cursor->offset++;
-               }
+               if (context->seen_enough)
+                       break;
+               cursor->offset++;
        }
        xfs_attr_trace_l_cl("blk end", context, leaf);
        return(retval);
 }
 
-#define        ATTR_ENTBASESIZE                /* minimum bytes used by an attr */ \
-       (((struct attrlist_ent *) 0)->a_name - (char *) 0)
-#define        ATTR_ENTSIZE(namelen)           /* actual bytes used by an attr */ \
-       ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
-        & ~(sizeof(u_int32_t)-1))
-
-/*
- * Format an attribute and copy it out to the user's buffer.
- * Take care to check values and protect against them changing later,
- * we may be reading them directly out of a user buffer.
- */
-/*ARGSUSED*/
-STATIC int
-xfs_attr_put_listent(xfs_attr_list_context_t *context,
-                    attrnames_t *namesp, char *name, int namelen, int valuelen)
-{
-       attrlist_ent_t *aep;
-       int arraytop;
-
-       ASSERT(!(context->flags & ATTR_KERNOVAL));
-       if (context->flags & ATTR_KERNAMELS) {
-               char *offset;
-
-               ASSERT(context->count >= 0);
-
-               arraytop = context->count + namesp->attr_namelen + namelen + 1;
-               if (arraytop > context->firstu) {
-                       context->count = -1;    /* insufficient space */
-                       return(1);
-               }
-               offset = (char *)context->alist + context->count;
-               strncpy(offset, namesp->attr_name, namesp->attr_namelen);
-               offset += namesp->attr_namelen;
-               strncpy(offset, name, namelen);                 /* real name */
-               offset += namelen;
-               *offset = '\0';
-               context->count += namesp->attr_namelen + namelen + 1;
-               return(0);
-       }
-
-       ASSERT(context->count >= 0);
-       ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
-       ASSERT(context->firstu >= sizeof(*context->alist));
-       ASSERT(context->firstu <= context->bufsize);
-
-       arraytop = sizeof(*context->alist) +
-                       context->count * sizeof(context->alist->al_offset[0]);
-       context->firstu -= ATTR_ENTSIZE(namelen);
-       if (context->firstu < arraytop) {
-               xfs_attr_trace_l_c("buffer full", context);
-               context->alist->al_more = 1;
-               return(1);
-       }
-
-       aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
-       aep->a_valuelen = valuelen;
-       memcpy(aep->a_name, name, namelen);
-       aep->a_name[ namelen ] = 0;
-       context->alist->al_offset[ context->count++ ] = context->firstu;
-       context->alist->al_count = context->count;
-       xfs_attr_trace_l_c("add", context);
-       return(0);
-}
 
 /*========================================================================
  * Manage the INCOMPLETE flag in a leaf entry
index 51c3ee156b2fdf787399710ce5b280007ff0655c..040f732ce1e22a22e513bd3afca283c1d432e167 100644 (file)
@@ -129,6 +129,19 @@ typedef struct xfs_attr_leafblock {
 #define XFS_ATTR_SECURE                (1 << XFS_ATTR_SECURE_BIT)
 #define XFS_ATTR_INCOMPLETE    (1 << XFS_ATTR_INCOMPLETE_BIT)
 
+/*
+ * Conversion macros for converting namespace bits from argument flags
+ * to ondisk flags.
+ */
+#define XFS_ATTR_NSP_ARGS_MASK         (ATTR_ROOT | ATTR_SECURE)
+#define XFS_ATTR_NSP_ONDISK_MASK       (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
+#define XFS_ATTR_NSP_ONDISK(flags)     ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
+#define XFS_ATTR_NSP_ARGS(flags)       ((flags) & XFS_ATTR_NSP_ARGS_MASK)
+#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
+                                        ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
+#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
+                                        ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
+
 /*
  * Alignment for namelist and valuelist entries (since they are mixed
  * there can be only one alignment value)
@@ -196,16 +209,26 @@ static inline int xfs_attr_leaf_entsize_local_max(int bsize)
  * Structure used to pass context around among the routines.
  *========================================================================*/
 
+
+struct xfs_attr_list_context;
+
+typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, struct attrnames *,
+                                     char *, int, int, char *);
+
 typedef struct xfs_attr_list_context {
-       struct xfs_inode                *dp;    /* inode */
-       struct attrlist_cursor_kern     *cursor;/* position in list */
-       struct attrlist                 *alist; /* output buffer */
-       int                             count;  /* num used entries */
-       int                             dupcnt; /* count dup hashvals seen */
-       int                             bufsize;/* total buffer size */
-       int                             firstu; /* first used byte in buffer */
-       int                             flags;  /* from VOP call */
-       int                             resynch;/* T/F: resynch with cursor */
+       struct xfs_inode                *dp;            /* inode */
+       struct attrlist_cursor_kern     *cursor;        /* position in list */
+       struct attrlist                 *alist;         /* output buffer */
+       int                             seen_enough;    /* T/F: seen enough of list? */
+       int                             count;          /* num used entries */
+       int                             dupcnt;         /* count dup hashvals seen */
+       int                             bufsize;        /* total buffer size */
+       int                             firstu;         /* first used byte in buffer */
+       int                             flags;          /* from VOP call */
+       int                             resynch;        /* T/F: resynch with cursor */
+       int                             put_value;      /* T/F: need value for listent */
+       put_listent_func_t              put_listent;    /* list output fmt function */
+       int                             index;          /* index into output buffer */
 } xfs_attr_list_context_t;
 
 /*
index f4fe3715a8032424975eff9f9975a8ae42260197..0dc17219d4129a821474af9c168f1010e2ee87c7 100644 (file)
@@ -109,26 +109,6 @@ bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
        prev->bd_next = bdp->bd_next;   /* remove from after prev */
 }
 
-/*
- * Look for a specific ops vector on the specified behavior chain.
- * Return the associated behavior descriptor.  Or NULL, if not found.
- */
-bhv_desc_t *
-bhv_lookup(bhv_head_t *bhp, void *ops)
-{
-       bhv_desc_t      *curdesc;
-
-       for (curdesc = bhp->bh_first;
-            curdesc != NULL;
-            curdesc = curdesc->bd_next) {
-
-               if (curdesc->bd_ops == ops)
-                       return curdesc;
-       }
-
-       return NULL;
-}
-
 /*
  * Looks for the first behavior within a specified range of positions.
  * Return the associated behavior descriptor.  Or NULL, if none found.
index 6e6e56fb352d2fc56585f923f693c9231795c912..e7ca1fed955a98ff3e15a68ac1dddcdf9e1e020a 100644 (file)
@@ -176,12 +176,10 @@ extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
  * Behavior module prototypes.
  */
 extern void            bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
-extern bhv_desc_t *    bhv_lookup(bhv_head_t *bhp, void *ops);
 extern bhv_desc_t *    bhv_lookup_range(bhv_head_t *bhp, int low, int high);
 extern bhv_desc_t *    bhv_base(bhv_head_t *bhp);
 
 /* No bhv locking on Linux */
-#define bhv_lookup_unlocked    bhv_lookup
 #define bhv_base_unlocked      bhv_base
 
 #endif /* __XFS_BEHAVIOR_H__ */
index bf46fae303af9826296dc9767fd8d696e2118862..5b050c06795fbbf3abd51b0f6c77a24daccc33f4 100644 (file)
@@ -2999,7 +2999,7 @@ xfs_bmap_btree_to_extents(
        int                     error;  /* error return value */
        xfs_ifork_t             *ifp;   /* inode fork data */
        xfs_mount_t             *mp;    /* mount point structure */
-       xfs_bmbt_ptr_t          *pp;    /* ptr to block address */
+       __be64                  *pp;    /* ptr to block address */
        xfs_bmbt_block_t        *rblock;/* root btree block */
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -3011,12 +3011,12 @@ xfs_bmap_btree_to_extents(
        ASSERT(XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes) == 1);
        mp = ip->i_mount;
        pp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, ifp->if_broot_bytes);
+       cbno = be64_to_cpu(*pp);
        *logflagsp = 0;
 #ifdef DEBUG
-       if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), 1)))
+       if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
                return error;
 #endif
-       cbno = INT_GET(*pp, ARCH_CONVERT);
        if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
                        XFS_BMAP_BTREE_REF)))
                return error;
@@ -3512,9 +3512,9 @@ xfs_bmap_extents_to_btree(
         */
        kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
        arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
-       INT_SET(kp->br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(arp));
+       kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
        pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
-       INT_SET(*pp, ARCH_CONVERT, args.fsbno);
+       *pp = cpu_to_be64(args.fsbno);
        /*
         * Do all this logging at the end so that
         * the root is at the right level.
@@ -3705,7 +3705,7 @@ STATIC xfs_bmbt_rec_t *                 /* pointer to found extent entry */
 xfs_bmap_search_extents(
        xfs_inode_t     *ip,            /* incore inode pointer */
        xfs_fileoff_t   bno,            /* block number searched for */
-       int             whichfork,      /* data or attr fork */
+       int             fork,           /* data or attr fork */
        int             *eofp,          /* out: end of file found */
        xfs_extnum_t    *lastxp,        /* out: last extent index */
        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
@@ -3713,25 +3713,28 @@ xfs_bmap_search_extents(
 {
        xfs_ifork_t     *ifp;           /* inode fork pointer */
        xfs_bmbt_rec_t  *ep;            /* extent record pointer */
-       int             rt;             /* realtime flag    */
 
        XFS_STATS_INC(xs_look_exlist);
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = XFS_IFORK_PTR(ip, fork);
 
        ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
 
-       rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
-       if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) {
-                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
-                       "start_block : %llx start_off : %llx blkcnt : %llx "
-                       "extent-state : %x \n",
-                       (ip->i_mount)->m_fsname, (long long)ip->i_ino,
+       if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
+                    !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
+               xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+                               "Access to block zero in inode %llu "
+                               "start_block: %llx start_off: %llx "
+                               "blkcnt: %llx extent-state: %x lastx: %x\n",
+                       (unsigned long long)ip->i_ino,
                        (unsigned long long)gotp->br_startblock,
                        (unsigned long long)gotp->br_startoff,
                        (unsigned long long)gotp->br_blockcount,
-                       gotp->br_state);
-        }
-        return ep;
+                       gotp->br_state, *lastxp);
+               *lastxp = NULLEXTNUM;
+               *eofp = 1;
+               return NULL;
+       }
+       return ep;
 }
 
 
@@ -4494,7 +4497,7 @@ xfs_bmap_read_extents(
        xfs_ifork_t             *ifp;   /* fork structure */
        int                     level;  /* btree level, for checking */
        xfs_mount_t             *mp;    /* file system mount structure */
-       xfs_bmbt_ptr_t          *pp;    /* pointer to block address */
+       __be64                  *pp;    /* pointer to block address */
        /* REFERENCED */
        xfs_extnum_t            room;   /* number of entries there's room for */
 
@@ -4510,10 +4513,10 @@ xfs_bmap_read_extents(
        level = be16_to_cpu(block->bb_level);
        ASSERT(level > 0);
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
-       ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
-       ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
-       ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
-       bno = INT_GET(*pp, ARCH_CONVERT);
+       bno = be64_to_cpu(*pp);
+       ASSERT(bno != NULLDFSBNO);
+       ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+       ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
        /*
         * Go down the tree until leaf level is reached, following the first
         * pointer (leftmost) at each level.
@@ -4530,10 +4533,8 @@ xfs_bmap_read_extents(
                        break;
                pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
                        1, mp->m_bmap_dmxr[1]);
-               XFS_WANT_CORRUPTED_GOTO(
-                       XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)),
-                       error0);
-               bno = INT_GET(*pp, ARCH_CONVERT);
+               bno = be64_to_cpu(*pp);
+               XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
                xfs_trans_brelse(tp, bp);
        }
        /*
@@ -6141,7 +6142,7 @@ xfs_check_block(
        short                   sz)
 {
        int                     i, j, dmxr;
-       xfs_bmbt_ptr_t          *pp, *thispa;   /* pointer to block address */
+       __be64                  *pp, *thispa;   /* pointer to block address */
        xfs_bmbt_key_t          *prevp, *keyp;
 
        ASSERT(be16_to_cpu(block->bb_level) > 0);
@@ -6179,11 +6180,10 @@ xfs_check_block(
                                thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
                                        xfs_bmbt, block, j, dmxr);
                        }
-                       if (INT_GET(*thispa, ARCH_CONVERT) ==
-                           INT_GET(*pp, ARCH_CONVERT)) {
+                       if (*thispa == *pp) {
                                cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
                                        __FUNCTION__, j, i,
-                                       INT_GET(*thispa, ARCH_CONVERT));
+                                       (unsigned long long)be64_to_cpu(*thispa));
                                panic("%s: ptrs are equal in node\n",
                                        __FUNCTION__);
                        }
@@ -6210,7 +6210,7 @@ xfs_bmap_check_leaf_extents(
        xfs_ifork_t             *ifp;   /* fork structure */
        int                     level;  /* btree level, for checking */
        xfs_mount_t             *mp;    /* file system mount structure */
-       xfs_bmbt_ptr_t          *pp;    /* pointer to block address */
+       __be64                  *pp;    /* pointer to block address */
        xfs_bmbt_rec_t          *ep;    /* pointer to current extent */
        xfs_bmbt_rec_t          *lastp; /* pointer to previous extent */
        xfs_bmbt_rec_t          *nextp; /* pointer to next extent */
@@ -6231,10 +6231,12 @@ xfs_bmap_check_leaf_extents(
        ASSERT(level > 0);
        xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
-       ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
-       ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
-       ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
-       bno = INT_GET(*pp, ARCH_CONVERT);
+       bno = be64_to_cpu(*pp);
+
+       ASSERT(bno != NULLDFSBNO);
+       ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+       ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
+
        /*
         * Go down the tree until leaf level is reached, following the first
         * pointer (leftmost) at each level.
@@ -6265,8 +6267,8 @@ xfs_bmap_check_leaf_extents(
                xfs_check_block(block, mp, 0, 0);
                pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
                        1, mp->m_bmap_dmxr[1]);
-               XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)), error0);
-               bno = INT_GET(*pp, ARCH_CONVERT);
+               bno = be64_to_cpu(*pp);
+               XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
                if (bp_release) {
                        bp_release = 0;
                        xfs_trans_brelse(NULL, bp);
@@ -6372,7 +6374,7 @@ xfs_bmap_count_blocks(
        xfs_ifork_t             *ifp;   /* fork structure */
        int                     level;  /* btree level, for checking */
        xfs_mount_t             *mp;    /* file system mount structure */
-       xfs_bmbt_ptr_t          *pp;    /* pointer to block address */
+       __be64                  *pp;    /* pointer to block address */
 
        bno = NULLFSBLOCK;
        mp = ip->i_mount;
@@ -6395,10 +6397,10 @@ xfs_bmap_count_blocks(
        level = be16_to_cpu(block->bb_level);
        ASSERT(level > 0);
        pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
-       ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
-       ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
-       ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
-       bno = INT_GET(*pp, ARCH_CONVERT);
+       bno = be64_to_cpu(*pp);
+       ASSERT(bno != NULLDFSBNO);
+       ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
+       ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
 
        if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
                XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
@@ -6425,7 +6427,7 @@ xfs_bmap_count_tree(
        int                     error;
        xfs_buf_t               *bp, *nbp;
        int                     level = levelin;
-       xfs_bmbt_ptr_t          *pp;
+       __be64                  *pp;
        xfs_fsblock_t           bno = blockno;
        xfs_fsblock_t           nextbno;
        xfs_bmbt_block_t        *block, *nextblock;
@@ -6452,7 +6454,7 @@ xfs_bmap_count_tree(
                /* Dive to the next level */
                pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
                        xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
-               bno = INT_GET(*pp, ARCH_CONVERT);
+               bno = be64_to_cpu(*pp);
                if (unlikely((error =
                     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
                        xfs_trans_brelse(tp, bp);
index 18fb7385d719fe4ad25b5f64ff23ec55d710d060..a7b835bf870ae123b0e5839d0fc0dc51687f0326 100644 (file)
@@ -58,7 +58,7 @@ STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
 STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
 STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *);
 STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *,
-               xfs_bmbt_key_t *, xfs_btree_cur_t **, int *);
+               __uint64_t *, xfs_btree_cur_t **, int *);
 STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int);
 
 
@@ -192,16 +192,11 @@ xfs_bmbt_trace_argifk(
        xfs_btree_cur_t         *cur,
        int                     i,
        xfs_fsblock_t           f,
-       xfs_bmbt_key_t          *k,
+       xfs_dfiloff_t           o,
        int                     line)
 {
-       xfs_dfsbno_t            d;
-       xfs_dfiloff_t           o;
-
-       d = (xfs_dfsbno_t)f;
-       o = INT_GET(k->br_startoff, ARCH_CONVERT);
        xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
-               i, d >> 32, (int)d, o >> 32,
+               i, (xfs_dfsbno_t)f >> 32, (int)f, o >> 32,
                (int)o, 0, 0, 0,
                0, 0, 0);
 }
@@ -248,7 +243,7 @@ xfs_bmbt_trace_argik(
 {
        xfs_dfiloff_t           o;
 
-       o = INT_GET(k->br_startoff, ARCH_CONVERT);
+       o = be64_to_cpu(k->br_startoff);
        xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
                i, o >> 32, (int)o, 0,
                0, 0, 0, 0,
@@ -286,8 +281,8 @@ xfs_bmbt_trace_cursor(
        xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
 #define        XFS_BMBT_TRACE_ARGI(c,i)        \
        xfs_bmbt_trace_argi(fname, c, i, __LINE__)
-#define        XFS_BMBT_TRACE_ARGIFK(c,i,f,k)  \
-       xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__)
+#define        XFS_BMBT_TRACE_ARGIFK(c,i,f,s)  \
+       xfs_bmbt_trace_argifk(fname, c, i, f, s, __LINE__)
 #define        XFS_BMBT_TRACE_ARGIFR(c,i,f,r)  \
        xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
 #define        XFS_BMBT_TRACE_ARGIK(c,i,k)     \
@@ -299,7 +294,7 @@ xfs_bmbt_trace_cursor(
 #define        XFS_BMBT_TRACE_ARGBII(c,b,i,j)
 #define        XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
 #define        XFS_BMBT_TRACE_ARGI(c,i)
-#define        XFS_BMBT_TRACE_ARGIFK(c,i,f,k)
+#define        XFS_BMBT_TRACE_ARGIFK(c,i,f,s)
 #define        XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
 #define        XFS_BMBT_TRACE_ARGIK(c,i,k)
 #define        XFS_BMBT_TRACE_CURSOR(c,s)
@@ -357,7 +352,7 @@ xfs_bmbt_delrec(
        XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
        XFS_BMBT_TRACE_ARGI(cur, level);
        ptr = cur->bc_ptrs[level];
-       tcur = (xfs_btree_cur_t *)0;
+       tcur = NULL;
        if (ptr == 0) {
                XFS_BMBT_TRACE_CURSOR(cur, EXIT);
                *stat = 0;
@@ -382,7 +377,7 @@ xfs_bmbt_delrec(
                pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
 #ifdef DEBUG
                for (i = ptr; i < numrecs; i++) {
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
+                       if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                goto error0;
                        }
@@ -404,7 +399,8 @@ xfs_bmbt_delrec(
                        xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
                }
                if (ptr == 1) {
-                       INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp));
+                       key.br_startoff =
+                               cpu_to_be64(xfs_bmbt_disk_get_startoff(rp));
                        kp = &key;
                }
        }
@@ -621,7 +617,7 @@ xfs_bmbt_delrec(
                rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
                for (i = 0; i < numrrecs; i++) {
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
+                       if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                goto error0;
                        }
@@ -748,7 +744,7 @@ xfs_bmbt_insrec(
        int                     logflags;       /* inode logging flags */
        xfs_fsblock_t           nbno;           /* new block number */
        struct xfs_btree_cur    *ncur;          /* new btree cursor */
-       xfs_bmbt_key_t          nkey;           /* new btree key value */
+       __uint64_t              startoff;       /* new btree key value */
        xfs_bmbt_rec_t          nrec;           /* new record count */
        int                     optr;           /* old key/record index */
        xfs_bmbt_ptr_t          *pp;            /* pointer to bmap block addr */
@@ -759,9 +755,8 @@ xfs_bmbt_insrec(
        ASSERT(level < cur->bc_nlevels);
        XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
        XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
-       ncur = (xfs_btree_cur_t *)0;
-       INT_SET(key.br_startoff, ARCH_CONVERT,
-               xfs_bmbt_disk_get_startoff(recp));
+       ncur = NULL;
+       key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp));
        optr = ptr = cur->bc_ptrs[level];
        if (ptr == 0) {
                XFS_BMBT_TRACE_CURSOR(cur, EXIT);
@@ -820,7 +815,7 @@ xfs_bmbt_insrec(
                                        optr = ptr = cur->bc_ptrs[level];
                                } else {
                                        if ((error = xfs_bmbt_split(cur, level,
-                                                       &nbno, &nkey, &ncur,
+                                                       &nbno, &startoff, &ncur,
                                                        &i))) {
                                                XFS_BMBT_TRACE_CURSOR(cur,
                                                        ERROR);
@@ -840,7 +835,7 @@ xfs_bmbt_insrec(
 #endif
                                                ptr = cur->bc_ptrs[level];
                                                xfs_bmbt_disk_set_allf(&nrec,
-                                                       nkey.br_startoff, 0, 0,
+                                                       startoff, 0, 0,
                                                        XFS_EXT_NORM);
                                        } else {
                                                XFS_BMBT_TRACE_CURSOR(cur,
@@ -858,7 +853,7 @@ xfs_bmbt_insrec(
                pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
 #ifdef DEBUG
                for (i = numrecs; i >= ptr; i--) {
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),
+                       if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1],
                                        level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                return error;
@@ -870,14 +865,13 @@ xfs_bmbt_insrec(
                memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
                        (numrecs - ptr + 1) * sizeof(*pp));
 #ifdef DEBUG
-               if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,
-                               level))) {
+               if ((error = xfs_btree_check_lptr(cur, *bnop, level))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                        return error;
                }
 #endif
                kp[ptr - 1] = key;
-               INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
+               pp[ptr - 1] = cpu_to_be64(*bnop);
                numrecs++;
                block->bb_numrecs = cpu_to_be16(numrecs);
                xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
@@ -988,7 +982,7 @@ xfs_bmbt_killroot(
        cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
 #ifdef DEBUG
        for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
-               if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) {
+               if ((error = xfs_btree_check_lptr_disk(cur, cpp[i], level - 1))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                        return error;
                }
@@ -1132,7 +1126,7 @@ xfs_bmbt_lookup(
                        d = XFS_FSB_TO_DADDR(mp, fsbno);
                        bp = cur->bc_bufs[level];
                        if (bp && XFS_BUF_ADDR(bp) != d)
-                               bp = (xfs_buf_t *)0;
+                               bp = NULL;
                        if (!bp) {
                                if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
                                                0, &bp, XFS_BMAP_BTREE_REF))) {
@@ -1170,7 +1164,7 @@ xfs_bmbt_lookup(
                                keyno = (low + high) >> 1;
                                if (level > 0) {
                                        kkp = kkbase + keyno - 1;
-                                       startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT);
+                                       startoff = be64_to_cpu(kkp->br_startoff);
                                } else {
                                        krp = krbase + keyno - 1;
                                        startoff = xfs_bmbt_disk_get_startoff(krp);
@@ -1189,13 +1183,13 @@ xfs_bmbt_lookup(
                        if (diff > 0 && --keyno < 1)
                                keyno = 1;
                        pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
+                       fsbno = be64_to_cpu(*pp);
 #ifdef DEBUG
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
+                       if ((error = xfs_btree_check_lptr(cur, fsbno, level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                return error;
                        }
 #endif
-                       fsbno = INT_GET(*pp, ARCH_CONVERT);
                        cur->bc_ptrs[level] = keyno;
                }
        }
@@ -1313,7 +1307,7 @@ xfs_bmbt_lshift(
                lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
                rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
-               if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) {
+               if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                        return error;
                }
@@ -1340,7 +1334,7 @@ xfs_bmbt_lshift(
        if (level > 0) {
 #ifdef DEBUG
                for (i = 0; i < rrecs; i++) {
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
+                       if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1],
                                        level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                return error;
@@ -1354,8 +1348,7 @@ xfs_bmbt_lshift(
        } else {
                memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
                xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
-               INT_SET(key.br_startoff, ARCH_CONVERT,
-                       xfs_bmbt_disk_get_startoff(rrp));
+               key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
                rkp = &key;
        }
        if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
@@ -1445,7 +1438,7 @@ xfs_bmbt_rshift(
                rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
                for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
+                       if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                return error;
                        }
@@ -1454,7 +1447,7 @@ xfs_bmbt_rshift(
                memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
                memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
 #ifdef DEBUG
-               if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) {
+               if ((error = xfs_btree_check_lptr_disk(cur, *lpp, level))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                        return error;
                }
@@ -1469,8 +1462,7 @@ xfs_bmbt_rshift(
                memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
                *rrp = *lrp;
                xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
-               INT_SET(key.br_startoff, ARCH_CONVERT,
-                       xfs_bmbt_disk_get_startoff(rrp));
+               key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
                rkp = &key;
        }
        be16_add(&left->bb_numrecs, -1);
@@ -1535,7 +1527,7 @@ xfs_bmbt_split(
        xfs_btree_cur_t         *cur,
        int                     level,
        xfs_fsblock_t           *bnop,
-       xfs_bmbt_key_t          *keyp,
+       __uint64_t              *startoff,
        xfs_btree_cur_t         **curp,
        int                     *stat)          /* success/failure */
 {
@@ -1560,7 +1552,7 @@ xfs_bmbt_split(
        xfs_bmbt_rec_t          *rrp;           /* right record pointer */
 
        XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
-       XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp);
+       XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff);
        args.tp = cur->bc_tp;
        args.mp = cur->bc_mp;
        lbp = cur->bc_bufs[level];
@@ -1619,7 +1611,7 @@ xfs_bmbt_split(
                rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
 #ifdef DEBUG
                for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
-                       if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) {
+                       if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) {
                                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                                return error;
                        }
@@ -1629,13 +1621,13 @@ xfs_bmbt_split(
                memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
                xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
                xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-               keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT);
+               *startoff = be64_to_cpu(rkp->br_startoff);
        } else {
                lrp = XFS_BMAP_REC_IADDR(left, i, cur);
                rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
                memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
                xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-               keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp);
+               *startoff = xfs_bmbt_disk_get_startoff(rrp);
        }
        be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
        right->bb_rightsib = left->bb_rightsib;
@@ -1728,9 +1720,9 @@ xfs_bmdr_to_bmbt(
 {
        int                     dmxr;
        xfs_bmbt_key_t          *fkp;
-       xfs_bmbt_ptr_t          *fpp;
+       __be64                  *fpp;
        xfs_bmbt_key_t          *tkp;
-       xfs_bmbt_ptr_t          *tpp;
+       __be64                  *tpp;
 
        rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
        rblock->bb_level = dblock->bb_level;
@@ -1745,7 +1737,7 @@ xfs_bmdr_to_bmbt(
        tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
        dmxr = be16_to_cpu(dblock->bb_numrecs);
        memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
-       memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
+       memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
 }
 
 /*
@@ -1805,7 +1797,7 @@ xfs_bmbt_decrement(
        tp = cur->bc_tp;
        mp = cur->bc_mp;
        for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
-               fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
+               fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));
                if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
                                XFS_BMAP_BTREE_REF))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
@@ -2135,7 +2127,7 @@ xfs_bmbt_increment(
        tp = cur->bc_tp;
        mp = cur->bc_mp;
        for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
-               fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
+               fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));
                if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
                                XFS_BMAP_BTREE_REF))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
@@ -2178,7 +2170,7 @@ xfs_bmbt_insert(
        level = 0;
        nbno = NULLFSBLOCK;
        xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
-       ncur = (xfs_btree_cur_t *)0;
+       ncur = NULL;
        pcur = cur;
        do {
                if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
@@ -2205,7 +2197,7 @@ xfs_bmbt_insert(
                }
                if (ncur) {
                        pcur = ncur;
-                       ncur = (xfs_btree_cur_t *)0;
+                       ncur = NULL;
                }
        } while (nbno != NULLFSBLOCK);
        XFS_BMBT_TRACE_CURSOR(cur, EXIT);
@@ -2356,12 +2348,12 @@ xfs_bmbt_newroot(
        args.firstblock = args.fsbno;
        if (args.fsbno == NULLFSBLOCK) {
 #ifdef DEBUG
-               if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
+               if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                        return error;
                }
 #endif
-               args.fsbno = INT_GET(*pp, ARCH_CONVERT);
+               args.fsbno = be64_to_cpu(*pp);
                args.type = XFS_ALLOCTYPE_START_BNO;
        } else
                args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -2393,7 +2385,7 @@ xfs_bmbt_newroot(
        cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
 #ifdef DEBUG
        for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
-               if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
+               if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
                        XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                        return error;
                }
@@ -2401,13 +2393,12 @@ xfs_bmbt_newroot(
 #endif
        memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
 #ifdef DEBUG
-       if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno,
-                       level))) {
+       if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) {
                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                return error;
        }
 #endif
-       INT_SET(*pp, ARCH_CONVERT, args.fsbno);
+       *pp = cpu_to_be64(args.fsbno);
        xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
                cur->bc_private.b.whichfork);
        xfs_btree_setbuf(cur, level, bp);
@@ -2681,9 +2672,9 @@ xfs_bmbt_to_bmdr(
 {
        int                     dmxr;
        xfs_bmbt_key_t          *fkp;
-       xfs_bmbt_ptr_t          *fpp;
+       __be64                  *fpp;
        xfs_bmbt_key_t          *tkp;
-       xfs_bmbt_ptr_t          *tpp;
+       __be64                  *tpp;
 
        ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
        ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
@@ -2698,7 +2689,7 @@ xfs_bmbt_to_bmdr(
        tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
        dmxr = be16_to_cpu(dblock->bb_numrecs);
        memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
-       memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
+       memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
 }
 
 /*
@@ -2740,7 +2731,7 @@ xfs_bmbt_update(
                XFS_BMBT_TRACE_CURSOR(cur, EXIT);
                return 0;
        }
-       INT_SET(key.br_startoff, ARCH_CONVERT, off);
+       key.br_startoff = cpu_to_be64(off);
        if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
                XFS_BMBT_TRACE_CURSOR(cur, ERROR);
                return error;
index 6478cfa0e5395054e35b6c9f75c686f7d6010ad2..49539de9525bc7aa71f93b553b734497c22748fb 100644 (file)
@@ -163,13 +163,14 @@ typedef struct xfs_bmbt_irec
 /*
  * Key structure for non-leaf levels of the tree.
  */
-typedef struct xfs_bmbt_key
-{
-       xfs_dfiloff_t   br_startoff;    /* starting file offset */
+typedef struct xfs_bmbt_key {
+       __be64          br_startoff;    /* starting file offset */
 } xfs_bmbt_key_t, xfs_bmdr_key_t;
 
-typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;   /* btree pointer type */
-                                       /* btree block header type */
+/* btree pointer type */
+typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
+
+/* btree block header type */
 typedef struct xfs_btree_lblock xfs_bmbt_block_t;
 
 #define XFS_BUF_TO_BMBT_BLOCK(bp)      ((xfs_bmbt_block_t *)XFS_BUF_PTR(bp))
index ee2255bd65624051d63729ceddf4670b4ed9002f..aeb87ca69fcc2e12e3042d21994b3ddbdd41fe75 100644 (file)
@@ -161,7 +161,7 @@ xfs_btree_check_key(
 
                k1 = ak1;
                k2 = ak2;
-               ASSERT(INT_GET(k1->br_startoff, ARCH_CONVERT) < INT_GET(k2->br_startoff, ARCH_CONVERT));
+               ASSERT(be64_to_cpu(k1->br_startoff) < be64_to_cpu(k2->br_startoff));
                break;
            }
        case XFS_BTNUM_INO: {
@@ -170,7 +170,7 @@ xfs_btree_check_key(
 
                k1 = ak1;
                k2 = ak2;
-               ASSERT(INT_GET(k1->ir_startino, ARCH_CONVERT) < INT_GET(k2->ir_startino, ARCH_CONVERT));
+               ASSERT(be32_to_cpu(k1->ir_startino) < be32_to_cpu(k2->ir_startino));
                break;
            }
        default:
@@ -285,8 +285,8 @@ xfs_btree_check_rec(
 
                r1 = ar1;
                r2 = ar2;
-               ASSERT(INT_GET(r1->ir_startino, ARCH_CONVERT) + XFS_INODES_PER_CHUNK <=
-                      INT_GET(r2->ir_startino, ARCH_CONVERT));
+               ASSERT(be32_to_cpu(r1->ir_startino) + XFS_INODES_PER_CHUNK <=
+                      be32_to_cpu(r2->ir_startino));
                break;
            }
        default:
index 44f1bd98064a49d04916366c921db35dbf508493..892b06c542637219d46be0f67798fa0e545fd43d 100644 (file)
@@ -145,7 +145,7 @@ typedef struct xfs_btree_cur
        union {
                xfs_alloc_rec_incore_t  a;
                xfs_bmbt_irec_t         b;
-               xfs_inobt_rec_t         i;
+               xfs_inobt_rec_incore_t  i;
        }               bc_rec;         /* current insert/search record value */
        struct xfs_buf  *bc_bufs[XFS_BTREE_MAXLEVELS];  /* buf ptr per level */
        int             bc_ptrs[XFS_BTREE_MAXLEVELS];   /* key/record # */
@@ -243,6 +243,9 @@ xfs_btree_check_lptr(
        xfs_dfsbno_t            ptr,    /* btree block disk address */
        int                     level); /* btree block level */
 
+#define xfs_btree_check_lptr_disk(cur, ptr, level) \
+       xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level)
+
 /*
  * Checking routine: check that short form block header is ok.
  */
index a4aa53974f7650668204ea2ce22f93de28adfa9c..7a55c248ea706a405fa4eddd1fb8d80a5f0c4d0b 100644 (file)
@@ -234,7 +234,6 @@ xfs_buf_item_format(
        ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
               (bip->bli_flags & XFS_BLI_STALE));
        bp = bip->bli_buf;
-       ASSERT(XFS_BUF_BP_ISMAPPED(bp));
        vecp = log_vector;
 
        /*
@@ -627,25 +626,6 @@ xfs_buf_item_committed(
        return (lsn);
 }
 
-/*
- * This is called when the transaction holding the buffer is aborted.
- * Just behave as if the transaction had been cancelled. If we're shutting down
- * and have aborted this transaction, we'll trap this buffer when it tries to
- * get written out.
- */
-STATIC void
-xfs_buf_item_abort(
-       xfs_buf_log_item_t      *bip)
-{
-       xfs_buf_t       *bp;
-
-       bp = bip->bli_buf;
-       xfs_buftrace("XFS_ABORT", bp);
-       XFS_BUF_SUPER_STALE(bp);
-       xfs_buf_item_unlock(bip);
-       return;
-}
-
 /*
  * This is called to asynchronously write the buffer associated with this
  * buf log item out to disk. The buffer will already have been locked by
@@ -693,7 +673,6 @@ STATIC struct xfs_item_ops xfs_buf_item_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_buf_item_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_buf_item_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_buf_item_abort,
        .iop_pushbuf    = NULL,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_buf_item_committing
@@ -901,7 +880,6 @@ xfs_buf_item_relse(
        XFS_BUF_SET_FSPRIVATE(bp, bip->bli_item.li_bio_list);
        if ((XFS_BUF_FSPRIVATE(bp, void *) == NULL) &&
            (XFS_BUF_IODONE_FUNC(bp) != NULL)) {
-               ASSERT((XFS_BUF_ISUNINITIAL(bp)) == 0);
                XFS_BUF_CLR_IODONE_FUNC(bp);
        }
 
index 32ab61d17acefdeab2683925b65b806e556f7d5d..a68bc1f1a313c8862106adedf30ef84d65b92cd8 100644 (file)
@@ -1054,7 +1054,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
        xfs_da_node_entry_t *btree;
        xfs_dablk_t blkno;
        int probe, span, max, error, retval;
-       xfs_dahash_t hashval;
+       xfs_dahash_t hashval, btreehashval;
        xfs_da_args_t *args;
 
        args = state->args;
@@ -1079,30 +1079,32 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                        return(error);
                }
                curr = blk->bp->data;
-               ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC ||
-                      be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC ||
-                      be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC);
+               blk->magic = be16_to_cpu(curr->magic);
+               ASSERT(blk->magic == XFS_DA_NODE_MAGIC ||
+                      blk->magic == XFS_DIR2_LEAFN_MAGIC ||
+                      blk->magic == XFS_ATTR_LEAF_MAGIC);
 
                /*
                 * Search an intermediate node for a match.
                 */
-               blk->magic = be16_to_cpu(curr->magic);
                if (blk->magic == XFS_DA_NODE_MAGIC) {
                        node = blk->bp->data;
-                       blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval);
+                       max = be16_to_cpu(node->hdr.count);
+                       btreehashval = node->btree[max-1].hashval;
+                       blk->hashval = be32_to_cpu(btreehashval);
 
                        /*
                         * Binary search.  (note: small blocks will skip loop)
                         */
-                       max = be16_to_cpu(node->hdr.count);
                        probe = span = max / 2;
                        hashval = args->hashval;
                        for (btree = &node->btree[probe]; span > 4;
                                   btree = &node->btree[probe]) {
                                span /= 2;
-                               if (be32_to_cpu(btree->hashval) < hashval)
+                               btreehashval = be32_to_cpu(btree->hashval);
+                               if (btreehashval < hashval)
                                        probe += span;
-                               else if (be32_to_cpu(btree->hashval) > hashval)
+                               else if (btreehashval > hashval)
                                        probe -= span;
                                else
                                        break;
@@ -1133,10 +1135,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                                blk->index = probe;
                                blkno = be32_to_cpu(btree->before);
                        }
-               } else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
+               } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
                        blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
                        break;
-               } else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
+               } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
                        blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
                        break;
                }
@@ -1152,11 +1154,13 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
                        retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
                                                        &blk->index, state);
-               }
-               else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
+               } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
                        retval = xfs_attr_leaf_lookup_int(blk->bp, args);
                        blk->index = args->index;
                        args->blkno = blk->blkno;
+               } else {
+                       ASSERT(0);
+                       return XFS_ERROR(EFSCORRUPTED);
                }
                if (((retval == ENOENT) || (retval == ENOATTR)) &&
                    (blk->hashval == args->hashval)) {
@@ -1166,8 +1170,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                                return(error);
                        if (retval == 0) {
                                continue;
-                       }
-                       else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
+                       } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
                                /* path_shift() gives ENOENT */
                                retval = XFS_ERROR(ENOATTR);
                        }
index bc43163456ef854ae2820a25af87e3a146d73cc9..0893e16b7d834a20a7cf9ef96189336fabcbaa90 100644 (file)
 #ifndef        __XFS_ERROR_H__
 #define        __XFS_ERROR_H__
 
-#define XFS_ERECOVER   1       /* Failure to recover log */
-#define XFS_ELOGSTAT   2       /* Failure to stat log in user space */
-#define XFS_ENOLOGSPACE        3       /* Reservation too large */
-#define XFS_ENOTSUP    4       /* Operation not supported */
-#define        XFS_ENOLSN      5       /* Can't find the lsn you asked for */
-#define XFS_ENOTFOUND  6
-#define XFS_ENOTXFS    7       /* Not XFS filesystem */
-
 #ifdef DEBUG
 #define        XFS_ERROR_NTRAP 10
 extern int     xfs_etrap[XFS_ERROR_NTRAP];
@@ -175,6 +167,7 @@ extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
 #define                XFS_PTAG_SHUTDOWN_CORRUPT       0x00000010
 #define                XFS_PTAG_SHUTDOWN_IOERROR       0x00000020
 #define                XFS_PTAG_SHUTDOWN_LOGERROR      0x00000040
+#define                XFS_PTAG_FSBLOCK_ZERO           0x00000080
 
 struct xfs_mount;
 /* PRINTFLIKE4 */
index 6cf6d8769b975902c290a4485372b9b507793aa1..6dba78199faf54e40fcc36fcdf9a61cbe865b436 100644 (file)
@@ -33,9 +33,6 @@ kmem_zone_t   *xfs_efi_zone;
 kmem_zone_t    *xfs_efd_zone;
 
 STATIC void    xfs_efi_item_unlock(xfs_efi_log_item_t *);
-STATIC void    xfs_efi_item_abort(xfs_efi_log_item_t *);
-STATIC void    xfs_efd_item_abort(xfs_efd_log_item_t *);
-
 
 void
 xfs_efi_item_free(xfs_efi_log_item_t *efip)
@@ -184,7 +181,7 @@ STATIC void
 xfs_efi_item_unlock(xfs_efi_log_item_t *efip)
 {
        if (efip->efi_item.li_flags & XFS_LI_ABORTED)
-               xfs_efi_item_abort(efip);
+               xfs_efi_item_free(efip);
        return;
 }
 
@@ -201,18 +198,6 @@ xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
        return lsn;
 }
 
-/*
- * This is called when the transaction logging the EFI is aborted.
- * Free up the EFI and return.  No need to clean up the slot for
- * the item in the transaction.  That was done by the unpin code
- * which is called prior to this routine in the abort/fs-shutdown path.
- */
-STATIC void
-xfs_efi_item_abort(xfs_efi_log_item_t *efip)
-{
-       xfs_efi_item_free(efip);
-}
-
 /*
  * There isn't much you can do to push on an efi item.  It is simply
  * stuck waiting for all of its corresponding efd items to be
@@ -255,7 +240,6 @@ STATIC struct xfs_item_ops xfs_efi_item_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_efi_item_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_efi_item_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_efi_item_abort,
        .iop_pushbuf    = NULL,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_efi_item_committing
@@ -386,33 +370,6 @@ xfs_efi_release(xfs_efi_log_item_t *efip,
        }
 }
 
-/*
- * This is called when the transaction that should be committing the
- * EFD corresponding to the given EFI is aborted.  The committed and
- * canceled flags are used to coordinate the freeing of the EFI and
- * the references by the transaction that committed it.
- */
-STATIC void
-xfs_efi_cancel(
-       xfs_efi_log_item_t      *efip)
-{
-       xfs_mount_t     *mp;
-       SPLDECL(s);
-
-       mp = efip->efi_item.li_mountp;
-       AIL_LOCK(mp, s);
-       if (efip->efi_flags & XFS_EFI_COMMITTED) {
-               /*
-                * xfs_trans_delete_ail() drops the AIL lock.
-                */
-               xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-               xfs_efi_item_free(efip);
-       } else {
-               efip->efi_flags |= XFS_EFI_CANCELED;
-               AIL_UNLOCK(mp, s);
-       }
-}
-
 STATIC void
 xfs_efd_item_free(xfs_efd_log_item_t *efdp)
 {
@@ -514,7 +471,7 @@ STATIC void
 xfs_efd_item_unlock(xfs_efd_log_item_t *efdp)
 {
        if (efdp->efd_item.li_flags & XFS_LI_ABORTED)
-               xfs_efd_item_abort(efdp);
+               xfs_efd_item_free(efdp);
        return;
 }
 
@@ -540,27 +497,6 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
        return (xfs_lsn_t)-1;
 }
 
-/*
- * The transaction of which this EFD is a part has been aborted.
- * Inform its companion EFI of this fact and then clean up after
- * ourselves.  No need to clean up the slot for the item in the
- * transaction.  That was done by the unpin code which is called
- * prior to this routine in the abort/fs-shutdown path.
- */
-STATIC void
-xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
-{
-       /*
-        * If we got a log I/O error, it's always the case that the LR with the
-        * EFI got unpinned and freed before the EFD got aborted. So don't
-        * reference the EFI at all in that case.
-        */
-       if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
-               xfs_efi_cancel(efdp->efd_efip);
-
-       xfs_efd_item_free(efdp);
-}
-
 /*
  * There isn't much you can do to push on an efd item.  It is simply
  * stuck waiting for the log to be flushed to disk.
@@ -602,7 +538,6 @@ STATIC struct xfs_item_ops xfs_efd_item_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_efd_item_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_efd_item_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_efd_item_abort,
        .iop_pushbuf    = NULL,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_efd_item_committing
index 0ea45edaab033b31ba258b2cc39c3f48634f0d70..2f049f63e85f73ea3ae1763c5eb66e6798368635 100644 (file)
@@ -33,14 +33,16 @@ typedef struct xfs_extent {
  * conversion routine.
  */
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_extent_32 {
-       xfs_dfsbno_t    ext_start;
-       xfs_extlen_t    ext_len;
+       __uint64_t      ext_start;
+       __uint32_t      ext_len;
 } __attribute__((packed)) xfs_extent_32_t;
+#endif
 
 typedef struct xfs_extent_64 {
-       xfs_dfsbno_t    ext_start;
-       xfs_extlen_t    ext_len;
+       __uint64_t      ext_start;
+       __uint32_t      ext_len;
        __uint32_t      ext_pad;
 } xfs_extent_64_t;
 
@@ -50,25 +52,27 @@ typedef struct xfs_extent_64 {
  * size is given by efi_nextents.
  */
 typedef struct xfs_efi_log_format {
-       unsigned short          efi_type;       /* efi log item type */
-       unsigned short          efi_size;       /* size of this item */
-       uint                    efi_nextents;   /* # extents to free */
+       __uint16_t              efi_type;       /* efi log item type */
+       __uint16_t              efi_size;       /* size of this item */
+       __uint32_t              efi_nextents;   /* # extents to free */
        __uint64_t              efi_id;         /* efi identifier */
        xfs_extent_t            efi_extents[1]; /* array of extents to free */
 } xfs_efi_log_format_t;
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_efi_log_format_32 {
-       unsigned short          efi_type;       /* efi log item type */
-       unsigned short          efi_size;       /* size of this item */
-       uint                    efi_nextents;   /* # extents to free */
+       __uint16_t              efi_type;       /* efi log item type */
+       __uint16_t              efi_size;       /* size of this item */
+       __uint32_t              efi_nextents;   /* # extents to free */
        __uint64_t              efi_id;         /* efi identifier */
        xfs_extent_32_t         efi_extents[1]; /* array of extents to free */
 } __attribute__((packed)) xfs_efi_log_format_32_t;
+#endif
 
 typedef struct xfs_efi_log_format_64 {
-       unsigned short          efi_type;       /* efi log item type */
-       unsigned short          efi_size;       /* size of this item */
-       uint                    efi_nextents;   /* # extents to free */
+       __uint16_t              efi_type;       /* efi log item type */
+       __uint16_t              efi_size;       /* size of this item */
+       __uint32_t              efi_nextents;   /* # extents to free */
        __uint64_t              efi_id;         /* efi identifier */
        xfs_extent_64_t         efi_extents[1]; /* array of extents to free */
 } xfs_efi_log_format_64_t;
@@ -79,25 +83,27 @@ typedef struct xfs_efi_log_format_64 {
  * size is given by efd_nextents;
  */
 typedef struct xfs_efd_log_format {
-       unsigned short          efd_type;       /* efd log item type */
-       unsigned short          efd_size;       /* size of this item */
-       uint                    efd_nextents;   /* # of extents freed */
+       __uint16_t              efd_type;       /* efd log item type */
+       __uint16_t              efd_size;       /* size of this item */
+       __uint32_t              efd_nextents;   /* # of extents freed */
        __uint64_t              efd_efi_id;     /* id of corresponding efi */
        xfs_extent_t            efd_extents[1]; /* array of extents freed */
 } xfs_efd_log_format_t;
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_efd_log_format_32 {
-       unsigned short          efd_type;       /* efd log item type */
-       unsigned short          efd_size;       /* size of this item */
-       uint                    efd_nextents;   /* # of extents freed */
+       __uint16_t              efd_type;       /* efd log item type */
+       __uint16_t              efd_size;       /* size of this item */
+       __uint32_t              efd_nextents;   /* # of extents freed */
        __uint64_t              efd_efi_id;     /* id of corresponding efi */
        xfs_extent_32_t         efd_extents[1]; /* array of extents freed */
 } __attribute__((packed)) xfs_efd_log_format_32_t;
+#endif
 
 typedef struct xfs_efd_log_format_64 {
-       unsigned short          efd_type;       /* efd log item type */
-       unsigned short          efd_size;       /* size of this item */
-       uint                    efd_nextents;   /* # of extents freed */
+       __uint16_t              efd_type;       /* efd log item type */
+       __uint16_t              efd_size;       /* size of this item */
+       __uint32_t              efd_nextents;   /* # of extents freed */
        __uint64_t              efd_efi_id;     /* id of corresponding efi */
        xfs_extent_64_t         efd_extents[1]; /* array of extents freed */
 } xfs_efd_log_format_64_t;
index 0f0ad1535951c8b137278d5bf4c994910adfa8bf..1335449841cdc1ecc77d2bc8c47ba32c91148993 100644 (file)
@@ -22,8 +22,6 @@
  * SGI's XFS filesystem's major stuff (constants, structures)
  */
 
-#define XFS_NAME       "xfs"
-
 /*
  * Direct I/O attribute record used with XFS_IOC_DIOINFO
  * d_miniosz is the min xfer size, xfer size multiple and file seek offset
@@ -426,11 +424,7 @@ typedef struct xfs_handle {
                                 - (char *) &(handle))                    \
                                 + (handle).ha_fid.xfs_fid_len)
 
-#define XFS_HANDLE_CMP(h1, h2) memcmp(h1, h2, sizeof(xfs_handle_t))
-
-#define FSHSIZE                sizeof(fsid_t)
-
-/* 
+/*
  * Flags for going down operation
  */
 #define XFS_FSOP_GOING_FLAGS_DEFAULT           0x0     /* going down */
index 33164a85aa9df4c3912a31157c9b8eddc5991f0c..a446e5a115c6bad4f60ece30a66d325f7da6a41f 100644 (file)
@@ -458,7 +458,7 @@ nextag:
                 */
                if (XFS_FORCED_SHUTDOWN(mp)) {
                        up_read(&mp->m_peraglock);
-                       return (xfs_buf_t *)0;
+                       return NULL;
                }
                agno++;
                if (agno >= agcount)
@@ -466,7 +466,7 @@ nextag:
                if (agno == pagno) {
                        if (flags == 0) {
                                up_read(&mp->m_peraglock);
-                               return (xfs_buf_t *)0;
+                               return NULL;
                        }
                        flags = 0;
                }
@@ -529,10 +529,10 @@ xfs_dialloc(
        int             offset;         /* index of inode in chunk */
        xfs_agino_t     pagino;         /* parent's a.g. relative inode # */
        xfs_agnumber_t  pagno;          /* parent's allocation group number */
-       xfs_inobt_rec_t rec;            /* inode allocation record */
+       xfs_inobt_rec_incore_t rec;     /* inode allocation record */
        xfs_agnumber_t  tagno;          /* testing allocation group number */
        xfs_btree_cur_t *tcur;          /* temp cursor */
-       xfs_inobt_rec_t trec;           /* temp inode allocation record */
+       xfs_inobt_rec_incore_t trec;    /* temp inode allocation record */
 
 
        if (*IO_agbp == NULL) {
@@ -945,7 +945,7 @@ xfs_difree(
        int             ilen;   /* inodes in an inode cluster */
        xfs_mount_t     *mp;    /* mount structure for filesystem */
        int             off;    /* offset of inode in inode chunk */
-       xfs_inobt_rec_t rec;    /* btree record */
+       xfs_inobt_rec_incore_t rec;     /* btree record */
 
        mp = tp->t_mountp;
 
@@ -1195,6 +1195,7 @@ xfs_dilocate(
                                        "(0x%llx)",
                                        ino, XFS_AGINO_TO_INO(mp, agno, agino));
                }
+               xfs_stack_trace();
 #endif /* DEBUG */
                return XFS_ERROR(EINVAL);
        }
index 616eeeb6953eb27e796102c7c0aa9b23092268a1..8cdeeaf8632b9bc7b1c5e5e19cf128908a91c2e3 100644 (file)
@@ -568,7 +568,7 @@ xfs_inobt_insrec(
        /*
         * Make a key out of the record data to be inserted, and save it.
         */
-       key.ir_startino = recp->ir_startino; /* INT_: direct copy */
+       key.ir_startino = recp->ir_startino;
        optr = ptr = cur->bc_ptrs[level];
        /*
         * If we're off the left edge, return failure.
@@ -600,7 +600,7 @@ xfs_inobt_insrec(
        }
 #endif
        nbno = NULLAGBLOCK;
-       ncur = (xfs_btree_cur_t *)0;
+       ncur = NULL;
        /*
         * If the block is full, we can't insert the new entry until we
         * make the block un-full.
@@ -641,7 +641,7 @@ xfs_inobt_insrec(
                                                return error;
 #endif
                                        ptr = cur->bc_ptrs[level];
-                                       nrec.ir_startino = nkey.ir_startino; /* INT_: direct copy */
+                                       nrec.ir_startino = nkey.ir_startino;
                                } else {
                                        /*
                                         * Otherwise the insert fails.
@@ -681,7 +681,7 @@ xfs_inobt_insrec(
                if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
                        return error;
 #endif
-               kp[ptr - 1] = key; /* INT_: struct copy */
+               kp[ptr - 1] = key;
                pp[ptr - 1] = cpu_to_be32(*bnop);
                numrecs++;
                block->bb_numrecs = cpu_to_be16(numrecs);
@@ -698,7 +698,7 @@ xfs_inobt_insrec(
                 * Now stuff the new record in, bump numrecs
                 * and log the new data.
                 */
-               rp[ptr - 1] = *recp; /* INT_: struct copy */
+               rp[ptr - 1] = *recp;
                numrecs++;
                block->bb_numrecs = cpu_to_be16(numrecs);
                xfs_inobt_log_recs(cur, bp, ptr, numrecs);
@@ -731,7 +731,7 @@ xfs_inobt_insrec(
         */
        *bnop = nbno;
        if (nbno != NULLAGBLOCK) {
-               *recp = nrec; /* INT_: struct copy */
+               *recp = nrec;
                *curp = ncur;
        }
        *stat = 1;
@@ -878,7 +878,7 @@ xfs_inobt_lookup(
                 */
                bp = cur->bc_bufs[level];
                if (bp && XFS_BUF_ADDR(bp) != d)
-                       bp = (xfs_buf_t *)0;
+                       bp = NULL;
                if (!bp) {
                        /*
                         * Need to get a new buffer.  Read it, then
@@ -950,12 +950,12 @@ xfs_inobt_lookup(
                                        xfs_inobt_key_t *kkp;
 
                                        kkp = kkbase + keyno - 1;
-                                       startino = INT_GET(kkp->ir_startino, ARCH_CONVERT);
+                                       startino = be32_to_cpu(kkp->ir_startino);
                                } else {
                                        xfs_inobt_rec_t *krp;
 
                                        krp = krbase + keyno - 1;
-                                       startino = INT_GET(krp->ir_startino, ARCH_CONVERT);
+                                       startino = be32_to_cpu(krp->ir_startino);
                                }
                                /*
                                 * Compute difference to get next direction.
@@ -1117,7 +1117,7 @@ xfs_inobt_lshift(
                if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level)))
                        return error;
 #endif
-               *lpp = *rpp; /* INT_: no-change copy */
+               *lpp = *rpp;
                xfs_inobt_log_ptrs(cur, lbp, nrec, nrec);
        }
        /*
@@ -1160,7 +1160,7 @@ xfs_inobt_lshift(
        } else {
                memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
                xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-               key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
+               key.ir_startino = rrp->ir_startino;
                rkp = &key;
        }
        /*
@@ -1297,13 +1297,13 @@ xfs_inobt_newroot(
         */
        kp = XFS_INOBT_KEY_ADDR(new, 1, cur);
        if (be16_to_cpu(left->bb_level) > 0) {
-               kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); /* INT_: struct copy */
-               kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); /* INT_: struct copy */
+               kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur);
+               kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur);
        } else {
                rp = XFS_INOBT_REC_ADDR(left, 1, cur);
-               INT_COPY(kp[0].ir_startino, rp->ir_startino, ARCH_CONVERT);
+               kp[0].ir_startino = rp->ir_startino;
                rp = XFS_INOBT_REC_ADDR(right, 1, cur);
-               INT_COPY(kp[1].ir_startino, rp->ir_startino, ARCH_CONVERT);
+               kp[1].ir_startino = rp->ir_startino;
        }
        xfs_inobt_log_keys(cur, nbp, 1, 2);
        /*
@@ -1410,8 +1410,8 @@ xfs_inobt_rshift(
                if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*lpp), level)))
                        return error;
 #endif
-               *rkp = *lkp; /* INT_: no change copy */
-               *rpp = *lpp; /* INT_: no change copy */
+               *rkp = *lkp;
+               *rpp = *lpp;
                xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
                xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
        } else {
@@ -1420,7 +1420,7 @@ xfs_inobt_rshift(
                memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
                *rrp = *lrp;
                xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
-               key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
+               key.ir_startino = rrp->ir_startino;
                rkp = &key;
        }
        /*
@@ -1559,7 +1559,7 @@ xfs_inobt_split(
                rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
                memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
                xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
-               keyp->ir_startino = rrp->ir_startino; /* INT_: direct copy */
+               keyp->ir_startino = rrp->ir_startino;
        }
        /*
         * Find the left block number by looking in the buffer.
@@ -1813,9 +1813,9 @@ xfs_inobt_get_rec(
         * Point to the record and extract its data.
         */
        rec = XFS_INOBT_REC_ADDR(block, ptr, cur);
-       *ino = INT_GET(rec->ir_startino, ARCH_CONVERT);
-       *fcnt = INT_GET(rec->ir_freecount, ARCH_CONVERT);
-       *free = INT_GET(rec->ir_free, ARCH_CONVERT);
+       *ino = be32_to_cpu(rec->ir_startino);
+       *fcnt = be32_to_cpu(rec->ir_freecount);
+       *free = be64_to_cpu(rec->ir_free);
        *stat = 1;
        return 0;
 }
@@ -1930,10 +1930,10 @@ xfs_inobt_insert(
 
        level = 0;
        nbno = NULLAGBLOCK;
-       INT_SET(nrec.ir_startino, ARCH_CONVERT, cur->bc_rec.i.ir_startino);
-       INT_SET(nrec.ir_freecount, ARCH_CONVERT, cur->bc_rec.i.ir_freecount);
-       INT_SET(nrec.ir_free, ARCH_CONVERT, cur->bc_rec.i.ir_free);
-       ncur = (xfs_btree_cur_t *)0;
+       nrec.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);
+       nrec.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount);
+       nrec.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
+       ncur = NULL;
        pcur = cur;
        /*
         * Loop going up the tree, starting at the leaf level.
@@ -1965,7 +1965,7 @@ xfs_inobt_insert(
                 */
                if (ncur) {
                        pcur = ncur;
-                       ncur = (xfs_btree_cur_t *)0;
+                       ncur = NULL;
                }
        } while (nbno != NULLAGBLOCK);
        *stat = i;
@@ -2060,9 +2060,9 @@ xfs_inobt_update(
        /*
         * Fill in the new contents and log them.
         */
-       INT_SET(rp->ir_startino, ARCH_CONVERT, ino);
-       INT_SET(rp->ir_freecount, ARCH_CONVERT, fcnt);
-       INT_SET(rp->ir_free, ARCH_CONVERT, free);
+       rp->ir_startino = cpu_to_be32(ino);
+       rp->ir_freecount = cpu_to_be32(fcnt);
+       rp->ir_free = cpu_to_be64(free);
        xfs_inobt_log_recs(cur, bp, ptr, ptr);
        /*
         * Updating first record in leaf. Pass new key value up to our parent.
@@ -2070,7 +2070,7 @@ xfs_inobt_update(
        if (ptr == 1) {
                xfs_inobt_key_t key;    /* key containing [ino] */
 
-               INT_SET(key.ir_startino, ARCH_CONVERT, ino);
+               key.ir_startino = cpu_to_be32(ino);
                if ((error = xfs_inobt_updkey(cur, &key, 1)))
                        return error;
        }
index ae3904cb1ee814caaf172f2a9efc8273c216b6f6..2c0e49893ff72731a06d51f81ea216b061014fd7 100644 (file)
@@ -47,19 +47,24 @@ static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
 /*
  * Data record structure
  */
-typedef struct xfs_inobt_rec
-{
+typedef struct xfs_inobt_rec {
+       __be32          ir_startino;    /* starting inode number */
+       __be32          ir_freecount;   /* count of free inodes (set bits) */
+       __be64          ir_free;        /* free inode mask */
+} xfs_inobt_rec_t;
+
+typedef struct xfs_inobt_rec_incore {
        xfs_agino_t     ir_startino;    /* starting inode number */
        __int32_t       ir_freecount;   /* count of free inodes (set bits) */
        xfs_inofree_t   ir_free;        /* free inode mask */
-} xfs_inobt_rec_t;
+} xfs_inobt_rec_incore_t;
+
 
 /*
  * Key structure
  */
-typedef struct xfs_inobt_key
-{
-       xfs_agino_t     ir_startino;    /* starting inode number */
+typedef struct xfs_inobt_key {
+       __be32          ir_startino;    /* starting inode number */
 } xfs_inobt_key_t;
 
 /* btree pointer type */
@@ -77,7 +82,7 @@ typedef       struct xfs_btree_sblock xfs_inobt_block_t;
 #define        XFS_INOBT_IS_FREE(rp,i)         \
                (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
 #define        XFS_INOBT_IS_FREE_DISK(rp,i)    \
-               ((INT_GET((rp)->ir_free,ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
+               ((be64_to_cpu((rp)->ir_free) & XFS_INOBT_MASK(i)) != 0)
 #define        XFS_INOBT_SET_FREE(rp,i)        ((rp)->ir_free |= XFS_INOBT_MASK(i))
 #define        XFS_INOBT_CLR_FREE(rp,i)        ((rp)->ir_free &= ~XFS_INOBT_MASK(i))
 
index 0724df7fabb755fea973ca3ac87176b4e4c24e93..b73d216ecaf939aa4df49f8a89a6cff9e2fafd16 100644 (file)
@@ -50,7 +50,7 @@ void
 xfs_ihash_init(xfs_mount_t *mp)
 {
        __uint64_t      icount;
-       uint            i, flags = KM_SLEEP | KM_MAYFAIL;
+       uint            i;
 
        if (!mp->m_ihsize) {
                icount = mp->m_maxicount ? mp->m_maxicount :
@@ -61,14 +61,13 @@ xfs_ihash_init(xfs_mount_t *mp)
                                        (64 * NBPP) / sizeof(xfs_ihash_t));
        }
 
-       while (!(mp->m_ihash = (xfs_ihash_t *)kmem_zalloc(mp->m_ihsize *
-                                               sizeof(xfs_ihash_t), flags))) {
-               if ((mp->m_ihsize >>= 1) <= NBPP)
-                       flags = KM_SLEEP;
-       }
-       for (i = 0; i < mp->m_ihsize; i++) {
+       mp->m_ihash = kmem_zalloc_greedy(&mp->m_ihsize,
+                                        NBPC * sizeof(xfs_ihash_t),
+                                        mp->m_ihsize * sizeof(xfs_ihash_t),
+                                        KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+       mp->m_ihsize /= sizeof(xfs_ihash_t);
+       for (i = 0; i < mp->m_ihsize; i++)
                rwlock_init(&(mp->m_ihash[i].ih_lock));
-       }
 }
 
 /*
@@ -77,7 +76,7 @@ xfs_ihash_init(xfs_mount_t *mp)
 void
 xfs_ihash_free(xfs_mount_t *mp)
 {
-       kmem_free(mp->m_ihash, mp->m_ihsize*sizeof(xfs_ihash_t));
+       kmem_free(mp->m_ihash, mp->m_ihsize * sizeof(xfs_ihash_t));
        mp->m_ihash = NULL;
 }
 
@@ -95,7 +94,7 @@ xfs_chash_init(xfs_mount_t *mp)
        mp->m_chsize = min_t(uint, mp->m_chsize, mp->m_ihsize);
        mp->m_chash = (xfs_chash_t *)kmem_zalloc(mp->m_chsize
                                                 * sizeof(xfs_chash_t),
-                                                KM_SLEEP);
+                                                KM_SLEEP | KM_LARGE);
        for (i = 0; i < mp->m_chsize; i++) {
                spinlock_init(&mp->m_chash[i].ch_lock,"xfshash");
        }
@@ -244,7 +243,9 @@ again:
 
                                XFS_STATS_INC(xs_ig_found);
 
+                               spin_lock(&ip->i_flags_lock);
                                ip->i_flags &= ~XFS_IRECLAIMABLE;
+                               spin_unlock(&ip->i_flags_lock);
                                version = ih->ih_version;
                                read_unlock(&ih->ih_lock);
                                xfs_ihash_promote(ih, ip, version);
@@ -290,15 +291,17 @@ again:
 
 finish_inode:
                        if (ip->i_d.di_mode == 0) {
-                               if (!(flags & IGET_CREATE))
+                               if (!(flags & XFS_IGET_CREATE))
                                        return ENOENT;
                                xfs_iocore_inode_reinit(ip);
                        }
-       
+
                        if (lock_flags != 0)
                                xfs_ilock(ip, lock_flags);
 
+                       spin_lock(&ip->i_flags_lock);
                        ip->i_flags &= ~XFS_ISTALE;
+                       spin_unlock(&ip->i_flags_lock);
 
                        vn_trace_exit(vp, "xfs_iget.found",
                                                (inst_t *)__return_address);
@@ -320,21 +323,20 @@ finish_inode:
         * Read the disk inode attributes into a new inode structure and get
         * a new vnode for it. This should also initialize i_ino and i_mount.
         */
-       error = xfs_iread(mp, tp, ino, &ip, bno);
-       if (error) {
+       error = xfs_iread(mp, tp, ino, &ip, bno,
+                         (flags & XFS_IGET_BULKSTAT) ? XFS_IMAP_BULKSTAT : 0);
+       if (error)
                return error;
-       }
 
        vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
 
        xfs_inode_lock_init(ip, vp);
        xfs_iocore_inode_init(ip);
 
-       if (lock_flags != 0) {
+       if (lock_flags)
                xfs_ilock(ip, lock_flags);
-       }
-               
-       if ((ip->i_d.di_mode == 0) && !(flags & IGET_CREATE)) {
+
+       if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
                xfs_idestroy(ip);
                return ENOENT;
        }
@@ -369,7 +371,9 @@ finish_inode:
        ih->ih_next = ip;
        ip->i_udquot = ip->i_gdquot = NULL;
        ih->ih_version++;
+       spin_lock(&ip->i_flags_lock);
        ip->i_flags |= XFS_INEW;
+       spin_unlock(&ip->i_flags_lock);
 
        write_unlock(&ih->ih_lock);
 
@@ -548,7 +552,7 @@ xfs_inode_lock_init(
        mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number);
        init_waitqueue_head(&ip->i_ipin_wait);
        atomic_set(&ip->i_pincount, 0);
-       init_sema(&ip->i_flock, 1, "xfsfino", vp->v_number);
+       initnsema(&ip->i_flock, 1, "xfsfino");
 }
 
 /*
index 1f8ecff8553a3b205525d3998abc0968f25bd2e5..c27d7d495aa0f498ade09aa6a5db5a67a8fa01ce 100644 (file)
@@ -854,7 +854,8 @@ xfs_iread(
        xfs_trans_t     *tp,
        xfs_ino_t       ino,
        xfs_inode_t     **ipp,
-       xfs_daddr_t     bno)
+       xfs_daddr_t     bno,
+       uint            imap_flags)
 {
        xfs_buf_t       *bp;
        xfs_dinode_t    *dip;
@@ -866,6 +867,7 @@ xfs_iread(
        ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
        ip->i_ino = ino;
        ip->i_mount = mp;
+       spin_lock_init(&ip->i_flags_lock);
 
        /*
         * Get pointer's to the on-disk inode and the buffer containing it.
@@ -874,7 +876,7 @@ xfs_iread(
         * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
         * know that this is a new incore inode.
         */
-       error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
+       error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags);
        if (error) {
                kmem_zone_free(xfs_inode_zone, ip);
                return error;
@@ -1113,7 +1115,7 @@ xfs_ialloc(
         * to prevent others from looking at until we're done.
         */
        error = xfs_trans_iget(tp->t_mountp, tp, ino,
-                       IGET_CREATE, XFS_ILOCK_EXCL, &ip);
+                               XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip);
        if (error != 0) {
                return error;
        }
@@ -2213,7 +2215,9 @@ xfs_ifree_cluster(
 
                        if (ip == free_ip) {
                                if (xfs_iflock_nowait(ip)) {
+                                       spin_lock(&ip->i_flags_lock);
                                        ip->i_flags |= XFS_ISTALE;
+                                       spin_unlock(&ip->i_flags_lock);
 
                                        if (xfs_inode_clean(ip)) {
                                                xfs_ifunlock(ip);
@@ -2227,7 +2231,9 @@ xfs_ifree_cluster(
 
                        if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
                                if (xfs_iflock_nowait(ip)) {
+                                       spin_lock(&ip->i_flags_lock);
                                        ip->i_flags |= XFS_ISTALE;
+                                       spin_unlock(&ip->i_flags_lock);
 
                                        if (xfs_inode_clean(ip)) {
                                                xfs_ifunlock(ip);
@@ -2257,7 +2263,9 @@ xfs_ifree_cluster(
                                AIL_LOCK(mp,s);
                                iip->ili_flush_lsn = iip->ili_item.li_lsn;
                                AIL_UNLOCK(mp, s);
+                               spin_lock(&iip->ili_inode->i_flags_lock);
                                iip->ili_inode->i_flags |= XFS_ISTALE;
+                               spin_unlock(&iip->ili_inode->i_flags_lock);
                                pre_flushed++;
                        }
                        lip = lip->li_bio_list;
@@ -2753,19 +2761,29 @@ xfs_iunpin(
                 * call as the inode reclaim may be blocked waiting for
                 * the inode to become unpinned.
                 */
+               struct inode *inode = NULL;
+
+               spin_lock(&ip->i_flags_lock);
                if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
                        bhv_vnode_t     *vp = XFS_ITOV_NULL(ip);
 
                        /* make sync come back and flush this inode */
                        if (vp) {
-                               struct inode    *inode = vn_to_inode(vp);
+                               inode = vn_to_inode(vp);
 
                                if (!(inode->i_state &
-                                               (I_NEW|I_FREEING|I_CLEAR)))
-                                       mark_inode_dirty_sync(inode);
+                                               (I_NEW|I_FREEING|I_CLEAR))) {
+                                       inode = igrab(inode);
+                                       if (inode)
+                                               mark_inode_dirty_sync(inode);
+                               } else
+                                       inode = NULL;
                        }
                }
+               spin_unlock(&ip->i_flags_lock);
                wake_up(&ip->i_ipin_wait);
+               if (inode)
+                       iput(inode);
        }
 }
 
index d10b76ed1e5bd0c6f99689998f5a342a12939bad..e96eb0835fe658a9a2ba8df257eb94a1f130a15d 100644 (file)
@@ -267,6 +267,7 @@ typedef struct xfs_inode {
        sema_t                  i_flock;        /* inode flush lock */
        atomic_t                i_pincount;     /* inode pin count */
        wait_queue_head_t       i_ipin_wait;    /* inode pinning wait queue */
+       spinlock_t              i_flags_lock;   /* inode i_flags lock */
 #ifdef HAVE_REFCACHE
        struct xfs_inode        **i_refcache;   /* ptr to entry in ref cache */
        struct xfs_inode        *i_release;     /* inode to unref */
@@ -389,11 +390,14 @@ typedef struct xfs_inode {
        (((vfsp)->vfs_flag & VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
 
 /*
- * xfs_iget.c prototypes.
+ * Flags for xfs_iget()
  */
+#define XFS_IGET_CREATE                0x1
+#define XFS_IGET_BULKSTAT      0x2
 
-#define IGET_CREATE    1
-
+/*
+ * xfs_iget.c prototypes.
+ */
 void           xfs_ihash_init(struct xfs_mount *);
 void           xfs_ihash_free(struct xfs_mount *);
 void           xfs_chash_init(struct xfs_mount *);
@@ -425,7 +429,7 @@ int         xfs_itobp(struct xfs_mount *, struct xfs_trans *,
                          xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
                          xfs_daddr_t, uint);
 int            xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-                         xfs_inode_t **, xfs_daddr_t);
+                         xfs_inode_t **, xfs_daddr_t, uint);
 int            xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
 int            xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
                           xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
index f8e80d8e72370ff12bfa66686256b7641f7ca7cc..a7a92251eb564d84c3898d407b01b04baf7c673f 100644 (file)
@@ -742,21 +742,6 @@ xfs_inode_item_committed(
        return (lsn);
 }
 
-/*
- * The transaction with the inode locked has aborted.  The inode
- * must not be dirty within the transaction (unless we're forcibly
- * shutting down).  We simply unlock just as if the transaction
- * had been cancelled.
- */
-STATIC void
-xfs_inode_item_abort(
-       xfs_inode_log_item_t    *iip)
-{
-       xfs_inode_item_unlock(iip);
-       return;
-}
-
-
 /*
  * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK
  * failed to get the inode flush lock but did get the inode locked SHARED.
@@ -915,7 +900,6 @@ STATIC struct xfs_item_ops xfs_inode_item_ops = {
        .iop_committed  = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_inode_item_committed,
        .iop_push       = (void(*)(xfs_log_item_t*))xfs_inode_item_push,
-       .iop_abort      = (void(*)(xfs_log_item_t*))xfs_inode_item_abort,
        .iop_pushbuf    = (void(*)(xfs_log_item_t*))xfs_inode_item_pushbuf,
        .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
                                        xfs_inode_item_committing
index 5db6cd1b4cf3278fec78975c7969492f96d67dde..bfe92ea17952a3764ffe284231ebb87120f38751 100644 (file)
  * must be added on to the end.
  */
 typedef struct xfs_inode_log_format {
-       unsigned short          ilf_type;       /* inode log item type */
-       unsigned short          ilf_size;       /* size of this item */
-       uint                    ilf_fields;     /* flags for fields logged */
-       ushort                  ilf_asize;      /* size of attr d/ext/root */
-       ushort                  ilf_dsize;      /* size of data/ext/root */
-       xfs_ino_t               ilf_ino;        /* inode number */
+       __uint16_t              ilf_type;       /* inode log item type */
+       __uint16_t              ilf_size;       /* size of this item */
+       __uint32_t              ilf_fields;     /* flags for fields logged */
+       __uint16_t              ilf_asize;      /* size of attr d/ext/root */
+       __uint16_t              ilf_dsize;      /* size of data/ext/root */
+       __uint64_t              ilf_ino;        /* inode number */
        union {
-               xfs_dev_t       ilfu_rdev;      /* rdev value for dev inode*/
+               __uint32_t      ilfu_rdev;      /* rdev value for dev inode*/
                uuid_t          ilfu_uuid;      /* mount point value */
        } ilf_u;
        __int64_t               ilf_blkno;      /* blkno of inode buffer */
-       int                     ilf_len;        /* len of inode buffer */
-       int                     ilf_boffset;    /* off of inode in buffer */
+       __int32_t               ilf_len;        /* len of inode buffer */
+       __int32_t               ilf_boffset;    /* off of inode in buffer */
 } xfs_inode_log_format_t;
 
+#ifndef HAVE_FORMAT32
 typedef struct xfs_inode_log_format_32 {
-       unsigned short          ilf_type;       /* 16: inode log item type */
-       unsigned short          ilf_size;       /* 16: size of this item */
-       uint                    ilf_fields;     /* 32: flags for fields logged */
-       ushort                  ilf_asize;      /* 32: size of attr d/ext/root */
-       ushort                  ilf_dsize;      /* 32: size of data/ext/root */
-       xfs_ino_t               ilf_ino;        /* 64: inode number */
+       __uint16_t              ilf_type;       /* inode log item type */
+       __uint16_t              ilf_size;       /* size of this item */
+       __uint32_t              ilf_fields;     /* flags for fields logged */
+       __uint16_t              ilf_asize;      /* size of attr d/ext/root */
+       __uint16_t              ilf_dsize;      /* size of data/ext/root */
+       __uint64_t              ilf_ino;        /* inode number */
        union {
-               xfs_dev_t       ilfu_rdev;      /* 32: rdev value for dev inode*/
-               uuid_t          ilfu_uuid;      /* 128: mount point value */
+               __uint32_t      ilfu_rdev;      /* rdev value for dev inode*/
+               uuid_t          ilfu_uuid;      /* mount point value */
        } ilf_u;
-       __int64_t               ilf_blkno;      /* 64: blkno of inode buffer */
-       int                     ilf_len;        /* 32: len of inode buffer */
-       int                     ilf_boffset;    /* 32: off of inode in buffer */
+       __int64_t               ilf_blkno;      /* blkno of inode buffer */
+       __int32_t               ilf_len;        /* len of inode buffer */
+       __int32_t               ilf_boffset;    /* off of inode in buffer */
 } __attribute__((packed)) xfs_inode_log_format_32_t;
+#endif
 
 typedef struct xfs_inode_log_format_64 {
-       unsigned short          ilf_type;       /* 16: inode log item type */
-       unsigned short          ilf_size;       /* 16: size of this item */
-       uint                    ilf_fields;     /* 32: flags for fields logged */
-       ushort                  ilf_asize;      /* 32: size of attr d/ext/root */
-       ushort                  ilf_dsize;      /* 32: size of data/ext/root */
-       __uint32_t              ilf_pad;        /* 32: pad for 64 bit boundary */
-       xfs_ino_t               ilf_ino;        /* 64: inode number */
+       __uint16_t              ilf_type;       /* inode log item type */
+       __uint16_t              ilf_size;       /* size of this item */
+       __uint32_t              ilf_fields;     /* flags for fields logged */
+       __uint16_t              ilf_asize;      /* size of attr d/ext/root */
+       __uint16_t              ilf_dsize;      /* size of data/ext/root */
+       __uint32_t              ilf_pad;        /* pad for 64 bit boundary */
+       __uint64_t              ilf_ino;        /* inode number */
        union {
-               xfs_dev_t       ilfu_rdev;      /* 32: rdev value for dev inode*/
-               uuid_t          ilfu_uuid;      /* 128: mount point value */
+               __uint32_t      ilfu_rdev;      /* rdev value for dev inode*/
+               uuid_t          ilfu_uuid;      /* mount point value */
        } ilf_u;
-       __int64_t               ilf_blkno;      /* 64: blkno of inode buffer */
-       int                     ilf_len;        /* 32: len of inode buffer */
-       int                     ilf_boffset;    /* 32: off of inode in buffer */
+       __int64_t               ilf_blkno;      /* blkno of inode buffer */
+       __int32_t               ilf_len;        /* len of inode buffer */
+       __int32_t               ilf_boffset;    /* off of inode in buffer */
 } xfs_inode_log_format_64_t;
 
 /*
index f1949c16df154157bbdada2882d2656ab918311f..19655124da782299a409eee8bb78ed26f676ceae 100644 (file)
@@ -398,6 +398,23 @@ xfs_flush_space(
        return 1;
 }
 
+STATIC int
+xfs_cmn_err_fsblock_zero(
+       xfs_inode_t     *ip,
+       xfs_bmbt_irec_t *imap)
+{
+       xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+                       "Access to block zero in inode %llu "
+                       "start_block: %llx start_off: %llx "
+                       "blkcnt: %llx extent-state: %x\n",
+               (unsigned long long)ip->i_ino,
+               (unsigned long long)imap->br_startblock,
+               (unsigned long long)imap->br_startoff,
+               (unsigned long long)imap->br_blockcount,
+               imap->br_state);
+       return EFSCORRUPTED;
+}
+
 int
 xfs_iomap_write_direct(
        xfs_inode_t     *ip,
@@ -536,23 +553,17 @@ xfs_iomap_write_direct(
         * Copy any maps to caller's array and return any error.
         */
        if (nimaps == 0) {
-               error = (ENOSPC);
+               error = ENOSPC;
+               goto error_out;
+       }
+
+       if (unlikely(!imap.br_startblock && !(io->io_flags & XFS_IOCORE_RT))) {
+               error = xfs_cmn_err_fsblock_zero(ip, &imap);
                goto error_out;
        }
 
        *ret_imap = imap;
        *nmaps = 1;
-       if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
-                cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
-                        "start_block : %llx start_off : %llx blkcnt : %llx "
-                        "extent-state : %x \n",
-                        (ip->i_mount)->m_fsname,
-                        (long long)ip->i_ino,
-                        (unsigned long long)ret_imap->br_startblock,
-                       (unsigned long long)ret_imap->br_startoff,
-                        (unsigned long long)ret_imap->br_blockcount,
-                       ret_imap->br_state);
-        }
        return 0;
 
 error0:        /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
@@ -715,17 +726,8 @@ retry:
                goto retry;
        }
 
-       if (!(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
-               cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
-                        "start_block : %llx start_off : %llx blkcnt : %llx "
-                        "extent-state : %x \n",
-                        (ip->i_mount)->m_fsname,
-                        (long long)ip->i_ino,
-                        (unsigned long long)ret_imap->br_startblock,
-                       (unsigned long long)ret_imap->br_startoff,
-                        (unsigned long long)ret_imap->br_blockcount,
-                       ret_imap->br_state);
-       }
+       if (unlikely(!imap[0].br_startblock && !(io->io_flags & XFS_IOCORE_RT)))
+               return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
 
        *ret_imap = imap[0];
        *nmaps = 1;
@@ -853,24 +855,10 @@ xfs_iomap_write_allocate(
                 * See if we were able to allocate an extent that
                 * covers at least part of the callers request
                 */
-
                for (i = 0; i < nimaps; i++) {
-                       if (!(io->io_flags & XFS_IOCORE_RT)  &&
-                           !imap[i].br_startblock) {
-                               cmn_err(CE_PANIC,"Access to block zero:  "
-                                       "fs <%s> inode: %lld "
-                                       "start_block : %llx start_off : %llx "
-                                       "blkcnt : %llx extent-state : %x \n",
-                                       (ip->i_mount)->m_fsname,
-                                       (long long)ip->i_ino,
-                                       (unsigned long long)
-                                               imap[i].br_startblock,
-                                       (unsigned long long)
-                                               imap[i].br_startoff,
-                                       (unsigned long long)
-                                               imap[i].br_blockcount,
-                                       imap[i].br_state);
-                        }
+                       if (unlikely(!imap[i].br_startblock &&
+                                    !(io->io_flags & XFS_IOCORE_RT)))
+                               return xfs_cmn_err_fsblock_zero(ip, &imap[i]);
                        if ((offset_fsb >= imap[i].br_startoff) &&
                            (offset_fsb < (imap[i].br_startoff +
                                           imap[i].br_blockcount))) {
@@ -941,7 +929,7 @@ xfs_iomap_write_unwritten(
                                XFS_WRITE_LOG_COUNT);
                if (error) {
                        xfs_trans_cancel(tp, 0);
-                       goto error0;
+                       return XFS_ERROR(error);
                }
 
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -967,19 +955,11 @@ xfs_iomap_write_unwritten(
                error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
                if (error)
-                       goto error0;
-
-               if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
-                       cmn_err(CE_PANIC,"Access to block zero:  fs <%s> "
-                               "inode: %lld start_block : %llx start_off : "
-                               "%llx blkcnt : %llx extent-state : %x \n",
-                               (ip->i_mount)->m_fsname,
-                               (long long)ip->i_ino,
-                               (unsigned long long)imap.br_startblock,
-                               (unsigned long long)imap.br_startoff,
-                               (unsigned long long)imap.br_blockcount,
-                               imap.br_state);
-               }
+                       return XFS_ERROR(error);
+
+               if (unlikely(!imap.br_startblock &&
+                            !(io->io_flags & XFS_IOCORE_RT)))
+                       return xfs_cmn_err_fsblock_zero(ip, &imap);
 
                if ((numblks_fsb = imap.br_blockcount) == 0) {
                        /*
@@ -999,6 +979,5 @@ error_on_bmapi_transaction:
        xfs_bmap_cancel(&free_list);
        xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
-error0:
        return XFS_ERROR(error);
 }
index 46249e4d1feaba62eec485e23376c2d3508f7440..7775ddc0b3c6b105449bef21a3954741533129f4 100644 (file)
 #include "xfs_error.h"
 #include "xfs_btree.h"
 
+int
+xfs_internal_inum(
+       xfs_mount_t     *mp,
+       xfs_ino_t       ino)
+{
+       return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+               (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
+                (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
+}
+
 STATIC int
 xfs_bulkstat_one_iget(
        xfs_mount_t     *mp,            /* mount point for filesystem */
@@ -52,7 +62,8 @@ xfs_bulkstat_one_iget(
        bhv_vnode_t     *vp;
        int             error;
 
-       error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
+       error = xfs_iget(mp, NULL, ino,
+                        XFS_IGET_BULKSTAT, XFS_ILOCK_SHARED, &ip, bno);
        if (error) {
                *stat = BULKSTAT_RV_NOTHING;
                return error;
@@ -212,17 +223,12 @@ xfs_bulkstat_one(
        xfs_dinode_t    *dip;           /* dinode inode pointer */
 
        dip = (xfs_dinode_t *)dibuff;
+       *stat = BULKSTAT_RV_NOTHING;
 
-       if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
-           (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
-            (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
-               *stat = BULKSTAT_RV_NOTHING;
+       if (!buffer || xfs_internal_inum(mp, ino))
                return XFS_ERROR(EINVAL);
-       }
-       if (ubsize < sizeof(*buf)) {
-               *stat = BULKSTAT_RV_NOTHING;
+       if (ubsize < sizeof(*buf))
                return XFS_ERROR(ENOMEM);
-       }
 
        buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
 
@@ -238,8 +244,7 @@ xfs_bulkstat_one(
        }
 
        if (copy_to_user(buffer, buf, sizeof(*buf)))  {
-               *stat = BULKSTAT_RV_NOTHING;
-               error =  EFAULT;
+               error = EFAULT;
                goto out_free;
        }
 
@@ -252,6 +257,46 @@ xfs_bulkstat_one(
        return error;
 }
 
+/*
+ * Test to see whether we can use the ondisk inode directly, based
+ * on the given bulkstat flags, filling in dipp accordingly.
+ * Returns zero if the inode is dodgey.
+ */
+STATIC int
+xfs_bulkstat_use_dinode(
+       xfs_mount_t     *mp,
+       int             flags,
+       xfs_buf_t       *bp,
+       int             clustidx,
+       xfs_dinode_t    **dipp)
+{
+       xfs_dinode_t    *dip;
+       unsigned int    aformat;
+
+       *dipp = NULL;
+       if (!bp || (flags & BULKSTAT_FG_IGET))
+               return 1;
+       dip = (xfs_dinode_t *)
+                       xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
+       if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC ||
+           !XFS_DINODE_GOOD_VERSION(
+                       INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
+               return 0;
+       if (flags & BULKSTAT_FG_QUICK) {
+               *dipp = dip;
+               return 1;
+       }
+       /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
+       aformat = INT_GET(dip->di_core.di_aformat, ARCH_CONVERT);
+       if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
+           (aformat == XFS_DINODE_FMT_LOCAL) ||
+           (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
+               *dipp = dip;
+               return 1;
+       }
+       return 1;
+}
+
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
@@ -284,10 +329,11 @@ xfs_bulkstat(
        xfs_agino_t             gino;   /* current btree rec's start inode */
        int                     i;      /* loop index */
        int                     icount; /* count of inodes good in irbuf */
+       size_t                  irbsize; /* size of irec buffer in bytes */
        xfs_ino_t               ino;    /* inode number (filesystem) */
-       xfs_inobt_rec_t         *irbp;  /* current irec buffer pointer */
-       xfs_inobt_rec_t         *irbuf; /* start of irec buffer */
-       xfs_inobt_rec_t         *irbufend; /* end of good irec buffer entries */
+       xfs_inobt_rec_incore_t  *irbp;  /* current irec buffer pointer */
+       xfs_inobt_rec_incore_t  *irbuf; /* start of irec buffer */
+       xfs_inobt_rec_incore_t  *irbufend; /* end of good irec buffer entries */
        xfs_ino_t               lastino=0; /* last inode number returned */
        int                     nbcluster; /* # of blocks in a cluster */
        int                     nicluster; /* # of inodes in a cluster */
@@ -328,13 +374,10 @@ xfs_bulkstat(
                (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
        nimask = ~(nicluster - 1);
        nbcluster = nicluster >> mp->m_sb.sb_inopblog;
-       /*
-        * Allocate a page-sized buffer for inode btree records.
-        * We could try allocating something smaller, but for normal
-        * calls we'll always (potentially) need the whole page.
-        */
-       irbuf = kmem_alloc(NBPC, KM_SLEEP);
-       nirbuf = NBPC / sizeof(*irbuf);
+       irbuf = kmem_zalloc_greedy(&irbsize, NBPC, NBPC * 4,
+                                  KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+       nirbuf = irbsize / sizeof(*irbuf);
+
        /*
         * Loop over the allocation groups, starting from the last
         * inode returned; 0 means start of the allocation group.
@@ -358,7 +401,7 @@ xfs_bulkstat(
                 * Allocate and initialize a btree cursor for ialloc btree.
                 */
                cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO,
-                       (xfs_inode_t *)0, 0);
+                                               (xfs_inode_t *)0, 0);
                irbp = irbuf;
                irbufend = irbuf + nirbuf;
                end_of_ag = 0;
@@ -395,9 +438,9 @@ xfs_bulkstat(
                                                gcnt++;
                                }
                                gfree |= XFS_INOBT_MASKN(0, chunkidx);
-                               INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
-                               INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
-                               INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
+                               irbp->ir_startino = gino;
+                               irbp->ir_freecount = gcnt;
+                               irbp->ir_free = gfree;
                                irbp++;
                                agino = gino + XFS_INODES_PER_CHUNK;
                                icount = XFS_INODES_PER_CHUNK - gcnt;
@@ -451,11 +494,27 @@ xfs_bulkstat(
                        }
                        /*
                         * If this chunk has any allocated inodes, save it.
+                        * Also start read-ahead now for this chunk.
                         */
                        if (gcnt < XFS_INODES_PER_CHUNK) {
-                               INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
-                               INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
-                               INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
+                               /*
+                                * Loop over all clusters in the next chunk.
+                                * Do a readahead if there are any allocated
+                                * inodes in that cluster.
+                                */
+                               for (agbno = XFS_AGINO_TO_AGBNO(mp, gino),
+                                    chunkidx = 0;
+                                    chunkidx < XFS_INODES_PER_CHUNK;
+                                    chunkidx += nicluster,
+                                    agbno += nbcluster) {
+                                       if (XFS_INOBT_MASKN(chunkidx,
+                                                           nicluster) & ~gfree)
+                                               xfs_btree_reada_bufs(mp, agno,
+                                                       agbno, nbcluster);
+                               }
+                               irbp->ir_startino = gino;
+                               irbp->ir_freecount = gcnt;
+                               irbp->ir_free = gfree;
                                irbp++;
                                icount += XFS_INODES_PER_CHUNK - gcnt;
                        }
@@ -478,34 +537,12 @@ xfs_bulkstat(
                irbufend = irbp;
                for (irbp = irbuf;
                     irbp < irbufend && ubleft >= statstruct_size; irbp++) {
-                       /*
-                        * Read-ahead the next chunk's worth of inodes.
-                        */
-                       if (&irbp[1] < irbufend) {
-                               /*
-                                * Loop over all clusters in the next chunk.
-                                * Do a readahead if there are any allocated
-                                * inodes in that cluster.
-                                */
-                               for (agbno = XFS_AGINO_TO_AGBNO(mp,
-                                                       INT_GET(irbp[1].ir_startino, ARCH_CONVERT)),
-                                    chunkidx = 0;
-                                    chunkidx < XFS_INODES_PER_CHUNK;
-                                    chunkidx += nicluster,
-                                    agbno += nbcluster) {
-                                       if (XFS_INOBT_MASKN(chunkidx,
-                                                           nicluster) &
-                                           ~(INT_GET(irbp[1].ir_free, ARCH_CONVERT)))
-                                               xfs_btree_reada_bufs(mp, agno,
-                                                       agbno, nbcluster);
-                               }
-                       }
                        /*
                         * Now process this chunk of inodes.
                         */
-                       for (agino = INT_GET(irbp->ir_startino, ARCH_CONVERT), chunkidx = 0, clustidx = 0;
+                       for (agino = irbp->ir_startino, chunkidx = clustidx = 0;
                             ubleft > 0 &&
-                               INT_GET(irbp->ir_freecount, ARCH_CONVERT) < XFS_INODES_PER_CHUNK;
+                               irbp->ir_freecount < XFS_INODES_PER_CHUNK;
                             chunkidx++, clustidx++, agino++) {
                                ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
                                /*
@@ -525,11 +562,12 @@ xfs_bulkstat(
                                 */
                                if ((chunkidx & (nicluster - 1)) == 0) {
                                        agbno = XFS_AGINO_TO_AGBNO(mp,
-                                                       INT_GET(irbp->ir_startino, ARCH_CONVERT)) +
+                                                       irbp->ir_startino) +
                                                ((chunkidx & nimask) >>
                                                 mp->m_sb.sb_inopblog);
 
-                                       if (flags & BULKSTAT_FG_QUICK) {
+                                       if (flags & (BULKSTAT_FG_QUICK |
+                                                    BULKSTAT_FG_INLINE)) {
                                                ino = XFS_AGINO_TO_INO(mp, agno,
                                                                       agino);
                                                bno = XFS_AGB_TO_DADDR(mp, agno,
@@ -543,6 +581,7 @@ xfs_bulkstat(
                                                                      KM_SLEEP);
                                                ip->i_ino = ino;
                                                ip->i_mount = mp;
+                                               spin_lock_init(&ip->i_flags_lock);
                                                if (bp)
                                                        xfs_buf_relse(bp);
                                                error = xfs_itobp(mp, NULL, ip,
@@ -564,30 +603,34 @@ xfs_bulkstat(
                                /*
                                 * Skip if this inode is free.
                                 */
-                               if (XFS_INOBT_MASK(chunkidx) & INT_GET(irbp->ir_free, ARCH_CONVERT))
+                               if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
                                        continue;
                                /*
                                 * Count used inodes as free so we can tell
                                 * when the chunk is used up.
                                 */
-                               INT_MOD(irbp->ir_freecount, ARCH_CONVERT, +1);
+                               irbp->ir_freecount++;
                                ino = XFS_AGINO_TO_INO(mp, agno, agino);
                                bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
-                               if (flags & BULKSTAT_FG_QUICK) {
-                                       dip = (xfs_dinode_t *)xfs_buf_offset(bp,
-                                             (clustidx << mp->m_sb.sb_inodelog));
-
-                                       if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT)
-                                                   != XFS_DINODE_MAGIC
-                                           || !XFS_DINODE_GOOD_VERSION(
-                                                   INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
-                                               continue;
+                               if (!xfs_bulkstat_use_dinode(mp, flags, bp,
+                                                            clustidx, &dip))
+                                       continue;
+                               /*
+                                * If we need to do an iget, cannot hold bp.
+                                * Drop it, until starting the next cluster.
+                                */
+                               if ((flags & BULKSTAT_FG_INLINE) && !dip) {
+                                       if (bp)
+                                               xfs_buf_relse(bp);
+                                       bp = NULL;
                                }
 
                                /*
                                 * Get the inode and fill in a single buffer.
                                 * BULKSTAT_FG_QUICK uses dip to fill it in.
                                 * BULKSTAT_FG_IGET uses igets.
+                                * BULKSTAT_FG_INLINE uses dip if we have an
+                                * inline attr fork, else igets.
                                 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
                                 * This is also used to count inodes/blks, etc
                                 * in xfs_qm_quotacheck.
@@ -597,8 +640,15 @@ xfs_bulkstat(
                                                ubleft, private_data,
                                                bno, &ubused, dip, &fmterror);
                                if (fmterror == BULKSTAT_RV_NOTHING) {
-                                       if (error == ENOMEM)
+                                        if (error == EFAULT) {
+                                                ubleft = 0;
+                                                rval = error;
+                                                break;
+                                        }
+                                       else if (error == ENOMEM)
                                                ubleft = 0;
+                                       else
+                                               lastino = ino;
                                        continue;
                                }
                                if (fmterror == BULKSTAT_RV_GIVEUP) {
@@ -633,7 +683,7 @@ xfs_bulkstat(
        /*
         * Done, we're either out of filesystem or space to put the data.
         */
-       kmem_free(irbuf, NBPC);
+       kmem_free(irbuf, irbsize);
        *ubcountp = ubelem;
        if (agno >= mp->m_sb.sb_agcount) {
                /*
index be5f12e07d2217d98814127747d8fc9eadb40cc0..f25a28862a1770a02e8c0b3ca4cd43a3b0b82352 100644 (file)
@@ -36,15 +36,16 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount     *mp,
 /*
  * Values for stat return value.
  */
-#define        BULKSTAT_RV_NOTHING     0
-#define        BULKSTAT_RV_DIDONE      1
-#define        BULKSTAT_RV_GIVEUP      2
+#define BULKSTAT_RV_NOTHING    0
+#define BULKSTAT_RV_DIDONE     1
+#define BULKSTAT_RV_GIVEUP     2
 
 /*
  * Values for bulkstat flag argument.
  */
-#define        BULKSTAT_FG_IGET        0x1     /* Go through the buffer cache */
-#define        BULKSTAT_FG_QUICK       0x2     /* No iget, walk the dinode cluster */
+#define BULKSTAT_FG_IGET       0x1     /* Go through the buffer cache */
+#define BULKSTAT_FG_QUICK      0x2     /* No iget, walk the dinode cluster */
+#define BULKSTAT_FG_INLINE     0x4     /* No iget if inline attrs */
 
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
@@ -80,6 +81,11 @@ xfs_bulkstat_one(
        void                    *dibuff,
        int                     *stat);
 
+int
+xfs_internal_inum(
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino);
+
 int                                    /* error status */
 xfs_inumbers(
        xfs_mount_t             *mp,    /* mount point for filesystem */
index 21ac1a67e3e03c763eb61ea9be1e2a2eb170631e..c48bf61f17bd847cdb04a6ca8ad6b6f9f8c7e273 100644 (file)
@@ -617,7 +617,8 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                reg[0].i_len  = sizeof(magic);
                XLOG_VEC_SET_TYPE(&reg[0], XLOG_REG_TYPE_UNMOUNT);
 
-               error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0, 0);
+               error = xfs_log_reserve(mp, 600, 1, &tic,
+                                       XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE);
                if (!error) {
                        /* remove inited flag */
                        ((xlog_ticket_t *)tic)->t_flags = 0;
@@ -655,8 +656,11 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                } else {
                        LOG_UNLOCK(log, s);
                }
-               if (tic)
+               if (tic) {
+                       xlog_trace_loggrant(log, tic, "unmount rec");
+                       xlog_ungrant_log_space(log, tic);
                        xlog_state_put_ticket(log, tic);
+               }
        } else {
                /*
                 * We're already in forced_shutdown mode, couldn't
@@ -1196,7 +1200,7 @@ xlog_alloc_log(xfs_mount_t        *mp,
                          kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
                iclog = *iclogp;
                iclog->hic_data = (xlog_in_core_2_t *)
-                         kmem_zalloc(iclogsize, KM_SLEEP);
+                         kmem_zalloc(iclogsize, KM_SLEEP | KM_LARGE);
 
                iclog->ic_prev = prev_iclog;
                prev_iclog = iclog;
@@ -2212,9 +2216,13 @@ xlog_state_do_callback(
 
                        iclog = iclog->ic_next;
                } while (first_iclog != iclog);
-               if (repeats && (repeats % 10) == 0) {
+
+               if (repeats > 5000) {
+                       flushcnt += repeats;
+                       repeats = 0;
                        xfs_fs_cmn_err(CE_WARN, log->l_mp,
-                               "xlog_state_do_callback: looping %d", repeats);
+                               "%s: possible infinite loop (%d iterations)",
+                               __FUNCTION__, flushcnt);
                }
        } while (!ioerrors && loopdidcallbacks);
 
@@ -2246,6 +2254,7 @@ xlog_state_do_callback(
        }
 #endif
 
+       flushcnt = 0;
        if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) {
                flushcnt = log->l_flushcnt;
                log->l_flushcnt = 0;
index eacb3d4987f25ad17a9927d1c302a0f99f879668..ebbe93f4f97bc7925a458996e2f8c11943223f9a 100644 (file)
@@ -47,17 +47,11 @@ static inline xfs_lsn_t     _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
  * Macros, structures, prototypes for interface to the log manager.
  */
 
-/*
- * Flags to xfs_log_mount
- */
-#define XFS_LOG_RECOVER                0x1
-
 /*
  * Flags to xfs_log_done()
  */
 #define XFS_LOG_REL_PERM_RESERV        0x1
 
-
 /*
  * Flags to xfs_log_reserve()
  *
@@ -70,8 +64,6 @@ static inline xfs_lsn_t       _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
 #define XFS_LOG_SLEEP          0x0
 #define XFS_LOG_NOSLEEP                0x1
 #define XFS_LOG_PERM_RESERV    0x2
-#define XFS_LOG_RESV_ALL       (XFS_LOG_NOSLEEP|XFS_LOG_PERM_RESERV)
-
 
 /*
  * Flags to xfs_log_force()
index 34bcbf50789c1e614e474427341cdcd6889e7efa..9bd3cdf11a87068db1b773b5afabb2ea0a5bc913 100644 (file)
@@ -32,7 +32,6 @@ struct xfs_mount;
 #define XLOG_MIN_ICLOGS                2
 #define XLOG_MED_ICLOGS                4
 #define XLOG_MAX_ICLOGS                8
-#define XLOG_CALLBACK_SIZE     10
 #define XLOG_HEADER_MAGIC_NUM  0xFEEDbabe      /* Invalid cycle number */
 #define XLOG_VERSION_1         1
 #define XLOG_VERSION_2         2               /* Large IClogs, Log sunit */
@@ -149,9 +148,6 @@ struct xfs_mount;
 #define XLOG_WAS_CONT_TRANS    0x08    /* Cont this trans into new region */
 #define XLOG_END_TRANS         0x10    /* End a continued transaction */
 #define XLOG_UNMOUNT_TRANS     0x20    /* Unmount a filesystem transaction */
-#define XLOG_SKIP_TRANS                (XLOG_COMMIT_TRANS | XLOG_CONTINUE_TRANS | \
-                                XLOG_WAS_CONT_TRANS | XLOG_END_TRANS | \
-                                XLOG_UNMOUNT_TRANS)
 
 #ifdef __KERNEL__
 /*
@@ -506,6 +502,12 @@ extern int  xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
 #define XLOG_TRACE_SLEEP_FLUSH 3
 #define XLOG_TRACE_WAKE_FLUSH  4
 
+/*
+ * Unmount record type is used as a pseudo transaction type for the ticket.
+ * It's value must be outside the range of XFS_TRANS_* values.
+ */
+#define XLOG_UNMOUNT_REC_TYPE  (-1U)
+
 #endif /* __KERNEL__ */
 
 #endif /* __XFS_LOG_PRIV_H__ */
index b2bd4be4200a305d449d831e6d88edeac614380e..e5f396ff9a3d57f45bb3174449f9cfbd752adf19 100644 (file)
@@ -331,7 +331,7 @@ typedef struct xfs_mount {
        xfs_agnumber_t          m_agirotor;     /* last ag dir inode alloced */
        lock_t                  m_agirotor_lock;/* .. and lock protecting it */
        xfs_agnumber_t          m_maxagi;       /* highest inode alloc group */
-       uint                    m_ihsize;       /* size of next field */
+       size_t                  m_ihsize;       /* size of next field */
        struct xfs_ihash        *m_ihash;       /* fs private inode hash table*/
        struct xfs_inode        *m_inodes;      /* active inode list */
        struct list_head        m_del_inodes;   /* inodes to reclaim */
@@ -541,7 +541,8 @@ static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp)
 #define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
 static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs)
 {
-       return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops));
+       return XFS_BHVTOM(bhv_lookup_range(VFS_BHVHEAD(vfs),
+                               VFS_POSITION_XFS, VFS_POSITION_XFS));
 }
 
 #define XFS_DADDR_TO_AGNO(mp,d)         xfs_daddr_to_agno(mp,d)
index acb853b33ebbd632765403361e6debf8ae90823a..9dcb32aa4e2ea2a25eac703996bedfc8bb219421 100644 (file)
@@ -281,8 +281,6 @@ typedef struct xfs_qoff_logformat {
                                 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
                                 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
                                 XFS_GQUOTA_ACCT)
-#define XFS_MOUNT_QUOTA_MASK   (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
-                                XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
 
 
 /*
index 5a0b678956e0e3ca616efb76ffb9d827f6d159fa..880c73271c05fac890f3e0dcdd53a4805ae26be0 100644 (file)
@@ -1948,7 +1948,7 @@ xfs_growfs_rt(
         */
        nrextents = nrblocks;
        do_div(nrextents, in->extsize);
-       nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
+       nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize);
        nrextslog = xfs_highbit32(nrextents);
        nrsumlevels = nrextslog + 1;
        nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
@@ -1976,7 +1976,10 @@ xfs_growfs_rt(
        if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
                        mp->m_sb.sb_rsumino)))
                return error;
-       nmp = NULL;
+       /*
+        * Allocate a new (fake) mount/sb.
+        */
+       nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
        /*
         * Loop over the bitmap blocks.
         * We will do everything one bitmap block at a time.
@@ -1987,10 +1990,6 @@ xfs_growfs_rt(
                     ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
             bmbno < nrbmblocks;
             bmbno++) {
-               /*
-                * Allocate a new (fake) mount/sb.
-                */
-               nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
                *nmp = *mp;
                nsbp = &nmp->m_sb;
                /*
@@ -2018,13 +2017,13 @@ xfs_growfs_rt(
                cancelflags = 0;
                if ((error = xfs_trans_reserve(tp, 0,
                                XFS_GROWRTFREE_LOG_RES(nmp), 0, 0, 0)))
-                       goto error_exit;
+                       break;
                /*
                 * Lock out other callers by grabbing the bitmap inode lock.
                 */
                if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
                                                XFS_ILOCK_EXCL, &ip)))
-                       goto error_exit;
+                       break;
                ASSERT(ip == mp->m_rbmip);
                /*
                 * Update the bitmap inode's size.
@@ -2038,7 +2037,7 @@ xfs_growfs_rt(
                 */
                if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0,
                                                XFS_ILOCK_EXCL, &ip)))
-                       goto error_exit;
+                       break;
                ASSERT(ip == mp->m_rsumip);
                /*
                 * Update the summary inode's size.
@@ -2053,7 +2052,7 @@ xfs_growfs_rt(
                    mp->m_rsumlevels != nmp->m_rsumlevels) {
                        error = xfs_rtcopy_summary(mp, nmp, tp);
                        if (error)
-                               goto error_exit;
+                               break;
                }
                /*
                 * Update superblock fields.
@@ -2080,17 +2079,12 @@ xfs_growfs_rt(
                error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
                        nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
                if (error)
-                       goto error_exit;
+                       break;
                /*
                 * Mark more blocks free in the superblock.
                 */
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
                        nsbp->sb_rextents - sbp->sb_rextents);
-               /*
-                * Free the fake mp structure.
-                */
-               kmem_free(nmp, sizeof(*nmp));
-               nmp = NULL;
                /*
                 * Update mp values into the real mp structure.
                 */
@@ -2101,15 +2095,15 @@ xfs_growfs_rt(
                 */
                xfs_trans_commit(tp, 0, NULL);
        }
-       return 0;
+
+       if (error)
+               xfs_trans_cancel(tp, cancelflags);
 
        /*
-        * Error paths come here.
+        * Free the fake mp structure.
         */
-error_exit:
-       if (nmp)
-               kmem_free(nmp, sizeof(*nmp));
-       xfs_trans_cancel(tp, cancelflags);
+       kmem_free(nmp, sizeof(*nmp));
+
        return error;
 }
 
index bf168a91ddb83ffd4e91f7456fe83fd5bf937e8f..467854b45c8f6dc4d61ce2a0a9a94423178b5147 100644 (file)
@@ -60,10 +60,6 @@ struct xfs_mount;
         XFS_SB_VERSION_LOGV2BIT | \
         XFS_SB_VERSION_SECTORBIT | \
         XFS_SB_VERSION_MOREBITSBIT)
-#define        XFS_SB_VERSION_OKSASHBITS       \
-       (XFS_SB_VERSION_NUMBITS | \
-        XFS_SB_VERSION_REALFBITS | \
-        XFS_SB_VERSION_OKSASHFBITS)
 #define        XFS_SB_VERSION_OKREALBITS       \
        (XFS_SB_VERSION_NUMBITS | \
         XFS_SB_VERSION_OKREALFBITS | \
@@ -81,9 +77,6 @@ struct xfs_mount;
 #define XFS_SB_VERSION2_RESERVED2BIT   0x00000002
 #define XFS_SB_VERSION2_RESERVED4BIT   0x00000004
 #define XFS_SB_VERSION2_ATTR2BIT       0x00000008      /* Inline attr rework */
-#define XFS_SB_VERSION2_SASHFBITS      0xff000000      /* Mask: features that
-                                                          require changing
-                                                          PROM and SASH */
 
 #define        XFS_SB_VERSION2_OKREALFBITS     \
        (XFS_SB_VERSION2_ATTR2BIT)
@@ -238,12 +231,6 @@ static inline int xfs_sb_good_version(xfs_sb_t *sbp)
 }
 #endif /* __KERNEL__ */
 
-#define        XFS_SB_GOOD_SASH_VERSION(sbp)   \
-       ((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
-         ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
-        ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
-         !((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKSASHBITS)))
-
 #define        XFS_SB_VERSION_TONEW(v) xfs_sb_version_tonew(v)
 static inline unsigned xfs_sb_version_tonew(unsigned v)
 {
@@ -461,15 +448,6 @@ static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
  * File system sector to basic block conversions.
  */
 #define XFS_FSS_TO_BB(mp,sec)  ((sec) << (mp)->m_sectbb_log)
-#define XFS_BB_TO_FSS(mp,bb)   \
-       (((bb) + (XFS_FSS_TO_BB(mp,1) - 1)) >> (mp)->m_sectbb_log)
-#define XFS_BB_TO_FSST(mp,bb)  ((bb) >> (mp)->m_sectbb_log)
-
-/*
- * File system sector to byte conversions.
- */
-#define XFS_FSS_TO_B(mp,sectno)        ((xfs_fsize_t)(sectno) << (mp)->m_sb.sb_sectlog)
-#define XFS_B_TO_FSST(mp,b)    (((__uint64_t)(b)) >> (mp)->m_sb.sb_sectlog)
 
 /*
  * File system block to basic block conversions.
index 9dc88b380608e6f29a6bef4c7ee5c21945367f0f..c68e00105d238daeedc3aa036e0f234dd38f8a3d 100644 (file)
@@ -149,7 +149,6 @@ typedef struct xfs_item_ops {
        void (*iop_unlock)(xfs_log_item_t *);
        xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
        void (*iop_push)(xfs_log_item_t *);
-       void (*iop_abort)(xfs_log_item_t *);
        void (*iop_pushbuf)(xfs_log_item_t *);
        void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
 } xfs_item_ops_t;
@@ -163,7 +162,6 @@ typedef struct xfs_item_ops {
 #define IOP_UNLOCK(ip)         (*(ip)->li_ops->iop_unlock)(ip)
 #define IOP_COMMITTED(ip, lsn) (*(ip)->li_ops->iop_committed)(ip, lsn)
 #define IOP_PUSH(ip)           (*(ip)->li_ops->iop_push)(ip)
-#define IOP_ABORT(ip)          (*(ip)->li_ops->iop_abort)(ip)
 #define IOP_PUSHBUF(ip)                (*(ip)->li_ops->iop_pushbuf)(ip)
 #define IOP_COMMITTING(ip, lsn) (*(ip)->li_ops->iop_committing)(ip, lsn)
 
index 558c87ff0c41faeea2da96536da6cf250c2e095d..fc39b166d403e609e356008f05c23fcb682d8b28 100644 (file)
@@ -276,7 +276,7 @@ xfs_trans_update_ail(
        xfs_mount_t     *mp,
        xfs_log_item_t  *lip,
        xfs_lsn_t       lsn,
-       unsigned long   s)
+       unsigned long   s) __releases(mp->m_ail_lock)
 {
        xfs_ail_entry_t         *ailp;
        xfs_log_item_t          *dlip=NULL;
@@ -328,7 +328,7 @@ void
 xfs_trans_delete_ail(
        xfs_mount_t     *mp,
        xfs_log_item_t  *lip,
-       unsigned long   s)
+       unsigned long   s) __releases(mp->m_ail_lock)
 {
        xfs_ail_entry_t         *ailp;
        xfs_log_item_t          *dlip;
index 13edab8a9e94d20493eb227afa5b77f45be9d5d8..447ac4308c917cd445a5a0acea364a7b567d5405 100644 (file)
@@ -46,11 +46,13 @@ xfs_log_busy_slot_t         *xfs_trans_add_busy(xfs_trans_t *tp,
 /*
  * From xfs_trans_ail.c
  */
-void                   xfs_trans_update_ail(struct xfs_mount *,
-                                    struct xfs_log_item *, xfs_lsn_t,
-                                    unsigned long);
-void                   xfs_trans_delete_ail(struct xfs_mount *,
-                                    struct xfs_log_item *, unsigned long);
+void                   xfs_trans_update_ail(struct xfs_mount *mp,
+                                    struct xfs_log_item *lip, xfs_lsn_t lsn,
+                                    unsigned long s)
+                                    __releases(mp->m_ail_lock);
+void                   xfs_trans_delete_ail(struct xfs_mount *mp,
+                                    struct xfs_log_item *lip, unsigned long s)
+                                    __releases(mp->m_ail_lock);
 struct xfs_log_item    *xfs_trans_first_ail(struct xfs_mount *, int *);
 struct xfs_log_item    *xfs_trans_next_ail(struct xfs_mount *,
                                     struct xfs_log_item *, int *, int *);
index a34796e57afb308c58c7ed816d278ad07b2f13b8..62336a4cc5a4c72339932fdc91dcf8dd2323f38a 100644 (file)
@@ -1922,7 +1922,7 @@ xfs_showargs(
        }
 
        if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
-               seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
+               seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", (int)mp->m_ihsize);
 
        if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
                seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
index 23cfa58377283b073f09503734581ea4df80edf0..061e2ffdd1dee3613bedb671dbdbb9256350aac8 100644 (file)
@@ -2366,10 +2366,15 @@ xfs_remove(
 
        namelen = VNAMELEN(dentry);
 
+       if (!xfs_get_dir_entry(dentry, &ip)) {
+               dm_di_mode = ip->i_d.di_mode;
+               IRELE(ip);
+       }
+
        if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
                error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
                                        DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
-                                       name, NULL, 0, 0, 0);
+                                       name, NULL, dm_di_mode, 0, 0);
                if (error)
                        return error;
        }
@@ -2995,7 +3000,7 @@ xfs_rmdir(
        int                     cancel_flags;
        int                     committed;
        bhv_vnode_t             *dir_vp;
-       int                     dm_di_mode = 0;
+       int                     dm_di_mode = S_IFDIR;
        int                     last_cdp_link;
        int                     namelen;
        uint                    resblks;
@@ -3010,11 +3015,16 @@ xfs_rmdir(
                return XFS_ERROR(EIO);
        namelen = VNAMELEN(dentry);
 
+       if (!xfs_get_dir_entry(dentry, &cdp)) {
+               dm_di_mode = cdp->i_d.di_mode;
+               IRELE(cdp);
+       }
+
        if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
                error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
                                        dir_vp, DM_RIGHT_NULL,
                                        NULL, DM_RIGHT_NULL,
-                                       name, NULL, 0, 0, 0);
+                                       name, NULL, dm_di_mode, 0, 0);
                if (error)
                        return XFS_ERROR(error);
        }
@@ -3834,7 +3844,9 @@ xfs_reclaim(
                XFS_MOUNT_ILOCK(mp);
                vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
                list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
+               spin_lock(&ip->i_flags_lock);
                ip->i_flags |= XFS_IRECLAIMABLE;
+               spin_unlock(&ip->i_flags_lock);
                XFS_MOUNT_IUNLOCK(mp);
        }
        return 0;
@@ -3859,8 +3871,10 @@ xfs_finish_reclaim(
         * us.
         */
        write_lock(&ih->ih_lock);
+       spin_lock(&ip->i_flags_lock);
        if ((ip->i_flags & XFS_IRECLAIM) ||
            (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
+               spin_unlock(&ip->i_flags_lock);
                write_unlock(&ih->ih_lock);
                if (locked) {
                        xfs_ifunlock(ip);
@@ -3869,6 +3883,7 @@ xfs_finish_reclaim(
                return 1;
        }
        ip->i_flags |= XFS_IRECLAIM;
+       spin_unlock(&ip->i_flags_lock);
        write_unlock(&ih->ih_lock);
 
        /*
@@ -4272,7 +4287,7 @@ xfs_free_file_space(
        xfs_mount_t             *mp;
        int                     nimap;
        uint                    resblks;
-       int                     rounding;
+       uint                    rounding;
        int                     rt;
        xfs_fileoff_t           startoffset_fsb;
        xfs_trans_t             *tp;
@@ -4313,8 +4328,7 @@ xfs_free_file_space(
                vn_iowait(vp);  /* wait for the completion of any pending DIOs */
        }
 
-       rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
-                       (__uint8_t)NBPP);
+       rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP);
        ilen = len + (offset & (rounding - 1));
        ioffset = offset & ~(rounding - 1);
        if (ilen & (rounding - 1))
index 0c294c9b0c558a8a45f080b8e0b825fadbdf859f..aeeb125f68513df03fe1d625de0cf1883b46c869 100644 (file)
@@ -166,4 +166,8 @@ static inline void __raw_write_unlock(raw_rwlock_t * lock)
        lock->lock = 0;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* _ALPHA_SPINLOCK_H */
index 58f40931a5c1fecdc58dd6cce9a6c0c548280eb2..a5a86b1ff886d73aac3bbccb0a3a9e849cbba52e 100644 (file)
 /*
  * Peripheral identifiers/interrupts.
  */
-#define AT91_ID_FIQ    0       /* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS    1       /* System Peripheral */
-#define AT91_ID_PIOA   2       /* Parallel IO Controller A */
-#define AT91_ID_PIOB   3       /* Parallel IO Controller B */
-#define AT91_ID_PIOC   4       /* Parallel IO Controller C */
-#define AT91_ID_PIOD   5       /* Parallel IO Controller D */
-#define AT91_ID_US0    6       /* USART 0 */
-#define AT91_ID_US1    7       /* USART 1 */
-#define AT91_ID_US2    8       /* USART 2 */
-#define AT91_ID_US3    9       /* USART 3 */
-#define AT91_ID_MCI    10      /* Multimedia Card Interface */
-#define AT91_ID_UDP    11      /* USB Device Port */
-#define AT91_ID_TWI    12      /* Two-Wire Interface */
-#define AT91_ID_SPI    13      /* Serial Peripheral Interface */
-#define AT91_ID_SSC0   14      /* Serial Synchronous Controller 0 */
-#define AT91_ID_SSC1   15      /* Serial Synchronous Controller 1 */
-#define AT91_ID_SSC2   16      /* Serial Synchronous Controller 2 */
-#define AT91_ID_TC0    17      /* Timer Counter 0 */
-#define AT91_ID_TC1    18      /* Timer Counter 1 */
-#define AT91_ID_TC2    19      /* Timer Counter 2 */
-#define AT91_ID_TC3    20      /* Timer Counter 3 */
-#define AT91_ID_TC4    21      /* Timer Counter 4 */
-#define AT91_ID_TC5    22      /* Timer Counter 5 */
-#define AT91_ID_UHP    23      /* USB Host port */
-#define AT91_ID_EMAC   24      /* Ethernet MAC */
-#define AT91_ID_IRQ0   25      /* Advanced Interrupt Controller (IRQ0) */
-#define AT91_ID_IRQ1   26      /* Advanced Interrupt Controller (IRQ1) */
-#define AT91_ID_IRQ2   27      /* Advanced Interrupt Controller (IRQ2) */
-#define AT91_ID_IRQ3   28      /* Advanced Interrupt Controller (IRQ3) */
-#define AT91_ID_IRQ4   29      /* Advanced Interrupt Controller (IRQ4) */
-#define AT91_ID_IRQ5   30      /* Advanced Interrupt Controller (IRQ5) */
-#define AT91_ID_IRQ6   31      /* Advanced Interrupt Controller (IRQ6) */
+#define AT91_ID_FIQ            0       /* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS            1       /* System Peripheral */
+#define AT91RM9200_ID_PIOA     2       /* Parallel IO Controller A */
+#define AT91RM9200_ID_PIOB     3       /* Parallel IO Controller B */
+#define AT91RM9200_ID_PIOC     4       /* Parallel IO Controller C */
+#define AT91RM9200_ID_PIOD     5       /* Parallel IO Controller D */
+#define AT91RM9200_ID_US0      6       /* USART 0 */
+#define AT91RM9200_ID_US1      7       /* USART 1 */
+#define AT91RM9200_ID_US2      8       /* USART 2 */
+#define AT91RM9200_ID_US3      9       /* USART 3 */
+#define AT91RM9200_ID_MCI      10      /* Multimedia Card Interface */
+#define AT91RM9200_ID_UDP      11      /* USB Device Port */
+#define AT91RM9200_ID_TWI      12      /* Two-Wire Interface */
+#define AT91RM9200_ID_SPI      13      /* Serial Peripheral Interface */
+#define AT91RM9200_ID_SSC0     14      /* Serial Synchronous Controller 0 */
+#define AT91RM9200_ID_SSC1     15      /* Serial Synchronous Controller 1 */
+#define AT91RM9200_ID_SSC2     16      /* Serial Synchronous Controller 2 */
+#define AT91RM9200_ID_TC0      17      /* Timer Counter 0 */
+#define AT91RM9200_ID_TC1      18      /* Timer Counter 1 */
+#define AT91RM9200_ID_TC2      19      /* Timer Counter 2 */
+#define AT91RM9200_ID_TC3      20      /* Timer Counter 3 */
+#define AT91RM9200_ID_TC4      21      /* Timer Counter 4 */
+#define AT91RM9200_ID_TC5      22      /* Timer Counter 5 */
+#define AT91RM9200_ID_UHP      23      /* USB Host port */
+#define AT91RM9200_ID_EMAC     24      /* Ethernet MAC */
+#define AT91RM9200_ID_IRQ0     25      /* Advanced Interrupt Controller (IRQ0) */
+#define AT91RM9200_ID_IRQ1     26      /* Advanced Interrupt Controller (IRQ1) */
+#define AT91RM9200_ID_IRQ2     27      /* Advanced Interrupt Controller (IRQ2) */
+#define AT91RM9200_ID_IRQ3     28      /* Advanced Interrupt Controller (IRQ3) */
+#define AT91RM9200_ID_IRQ4     29      /* Advanced Interrupt Controller (IRQ4) */
+#define AT91RM9200_ID_IRQ5     30      /* Advanced Interrupt Controller (IRQ5) */
+#define AT91RM9200_ID_IRQ6     31      /* Advanced Interrupt Controller (IRQ6) */
 
 
 /*
  * Peripheral physical base addresses.
  */
-#define AT91_BASE_TCB0         0xfffa0000
-#define AT91_BASE_TC0          0xfffa0000
-#define AT91_BASE_TC1          0xfffa0040
-#define AT91_BASE_TC2          0xfffa0080
-#define AT91_BASE_TCB1         0xfffa4000
-#define AT91_BASE_TC3          0xfffa4000
-#define AT91_BASE_TC4          0xfffa4040
-#define AT91_BASE_TC5          0xfffa4080
-#define AT91_BASE_UDP          0xfffb0000
-#define AT91_BASE_MCI          0xfffb4000
-#define AT91_BASE_TWI          0xfffb8000
-#define AT91_BASE_EMAC         0xfffbc000
-#define AT91_BASE_US0          0xfffc0000
-#define AT91_BASE_US1          0xfffc4000
-#define AT91_BASE_US2          0xfffc8000
-#define AT91_BASE_US3          0xfffcc000
-#define AT91_BASE_SSC0         0xfffd0000
-#define AT91_BASE_SSC1         0xfffd4000
-#define AT91_BASE_SSC2         0xfffd8000
-#define AT91_BASE_SPI          0xfffe0000
+#define AT91RM9200_BASE_TCB0   0xfffa0000
+#define AT91RM9200_BASE_TC0    0xfffa0000
+#define AT91RM9200_BASE_TC1    0xfffa0040
+#define AT91RM9200_BASE_TC2    0xfffa0080
+#define AT91RM9200_BASE_TCB1   0xfffa4000
+#define AT91RM9200_BASE_TC3    0xfffa4000
+#define AT91RM9200_BASE_TC4    0xfffa4040
+#define AT91RM9200_BASE_TC5    0xfffa4080
+#define AT91RM9200_BASE_UDP    0xfffb0000
+#define AT91RM9200_BASE_MCI    0xfffb4000
+#define AT91RM9200_BASE_TWI    0xfffb8000
+#define AT91RM9200_BASE_EMAC   0xfffbc000
+#define AT91RM9200_BASE_US0    0xfffc0000
+#define AT91RM9200_BASE_US1    0xfffc4000
+#define AT91RM9200_BASE_US2    0xfffc8000
+#define AT91RM9200_BASE_US3    0xfffcc000
+#define AT91RM9200_BASE_SSC0   0xfffd0000
+#define AT91RM9200_BASE_SSC1   0xfffd4000
+#define AT91RM9200_BASE_SSC2   0xfffd8000
+#define AT91RM9200_BASE_SPI    0xfffe0000
 #define AT91_BASE_SYS          0xfffff000
 
 
+/*
+ * Internal Memory.
+ */
+#define AT91RM9200_ROM_BASE    0x00100000      /* Internal ROM base address */
+#define AT91RM9200_ROM_SIZE    SZ_128K         /* Internal ROM size (128Kb) */
+
+#define AT91RM9200_SRAM_BASE   0x00200000      /* Internal SRAM base address */
+#define AT91RM9200_SRAM_SIZE   SZ_16K          /* Internal SRAM size (16Kb) */
+
+#define AT91RM9200_UHP_BASE    0x00300000      /* USB Host controller */
+
+
+#if 0
 /*
  * PIO pin definitions (peripheral A/B multiplexing).
  */
 #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 0f4c12d5f0cdc98e42102fac332dfb9cc73f4f1b..73693fea76a204144d9251e3dd6c81c925bd3aad 100644 (file)
@@ -80,6 +80,9 @@
 #define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
 #define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
 
+#define AT91_AIC_FFER          (AT91_AIC + 0x140)      /* Fast Forcing Enable Register [SAM9 only] */
+#define AT91_AIC_FFDR          (AT91_AIC + 0x144)      /* Fast Forcing Disable Register [SAM9 only] */
+#define AT91_AIC_FFSR          (AT91_AIC + 0x148)      /* Fast Forcing Status Register [SAM9 only] */
 
 /*
  * PIO Controllers.
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_twi.h
new file mode 100644 (file)
index 0000000..93547d7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_twi.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Two-wire Interface (TWI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * 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 AT91RM9200_TWI_H
+#define AT91RM9200_TWI_H
+
+#define        AT91_TWI_CR             0x00            /* Control Register */
+#define                AT91_TWI_START          (1 <<  0)       /* Send a Start Condition */
+#define                AT91_TWI_STOP           (1 <<  1)       /* Send a Stop Condition */
+#define                AT91_TWI_MSEN           (1 <<  2)       /* Master Transfer Enable */
+#define                AT91_TWI_MSDIS          (1 <<  3)       /* Master Transfer Disable */
+#define                AT91_TWI_SWRST          (1 <<  7)       /* Software Reset */
+
+#define        AT91_TWI_MMR            0x04            /* Master Mode Register */
+#define                AT91_TWI_IADRSZ         (3    <<  8)    /* Internal Device Address Size */
+#define                        AT91_TWI_IADRSZ_NO              (0 << 8)
+#define                        AT91_TWI_IADRSZ_1               (1 << 8)
+#define                        AT91_TWI_IADRSZ_2               (2 << 8)
+#define                        AT91_TWI_IADRSZ_3               (3 << 8)
+#define                AT91_TWI_MREAD          (1    << 12)    /* Master Read Direction */
+#define                AT91_TWI_DADR           (0x7f << 16)    /* Device Address */
+
+#define        AT91_TWI_IADR           0x0c            /* Internal Address Register */
+
+#define        AT91_TWI_CWGR           0x10            /* Clock Waveform Generator Register */
+#define                AT91_TWI_CLDIV          (0xff <<  0)    /* Clock Low Divisor */
+#define                AT91_TWI_CHDIV          (0xff <<  8)    /* Clock High Divisor */
+#define                AT91_TWI_CKDIV          (7    << 16)    /* Clock Divider */
+
+#define        AT91_TWI_SR             0x20            /* Status Register */
+#define                AT91_TWI_TXCOMP         (1 <<  0)       /* Transmission Complete */
+#define                AT91_TWI_RXRDY          (1 <<  1)       /* Receive Holding Register Ready */
+#define                AT91_TWI_TXRDY          (1 <<  2)       /* Transmit Holding Register Ready */
+#define                AT91_TWI_OVRE           (1 <<  6)       /* Overrun Error */
+#define                AT91_TWI_UNRE           (1 <<  7)       /* Underrun Error */
+#define                AT91_TWI_NACK           (1 <<  8)       /* Not Acknowledged */
+
+#define        AT91_TWI_IER            0x24            /* Interrupt Enable Register */
+#define        AT91_TWI_IDR            0x28            /* Interrupt Disable Register */
+#define        AT91_TWI_IMR            0x2c            /* Interrupt Mask Register */
+#define        AT91_TWI_RHR            0x30            /* Receive Holding Register */
+#define        AT91_TWI_THR            0x34            /* Transmit Holding Register */
+
+#endif
+
index dbde1baaf251e0abe27e0e97b42372abbffb0c93..a011d27876a2dd0b2c42df472f199519b46849da 100644 (file)
 
 #define PIN_BASE               NR_AIC_IRQS
 
-#define PQFP_GPIO_BANKS                3       /* PQFP package has 3 banks */
-#define BGA_GPIO_BANKS         4       /* BGA package has 4 banks */
+#define MAX_GPIO_BANKS         4
 
-/* these pin numbers double as IRQ numbers, like AT91_ID_* values */
+/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
 
 #define        AT91_PIN_PA0    (PIN_BASE + 0x00 + 0)
 #define        AT91_PIN_PA1    (PIN_BASE + 0x00 + 1)
 
 #ifndef __ASSEMBLY__
 /* setup setup routines, called from board init or driver probe() */
-extern int at91_set_A_periph(unsigned pin, int use_pullup);
-extern int at91_set_B_periph(unsigned pin, int use_pullup);
-extern int at91_set_gpio_input(unsigned pin, int use_pullup);
-extern int at91_set_gpio_output(unsigned pin, int value);
-extern int at91_set_deglitch(unsigned pin, int is_on);
-extern int at91_set_multi_drive(unsigned pin, int is_on);
+extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
+extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
+extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
+extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
 
 /* callable at any time */
 extern int at91_set_gpio_value(unsigned pin, int value);
 extern int at91_get_gpio_value(unsigned pin);
 
+/* callable only from core power-management code */
 extern void at91_gpio_suspend(void);
 extern void at91_gpio_resume(void);
 #endif
index 235d39d91107914d0101c1e8b4b8e048f3a8d0c4..6551b4d1ff7b21ca6e78e9c53a563fc3e50e114a 100644 (file)
  * Virtual to Physical Address mapping for IO devices.
  */
 #define AT91_VA_BASE_SYS       AT91_IO_P2V(AT91_BASE_SYS)
-#define AT91_VA_BASE_SPI       AT91_IO_P2V(AT91_BASE_SPI)
-#define AT91_VA_BASE_SSC2      AT91_IO_P2V(AT91_BASE_SSC2)
-#define AT91_VA_BASE_SSC1      AT91_IO_P2V(AT91_BASE_SSC1)
-#define AT91_VA_BASE_SSC0      AT91_IO_P2V(AT91_BASE_SSC0)
-#define AT91_VA_BASE_US3       AT91_IO_P2V(AT91_BASE_US3)
-#define AT91_VA_BASE_US2       AT91_IO_P2V(AT91_BASE_US2)
-#define AT91_VA_BASE_US1       AT91_IO_P2V(AT91_BASE_US1)
-#define AT91_VA_BASE_US0       AT91_IO_P2V(AT91_BASE_US0)
-#define AT91_VA_BASE_EMAC      AT91_IO_P2V(AT91_BASE_EMAC)
-#define AT91_VA_BASE_TWI       AT91_IO_P2V(AT91_BASE_TWI)
-#define AT91_VA_BASE_MCI       AT91_IO_P2V(AT91_BASE_MCI)
-#define AT91_VA_BASE_UDP       AT91_IO_P2V(AT91_BASE_UDP)
-#define AT91_VA_BASE_TCB1      AT91_IO_P2V(AT91_BASE_TCB1)
-#define AT91_VA_BASE_TCB0      AT91_IO_P2V(AT91_BASE_TCB0)
-
-/* Internal SRAM */
-#define AT91_SRAM_BASE         0x00200000      /* Internal SRAM base address */
-#define AT91_SRAM_SIZE         0x00004000      /* Internal SRAM SIZE (16Kb) */
+#define AT91_VA_BASE_SPI       AT91_IO_P2V(AT91RM9200_BASE_SPI)
+#define AT91_VA_BASE_EMAC      AT91_IO_P2V(AT91RM9200_BASE_EMAC)
+#define AT91_VA_BASE_TWI       AT91_IO_P2V(AT91RM9200_BASE_TWI)
+#define AT91_VA_BASE_MCI       AT91_IO_P2V(AT91RM9200_BASE_MCI)
+#define AT91_VA_BASE_UDP       AT91_IO_P2V(AT91RM9200_BASE_UDP)
 
  /* Internal SRAM is mapped below the IO devices */
-#define AT91_SRAM_VIRT_BASE    (AT91_IO_VIRT_BASE - AT91_SRAM_SIZE)
+#define AT91_SRAM_VIRT_BASE    (AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE)
 
 /* Serial ports */
 #define AT91_NR_UART           5               /* 4 USART3's and one DBGU port */
@@ -71,9 +58,6 @@
 /* Compact Flash */
 #define AT91_CF_BASE           0x50000000      /* NCS4-NCS6: Compact Flash physical base address */
 
-/* Multi-Master Memory controller */
-#define AT91_UHP_BASE          0x00300000      /* USB Host controller */
-
 /* Clocks */
 #define AT91_SLOW_CLOCK                32768           /* slow clock */
 
index f63842c2c0938f10d170922b7eae79ee084fdffe..763cb96c418bac0f6bebc32dbb40c55f2cc1f8e9 100644 (file)
@@ -32,7 +32,7 @@
 
 
 /*
- * IRQ interrupt symbols are the AT91_ID_* symbols in at91rm9200.h
+ * IRQ interrupt symbols are the AT91xxx_ID_* symbols
  * for IRQs handled directly through the AIC, or else the AT91_PIN_*
  * symbols in gpio.h for ones handled indirectly as GPIOs.
  * We make provision for 4 banks of GPIO.
index 9cb27cd4e6ae9cb3237060ecd8c51f07c7a8822d..0e4a3901d3b36b0afa8ea1acbff9165e1bf515db 100644 (file)
@@ -29,7 +29,7 @@ static irqreturn_t
 p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        do_leds();
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
diff --git a/include/asm-arm/arch-iop32x/debug-macro.S b/include/asm-arm/arch-iop32x/debug-macro.S
new file mode 100644 (file)
index 0000000..9022b68
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-iop32x/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+               .macro  addruart, rx
+               mov     \rx, #0xfe000000        @ physical as well as virtual
+               orr     \rx, \rx, #0x00800000   @ location of the UART
+               .endm
+
+#define UART_SHIFT     0
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop32x/dma.h b/include/asm-arm/arch-iop32x/dma.h
new file mode 100644 (file)
index 0000000..e977a9e
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-iop32x/dma.h
+ *
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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.
+ */
diff --git a/include/asm-arm/arch-iop32x/entry-macro.S b/include/asm-arm/arch-iop32x/entry-macro.S
new file mode 100644 (file)
index 0000000..1500cbb
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-iop32x/entry-macro.S
+ *
+ * Low-level IRQ helper macros for IOP32x-based platforms
+ *
+ * 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 <asm/arch/iop32x.h>
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+               ldr     \base, =IOP3XX_REG_ADDR(0x07D8)
+               ldr     \irqstat, [\base]               @ Read IINTSRC
+               cmp     \irqstat, #0
+               clzne   \irqnr, \irqstat
+               rsbne   \irqnr, \irqnr, #31
+               .endm
diff --git a/include/asm-arm/arch-iop32x/glantank.h b/include/asm-arm/arch-iop32x/glantank.h
new file mode 100644 (file)
index 0000000..3b06561
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * include/asm/arch-iop32x/glantank.h
+ *
+ * IO-Data GLAN Tank board registers
+ */
+
+#ifndef __GLANTANK_H
+#define __GLANTANK_H
+
+#define GLANTANK_UART          0xfe800000      /* UART */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/hardware.h b/include/asm-arm/arch-iop32x/hardware.h
new file mode 100644 (file)
index 0000000..6556ed5
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * include/asm-arm/arch-iop32x/hardware.h
+ */
+
+#ifndef __HARDWARE_H
+#define __HARDWARE_H
+
+#include <asm/types.h>
+
+/*
+ * Note about PCI IO space mappings
+ *
+ * To make IO space accesses efficient, we store virtual addresses in
+ * the IO resources.
+ *
+ * The PCI IO space is located at virtual 0xfe000000 from physical
+ * 0x90000000. The PCI BARs must be programmed with physical addresses,
+ * but when we read them, we convert them to virtual addresses. See
+ * arch/arm/plat-iop/pci.c.
+ */
+#define pcibios_assign_all_busses() 1
+#define PCIBIOS_MIN_IO         0x00000000
+#define PCIBIOS_MIN_MEM                0x00000000
+
+#ifndef __ASSEMBLY__
+void iop32x_init_irq(void);
+#endif
+
+
+/*
+ * Generic chipset bits
+ */
+#include "iop32x.h"
+
+/*
+ * Board specific bits
+ */
+#include "glantank.h"
+#include "iq80321.h"
+#include "iq31244.h"
+#include "n2100.h"
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/io.h b/include/asm-arm/arch-iop32x/io.h
new file mode 100644 (file)
index 0000000..12d9ee0
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-iop32x/io.h
+ *
+ * Copyright (C) 2001 MontaVista Software, 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.
+ */
+
+#ifndef __IO_H
+#define __IO_H
+
+#include <asm/hardware.h>
+
+#define IO_SPACE_LIMIT         0xffffffff
+
+#define __io(p)                        ((void __iomem *)(p))
+#define __mem_pci(a)           (a)
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/iop32x.h b/include/asm-arm/arch-iop32x/iop32x.h
new file mode 100644 (file)
index 0000000..4bbd85f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * include/asm-arm/arch-iop32x/iop32x.h
+ *
+ * Intel IOP32X Chip definitions
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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 __IOP32X_H
+#define __IOP32X_H
+
+/*
+ * Peripherals that are shared between the iop32x and iop33x but
+ * located at different addresses.
+ */
+#define IOP3XX_GPIO_REG(reg)   (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07c0 + (reg))
+#define IOP3XX_TIMER_REG(reg)  (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
+
+#include <asm/hardware/iop3xx.h>
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/iq31244.h b/include/asm-arm/arch-iop32x/iq31244.h
new file mode 100644 (file)
index 0000000..fff4eaf
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * include/asm-arm/arch-iop32x/iq31244.h
+ *
+ * Intel IQ31244 evaluation board registers
+ */
+
+#ifndef __IQ31244_H
+#define __IQ31244_H
+
+#define IQ31244_UART           0xfe800000      /* UART #1 */
+#define IQ31244_7SEG_1         0xfe840000      /* 7-Segment MSB */
+#define IQ31244_7SEG_0         0xfe850000      /* 7-Segment LSB (WO) */
+#define IQ31244_ROTARY_SW      0xfe8d0000      /* Rotary Switch */
+#define IQ31244_BATT_STAT      0xfe8f0000      /* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/iq80321.h b/include/asm-arm/arch-iop32x/iq80321.h
new file mode 100644 (file)
index 0000000..eb69db9
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * include/asm-arm/arch-iop32x/iq80321.h
+ *
+ * Intel IQ80321 evaluation board registers
+ */
+
+#ifndef __IQ80321_H
+#define __IQ80321_H
+
+#define IQ80321_UART           0xfe800000      /* UART #1 */
+#define IQ80321_7SEG_1         0xfe840000      /* 7-Segment MSB */
+#define IQ80321_7SEG_0         0xfe850000      /* 7-Segment LSB (WO) */
+#define IQ80321_ROTARY_SW      0xfe8d0000      /* Rotary Switch */
+#define IQ80321_BATT_STAT      0xfe8f0000      /* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/irqs.h b/include/asm-arm/arch-iop32x/irqs.h
new file mode 100644 (file)
index 0000000..bbaef87
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * include/asm-arm/arch-iop32x/irqs.h
+ *
+ * Author:     Rory Bolt <rorybolt@pacbell.net>
+ * Copyright:  (C) 2002 Rory Bolt
+ *
+ * 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 __IRQS_H
+#define __IRQS_H
+
+/*
+ * IOP80321 chipset interrupts
+ */
+#define IRQ_IOP32X_DMA0_EOT    0
+#define IRQ_IOP32X_DMA0_EOC    1
+#define IRQ_IOP32X_DMA1_EOT    2
+#define IRQ_IOP32X_DMA1_EOC    3
+#define IRQ_IOP32X_AA_EOT      6
+#define IRQ_IOP32X_AA_EOC      7
+#define IRQ_IOP32X_CORE_PMON   8
+#define IRQ_IOP32X_TIMER0      9
+#define IRQ_IOP32X_TIMER1      10
+#define IRQ_IOP32X_I2C_0       11
+#define IRQ_IOP32X_I2C_1       12
+#define IRQ_IOP32X_MESSAGING   13
+#define IRQ_IOP32X_ATU_BIST    14
+#define IRQ_IOP32X_PERFMON     15
+#define IRQ_IOP32X_CORE_PMU    16
+#define IRQ_IOP32X_BIU_ERR     17
+#define IRQ_IOP32X_ATU_ERR     18
+#define IRQ_IOP32X_MCU_ERR     19
+#define IRQ_IOP32X_DMA0_ERR    20
+#define IRQ_IOP32X_DMA1_ERR    21
+#define IRQ_IOP32X_AA_ERR      23
+#define IRQ_IOP32X_MSG_ERR     24
+#define IRQ_IOP32X_SSP         25
+#define IRQ_IOP32X_XINT0       27
+#define IRQ_IOP32X_XINT1       28
+#define IRQ_IOP32X_XINT2       29
+#define IRQ_IOP32X_XINT3       30
+#define IRQ_IOP32X_HPI         31
+
+#define NR_IRQS                        32
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/memory.h b/include/asm-arm/arch-iop32x/memory.h
new file mode 100644 (file)
index 0000000..764cd3f
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-iop32x/memory.h
+ */
+
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+#include <asm/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET    UL(0xa0000000)
+
+/*
+ * Virtual view <-> PCI DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *             address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *             to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
+#define __bus_to_virt(x)       (__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/n2100.h b/include/asm-arm/arch-iop32x/n2100.h
new file mode 100644 (file)
index 0000000..fed31a6
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * include/asm/arch-iop32x/n2100.h
+ *
+ * Thecus N2100 board registers
+ */
+
+#ifndef __N2100_H
+#define __N2100_H
+
+#define N2100_UART             0xfe800000      /* UART */
+
+#define N2100_COPY_BUTTON      IOP3XX_GPIO_LINE(0)
+#define N2100_PCA9532_RESET    IOP3XX_GPIO_LINE(2)
+#define N2100_RESET_BUTTON     IOP3XX_GPIO_LINE(3)
+#define N2100_HARDWARE_RESET   IOP3XX_GPIO_LINE(4)
+#define N2100_POWER_BUTTON     IOP3XX_GPIO_LINE(5)
+
+
+#endif
diff --git a/include/asm-arm/arch-iop32x/system.h b/include/asm-arm/arch-iop32x/system.h
new file mode 100644 (file)
index 0000000..17b7eb7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-iop32x/system.h
+ *
+ * Copyright (C) 2001 MontaVista Software, 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 <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       local_irq_disable();
+
+       if (machine_is_n2100()) {
+               gpio_line_set(N2100_HARDWARE_RESET, GPIO_LOW);
+               gpio_line_config(N2100_HARDWARE_RESET, GPIO_OUT);
+               while (1)
+                       ;
+       }
+
+       *IOP3XX_PCSR = 0x30;
+
+       /* Jump into ROM at address 0 */
+       cpu_reset(0);
+}
diff --git a/include/asm-arm/arch-iop32x/timex.h b/include/asm-arm/arch-iop32x/timex.h
new file mode 100644 (file)
index 0000000..9934b08
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-iop32x/timex.h
+ *
+ * IOP32x architecture timex specifications
+ */
+
+#include <asm/hardware.h>
+
+#define CLOCK_TICK_RATE                (100 * HZ)
diff --git a/include/asm-arm/arch-iop32x/uncompress.h b/include/asm-arm/arch-iop32x/uncompress.h
new file mode 100644 (file)
index 0000000..e64f52b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-iop32x/uncompress.h
+ */
+
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <linux/serial_reg.h>
+#include <asm/hardware.h>
+
+static volatile u8 *uart_base;
+
+#define TX_DONE                (UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void putc(char c)
+{
+       while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+               barrier();
+       uart_base[UART_TX] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+       if (machine_is_iq80321())
+               uart_base = (volatile u8 *)IQ80321_UART;
+       else if (machine_is_iq31244())
+               uart_base = (volatile u8 *)IQ31244_UART;
+       else
+               uart_base = (volatile u8 *)0xfe800000;
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()    __arch_decomp_setup(arch_id)
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop32x/vmalloc.h b/include/asm-arm/arch-iop32x/vmalloc.h
new file mode 100644 (file)
index 0000000..0a70baa
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * include/asm-arm/arch-iop32x/vmalloc.h
+ */
+
+#define VMALLOC_END    0xfe000000
diff --git a/include/asm-arm/arch-iop33x/debug-macro.S b/include/asm-arm/arch-iop33x/debug-macro.S
new file mode 100644 (file)
index 0000000..9e7132e
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * include/asm-arm/arch-iop33x/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ */
+
+               .macro  addruart, rx
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1                 @ mmu enabled?
+               moveq   \rx, #0xff000000        @ physical
+               movne   \rx, #0xfe000000        @ virtual
+               orr     \rx, \rx, #0x00ff0000
+               orr     \rx, \rx, #0x0000f700
+               .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop33x/dma.h b/include/asm-arm/arch-iop33x/dma.h
new file mode 100644 (file)
index 0000000..b7775fd
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-iop33x/dma.h
+ *
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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.
+ */
diff --git a/include/asm-arm/arch-iop33x/entry-macro.S b/include/asm-arm/arch-iop33x/entry-macro.S
new file mode 100644 (file)
index 0000000..92b7917
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-iop33x/entry-macro.S
+ *
+ * Low-level IRQ helper macros for IOP33x-based platforms
+ *
+ * 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 <asm/arch/iop33x.h>
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+               ldr     \base, =IOP3XX_REG_ADDR(0x07C8)
+               ldr     \irqstat, [\base]               @ Read IINTVEC
+               cmp     \irqstat, #0
+               ldreq   \irqstat, [\base]               @ erratum 63 workaround
+               adds    \irqnr, \irqstat, #1
+               movne   \irqnr, \irqstat, lsr #2
+               .endm
diff --git a/include/asm-arm/arch-iop33x/hardware.h b/include/asm-arm/arch-iop33x/hardware.h
new file mode 100644 (file)
index 0000000..0659cf9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * include/asm-arm/arch-iop33x/hardware.h
+ */
+
+#ifndef __HARDWARE_H
+#define __HARDWARE_H
+
+#include <asm/types.h>
+
+/*
+ * Note about PCI IO space mappings
+ *
+ * To make IO space accesses efficient, we store virtual addresses in
+ * the IO resources.
+ *
+ * The PCI IO space is located at virtual 0xfe000000 from physical
+ * 0x90000000.  The PCI BARs must be programmed with physical addresses,
+ * but when we read them, we convert them to virtual addresses.  See
+ * arch/arm/mach-iop3xx/iop3xx-pci.c
+ */
+#define pcibios_assign_all_busses()    1
+#define PCIBIOS_MIN_IO         0x00000000
+#define PCIBIOS_MIN_MEM                0x00000000
+
+#ifndef __ASSEMBLY__
+void iop33x_init_irq(void);
+
+extern struct platform_device iop33x_uart0_device;
+extern struct platform_device iop33x_uart1_device;
+#endif
+
+
+/*
+ * Generic chipset bits
+ *
+ */
+#include "iop33x.h"
+
+/*
+ * Board specific bits
+ */
+#include "iq80331.h"
+#include "iq80332.h"
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/io.h b/include/asm-arm/arch-iop33x/io.h
new file mode 100644 (file)
index 0000000..c017402
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-iop33x/io.h
+ *
+ * Copyright (C) 2001  MontaVista Software, 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.
+ */
+
+#ifndef __IO_H
+#define __IO_H
+
+#include <asm/hardware.h>
+
+#define IO_SPACE_LIMIT         0xffffffff
+#define __io(p)                        ((void __iomem *)(p))
+#define __mem_pci(a)           (a)
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/iop33x.h b/include/asm-arm/arch-iop33x/iop33x.h
new file mode 100644 (file)
index 0000000..7ac6e93
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-iop33x/iop33x.h
+ *
+ * Intel IOP33X Chip definitions
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2003, 2004 Intel Corp.
+ *
+ * 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 __IOP33X_H
+#define __IOP33X_H
+
+/*
+ * Peripherals that are shared between the iop32x and iop33x but
+ * located at different addresses.
+ */
+#define IOP3XX_GPIO_REG(reg)   (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1780 + (reg))
+#define IOP3XX_TIMER_REG(reg)  (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07d0 + (reg))
+
+#include <asm/hardware/iop3xx.h>
+
+/* UARTs  */
+#define IOP33X_UART0_PHYS      (IOP3XX_PERIPHERAL_PHYS_BASE + 0x1700)
+#define IOP33X_UART0_VIRT      (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1700)
+#define IOP33X_UART1_PHYS      (IOP3XX_PERIPHERAL_PHYS_BASE + 0x1740)
+#define IOP33X_UART1_VIRT      (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1740)
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/iq80331.h b/include/asm-arm/arch-iop33x/iq80331.h
new file mode 100644 (file)
index 0000000..79b9302
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-iop33x/iq80331.h
+ *
+ * Intel IQ80331 evaluation board registers
+ */
+
+#ifndef __IQ80331_H
+#define __IQ80331_H
+
+#define IQ80331_7SEG_1         0xce840000      /* 7-Segment MSB */
+#define IQ80331_7SEG_0         0xce850000      /* 7-Segment LSB (WO) */
+#define IQ80331_ROTARY_SW      0xce8d0000      /* Rotary Switch */
+#define IQ80331_BATT_STAT      0xce8f0000      /* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/iq80332.h b/include/asm-arm/arch-iop33x/iq80332.h
new file mode 100644 (file)
index 0000000..0531656
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-iop33x/iq80332.h
+ *
+ * Intel IQ80332 evaluation board registers
+ */
+
+#ifndef __IQ80332_H
+#define __IQ80332_H
+
+#define IQ80332_7SEG_1         0xce840000      /* 7-Segment MSB */
+#define IQ80332_7SEG_0         0xce850000      /* 7-Segment LSB (WO) */
+#define IQ80332_ROTARY_SW      0xce8d0000      /* Rotary Switch */
+#define IQ80332_BATT_STAT      0xce8f0000      /* Battery Status */
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/irqs.h b/include/asm-arm/arch-iop33x/irqs.h
new file mode 100644 (file)
index 0000000..d045f84
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * include/asm-arm/arch-iop33x/irqs.h
+ *
+ * Author:     Dave Jiang (dave.jiang@intel.com)
+ * Copyright:  (C) 2003 Intel Corp.
+ *
+ * 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 __IRQS_H
+#define __IRQS_H
+
+/*
+ * IOP80331 chipset interrupts
+ */
+#define IRQ_IOP33X_DMA0_EOT    0
+#define IRQ_IOP33X_DMA0_EOC    1
+#define IRQ_IOP33X_DMA1_EOT    2
+#define IRQ_IOP33X_DMA1_EOC    3
+#define IRQ_IOP33X_AA_EOT      6
+#define IRQ_IOP33X_AA_EOC      7
+#define IRQ_IOP33X_TIMER0      8
+#define IRQ_IOP33X_TIMER1      9
+#define IRQ_IOP33X_I2C_0       10
+#define IRQ_IOP33X_I2C_1       11
+#define IRQ_IOP33X_MSG         12
+#define IRQ_IOP33X_MSGIBQ      13
+#define IRQ_IOP33X_ATU_BIST    14
+#define IRQ_IOP33X_PERFMON     15
+#define IRQ_IOP33X_CORE_PMU    16
+#define IRQ_IOP33X_XINT0       24
+#define IRQ_IOP33X_XINT1       25
+#define IRQ_IOP33X_XINT2       26
+#define IRQ_IOP33X_XINT3       27
+#define IRQ_IOP33X_XINT8       32
+#define IRQ_IOP33X_XINT9       33
+#define IRQ_IOP33X_XINT10      34
+#define IRQ_IOP33X_XINT11      35
+#define IRQ_IOP33X_XINT12      36
+#define IRQ_IOP33X_XINT13      37
+#define IRQ_IOP33X_XINT14      38
+#define IRQ_IOP33X_XINT15      39
+#define IRQ_IOP33X_UART0       51
+#define IRQ_IOP33X_UART1       52
+#define IRQ_IOP33X_PBIE                53
+#define IRQ_IOP33X_ATU_CRW     54
+#define IRQ_IOP33X_ATU_ERR     55
+#define IRQ_IOP33X_MCU_ERR     56
+#define IRQ_IOP33X_DMA0_ERR    57
+#define IRQ_IOP33X_DMA1_ERR    58
+#define IRQ_IOP33X_AA_ERR      60
+#define IRQ_IOP33X_MSG_ERR     62
+#define IRQ_IOP33X_HPI         63
+
+#define NR_IRQS                        64
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/memory.h b/include/asm-arm/arch-iop33x/memory.h
new file mode 100644 (file)
index 0000000..0d39139
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-iop33x/memory.h
+ */
+
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+#include <asm/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET    UL(0x00000000)
+
+/*
+ * Virtual view <-> PCI DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *             address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *             to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP3XX_IATVR2)) | ((*IOP3XX_IABAR2) & 0xfffffff0))
+#define __bus_to_virt(x)       (__phys_to_virt(((x) & ~(*IOP3XX_IALR2)) | ( *IOP3XX_IATVR2)))
+
+
+#endif
diff --git a/include/asm-arm/arch-iop33x/system.h b/include/asm-arm/arch-iop33x/system.h
new file mode 100644 (file)
index 0000000..00dd07e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-iop33x/system.h
+ *
+ * Copyright (C) 2001 MontaVista Software, 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.
+ */
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       *IOP3XX_PCSR = 0x30;
+
+       /* Jump into ROM at address 0 */
+       cpu_reset(0);
+}
diff --git a/include/asm-arm/arch-iop33x/timex.h b/include/asm-arm/arch-iop33x/timex.h
new file mode 100644 (file)
index 0000000..fe3e1e3
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-iop33x/timex.h
+ *
+ * IOP3xx architecture timex specifications
+ */
+
+#include <asm/hardware.h>
+
+#define CLOCK_TICK_RATE                (100 * HZ)
diff --git a/include/asm-arm/arch-iop33x/uncompress.h b/include/asm-arm/arch-iop33x/uncompress.h
new file mode 100644 (file)
index 0000000..e17fbc0
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-iop33x/uncompress.h
+ */
+
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <linux/serial_reg.h>
+#include <asm/hardware.h>
+
+static volatile u32 *uart_base;
+
+#define TX_DONE                (UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void putc(char c)
+{
+       while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+               barrier();
+       uart_base[UART_TX] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+       if (machine_is_iq80331() || machine_is_iq80332())
+               uart_base = (volatile u32 *)IOP33X_UART0_PHYS;
+       else
+               uart_base = (volatile u32 *)0xfe800000;
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()    __arch_decomp_setup(arch_id)
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop33x/vmalloc.h b/include/asm-arm/arch-iop33x/vmalloc.h
new file mode 100644 (file)
index 0000000..66f545a
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * include/asm-arm/arch-iop33x/vmalloc.h
+ */
+
+#define VMALLOC_END    0xfe000000
diff --git a/include/asm-arm/arch-iop3xx/debug-macro.S b/include/asm-arm/arch-iop3xx/debug-macro.S
deleted file mode 100644 (file)
index ce007e5..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/include/asm-arm/arch-iop3xx/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * 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.
- *
-*/
-
-               .macro  addruart,rx
-               mov     \rx, #0xfe000000        @ physical
-#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
-               orr     \rx, \rx, #0x00800000   @ location of the UART
-#elif defined(CONFIG_ARCH_IOP331)
-               mrc     p15, 0, \rx, c1, c0
-               tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x000fe000        @ Physical Base
-               movne   \rx, #0
-               orr     \rx, \rx, #0xfe000000
-               orr     \rx, \rx, #0x00f00000   @ Virtual Base
-               orr     \rx, \rx, #0x00001700   @ location of the UART
-#else
-#error Unknown IOP3XX implementation
-#endif
-               .endm
-
-#if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331)
-#define FLOW_CONTROL
-#endif
-#define UART_SHIFT     0
-#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-iop3xx/dma.h b/include/asm-arm/arch-iop3xx/dma.h
deleted file mode 100644 (file)
index 1e808db..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/dma.h
- *
- *  Copyright (C) 2004 Intel Corp.
- *
- * 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.
- */
diff --git a/include/asm-arm/arch-iop3xx/entry-macro.S b/include/asm-arm/arch-iop3xx/entry-macro.S
deleted file mode 100644 (file)
index 926668c..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * include/asm-arm/arch-iop3xx/entry-macro.S
- *
- * Low-level IRQ helper macros for IOP3xx-based platforms
- *
- * 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 <asm/arch/irqs.h>
-
-#if defined(CONFIG_ARCH_IOP321)
-               .macro  disable_fiq
-               .endm
-
-               /*
-                * Note: only deal with normal interrupts, not FIQ
-                */
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               mov     \irqnr, #0
-               mrc     p6, 0, \irqstat, c8, c0, 0      @ Read IINTSRC
-               cmp     \irqstat, #0
-               beq     1001f
-               clz     \irqnr, \irqstat
-               mov     \base, #31
-               subs    \irqnr,\base,\irqnr
-               add     \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT
-1001:
-               .endm
-
-#elif defined(CONFIG_ARCH_IOP331)
-               .macro  disable_fiq
-               .endm
-
-               /*
-                * Note: only deal with normal interrupts, not FIQ
-                */
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               mov     \irqnr, #0
-               mrc     p6, 0, \irqstat, c4, c0, 0      @ Read IINTSRC0
-               cmp     \irqstat, #0
-               bne     1002f
-               mrc     p6, 0, \irqstat, c5, c0, 0      @ Read IINTSRC1
-               cmp     \irqstat, #0
-               beq     1001f
-               clz     \irqnr, \irqstat
-               rsbs    \irqnr,\irqnr,#31   @ recommend by RMK
-               add     \irqnr,\irqnr,#IRQ_IOP331_XINT8
-               b       1001f
-1002:  clz     \irqnr, \irqstat
-               rsbs    \irqnr,\irqnr,#31   @ recommend by RMK
-               add     \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT
-1001:
-               .endm
-
-#endif
-
diff --git a/include/asm-arm/arch-iop3xx/hardware.h b/include/asm-arm/arch-iop3xx/hardware.h
deleted file mode 100644 (file)
index 3b13817..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/hardware.h
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/types.h>
-
-/*
- * Note about PCI IO space mappings
- *
- * To make IO space accesses efficient, we store virtual addresses in
- * the IO resources.
- *
- * The PCI IO space is located at virtual 0xfe000000 from physical
- * 0x90000000.  The PCI BARs must be programmed with physical addresses,
- * but when we read them, we convert them to virtual addresses.  See
- * arch/arm/mach-iop3xx/iop3xx-pci.c
- */
-
-#define pcibios_assign_all_busses() 1
-
-
-/*
- * The min PCI I/O and MEM space are dependent on what specific
- * chipset/platform we are running on, so instead of hardcoding with
- * #ifdefs, we just fill these in the platform level PCI init code.
- */
-#ifndef __ASSEMBLY__
-extern unsigned long iop3xx_pcibios_min_io;
-extern unsigned long iop3xx_pcibios_min_mem;
-
-extern unsigned int processor_id;
-#endif
-
-/*
- * We just set these to zero since they are really bogus anyways
- */
-#define PCIBIOS_MIN_IO      (iop3xx_pcibios_min_io)
-#define PCIBIOS_MIN_MEM     (iop3xx_pcibios_min_mem)
-
-/*
- * Generic chipset bits
- *
- */
-#include "iop321.h"
-#include "iop331.h"
-
-/*
- * Board specific bits
- */
-#include "iq80321.h"
-#include "iq31244.h"
-#include "iq80331.h"
-#include "iq80332.h"
-
-#endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-iop3xx/io.h b/include/asm-arm/arch-iop3xx/io.h
deleted file mode 100644 (file)
index 36adbdf..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/io.h
- *
- *  Copyright (C) 2001  MontaVista Software, 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.
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#include <asm/hardware.h>
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(p)                        ((void __iomem *)(p))
-#define __mem_pci(a)           (a)
-
-#endif
diff --git a/include/asm-arm/arch-iop3xx/iop321-irqs.h b/include/asm-arm/arch-iop3xx/iop321-irqs.h
deleted file mode 100644 (file)
index 2fcc165..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/irqs.h
- *
- * Author:     Rory Bolt <rorybolt@pacbell.net>
- * Copyright:  (C) 2002 Rory Bolt
- *
- * 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 _IOP321_IRQS_H_
-#define _IOP321_IRQS_H_
-
-/*
- * IOP80321 chipset interrupts
- */
-#define IOP321_IRQ_OFS         0
-#define IOP321_IRQ(x)          (IOP321_IRQ_OFS + (x))
-
-/*
- * On IRQ or FIQ register
- */
-#define IRQ_IOP321_DMA0_EOT    IOP321_IRQ(0)
-#define IRQ_IOP321_DMA0_EOC    IOP321_IRQ(1)
-#define IRQ_IOP321_DMA1_EOT    IOP321_IRQ(2)
-#define IRQ_IOP321_DMA1_EOC    IOP321_IRQ(3)
-#define IRQ_IOP321_RSVD_4      IOP321_IRQ(4)
-#define IRQ_IOP321_RSVD_5      IOP321_IRQ(5)
-#define IRQ_IOP321_AA_EOT      IOP321_IRQ(6)
-#define IRQ_IOP321_AA_EOC      IOP321_IRQ(7)
-#define IRQ_IOP321_CORE_PMON   IOP321_IRQ(8)
-#define IRQ_IOP321_TIMER0      IOP321_IRQ(9)
-#define IRQ_IOP321_TIMER1      IOP321_IRQ(10)
-#define IRQ_IOP321_I2C_0       IOP321_IRQ(11)
-#define IRQ_IOP321_I2C_1       IOP321_IRQ(12)
-#define IRQ_IOP321_MESSAGING   IOP321_IRQ(13)
-#define IRQ_IOP321_ATU_BIST    IOP321_IRQ(14)
-#define IRQ_IOP321_PERFMON     IOP321_IRQ(15)
-#define IRQ_IOP321_CORE_PMU    IOP321_IRQ(16)
-#define IRQ_IOP321_BIU_ERR     IOP321_IRQ(17)
-#define IRQ_IOP321_ATU_ERR     IOP321_IRQ(18)
-#define IRQ_IOP321_MCU_ERR     IOP321_IRQ(19)
-#define IRQ_IOP321_DMA0_ERR    IOP321_IRQ(20)
-#define IRQ_IOP321_DMA1_ERR    IOP321_IRQ(21)
-#define IRQ_IOP321_RSVD_22     IOP321_IRQ(22)
-#define IRQ_IOP321_AA_ERR      IOP321_IRQ(23)
-#define IRQ_IOP321_MSG_ERR     IOP321_IRQ(24)
-#define IRQ_IOP321_SSP         IOP321_IRQ(25)
-#define IRQ_IOP321_RSVD_26     IOP321_IRQ(26)
-#define IRQ_IOP321_XINT0       IOP321_IRQ(27)
-#define IRQ_IOP321_XINT1       IOP321_IRQ(28)
-#define IRQ_IOP321_XINT2       IOP321_IRQ(29)
-#define IRQ_IOP321_XINT3       IOP321_IRQ(30)
-#define IRQ_IOP321_HPI         IOP321_IRQ(31)
-
-#define NR_IOP321_IRQS         (IOP321_IRQ(31) + 1)
-
-#define NR_IRQS                        NR_IOP321_IRQS
-
-
-/*
- * Interrupts available on the IQ80321 board
- */
-
-/*
- * On board devices
- */
-#define        IRQ_IQ80321_I82544      IRQ_IOP321_XINT0
-#define IRQ_IQ80321_UART       IRQ_IOP321_XINT1
-
-/*
- * PCI interrupts
- */
-#define        IRQ_IQ80321_INTA        IRQ_IOP321_XINT0
-#define        IRQ_IQ80321_INTB        IRQ_IOP321_XINT1
-#define        IRQ_IQ80321_INTC        IRQ_IOP321_XINT2
-#define        IRQ_IQ80321_INTD        IRQ_IOP321_XINT3
-
-/*
- * Interrupts on the IQ31244 board
- */
-
-/*
- * On board devices
- */
-#define IRQ_IQ31244_UART       IRQ_IOP321_XINT1
-#define        IRQ_IQ31244_I82546      IRQ_IOP321_XINT0
-#define IRQ_IQ31244_SATA       IRQ_IOP321_XINT2
-#define        IRQ_IQ31244_PCIX_SLOT   IRQ_IOP321_XINT3
-
-/*
- * PCI interrupts
- */
-#define        IRQ_IQ31244_INTA        IRQ_IOP321_XINT0
-#define        IRQ_IQ31244_INTB        IRQ_IOP321_XINT1
-#define        IRQ_IQ31244_INTC        IRQ_IOP321_XINT2
-#define        IRQ_IQ31244_INTD        IRQ_IOP321_XINT3
-
-#endif // _IOP321_IRQ_H_
diff --git a/include/asm-arm/arch-iop3xx/iop321.h b/include/asm-arm/arch-iop3xx/iop321.h
deleted file mode 100644 (file)
index f8df778..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iop321.h
- *
- * Intel IOP321 Chip definitions
- *
- * Author: Rory Bolt <rorybolt@pacbell.net>
- * Copyright (C) 2002 Rory Bolt
- * Copyright (C) 2004 Intel Corp.
- *
- * 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 _IOP321_HW_H_
-#define _IOP321_HW_H_
-
-
-/*
- * This is needed for mixed drivers that need to work on all
- * IOP3xx variants but behave slightly differently on each.
- */
-#ifndef __ASSEMBLY__
-#ifdef CONFIG_ARCH_IOP321
-#define iop_is_321() (((processor_id & 0xfffff5e0) == 0x69052420))
-#else
-#define        iop_is_321()    0
-#endif
-#endif
-
-/*
- * IOP321 I/O and Mem space regions for PCI autoconfiguration
- */
-#define IOP321_PCI_IO_WINDOW_SIZE   0x00010000
-#define IOP321_PCI_LOWER_IO_PA      0x90000000
-#define IOP321_PCI_LOWER_IO_VA      0xfe000000
-#define IOP321_PCI_LOWER_IO_BA      (*IOP321_OIOWTVR)
-#define IOP321_PCI_UPPER_IO_PA      (IOP321_PCI_LOWER_IO_PA + IOP321_PCI_IO_WINDOW_SIZE - 1)
-#define IOP321_PCI_UPPER_IO_VA      (IOP321_PCI_LOWER_IO_VA + IOP321_PCI_IO_WINDOW_SIZE - 1)
-#define IOP321_PCI_UPPER_IO_BA      (IOP321_PCI_LOWER_IO_BA + IOP321_PCI_IO_WINDOW_SIZE - 1)
-#define IOP321_PCI_IO_OFFSET        (IOP321_PCI_LOWER_IO_VA - IOP321_PCI_LOWER_IO_BA)
-
-/* #define IOP321_PCI_MEM_WINDOW_SIZE  (~*IOP321_IALR1 + 1) */
-#define IOP321_PCI_MEM_WINDOW_SIZE  0x04000000 /* 64M outbound window */
-#define IOP321_PCI_LOWER_MEM_PA     0x80000000
-#define IOP321_PCI_LOWER_MEM_BA     (*IOP321_OMWTVR0)
-#define IOP321_PCI_UPPER_MEM_PA     (IOP321_PCI_LOWER_MEM_PA + IOP321_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP321_PCI_UPPER_MEM_BA     (IOP321_PCI_LOWER_MEM_BA + IOP321_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP321_PCI_MEM_OFFSET       (IOP321_PCI_LOWER_MEM_PA - IOP321_PCI_LOWER_MEM_BA)
-
-
-/*
- * IOP321 chipset registers
- */
-#define IOP321_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
-#define IOP321_PHYS_MEM_BASE 0xffffe000  /* chip physical memory address */
-#define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
-
-/* Reserved 0x00000000 through 0x000000FF */
-
-/* Address Translation Unit 0x00000100 through 0x000001FF */
-#define IOP321_ATUVID     (volatile u16 *)IOP321_REG_ADDR(0x00000100)
-#define IOP321_ATUDID     (volatile u16 *)IOP321_REG_ADDR(0x00000102)
-#define IOP321_ATUCMD     (volatile u16 *)IOP321_REG_ADDR(0x00000104)
-#define IOP321_ATUSR      (volatile u16 *)IOP321_REG_ADDR(0x00000106)
-#define IOP321_ATURID     (volatile u8  *)IOP321_REG_ADDR(0x00000108)
-#define IOP321_ATUCCR     (volatile u32 *)IOP321_REG_ADDR(0x00000109)
-#define IOP321_ATUCLSR    (volatile u8  *)IOP321_REG_ADDR(0x0000010C)
-#define IOP321_ATULT      (volatile u8  *)IOP321_REG_ADDR(0x0000010D)
-#define IOP321_ATUHTR     (volatile u8  *)IOP321_REG_ADDR(0x0000010E)
-#define IOP321_ATUBIST    (volatile u8  *)IOP321_REG_ADDR(0x0000010F)
-#define IOP321_IABAR0     (volatile u32 *)IOP321_REG_ADDR(0x00000110)
-#define IOP321_IAUBAR0    (volatile u32 *)IOP321_REG_ADDR(0x00000114)
-#define IOP321_IABAR1     (volatile u32 *)IOP321_REG_ADDR(0x00000118)
-#define IOP321_IAUBAR1    (volatile u32 *)IOP321_REG_ADDR(0x0000011C)
-#define IOP321_IABAR2     (volatile u32 *)IOP321_REG_ADDR(0x00000120)
-#define IOP321_IAUBAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000124)
-#define IOP321_ASVIR      (volatile u16 *)IOP321_REG_ADDR(0x0000012C)
-#define IOP321_ASIR       (volatile u16 *)IOP321_REG_ADDR(0x0000012E)
-#define IOP321_ERBAR      (volatile u32 *)IOP321_REG_ADDR(0x00000130)
-/* Reserved 0x00000134 through 0x0000013B */
-#define IOP321_ATUILR     (volatile u8  *)IOP321_REG_ADDR(0x0000013C)
-#define IOP321_ATUIPR     (volatile u8  *)IOP321_REG_ADDR(0x0000013D)
-#define IOP321_ATUMGNT    (volatile u8  *)IOP321_REG_ADDR(0x0000013E)
-#define IOP321_ATUMLAT    (volatile u8  *)IOP321_REG_ADDR(0x0000013F)
-#define IOP321_IALR0      (volatile u32 *)IOP321_REG_ADDR(0x00000140)
-#define IOP321_IATVR0     (volatile u32 *)IOP321_REG_ADDR(0x00000144)
-#define IOP321_ERLR       (volatile u32 *)IOP321_REG_ADDR(0x00000148)
-#define IOP321_ERTVR      (volatile u32 *)IOP321_REG_ADDR(0x0000014C)
-#define IOP321_IALR1      (volatile u32 *)IOP321_REG_ADDR(0x00000150)
-#define IOP321_IALR2      (volatile u32 *)IOP321_REG_ADDR(0x00000154)
-#define IOP321_IATVR2     (volatile u32 *)IOP321_REG_ADDR(0x00000158)
-#define IOP321_OIOWTVR    (volatile u32 *)IOP321_REG_ADDR(0x0000015C)
-#define IOP321_OMWTVR0    (volatile u32 *)IOP321_REG_ADDR(0x00000160)
-#define IOP321_OUMWTVR0   (volatile u32 *)IOP321_REG_ADDR(0x00000164)
-#define IOP321_OMWTVR1    (volatile u32 *)IOP321_REG_ADDR(0x00000168)
-#define IOP321_OUMWTVR1   (volatile u32 *)IOP321_REG_ADDR(0x0000016C)
-/* Reserved 0x00000170 through 0x00000177*/
-#define IOP321_OUDWTVR    (volatile u32 *)IOP321_REG_ADDR(0x00000178)
-/* Reserved 0x0000017C through 0x0000017F*/
-#define IOP321_ATUCR      (volatile u32 *)IOP321_REG_ADDR(0x00000180)
-#define IOP321_PCSR       (volatile u32 *)IOP321_REG_ADDR(0x00000184)
-#define IOP321_ATUISR     (volatile u32 *)IOP321_REG_ADDR(0x00000188)
-#define IOP321_ATUIMR     (volatile u32 *)IOP321_REG_ADDR(0x0000018C)
-#define IOP321_IABAR3     (volatile u32 *)IOP321_REG_ADDR(0x00000190)
-#define IOP321_IAUBAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000194)
-#define IOP321_IALR3      (volatile u32 *)IOP321_REG_ADDR(0x00000198)
-#define IOP321_IATVR3     (volatile u32 *)IOP321_REG_ADDR(0x0000019C)
-/* Reserved 0x000001A0 through 0x000001A3*/
-#define IOP321_OCCAR      (volatile u32 *)IOP321_REG_ADDR(0x000001A4)
-/* Reserved 0x000001A8 through 0x000001AB*/
-#define IOP321_OCCDR      (volatile u32 *)IOP321_REG_ADDR(0x000001AC)
-/* Reserved 0x000001B0 through 0x000001BB*/
-#define IOP321_PDSCR      (volatile u32 *)IOP321_REG_ADDR(0x000001BC)
-#define IOP321_PMCAPID    (volatile u8  *)IOP321_REG_ADDR(0x000001C0)
-#define IOP321_PMNEXT     (volatile u8  *)IOP321_REG_ADDR(0x000001C1)
-#define IOP321_APMCR      (volatile u16 *)IOP321_REG_ADDR(0x000001C2)
-#define IOP321_APMCSR     (volatile u16 *)IOP321_REG_ADDR(0x000001C4)
-/* Reserved 0x000001C6 through 0x000001DF */
-#define IOP321_PCIXCAPID  (volatile u8  *)IOP321_REG_ADDR(0x000001E0)
-#define IOP321_PCIXNEXT   (volatile u8  *)IOP321_REG_ADDR(0x000001E1)
-#define IOP321_PCIXCMD    (volatile u16 *)IOP321_REG_ADDR(0x000001E2)
-#define IOP321_PCIXSR     (volatile u32 *)IOP321_REG_ADDR(0x000001E4)
-#define IOP321_PCIIRSR    (volatile u32 *)IOP321_REG_ADDR(0x000001EC)
-
-/* Messaging Unit 0x00000300 through 0x000003FF */
-
-/* Reserved 0x00000300 through 0x0000030c */
-#define IOP321_IMR0       (volatile u32 *)IOP321_REG_ADDR(0x00000310)
-#define IOP321_IMR1       (volatile u32 *)IOP321_REG_ADDR(0x00000314)
-#define IOP321_OMR0       (volatile u32 *)IOP321_REG_ADDR(0x00000318)
-#define IOP321_OMR1       (volatile u32 *)IOP321_REG_ADDR(0x0000031C)
-#define IOP321_IDR        (volatile u32 *)IOP321_REG_ADDR(0x00000320)
-#define IOP321_IISR       (volatile u32 *)IOP321_REG_ADDR(0x00000324)
-#define IOP321_IIMR       (volatile u32 *)IOP321_REG_ADDR(0x00000328)
-#define IOP321_ODR        (volatile u32 *)IOP321_REG_ADDR(0x0000032C)
-#define IOP321_OISR       (volatile u32 *)IOP321_REG_ADDR(0x00000330)
-#define IOP321_OIMR       (volatile u32 *)IOP321_REG_ADDR(0x00000334)
-/* Reserved 0x00000338 through 0x0000034F */
-#define IOP321_MUCR       (volatile u32 *)IOP321_REG_ADDR(0x00000350)
-#define IOP321_QBAR       (volatile u32 *)IOP321_REG_ADDR(0x00000354)
-/* Reserved 0x00000358 through 0x0000035C */
-#define IOP321_IFHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000360)
-#define IOP321_IFTPR      (volatile u32 *)IOP321_REG_ADDR(0x00000364)
-#define IOP321_IPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000368)
-#define IOP321_IPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000036C)
-#define IOP321_OFHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000370)
-#define IOP321_OFTPR      (volatile u32 *)IOP321_REG_ADDR(0x00000374)
-#define IOP321_OPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000378)
-#define IOP321_OPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
-#define IOP321_IAR        (volatile u32 *)IOP321_REG_ADDR(0x00000380)
-
-#define IOP321_IIxR_MASK       0x7f /* masks all */
-#define IOP321_IIxR_IRI                0x40 /* RC Index Register Interrupt */
-#define IOP321_IIxR_OFQF       0x20 /* RC Output Free Q Full (ERROR) */
-#define IOP321_IIxR_ipq                0x10 /* RC Inbound Post Q (post) */
-#define IOP321_IIxR_ERRDI      0x08 /* RO Error Doorbell Interrupt */
-#define IOP321_IIxR_IDI                0x04 /* RO Inbound Doorbell Interrupt */
-#define IOP321_IIxR_IM1                0x02 /* RC Inbound Message 1 Interrupt */
-#define IOP321_IIxR_IM0                0x01 /* RC Inbound Message 0 Interrupt */
-
-/* Reserved 0x00000384 through 0x000003FF */
-
-/* DMA Controller 0x00000400 through 0x000004FF */
-#define IOP321_DMA0_CCR   (volatile u32 *)IOP321_REG_ADDR(0x00000400)
-#define IOP321_DMA0_CSR   (volatile u32 *)IOP321_REG_ADDR(0x00000404)
-#define IOP321_DMA0_DAR   (volatile u32 *)IOP321_REG_ADDR(0x0000040C)
-#define IOP321_DMA0_NDAR  (volatile u32 *)IOP321_REG_ADDR(0x00000410)
-#define IOP321_DMA0_PADR  (volatile u32 *)IOP321_REG_ADDR(0x00000414)
-#define IOP321_DMA0_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000418)
-#define IOP321_DMA0_LADR  (volatile u32 *)IOP321_REG_ADDR(0X0000041C)
-#define IOP321_DMA0_BCR   (volatile u32 *)IOP321_REG_ADDR(0x00000420)
-#define IOP321_DMA0_DCR   (volatile u32 *)IOP321_REG_ADDR(0x00000424)
-/* Reserved 0x00000428 through 0x0000043C */
-#define IOP321_DMA1_CCR   (volatile u32 *)IOP321_REG_ADDR(0x00000440)
-#define IOP321_DMA1_CSR   (volatile u32 *)IOP321_REG_ADDR(0x00000444)
-#define IOP321_DMA1_DAR   (volatile u32 *)IOP321_REG_ADDR(0x0000044C)
-#define IOP321_DMA1_NDAR  (volatile u32 *)IOP321_REG_ADDR(0x00000450)
-#define IOP321_DMA1_PADR  (volatile u32 *)IOP321_REG_ADDR(0x00000454)
-#define IOP321_DMA1_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000458)
-#define IOP321_DMA1_LADR  (volatile u32 *)IOP321_REG_ADDR(0x0000045C)
-#define IOP321_DMA1_BCR   (volatile u32 *)IOP321_REG_ADDR(0x00000460)
-#define IOP321_DMA1_DCR   (volatile u32 *)IOP321_REG_ADDR(0x00000464)
-/* Reserved 0x00000468 through 0x000004FF */
-
-/* Memory controller 0x00000500 through 0x0005FF */
-
-/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
-#define IOP321_PBCR       (volatile u32 *)IOP321_REG_ADDR(0x00000680)
-#define IOP321_PBISR      (volatile u32 *)IOP321_REG_ADDR(0x00000684)
-#define IOP321_PBBAR0     (volatile u32 *)IOP321_REG_ADDR(0x00000688)
-#define IOP321_PBLR0      (volatile u32 *)IOP321_REG_ADDR(0x0000068C)
-#define IOP321_PBBAR1     (volatile u32 *)IOP321_REG_ADDR(0x00000690)
-#define IOP321_PBLR1      (volatile u32 *)IOP321_REG_ADDR(0x00000694)
-#define IOP321_PBBAR2     (volatile u32 *)IOP321_REG_ADDR(0x00000698)
-#define IOP321_PBLR2      (volatile u32 *)IOP321_REG_ADDR(0x0000069C)
-#define IOP321_PBBAR3     (volatile u32 *)IOP321_REG_ADDR(0x000006A0)
-#define IOP321_PBLR3      (volatile u32 *)IOP321_REG_ADDR(0x000006A4)
-#define IOP321_PBBAR4     (volatile u32 *)IOP321_REG_ADDR(0x000006A8)
-#define IOP321_PBLR4      (volatile u32 *)IOP321_REG_ADDR(0x000006AC)
-#define IOP321_PBBAR5     (volatile u32 *)IOP321_REG_ADDR(0x000006B0)
-#define IOP321_PBLR5      (volatile u32 *)IOP321_REG_ADDR(0x000006B4)
-#define IOP321_PBDSCR     (volatile u32 *)IOP321_REG_ADDR(0x000006B8)
-/* Reserved 0x000006BC */
-#define IOP321_PMBR0      (volatile u32 *)IOP321_REG_ADDR(0x000006C0)
-/* Reserved 0x000006C4 through 0x000006DC */
-#define IOP321_PMBR1      (volatile u32 *)IOP321_REG_ADDR(0x000006E0)
-#define IOP321_PMBR2      (volatile u32 *)IOP321_REG_ADDR(0x000006E4)
-
-#define IOP321_PBCR_EN    0x1
-
-#define IOP321_PBISR_BOOR_ERR 0x1
-
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
-#define IOP321_GTMR    (volatile u32 *)IOP321_REG_ADDR(0x00000700)
-#define IOP321_ESR     (volatile u32 *)IOP321_REG_ADDR(0x00000704)
-#define IOP321_EMISR   (volatile u32 *)IOP321_REG_ADDR(0x00000708)
-/* reserved 0x00000070c */
-#define IOP321_GTSR    (volatile u32 *)IOP321_REG_ADDR(0x00000710)
-/* PERC0 DOESN'T EXIST - index from 1! */
-#define IOP321_PERCR0  (volatile u32 *)IOP321_REG_ADDR(0x00000710)
-
-#define IOP321_GTMR_NGCE       0x04 /* (Not) Global Counter Enable */
-
-/* Internal arbitration unit 0x00000780 through 0x0007BF */
-#define IOP321_IACR    (volatile u32 *)IOP321_REG_ADDR(0x00000780)
-#define IOP321_MTTR1   (volatile u32 *)IOP321_REG_ADDR(0x00000784)
-#define IOP321_MTTR2   (volatile u32 *)IOP321_REG_ADDR(0x00000788)
-
-/* General Purpose I/O Registers */
-#define IOP321_GPOE       (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
-#define IOP321_GPID       (volatile u32 *)IOP321_REG_ADDR(0x000007C8)
-#define IOP321_GPOD       (volatile u32 *)IOP321_REG_ADDR(0x000007CC)
-
-/* Interrupt Controller */
-#define IOP321_INTCTL     (volatile u32 *)IOP321_REG_ADDR(0x000007D0)
-#define IOP321_INTSTR     (volatile u32 *)IOP321_REG_ADDR(0x000007D4)
-#define IOP321_IINTSRC    (volatile u32 *)IOP321_REG_ADDR(0x000007D8)
-#define IOP321_FINTSRC    (volatile u32 *)IOP321_REG_ADDR(0x000007DC)
-
-/* Timers */
-
-#define IOP321_TU_TMR0         (volatile u32 *)IOP321_REG_ADDR(0x000007E0)
-#define IOP321_TU_TMR1         (volatile u32 *)IOP321_REG_ADDR(0x000007E4)
-
-#ifdef CONFIG_ARCH_IQ80321
-#define        IOP321_TICK_RATE        200000000       /* 200 MHz clock */
-#elif defined(CONFIG_ARCH_IQ31244)
-#define IOP321_TICK_RATE       198000000       /* 33.000 MHz crystal */
-#endif
-
-#ifdef CONFIG_ARCH_EP80219
-#undef IOP321_TICK_RATE
-#define IOP321_TICK_RATE 200000000 /* 33.333333 Mhz crystal */
-#endif
-
-#define IOP321_TMR_TC          0x01
-#define        IOP321_TMR_EN           0x02
-#define IOP321_TMR_RELOAD      0x04
-#define        IOP321_TMR_PRIVILEGED   0x09
-
-#define        IOP321_TMR_RATIO_1_1    0x00
-#define        IOP321_TMR_RATIO_4_1    0x10
-#define        IOP321_TMR_RATIO_8_1    0x20
-#define        IOP321_TMR_RATIO_16_1   0x30
-
-#define IOP321_TU_TCR0    (volatile u32 *)IOP321_REG_ADDR(0x000007E8)
-#define IOP321_TU_TCR1    (volatile u32 *)IOP321_REG_ADDR(0x000007EC)
-#define IOP321_TU_TRR0    (volatile u32 *)IOP321_REG_ADDR(0x000007F0)
-#define IOP321_TU_TRR1    (volatile u32 *)IOP321_REG_ADDR(0x000007F4)
-#define IOP321_TU_TISR    (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
-#define IOP321_TU_WDTCR   (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
-
-/* Application accelerator unit 0x00000800 - 0x000008FF */
-#define IOP321_AAU_ACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
-#define IOP321_AAU_ASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
-#define IOP321_AAU_ADAR    (volatile u32 *)IOP321_REG_ADDR(0x00000808)
-#define IOP321_AAU_ANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
-#define IOP321_AAU_SAR1    (volatile u32 *)IOP321_REG_ADDR(0x00000810)
-#define IOP321_AAU_SAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000814)
-#define IOP321_AAU_SAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000818)
-#define IOP321_AAU_SAR4    (volatile u32 *)IOP321_REG_ADDR(0x0000081C)
-#define IOP321_AAU_SAR5    (volatile u32 *)IOP321_REG_ADDR(0x0000082C)
-#define IOP321_AAU_SAR6    (volatile u32 *)IOP321_REG_ADDR(0x00000830)
-#define IOP321_AAU_SAR7    (volatile u32 *)IOP321_REG_ADDR(0x00000834)
-#define IOP321_AAU_SAR8    (volatile u32 *)IOP321_REG_ADDR(0x00000838)
-#define IOP321_AAU_SAR9    (volatile u32 *)IOP321_REG_ADDR(0x00000840)
-#define IOP321_AAU_SAR10   (volatile u32 *)IOP321_REG_ADDR(0x00000844)
-#define IOP321_AAU_SAR11   (volatile u32 *)IOP321_REG_ADDR(0x00000848)
-#define IOP321_AAU_SAR12   (volatile u32 *)IOP321_REG_ADDR(0x0000084C)
-#define IOP321_AAU_SAR13   (volatile u32 *)IOP321_REG_ADDR(0x00000850)
-#define IOP321_AAU_SAR14   (volatile u32 *)IOP321_REG_ADDR(0x00000854)
-#define IOP321_AAU_SAR15   (volatile u32 *)IOP321_REG_ADDR(0x00000858)
-#define IOP321_AAU_SAR16   (volatile u32 *)IOP321_REG_ADDR(0x0000085C)
-#define IOP321_AAU_SAR17   (volatile u32 *)IOP321_REG_ADDR(0x00000864)
-#define IOP321_AAU_SAR18   (volatile u32 *)IOP321_REG_ADDR(0x00000868)
-#define IOP321_AAU_SAR19   (volatile u32 *)IOP321_REG_ADDR(0x0000086C)
-#define IOP321_AAU_SAR20   (volatile u32 *)IOP321_REG_ADDR(0x00000870)
-#define IOP321_AAU_SAR21   (volatile u32 *)IOP321_REG_ADDR(0x00000874)
-#define IOP321_AAU_SAR22   (volatile u32 *)IOP321_REG_ADDR(0x00000878)
-#define IOP321_AAU_SAR23   (volatile u32 *)IOP321_REG_ADDR(0x0000087C)
-#define IOP321_AAU_SAR24   (volatile u32 *)IOP321_REG_ADDR(0x00000880)
-#define IOP321_AAU_SAR25   (volatile u32 *)IOP321_REG_ADDR(0x00000888)
-#define IOP321_AAU_SAR26   (volatile u32 *)IOP321_REG_ADDR(0x0000088C)
-#define IOP321_AAU_SAR27   (volatile u32 *)IOP321_REG_ADDR(0x00000890)
-#define IOP321_AAU_SAR28   (volatile u32 *)IOP321_REG_ADDR(0x00000894)
-#define IOP321_AAU_SAR29   (volatile u32 *)IOP321_REG_ADDR(0x00000898)
-#define IOP321_AAU_SAR30   (volatile u32 *)IOP321_REG_ADDR(0x0000089C)
-#define IOP321_AAU_SAR31   (volatile u32 *)IOP321_REG_ADDR(0x000008A0)
-#define IOP321_AAU_SAR32   (volatile u32 *)IOP321_REG_ADDR(0x000008A4)
-#define IOP321_AAU_DAR     (volatile u32 *)IOP321_REG_ADDR(0x00000820)
-#define IOP321_AAU_ABCR    (volatile u32 *)IOP321_REG_ADDR(0x00000824)
-#define IOP321_AAU_ADCR    (volatile u32 *)IOP321_REG_ADDR(0x00000828)
-#define IOP321_AAU_EDCR0   (volatile u32 *)IOP321_REG_ADDR(0x0000083c)
-#define IOP321_AAU_EDCR1   (volatile u32 *)IOP321_REG_ADDR(0x00000860)
-#define IOP321_AAU_EDCR2   (volatile u32 *)IOP321_REG_ADDR(0x00000884)
-
-
-/* SSP serial port unit 0x00001600 - 0x0000167F */
-/* I2C bus interface unit 0x00001680 - 0x000016FF */
-#define IOP321_ICR0       (volatile u32 *)IOP321_REG_ADDR(0x00001680)
-#define IOP321_ISR0       (volatile u32 *)IOP321_REG_ADDR(0x00001684)
-#define IOP321_ISAR0      (volatile u32 *)IOP321_REG_ADDR(0x00001688)
-#define IOP321_IDBR0      (volatile u32 *)IOP321_REG_ADDR(0x0000168C)
-/* Reserved 0x00001690 */
-#define IOP321_IBMR0      (volatile u32 *)IOP321_REG_ADDR(0x00001694)
-/* Reserved 0x00001698 */
-/* Reserved 0x0000169C */
-#define IOP321_ICR1       (volatile u32 *)IOP321_REG_ADDR(0x000016A0)
-#define IOP321_ISR1       (volatile u32 *)IOP321_REG_ADDR(0x000016A4)
-#define IOP321_ISAR1      (volatile u32 *)IOP321_REG_ADDR(0x000016A8)
-#define IOP321_IDBR1      (volatile u32 *)IOP321_REG_ADDR(0x000016AC)
-#define IOP321_IBMR1      (volatile u32 *)IOP321_REG_ADDR(0x000016B4)
-/* Reserved 0x000016B8 through 0x000016FC */
-
-/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
-
-
-#ifndef __ASSEMBLY__
-extern void iop321_map_io(void);
-extern void iop321_init_irq(void);
-extern void iop321_time_init(void);
-#endif
-
-#endif // _IOP321_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iop331-irqs.h b/include/asm-arm/arch-iop3xx/iop331-irqs.h
deleted file mode 100644 (file)
index 7135ad7..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/irqs.h
- *
- * Author:     Dave Jiang (dave.jiang@intel.com)
- * Copyright:  (C) 2003 Intel Corp.
- *
- * 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 _IOP331_IRQS_H_
-#define _IOP331_IRQS_H_
-
-/*
- * IOP80331 chipset interrupts
- */
-#define IOP331_IRQ_OFS         0
-#define IOP331_IRQ(x)          (IOP331_IRQ_OFS + (x))
-
-/*
- * On IRQ or FIQ register
- */
-#define IRQ_IOP331_DMA0_EOT    IOP331_IRQ(0)
-#define IRQ_IOP331_DMA0_EOC    IOP331_IRQ(1)
-#define IRQ_IOP331_DMA1_EOT    IOP331_IRQ(2)
-#define IRQ_IOP331_DMA1_EOC    IOP331_IRQ(3)
-#define IRQ_IOP331_RSVD_4      IOP331_IRQ(4)
-#define IRQ_IOP331_RSVD_5      IOP331_IRQ(5)
-#define IRQ_IOP331_AA_EOT      IOP331_IRQ(6)
-#define IRQ_IOP331_AA_EOC      IOP331_IRQ(7)
-#define IRQ_IOP331_TIMER0      IOP331_IRQ(8)
-#define IRQ_IOP331_TIMER1      IOP331_IRQ(9)
-#define IRQ_IOP331_I2C_0       IOP331_IRQ(10)
-#define IRQ_IOP331_I2C_1       IOP331_IRQ(11)
-#define IRQ_IOP331_MSG     IOP331_IRQ(12)
-#define IRQ_IOP331_MSGIBQ   IOP331_IRQ(13)
-#define IRQ_IOP331_ATU_BIST    IOP331_IRQ(14)
-#define IRQ_IOP331_PERFMON     IOP331_IRQ(15)
-#define IRQ_IOP331_CORE_PMU    IOP331_IRQ(16)
-#define IRQ_IOP331_RSVD_17     IOP331_IRQ(17)
-#define IRQ_IOP331_RSVD_18     IOP331_IRQ(18)
-#define IRQ_IOP331_RSVD_19     IOP331_IRQ(19)
-#define IRQ_IOP331_RSVD_20     IOP331_IRQ(20)
-#define IRQ_IOP331_RSVD_21     IOP331_IRQ(21)
-#define IRQ_IOP331_RSVD_22     IOP331_IRQ(22)
-#define IRQ_IOP331_RSVD_23     IOP331_IRQ(23)
-#define IRQ_IOP331_XINT0       IOP331_IRQ(24)
-#define IRQ_IOP331_XINT1       IOP331_IRQ(25)
-#define IRQ_IOP331_XINT2       IOP331_IRQ(26)
-#define IRQ_IOP331_XINT3       IOP331_IRQ(27)
-#define IRQ_IOP331_RSVD_28  IOP331_IRQ(28)
-#define IRQ_IOP331_RSVD_29  IOP331_IRQ(29)
-#define IRQ_IOP331_RSVD_30  IOP331_IRQ(30)
-#define IRQ_IOP331_RSVD_31  IOP331_IRQ(31)
-#define IRQ_IOP331_XINT8    IOP331_IRQ(32)  // 0
-#define IRQ_IOP331_XINT9    IOP331_IRQ(33)  // 1
-#define IRQ_IOP331_XINT10   IOP331_IRQ(34)  // 2
-#define IRQ_IOP331_XINT11   IOP331_IRQ(35)  // 3
-#define IRQ_IOP331_XINT12   IOP331_IRQ(36)  // 4
-#define IRQ_IOP331_XINT13   IOP331_IRQ(37)  // 5
-#define IRQ_IOP331_XINT14   IOP331_IRQ(38)  // 6
-#define IRQ_IOP331_XINT15   IOP331_IRQ(39)  // 7
-#define IRQ_IOP331_RSVD_40  IOP331_IRQ(40)  // 8
-#define IRQ_IOP331_RSVD_41  IOP331_IRQ(41)  // 9
-#define IRQ_IOP331_RSVD_42  IOP331_IRQ(42)  // 10
-#define IRQ_IOP331_RSVD_43  IOP331_IRQ(43)  // 11
-#define IRQ_IOP331_RSVD_44  IOP331_IRQ(44)  // 12
-#define IRQ_IOP331_RSVD_45  IOP331_IRQ(45)  // 13
-#define IRQ_IOP331_RSVD_46  IOP331_IRQ(46)  // 14
-#define IRQ_IOP331_RSVD_47  IOP331_IRQ(47)  // 15
-#define IRQ_IOP331_RSVD_48  IOP331_IRQ(48)  // 16
-#define IRQ_IOP331_RSVD_49  IOP331_IRQ(49)  // 17
-#define IRQ_IOP331_RSVD_50  IOP331_IRQ(50)  // 18
-#define IRQ_IOP331_UART0    IOP331_IRQ(51)  // 19
-#define IRQ_IOP331_UART1    IOP331_IRQ(52)  // 20
-#define IRQ_IOP331_PBIE     IOP331_IRQ(53)  // 21
-#define IRQ_IOP331_ATU_CRW  IOP331_IRQ(54)  // 22
-#define IRQ_IOP331_ATU_ERR     IOP331_IRQ(55)  // 23
-#define IRQ_IOP331_MCU_ERR     IOP331_IRQ(56)  // 24
-#define IRQ_IOP331_DMA0_ERR    IOP331_IRQ(57)  // 25
-#define IRQ_IOP331_DMA1_ERR    IOP331_IRQ(58)  // 26
-#define IRQ_IOP331_RSVD_59  IOP331_IRQ(59)  // 27
-#define IRQ_IOP331_AA_ERR      IOP331_IRQ(60)  // 28
-#define IRQ_IOP331_RSVD_61  IOP331_IRQ(61)  // 29
-#define IRQ_IOP331_MSG_ERR     IOP331_IRQ(62)  // 30
-#define IRQ_IOP331_HPI         IOP331_IRQ(63)  // 31
-
-#define NR_IOP331_IRQS         (IOP331_IRQ(63) + 1)
-
-#define NR_IRQS                        NR_IOP331_IRQS
-
-
-/*
- * Interrupts available on the IQ80331 board
- */
-
-/*
- * On board devices
- */
-#define        IRQ_IQ80331_I82544      IRQ_IOP331_XINT0
-#define IRQ_IQ80331_UART0      IRQ_IOP331_UART0
-#define IRQ_IQ80331_UART1      IRQ_IOP331_UART1
-
-/*
- * PCI interrupts
- */
-#define        IRQ_IQ80331_INTA        IRQ_IOP331_XINT0
-#define        IRQ_IQ80331_INTB        IRQ_IOP331_XINT1
-#define        IRQ_IQ80331_INTC        IRQ_IOP331_XINT2
-#define        IRQ_IQ80331_INTD        IRQ_IOP331_XINT3
-
-/*
- * Interrupts available on the IQ80332 board
- */
-
-/*
- * On board devices
- */
-#define        IRQ_IQ80332_I82544      IRQ_IOP331_XINT0
-#define IRQ_IQ80332_UART0      IRQ_IOP331_UART0
-#define IRQ_IQ80332_UART1      IRQ_IOP331_UART1
-
-/*
- * PCI interrupts
- */
-#define        IRQ_IQ80332_INTA        IRQ_IOP331_XINT0
-#define        IRQ_IQ80332_INTB        IRQ_IOP331_XINT1
-#define        IRQ_IQ80332_INTC        IRQ_IOP331_XINT2
-#define        IRQ_IQ80332_INTD        IRQ_IOP331_XINT3
-
-#endif // _IOP331_IRQ_H_
diff --git a/include/asm-arm/arch-iop3xx/iop331.h b/include/asm-arm/arch-iop3xx/iop331.h
deleted file mode 100644 (file)
index fbf0cc1..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iop331.h
- *
- * Intel IOP331 Chip definitions
- *
- * Author: Dave Jiang (dave.jiang@intel.com)
- * Copyright (C) 2003, 2004 Intel Corp.
- *
- * 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 _IOP331_HW_H_
-#define _IOP331_HW_H_
-
-
-/*
- * This is needed for mixed drivers that need to work on all
- * IOP3xx variants but behave slightly differently on each.
- */
-#ifndef __ASSEMBLY__
-#ifdef CONFIG_ARCH_IOP331
-/*#define      iop_is_331()    ((processor_id & 0xffffffb0) == 0x69054090) */
-#define        iop_is_331()    ((processor_id & 0xffffff30) == 0x69054010)
-#else
-#define        iop_is_331()    0
-#endif
-#endif
-
-/*
- * IOP331 I/O and Mem space regions for PCI autoconfiguration
- */
-#define IOP331_PCI_IO_WINDOW_SIZE   0x00010000
-#define IOP331_PCI_LOWER_IO_PA      0x90000000
-#define IOP331_PCI_LOWER_IO_VA      0xfe000000
-#define IOP331_PCI_LOWER_IO_BA      (*IOP331_OIOWTVR)
-#define IOP331_PCI_UPPER_IO_PA      (IOP331_PCI_LOWER_IO_PA + IOP331_PCI_IO_WINDOW_SIZE - 1)
-#define IOP331_PCI_UPPER_IO_VA      (IOP331_PCI_LOWER_IO_VA + IOP331_PCI_IO_WINDOW_SIZE - 1)
-#define IOP331_PCI_UPPER_IO_BA      (IOP331_PCI_LOWER_IO_BA + IOP331_PCI_IO_WINDOW_SIZE - 1)
-#define IOP331_PCI_IO_OFFSET        (IOP331_PCI_LOWER_IO_VA - IOP331_PCI_LOWER_IO_BA)
-
-/* this can be 128M if OMWTVR1 is set */
-#define IOP331_PCI_MEM_WINDOW_SIZE     0x04000000 /* 64M outbound window */
-/* #define IOP331_PCI_MEM_WINDOW_SIZE  (~*IOP331_IALR1 + 1) */
-#define IOP331_PCI_LOWER_MEM_PA     0x80000000
-#define IOP331_PCI_LOWER_MEM_BA     (*IOP331_OMWTVR0)
-#define IOP331_PCI_UPPER_MEM_PA     (IOP331_PCI_LOWER_MEM_PA + IOP331_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP331_PCI_UPPER_MEM_BA     (IOP331_PCI_LOWER_MEM_BA + IOP331_PCI_MEM_WINDOW_SIZE - 1)
-#define IOP331_PCI_MEM_OFFSET       (IOP331_PCI_LOWER_MEM_PA - IOP331_PCI_LOWER_MEM_BA)
-
-/*
- * IOP331 chipset registers
- */
-#define IOP331_VIRT_MEM_BASE  0xfeffe000  /* chip virtual mem address*/
-#define IOP331_PHYS_MEM_BASE  0xffffe000  /* chip physical memory address */
-#define IOP331_REG_ADDR(reg) (IOP331_VIRT_MEM_BASE | (reg))
-
-/* Reserved 0x00000000 through 0x000000FF */
-
-/* Address Translation Unit 0x00000100 through 0x000001FF */
-#define IOP331_ATUVID     (volatile u16 *)IOP331_REG_ADDR(0x00000100)
-#define IOP331_ATUDID     (volatile u16 *)IOP331_REG_ADDR(0x00000102)
-#define IOP331_ATUCMD     (volatile u16 *)IOP331_REG_ADDR(0x00000104)
-#define IOP331_ATUSR      (volatile u16 *)IOP331_REG_ADDR(0x00000106)
-#define IOP331_ATURID     (volatile u8  *)IOP331_REG_ADDR(0x00000108)
-#define IOP331_ATUCCR     (volatile u32 *)IOP331_REG_ADDR(0x00000109)
-#define IOP331_ATUCLSR    (volatile u8  *)IOP331_REG_ADDR(0x0000010C)
-#define IOP331_ATULT      (volatile u8  *)IOP331_REG_ADDR(0x0000010D)
-#define IOP331_ATUHTR     (volatile u8  *)IOP331_REG_ADDR(0x0000010E)
-#define IOP331_ATUBIST    (volatile u8  *)IOP331_REG_ADDR(0x0000010F)
-#define IOP331_IABAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000110)
-#define IOP331_IAUBAR0    (volatile u32 *)IOP331_REG_ADDR(0x00000114)
-#define IOP331_IABAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000118)
-#define IOP331_IAUBAR1    (volatile u32 *)IOP331_REG_ADDR(0x0000011C)
-#define IOP331_IABAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000120)
-#define IOP331_IAUBAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000124)
-#define IOP331_ASVIR      (volatile u16 *)IOP331_REG_ADDR(0x0000012C)
-#define IOP331_ASIR       (volatile u16 *)IOP331_REG_ADDR(0x0000012E)
-#define IOP331_ERBAR      (volatile u32 *)IOP331_REG_ADDR(0x00000130)
-#define IOP331_ATU_CAPPTR (volatile u32 *)IOP331_REG_ADDR(0x00000134)
-/* Reserved 0x00000138 through 0x0000013B */
-#define IOP331_ATUILR     (volatile u8  *)IOP331_REG_ADDR(0x0000013C)
-#define IOP331_ATUIPR     (volatile u8  *)IOP331_REG_ADDR(0x0000013D)
-#define IOP331_ATUMGNT    (volatile u8  *)IOP331_REG_ADDR(0x0000013E)
-#define IOP331_ATUMLAT    (volatile u8  *)IOP331_REG_ADDR(0x0000013F)
-#define IOP331_IALR0      (volatile u32 *)IOP331_REG_ADDR(0x00000140)
-#define IOP331_IATVR0     (volatile u32 *)IOP331_REG_ADDR(0x00000144)
-#define IOP331_ERLR       (volatile u32 *)IOP331_REG_ADDR(0x00000148)
-#define IOP331_ERTVR      (volatile u32 *)IOP331_REG_ADDR(0x0000014C)
-#define IOP331_IALR1      (volatile u32 *)IOP331_REG_ADDR(0x00000150)
-#define IOP331_IALR2      (volatile u32 *)IOP331_REG_ADDR(0x00000154)
-#define IOP331_IATVR2     (volatile u32 *)IOP331_REG_ADDR(0x00000158)
-#define IOP331_OIOWTVR    (volatile u32 *)IOP331_REG_ADDR(0x0000015C)
-#define IOP331_OMWTVR0    (volatile u32 *)IOP331_REG_ADDR(0x00000160)
-#define IOP331_OUMWTVR0   (volatile u32 *)IOP331_REG_ADDR(0x00000164)
-#define IOP331_OMWTVR1    (volatile u32 *)IOP331_REG_ADDR(0x00000168)
-#define IOP331_OUMWTVR1   (volatile u32 *)IOP331_REG_ADDR(0x0000016C)
-/* Reserved 0x00000170 through 0x00000177*/
-#define IOP331_OUDWTVR    (volatile u32 *)IOP331_REG_ADDR(0x00000178)
-/* Reserved 0x0000017C through 0x0000017F*/
-#define IOP331_ATUCR      (volatile u32 *)IOP331_REG_ADDR(0x00000180)
-#define IOP331_PCSR       (volatile u32 *)IOP331_REG_ADDR(0x00000184)
-#define IOP331_ATUISR     (volatile u32 *)IOP331_REG_ADDR(0x00000188)
-#define IOP331_ATUIMR     (volatile u32 *)IOP331_REG_ADDR(0x0000018C)
-#define IOP331_IABAR3     (volatile u32 *)IOP331_REG_ADDR(0x00000190)
-#define IOP331_IAUBAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000194)
-#define IOP331_IALR3      (volatile u32 *)IOP331_REG_ADDR(0x00000198)
-#define IOP331_IATVR3     (volatile u32 *)IOP331_REG_ADDR(0x0000019C)
-/* Reserved 0x000001A0 through 0x000001A3*/
-#define IOP331_OCCAR      (volatile u32 *)IOP331_REG_ADDR(0x000001A4)
-/* Reserved 0x000001A8 through 0x000001AB*/
-#define IOP331_OCCDR      (volatile u32 *)IOP331_REG_ADDR(0x000001AC)
-/* Reserved 0x000001B0 through 0x000001BB*/
-#define IOP331_VPDCAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001B8)
-#define IOP331_VPDNXTP    (volatile u8 *)IOP331_REG_ADDR(0x000001B9)
-#define IOP331_VPDAR     (volatile u16 *)IOP331_REG_ADDR(0x000001BA)
-#define IOP331_VPDDR      (volatile u32 *)IOP331_REG_ADDR(0x000001BC)
-#define IOP331_PMCAPID    (volatile u8 *)IOP331_REG_ADDR(0x000001C0)
-#define IOP331_PMNEXT     (volatile u8 *)IOP331_REG_ADDR(0x000001C1)
-#define IOP331_APMCR      (volatile u16 *)IOP331_REG_ADDR(0x000001C2)
-#define IOP331_APMCSR     (volatile u16 *)IOP331_REG_ADDR(0x000001C4)
-/* Reserved 0x000001C6 through 0x000001CF */
-#define IOP331_MSICAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001D0)
-#define IOP331_MSINXTP   (volatile u8 *)IOP331_REG_ADDR(0x000001D1)
-#define IOP331_MSIMCR     (volatile u16 *)IOP331_REG_ADDR(0x000001D2)
-#define IOP331_MSIMAR     (volatile u32 *)IOP331_REG_ADDR(0x000001D4)
-#define IOP331_MSIMUAR   (volatile u32 *)IOP331_REG_ADDR(0x000001D8)
-#define IOP331_MSIMDR    (volatile u32 *)IOP331_REG_ADDR(0x000001DC)
-#define IOP331_PCIXCAPID  (volatile u8 *)IOP331_REG_ADDR(0x000001E0)
-#define IOP331_PCIXNEXT   (volatile u8 *)IOP331_REG_ADDR(0x000001E1)
-#define IOP331_PCIXCMD    (volatile u16 *)IOP331_REG_ADDR(0x000001E2)
-#define IOP331_PCIXSR     (volatile u32 *)IOP331_REG_ADDR(0x000001E4)
-#define IOP331_PCIIRSR    (volatile u32 *)IOP331_REG_ADDR(0x000001EC)
-
-/* Messaging Unit 0x00000300 through 0x000003FF */
-
-/* Reserved 0x00000300 through 0x0000030c */
-#define IOP331_IMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000310)
-#define IOP331_IMR1       (volatile u32 *)IOP331_REG_ADDR(0x00000314)
-#define IOP331_OMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000318)
-#define IOP331_OMR1       (volatile u32 *)IOP331_REG_ADDR(0x0000031C)
-#define IOP331_IDR        (volatile u32 *)IOP331_REG_ADDR(0x00000320)
-#define IOP331_IISR       (volatile u32 *)IOP331_REG_ADDR(0x00000324)
-#define IOP331_IIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000328)
-#define IOP331_ODR        (volatile u32 *)IOP331_REG_ADDR(0x0000032C)
-#define IOP331_OISR       (volatile u32 *)IOP331_REG_ADDR(0x00000330)
-#define IOP331_OIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000334)
-/* Reserved 0x00000338 through 0x0000034F */
-#define IOP331_MUCR       (volatile u32 *)IOP331_REG_ADDR(0x00000350)
-#define IOP331_QBAR       (volatile u32 *)IOP331_REG_ADDR(0x00000354)
-/* Reserved 0x00000358 through 0x0000035C */
-#define IOP331_IFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000360)
-#define IOP331_IFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000364)
-#define IOP331_IPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000368)
-#define IOP331_IPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000036C)
-#define IOP331_OFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000370)
-#define IOP331_OFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000374)
-#define IOP331_OPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000378)
-#define IOP331_OPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000037C)
-#define IOP331_IAR        (volatile u32 *)IOP331_REG_ADDR(0x00000380)
-/* Reserved 0x00000384 through 0x000003FF */
-
-/* DMA Controller 0x00000400 through 0x000004FF */
-#define IOP331_DMA0_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000400)
-#define IOP331_DMA0_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000404)
-#define IOP331_DMA0_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000040C)
-#define IOP331_DMA0_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000410)
-#define IOP331_DMA0_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000414)
-#define IOP331_DMA0_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000418)
-#define IOP331_DMA0_LADR  (volatile u32 *)IOP331_REG_ADDR(0X0000041C)
-#define IOP331_DMA0_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000420)
-#define IOP331_DMA0_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000424)
-/* Reserved 0x00000428 through 0x0000043C */
-#define IOP331_DMA1_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000440)
-#define IOP331_DMA1_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000444)
-#define IOP331_DMA1_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000044C)
-#define IOP331_DMA1_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000450)
-#define IOP331_DMA1_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000454)
-#define IOP331_DMA1_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000458)
-#define IOP331_DMA1_LADR  (volatile u32 *)IOP331_REG_ADDR(0x0000045C)
-#define IOP331_DMA1_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000460)
-#define IOP331_DMA1_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000464)
-/* Reserved 0x00000468 through 0x000004FF */
-
-/* Memory controller 0x00000500 through 0x0005FF */
-
-/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
-#define IOP331_PBCR       (volatile u32 *)IOP331_REG_ADDR(0x00000680)
-#define IOP331_PBISR      (volatile u32 *)IOP331_REG_ADDR(0x00000684)
-#define IOP331_PBBAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000688)
-#define IOP331_PBLR0      (volatile u32 *)IOP331_REG_ADDR(0x0000068C)
-#define IOP331_PBBAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000690)
-#define IOP331_PBLR1      (volatile u32 *)IOP331_REG_ADDR(0x00000694)
-#define IOP331_PBBAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000698)
-#define IOP331_PBLR2      (volatile u32 *)IOP331_REG_ADDR(0x0000069C)
-#define IOP331_PBBAR3     (volatile u32 *)IOP331_REG_ADDR(0x000006A0)
-#define IOP331_PBLR3      (volatile u32 *)IOP331_REG_ADDR(0x000006A4)
-#define IOP331_PBBAR4     (volatile u32 *)IOP331_REG_ADDR(0x000006A8)
-#define IOP331_PBLR4      (volatile u32 *)IOP331_REG_ADDR(0x000006AC)
-#define IOP331_PBBAR5     (volatile u32 *)IOP331_REG_ADDR(0x000006B0)
-#define IOP331_PBLR5      (volatile u32 *)IOP331_REG_ADDR(0x000006B4)
-#define IOP331_PBDSCR     (volatile u32 *)IOP331_REG_ADDR(0x000006B8)
-/* Reserved 0x000006BC */
-#define IOP331_PMBR0      (volatile u32 *)IOP331_REG_ADDR(0x000006C0)
-/* Reserved 0x000006C4 through 0x000006DC */
-#define IOP331_PMBR1      (volatile u32 *)IOP331_REG_ADDR(0x000006E0)
-#define IOP331_PMBR2      (volatile u32 *)IOP331_REG_ADDR(0x000006E4)
-
-#define IOP331_PBCR_EN    0x1
-
-#define IOP331_PBISR_BOOR_ERR 0x1
-
-
-
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
-/* Internal arbitration unit 0x00000780 through 0x0007BF */
-
-/* Interrupt Controller */
-#define IOP331_INTCTL0    (volatile u32 *)IOP331_REG_ADDR(0x00000790)
-#define IOP331_INTCTL1    (volatile u32 *)IOP331_REG_ADDR(0x00000794)
-#define IOP331_INTSTR0    (volatile u32 *)IOP331_REG_ADDR(0x00000798)
-#define IOP331_INTSTR1    (volatile u32 *)IOP331_REG_ADDR(0x0000079C)
-#define IOP331_IINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A0)
-#define IOP331_IINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007A4)
-#define IOP331_FINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A8)
-#define IOP331_FINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007AC)
-#define IOP331_IPR0       (volatile u32 *)IOP331_REG_ADDR(0x000007B0)
-#define IOP331_IPR1       (volatile u32 *)IOP331_REG_ADDR(0x000007B4)
-#define IOP331_IPR2       (volatile u32 *)IOP331_REG_ADDR(0x000007B8)
-#define IOP331_IPR3       (volatile u32 *)IOP331_REG_ADDR(0x000007BC)
-#define IOP331_INTBASE    (volatile u32 *)IOP331_REG_ADDR(0x000007C0)
-#define IOP331_INTSIZE    (volatile u32 *)IOP331_REG_ADDR(0x000007C4)
-#define IOP331_IINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007C8)
-#define IOP331_FINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007CC)
-
-
-/* Timers */
-
-#define IOP331_TU_TMR0         (volatile u32 *)IOP331_REG_ADDR(0x000007D0)
-#define IOP331_TU_TMR1         (volatile u32 *)IOP331_REG_ADDR(0x000007D4)
-
-#define IOP331_TMR_TC          0x01
-#define        IOP331_TMR_EN           0x02
-#define IOP331_TMR_RELOAD      0x04
-#define        IOP331_TMR_PRIVILEGED   0x09
-
-#define        IOP331_TMR_RATIO_1_1    0x00
-#define        IOP331_TMR_RATIO_4_1    0x10
-#define        IOP331_TMR_RATIO_8_1    0x20
-#define        IOP331_TMR_RATIO_16_1   0x30
-
-#define IOP331_TU_TCR0    (volatile u32 *)IOP331_REG_ADDR(0x000007D8)
-#define IOP331_TU_TCR1    (volatile u32 *)IOP331_REG_ADDR(0x000007DC)
-#define IOP331_TU_TRR0    (volatile u32 *)IOP331_REG_ADDR(0x000007E0)
-#define IOP331_TU_TRR1    (volatile u32 *)IOP331_REG_ADDR(0x000007E4)
-#define IOP331_TU_TISR    (volatile u32 *)IOP331_REG_ADDR(0x000007E8)
-#define IOP331_TU_WDTCR   (volatile u32 *)IOP331_REG_ADDR(0x000007EC)
-
-#if defined(CONFIG_ARCH_IOP331)
-#define        IOP331_TICK_RATE        266000000       /* 266 MHz IB clock */
-#endif
-
-#if defined(CONFIG_IOP331_STEPD) || defined(CONFIG_ARCH_IQ80333)
-#undef IOP331_TICK_RATE
-#define IOP331_TICK_RATE       333000000       /* 333 Mhz IB clock */
-#endif
-
-/* Application accelerator unit 0x00000800 - 0x000008FF */
-#define IOP331_AAU_ACR     (volatile u32 *)IOP331_REG_ADDR(0x00000800)
-#define IOP331_AAU_ASR     (volatile u32 *)IOP331_REG_ADDR(0x00000804)
-#define IOP331_AAU_ADAR    (volatile u32 *)IOP331_REG_ADDR(0x00000808)
-#define IOP331_AAU_ANDAR   (volatile u32 *)IOP331_REG_ADDR(0x0000080C)
-#define IOP331_AAU_SAR1    (volatile u32 *)IOP331_REG_ADDR(0x00000810)
-#define IOP331_AAU_SAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000814)
-#define IOP331_AAU_SAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000818)
-#define IOP331_AAU_SAR4    (volatile u32 *)IOP331_REG_ADDR(0x0000081C)
-#define IOP331_AAU_SAR5    (volatile u32 *)IOP331_REG_ADDR(0x0000082C)
-#define IOP331_AAU_SAR6    (volatile u32 *)IOP331_REG_ADDR(0x00000830)
-#define IOP331_AAU_SAR7    (volatile u32 *)IOP331_REG_ADDR(0x00000834)
-#define IOP331_AAU_SAR8    (volatile u32 *)IOP331_REG_ADDR(0x00000838)
-#define IOP331_AAU_SAR9    (volatile u32 *)IOP331_REG_ADDR(0x00000840)
-#define IOP331_AAU_SAR10   (volatile u32 *)IOP331_REG_ADDR(0x00000844)
-#define IOP331_AAU_SAR11   (volatile u32 *)IOP331_REG_ADDR(0x00000848)
-#define IOP331_AAU_SAR12   (volatile u32 *)IOP331_REG_ADDR(0x0000084C)
-#define IOP331_AAU_SAR13   (volatile u32 *)IOP331_REG_ADDR(0x00000850)
-#define IOP331_AAU_SAR14   (volatile u32 *)IOP331_REG_ADDR(0x00000854)
-#define IOP331_AAU_SAR15   (volatile u32 *)IOP331_REG_ADDR(0x00000858)
-#define IOP331_AAU_SAR16   (volatile u32 *)IOP331_REG_ADDR(0x0000085C)
-#define IOP331_AAU_SAR17   (volatile u32 *)IOP331_REG_ADDR(0x00000864)
-#define IOP331_AAU_SAR18   (volatile u32 *)IOP331_REG_ADDR(0x00000868)
-#define IOP331_AAU_SAR19   (volatile u32 *)IOP331_REG_ADDR(0x0000086C)
-#define IOP331_AAU_SAR20   (volatile u32 *)IOP331_REG_ADDR(0x00000870)
-#define IOP331_AAU_SAR21   (volatile u32 *)IOP331_REG_ADDR(0x00000874)
-#define IOP331_AAU_SAR22   (volatile u32 *)IOP331_REG_ADDR(0x00000878)
-#define IOP331_AAU_SAR23   (volatile u32 *)IOP331_REG_ADDR(0x0000087C)
-#define IOP331_AAU_SAR24   (volatile u32 *)IOP331_REG_ADDR(0x00000880)
-#define IOP331_AAU_SAR25   (volatile u32 *)IOP331_REG_ADDR(0x00000888)
-#define IOP331_AAU_SAR26   (volatile u32 *)IOP331_REG_ADDR(0x0000088C)
-#define IOP331_AAU_SAR27   (volatile u32 *)IOP331_REG_ADDR(0x00000890)
-#define IOP331_AAU_SAR28   (volatile u32 *)IOP331_REG_ADDR(0x00000894)
-#define IOP331_AAU_SAR29   (volatile u32 *)IOP331_REG_ADDR(0x00000898)
-#define IOP331_AAU_SAR30   (volatile u32 *)IOP331_REG_ADDR(0x0000089C)
-#define IOP331_AAU_SAR31   (volatile u32 *)IOP331_REG_ADDR(0x000008A0)
-#define IOP331_AAU_SAR32   (volatile u32 *)IOP331_REG_ADDR(0x000008A4)
-#define IOP331_AAU_DAR     (volatile u32 *)IOP331_REG_ADDR(0x00000820)
-#define IOP331_AAU_ABCR    (volatile u32 *)IOP331_REG_ADDR(0x00000824)
-#define IOP331_AAU_ADCR    (volatile u32 *)IOP331_REG_ADDR(0x00000828)
-#define IOP331_AAU_EDCR0   (volatile u32 *)IOP331_REG_ADDR(0x0000083c)
-#define IOP331_AAU_EDCR1   (volatile u32 *)IOP331_REG_ADDR(0x00000860)
-#define IOP331_AAU_EDCR2   (volatile u32 *)IOP331_REG_ADDR(0x00000884)
-
-
-#define IOP331_SPDSCR    (volatile u32 *)IOP331_REG_ADDR(0x000015C0)
-#define IOP331_PPDSCR    (volatile u32 *)IOP331_REG_ADDR(0x000015C8)
-/* SSP serial port unit 0x00001600 - 0x0000167F */
-
-/* I2C bus interface unit 0x00001680 - 0x000016FF */
-/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
-
-#define IOP331_ICR0       (volatile u32 *)IOP331_REG_ADDR(0x00001680)
-#define IOP331_ISR0       (volatile u32 *)IOP331_REG_ADDR(0x00001684)
-#define IOP331_ISAR0      (volatile u32 *)IOP331_REG_ADDR(0x00001688)
-#define IOP331_IDBR0      (volatile u32 *)IOP331_REG_ADDR(0x0000168C)
-/* Reserved 0x00001690 */
-#define IOP331_IBMR0      (volatile u32 *)IOP331_REG_ADDR(0x00001694)
-/* Reserved 0x00001698 */
-/* Reserved 0x0000169C */
-#define IOP331_ICR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A0)
-#define IOP331_ISR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A4)
-#define IOP331_ISAR1      (volatile u32 *)IOP331_REG_ADDR(0x000016A8)
-#define IOP331_IDBR1      (volatile u32 *)IOP331_REG_ADDR(0x000016AC)
-#define IOP331_IBMR1      (volatile u32 *)IOP331_REG_ADDR(0x000016B4)
-/* Reserved 0x000016B8 through 0x000016FF */
-
-/* 0x00001700 through 0x0000172C  UART 0 */
-
-/* Reserved 0x00001730 through 0x0000173F */
-
-/* 0x00001740 through 0x0000176C UART 1 */
-
-#define IOP331_UART0_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001700) /* UART #1 physical */
-#define IOP331_UART1_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001740) /* UART #2 physical */
-#define IOP331_UART0_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001700) /* UART #1 virtual addr */
-#define IOP331_UART1_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001740) /* UART #2 virtual addr */
-
-/* Reserved 0x00001770 through 0x0000177F */
-
-/* General Purpose I/O Registers */
-#define IOP331_GPOE       (volatile u32 *)IOP331_REG_ADDR(0x00001780)
-#define IOP331_GPID       (volatile u32 *)IOP331_REG_ADDR(0x00001784)
-#define IOP331_GPOD       (volatile u32 *)IOP331_REG_ADDR(0x00001788)
-
-/* Reserved 0x0000178c through 0x000019ff */
-
-
-#ifndef __ASSEMBLY__
-extern void iop331_map_io(void);
-extern void iop331_init_irq(void);
-extern void iop331_time_init(void);
-#endif
-
-#endif // _IOP331_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iq31244.h b/include/asm-arm/arch-iop3xx/iq31244.h
deleted file mode 100644 (file)
index 4177cfa..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq31244.h
- *
- * Intel IQ31244 evaluation board registers
- */
-
-#ifndef _IQ31244_H_
-#define _IQ31244_H_
-
-#define        IQ31244_FLASHBASE       0xf0000000      /* Flash */
-#define        IQ31244_FLASHSIZE       0x00800000
-#define        IQ31244_FLASHWIDTH      2
-
-#define IQ31244_UART           0xfe800000      /* UART #1 */
-#define IQ31244_7SEG_1         0xfe840000      /* 7-Segment MSB */
-#define IQ31244_7SEG_0         0xfe850000      /* 7-Segment LSB (WO) */
-#define IQ31244_ROTARY_SW      0xfe8d0000      /* Rotary Switch */
-#define IQ31244_BATT_STAT      0xfe8f0000      /* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq31244_map_io(void);
-#endif
-
-#endif // _IQ31244_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80321.h b/include/asm-arm/arch-iop3xx/iq80321.h
deleted file mode 100644 (file)
index cb87259..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq80321.h
- *
- * Intel IQ80321 evaluation board registers
- */
-
-#ifndef _IQ80321_H_
-#define _IQ80321_H_
-
-#define        IQ80321_FLASHBASE       0xf0000000      /* Flash */
-#define        IQ80321_FLASHSIZE       0x00800000
-#define        IQ80321_FLASHWIDTH      1
-
-#define IQ80321_UART           0xfe800000      /* UART #1 */
-#define IQ80321_7SEG_1         0xfe840000      /* 7-Segment MSB */
-#define IQ80321_7SEG_0         0xfe850000      /* 7-Segment LSB (WO) */
-#define IQ80321_ROTARY_SW      0xfe8d0000      /* Rotary Switch */
-#define IQ80321_BATT_STAT      0xfe8f0000      /* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq80321_map_io(void);
-#endif
-
-#endif // _IQ80321_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80331.h b/include/asm-arm/arch-iop3xx/iq80331.h
deleted file mode 100644 (file)
index 0668e78..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq80331.h
- *
- * Intel IQ80331 evaluation board registers
- */
-
-#ifndef _IQ80331_H_
-#define _IQ80331_H_
-
-#define        IQ80331_FLASHBASE       0xc0000000      /* Flash */
-#define        IQ80331_FLASHSIZE       0x00800000
-#define        IQ80331_FLASHWIDTH      1
-
-#define IQ80331_7SEG_1         0xce840000      /* 7-Segment MSB */
-#define IQ80331_7SEG_0         0xce850000      /* 7-Segment LSB (WO) */
-#define IQ80331_ROTARY_SW      0xce8d0000      /* Rotary Switch */
-#define IQ80331_BATT_STAT      0xce8f0000      /* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq80331_map_io(void);
-#endif
-
-#endif // _IQ80331_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80332.h b/include/asm-arm/arch-iop3xx/iq80332.h
deleted file mode 100644 (file)
index e5fff17..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iq80332.h
- *
- * Intel IQ80332 evaluation board registers
- */
-
-#ifndef _IQ80332_H_
-#define _IQ80332_H_
-
-#define        IQ80332_FLASHBASE       0xc0000000      /* Flash */
-#define        IQ80332_FLASHSIZE       0x00800000
-#define        IQ80332_FLASHWIDTH      1
-
-#define IQ80332_7SEG_1         0xce840000      /* 7-Segment MSB */
-#define IQ80332_7SEG_0         0xce850000      /* 7-Segment LSB (WO) */
-#define IQ80332_ROTARY_SW      0xce8d0000      /* Rotary Switch */
-#define IQ80332_BATT_STAT      0xce8f0000      /* Battery Status */
-
-#ifndef __ASSEMBLY__
-extern void iq80332_map_io(void);
-#endif
-
-#endif // _IQ80332_H_
diff --git a/include/asm-arm/arch-iop3xx/irqs.h b/include/asm-arm/arch-iop3xx/irqs.h
deleted file mode 100644 (file)
index b2c03f4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/irqs.h
- *
- * Copyright:  (C) 2001-2003 MontaVista Software 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.
- *
- */
-
-/*
- * Chipset-specific bits
- */
-#ifdef CONFIG_ARCH_IOP321
-#include "iop321-irqs.h"
-#endif
-
-#ifdef CONFIG_ARCH_IOP331
-#include "iop331-irqs.h"
-#endif
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
deleted file mode 100644 (file)
index e43ebd9..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/hardware.h>
-
-/*
- * Physical DRAM offset.
- */
-#ifndef CONFIG_ARCH_IOP331
-#define PHYS_OFFSET    UL(0xa0000000)
-#else
-#define PHYS_OFFSET    UL(0x00000000)
-#endif
-
-/*
- * Virtual view <-> PCI DMA view memory address translations
- * virt_to_bus: Used to translate the virtual address to an
- *             address suitable to be passed to set_dma_addr
- * bus_to_virt: Used to convert an address for DMA operations
- *             to an address that the kernel can use.
- */
-#if defined(CONFIG_ARCH_IOP321)
-
-#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP321_IATVR2)) | ((*IOP321_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP321_IALR2)) | ( *IOP321_IATVR2)))
-
-#elif defined(CONFIG_ARCH_IOP331)
-
-#define __virt_to_bus(x)       (((__virt_to_phys(x)) & ~(*IOP331_IATVR2)) | ((*IOP331_IABAR2) & 0xfffffff0))
-#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP331_IALR2)) | ( *IOP331_IATVR2)))
-
-#endif
-
-#endif
diff --git a/include/asm-arm/arch-iop3xx/system.h b/include/asm-arm/arch-iop3xx/system.h
deleted file mode 100644 (file)
index af6ae8c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/system.h
- *
- *  Copyright (C) 2001 MontaVista Software, 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.
- */
-
-static inline void arch_idle(void)
-{
-       cpu_do_idle();
-}
-
-
-static inline void arch_reset(char mode)
-{
-#ifdef CONFIG_ARCH_IOP321
-    *IOP321_PCSR = 0x30;
-#endif
-
-#ifdef CONFIG_ARCH_IOP331
-    *IOP331_PCSR = 0x30;
-#endif
-
-       if ( 1 && mode == 's') {
-               /* Jump into ROM at address 0 */
-               cpu_reset(0);
-       } else {
-               /* No on-chip reset capability */
-               cpu_reset(0);
-       }
-}
-
diff --git a/include/asm-arm/arch-iop3xx/timex.h b/include/asm-arm/arch-iop3xx/timex.h
deleted file mode 100644 (file)
index 14ca8d0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/timex.h
- *
- * IOP3xx architecture timex specifications
- */
-#include <asm/hardware.h>
-
-#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
-
-#define CLOCK_TICK_RATE IOP321_TICK_RATE
-
-#elif defined(CONFIG_ARCH_IQ80331) || defined(CONFIG_MACH_IQ80332)
-
-#define CLOCK_TICK_RATE IOP331_TICK_RATE
-
-#else
-
-#error "No IOP3xx timex information for this architecture"
-
-#endif
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
deleted file mode 100644 (file)
index fbdd5af..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-iop3xx/uncompress.h
- */
-#include <asm/types.h>
-#include <asm/mach-types.h>
-#include <linux/serial_reg.h>
-#include <asm/hardware.h>
-
-#ifdef CONFIG_ARCH_IOP321
-#define UTYPE unsigned char *
-#elif defined(CONFIG_ARCH_IOP331)
-#define UTYPE u32 *
-#else
-#error "Missing IOP3xx arch type def"
-#endif
-
-static volatile UTYPE uart_base;
-
-#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
-
-static inline void putc(char c)
-{
-       while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
-               barrier();
-       *uart_base = c;
-}
-
-static inline void flush(void)
-{
-}
-
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
-        if(machine_is_iq80321())
-                       uart_base = (volatile UTYPE)IQ80321_UART;
-               else if(machine_is_iq31244())
-                       uart_base = (volatile UTYPE)IQ31244_UART;
-               else if(machine_is_iq80331() || machine_is_iq80332())
-                       uart_base = (volatile UTYPE)IOP331_UART0_PHYS;
-               else
-                       uart_base = (volatile UTYPE)0xfe800000;
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()    __arch_decomp_setup(arch_id)
-#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop3xx/vmalloc.h b/include/asm-arm/arch-iop3xx/vmalloc.h
deleted file mode 100644 (file)
index 0f2f684..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop3xx/vmalloc.h
- */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "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. ;)
- */
-//#define VMALLOC_END       (0xe8000000)
-/* increase usable physical RAM to ~992M per RMK */
-#define VMALLOC_END       (0xfe000000)
-
index 13aee17b04750b692d5cab4b445d61d84163d740..8d10a91876932587e6c96cf3d259902b2f20dd66 100644 (file)
@@ -89,6 +89,11 @@ struct ixp4xx_i2c_pins {
 
 struct sys_timer;
 
+/*
+ * Frequency of clock used for primary clocksource
+ */
+extern unsigned long ixp4xx_timer_freq;
+
 /*
  * Functions used by platform-level setup code
  */
index cd080d8384d9232135a68802facdea5dca5a3783..d744d97c18a5fee15f664302ed6085424a9c7f3d 100644 (file)
@@ -31,9 +31,9 @@
 static inline unsigned int __arch_getw(unsigned long a)
 {
        unsigned int value;
-       __asm__ __volatile__("ldr%?h    %0, [%1, #0]    @ getw"
+       __asm__ __volatile__("ldrh    %0, [%1, #0]    @ getw"
                : "=&r" (value)
-               : "r" (a));
+               : "r" (a) : "cc");
        return value;
 }
 
@@ -42,8 +42,8 @@ static inline unsigned int __arch_getw(unsigned long a)
 
 static inline void __arch_putw(unsigned int value, unsigned long a)
 {
-        __asm__ __volatile__("str%?h    %0, [%1, #0]    @ putw"
-                : : "r" (value), "r" (a));
+        __asm__ __volatile__("strh    %0, [%1, #0]    @ putw"
+                : : "r" (value), "r" (a) : "cc");
 }
 
 /*
index 7b98b533e63a85e84e36618a713d5a6412b9478f..c69cb508735f74aed3db85f0d7e1e662eba0896e 100644 (file)
@@ -45,7 +45,7 @@
 static irqreturn_t
 timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode(regs));
 #endif
index 0070f6d3b75ceb30550118e6c94db29ae0fe00ed..9aee15d97145df25e9c2b32f1e56a510e64aa192 100644 (file)
 #define AMS_DELTA_LATCH2_NAND_NWE      0x0020
 #define AMS_DELTA_LATCH2_NAND_ALE      0x0040
 #define AMS_DELTA_LATCH2_NAND_CLE      0x0080
+#define AMD_DELTA_LATCH2_KEYBRD_PWR    0x0100
+#define AMD_DELTA_LATCH2_KEYBRD_DATA   0x0200
+#define AMD_DELTA_LATCH2_SCARD_RSTIN   0x0400
+#define AMD_DELTA_LATCH2_SCARD_CMDVCC  0x0800
 #define AMS_DELTA_LATCH2_MODEM_NRESET  0x1000
 #define AMS_DELTA_LATCH2_MODEM_CODEC   0x2000
 
+#define AMS_DELTA_GPIO_PIN_KEYBRD_DATA 0
+#define AMS_DELTA_GPIO_PIN_KEYBRD_CLK  1
+#define AMS_DELTA_GPIO_PIN_MODEM_IRQ   2
+#define AMS_DELTA_GPIO_PIN_HOOK_SWITCH 4
+#define AMS_DELTA_GPIO_PIN_SCARD_NOFF  6
+#define AMS_DELTA_GPIO_PIN_SCARD_IO    7
+#define AMS_DELTA_GPIO_PIN_CONFIG      11
 #define AMS_DELTA_GPIO_PIN_NAND_RB     12
 
 #ifndef __ASSEMBLY__
index f83003f5287b04dbd63b3998ea8e98beae0b7286..fa68810499034057f5b8544606a8579dd8d58eee 100644 (file)
@@ -45,6 +45,7 @@ struct clk_functions {
        struct clk *    (*clk_get_parent)(struct clk *clk);
        void            (*clk_allow_idle)(struct clk *clk);
        void            (*clk_deny_idle)(struct clk *clk);
+       void            (*clk_disable_unused)(struct clk *clk);
 };
 
 extern unsigned int mpurate;
index 1b1b02307e77f5c600ed32064915bf0594158511..d591d0585bbab64f7cb944788ac02c5f957d258c 100644 (file)
@@ -331,6 +331,12 @@ enum omap_dma_color_mode {
        OMAP_DMA_TRANSPARENT_COPY
 };
 
+enum omap_dma_write_mode {
+       OMAP_DMA_WRITE_NON_POSTED = 0,
+       OMAP_DMA_WRITE_POSTED,
+       OMAP_DMA_WRITE_LAST_NON_POSTED
+};
+
 struct omap_dma_channel_params {
        int data_type;          /* data type 8,16,32 */
        int elem_count;         /* number of elements in a frame */
@@ -338,13 +344,13 @@ struct omap_dma_channel_params {
 
        int src_port;           /* Only on OMAP1 REVISIT: Is this needed? */
        int src_amode;          /* constant , post increment, indexed , double indexed */
-       int src_start;          /* source address : physical */
+       unsigned long src_start;        /* source address : physical */
        int src_ei;             /* source element index */
        int src_fi;             /* source frame index */
 
        int dst_port;           /* Only on OMAP1 REVISIT: Is this needed? */
        int dst_amode;          /* constant , post increment, indexed , double indexed */
-       int dst_start;          /* source address : physical */
+       unsigned long dst_start;        /* source address : physical */
        int dst_ei;             /* source element index */
        int dst_fi;             /* source frame index */
 
@@ -356,7 +362,7 @@ struct omap_dma_channel_params {
 };
 
 
-extern void omap_set_dma_priority(int dst_port, int priority);
+extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
                            void (* callback)(int lch, u16 ch_status, void *data),
                            void *data, int *dma_ch);
@@ -371,6 +377,7 @@ extern void omap_set_dma_transfer_params(int lch, int data_type,
                                         int dma_trigger, int src_or_dst_synch);
 extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
                                    u32 color);
+extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
 
 extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
                                    unsigned long src_start,
@@ -394,6 +401,9 @@ extern void omap_set_dma_params(int lch,
 extern void omap_dma_link_lch (int lch_head, int lch_queue);
 extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
 
+extern int omap_set_dma_callback(int lch,
+                       void (* callback)(int lch, u16 ch_status, void *data),
+                       void *data);
 extern dma_addr_t omap_get_dma_src_pos(int lch);
 extern dma_addr_t omap_get_dma_dst_pos(int lch);
 extern int omap_get_dma_src_addr_counter(int lch);
index 7a289ff07404c3b333c756e5b751316b9bfffb88..b5f3a71b899dbdb836394f84652831151b4390a5 100644 (file)
@@ -52,6 +52,8 @@ int omap_dm_timer_init(void);
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
 void omap_dm_timer_free(struct omap_dm_timer *timer);
+void omap_dm_timer_enable(struct omap_dm_timer *timer);
+void omap_dm_timer_disable(struct omap_dm_timer *timer);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
 
index 1a0a5207822d660fc1e74efb1d501621a4a5c308..7c03ef6c14c4f6e7d4391bb5275ef9be61045aec 100644 (file)
@@ -85,7 +85,7 @@ extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
 extern u32 gpmc_cs_read_reg(int cs, int idx);
 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 unsigned long gpmc_cs_get_base_addr(int cs);
-
+extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+extern void gpmc_cs_free(int cs);
 
 #endif
index 2542495d8a435db14adc3baaaa1429d8bc114c49..c5bb05a69b81ec815c405d79b8b3bd553e29abc3 100644 (file)
 #define INT_24XX_SDMA_IRQ1     13
 #define INT_24XX_SDMA_IRQ2     14
 #define INT_24XX_SDMA_IRQ3     15
+#define INT_24XX_CAM_IRQ       24
 #define INT_24XX_DSS_IRQ       25
 #define INT_24XX_GPIO_BANK1    29
 #define INT_24XX_GPIO_BANK2    30
 #define INT_24XX_UART1_IRQ     72
 #define INT_24XX_UART2_IRQ     73
 #define INT_24XX_UART3_IRQ     74
+#define INT_24XX_MMC_IRQ       83
 
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
  * 16 MPUIO lines */
index 8a023a984acb52435367435a21320259e604b37f..b7f83075436ec7e226e224d327fa678f4a8c4e41 100644 (file)
@@ -14,7 +14,10 @@ struct omap_kp_platform_data {
        int rows;
        int cols;
        int *keymap;
+       unsigned int keymapsize;
        unsigned int rep:1;
+       unsigned long delay;
+       unsigned int dbounce:1;
        /* specific to OMAP242x*/
        unsigned int *row_gpios;
        unsigned int *col_gpios;
index 679869c5e68fbdd0ff4aca17028645cb9ee5bab6..828cc5c114e18e66e4e0c7a797b4df3d928dc281 100644 (file)
@@ -320,6 +320,17 @@ enum omap1xxx_index {
        P15_1610_UWIRE_CS3,
        N15_1610_UWIRE_CS1,
 
+       /* OMAP-1610 SPI */
+       U19_1610_SPIF_SCK,
+       U18_1610_SPIF_DIN,
+       P20_1610_SPIF_DIN,
+       W21_1610_SPIF_DOUT,
+       R18_1610_SPIF_DOUT,
+       N14_1610_SPIF_CS0,
+       N15_1610_SPIF_CS1,
+       T19_1610_SPIF_CS2,
+       P15_1610_SPIF_CS3,
+
        /* OMAP-1610 Flash */
        L3_1610_FLASH_CS2B_OE,
        M8_1610_FLASH_CS2B_WE,
@@ -461,6 +472,20 @@ enum omap24xx_index {
        K15_24XX_UART3_TX,
        K14_24XX_UART3_RX,
 
+       /* MMC/SDIO */
+       G19_24XX_MMC_CLKO,
+       H18_24XX_MMC_CMD,
+       F20_24XX_MMC_DAT0,
+       H14_24XX_MMC_DAT1,
+       E19_24XX_MMC_DAT2,
+       D19_24XX_MMC_DAT3,
+       F19_24XX_MMC_DAT_DIR0,
+       E20_24XX_MMC_DAT_DIR1,
+       F18_24XX_MMC_DAT_DIR2,
+       E18_24XX_MMC_DAT_DIR3,
+       G18_24XX_MMC_CMD_DIR,
+       H15_24XX_MMC_CLKI,
+
        /* Keypad GPIO*/
        T19_24XX_KBR0,
        R19_24XX_KBR1,
index 30548a30c773e1685c97c08e53f63ad4bff9f385..121cd241115d33c1e22745d8fc3b1b36c0055db6 100644 (file)
@@ -12,6 +12,14 @@ struct pxa2xx_udc_mach_info {
         void (*udc_command)(int cmd);
 #define        PXA2XX_UDC_CMD_CONNECT          0       /* let host see us */
 #define        PXA2XX_UDC_CMD_DISCONNECT       1       /* so host won't see us */
+
+       /* Boards following the design guidelines in the developer's manual,
+        * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
+        * VBUS IRQ and omit the methods above.  Store the GPIO number
+        * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
+        */
+       u16     gpio_vbus;                      /* high == vbus present */
+       u16     gpio_pullup;                    /* high == pullup activated */
 };
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
index 3661e465b0a5a51efe1e874e02ca826d9f3f8d77..7ac22483697130e6cdf7b57ccc9b3beac3376149 100644 (file)
 #define MAX_DMA_ADDRESS                0x40000000
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
+/* We use `virtual` dma channels to hide the fact we have only a limited
+ * number of DMA channels, and not of all of them (dependant on the device)
+ * can be attached to any DMA source. We therefore let the DMA core handle
+ * the allocation of hardware channels to clients.
+*/
+
+enum dma_ch {
+       DMACH_XD0,
+       DMACH_XD1,
+       DMACH_SDI,
+       DMACH_SPI0,
+       DMACH_SPI1,
+       DMACH_UART0,
+       DMACH_UART1,
+       DMACH_UART2,
+       DMACH_TIMER,
+       DMACH_I2S_IN,
+       DMACH_I2S_OUT,
+       DMACH_PCM_IN,
+       DMACH_PCM_OUT,
+       DMACH_MIC_IN,
+       DMACH_USB_EP1,
+       DMACH_USB_EP2,
+       DMACH_USB_EP3,
+       DMACH_USB_EP4,
+       DMACH_UART0_SRC2,       /* s3c2412 second uart sources */
+       DMACH_UART1_SRC2,
+       DMACH_UART2_SRC2,
+       DMACH_MAX,              /* the end entry */
+};
+
+#define DMACH_LOW_LEVEL        (1<<28) /* use this to specifiy hardware ch no */
+
 /* we have 4 dma channels */
 #define S3C2410_DMA_CHANNELS        (4)
 
@@ -149,6 +182,8 @@ struct s3c2410_dma_stats {
        unsigned long           timeout_failed;
 };
 
+struct s3c2410_dma_map;
+
 /* struct s3c2410_dma_chan
  *
  * full state information for each DMA channel
@@ -174,6 +209,8 @@ struct s3c2410_dma_chan {
        unsigned long            load_timeout;
        unsigned int             flags;         /* channel flags */
 
+       struct s3c24xx_dma_map  *map;           /* channel hw maps */
+
        /* channel's hardware position and configuration */
        void __iomem            *regs;          /* channels registers */
        void __iomem            *addr_reg;      /* data address register */
@@ -283,6 +320,7 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 #define S3C2410_DMA_DCSRC       (0x18)
 #define S3C2410_DMA_DCDST       (0x1C)
 #define S3C2410_DMA_DMASKTRIG   (0x20)
+#define S3C2412_DMA_DMAREQSEL  (0x24)
 
 #define S3C2410_DISRCC_INC     (1<<0)
 #define S3C2410_DISRCC_APB     (1<<1)
@@ -349,4 +387,32 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 #define S3C2440_DCON_CH3_PCMOUT        (6<<24)
 #endif
 
+#ifdef CONFIG_CPU_S3C2412
+
+#define S3C2412_DMAREQSEL_SRC(x)       ((x)<<1)
+
+#define S3C2412_DMAREQSEL_HW           (1)
+
+#define S3C2412_DMAREQSEL_SPI0TX       S3C2412_DMAREQSEL_SRC(0)
+#define S3C2412_DMAREQSEL_SPI0RX       S3C2412_DMAREQSEL_SRC(1)
+#define S3C2412_DMAREQSEL_SPI1TX       S3C2412_DMAREQSEL_SRC(2)
+#define S3C2412_DMAREQSEL_SPI1RX       S3C2412_DMAREQSEL_SRC(3)
+#define S3C2412_DMAREQSEL_I2STX                S3C2412_DMAREQSEL_SRC(4)
+#define S3C2412_DMAREQSEL_I2SRX                S3C2412_DMAREQSEL_SRC(5)
+#define S3C2412_DMAREQSEL_TIMER                S3C2412_DMAREQSEL_SRC(9)
+#define S3C2412_DMAREQSEL_SDI          S3C2412_DMAREQSEL_SRC(10)
+#define S3C2412_DMAREQSEL_USBEP1       S3C2412_DMAREQSEL_SRC(13)
+#define S3C2412_DMAREQSEL_USBEP2       S3C2412_DMAREQSEL_SRC(14)
+#define S3C2412_DMAREQSEL_USBEP3       S3C2412_DMAREQSEL_SRC(15)
+#define S3C2412_DMAREQSEL_USBEP4       S3C2412_DMAREQSEL_SRC(16)
+#define S3C2412_DMAREQSEL_XDREQ0       S3C2412_DMAREQSEL_SRC(17)
+#define S3C2412_DMAREQSEL_XDREQ1       S3C2412_DMAREQSEL_SRC(18)
+#define S3C2412_DMAREQSEL_UART0_0      S3C2412_DMAREQSEL_SRC(19)
+#define S3C2412_DMAREQSEL_UART0_1      S3C2412_DMAREQSEL_SRC(20)
+#define S3C2412_DMAREQSEL_UART1_0      S3C2412_DMAREQSEL_SRC(21)
+#define S3C2412_DMAREQSEL_UART1_1      S3C2412_DMAREQSEL_SRC(22)
+#define S3C2412_DMAREQSEL_UART2_0      S3C2412_DMAREQSEL_SRC(23)
+#define S3C2412_DMAREQSEL_UART2_1      S3C2412_DMAREQSEL_SRC(24)
+
+#endif
 #endif /* __ASM_ARCH_DMA_H */
index 27ba0ac3fdd5ad48f5d8e9e40e610189d86bc421..7895042d176b3f4710514c7e6593484b709bf937 100644 (file)
 #define S3C2440_PA_CAMIF   (0x4F000000)
 #define S3C2440_SZ_CAMIF   SZ_1M
 
+/* AC97 */
+
+#define S3C2440_PA_AC97           (0x5B000000)
+#define S3C2440_SZ_AC97           SZ_1M
+
 /* ISA style IO, for each machine to sort out mappings for, if it
  * implements it. We reserve two 16M regions for ISA.
  */
index e2d406218ae554fe39b92bbd1c86af76554d86c1..a14164dfa525ae9638f40dedd4bd2cad5a7717bc 100644 (file)
 
 /* start peripherals off after the S3C2410 */
 
-#define OSIRIS_IOADDR(x)       (S3C2410_ADDR((x) + 0x05000000))
+#define OSIRIS_IOADDR(x)       (S3C2410_ADDR((x) + 0x04000000))
 
-#define OSIRIS_PA_CPLD         (S3C2410_CS1 | (3<<25))
+#define OSIRIS_PA_CPLD         (S3C2410_CS1 | (1<<26))
 
 /* we put the CPLD registers next, to get them out of the way */
 
-#define OSIRIS_VA_CTRL1            OSIRIS_IOADDR(0x00000000)    /* 0x01300000 */
+#define OSIRIS_VA_CTRL1            OSIRIS_IOADDR(0x00000000)
 #define OSIRIS_PA_CTRL1            (OSIRIS_PA_CPLD)
 
-#define OSIRIS_VA_CTRL2            OSIRIS_IOADDR(0x00100000)    /* 0x01400000 */
-#define OSIRIS_PA_CTRL2            (OSIRIS_PA_CPLD + (1<<24))
+#define OSIRIS_VA_CTRL2            OSIRIS_IOADDR(0x00100000)
+#define OSIRIS_PA_CTRL2            (OSIRIS_PA_CPLD + (1<<23))
 
-#define OSIRIS_VA_CTRL3            OSIRIS_IOADDR(0x00200000)    /* 0x01500000 */
-#define OSIRIS_PA_CTRL3            (OSIRIS_PA_CPLD + (2<<24))
+#define OSIRIS_VA_CTRL3            OSIRIS_IOADDR(0x00200000)
+#define OSIRIS_PA_CTRL3            (OSIRIS_PA_CPLD + (2<<23))
 
-#define OSIRIS_VA_CTRL4            OSIRIS_IOADDR(0x00300000)    /* 0x01600000 */
-#define OSIRIS_PA_CTRL4            (OSIRIS_PA_CPLD + (3<<24))
+#define OSIRIS_VA_CTRL4            OSIRIS_IOADDR(0x00300000)
+#define OSIRIS_PA_CTRL4            (OSIRIS_PA_CPLD + (3<<23))
 
 #endif /* __ASM_ARCH_OSIRISMAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-ac97.h b/include/asm-arm/arch-s3c2410/regs-ac97.h
new file mode 100644 (file)
index 0000000..bdd6a4f
--- /dev/null
@@ -0,0 +1,23 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-ac97.h
+ *
+ * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk>
+ *             http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2440 AC97 Controller
+*/
+
+#ifndef __ASM_ARCH_REGS_AC97_H
+#define __ASM_ARCH_REGS_AC97_H __FILE__
+
+#define S3C_AC97_GLBCTRL       (0x00)
+#define S3C_AC97_GLBSTAT       (0x04)
+#define S3C_AC97_CODEC_CMD     (0x08)
+#define S3C_AC97_PCM_ADDR      (0x10)
+#define S3C_AC97_PCM_DATA      (0x18)
+#define S3C_AC97_MIC_DATA      (0x1C)
+
+#endif /* __ASM_ARCH_REGS_AC97_H */
index b306d6e3135d00d212e1606adaef7047bfcfa970..6d7881c8cfc8ee35077a018f56b17a1a7f2d98ba 100644 (file)
@@ -63,6 +63,8 @@
 #define S3C2410_LCDCON3_GET_HBPD(x) ( ((x) >> 19) & 0x7F)
 #define S3C2410_LCDCON3_GET_HFPD(x) ( ((x) >>  0) & 0xFF)
 
+/* LDCCON4 changes for STN mode on the S3C2412 */
+
 #define S3C2410_LCDCON4_MVAL(x)            ((x) << 8)
 #define S3C2410_LCDCON4_HSPW(x)            ((x) << 0)
 #define S3C2410_LCDCON4_WLH(x)     ((x) << 0)
 #define        S3C2410_LCDINT_FRSYNC   (1<<1)
 #define S3C2410_LCDINT_FICNT   (1<<0)
 
+/* s3c2442 extra stn registers */
+
+#define S3C2442_REDLUT         S3C2410_LCDREG(0x20)
+#define S3C2442_GREENLUT       S3C2410_LCDREG(0x24)
+#define S3C2442_BLUELUT                S3C2410_LCDREG(0x28)
+#define S3C2442_DITHMODE       S3C2410_LCDREG(0x20)
+
 #define S3C2410_LPCSEL    S3C2410_LCDREG(0x60)
 
 #define S3C2410_TFTPAL(x)  S3C2410_LCDREG((0x400 + (x)*4))
 
+/* S3C2412 registers */
+
+#define S3C2412_TPAL           S3C2410_LCDREG(0x20)
+
+#define S3C2412_LCDINTPND      S3C2410_LCDREG(0x24)
+#define S3C2412_LCDSRCPND      S3C2410_LCDREG(0x28)
+#define S3C2412_LCDINTMSK      S3C2410_LCDREG(0x2C)
+
+#define S3C2412_TCONSEL                S3C2410_LCDREG(0x30)
+
+#define S3C2412_LCDCON6                S3C2410_LCDREG(0x34)
+#define S3C2412_LCDCON7                S3C2410_LCDREG(0x38)
+#define S3C2412_LCDCON8                S3C2410_LCDREG(0x3C)
+#define S3C2412_LCDCON9                S3C2410_LCDREG(0x40)
+
+#define S3C2412_REDLUT(x)      S3C2410_LCDREG(0x44 + ((x)*4))
+#define S3C2412_GREENLUT(x)    S3C2410_LCDREG(0x60 + ((x)*4))
+#define S3C2412_BLUELUT(x)     S3C2410_LCDREG(0x98 + ((x)*4))
+
+#define S3C2412_FRCPAT(x)      S3C2410_LCDREG(0xB4 + ((x)*4))
+
 #endif /* ___ASM_ARCH_REGS_LCD_H */
 
 
index 4b0ce3e7de9a4267088ab585e46232214b139879..ea88aa6bfc78e91c9d0442ab2b504e3ddabe1c56 100644 (file)
@@ -128,10 +128,10 @@ static inline int atomic_add_return(int i, atomic_t *v)
        unsigned long flags;
        int val;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        val = v->counter;
        v->counter = val += i;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        return val;
 }
@@ -141,10 +141,10 @@ static inline int atomic_sub_return(int i, atomic_t *v)
        unsigned long flags;
        int val;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        val = v->counter;
        v->counter = val -= i;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        return val;
 }
@@ -154,11 +154,11 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
        int ret;
        unsigned long flags;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        ret = v->counter;
        if (likely(ret == old))
                v->counter = new;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        return ret;
 }
@@ -167,9 +167,9 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 {
        unsigned long flags;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        *addr &= ~mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 }
 
 #endif /* __LINUX_ARM_ARCH__ */
index 0ac54b1a8bad7c0e8e7a7a3ec8f5063d6c972732..b41831b6432fb44f7967720b31e892e58005ed82 100644 (file)
@@ -37,9 +37,9 @@ static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *
 
        p += bit >> 5;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        *p |= mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 }
 
 static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
@@ -49,9 +49,9 @@ static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long
 
        p += bit >> 5;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        *p &= ~mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 }
 
 static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
@@ -61,9 +61,9 @@ static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned lon
 
        p += bit >> 5;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        *p ^= mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 }
 
 static inline int
@@ -75,10 +75,10 @@ ____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
 
        p += bit >> 5;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        res = *p;
        *p = res | mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        return res & mask;
 }
@@ -92,10 +92,10 @@ ____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
 
        p += bit >> 5;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        res = *p;
        *p = res & ~mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        return res & mask;
 }
@@ -109,10 +109,10 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 
        p += bit >> 5;
 
-       local_irq_save(flags);
+       raw_local_irq_save(flags);
        res = *p;
        *p = res ^ mask;
-       local_irq_restore(flags);
+       raw_local_irq_restore(flags);
 
        return res & mask;
 }
index e4a2569c636c688da3da32b7ff73fde1105a3fcd..f0845646aacb34a05332f7b7348cbbec436ed9f1 100644 (file)
@@ -25,7 +25,7 @@
 #undef _CACHE
 #undef MULTI_CACHE
 
-#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+#if defined(CONFIG_CPU_CACHE_V3)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
 # else
@@ -33,7 +33,7 @@
 # endif
 #endif
 
-#if defined(CONFIG_CPU_ARM720T)
+#if defined(CONFIG_CPU_CACHE_V4)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
 # else
 # endif
 #endif
 
-#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+#if defined(CONFIG_CPU_ARM940T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm940
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM946E)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm946
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4WB)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
 # else
diff --git a/include/asm-arm/flat.h b/include/asm-arm/flat.h
new file mode 100644 (file)
index 0000000..9669464
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/flat.h -- uClinux flat-format executables
+ */
+
+#ifndef __ARM_FLAT_H__
+#define __ARM_FLAT_H__
+
+#define        flat_stack_align(sp)                    /* nothing needed */
+#define        flat_argvp_envp_on_stack()              1
+#define        flat_old_ram_flag(flags)                (flags)
+#define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
+#define        flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp)
+#define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
+#define        flat_get_relocate_addr(rel)             (rel)
+
+#endif /* __ARM_FLAT_H__ */
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
new file mode 100644 (file)
index 0000000..1018a74
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * include/asm-arm/hardware/iop3xx.h
+ *
+ * Intel IOP32X and IOP33X register definitions
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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 __IOP3XX_H
+#define __IOP3XX_H
+
+/*
+ * IOP3XX GPIO handling
+ */
+#define GPIO_IN                        0
+#define GPIO_OUT               1
+#define GPIO_LOW               0
+#define GPIO_HIGH              1
+#define IOP3XX_GPIO_LINE(x)    (x)
+
+#ifndef __ASSEMBLY__
+extern void gpio_line_config(int line, int direction);
+extern int  gpio_line_get(int line);
+extern void gpio_line_set(int line, int value);
+#endif
+
+
+/*
+ * IOP3XX processor registers
+ */
+#define IOP3XX_PERIPHERAL_PHYS_BASE    0xffffe000
+#define IOP3XX_PERIPHERAL_VIRT_BASE    0xfeffe000
+#define IOP3XX_PERIPHERAL_SIZE         0x00002000
+#define IOP3XX_REG_ADDR(reg)           (IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
+
+/* Address Translation Unit  */
+#define IOP3XX_ATUVID          (volatile u16 *)IOP3XX_REG_ADDR(0x0100)
+#define IOP3XX_ATUDID          (volatile u16 *)IOP3XX_REG_ADDR(0x0102)
+#define IOP3XX_ATUCMD          (volatile u16 *)IOP3XX_REG_ADDR(0x0104)
+#define IOP3XX_ATUSR           (volatile u16 *)IOP3XX_REG_ADDR(0x0106)
+#define IOP3XX_ATURID          (volatile u8  *)IOP3XX_REG_ADDR(0x0108)
+#define IOP3XX_ATUCCR          (volatile u32 *)IOP3XX_REG_ADDR(0x0109)
+#define IOP3XX_ATUCLSR         (volatile u8  *)IOP3XX_REG_ADDR(0x010c)
+#define IOP3XX_ATULT           (volatile u8  *)IOP3XX_REG_ADDR(0x010d)
+#define IOP3XX_ATUHTR          (volatile u8  *)IOP3XX_REG_ADDR(0x010e)
+#define IOP3XX_ATUBIST         (volatile u8  *)IOP3XX_REG_ADDR(0x010f)
+#define IOP3XX_IABAR0          (volatile u32 *)IOP3XX_REG_ADDR(0x0110)
+#define IOP3XX_IAUBAR0         (volatile u32 *)IOP3XX_REG_ADDR(0x0114)
+#define IOP3XX_IABAR1          (volatile u32 *)IOP3XX_REG_ADDR(0x0118)
+#define IOP3XX_IAUBAR1         (volatile u32 *)IOP3XX_REG_ADDR(0x011c)
+#define IOP3XX_IABAR2          (volatile u32 *)IOP3XX_REG_ADDR(0x0120)
+#define IOP3XX_IAUBAR2         (volatile u32 *)IOP3XX_REG_ADDR(0x0124)
+#define IOP3XX_ASVIR           (volatile u16 *)IOP3XX_REG_ADDR(0x012c)
+#define IOP3XX_ASIR            (volatile u16 *)IOP3XX_REG_ADDR(0x012e)
+#define IOP3XX_ERBAR           (volatile u32 *)IOP3XX_REG_ADDR(0x0130)
+#define IOP3XX_ATUILR          (volatile u8  *)IOP3XX_REG_ADDR(0x013c)
+#define IOP3XX_ATUIPR          (volatile u8  *)IOP3XX_REG_ADDR(0x013d)
+#define IOP3XX_ATUMGNT         (volatile u8  *)IOP3XX_REG_ADDR(0x013e)
+#define IOP3XX_ATUMLAT         (volatile u8  *)IOP3XX_REG_ADDR(0x013f)
+#define IOP3XX_IALR0           (volatile u32 *)IOP3XX_REG_ADDR(0x0140)
+#define IOP3XX_IATVR0          (volatile u32 *)IOP3XX_REG_ADDR(0x0144)
+#define IOP3XX_ERLR            (volatile u32 *)IOP3XX_REG_ADDR(0x0148)
+#define IOP3XX_ERTVR           (volatile u32 *)IOP3XX_REG_ADDR(0x014c)
+#define IOP3XX_IALR1           (volatile u32 *)IOP3XX_REG_ADDR(0x0150)
+#define IOP3XX_IALR2           (volatile u32 *)IOP3XX_REG_ADDR(0x0154)
+#define IOP3XX_IATVR2          (volatile u32 *)IOP3XX_REG_ADDR(0x0158)
+#define IOP3XX_OIOWTVR         (volatile u32 *)IOP3XX_REG_ADDR(0x015c)
+#define IOP3XX_OMWTVR0         (volatile u32 *)IOP3XX_REG_ADDR(0x0160)
+#define IOP3XX_OUMWTVR0                (volatile u32 *)IOP3XX_REG_ADDR(0x0164)
+#define IOP3XX_OMWTVR1         (volatile u32 *)IOP3XX_REG_ADDR(0x0168)
+#define IOP3XX_OUMWTVR1                (volatile u32 *)IOP3XX_REG_ADDR(0x016c)
+#define IOP3XX_OUDWTVR         (volatile u32 *)IOP3XX_REG_ADDR(0x0178)
+#define IOP3XX_ATUCR           (volatile u32 *)IOP3XX_REG_ADDR(0x0180)
+#define IOP3XX_PCSR            (volatile u32 *)IOP3XX_REG_ADDR(0x0184)
+#define IOP3XX_ATUISR          (volatile u32 *)IOP3XX_REG_ADDR(0x0188)
+#define IOP3XX_ATUIMR          (volatile u32 *)IOP3XX_REG_ADDR(0x018c)
+#define IOP3XX_IABAR3          (volatile u32 *)IOP3XX_REG_ADDR(0x0190)
+#define IOP3XX_IAUBAR3         (volatile u32 *)IOP3XX_REG_ADDR(0x0194)
+#define IOP3XX_IALR3           (volatile u32 *)IOP3XX_REG_ADDR(0x0198)
+#define IOP3XX_IATVR3          (volatile u32 *)IOP3XX_REG_ADDR(0x019c)
+#define IOP3XX_OCCAR           (volatile u32 *)IOP3XX_REG_ADDR(0x01a4)
+#define IOP3XX_OCCDR           (volatile u32 *)IOP3XX_REG_ADDR(0x01ac)
+#define IOP3XX_PDSCR           (volatile u32 *)IOP3XX_REG_ADDR(0x01bc)
+#define IOP3XX_PMCAPID         (volatile u8  *)IOP3XX_REG_ADDR(0x01c0)
+#define IOP3XX_PMNEXT          (volatile u8  *)IOP3XX_REG_ADDR(0x01c1)
+#define IOP3XX_APMCR           (volatile u16 *)IOP3XX_REG_ADDR(0x01c2)
+#define IOP3XX_APMCSR          (volatile u16 *)IOP3XX_REG_ADDR(0x01c4)
+#define IOP3XX_PCIXCAPID       (volatile u8  *)IOP3XX_REG_ADDR(0x01e0)
+#define IOP3XX_PCIXNEXT                (volatile u8  *)IOP3XX_REG_ADDR(0x01e1)
+#define IOP3XX_PCIXCMD         (volatile u16 *)IOP3XX_REG_ADDR(0x01e2)
+#define IOP3XX_PCIXSR          (volatile u32 *)IOP3XX_REG_ADDR(0x01e4)
+#define IOP3XX_PCIIRSR         (volatile u32 *)IOP3XX_REG_ADDR(0x01ec)
+
+/* Messaging Unit  */
+#define IOP3XX_IMR0            (volatile u32 *)IOP3XX_REG_ADDR(0x0310)
+#define IOP3XX_IMR1            (volatile u32 *)IOP3XX_REG_ADDR(0x0314)
+#define IOP3XX_OMR0            (volatile u32 *)IOP3XX_REG_ADDR(0x0318)
+#define IOP3XX_OMR1            (volatile u32 *)IOP3XX_REG_ADDR(0x031c)
+#define IOP3XX_IDR             (volatile u32 *)IOP3XX_REG_ADDR(0x0320)
+#define IOP3XX_IISR            (volatile u32 *)IOP3XX_REG_ADDR(0x0324)
+#define IOP3XX_IIMR            (volatile u32 *)IOP3XX_REG_ADDR(0x0328)
+#define IOP3XX_ODR             (volatile u32 *)IOP3XX_REG_ADDR(0x032c)
+#define IOP3XX_OISR            (volatile u32 *)IOP3XX_REG_ADDR(0x0330)
+#define IOP3XX_OIMR            (volatile u32 *)IOP3XX_REG_ADDR(0x0334)
+#define IOP3XX_MUCR            (volatile u32 *)IOP3XX_REG_ADDR(0x0350)
+#define IOP3XX_QBAR            (volatile u32 *)IOP3XX_REG_ADDR(0x0354)
+#define IOP3XX_IFHPR           (volatile u32 *)IOP3XX_REG_ADDR(0x0360)
+#define IOP3XX_IFTPR           (volatile u32 *)IOP3XX_REG_ADDR(0x0364)
+#define IOP3XX_IPHPR           (volatile u32 *)IOP3XX_REG_ADDR(0x0368)
+#define IOP3XX_IPTPR           (volatile u32 *)IOP3XX_REG_ADDR(0x036c)
+#define IOP3XX_OFHPR           (volatile u32 *)IOP3XX_REG_ADDR(0x0370)
+#define IOP3XX_OFTPR           (volatile u32 *)IOP3XX_REG_ADDR(0x0374)
+#define IOP3XX_OPHPR           (volatile u32 *)IOP3XX_REG_ADDR(0x0378)
+#define IOP3XX_OPTPR           (volatile u32 *)IOP3XX_REG_ADDR(0x037c)
+#define IOP3XX_IAR             (volatile u32 *)IOP3XX_REG_ADDR(0x0380)
+
+/* DMA Controller  */
+#define IOP3XX_DMA0_CCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0400)
+#define IOP3XX_DMA0_CSR                (volatile u32 *)IOP3XX_REG_ADDR(0x0404)
+#define IOP3XX_DMA0_DAR                (volatile u32 *)IOP3XX_REG_ADDR(0x040c)
+#define IOP3XX_DMA0_NDAR       (volatile u32 *)IOP3XX_REG_ADDR(0x0410)
+#define IOP3XX_DMA0_PADR       (volatile u32 *)IOP3XX_REG_ADDR(0x0414)
+#define IOP3XX_DMA0_PUADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0418)
+#define IOP3XX_DMA0_LADR       (volatile u32 *)IOP3XX_REG_ADDR(0x041c)
+#define IOP3XX_DMA0_BCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0420)
+#define IOP3XX_DMA0_DCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0424)
+#define IOP3XX_DMA1_CCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0440)
+#define IOP3XX_DMA1_CSR                (volatile u32 *)IOP3XX_REG_ADDR(0x0444)
+#define IOP3XX_DMA1_DAR                (volatile u32 *)IOP3XX_REG_ADDR(0x044c)
+#define IOP3XX_DMA1_NDAR       (volatile u32 *)IOP3XX_REG_ADDR(0x0450)
+#define IOP3XX_DMA1_PADR       (volatile u32 *)IOP3XX_REG_ADDR(0x0454)
+#define IOP3XX_DMA1_PUADR      (volatile u32 *)IOP3XX_REG_ADDR(0x0458)
+#define IOP3XX_DMA1_LADR       (volatile u32 *)IOP3XX_REG_ADDR(0x045c)
+#define IOP3XX_DMA1_BCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0460)
+#define IOP3XX_DMA1_DCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0464)
+
+/* Peripheral bus interface  */
+#define IOP3XX_PBCR            (volatile u32 *)IOP3XX_REG_ADDR(0x0680)
+#define IOP3XX_PBISR           (volatile u32 *)IOP3XX_REG_ADDR(0x0684)
+#define IOP3XX_PBBAR0          (volatile u32 *)IOP3XX_REG_ADDR(0x0688)
+#define IOP3XX_PBLR0           (volatile u32 *)IOP3XX_REG_ADDR(0x068c)
+#define IOP3XX_PBBAR1          (volatile u32 *)IOP3XX_REG_ADDR(0x0690)
+#define IOP3XX_PBLR1           (volatile u32 *)IOP3XX_REG_ADDR(0x0694)
+#define IOP3XX_PBBAR2          (volatile u32 *)IOP3XX_REG_ADDR(0x0698)
+#define IOP3XX_PBLR2           (volatile u32 *)IOP3XX_REG_ADDR(0x069c)
+#define IOP3XX_PBBAR3          (volatile u32 *)IOP3XX_REG_ADDR(0x06a0)
+#define IOP3XX_PBLR3           (volatile u32 *)IOP3XX_REG_ADDR(0x06a4)
+#define IOP3XX_PBBAR4          (volatile u32 *)IOP3XX_REG_ADDR(0x06a8)
+#define IOP3XX_PBLR4           (volatile u32 *)IOP3XX_REG_ADDR(0x06ac)
+#define IOP3XX_PBBAR5          (volatile u32 *)IOP3XX_REG_ADDR(0x06b0)
+#define IOP3XX_PBLR5           (volatile u32 *)IOP3XX_REG_ADDR(0x06b4)
+#define IOP3XX_PMBR0           (volatile u32 *)IOP3XX_REG_ADDR(0x06c0)
+#define IOP3XX_PMBR1           (volatile u32 *)IOP3XX_REG_ADDR(0x06e0)
+#define IOP3XX_PMBR2           (volatile u32 *)IOP3XX_REG_ADDR(0x06e4)
+
+/* Peripheral performance monitoring unit  */
+#define IOP3XX_GTMR            (volatile u32 *)IOP3XX_REG_ADDR(0x0700)
+#define IOP3XX_ESR             (volatile u32 *)IOP3XX_REG_ADDR(0x0704)
+#define IOP3XX_EMISR           (volatile u32 *)IOP3XX_REG_ADDR(0x0708)
+#define IOP3XX_GTSR            (volatile u32 *)IOP3XX_REG_ADDR(0x0710)
+/* PERCR0 DOESN'T EXIST - index from 1! */
+#define IOP3XX_PERCR0          (volatile u32 *)IOP3XX_REG_ADDR(0x0710)
+
+/* General Purpose I/O  */
+#define IOP3XX_GPOE            (volatile u32 *)IOP3XX_GPIO_REG(0x0004)
+#define IOP3XX_GPID            (volatile u32 *)IOP3XX_GPIO_REG(0x0008)
+#define IOP3XX_GPOD            (volatile u32 *)IOP3XX_GPIO_REG(0x000c)
+
+/* Timers  */
+#define IOP3XX_TU_TMR0         (volatile u32 *)IOP3XX_TIMER_REG(0x0000)
+#define IOP3XX_TU_TMR1         (volatile u32 *)IOP3XX_TIMER_REG(0x0004)
+#define IOP3XX_TU_TCR0         (volatile u32 *)IOP3XX_TIMER_REG(0x0008)
+#define IOP3XX_TU_TCR1         (volatile u32 *)IOP3XX_TIMER_REG(0x000c)
+#define IOP3XX_TU_TRR0         (volatile u32 *)IOP3XX_TIMER_REG(0x0010)
+#define IOP3XX_TU_TRR1         (volatile u32 *)IOP3XX_TIMER_REG(0x0014)
+#define IOP3XX_TU_TISR         (volatile u32 *)IOP3XX_TIMER_REG(0x0018)
+#define IOP3XX_TU_WDTCR                (volatile u32 *)IOP3XX_TIMER_REG(0x001c)
+#define IOP3XX_TMR_TC          0x01
+#define IOP3XX_TMR_EN          0x02
+#define IOP3XX_TMR_RELOAD      0x04
+#define IOP3XX_TMR_PRIVILEGED  0x09
+#define IOP3XX_TMR_RATIO_1_1   0x00
+#define IOP3XX_TMR_RATIO_4_1   0x10
+#define IOP3XX_TMR_RATIO_8_1   0x20
+#define IOP3XX_TMR_RATIO_16_1  0x30
+
+/* Application accelerator unit  */
+#define IOP3XX_AAU_ACR         (volatile u32 *)IOP3XX_REG_ADDR(0x0800)
+#define IOP3XX_AAU_ASR         (volatile u32 *)IOP3XX_REG_ADDR(0x0804)
+#define IOP3XX_AAU_ADAR                (volatile u32 *)IOP3XX_REG_ADDR(0x0808)
+#define IOP3XX_AAU_ANDAR       (volatile u32 *)IOP3XX_REG_ADDR(0x080c)
+#define IOP3XX_AAU_SAR1                (volatile u32 *)IOP3XX_REG_ADDR(0x0810)
+#define IOP3XX_AAU_SAR2                (volatile u32 *)IOP3XX_REG_ADDR(0x0814)
+#define IOP3XX_AAU_SAR3                (volatile u32 *)IOP3XX_REG_ADDR(0x0818)
+#define IOP3XX_AAU_SAR4                (volatile u32 *)IOP3XX_REG_ADDR(0x081c)
+#define IOP3XX_AAU_DAR         (volatile u32 *)IOP3XX_REG_ADDR(0x0820)
+#define IOP3XX_AAU_ABCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0824)
+#define IOP3XX_AAU_ADCR                (volatile u32 *)IOP3XX_REG_ADDR(0x0828)
+#define IOP3XX_AAU_SAR5                (volatile u32 *)IOP3XX_REG_ADDR(0x082c)
+#define IOP3XX_AAU_SAR6                (volatile u32 *)IOP3XX_REG_ADDR(0x0830)
+#define IOP3XX_AAU_SAR7                (volatile u32 *)IOP3XX_REG_ADDR(0x0834)
+#define IOP3XX_AAU_SAR8                (volatile u32 *)IOP3XX_REG_ADDR(0x0838)
+#define IOP3XX_AAU_EDCR0       (volatile u32 *)IOP3XX_REG_ADDR(0x083c)
+#define IOP3XX_AAU_SAR9                (volatile u32 *)IOP3XX_REG_ADDR(0x0840)
+#define IOP3XX_AAU_SAR10       (volatile u32 *)IOP3XX_REG_ADDR(0x0844)
+#define IOP3XX_AAU_SAR11       (volatile u32 *)IOP3XX_REG_ADDR(0x0848)
+#define IOP3XX_AAU_SAR12       (volatile u32 *)IOP3XX_REG_ADDR(0x084c)
+#define IOP3XX_AAU_SAR13       (volatile u32 *)IOP3XX_REG_ADDR(0x0850)
+#define IOP3XX_AAU_SAR14       (volatile u32 *)IOP3XX_REG_ADDR(0x0854)
+#define IOP3XX_AAU_SAR15       (volatile u32 *)IOP3XX_REG_ADDR(0x0858)
+#define IOP3XX_AAU_SAR16       (volatile u32 *)IOP3XX_REG_ADDR(0x085c)
+#define IOP3XX_AAU_EDCR1       (volatile u32 *)IOP3XX_REG_ADDR(0x0860)
+#define IOP3XX_AAU_SAR17       (volatile u32 *)IOP3XX_REG_ADDR(0x0864)
+#define IOP3XX_AAU_SAR18       (volatile u32 *)IOP3XX_REG_ADDR(0x0868)
+#define IOP3XX_AAU_SAR19       (volatile u32 *)IOP3XX_REG_ADDR(0x086c)
+#define IOP3XX_AAU_SAR20       (volatile u32 *)IOP3XX_REG_ADDR(0x0870)
+#define IOP3XX_AAU_SAR21       (volatile u32 *)IOP3XX_REG_ADDR(0x0874)
+#define IOP3XX_AAU_SAR22       (volatile u32 *)IOP3XX_REG_ADDR(0x0878)
+#define IOP3XX_AAU_SAR23       (volatile u32 *)IOP3XX_REG_ADDR(0x087c)
+#define IOP3XX_AAU_SAR24       (volatile u32 *)IOP3XX_REG_ADDR(0x0880)
+#define IOP3XX_AAU_EDCR2       (volatile u32 *)IOP3XX_REG_ADDR(0x0884)
+#define IOP3XX_AAU_SAR25       (volatile u32 *)IOP3XX_REG_ADDR(0x0888)
+#define IOP3XX_AAU_SAR26       (volatile u32 *)IOP3XX_REG_ADDR(0x088c)
+#define IOP3XX_AAU_SAR27       (volatile u32 *)IOP3XX_REG_ADDR(0x0890)
+#define IOP3XX_AAU_SAR28       (volatile u32 *)IOP3XX_REG_ADDR(0x0894)
+#define IOP3XX_AAU_SAR29       (volatile u32 *)IOP3XX_REG_ADDR(0x0898)
+#define IOP3XX_AAU_SAR30       (volatile u32 *)IOP3XX_REG_ADDR(0x089c)
+#define IOP3XX_AAU_SAR31       (volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
+#define IOP3XX_AAU_SAR32       (volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
+
+/* I2C bus interface unit  */
+#define IOP3XX_ICR0            (volatile u32 *)IOP3XX_REG_ADDR(0x1680)
+#define IOP3XX_ISR0            (volatile u32 *)IOP3XX_REG_ADDR(0x1684)
+#define IOP3XX_ISAR0           (volatile u32 *)IOP3XX_REG_ADDR(0x1688)
+#define IOP3XX_IDBR0           (volatile u32 *)IOP3XX_REG_ADDR(0x168c)
+#define IOP3XX_IBMR0           (volatile u32 *)IOP3XX_REG_ADDR(0x1694)
+#define IOP3XX_ICR1            (volatile u32 *)IOP3XX_REG_ADDR(0x16a0)
+#define IOP3XX_ISR1            (volatile u32 *)IOP3XX_REG_ADDR(0x16a4)
+#define IOP3XX_ISAR1           (volatile u32 *)IOP3XX_REG_ADDR(0x16a8)
+#define IOP3XX_IDBR1           (volatile u32 *)IOP3XX_REG_ADDR(0x16ac)
+#define IOP3XX_IBMR1           (volatile u32 *)IOP3XX_REG_ADDR(0x16b4)
+
+
+/*
+ * IOP3XX I/O and Mem space regions for PCI autoconfiguration
+ */
+#define IOP3XX_PCI_MEM_WINDOW_SIZE     0x04000000
+#define IOP3XX_PCI_LOWER_MEM_PA                0x80000000
+#define IOP3XX_PCI_LOWER_MEM_BA                (*IOP3XX_OMWTVR0)
+
+#define IOP3XX_PCI_IO_WINDOW_SIZE      0x00010000
+#define IOP3XX_PCI_LOWER_IO_PA         0x90000000
+#define IOP3XX_PCI_LOWER_IO_VA         0xfe000000
+#define IOP3XX_PCI_LOWER_IO_BA         (*IOP3XX_OIOWTVR)
+
+
+#ifndef __ASSEMBLY__
+void iop3xx_map_io(void);
+void iop3xx_init_time(unsigned long);
+unsigned long iop3xx_gettimeoffset(void);
+
+extern struct platform_device iop3xx_i2c0_device;
+extern struct platform_device iop3xx_i2c1_device;
+
+extern inline void iop3xx_cp6_enable(void)
+{
+       u32 temp;
+
+       asm volatile (
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "orr    %0, %0, #(1 << 6)\n\t"
+               "mcr    p15, 0, %0, c15, c1, 0\n\t"
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "mov    %0, %0\n\t"
+               "sub    pc, pc, #4\n\t"
+               : "=r" (temp) );
+}
+
+extern inline void iop3xx_cp6_disable(void)
+{
+       u32 temp;
+
+       asm volatile (
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "bic    %0, %0, #(1 << 6)\n\t"
+               "mcr    p15, 0, %0, c15, c1, 0\n\t"
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "mov    %0, %0\n\t"
+               "sub    pc, pc, #4\n\t"
+               : "=r" (temp) );
+}
+#endif
+
+
+#endif
index 22dfb1737768537c45cb73df860b7d4f22d2621b..adab77780ed3afe2522c1b2cb34fb7ae05b222d4 100644 (file)
 #define        LOCOMO_DAC_SDAOEB       0x01    /* SDA pin output data       */
 
 /* SPI interface */
-#define LOCOMO_SPIMD   0x60            /* SPI mode setting */
-#define LOCOMO_SPICT   0x64            /* SPI mode control */
-#define LOCOMO_SPIST   0x68            /* SPI status */
-#define LOCOMO_SPIIS   0x70            /* SPI interrupt status */
-#define LOCOMO_SPIWE   0x74            /* SPI interrupt status write enable */
-#define LOCOMO_SPIIE   0x78            /* SPI interrupt enable */
-#define LOCOMO_SPIIR   0x7c            /* SPI interrupt request */
-#define LOCOMO_SPITD   0x80            /* SPI transfer data write */
-#define LOCOMO_SPIRD   0x84            /* SPI receive data read */
-#define LOCOMO_SPITS   0x88            /* SPI transfer data shift */
-#define LOCOMO_SPIRS   0x8C            /* SPI receive data shift */
+#define LOCOMO_SPI     0x60
+#define LOCOMO_SPIMD   0x00            /* SPI mode setting */
+#define LOCOMO_SPICT   0x04            /* SPI mode control */
+#define LOCOMO_SPIST   0x08            /* SPI status */
+#define LOCOMO_SPIIS   0x10            /* SPI interrupt status */
+#define LOCOMO_SPIWE   0x14            /* SPI interrupt status write enable */
+#define LOCOMO_SPIIE   0x18            /* SPI interrupt enable */
+#define LOCOMO_SPIIR   0x1c            /* SPI interrupt request */
+#define LOCOMO_SPITD   0x20            /* SPI transfer data write */
+#define LOCOMO_SPIRD   0x24            /* SPI receive data read */
+#define LOCOMO_SPITS   0x28            /* SPI transfer data shift */
+#define LOCOMO_SPIRS   0x2C            /* SPI receive data shift */
 #define        LOCOMO_SPI_TEND (1 << 3)        /* Transfer end bit */
 #define        LOCOMO_SPI_OVRN (1 << 2)        /* Over Run bit */
 #define        LOCOMO_SPI_RFW  (1 << 1)        /* write buffer bit */
@@ -161,6 +162,7 @@ extern struct bus_type locomo_bus_type;
 #define LOCOMO_DEVID_AUDIO     3
 #define LOCOMO_DEVID_LED       4
 #define LOCOMO_DEVID_UART      5
+#define LOCOMO_DEVID_SPI               6
 
 struct locomo_dev {
        struct device   dev;
@@ -197,10 +199,11 @@ int locomo_driver_register(struct locomo_driver *);
 void locomo_driver_unregister(struct locomo_driver *);
 
 /* GPIO control functions */
-void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir);
-unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits);
-unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits);
-void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set);
+void locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir);
+int locomo_gpio_read_level(struct device *dev, unsigned int bits);
+int locomo_gpio_read_output(struct device *dev, unsigned int bits);
+void locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set);
+
 
 /* M62332 control function */
 void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel);
index ecf15b83956f88ce1b09ef99943ad95501de7263..a836e76a14f7de1b8b8c8da0215304de6ad8801a 100644 (file)
@@ -25,6 +25,7 @@ struct sharpsl_charger_machinfo {
        void (*measure_temp)(int);
        void (*presuspend)(void);
        void (*postsuspend)(void);
+       void (*earlyresume)(void);
        unsigned long (*read_devdata)(int);
 #define SHARPSL_BATT_VOLT       1
 #define SHARPSL_BATT_TEMP       2
index bf7b9dea30f1f9b0ae7f16dfbc1cd752e5c5327c..8076a85c367541479c6e6aaa4dd54e358cb3ba6f 100644 (file)
@@ -280,6 +280,10 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
 #define BIOVEC_MERGEABLE(vec1, vec2)   \
        ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
 
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
diff --git a/include/asm-arm/irqflags.h b/include/asm-arm/irqflags.h
new file mode 100644 (file)
index 0000000..6d09974
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef __ASM_ARM_IRQFLAGS_H
+#define __ASM_ARM_IRQFLAGS_H
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+
+/*
+ * CPU interrupt mask handling.
+ */
+#if __LINUX_ARM_ARCH__ >= 6
+
+#define raw_local_irq_save(x)                                  \
+       ({                                                      \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ local_irq_save\n"     \
+       "cpsid  i"                                              \
+       : "=r" (x) : : "memory", "cc");                         \
+       })
+
+#define raw_local_irq_enable()  __asm__("cpsie i       @ __sti" : : : "memory", "cc")
+#define raw_local_irq_disable() __asm__("cpsid i       @ __cli" : : : "memory", "cc")
+#define local_fiq_enable()  __asm__("cpsie f   @ __stf" : : : "memory", "cc")
+#define local_fiq_disable() __asm__("cpsid f   @ __clf" : : : "memory", "cc")
+
+#else
+
+/*
+ * Save the current interrupt enable state & disable IRQs
+ */
+#define raw_local_irq_save(x)                                  \
+       ({                                                      \
+               unsigned long temp;                             \
+               (void) (&temp == &x);                           \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ local_irq_save\n"     \
+"      orr     %1, %0, #128\n"                                 \
+"      msr     cpsr_c, %1"                                     \
+       : "=r" (x), "=r" (temp)                                 \
+       :                                                       \
+       : "memory", "cc");                                      \
+       })
+       
+/*
+ * Enable IRQs
+ */
+#define raw_local_irq_enable()                                 \
+       ({                                                      \
+               unsigned long temp;                             \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ local_irq_enable\n"   \
+"      bic     %0, %0, #128\n"                                 \
+"      msr     cpsr_c, %0"                                     \
+       : "=r" (temp)                                           \
+       :                                                       \
+       : "memory", "cc");                                      \
+       })
+
+/*
+ * Disable IRQs
+ */
+#define raw_local_irq_disable()                                        \
+       ({                                                      \
+               unsigned long temp;                             \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ local_irq_disable\n"  \
+"      orr     %0, %0, #128\n"                                 \
+"      msr     cpsr_c, %0"                                     \
+       : "=r" (temp)                                           \
+       :                                                       \
+       : "memory", "cc");                                      \
+       })
+
+/*
+ * Enable FIQs
+ */
+#define local_fiq_enable()                                     \
+       ({                                                      \
+               unsigned long temp;                             \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ stf\n"                \
+"      bic     %0, %0, #64\n"                                  \
+"      msr     cpsr_c, %0"                                     \
+       : "=r" (temp)                                           \
+       :                                                       \
+       : "memory", "cc");                                      \
+       })
+
+/*
+ * Disable FIQs
+ */
+#define local_fiq_disable()                                    \
+       ({                                                      \
+               unsigned long temp;                             \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ clf\n"                \
+"      orr     %0, %0, #64\n"                                  \
+"      msr     cpsr_c, %0"                                     \
+       : "=r" (temp)                                           \
+       :                                                       \
+       : "memory", "cc");                                      \
+       })
+
+#endif
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define raw_local_save_flags(x)                                        \
+       ({                                                      \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ local_save_flags"     \
+       : "=r" (x) : : "memory", "cc");                         \
+       })
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+#define raw_local_irq_restore(x)                               \
+       __asm__ __volatile__(                                   \
+       "msr    cpsr_c, %0              @ local_irq_restore\n"  \
+       :                                                       \
+       : "r" (x)                                               \
+       : "memory", "cc")
+
+#define raw_irqs_disabled_flags(flags) \
+({                                     \
+       (int)((flags) & PSR_I_BIT);     \
+})
+
+#endif
+#endif
index 923e0ca66200c1f0a592ff470528d4c524a15583..24621c49a0c73abaa778a9b1d60801c23f409bc8 100644 (file)
@@ -52,13 +52,9 @@ void pci_common_init(struct hw_pci *);
 /*
  * PCI controllers
  */
-extern int iop321_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
-extern void iop321_init(void);
-
-extern int iop331_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
-extern void iop331_init(void);
+extern int iop3xx_pci_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *);
+extern void iop3xx_pci_preinit(void);
 
 extern int dc21285_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
index dee0bc336fe8393ae8e13b4079a1a3f3eab6f328..1eb93f5c0d6cf921c6bfc3cf211bf84b654687c6 100644 (file)
@@ -38,7 +38,9 @@ struct sys_timer {
        void                    (*init)(void);
        void                    (*suspend)(void);
        void                    (*resume)(void);
+#ifndef CONFIG_GENERIC_TIME
        unsigned long           (*offset)(void);
+#endif
 
 #ifdef CONFIG_NO_IDLE_HZ
        struct dyn_tick_timer   *dyn_tick;
index 02bd3ee935b07e0c88c2f865aa6c4510d814c4dc..7e85db77d99b12f635514a7c84e9b8c713064af4 100644 (file)
@@ -174,9 +174,6 @@ typedef unsigned long pgprot_t;
 
 #endif /* STRICT_MM_TYPECHECKS */
 
-/* the upper-most page table pointer */
-extern pmd_t *top_pmd;
-
 #endif /* CONFIG_MMU */
 
 #include <asm/memory.h>
index 4d10d319fa34d1c5d4aade4c2eddbeaa5391e31f..ed8cb5963e99cde381f94171b1f59a98aa1805d8 100644 (file)
@@ -135,6 +135,13 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #define FIRST_USER_PGD_NR      1
 #define USER_PTRS_PER_PGD      ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
 
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT          20
+#define SECTION_SIZE           (1UL << SECTION_SHIFT)
+#define SECTION_MASK           (~(SECTION_SIZE-1))
+
 /*
  * ARMv6 supersection address mask and size definitions.
  */
index 1bde92cdaebd01739c3db199a438f47a7ffd0493..ea7e54c319be535ed1777640f0e1740b36c748a5 100644 (file)
 #   define CPU_NAME cpu_arm6
 #  endif
 # endif
+# ifdef CONFIG_CPU_ARM7TDMI
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm7tdmi
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM710
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
 #   define CPU_NAME cpu_arm720
 #  endif
 # endif
+# ifdef CONFIG_CPU_ARM740T
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm740
+#  endif
+# endif
+# ifdef CONFIG_CPU_ARM9TDMI
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm9tdmi
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM920T
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
 #   define CPU_NAME cpu_arm926
 #  endif
 # endif
+# ifdef CONFIG_CPU_ARM940T
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm940
+#  endif
+# endif
+# ifdef CONFIG_CPU_ARM946E
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm946
+#  endif
+# endif
 # ifdef CONFIG_CPU_SA110
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
index ea3ed24652333e8dbcc3020074a626050895ed84..aa4b5782f0c9723cf1d604ca7756a09bea8e6829 100644 (file)
@@ -194,13 +194,15 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn }
 # define NR_BANKS 8
 #endif
 
+struct membank {
+       unsigned long start;
+       unsigned long size;
+       int           node;
+};
+
 struct meminfo {
        int nr_banks;
-       struct {
-               unsigned long start;
-               unsigned long size;
-               int           node;
-       } bank[NR_BANKS];
+       struct membank bank[NR_BANKS];
 };
 
 /*
index 01b7c26a30386951905de5ae46d3bc31fdde30cd..861092fbaa53283953bd41c9dbb6e840bb42ff02 100644 (file)
@@ -218,4 +218,8 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
 /* read_can_lock - would read_trylock() succeed? */
 #define __raw_read_can_lock(x)         ((x)->lock < 0x80000000)
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SPINLOCK_H */
index 0947cbf9b69a3394bd3cba0803a112ece0c183c1..f05fbe31576cbeabb2b6d717698d7cebfdc63b4e 100644 (file)
@@ -46,6 +46,7 @@
 #define CPUID_TCM      2
 #define CPUID_TLBTYPE  3
 
+#ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)                                                        \
        ({                                                              \
                unsigned int __val;                                     \
@@ -55,6 +56,9 @@
                    : "cc");                                            \
                __val;                                                  \
        })
+#else
+#define read_cpuid(reg) (processor_id)
+#endif
 
 /*
  * This is used to ensure the compiler did actually allocate the register we
@@ -207,130 +211,7 @@ static inline void sched_cacheflush(void)
 {
 }
 
-/*
- * CPU interrupt mask handling.
- */
-#if __LINUX_ARM_ARCH__ >= 6
-
-#define local_irq_save(x)                                      \
-       ({                                                      \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_save\n"     \
-       "cpsid  i"                                              \
-       : "=r" (x) : : "memory", "cc");                         \
-       })
-
-#define local_irq_enable()  __asm__("cpsie i   @ __sti" : : : "memory", "cc")
-#define local_irq_disable() __asm__("cpsid i   @ __cli" : : : "memory", "cc")
-#define local_fiq_enable()  __asm__("cpsie f   @ __stf" : : : "memory", "cc")
-#define local_fiq_disable() __asm__("cpsid f   @ __clf" : : : "memory", "cc")
-
-#else
-
-/*
- * Save the current interrupt enable state & disable IRQs
- */
-#define local_irq_save(x)                                      \
-       ({                                                      \
-               unsigned long temp;                             \
-               (void) (&temp == &x);                           \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_save\n"     \
-"      orr     %1, %0, #128\n"                                 \
-"      msr     cpsr_c, %1"                                     \
-       : "=r" (x), "=r" (temp)                                 \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
-       
-/*
- * Enable IRQs
- */
-#define local_irq_enable()                                     \
-       ({                                                      \
-               unsigned long temp;                             \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_enable\n"   \
-"      bic     %0, %0, #128\n"                                 \
-"      msr     cpsr_c, %0"                                     \
-       : "=r" (temp)                                           \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
-
-/*
- * Disable IRQs
- */
-#define local_irq_disable()                                    \
-       ({                                                      \
-               unsigned long temp;                             \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_irq_disable\n"  \
-"      orr     %0, %0, #128\n"                                 \
-"      msr     cpsr_c, %0"                                     \
-       : "=r" (temp)                                           \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
-
-/*
- * Enable FIQs
- */
-#define local_fiq_enable()                                     \
-       ({                                                      \
-               unsigned long temp;                             \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ stf\n"                \
-"      bic     %0, %0, #64\n"                                  \
-"      msr     cpsr_c, %0"                                     \
-       : "=r" (temp)                                           \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
-
-/*
- * Disable FIQs
- */
-#define local_fiq_disable()                                    \
-       ({                                                      \
-               unsigned long temp;                             \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ clf\n"                \
-"      orr     %0, %0, #64\n"                                  \
-"      msr     cpsr_c, %0"                                     \
-       : "=r" (temp)                                           \
-       :                                                       \
-       : "memory", "cc");                                      \
-       })
-
-#endif
-
-/*
- * Save the current interrupt enable state.
- */
-#define local_save_flags(x)                                    \
-       ({                                                      \
-       __asm__ __volatile__(                                   \
-       "mrs    %0, cpsr                @ local_save_flags"     \
-       : "=r" (x) : : "memory", "cc");                         \
-       })
-
-/*
- * restore saved IRQ & FIQ state
- */
-#define local_irq_restore(x)                                   \
-       __asm__ __volatile__(                                   \
-       "msr    cpsr_c, %0              @ local_irq_restore\n"  \
-       :                                                       \
-       : "r" (x)                                               \
-       : "memory", "cc")
-
-#define irqs_disabled()                        \
-({                                     \
-       unsigned long flags;            \
-       local_save_flags(flags);        \
-       (int)(flags & PSR_I_BIT);       \
-})
+#include <linux/irqflags.h>
 
 #ifdef CONFIG_SMP
 
@@ -405,17 +286,17 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
 #error SMP is not supported on this platform
 #endif
        case 1:
-               local_irq_save(flags);
+               raw_local_irq_save(flags);
                ret = *(volatile unsigned char *)ptr;
                *(volatile unsigned char *)ptr = x;
-               local_irq_restore(flags);
+               raw_local_irq_restore(flags);
                break;
 
        case 4:
-               local_irq_save(flags);
+               raw_local_irq_save(flags);
                ret = *(volatile unsigned long *)ptr;
                *(volatile unsigned long *)ptr = x;
-               local_irq_restore(flags);
+               raw_local_irq_restore(flags);
                break;
 #else
        case 1:
diff --git a/include/asm-arm/timeofday.h b/include/asm-arm/timeofday.h
new file mode 100644 (file)
index 0000000..27254bd
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _ASM_ARM_TIMEOFDAY_H
+#define _ASM_ARM_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
index d97fc76189a5e5c95570424a19e0e0f5790a8fea..cd10a0b5f8ae77510234c15c9295f80944f59f4a 100644 (file)
@@ -247,16 +247,16 @@ static inline void local_flush_tlb_all(void)
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_WB))
-               asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 
        if (tlb_flag(TLB_V3_FULL))
-               asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
+               asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
        if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL))
-               asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
+               asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
        if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL))
-               asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
+               asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
        if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
-               asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+               asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 }
 
 static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -266,25 +266,25 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_WB))
-               asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 
        if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
                if (tlb_flag(TLB_V3_FULL))
-                       asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
+                       asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
                if (tlb_flag(TLB_V4_U_FULL))
-                       asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
+                       asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
                if (tlb_flag(TLB_V4_D_FULL))
-                       asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
+                       asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
                if (tlb_flag(TLB_V4_I_FULL))
-                       asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+                       asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
        }
 
        if (tlb_flag(TLB_V6_U_ASID))
-               asm("mcr%? p15, 0, %0, c8, c7, 2" : : "r" (asid));
+               asm("mcr p15, 0, %0, c8, c7, 2" : : "r" (asid) : "cc");
        if (tlb_flag(TLB_V6_D_ASID))
-               asm("mcr%? p15, 0, %0, c8, c6, 2" : : "r" (asid));
+               asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
        if (tlb_flag(TLB_V6_I_ASID))
-               asm("mcr%? p15, 0, %0, c8, c5, 2" : : "r" (asid));
+               asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
 }
 
 static inline void
@@ -296,27 +296,27 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
        uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
 
        if (tlb_flag(TLB_WB))
-               asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero));
 
        if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
                if (tlb_flag(TLB_V3_PAGE))
-                       asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (uaddr));
+                       asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (uaddr) : "cc");
                if (tlb_flag(TLB_V4_U_PAGE))
-                       asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr));
+                       asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
                if (tlb_flag(TLB_V4_D_PAGE))
-                       asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr));
+                       asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
                if (tlb_flag(TLB_V4_I_PAGE))
-                       asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
+                       asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
                if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
-                       asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+                       asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
        }
 
        if (tlb_flag(TLB_V6_U_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr));
+               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
        if (tlb_flag(TLB_V6_D_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr));
+               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
        if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
+               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
 }
 
 static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -327,31 +327,31 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        kaddr &= PAGE_MASK;
 
        if (tlb_flag(TLB_WB))
-               asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 
        if (tlb_flag(TLB_V3_PAGE))
-               asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
        if (tlb_flag(TLB_V4_U_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
        if (tlb_flag(TLB_V4_D_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
        if (tlb_flag(TLB_V4_I_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
        if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
-               asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+               asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 
        if (tlb_flag(TLB_V6_U_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
        if (tlb_flag(TLB_V6_D_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
        if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
+               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
 
        /* The ARM ARM states that the completion of a TLB maintenance
         * operation is only guaranteed by a DSB instruction
         */
        if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE))
-               asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+               asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
 }
 
 /*
@@ -373,11 +373,11 @@ static inline void flush_pmd_entry(pmd_t *pmd)
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_DCLEAN))
-               asm("mcr%?      p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd));
+               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
+                       : : "r" (pmd) : "cc");
        if (tlb_flag(TLB_WB))
-               asm("mcr%?      p15, 0, %0, c7, c10, 4  @ flush_pmd"
-                       : : "r" (zero));
+               asm("mcr        p15, 0, %0, c7, c10, 4  @ flush_pmd"
+                       : : "r" (zero) : "cc");
 }
 
 static inline void clean_pmd_entry(pmd_t *pmd)
@@ -385,8 +385,8 @@ static inline void clean_pmd_entry(pmd_t *pmd)
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
        if (tlb_flag(TLB_DCLEAN))
-               asm("mcr%?      p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd));
+               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
+                       : : "r" (pmd) : "cc");
 }
 
 #undef tlb_flag
index 1b39c2f322c9a5b332352512a6ff81ffe0f25a5e..795b9e5b9e6ab88e07641189eaba1c3110a7cba4 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <asm/types.h>
 
-extern int __bug_unaligned_x(void *ptr);
+extern int __bug_unaligned_x(const void *ptr);
 
 /*
  * What is the most efficient way of loading/storing an unaligned value?
@@ -51,44 +51,32 @@ extern int __bug_unaligned_x(void *ptr);
 #define __get_unaligned_4_be(__p)                                      \
        (__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
 
-#define __get_unaligned_le(ptr)                                        \
-       ({                                                      \
-               __typeof__(*(ptr)) __v;                         \
-               __u8 *__p = (__u8 *)(ptr);                      \
-               switch (sizeof(*(ptr))) {                       \
-               case 1: __v = *(ptr);                   break;  \
-               case 2: __v = __get_unaligned_2_le(__p);        break;  \
-               case 4: __v = __get_unaligned_4_le(__p);        break;  \
-               case 8: {                                       \
-                               unsigned int __v1, __v2;        \
-                               __v2 = __get_unaligned_4_le((__p+4)); \
-                               __v1 = __get_unaligned_4_le(__p);       \
-                               __v = ((unsigned long long)__v2 << 32 | __v1);  \
-                       }                                       \
-                       break;                                  \
-               default: __v = __bug_unaligned_x(__p);  break;  \
-               }                                               \
-               __v;                                            \
+#define __get_unaligned_8_le(__p)                                      \
+       ((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 |      \
+               __get_unaligned_4_le(__p))
+
+#define __get_unaligned_8_be(__p)                                      \
+       ((unsigned long long)__get_unaligned_4_be(__p) << 32 |          \
+               __get_unaligned_4_be((__p+4)))
+
+#define __get_unaligned_le(ptr)                                                \
+       ({                                                              \
+               const __u8 *__p = (const __u8 *)(ptr);                  \
+               __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,        \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_le(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_le(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_le(__p), \
+                   (void)__bug_unaligned_x(__p)))));                   \
        })
 
-#define __get_unaligned_be(ptr)                                        \
-       ({                                                      \
-               __typeof__(*(ptr)) __v;                         \
-               __u8 *__p = (__u8 *)(ptr);                      \
-               switch (sizeof(*(ptr))) {                       \
-               case 1: __v = *(ptr);                   break;  \
-               case 2: __v = __get_unaligned_2_be(__p);        break;  \
-               case 4: __v = __get_unaligned_4_be(__p);        break;  \
-               case 8: {                                       \
-                               unsigned int __v1, __v2;        \
-                               __v2 = __get_unaligned_4_be(__p); \
-                               __v1 = __get_unaligned_4_be((__p+4));   \
-                               __v = ((unsigned long long)__v2 << 32 | __v1);  \
-                       }                                       \
-                       break;                                  \
-               default: __v = __bug_unaligned_x(__p);  break;  \
-               }                                               \
-               __v;                                            \
+#define __get_unaligned_be(ptr)                                                \
+       ({                                                              \
+               const __u8 *__p = (const __u8 *)(ptr);                  \
+               __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,        \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_be(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_be(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_be(__p), \
+                   (void)__bug_unaligned_x(__p)))));                   \
        })
 
 
index 1e891f860ef3ef4f430d6757dc7c6786977de882..2ab4078334bf1ee57afba6e6ffa7639903dd6889 100644 (file)
 #endif
 
 #ifdef __KERNEL__
+#include <linux/err.h>
 #include <linux/linkage.h>
 
 #define __sys2(x) #x
 
 #define __syscall_return(type, res)                                    \
 do {                                                                   \
-       if ((unsigned long)(res) >= (unsigned long)(-129)) {            \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {      \
                errno = -(res);                                         \
                res = -1;                                               \
        }                                                               \
index 70eb6d91cfd0c85448477479fa0d2fca848dfaf9..c6d2436c9d349ca322790a81fe95181988641da0 100644 (file)
 #define __ARM_NR_usr26                 (__ARM_NR_BASE+3)
 
 #ifdef __KERNEL__
+#include <linux/err.h>
 #include <linux/linkage.h>
 
 #define __sys2(x) #x
 
 #define __syscall_return(type, res)                                    \
 do {                                                                   \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) {            \
+       if ((unsigned long)(res) >= (unsigned long)-MAX_ERRNO) {        \
                errno = -(res);                                         \
                res = -1;                                               \
        }                                                               \
index 52df72a622329659d27524f57fc1d2f95556bc13..5f43df0a5fb42df32847984e49e6a2d8db070f2c 100644 (file)
@@ -160,4 +160,8 @@ static __inline__ int is_write_locked(rwlock_t *rw)
        return rw->counter < 0;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_ARCH_SPINLOCK_H */
index 2fb3c6f05e034b30c2c3a419b4958106cbe7b45c..ba1b37df69d50d6147a2150b052c5e8cc89dd9de 100644 (file)
@@ -176,8 +176,6 @@ do {                                                        \
 } while(0)
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
-#define set_pte_atomic(pteptr, pteval)         set_pte((pteptr), (pteval))
-
 /*
  * pgd_offset() returns a (pgd_t *)
  * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
index 2aa562fa067bf4e371a79b9ea3e80edf15e4504c..a89bddefdacf9194373a201c6c6c4cf8c4ac87c0 100644 (file)
@@ -6,11 +6,6 @@
 #define CLOCK_TICK_RATE                1193180 /* Underlying HZ */
 #define CLOCK_TICK_FACTOR      20      /* Factor of both 1000000 and CLOCK_TICK_RATE */
 
-#define FINETUNE                                                       \
-((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) *                        \
-   (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR))  \
-  << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
-
 typedef unsigned long cycles_t;
 
 static inline cycles_t get_cycles(void)
index b80dbd839475677b1c5721a9d5033875ee20770d..d104d1b91d399bb4f34f627b478f8740ebbee662 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 310
+#include <linux/err.h>
 
 /*
  * process the return value of a syscall, consigning it to one of two possible fates
 #define __syscall_return(type, res)                                    \
 do {                                                                   \
         unsigned long __sr2 = (res);                                   \
-       if (__builtin_expect(__sr2 >= (unsigned long)(-4095), 0)) {     \
+       if (__builtin_expect(__sr2 >= (unsigned long)(-MAX_ERRNO), 0)) { \
                errno = (-__sr2);                                       \
                __sr2 = ~0UL;                                           \
        }                                                               \
index 8ceab7bcd8b4f229f45536f8208e5394c99e9695..a5250895155ef6e5affcae708a4a79f692f037e2 100644 (file)
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
-#define WARN_ON(condition) do { \
-       if (unlikely((condition)!=0)) { \
-               printk("BUG: warning at %s:%d/%s()\n", __FILE__, __LINE__, __FUNCTION__); \
-               dump_stack(); \
-       } \
-} while (0)
+#define WARN_ON(condition) ({                                          \
+       typeof(condition) __ret_warn_on = (condition);                  \
+       if (unlikely(__ret_warn_on)) {                                  \
+               printk("BUG: warning at %s:%d/%s()\n", __FILE__,        \
+                       __LINE__, __FUNCTION__);                        \
+               dump_stack();                                           \
+       }                                                               \
+       unlikely(__ret_warn_on);                                        \
+})
 #endif
 
 #else /* !CONFIG_BUG */
 #endif
 
 #ifndef HAVE_ARCH_WARN_ON
-#define WARN_ON(condition) do { if (condition) ; } while(0)
+#define WARN_ON(condition) unlikely((condition))
 #endif
 #endif
 
-#define WARN_ON_ONCE(condition)                                \
-({                                                     \
+#define WARN_ON_ONCE(condition)        ({                      \
        static int __warn_once = 1;                     \
-       int __ret = 0;                                  \
+       typeof(condition) __ret_warn_once = (condition);\
                                                        \
-       if (unlikely((condition) && __warn_once)) {     \
-               __warn_once = 0;                        \
-               WARN_ON(1);                             \
-               __ret = 1;                              \
-       }                                               \
-       __ret;                                          \
+       if (likely(__warn_once))                        \
+               if (WARN_ON(__ret_warn_once))           \
+                       __warn_once = 0;                \
+       unlikely(__ret_warn_once);                      \
 })
 
 #ifdef CONFIG_SMP
index 349260cd86ededc1487131a77518f6dc6187da8e..9d774d07d95b4a3a53d5fb75fac15b076d892a02 100644 (file)
  * Note: the old pte is known to not be writable, so we don't need to
  * worry about dirty bits etc getting lost.
  */
-#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
 #define ptep_establish(__vma, __address, __ptep, __entry)              \
 do {                                                                   \
        set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry);       \
        flush_tlb_page(__vma, __address);                               \
 } while (0)
-#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
-#define ptep_establish(__vma, __address, __ptep, __entry)              \
-do {                                                                   \
-       set_pte_atomic(__ptep, __entry);                                \
-       flush_tlb_page(__vma, __address);                               \
-} while (0)
-#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
@@ -112,8 +104,13 @@ do {                                                                         \
 })
 #endif
 
-#ifndef __HAVE_ARCH_PTE_CLEAR_FULL
-#define pte_clear_full(__mm, __address, __ptep, __full)                        \
+/*
+ * Some architectures may be able to avoid expensive synchronization
+ * primitives when modifications are made to PTE's which are already
+ * not present, or in the process of an address space destruction.
+ */
+#ifndef __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL
+#define pte_clear_not_present_full(__mm, __address, __ptep, __full)    \
 do {                                                                   \
        pte_clear((__mm), (__address), (__ptep));                       \
 } while (0)
@@ -165,6 +162,26 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #define move_pte(pte, prot, old_addr, new_addr)        (pte)
 #endif
 
+/*
+ * A facility to provide lazy MMU batching.  This allows PTE updates and
+ * page invalidations to be delayed until a call to leave lazy MMU mode
+ * is issued.  Some architectures may benefit from doing this, and it is
+ * beneficial for both shadow and direct mode hypervisors, which may batch
+ * the PTE updates which happen during this window.  Note that using this
+ * interface requires that read hazards be removed from the code.  A read
+ * hazard could result in the direct mode hypervisor case, since the actual
+ * write to the page tables may not yet have taken place, so reads though
+ * a raw PTE pointer after it has been modified are not guaranteed to be
+ * up to date.  This mode can only be entered and left under the protection of
+ * the page table locks for all page tables which may be modified.  In the UP
+ * case, this is required so that preemption is disabled, and in the SMP case,
+ * it must synchronize the delayed page table writes properly on other CPUs.
+ */
+#ifndef __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+#define arch_enter_lazy_mmu_mode()     do {} while (0)
+#define arch_leave_lazy_mmu_mode()     do {} while (0)
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
index 253ae1328271090b4a7d94853673e93f38800d1c..69240b52f8e17931d939c96c6c2901978717b9b9 100644 (file)
         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {        \
                *(__ksymtab_strings)                                    \
        }                                                               \
-       __end_rodata = .;                                               \
-       . = ALIGN(4096);                                                \
                                                                        \
        /* Built-in module parameters. */                               \
        __param : AT(ADDR(__param) - LOAD_OFFSET) {                     \
                VMLINUX_SYMBOL(__start___param) = .;                    \
                *(__param)                                              \
                VMLINUX_SYMBOL(__stop___param) = .;                     \
-       }
+       }                                                               \
+       __end_rodata = .;                                               \
+       . = ALIGN(4096);
 
 #define SECURITY_INIT                                                  \
        .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
index fbad65e8a5c0ab8cf70d702b30abadf0a8366ee0..90efbd65539076b2afd06d1f9cafb714f8e1a7fb 100644 (file)
 #define kbd_enable_irq(x...)   do {;} while (0)
 #define kbd_disable_irq(x...)  do {;} while (0)
 
-
-/* needed if MAGIC_SYSRQ is enabled for serial console */
-#ifndef SYSRQ_KEY
-#define SYSRQ_KEY              ((unsigned char)(-1))
-#define kbd_sysrq_xlate         ((unsigned char *)NULL)
-#endif
-
-
 #endif  /* _H8300_KEYBOARD_H */
 
 
index 226dd596c2dad0de1e22943ba1853610c7c8cb20..a2dd90462d80f172b17760b1501dfd6c91e3030d 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 289
+#include <linux/err.h>
 
-
-/* user-visible error numbers are in the range -1 - -122: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
    <asm-m68k/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* avoid using res which is declared to be in register d0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index 576ae01d71c81d98d91357c55a56ddbeee1499e6..81999a3ebe7c4c712ac91da21fc963e24c638270 100644 (file)
@@ -21,7 +21,7 @@ static inline dma_addr_t
 dma_map_single(struct device *dev, void *ptr, size_t size,
               enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!valid_dma_direction(direction));
        WARN_ON(size == 0);
        flush_write_buffers();
        return virt_to_phys(ptr);
@@ -31,7 +31,7 @@ static inline void
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                 enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!valid_dma_direction(direction));
 }
 
 static inline int
@@ -40,7 +40,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 {
        int i;
 
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!valid_dma_direction(direction));
        WARN_ON(nents == 0 || sg[0].length == 0);
 
        for (i = 0; i < nents; i++ ) {
@@ -57,7 +57,7 @@ static inline dma_addr_t
 dma_map_page(struct device *dev, struct page *page, unsigned long offset,
             size_t size, enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!valid_dma_direction(direction));
        return page_to_phys(page) + offset;
 }
 
@@ -65,7 +65,7 @@ static inline void
 dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
               enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!valid_dma_direction(direction));
 }
 
 
@@ -73,7 +73,7 @@ static inline void
 dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
             enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!valid_dma_direction(direction));
 }
 
 static inline void
index 6312c3e798147d508c1c695c175559dd96dc8daf..4182c347ef85052178ee67b193d3c5750c14aa58 100644 (file)
@@ -16,7 +16,7 @@
 
 static inline void do_timer_interrupt_hook(struct pt_regs *regs)
 {
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode_vm(regs));
 #endif
index a81b0596159508618a3e2b2bfc11ea5b9d62fe47..254a0fe01c6a3f46b5983afc9336b11a61a3d81d 100644 (file)
@@ -88,7 +88,7 @@ static inline void clustered_apic_check(void)
 
 static inline int apicid_to_node(int logical_apicid)
 {
-       return logical_apicid >> 5;          /* 2 clusterids per CEC */
+       return apicid_2_node[logical_apicid];
 }
 
 /* Mapping from cpu number to logical apicid */
index 95568e6ca91cf3cff150c743ff9f0f87a070a4d9..8db618c5a72b0e50ec0502e7b0d6b8baadec456c 100644 (file)
@@ -9,7 +9,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs)
        /* Clear the interrupt */
        co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
 
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode_vm(regs));
 #endif
index eaf518098981cc843e564d3ec1b650f17442256e..099fe9f5c1b2bcc922079c7fa64b21b197d864b7 100644 (file)
@@ -3,7 +3,7 @@
 
 static inline void do_timer_interrupt_hook(struct pt_regs *regs)
 {
-       do_timer(regs);
+       do_timer(1);
 #ifndef CONFIG_SMP
        update_process_times(user_mode_vm(regs));
 #endif
index 303bcd4592bbe332337c10726dce6a0b3bd4c94a..269d315719ca422d478e7d18cd441cf71c44438d 100644 (file)
@@ -36,4 +36,10 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC 2
 #define NMI_INVALID    3
 
+struct ctl_table;
+struct file;
+extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+                       void __user *, size_t *, loff_t *);
+extern int unknown_nmi_panic;
+
 #endif /* ASM_NMI_H */
index 201c86a6711e87f91f688ab15b2c10ddf3b8ad64..8d8d3b9ecdb02d0437b0e0393fc8e753cd439178 100644 (file)
@@ -16,6 +16,7 @@
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
+#define set_pte_present(mm,addr,ptep,pteval) set_pte_at(mm,addr,ptep,pteval)
 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
 
 #define pte_clear(mm,addr,xp)  do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
index 0d899173232e1f54bf6e80e924391a8fa0b30cc2..c2d701ea35beb0650ecd0cd8360f857a1e90ca31 100644 (file)
@@ -58,7 +58,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
-#define __HAVE_ARCH_SET_PTE_ATOMIC
+/*
+ * Since this is only called on user PTEs, and the page fault handler
+ * must handle the already racy situation of simultaneous page faults,
+ * we are justified in merely clearing the PTE present bit, followed
+ * by a set.  The ordering here is important.
+ */
+static inline void set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+       ptep->pte_low = 0;
+       smp_wmb();
+       ptep->pte_high = pte.pte_high;
+       smp_wmb();
+       ptep->pte_low = pte.pte_low;
+}
+
 #define set_pte_atomic(pteptr,pteval) \
                set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
 #define set_pmd(pmdptr,pmdval) \
index 541b3e23433571d590f8e79291bb2c21fded9306..7d398f493ddeedfc2d5e826d595028767ae64b76 100644 (file)
@@ -246,6 +246,23 @@ static inline pte_t pte_mkhuge(pte_t pte)  { (pte).pte_low |= _PAGE_PSE; return p
 # include <asm/pgtable-2level.h>
 #endif
 
+/*
+ * Rules for using pte_update - it must be called after any PTE update which
+ * has not been done using the set_pte / clear_pte interfaces.  It is used by
+ * shadow mode hypervisors to resynchronize the shadow page tables.  Kernel PTE
+ * updates should either be sets, clears, or set_pte_atomic for P->P
+ * transitions, which means this hook should only be called for user PTEs.
+ * This hook implies a P->P protection or access change has taken place, which
+ * requires a subsequent TLB flush.  The notification can optionally be delayed
+ * until the TLB flush event by using the pte_update_defer form of the
+ * interface, but care must be taken to assure that the flush happens while
+ * still holding the same page table lock so that the shadow and primary pages
+ * do not become out of sync on SMP.
+ */
+#define pte_update(mm, addr, ptep)             do { } while (0)
+#define pte_update_defer(mm, addr, ptep)       do { } while (0)
+
+
 /*
  * We only update the dirty/accessed state if we set
  * the dirty bit by hand in the kernel, since the hardware
@@ -258,25 +275,54 @@ static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PSE; return p
 do {                                                                   \
        if (dirty) {                                                    \
                (ptep)->pte_low = (entry).pte_low;                      \
+               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
                flush_tlb_page(vma, address);                           \
        }                                                               \
 } while (0)
 
+/*
+ * We don't actually have these, but we want to advertise them so that
+ * we can encompass the flush here.
+ */
 #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)
-{
-       if (!pte_dirty(*ptep))
-               return 0;
-       return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
-}
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-       if (!pte_young(*ptep))
-               return 0;
-       return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
-}
+
+/*
+ * Rules for using ptep_establish: the pte MUST be a user pte, and
+ * must be a present->present transition.
+ */
+#define __HAVE_ARCH_PTEP_ESTABLISH
+#define ptep_establish(vma, address, ptep, pteval)                     \
+do {                                                                   \
+       set_pte_present((vma)->vm_mm, address, ptep, pteval);           \
+       flush_tlb_page(vma, address);                                   \
+} while (0)
+
+#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
+#define ptep_clear_flush_dirty(vma, address, ptep)                     \
+({                                                                     \
+       int __dirty;                                                    \
+       __dirty = pte_dirty(*(ptep));                                   \
+       if (__dirty) {                                                  \
+               clear_bit(_PAGE_BIT_DIRTY, &(ptep)->pte_low);           \
+               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               flush_tlb_page(vma, address);                           \
+       }                                                               \
+       __dirty;                                                        \
+})
+
+#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+#define ptep_clear_flush_young(vma, address, ptep)                     \
+({                                                                     \
+       int __young;                                                    \
+       __young = pte_young(*(ptep));                                   \
+       if (__young) {                                                  \
+               clear_bit(_PAGE_BIT_ACCESSED, &(ptep)->pte_low);        \
+               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               flush_tlb_page(vma, address);                           \
+       }                                                               \
+       __young;                                                        \
+})
 
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
@@ -295,6 +341,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
+       pte_update(mm, addr, ptep);
 }
 
 /*
@@ -426,6 +473,13 @@ extern pte_t *lookup_address(unsigned long address);
 #define pte_unmap_nested(pte) do { } while (0)
 #endif
 
+/* Clear a kernel PTE and flush it from the TLB */
+#define kpte_clear_flush(ptep, vaddr)                                  \
+do {                                                                   \
+       pte_clear(&init_mm, vaddr, ptep);                               \
+       __flush_tlb_one(vaddr);                                         \
+} while (0)
+
 /*
  * The i386 doesn't have any external MMU info: the kernel page
  * tables contain all the necessary information.
index e63b6a68f04c1d976a16f91b35d93eaf4933d8b1..4e34a468c3835cc323eea52518f5c916cea79691 100644 (file)
@@ -126,7 +126,7 @@ static inline int down_interruptible(struct semaphore * sem)
                "lea %1,%%eax\n\t"
                "call __down_failed_interruptible\n"
                "2:"
-               :"=a" (result), "+m" (sem->count)
+               :"=&a" (result), "+m" (sem->count)
                :
                :"memory");
        return result;
@@ -148,7 +148,7 @@ static inline int down_trylock(struct semaphore * sem)
                "lea %1,%%eax\n\t"
                "call __down_failed_trylock\n\t"
                "2:\n"
-               :"=a" (result), "+m" (sem->count)
+               :"=&a" (result), "+m" (sem->count)
                :
                :"memory");
        return result;
index 32ac8c91d5c5ccb2e8856ee2a6943d59609d090e..6aa1206f6e2a9b17ffd120f94625db0552916f71 100644 (file)
@@ -46,6 +46,8 @@ extern u8 x86_cpu_to_apicid[];
 
 #define cpu_physical_id(cpu)   x86_cpu_to_apicid[cpu]
 
+extern u8 apicid_2_node[];
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern void cpu_exit_clear(void);
 extern void cpu_uninit(void);
@@ -82,6 +84,7 @@ static inline int hard_smp_processor_id(void)
 #endif
 #endif
 
+extern int safe_smp_processor_id(void);
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
 extern unsigned int num_processors;
@@ -90,6 +93,7 @@ extern unsigned int num_processors;
 
 #else /* CONFIG_SMP */
 
+#define safe_smp_processor_id()                0
 #define cpu_physical_id(cpu)           boot_cpu_physical_apicid
 
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
index b0b3043f05e154742738f5ff03b7c409d265f2f4..c18b71fae6b38f6ec0a524509deb4a229de002ad 100644 (file)
@@ -205,4 +205,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
                                 : "+m" (rw->lock) : : "memory");
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SPINLOCK_H */
index 565d0897b2053d274f279f6bb2d4d2b614a92670..bd9987087adc6adb90d95daabf67c4eba7be8392 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 319
+#include <linux/err.h>
 
 /*
- * user-visible error numbers are in the range -1 - -128: see
+ * user-visible error numbers are in the range -1 - -MAX_ERRNO: see
  * <asm-i386/errno.h>
  */
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
                errno = -(res); \
                res = -1; \
        } \
diff --git a/include/asm-ia64/esi.h b/include/asm-ia64/esi.h
new file mode 100644 (file)
index 0000000..84aac0e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * ESI service calls.
+ *
+ * Copyright (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P.
+ *     Alex Williamson <alex.williamson@hp.com>
+ */
+#ifndef esi_h
+#define esi_h
+
+#include <linux/efi.h>
+
+#define ESI_QUERY                      0x00000001
+#define ESI_OPEN_HANDLE                        0x02000000
+#define ESI_CLOSE_HANDLE               0x02000001
+
+enum esi_proc_type {
+       ESI_PROC_SERIALIZED,    /* calls need to be serialized */
+       ESI_PROC_MP_SAFE,       /* MP-safe, but not reentrant */
+       ESI_PROC_REENTRANT      /* MP-safe and reentrant */
+};
+
+extern int ia64_esi_init (void);
+extern struct ia64_sal_retval esi_call_phys (void *, u64 *);
+extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *,
+                        enum esi_proc_type,
+                        u64, u64, u64, u64, u64, u64, u64, u64);
+extern int ia64_esi_call_phys(efi_guid_t, struct ia64_sal_retval *, u64, u64,
+                              u64, u64, u64, u64, u64, u64);
+
+#endif /* esi_h */
index 6a332a9f099c2eafbf78ee5f79056a349d41a775..07d77f3a8cbe278bbad15d99e80442b86cbd7d83 100644 (file)
@@ -1,6 +1,124 @@
 #ifndef _ASM_FUTEX_H
 #define _ASM_FUTEX_H
 
-#include <asm-generic/futex.h>
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
-#endif
+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+do {                                                                   \
+       register unsigned long r8 __asm ("r8") = 0;                     \
+       __asm__ __volatile__(                                           \
+               "       mf;;                                    \n"     \
+               "[1:] " insn ";;                                \n"     \
+               "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"     \
+               "[2:]"                                                  \
+               : "+r" (r8), "=r" (oldval)                              \
+               : "r" (uaddr), "r" (oparg)                              \
+               : "memory");                                            \
+       ret = r8;                                                       \
+} while (0)
+
+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+do {                                                                   \
+       register unsigned long r8 __asm ("r8") = 0;                     \
+       int val, newval;                                                \
+       do {                                                            \
+               __asm__ __volatile__(                                   \
+                       "       mf;;                              \n"   \
+                       "[1:]   ld4 %3=[%4];;                     \n"   \
+                       "       mov %2=%3                         \n"   \
+                               insn    ";;                       \n"   \
+                       "       mov ar.ccv=%2;;                   \n"   \
+                       "[2:]   cmpxchg4.acq %1=[%4],%3,ar.ccv;;  \n"   \
+                       "       .xdata4 \"__ex_table\", 1b-., 3f-.\n"   \
+                       "       .xdata4 \"__ex_table\", 2b-., 3f-.\n"   \
+                       "[3:]"                                          \
+                       : "+r" (r8), "=r" (val), "=&r" (oldval),        \
+                          "=&r" (newval)                               \
+                       : "r" (uaddr), "r" (oparg)                      \
+                       : "memory");                                    \
+               if (unlikely (r8))                                      \
+                       break;                                          \
+       } while (unlikely (val != oldval));                             \
+       ret = r8;                                                       \
+} while (0)
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op1("xchg4 %1=[%2],%3", ret, oldval, uaddr,
+                                  oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op2("add %3=%3,%5", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op2("or %3=%3,%5", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op2("and %3=%3,%5", ret, oldval, uaddr,
+                                  ~oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op2("xor %3=%3,%5", ret, oldval, uaddr, oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       {
+               register unsigned long r8 __asm ("r8");
+               __asm__ __volatile__(
+                       "       mf;;                                    \n"
+                       "       mov ar.ccv=%3;;                         \n"
+                       "[1:]   cmpxchg4.acq %0=[%1],%2,ar.ccv          \n"
+                       "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"
+                       "[2:]"
+                       : "=r" (r8)
+                       : "r" (uaddr), "r" (newval),
+                         "rO" ((long) (unsigned) oldval)
+                       : "memory");
+               return r8;
+       }
+}
+
+#endif /* _ASM_FUTEX_H */
index 9389049101157360555125760c2c4c268d9426ff..1b45b71c79b98bfe0c0f9bc51855920e3b0b35a0 100644 (file)
@@ -29,7 +29,8 @@
 #include <linux/percpu.h>
 #include <asm/break.h>
 
-#define MAX_INSN_SIZE   16
+#define __ARCH_WANT_KPROBES_INSN_SLOT
+#define MAX_INSN_SIZE   1
 #define BREAK_INST     (long)(__IA64_BREAK_KPROBE << 6)
 
 typedef union cmp_inst {
@@ -94,7 +95,7 @@ struct kprobe_ctlblk {
 #define IP_RELATIVE_PREDICT_OPCODE     (7)
 #define LONG_BRANCH_OPCODE             (0xC)
 #define LONG_CALL_OPCODE               (0xD)
-#define arch_remove_kprobe(p)          do {} while (0)
+#define flush_insn_slot(p)             do { } while (0)
 
 typedef struct kprobe_opcode {
        bundle_t bundle;
@@ -108,7 +109,7 @@ struct fnptr {
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
        /* copy of the instruction to be emulated */
-       kprobe_opcode_t insn;
+       kprobe_opcode_t *insn;
  #define INST_FLAG_FIX_RELATIVE_IP_ADDR                1
  #define INST_FLAG_FIX_BRANCH_REG              2
  #define INST_FLAG_BREAK_INST                  4
@@ -125,6 +126,6 @@ static inline void jprobe_return(void)
 }
 extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
-extern void flush_insn_slot(struct kprobe *p);
+extern void arch_remove_kprobe(struct kprobe *p);
 
 #endif                         /* _ASM_KPROBES_H */
index 27c9203d8ce3173bff55753e1882a651faf11bc6..76203f9a8718d6706216a961684205f6beffbdaa 100644 (file)
        movl    temp2 = start_addr;                             \
        ;;                                                      \
        mov     cr.iip = temp2;                                 \
+       movl    gp = __gp                                       \
        ;;                                                      \
        DATA_PA_TO_VA(sp, temp1);                               \
-       DATA_PA_TO_VA(gp, temp2);                               \
        srlz.i;                                                 \
        ;;                                                      \
        nop     1;                                              \
index 6a33a07b3f1dfc608a5995a871896dac5c00b4ef..c3b1f862e6e75dfda6b1f677d8f358df0cc4fbad 100644 (file)
@@ -55,6 +55,7 @@ extern void efi_memmap_init(unsigned long *, unsigned long *);
   extern unsigned long vmalloc_end;
   extern struct page *vmem_map;
   extern int find_largest_hole (u64 start, u64 end, void *arg);
+  extern int register_active_ranges (u64 start, u64 end, void *arg);
   extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
   extern int vmemmap_find_next_valid_pfn(int, int);
 #else
index e0a1d173e42df07fd74ebee65ffde116b9e76ec9..7d5e2ccc37a079fb4fe2ffbd16d69c919c6610a5 100644 (file)
@@ -69,6 +69,8 @@ extern void unmap_cpu_from_node(int cpu, int nid);
 
 
 #else /* !CONFIG_NUMA */
+#define map_cpu_to_node(cpu, nid)      do{}while(0)
+#define unmap_cpu_from_node(cpu, nid)  do{}while(0)
 
 #define paddr_to_nid(addr)     0
 
index 20a8d618c8454776b441245317c21d7e19444a87..2c8fd92d0ece088e36b15548588947a59fd5cea7 100644 (file)
@@ -78,6 +78,7 @@
 #define PAL_VM_TR_READ         261     /* read contents of translation register */
 #define PAL_GET_PSTATE         262     /* get the current P-state */
 #define PAL_SET_PSTATE         263     /* set the P-state */
+#define PAL_BRAND_INFO         274     /* Processor branding information */
 
 #ifndef __ASSEMBLY__
 
@@ -963,7 +964,8 @@ static inline s64
 ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr)
 {
        struct ia64_pal_retval iprv;
-       PAL_CALL(iprv, PAL_CACHE_READ, line_id.pclid_data, physical_addr, 0);
+       PAL_CALL_PHYS_STK(iprv, PAL_CACHE_READ, line_id.pclid_data,
+                               physical_addr, 0);
        return iprv.status;
 }
 
@@ -985,7 +987,8 @@ static inline s64
 ia64_pal_cache_write (pal_cache_line_id_u_t line_id, u64 physical_addr, u64 data)
 {
        struct ia64_pal_retval iprv;
-       PAL_CALL(iprv, PAL_CACHE_WRITE, line_id.pclid_data, physical_addr, data);
+       PAL_CALL_PHYS_STK(iprv, PAL_CACHE_WRITE, line_id.pclid_data,
+                               physical_addr, data);
        return iprv.status;
 }
 
@@ -1133,6 +1136,15 @@ ia64_pal_set_pstate (u64 pstate_index)
        return iprv.status;
 }
 
+/* Processor branding information*/
+static inline s64
+ia64_pal_get_brand_info (char *brand_info)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL_STK(iprv, PAL_BRAND_INFO, 0, (u64)brand_info, 0);
+       return iprv.status;
+}
+
 /* Cause the processor to enter LIGHT HALT state, where prefetching and execution are
  * suspended, but cache and TLB coherency is maintained.
  */
index 265f4824db0e2e6ea04abc225f81758547a8de62..5830d36fd8e6a407697001a1f5c0aeef9c4747f6 100644 (file)
 #include <asm/ustack.h>
 
 #define IA64_NUM_DBG_REGS      8
-/*
- * Limits for PMC and PMD are set to less than maximum architected values
- * but should be sufficient for a while
- */
-#define IA64_NUM_PMC_REGS      64
-#define IA64_NUM_PMD_REGS      64
 
 #define DEFAULT_MAP_BASE       __IA64_UL_CONST(0x2000000000000000)
 #define DEFAULT_TASK_SIZE      __IA64_UL_CONST(0xa000000000000000)
@@ -163,6 +157,7 @@ struct cpuinfo_ia64 {
        __u8 family;
        __u8 archrev;
        char vendor[16];
+       char *model_name;
 
 #ifdef CONFIG_NUMA
        struct ia64_node_data *node_data;
@@ -262,13 +257,9 @@ struct thread_struct {
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
 #ifdef CONFIG_PERFMON
-       __u64 pmcs[IA64_NUM_PMC_REGS];
-       __u64 pmds[IA64_NUM_PMD_REGS];
        void *pfm_context;                   /* pointer to detailed PMU context */
        unsigned long pfm_needs_checking;    /* when >0, pending perfmon work on kernel exit */
-# define INIT_THREAD_PM                .pmcs =                 {0UL, },  \
-                               .pmds =                 {0UL, },  \
-                               .pfm_context =          NULL,     \
+# define INIT_THREAD_PM                .pfm_context =          NULL,     \
                                .pfm_needs_checking =   0UL,
 #else
 # define INIT_THREAD_PM
index 74bde1c2bb1a93b48c2c4ac78df57dc8965913b5..60fd4ae014f6fbe8a3fe19b8e9171a7e277f609e 100644 (file)
@@ -126,6 +126,7 @@ extern void smp_send_reschedule (int cpu);
 extern void lock_ipi_calllock(void);
 extern void unlock_ipi_calllock(void);
 extern void identify_siblings (struct cpuinfo_ia64 *);
+extern int is_multithreading_enabled(void);
 
 #else
 
index 9e83210dc31257adc4c5356b64f37b24e83bf1e4..ff857e31738a00dfbed4534ee1832528e231fb33 100644 (file)
@@ -213,4 +213,8 @@ static inline int __raw_read_trylock(raw_rwlock_t *x)
        return (u32)ia64_cmpxchg4_acq((__u32 *)(x), new.word, old.word) == old.word;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /*  _ASM_IA64_SPINLOCK_H */
index f581662c5ab8a8ee7ef75e592ad48e626b43038f..bb0eb727dcd086fb15d43135ca7e0e20ebb4cdf8 100644 (file)
 /* 1294, 1295 reserved for pselect/ppoll */
 #define __NR_unshare                   1296
 #define __NR_splice                    1297
-/* 1298, 1299 reserved for set_robust_list/get_robust_list */
+#define __NR_set_robust_list           1298
+#define __NR_get_robust_list           1299
 #define __NR_sync_file_range           1300
 #define __NR_tee                       1301
 #define __NR_vmsplice                  1302
index 6a674e3d37a20cdc30a5efd4d8765d106ec87c87..84152760e0b56e90847b9eb49c3772459afbdc09 100644 (file)
@@ -44,7 +44,7 @@ static inline int pgd_present(pgd_t pgd)      { return 1; }
  */
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
+
 /*
  * (pmds are folded into pgds so this doesnt get actually called,
  * but the define is needed for a generic inline function.)
index f94c1a673569109cbe336c2849b7f228183bc988..f5cfba81ee10c1f59b007dcf34fd9db508a9bff5 100644 (file)
@@ -298,7 +298,14 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
        );
 }
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
+{
+       atomic_t *count = (atomic_t*)lock;
+       if (atomic_dec_return(count) >= 0)
+               return 1;
+       atomic_inc(count);
+       return 0;
+}
 
 static inline int __raw_write_trylock(raw_rwlock_t *lock)
 {
@@ -309,4 +316,8 @@ static inline int __raw_write_trylock(raw_rwlock_t *lock)
        return 0;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* _ASM_M32R_SPINLOCK_H */
index 9e618afec6ed7bd6480962dfa85abb2931c61e7a..4ce0619f6989024855782484766eb0adfa88cc78 100644 (file)
@@ -328,15 +328,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
 #define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
 #else
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
 #define smp_wmb()      barrier()
 #define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
 #endif
 
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-
 #define arch_align_stack(x) (x)
 
 #endif  /* _ASM_M32R_SYSTEM_H */
index e89bfd17db519bd0e78718f2db2342547060c21a..019441c1d7a0ef4feaff5523a6435d58283057ab 100644 (file)
@@ -12,9 +12,6 @@
 
 #define CLOCK_TICK_RATE        (CONFIG_BUS_CLOCK / CONFIG_TIMER_DIVIDE)
 #define CLOCK_TICK_FACTOR      20      /* Factor of both 1000000 and CLOCK_TICK_RATE */
-#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
-       (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
-               << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
 
 #ifdef __KERNEL__
 /*
index 89f376e6229f7ddb2cf332a613177e9f09f1b19a..5c6a9ac6cf1aea11eefcca4969dae98057e6c724 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 285
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -124: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
  * <asm-m32r/errno.h>
  */
 
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-(124 + 1))) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* Avoid using "res" which is declared to be in register r0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index 7c0b6296b45c6b8c14cd545deb9a565b5db78f0d..751632b904dbca90a4e8a1967ff24a28815d9532 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls            282
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -124: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
    <asm-m68k/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* avoid using res which is declared to be in register d0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index 1b2abdf281e1800b62f66bdda3b7ff9a9057bfb9..21fdc37c5c2c60c8c4e69d0a6829efa297042dc9 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls            282
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -122: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
    <asm-m68k/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* avoid using res which is declared to be in register d0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index c68e1680da0173d5754d1a1df4944120a5239e58..7897f05e316520ed5279e479eef15a4278a6afa9 100644 (file)
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += cachectl.h sgidefs.h sysmips.h
index 3b745e76f429bd0bea3e2615d33136bdc82ba9e1..78c35ec463624d2c4d337f9dbd2d2c2a25701301 100644 (file)
  * Valid machtype for group GALILEO
  */
 #define MACH_GROUP_GALILEO     11      /* Galileo Eval Boards          */
-#define  MACH_EV96100          0       /* EV96100 */
-#define  MACH_EV64120A         1       /* EV64120A */
+#define  MACH_EV64120A         0       /* EV64120A */
 
 /*
  * Valid machtype for group MOMENCO
index 47bc8f6c20d2e2795211335e37cbb4e01489e0c2..36416fdfcf6893030e4f0325e8407023857babc0 100644 (file)
@@ -21,7 +21,6 @@
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *  - flush_icache_range(start, end) flush a range of instructions
  *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
  *
  * MIPS specific flush operations:
  *
@@ -39,7 +38,7 @@ extern void __flush_dcache_page(struct page *page);
 
 static inline void flush_dcache_page(struct page *page)
 {
-       if (cpu_has_dc_aliases)
+       if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
                __flush_dcache_page(page);
 
 }
@@ -47,8 +46,13 @@ static inline void flush_dcache_page(struct page *page)
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-extern void (*flush_icache_page)(struct vm_area_struct *vma,
+extern void (*__flush_icache_page)(struct vm_area_struct *vma,
        struct page *page);
+static inline void flush_icache_page(struct vm_area_struct *vma,
+       struct page *page)
+{
+}
+
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
@@ -60,7 +64,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
        if (cpu_has_dc_aliases)
                flush_cache_page(vma, vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       flush_icache_page(vma, page);
+       __flush_icache_page(vma, page);
 }
 
 static inline void copy_from_user_page(struct vm_area_struct *vma,
index 787220e6c1fc4f187b855de989f24b0e4f63c441..00a50ec1c19fd6426bd57732aad5e2bdd64e7807 100644 (file)
@@ -25,8 +25,6 @@
 
 #define F_SETOWN       24      /*  for sockets. */
 #define F_GETOWN       23      /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
 
 #ifndef __mips64
 #define F_GETLK64      33      /*  using 'struct flock64' */
diff --git a/include/asm-mips/galileo-boards/gt96100.h b/include/asm-mips/galileo-boards/gt96100.h
deleted file mode 100644 (file)
index aabd1b6..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             stevel@mvista.com or source@mvista.com
- *
- *  This program is free software; you can distribute 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 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.
- *
- * Register offsets of the MIPS GT96100 Advanced Communication Controller.
- */
-#ifndef _GT96100_H
-#define _GT96100_H
-
-/*
- * Galileo GT96100 internal register base.
- */
-#define MIPS_GT96100_BASE (KSEG1ADDR(0x14000000))
-
-#define GT96100_WRITE(ofs, data) \
-    *(volatile u32 *)(MIPS_GT96100_BASE+ofs) = cpu_to_le32(data)
-#define GT96100_READ(ofs) \
-    le32_to_cpu(*(volatile u32 *)(MIPS_GT96100_BASE+ofs))
-
-#define GT96100_ETH_IO_SIZE 0x4000
-
-/************************************************************************
- *  Register offset addresses follow
- ************************************************************************/
-
-/* CPU Interface Control Registers */
-#define GT96100_CPU_INTERF_CONFIG 0x000000
-
-/* Ethernet Ports */
-#define GT96100_ETH_PHY_ADDR_REG             0x080800
-#define GT96100_ETH_SMI_REG                  0x080810
-/*
-  These are offsets to port 0 registers. Add GT96100_ETH_IO_SIZE to
-  get offsets to port 1 registers.
-*/
-#define GT96100_ETH_PORT_CONFIG          0x084800
-#define GT96100_ETH_PORT_CONFIG_EXT      0x084808
-#define GT96100_ETH_PORT_COMM            0x084810
-#define GT96100_ETH_PORT_STATUS          0x084818
-#define GT96100_ETH_SER_PARAM            0x084820
-#define GT96100_ETH_HASH_TBL_PTR         0x084828
-#define GT96100_ETH_FLOW_CNTRL_SRC_ADDR_L    0x084830
-#define GT96100_ETH_FLOW_CNTRL_SRC_ADDR_H    0x084838
-#define GT96100_ETH_SDMA_CONFIG          0x084840
-#define GT96100_ETH_SDMA_COMM            0x084848
-#define GT96100_ETH_INT_CAUSE            0x084850
-#define GT96100_ETH_INT_MASK             0x084858
-#define GT96100_ETH_1ST_RX_DESC_PTR0         0x084880
-#define GT96100_ETH_1ST_RX_DESC_PTR1         0x084884
-#define GT96100_ETH_1ST_RX_DESC_PTR2         0x084888
-#define GT96100_ETH_1ST_RX_DESC_PTR3         0x08488C
-#define GT96100_ETH_CURR_RX_DESC_PTR0        0x0848A0
-#define GT96100_ETH_CURR_RX_DESC_PTR1        0x0848A4
-#define GT96100_ETH_CURR_RX_DESC_PTR2        0x0848A8
-#define GT96100_ETH_CURR_RX_DESC_PTR3        0x0848AC
-#define GT96100_ETH_CURR_TX_DESC_PTR0        0x0848E0
-#define GT96100_ETH_CURR_TX_DESC_PTR1        0x0848E4
-#define GT96100_ETH_MIB_COUNT_BASE           0x085800
-
-/* SDMAs */
-#define GT96100_SDMA_GROUP_CONFIG           0x101AF0
-/* SDMA Group 0 */
-#define GT96100_SDMA_G0_CHAN0_CONFIG        0x000900
-#define GT96100_SDMA_G0_CHAN0_COMM          0x000908
-#define GT96100_SDMA_G0_CHAN0_RX_DESC_BASE      0x008900
-#define GT96100_SDMA_G0_CHAN0_CURR_RX_DESC_PTR  0x008910
-#define GT96100_SDMA_G0_CHAN0_TX_DESC_BASE      0x00C900
-#define GT96100_SDMA_G0_CHAN0_CURR_TX_DESC_PTR  0x00C910
-#define GT96100_SDMA_G0_CHAN0_1ST_TX_DESC_PTR   0x00C914
-#define GT96100_SDMA_G0_CHAN1_CONFIG        0x010900
-#define GT96100_SDMA_G0_CHAN1_COMM          0x010908
-#define GT96100_SDMA_G0_CHAN1_RX_DESC_BASE      0x018900
-#define GT96100_SDMA_G0_CHAN1_CURR_RX_DESC_PTR  0x018910
-#define GT96100_SDMA_G0_CHAN1_TX_DESC_BASE      0x01C900
-#define GT96100_SDMA_G0_CHAN1_CURR_TX_DESC_PTR  0x01C910
-#define GT96100_SDMA_G0_CHAN1_1ST_TX_DESC_PTR   0x01C914
-#define GT96100_SDMA_G0_CHAN2_CONFIG        0x020900
-#define GT96100_SDMA_G0_CHAN2_COMM          0x020908
-#define GT96100_SDMA_G0_CHAN2_RX_DESC_BASE      0x028900
-#define GT96100_SDMA_G0_CHAN2_CURR_RX_DESC_PTR  0x028910
-#define GT96100_SDMA_G0_CHAN2_TX_DESC_BASE      0x02C900
-#define GT96100_SDMA_G0_CHAN2_CURR_TX_DESC_PTR  0x02C910
-#define GT96100_SDMA_G0_CHAN2_1ST_TX_DESC_PTR   0x02C914
-#define GT96100_SDMA_G0_CHAN3_CONFIG        0x030900
-#define GT96100_SDMA_G0_CHAN3_COMM          0x030908
-#define GT96100_SDMA_G0_CHAN3_RX_DESC_BASE      0x038900
-#define GT96100_SDMA_G0_CHAN3_CURR_RX_DESC_PTR  0x038910
-#define GT96100_SDMA_G0_CHAN3_TX_DESC_BASE      0x03C900
-#define GT96100_SDMA_G0_CHAN3_CURR_TX_DESC_PTR  0x03C910
-#define GT96100_SDMA_G0_CHAN3_1ST_TX_DESC_PTR   0x03C914
-#define GT96100_SDMA_G0_CHAN4_CONFIG        0x040900
-#define GT96100_SDMA_G0_CHAN4_COMM          0x040908
-#define GT96100_SDMA_G0_CHAN4_RX_DESC_BASE      0x048900
-#define GT96100_SDMA_G0_CHAN4_CURR_RX_DESC_PTR  0x048910
-#define GT96100_SDMA_G0_CHAN4_TX_DESC_BASE      0x04C900
-#define GT96100_SDMA_G0_CHAN4_CURR_TX_DESC_PTR  0x04C910
-#define GT96100_SDMA_G0_CHAN4_1ST_TX_DESC_PTR   0x04C914
-#define GT96100_SDMA_G0_CHAN5_CONFIG        0x050900
-#define GT96100_SDMA_G0_CHAN5_COMM          0x050908
-#define GT96100_SDMA_G0_CHAN5_RX_DESC_BASE      0x058900
-#define GT96100_SDMA_G0_CHAN5_CURR_RX_DESC_PTR  0x058910
-#define GT96100_SDMA_G0_CHAN5_TX_DESC_BASE      0x05C900
-#define GT96100_SDMA_G0_CHAN5_CURR_TX_DESC_PTR  0x05C910
-#define GT96100_SDMA_G0_CHAN5_1ST_TX_DESC_PTR   0x05C914
-#define GT96100_SDMA_G0_CHAN6_CONFIG        0x060900
-#define GT96100_SDMA_G0_CHAN6_COMM          0x060908
-#define GT96100_SDMA_G0_CHAN6_RX_DESC_BASE      0x068900
-#define GT96100_SDMA_G0_CHAN6_CURR_RX_DESC_PTR  0x068910
-#define GT96100_SDMA_G0_CHAN6_TX_DESC_BASE      0x06C900
-#define GT96100_SDMA_G0_CHAN6_CURR_TX_DESC_PTR  0x06C910
-#define GT96100_SDMA_G0_CHAN6_1ST_TX_DESC_PTR   0x06C914
-#define GT96100_SDMA_G0_CHAN7_CONFIG        0x070900
-#define GT96100_SDMA_G0_CHAN7_COMM          0x070908
-#define GT96100_SDMA_G0_CHAN7_RX_DESC_BASE      0x078900
-#define GT96100_SDMA_G0_CHAN7_CURR_RX_DESC_PTR  0x078910
-#define GT96100_SDMA_G0_CHAN7_TX_DESC_BASE      0x07C900
-#define GT96100_SDMA_G0_CHAN7_CURR_TX_DESC_PTR  0x07C910
-#define GT96100_SDMA_G0_CHAN7_1ST_TX_DESC_PTR   0x07C914
-/* SDMA Group 1 */
-#define GT96100_SDMA_G1_CHAN0_CONFIG        0x100900
-#define GT96100_SDMA_G1_CHAN0_COMM          0x100908
-#define GT96100_SDMA_G1_CHAN0_RX_DESC_BASE      0x108900
-#define GT96100_SDMA_G1_CHAN0_CURR_RX_DESC_PTR  0x108910
-#define GT96100_SDMA_G1_CHAN0_TX_DESC_BASE      0x10C900
-#define GT96100_SDMA_G1_CHAN0_CURR_TX_DESC_PTR  0x10C910
-#define GT96100_SDMA_G1_CHAN0_1ST_TX_DESC_PTR   0x10C914
-#define GT96100_SDMA_G1_CHAN1_CONFIG        0x110900
-#define GT96100_SDMA_G1_CHAN1_COMM          0x110908
-#define GT96100_SDMA_G1_CHAN1_RX_DESC_BASE      0x118900
-#define GT96100_SDMA_G1_CHAN1_CURR_RX_DESC_PTR  0x118910
-#define GT96100_SDMA_G1_CHAN1_TX_DESC_BASE      0x11C900
-#define GT96100_SDMA_G1_CHAN1_CURR_TX_DESC_PTR  0x11C910
-#define GT96100_SDMA_G1_CHAN1_1ST_TX_DESC_PTR   0x11C914
-#define GT96100_SDMA_G1_CHAN2_CONFIG        0x120900
-#define GT96100_SDMA_G1_CHAN2_COMM          0x120908
-#define GT96100_SDMA_G1_CHAN2_RX_DESC_BASE      0x128900
-#define GT96100_SDMA_G1_CHAN2_CURR_RX_DESC_PTR  0x128910
-#define GT96100_SDMA_G1_CHAN2_TX_DESC_BASE      0x12C900
-#define GT96100_SDMA_G1_CHAN2_CURR_TX_DESC_PTR  0x12C910
-#define GT96100_SDMA_G1_CHAN2_1ST_TX_DESC_PTR   0x12C914
-#define GT96100_SDMA_G1_CHAN3_CONFIG        0x130900
-#define GT96100_SDMA_G1_CHAN3_COMM          0x130908
-#define GT96100_SDMA_G1_CHAN3_RX_DESC_BASE      0x138900
-#define GT96100_SDMA_G1_CHAN3_CURR_RX_DESC_PTR  0x138910
-#define GT96100_SDMA_G1_CHAN3_TX_DESC_BASE      0x13C900
-#define GT96100_SDMA_G1_CHAN3_CURR_TX_DESC_PTR  0x13C910
-#define GT96100_SDMA_G1_CHAN3_1ST_TX_DESC_PTR   0x13C914
-#define GT96100_SDMA_G1_CHAN4_CONFIG        0x140900
-#define GT96100_SDMA_G1_CHAN4_COMM          0x140908
-#define GT96100_SDMA_G1_CHAN4_RX_DESC_BASE      0x148900
-#define GT96100_SDMA_G1_CHAN4_CURR_RX_DESC_PTR  0x148910
-#define GT96100_SDMA_G1_CHAN4_TX_DESC_BASE      0x14C900
-#define GT96100_SDMA_G1_CHAN4_CURR_TX_DESC_PTR  0x14C910
-#define GT96100_SDMA_G1_CHAN4_1ST_TX_DESC_PTR   0x14C914
-#define GT96100_SDMA_G1_CHAN5_CONFIG        0x150900
-#define GT96100_SDMA_G1_CHAN5_COMM          0x150908
-#define GT96100_SDMA_G1_CHAN5_RX_DESC_BASE      0x158900
-#define GT96100_SDMA_G1_CHAN5_CURR_RX_DESC_PTR  0x158910
-#define GT96100_SDMA_G1_CHAN5_TX_DESC_BASE      0x15C900
-#define GT96100_SDMA_G1_CHAN5_CURR_TX_DESC_PTR  0x15C910
-#define GT96100_SDMA_G1_CHAN5_1ST_TX_DESC_PTR   0x15C914
-#define GT96100_SDMA_G1_CHAN6_CONFIG        0x160900
-#define GT96100_SDMA_G1_CHAN6_COMM          0x160908
-#define GT96100_SDMA_G1_CHAN6_RX_DESC_BASE      0x168900
-#define GT96100_SDMA_G1_CHAN6_CURR_RX_DESC_PTR  0x168910
-#define GT96100_SDMA_G1_CHAN6_TX_DESC_BASE      0x16C900
-#define GT96100_SDMA_G1_CHAN6_CURR_TX_DESC_PTR  0x16C910
-#define GT96100_SDMA_G1_CHAN6_1ST_TX_DESC_PTR   0x16C914
-#define GT96100_SDMA_G1_CHAN7_CONFIG        0x170900
-#define GT96100_SDMA_G1_CHAN7_COMM          0x170908
-#define GT96100_SDMA_G1_CHAN7_RX_DESC_BASE      0x178900
-#define GT96100_SDMA_G1_CHAN7_CURR_RX_DESC_PTR  0x178910
-#define GT96100_SDMA_G1_CHAN7_TX_DESC_BASE      0x17C900
-#define GT96100_SDMA_G1_CHAN7_CURR_TX_DESC_PTR  0x17C910
-#define GT96100_SDMA_G1_CHAN7_1ST_TX_DESC_PTR   0x17C914
-/*  MPSCs  */
-#define GT96100_MPSC0_MAIN_CONFIG_LOW   0x000A00
-#define GT96100_MPSC0_MAIN_CONFIG_HIGH  0x000A04
-#define GT96100_MPSC0_PROTOCOL_CONFIG   0x000A08
-#define GT96100_MPSC_CHAN0_REG1         0x000A0C
-#define GT96100_MPSC_CHAN0_REG2         0x000A10
-#define GT96100_MPSC_CHAN0_REG3         0x000A14
-#define GT96100_MPSC_CHAN0_REG4         0x000A18
-#define GT96100_MPSC_CHAN0_REG5         0x000A1C
-#define GT96100_MPSC_CHAN0_REG6         0x000A20
-#define GT96100_MPSC_CHAN0_REG7         0x000A24
-#define GT96100_MPSC_CHAN0_REG8         0x000A28
-#define GT96100_MPSC_CHAN0_REG9         0x000A2C
-#define GT96100_MPSC_CHAN0_REG10        0x000A30
-#define GT96100_MPSC_CHAN0_REG11        0x000A34
-#define GT96100_MPSC1_MAIN_CONFIG_LOW   0x008A00
-#define GT96100_MPSC1_MAIN_CONFIG_HIGH  0x008A04
-#define GT96100_MPSC1_PROTOCOL_CONFIG   0x008A08
-#define GT96100_MPSC_CHAN1_REG1         0x008A0C
-#define GT96100_MPSC_CHAN1_REG2         0x008A10
-#define GT96100_MPSC_CHAN1_REG3         0x008A14
-#define GT96100_MPSC_CHAN1_REG4         0x008A18
-#define GT96100_MPSC_CHAN1_REG5         0x008A1C
-#define GT96100_MPSC_CHAN1_REG6         0x008A20
-#define GT96100_MPSC_CHAN1_REG7         0x008A24
-#define GT96100_MPSC_CHAN1_REG8         0x008A28
-#define GT96100_MPSC_CHAN1_REG9         0x008A2C
-#define GT96100_MPSC_CHAN1_REG10        0x008A30
-#define GT96100_MPSC_CHAN1_REG11        0x008A34
-#define GT96100_MPSC2_MAIN_CONFIG_LOW   0x010A00
-#define GT96100_MPSC2_MAIN_CONFIG_HIGH  0x010A04
-#define GT96100_MPSC2_PROTOCOL_CONFIG   0x010A08
-#define GT96100_MPSC_CHAN2_REG1         0x010A0C
-#define GT96100_MPSC_CHAN2_REG2         0x010A10
-#define GT96100_MPSC_CHAN2_REG3         0x010A14
-#define GT96100_MPSC_CHAN2_REG4         0x010A18
-#define GT96100_MPSC_CHAN2_REG5         0x010A1C
-#define GT96100_MPSC_CHAN2_REG6         0x010A20
-#define GT96100_MPSC_CHAN2_REG7         0x010A24
-#define GT96100_MPSC_CHAN2_REG8         0x010A28
-#define GT96100_MPSC_CHAN2_REG9         0x010A2C
-#define GT96100_MPSC_CHAN2_REG10        0x010A30
-#define GT96100_MPSC_CHAN2_REG11        0x010A34
-#define GT96100_MPSC3_MAIN_CONFIG_LOW   0x018A00
-#define GT96100_MPSC3_MAIN_CONFIG_HIGH  0x018A04
-#define GT96100_MPSC3_PROTOCOL_CONFIG   0x018A08
-#define GT96100_MPSC_CHAN3_REG1         0x018A0C
-#define GT96100_MPSC_CHAN3_REG2         0x018A10
-#define GT96100_MPSC_CHAN3_REG3         0x018A14
-#define GT96100_MPSC_CHAN3_REG4         0x018A18
-#define GT96100_MPSC_CHAN3_REG5         0x018A1C
-#define GT96100_MPSC_CHAN3_REG6         0x018A20
-#define GT96100_MPSC_CHAN3_REG7         0x018A24
-#define GT96100_MPSC_CHAN3_REG8         0x018A28
-#define GT96100_MPSC_CHAN3_REG9         0x018A2C
-#define GT96100_MPSC_CHAN3_REG10        0x018A30
-#define GT96100_MPSC_CHAN3_REG11        0x018A34
-#define GT96100_MPSC4_MAIN_CONFIG_LOW   0x020A00
-#define GT96100_MPSC4_MAIN_CONFIG_HIGH  0x020A04
-#define GT96100_MPSC4_PROTOCOL_CONFIG   0x020A08
-#define GT96100_MPSC_CHAN4_REG1         0x020A0C
-#define GT96100_MPSC_CHAN4_REG2         0x020A10
-#define GT96100_MPSC_CHAN4_REG3         0x020A14
-#define GT96100_MPSC_CHAN4_REG4         0x020A18
-#define GT96100_MPSC_CHAN4_REG5         0x020A1C
-#define GT96100_MPSC_CHAN4_REG6         0x020A20
-#define GT96100_MPSC_CHAN4_REG7         0x020A24
-#define GT96100_MPSC_CHAN4_REG8         0x020A28
-#define GT96100_MPSC_CHAN4_REG9         0x020A2C
-#define GT96100_MPSC_CHAN4_REG10        0x020A30
-#define GT96100_MPSC_CHAN4_REG11        0x020A34
-#define GT96100_MPSC5_MAIN_CONFIG_LOW   0x028A00
-#define GT96100_MPSC5_MAIN_CONFIG_HIGH  0x028A04
-#define GT96100_MPSC5_PROTOCOL_CONFIG   0x028A08
-#define GT96100_MPSC_CHAN5_REG1         0x028A0C
-#define GT96100_MPSC_CHAN5_REG2         0x028A10
-#define GT96100_MPSC_CHAN5_REG3         0x028A14
-#define GT96100_MPSC_CHAN5_REG4         0x028A18
-#define GT96100_MPSC_CHAN5_REG5         0x028A1C
-#define GT96100_MPSC_CHAN5_REG6         0x028A20
-#define GT96100_MPSC_CHAN5_REG7         0x028A24
-#define GT96100_MPSC_CHAN5_REG8         0x028A28
-#define GT96100_MPSC_CHAN5_REG9         0x028A2C
-#define GT96100_MPSC_CHAN5_REG10        0x028A30
-#define GT96100_MPSC_CHAN5_REG11        0x028A34
-#define GT96100_MPSC6_MAIN_CONFIG_LOW   0x030A00
-#define GT96100_MPSC6_MAIN_CONFIG_HIGH  0x030A04
-#define GT96100_MPSC6_PROTOCOL_CONFIG   0x030A08
-#define GT96100_MPSC_CHAN6_REG1         0x030A0C
-#define GT96100_MPSC_CHAN6_REG2         0x030A10
-#define GT96100_MPSC_CHAN6_REG3         0x030A14
-#define GT96100_MPSC_CHAN6_REG4         0x030A18
-#define GT96100_MPSC_CHAN6_REG5         0x030A1C
-#define GT96100_MPSC_CHAN6_REG6         0x030A20
-#define GT96100_MPSC_CHAN6_REG7         0x030A24
-#define GT96100_MPSC_CHAN6_REG8         0x030A28
-#define GT96100_MPSC_CHAN6_REG9         0x030A2C
-#define GT96100_MPSC_CHAN6_REG10        0x030A30
-#define GT96100_MPSC_CHAN6_REG11        0x030A34
-#define GT96100_MPSC7_MAIN_CONFIG_LOW   0x038A00
-#define GT96100_MPSC7_MAIN_CONFIG_HIGH  0x038A04
-#define GT96100_MPSC7_PROTOCOL_CONFIG   0x038A08
-#define GT96100_MPSC_CHAN7_REG1         0x038A0C
-#define GT96100_MPSC_CHAN7_REG2         0x038A10
-#define GT96100_MPSC_CHAN7_REG3         0x038A14
-#define GT96100_MPSC_CHAN7_REG4         0x038A18
-#define GT96100_MPSC_CHAN7_REG5         0x038A1C
-#define GT96100_MPSC_CHAN7_REG6         0x038A20
-#define GT96100_MPSC_CHAN7_REG7         0x038A24
-#define GT96100_MPSC_CHAN7_REG8         0x038A28
-#define GT96100_MPSC_CHAN7_REG9         0x038A2C
-#define GT96100_MPSC_CHAN7_REG10        0x038A30
-#define GT96100_MPSC_CHAN7_REG11        0x038A34
-/*  FlexTDMs  */
-/* TDPR0 - Transmit Dual Port RAM. block size 0xff */
-#define GT96100_FXTDM0_TDPR0_BLK0_BASE  0x000B00
-#define GT96100_FXTDM0_TDPR0_BLK1_BASE  0x001B00
-#define GT96100_FXTDM0_TDPR0_BLK2_BASE  0x002B00
-#define GT96100_FXTDM0_TDPR0_BLK3_BASE  0x003B00
-/* RDPR0 - Receive Dual Port RAM. block size 0xff */
-#define GT96100_FXTDM0_RDPR0_BLK0_BASE  0x004B00
-#define GT96100_FXTDM0_RDPR0_BLK1_BASE  0x005B00
-#define GT96100_FXTDM0_RDPR0_BLK2_BASE  0x006B00
-#define GT96100_FXTDM0_RDPR0_BLK3_BASE  0x007B00
-#define GT96100_FXTDM0_TX_READ_PTR      0x008B00
-#define GT96100_FXTDM0_RX_READ_PTR      0x008B04
-#define GT96100_FXTDM0_CONFIG       0x008B08
-#define GT96100_FXTDM0_AUX_CHANA_TX 0x008B0C
-#define GT96100_FXTDM0_AUX_CHANA_RX 0x008B10
-#define GT96100_FXTDM0_AUX_CHANB_TX 0x008B14
-#define GT96100_FXTDM0_AUX_CHANB_RX 0x008B18
-#define GT96100_FXTDM1_TDPR1_BLK0_BASE  0x010B00
-#define GT96100_FXTDM1_TDPR1_BLK1_BASE  0x011B00
-#define GT96100_FXTDM1_TDPR1_BLK2_BASE  0x012B00
-#define GT96100_FXTDM1_TDPR1_BLK3_BASE  0x013B00
-#define GT96100_FXTDM1_RDPR1_BLK0_BASE  0x014B00
-#define GT96100_FXTDM1_RDPR1_BLK1_BASE  0x015B00
-#define GT96100_FXTDM1_RDPR1_BLK2_BASE  0x016B00
-#define GT96100_FXTDM1_RDPR1_BLK3_BASE  0x017B00
-#define GT96100_FXTDM1_TX_READ_PTR      0x018B00
-#define GT96100_FXTDM1_RX_READ_PTR      0x018B04
-#define GT96100_FXTDM1_CONFIG       0x018B08
-#define GT96100_FXTDM1_AUX_CHANA_TX 0x018B0C
-#define GT96100_FXTDM1_AUX_CHANA_RX 0x018B10
-#define GT96100_FLTDM1_AUX_CHANB_TX 0x018B14
-#define GT96100_FLTDM1_AUX_CHANB_RX 0x018B18
-#define GT96100_FLTDM2_TDPR2_BLK0_BASE  0x020B00
-#define GT96100_FLTDM2_TDPR2_BLK1_BASE  0x021B00
-#define GT96100_FLTDM2_TDPR2_BLK2_BASE  0x022B00
-#define GT96100_FLTDM2_TDPR2_BLK3_BASE  0x023B00
-#define GT96100_FLTDM2_RDPR2_BLK0_BASE  0x024B00
-#define GT96100_FLTDM2_RDPR2_BLK1_BASE  0x025B00
-#define GT96100_FLTDM2_RDPR2_BLK2_BASE  0x026B00
-#define GT96100_FLTDM2_RDPR2_BLK3_BASE  0x027B00
-#define GT96100_FLTDM2_TX_READ_PTR      0x028B00
-#define GT96100_FLTDM2_RX_READ_PTR      0x028B04
-#define GT96100_FLTDM2_CONFIG       0x028B08
-#define GT96100_FLTDM2_AUX_CHANA_TX 0x028B0C
-#define GT96100_FLTDM2_AUX_CHANA_RX 0x028B10
-#define GT96100_FLTDM2_AUX_CHANB_TX 0x028B14
-#define GT96100_FLTDM2_AUX_CHANB_RX 0x028B18
-#define GT96100_FLTDM3_TDPR3_BLK0_BASE  0x030B00
-#define GT96100_FLTDM3_TDPR3_BLK1_BASE  0x031B00
-#define GT96100_FLTDM3_TDPR3_BLK2_BASE  0x032B00
-#define GT96100_FLTDM3_TDPR3_BLK3_BASE  0x033B00
-#define GT96100_FXTDM3_RDPR3_BLK0_BASE  0x034B00
-#define GT96100_FXTDM3_RDPR3_BLK1_BASE  0x035B00
-#define GT96100_FXTDM3_RDPR3_BLK2_BASE  0x036B00
-#define GT96100_FXTDM3_RDPR3_BLK3_BASE  0x037B00
-#define GT96100_FXTDM3_TX_READ_PTR      0x038B00
-#define GT96100_FXTDM3_RX_READ_PTR      0x038B04
-#define GT96100_FXTDM3_CONFIG       0x038B08
-#define GT96100_FXTDM3_AUX_CHANA_TX 0x038B0C
-#define GT96100_FXTDM3_AUX_CHANA_RX 0x038B10
-#define GT96100_FXTDM3_AUX_CHANB_TX 0x038B14
-#define GT96100_FXTDM3_AUX_CHANB_RX 0x038B18
-/*  Baud Rate Generators  */
-#define GT96100_BRG0_CONFIG     0x102A00
-#define GT96100_BRG0_BAUD_TUNE  0x102A04
-#define GT96100_BRG1_CONFIG     0x102A08
-#define GT96100_BRG1_BAUD_TUNE  0x102A0C
-#define GT96100_BRG2_CONFIG     0x102A10
-#define GT96100_BRG2_BAUD_TUNE  0x102A14
-#define GT96100_BRG3_CONFIG     0x102A18
-#define GT96100_BRG3_BAUD_TUNE  0x102A1C
-#define GT96100_BRG4_CONFIG     0x102A20
-#define GT96100_BRG4_BAUD_TUNE  0x102A24
-#define GT96100_BRG5_CONFIG     0x102A28
-#define GT96100_BRG5_BAUD_TUNE  0x102A2C
-#define GT96100_BRG6_CONFIG     0x102A30
-#define GT96100_BRG6_BAUD_TUNE  0x102A34
-#define GT96100_BRG7_CONFIG     0x102A38
-#define GT96100_BRG7_BAUD_TUNE  0x102A3C
-/*  Routing Registers  */
-#define GT96100_ROUTE_MAIN      0x101A00
-#define GT96100_ROUTE_RX_CLOCK  0x101A10
-#define GT96100_ROUTE_TX_CLOCK  0x101A20
-/*  General Purpose Ports  */
-#define GT96100_GPP_CONFIG0     0x100A00
-#define GT96100_GPP_CONFIG1     0x100A04
-#define GT96100_GPP_CONFIG2     0x100A08
-#define GT96100_GPP_CONFIG3     0x100A0C
-#define GT96100_GPP_IO0         0x100A20
-#define GT96100_GPP_IO1         0x100A24
-#define GT96100_GPP_IO2         0x100A28
-#define GT96100_GPP_IO3         0x100A2C
-#define GT96100_GPP_DATA0       0x100A40
-#define GT96100_GPP_DATA1       0x100A44
-#define GT96100_GPP_DATA2       0x100A48
-#define GT96100_GPP_DATA3       0x100A4C
-#define GT96100_GPP_LEVEL0      0x100A60
-#define GT96100_GPP_LEVEL1      0x100A64
-#define GT96100_GPP_LEVEL2      0x100A68
-#define GT96100_GPP_LEVEL3      0x100A6C
-/*  Watchdog  */
-#define GT96100_WD_CONFIG   0x101A80
-#define GT96100_WD_VALUE    0x101A84
-/* Communication Unit Arbiter  */
-#define GT96100_COMM_UNIT_ARBTR_CONFIG 0x101AC0
-/*  PCI Arbiters  */
-#define GT96100_PCI0_ARBTR_CONFIG 0x101AE0
-#define GT96100_PCI1_ARBTR_CONFIG 0x101AE4
-/* CIU Arbiter */
-#define GT96100_CIU_ARBITER_CONFIG 0x101AC0
-/* Interrupt Controller */
-#define GT96100_MAIN_CAUSE     0x000C18
-#define GT96100_INT0_MAIN_MASK 0x000C1C
-#define GT96100_INT1_MAIN_MASK 0x000C24
-#define GT96100_HIGH_CAUSE     0x000C98
-#define GT96100_INT0_HIGH_MASK 0x000C9C
-#define GT96100_INT1_HIGH_MASK 0x000CA4
-#define GT96100_INT0_SELECT    0x000C70
-#define GT96100_INT1_SELECT    0x000C74
-#define GT96100_SERIAL_CAUSE   0x103A00
-#define GT96100_SERINT0_MASK   0x103A80
-#define GT96100_SERINT1_MASK   0x103A88
-
-#endif /*  _GT96100_H */
index 25f5e8a4177d1378fb60645483a4e364c1e879c1..0fe02945feba0b8a18868126a99d977558294d33 100644 (file)
 
 
 #ifdef __ASSEMBLY__
-
-       .macro  _ssnop
-       sll     $0, $0, 1
-       .endm
-
-       .macro  _ehb
-       sll     $0, $0, 3
-       .endm
-
-/*
- * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
- * use of the JTLB for instructions should not occur for 4 cpu cycles and use
- * for data translations should not occur for 3 cpu cycles.
- */
-#ifdef CONFIG_CPU_RM9000
-
-       .macro  mtc0_tlbw_hazard
-       .set    push
-       .set    mips32
-       _ssnop; _ssnop; _ssnop; _ssnop
-       .set    pop
-       .endm
-
-       .macro  tlbw_eret_hazard
-       .set    push
-       .set    mips32
-       _ssnop; _ssnop; _ssnop; _ssnop
-       .set    pop
-       .endm
-
+#define ASMMACRO(name, code...) .macro name; code; .endm
 #else
 
-/*
- * The taken branch will result in a two cycle penalty for the two killed
- * instructions on R4000 / R4400.  Other processors only have a single cycle
- * hazard so this is nice trick to have an optimal code for a range of
- * processors.
- */
-       .macro  mtc0_tlbw_hazard
-       b       . + 8
-       .endm
+#define ASMMACRO(name, code...)                                                \
+__asm__(".macro " #name "; " #code "; .endm");                         \
+                                                                       \
+static inline void name(void)                                          \
+{                                                                      \
+       __asm__ __volatile__ (#name);                                   \
+}
 
-       .macro  tlbw_eret_hazard
-       .endm
 #endif
 
+ASMMACRO(_ssnop,
+        sll    $0, $0, 1
+       )
+
+ASMMACRO(_ehb,
+        sll    $0, $0, 3
+       )
+
 /*
- * mtc0->mfc0 hazard
- * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
- * It is a MIPS32R2 processor so ehb will clear the hazard.
+ * TLB hazards
  */
+#if defined(CONFIG_CPU_MIPSR2)
 
-#ifdef CONFIG_CPU_MIPSR2
 /*
- * Use a macro for ehb unless explicit support for MIPSR2 is enabled
+ * MIPSR2 defines ehb for hazard avoidance
  */
 
-#define irq_enable_hazard                                              \
+ASMMACRO(mtc0_tlbw_hazard,
+        _ehb
+       )
+ASMMACRO(tlbw_use_hazard,
+        _ehb
+       )
+ASMMACRO(tlb_probe_hazard,
+        _ehb
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
        _ehb
-
-#define irq_disable_hazard                                             \
-       _ehb
-
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
-
+       )
+ASMMACRO(back_to_back_c0_hazard,
+        _ehb
+       )
 /*
- * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
+ * gcc has a tradition of misscompiling the previous construct using the
+ * address of a label as argument to inline assembler.  Gas otoh has the
+ * annoying difference between la and dla which are only usable for 32-bit
+ * rsp. 64-bit code, so can't be used without conditional compilation.
+ * The alterantive is switching the assembler to 64-bit code which happens
+ * to work right even for 32-bit code ...
  */
+#define instruction_hazard()                                           \
+do {                                                                   \
+       unsigned long tmp;                                              \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    mips64r2                                \n"     \
+       "       dla     %0, 1f                                  \n"     \
+       "       jr.hb   %0                                      \n"     \
+       "       .set    mips0                                   \n"     \
+       "1:                                                     \n"     \
+       : "=r" (tmp));                                                  \
+} while (0)
 
-#define irq_enable_hazard
-
-#define irq_disable_hazard
-
-#else
+#elif defined(CONFIG_CPU_R10000)
 
 /*
- * Classic MIPS needs 1 - 3 nops or ssnops
+ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
  */
-#define irq_enable_hazard
-#define irq_disable_hazard                                             \
-       _ssnop; _ssnop; _ssnop
 
-#endif
-
-#else /* __ASSEMBLY__ */
-
-__asm__(
-       "       .macro  _ssnop                                  \n"
-       "       sll     $0, $0, 1                               \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro  _ehb                                    \n"
-       "       sll     $0, $0, 3                               \n"
-       "       .endm                                           \n");
+ASMMACRO(mtc0_tlbw_hazard,
+       )
+ASMMACRO(tlbw_use_hazard,
+       )
+ASMMACRO(tlb_probe_hazard,
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+       )
+ASMMACRO(back_to_back_c0_hazard,
+       )
+#define instruction_hazard() do { } while (0)
 
-#ifdef CONFIG_CPU_RM9000
+#elif defined(CONFIG_CPU_RM9000)
 
 /*
  * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
@@ -115,176 +108,73 @@ __asm__(
  * for data translations should not occur for 3 cpu cycles.
  */
 
-#define mtc0_tlbw_hazard()                                             \
-       __asm__ __volatile__(                                           \
-       "       .set    mips32                                  \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       .set    mips0                                   \n")
-
-#define tlbw_use_hazard()                                              \
-       __asm__ __volatile__(                                           \
-       "       .set    mips32                                  \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       .set    mips0                                   \n")
-
-#else
-
-/*
- * Overkill warning ...
- */
-#define mtc0_tlbw_hazard()                                             \
-       __asm__ __volatile__(                                           \
-       "       .set    noreorder                               \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       .set    reorder                                 \n")
-
-#define tlbw_use_hazard()                                              \
-       __asm__ __volatile__(                                           \
-       "       .set    noreorder                               \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       .set    reorder                                 \n")
-
-#endif
-
-/*
- * Interrupt enable/disable hazards
- * Some processors have hazards when modifying
- * the status register to change the interrupt state
- */
-
-#ifdef CONFIG_CPU_MIPSR2
-
-__asm__("      .macro  irq_enable_hazard                       \n"
-       "       _ehb                                            \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro  irq_disable_hazard                      \n"
-       "       _ehb                                            \n"
-       "       .endm                                           \n");
+ASMMACRO(mtc0_tlbw_hazard,
+        _ssnop; _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(tlbw_use_hazard,
+        _ssnop; _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(tlb_probe_hazard,
+        _ssnop; _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+       )
+ASMMACRO(back_to_back_c0_hazard,
+       )
+#define instruction_hazard() do { } while (0)
 
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
+#elif defined(CONFIG_CPU_SB1)
 
 /*
- * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
+ * Mostly like R4000 for historic reasons
  */
-
-__asm__(
-       "       .macro  irq_enable_hazard                       \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro  irq_disable_hazard                      \n"
-       "       .endm                                           \n");
+ASMMACRO(mtc0_tlbw_hazard,
+       )
+ASMMACRO(tlbw_use_hazard,
+       )
+ASMMACRO(tlb_probe_hazard,
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+        _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(back_to_back_c0_hazard,
+       )
+#define instruction_hazard() do { } while (0)
 
 #else
 
 /*
- * Default for classic MIPS processors.  Assume worst case hazards but don't
- * care about the irq_enable_hazard - sooner or later the hardware will
- * enable it and we don't care when exactly.
- */
-
-__asm__(
-       "       #                                               \n"
-       "       # There is a hazard but we do not care          \n"
-       "       #                                               \n"
-       "       .macro\tirq_enable_hazard                       \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro\tirq_disable_hazard                      \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       .endm                                           \n");
-
-#endif
-
-#define irq_enable_hazard()                                            \
-       __asm__ __volatile__("irq_enable_hazard")
-#define irq_disable_hazard()                                           \
-       __asm__ __volatile__("irq_disable_hazard")
-
-
-/*
- * Back-to-back hazards -
+ * Finally the catchall case for all other processors including R4000, R4400,
+ * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
  *
- * What is needed to separate a move to cp0 from a subsequent read from the
- * same cp0 register?
- */
-#ifdef CONFIG_CPU_MIPSR2
-
-__asm__("      .macro  back_to_back_c0_hazard                  \n"
-       "       _ehb                                            \n"
-       "       .endm                                           \n");
-
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
-      defined(CONFIG_CPU_SB1)
-
-__asm__("      .macro  back_to_back_c0_hazard                  \n"
-       "       .endm                                           \n");
-
-#else
-
-__asm__("      .macro  back_to_back_c0_hazard                  \n"
-       "       .set    noreorder                               \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       .set    reorder                                 \n"
-       "       .endm");
-
-#endif
-
-#define back_to_back_c0_hazard()                                       \
-       __asm__ __volatile__("back_to_back_c0_hazard")
-
-
-/*
- * Instruction execution hazard
- */
-#ifdef CONFIG_CPU_MIPSR2
-/*
- * gcc has a tradition of misscompiling the previous construct using the
- * address of a label as argument to inline assembler.  Gas otoh has the
- * annoying difference between la and dla which are only usable for 32-bit
- * rsp. 64-bit code, so can't be used without conditional compilation.
- * The alterantive is switching the assembler to 64-bit code which happens
- * to work right even for 32-bit code ...
+ * The taken branch will result in a two cycle penalty for the two killed
+ * instructions on R4000 / R4400.  Other processors only have a single cycle
+ * hazard so this is nice trick to have an optimal code for a range of
+ * processors.
  */
-#define instruction_hazard()                                           \
-do {                                                                   \
-       unsigned long tmp;                                              \
-                                                                       \
-       __asm__ __volatile__(                                           \
-       "       .set    mips64r2                                \n"     \
-       "       dla     %0, 1f                                  \n"     \
-       "       jr.hb   %0                                      \n"     \
-       "       .set    mips0                                   \n"     \
-       "1:                                                     \n"     \
-       : "=r" (tmp));                                                  \
-} while (0)
-
-#else
+ASMMACRO(mtc0_tlbw_hazard,
+       nop
+       )
+ASMMACRO(tlbw_use_hazard,
+       nop; nop; nop
+       )
+ASMMACRO(tlb_probe_hazard,
+        nop; nop; nop
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+       nop; nop; nop
+       )
+ASMMACRO(back_to_back_c0_hazard,
+        _ssnop; _ssnop; _ssnop;
+       )
 #define instruction_hazard() do { } while (0)
-#endif
-
-extern void mips_ihb(void);
 
-#endif /* __ASSEMBLY__ */
+#endif
 
 #endif /* _ASM_HAZARDS_H */
index 896550bad3229cbd388fa8ce9705129ecdf91ca4..d35c61776a0249d5620a8a70a8033b15735f48fc 100644 (file)
@@ -76,8 +76,4 @@ extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
                           unsigned long hwmask);
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-#ifdef CONFIG_SMP
-#define ARCH_HAS_IRQ_PER_CPU
-#endif
-
 #endif /* _ASM_IRQ_H */
index 397522ea55650b0af3f1985105a3efc18296abf1..a73a5698420c1cde3486c42adbd4f5db6d349988 100644 (file)
 #include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
 
+#define ARCH_RTC_LOCATION
+
 #define RTC_PORT(x)    (ATLAS_RTC_ADR_REG + (x) * 8)
 #define RTC_IO_EXTENT  0x100
 #define RTC_IOMAPPED   0
-#define RTC_IRQ                ATLASINT_RTC
+#define RTC_IRQ                ATLAS_INT_RTC
 
 static inline unsigned char CMOS_READ(unsigned long addr)
 {
diff --git a/include/asm-mips/mach-ev96100/mach-gt64120.h b/include/asm-mips/mach-ev96100/mach-gt64120.h
deleted file mode 100644 (file)
index 0ef1e6c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _ASM_GT64120_EV96100_GT64120_DEP_H
-#define _ASM_GT64120_EV96100_GT64120_DEP_H
-
-/*
- *   GT96100 config space base address
- */
-#define GT64120_BASE   (KSEG1ADDR(0x14000000))
-
-/*
- *   PCI Bus allocation
- *
- *   (Guessing ...)
- */
-#define GT_PCI_MEM_BASE        0x12000000UL
-#define GT_PCI_MEM_SIZE        0x02000000UL
-#define GT_PCI_IO_BASE 0x10000000UL
-#define GT_PCI_IO_SIZE 0x02000000UL
-#define GT_ISA_IO_BASE PCI_IO_BASE
-
-/*
- *   Duart I/O ports.
- */
-#define EV96100_COM1_BASE_ADDR (0xBD000000 + 0x20)
-#define EV96100_COM2_BASE_ADDR (0xBD000000 + 0x00)
-
-
-/*
- *   EV96100 interrupt controller register base.
- */
-#define EV96100_ICTRL_REGS_BASE        (KSEG1ADDR(0x1f000000))
-
-/*
- *   EV96100 UART register base.
- */
-#define EV96100_UART0_REGS_BASE        EV96100_COM1_BASE_ADDR
-#define EV96100_UART1_REGS_BASE        EV96100_COM2_BASE_ADDR
-#define EV96100_BASE_BAUD      ( 3686400 / 16 )
-
-#endif /* _ASM_GT64120_EV96100_GT64120_DEP_H */
index 130bd4b8edcea3210b703a9e441a09826ecb3587..4c29ba44992c11e8b1ffce23099b34dba6906512 100644 (file)
@@ -7,7 +7,7 @@
 
 #define EXCITE_CPU_EXT_CLOCK 100000000
 
-#if !defined(__ASSEMBLER__)
+#if !defined(__ASSEMBLY__)
 void __init excite_kgdb_init(void);
 void excite_procfs_init(void);
 extern unsigned long memsize;
diff --git a/include/asm-mips/mach-excite/excite_fpga.h b/include/asm-mips/mach-excite/excite_fpga.h
new file mode 100644 (file)
index 0000000..38fcda7
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef EXCITE_FPGA_H_INCLUDED
+#define EXCITE_FPGA_H_INCLUDED
+
+
+/**
+ * Adress alignment of the individual FPGA bytes.
+ * The address arrangement of the individual bytes of the FPGA is two
+ * byte aligned at the embedded MK2 platform.
+ */
+#ifdef EXCITE_CCI_FPGA_MK2
+typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
+#else
+typedef unsigned char excite_cci_fpga_align_t;
+#endif
+
+
+/**
+ * Size of Dual Ported RAM.
+ */
+#define EXCITE_DPR_SIZE 263
+
+
+/**
+ * Size of Reserved Status Fields in Dual Ported RAM.
+ */
+#define EXCITE_DPR_STATUS_SIZE 7
+
+
+
+/**
+ * FPGA.
+ * Hardware register layout of the FPGA interface. The FPGA must accessed
+ * byte wise solely.
+ * @see EXCITE_CCI_DPR_MK2
+ */
+typedef struct excite_fpga {
+
+       /**
+        * Dual Ported RAM.
+        */
+       excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
+
+       /**
+        * Status.
+        */
+       excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
+
+#ifdef EXCITE_CCI_FPGA_MK2
+       /**
+        * RM9000 Interrupt.
+        * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
+        */
+       excite_cci_fpga_align_t rm9k_int;
+#else
+       /**
+        * MK2 Interrupt.
+        * Write access initiates interrupt at the ARM processor of the MK2.
+        */
+       excite_cci_fpga_align_t mk2_int;
+
+       excite_cci_fpga_align_t gap[0x1000-0x10f];
+
+       /**
+        * IRQ Source/Acknowledge.
+        */
+       excite_cci_fpga_align_t rm9k_irq_src;
+
+       /**
+        * IRQ Mask.
+        * Set bits enable the related interrupt.
+        */
+       excite_cci_fpga_align_t rm9k_irq_mask;
+#endif
+
+
+} excite_fpga;
+
+
+
+#endif /* ndef EXCITE_FPGA_H_INCLUDED */
index f4e370e271684e9fb8884a41c0c592c2e5cb9e4a..529445dacedb7283f44b3430ebdfb27602a76da2 100644 (file)
@@ -20,7 +20,7 @@
 
 #define cpu_has_llsc           1
 #define cpu_has_vtag_icache    0
-#define cpu_has_dc_aliases     (PAGE_SIZE < 0x4000)
+#define cpu_has_dc_aliases     0
 #define cpu_has_ic_fills_f_dc  0
 
 #define cpu_has_dsp            0
index fd7ebc54fa901ff7384df77024dca98abf6e257e..b15e4ea0b0911bdffa62b3c122663d9f8b8a5134 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2006  MIPS Technologies, Inc.  All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
 #ifndef _MIPS_ATLASINT_H
 #define _MIPS_ATLASINT_H
 
-#define ATLASINT_BASE          1
-#define ATLASINT_UART          (ATLASINT_BASE+0)
-#define ATLASINT_TIM0          (ATLASINT_BASE+1)
-#define ATLASINT_RES2          (ATLASINT_BASE+2)
-#define ATLASINT_RES3          (ATLASINT_BASE+3)
-#define ATLASINT_RTC           (ATLASINT_BASE+4)
-#define ATLASINT_COREHI                (ATLASINT_BASE+5)
-#define ATLASINT_CORELO                (ATLASINT_BASE+6)
-#define ATLASINT_RES7          (ATLASINT_BASE+7)
-#define ATLASINT_PCIA          (ATLASINT_BASE+8)
-#define ATLASINT_PCIB          (ATLASINT_BASE+9)
-#define ATLASINT_PCIC          (ATLASINT_BASE+10)
-#define ATLASINT_PCID          (ATLASINT_BASE+11)
-#define ATLASINT_ENUM          (ATLASINT_BASE+12)
-#define ATLASINT_DEG           (ATLASINT_BASE+13)
-#define ATLASINT_ATXFAIL       (ATLASINT_BASE+14)
-#define ATLASINT_INTA          (ATLASINT_BASE+15)
-#define ATLASINT_INTB          (ATLASINT_BASE+16)
-#define ATLASINT_ETH           ATLASINT_INTB
-#define ATLASINT_INTC          (ATLASINT_BASE+17)
-#define ATLASINT_SCSI          ATLASINT_INTC
-#define ATLASINT_INTD          (ATLASINT_BASE+18)
-#define ATLASINT_SERR          (ATLASINT_BASE+19)
-#define ATLASINT_RES20         (ATLASINT_BASE+20)
-#define ATLASINT_RES21         (ATLASINT_BASE+21)
-#define ATLASINT_RES22         (ATLASINT_BASE+22)
-#define ATLASINT_RES23         (ATLASINT_BASE+23)
-#define ATLASINT_RES24         (ATLASINT_BASE+24)
-#define ATLASINT_RES25         (ATLASINT_BASE+25)
-#define ATLASINT_RES26         (ATLASINT_BASE+26)
-#define ATLASINT_RES27         (ATLASINT_BASE+27)
-#define ATLASINT_RES28         (ATLASINT_BASE+28)
-#define ATLASINT_RES29         (ATLASINT_BASE+29)
-#define ATLASINT_RES30         (ATLASINT_BASE+30)
-#define ATLASINT_RES31         (ATLASINT_BASE+31)
-#define ATLASINT_END           (ATLASINT_BASE+31)
+/*
+ * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
+ */
+#define MIPSCPU_INT_BASE       0
+
+/* CPU interrupt offsets */
+#define MIPSCPU_INT_SW0                0
+#define MIPSCPU_INT_SW1                1
+#define MIPSCPU_INT_MB0                2
+#define MIPSCPU_INT_ATLAS      MIPSCPU_INT_MB0
+#define MIPSCPU_INT_MB1                3
+#define MIPSCPU_INT_MB2                4
+#define MIPSCPU_INT_MB3                5
+#define MIPSCPU_INT_MB4                6
+#define MIPSCPU_INT_CPUCTR     7
+
+/*
+ * Interrupts 8..39 are used for Atlas interrupt controller interrupts
+ */
+#define ATLAS_INT_BASE         8
+#define ATLAS_INT_UART         (ATLAS_INT_BASE + 0)
+#define ATLAS_INT_TIM0         (ATLAS_INT_BASE + 1)
+#define ATLAS_INT_RES2         (ATLAS_INT_BASE + 2)
+#define ATLAS_INT_RES3         (ATLAS_INT_BASE + 3)
+#define ATLAS_INT_RTC          (ATLAS_INT_BASE + 4)
+#define ATLAS_INT_COREHI       (ATLAS_INT_BASE + 5)
+#define ATLAS_INT_CORELO       (ATLAS_INT_BASE + 6)
+#define ATLAS_INT_RES7         (ATLAS_INT_BASE + 7)
+#define ATLAS_INT_PCIA         (ATLAS_INT_BASE + 8)
+#define ATLAS_INT_PCIB         (ATLAS_INT_BASE + 9)
+#define ATLAS_INT_PCIC         (ATLAS_INT_BASE + 10)
+#define ATLAS_INT_PCID         (ATLAS_INT_BASE + 11)
+#define ATLAS_INT_ENUM         (ATLAS_INT_BASE + 12)
+#define ATLAS_INT_DEG          (ATLAS_INT_BASE + 13)
+#define ATLAS_INT_ATXFAIL      (ATLAS_INT_BASE + 14)
+#define ATLAS_INT_INTA         (ATLAS_INT_BASE + 15)
+#define ATLAS_INT_INTB         (ATLAS_INT_BASE + 16)
+#define ATLAS_INT_ETH          ATLAS_INT_INTB
+#define ATLAS_INT_INTC         (ATLAS_INT_BASE + 17)
+#define ATLAS_INT_SCSI         ATLAS_INT_INTC
+#define ATLAS_INT_INTD         (ATLAS_INT_BASE + 18)
+#define ATLAS_INT_SERR         (ATLAS_INT_BASE + 19)
+#define ATLAS_INT_RES20                (ATLAS_INT_BASE + 20)
+#define ATLAS_INT_RES21                (ATLAS_INT_BASE + 21)
+#define ATLAS_INT_RES22                (ATLAS_INT_BASE + 22)
+#define ATLAS_INT_RES23                (ATLAS_INT_BASE + 23)
+#define ATLAS_INT_RES24                (ATLAS_INT_BASE + 24)
+#define ATLAS_INT_RES25                (ATLAS_INT_BASE + 25)
+#define ATLAS_INT_RES26                (ATLAS_INT_BASE + 26)
+#define ATLAS_INT_RES27                (ATLAS_INT_BASE + 27)
+#define ATLAS_INT_RES28                (ATLAS_INT_BASE + 28)
+#define ATLAS_INT_RES29                (ATLAS_INT_BASE + 29)
+#define ATLAS_INT_RES30                (ATLAS_INT_BASE + 30)
+#define ATLAS_INT_RES31                (ATLAS_INT_BASE + 31)
+#define ATLAS_INT_END          (ATLAS_INT_BASE + 31)
+
+/*
+ * Interrupts 64..127 are used for Soc-it Classic interrupts
+ */
+#define MSC01C_INT_BASE                64
+
+/* SOC-it Classic interrupt offsets */
+#define MSC01C_INT_TMR         0
+#define MSC01C_INT_PCI         1
+
+/*
+ * Interrupts 64..127 are used for Soc-it EIC interrupts
+ */
+#define MSC01E_INT_BASE                64
+
+/* SOC-it EIC interrupt offsets */
+#define        MSC01E_INT_SW0          1
+#define        MSC01E_INT_SW1          2
+#define        MSC01E_INT_MB0          3
+#define        MSC01E_INT_ATLAS        MSC01E_INT_MB0
+#define        MSC01E_INT_MB1          4
+#define        MSC01E_INT_MB2          5
+#define        MSC01E_INT_MB3          6
+#define        MSC01E_INT_MB4          7
+#define        MSC01E_INT_TMR          8
+#define        MSC01E_INT_PCI          9
+#define        MSC01E_INT_PERFCTR      10
+#define        MSC01E_INT_CPUCTR       11
 
 #endif /* !(_MIPS_ATLASINT_H) */
index 18b69de87daa14ff4881a5bc10ffd3c999e0be5a..fe065d6070ca3885b4f4f3f9467a87de01fed0e8 100644 (file)
@@ -262,10 +262,10 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
                /* See comments for similar code above */
                prevvpe = dvpe();
                oldasid = (read_c0_entryhi() & ASID_MASK);
-               if(smtc_live_asid[mytlb][oldasid]) {
-                 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
-                 if(smtc_live_asid[mytlb][oldasid] == 0)
-                       smtc_flush_tlb_asid(oldasid);
+               if (smtc_live_asid[mytlb][oldasid]) {
+                       smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+                       if(smtc_live_asid[mytlb][oldasid] == 0)
+                               smtc_flush_tlb_asid(oldasid);
                }
                /* See comments for similar code above */
                write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
index 219d359861f3df8a522914aec8b71b6a88cf5e66..85b258ee7090737d4864ae068f00833bb8e59f53 100644 (file)
@@ -34,6 +34,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/cpu-features.h>
+
 extern void clear_page(void * page);
 extern void copy_page(void * to, void * from);
 
@@ -53,7 +55,7 @@ static inline void clear_user_page(void *addr, unsigned long vaddr,
        extern void (*flush_data_cache_page)(unsigned long addr);
 
        clear_page(addr);
-       if (pages_do_alias((unsigned long) addr, vaddr))
+       if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
                flush_data_cache_page((unsigned long)addr);
 }
 
@@ -63,7 +65,8 @@ static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
        extern void (*flush_data_cache_page)(unsigned long addr);
 
        copy_page(vto, vfrom);
-       if (pages_do_alias((unsigned long)vto, vaddr))
+       if (!cpu_has_ic_fills_f_dc ||
+           pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
                flush_data_cache_page((unsigned long)vto);
 }
 
@@ -74,15 +77,17 @@ static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
   #ifdef CONFIG_CPU_MIPS32
     typedef struct { unsigned long pte_low, pte_high; } pte_t;
     #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+    #define __pte(x)      ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; })
   #else
      typedef struct { unsigned long long pte; } pte_t;
      #define pte_val(x)        ((x).pte)
+     #define __pte(x)  ((pte_t) { (x) } )
   #endif
 #else
 typedef struct { unsigned long pte; } pte_t;
 #define pte_val(x)     ((x).pte)
-#endif
 #define __pte(x)       ((pte_t) { (x) } )
+#endif
 
 /*
  * For 3-level pagetables we defines these ourselves, for 2-level the
index c59a1e21f5b0d26c87c2606a3a64fa74e84487a8..d05fb6f38aa7523c61e943f81d33ab2257058a1d 100644 (file)
 #define PTRS_PER_PMD   ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t))
 #define PTRS_PER_PTE   ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
 
+#if PGDIR_SIZE >= TASK_SIZE
+#define USER_PTRS_PER_PGD       (1)
+#else
 #define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SIZE)
-#define FIRST_USER_ADDRESS     0
+#endif
+#define FIRST_USER_ADDRESS     0UL
 
 #define VMALLOC_START          MAP_BASE
 #define VMALLOC_END    \
index 4113316ee0da595bc6292bb50bbedb19737dcb46..4fb0fc43ffd71af828d8362052612b32b7fcafc1 100644 (file)
@@ -10,8 +10,6 @@
 #define _ASM_PTRACE_H
 
 
-#include <asm/isadep.h>
-
 /* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
 #define FPR_BASE       32
 #define PC             64
@@ -73,6 +71,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #include <linux/linkage.h>
+#include <asm/isadep.h>
 
 /*
  * Does the process account for user or for system time?
index 584bd9c0ab2e862f8267ea78af7c5ede2700acd4..035637c67e7c0ab2c29b62f5d16dc7ce85b42c62 100644 (file)
@@ -52,9 +52,9 @@
 #endif
 
 /*
- * Both Galileo boards have the same UART mappings.
+ * Galileo EV64120 evaluation board
  */
-#if defined (CONFIG_MIPS_EV96100) || defined (CONFIG_MIPS_EV64120)
+#ifdef CONFIG_MIPS_EV64120
 #include <asm/galileo-boards/ev96100.h>
 #include <asm/galileo-boards/ev96100int.h>
 #define EV96100_SERIAL_PORT_DEFNS                                  \
index 335dbaf1d8319a1e1d2c352b12fa75e68e6652ce..a885491217c18da6d6515563e783dce1c11d881a 100644 (file)
  * Note: you'll need to define uint32_t and uint64_t in your headers.
  */
 
-#if !defined(__ASSEMBLER__)
+#if !defined(__ASSEMBLY__)
 #define _SB_MAKE64(x) ((uint64_t)(x))
 #define _SB_MAKE32(x) ((uint32_t)(x))
 #else
  */
 
 
-#if defined(__mips64) && !defined(__ASSEMBLER__)
+#if defined(__mips64) && !defined(__ASSEMBLY__)
 #define SBWRITECSR(csr,val) *((volatile uint64_t *) PHYS_TO_K1(csr)) = (val)
 #define SBREADCSR(csr) (*((volatile uint64_t *) PHYS_TO_K1(csr)))
-#endif /* __ASSEMBLER__ */
+#endif /* __ASSEMBLY__ */
 
 #endif
index f4178bdcfcb08636ec4985a8e52de6d784ae7372..7ed0bb611e56131035cad690422cd49fdbeed224 100644 (file)
  * (For the assembler version, sysrev and dest may be the same register.
  * Also, it clobbers AT.)
  */
-#ifdef __ASSEMBLER__
+#ifdef __ASSEMBLY__
 #define SYS_SOC_TYPE(dest, sysrev)                                     \
        .set push ;                                                     \
        .set reorder ;                                                  \
index 87a1dff9519917d2480025310e54dc6a5dfd9830..8b391a2f0814ad113d4313be9bd84dd351d4a541 100644 (file)
@@ -108,17 +108,8 @@ typedef unsigned long old_sigset_t;                /* at least 32 bits */
 #define SIG_BLOCK      1       /* for blocking signals */
 #define SIG_UNBLOCK    2       /* for unblocking signals */
 #define SIG_SETMASK    3       /* for setting the signal mask */
-#define SIG_SETMASK32  256     /* Goodie from SGI for BSD compatibility:
-                                  set only the low 32 bit of the sigset.  */
 
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-/* Fake signal functions */
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+#include <asm-generic/signal.h>
 
 struct sigaction {
        unsigned int    sa_flags;
index 669b8e349ff29544fce6a35c91307950ba660f4a..c8d5587467bbf6181ba2950fa66bf63c8dcc3858 100644 (file)
@@ -239,7 +239,51 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
        : "memory");
 }
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+       unsigned int tmp;
+       int ret;
+
+       if (R10000_LLSC_WAR) {
+               __asm__ __volatile__(
+               "       .set    noreorder       # __raw_read_trylock    \n"
+               "       li      %2, 0                                   \n"
+               "1:     ll      %1, %3                                  \n"
+               "       bnez    %1, 2f                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       sc      %1, %0                                  \n"
+               "       beqzl   %1, 1b                                  \n"
+               "       .set    reorder                                 \n"
+#ifdef CONFIG_SMP
+               "        sync                                           \n"
+#endif
+               "       li      %2, 1                                   \n"
+               "2:                                                     \n"
+               : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+               : "m" (rw->lock)
+               : "memory");
+       } else {
+               __asm__ __volatile__(
+               "       .set    noreorder       # __raw_read_trylock    \n"
+               "       li      %2, 0                                   \n"
+               "1:     ll      %1, %3                                  \n"
+               "       bnez    %1, 2f                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       sc      %1, %0                                  \n"
+               "       beqz    %1, 1b                                  \n"
+               "       .set    reorder                                 \n"
+#ifdef CONFIG_SMP
+               "        sync                                           \n"
+#endif
+               "       li      %2, 1                                   \n"
+               "2:                                                     \n"
+               : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+               : "m" (rw->lock)
+               : "memory");
+       }
+
+       return ret;
+}
 
 static inline int __raw_write_trylock(raw_rwlock_t *rw)
 {
@@ -283,4 +327,9 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
        return ret;
 }
 
+
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* _ASM_SPINLOCK_H */
index 98aa737b34aa75fc79d582431fcd12bf2bc42a43..b80de8e0fbbda8d8ca9f66dad92c32e25ce6e05a 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _ASM_TIMEX_H
 #define _ASM_TIMEX_H
 
+#ifdef __KERNEL__
+
 #include <asm/mipsregs.h>
 
 /*
@@ -51,4 +53,6 @@ static inline cycles_t get_cycles (void)
        return read_c0_count();
 }
 
+#endif /* __KERNEL__ */
+
 #endif /*  _ASM_TIMEX_H */
index 610ccb8a50b3a6fc1fe427de0c50be79edae646b..c39142920fe6e61bd2610345fd8849a051c54676 100644 (file)
 #define __NR_mknodat                   (__NR_Linux + 290)
 #define __NR_fchownat                  (__NR_Linux + 291)
 #define __NR_futimesat                 (__NR_Linux + 292)
-#define __NR_fstatat                   (__NR_Linux + 293)
+#define __NR_fstatat64                 (__NR_Linux + 293)
 #define __NR_unlinkat                  (__NR_Linux + 294)
 #define __NR_renameat                  (__NR_Linux + 295)
 #define __NR_linkat                    (__NR_Linux + 296)
 #define __NR_tee                       (__NR_Linux + 306)
 #define __NR_vmsplice                  (__NR_Linux + 307)
 #define __NR_move_pages                        (__NR_Linux + 308)
+#define __NR_set_robust_list           (__NR_Linux + 309)
+#define __NR_get_robust_list           (__NR_Linux + 310)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            308
+#define __NR_Linux_syscalls            310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                308
+#define __NR_O32_Linux_syscalls                310
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_mknodat                   (__NR_Linux + 249)
 #define __NR_fchownat                  (__NR_Linux + 250)
 #define __NR_futimesat                 (__NR_Linux + 251)
-#define __NR_fstatat                   (__NR_Linux + 252)
+#define __NR_newfstatat                        (__NR_Linux + 252)
 #define __NR_unlinkat                  (__NR_Linux + 253)
 #define __NR_renameat                  (__NR_Linux + 254)
 #define __NR_linkat                    (__NR_Linux + 255)
 #define __NR_tee                       (__NR_Linux + 265)
 #define __NR_vmsplice                  (__NR_Linux + 266)
 #define __NR_move_pages                        (__NR_Linux + 267)
+#define __NR_set_robust_list           (__NR_Linux + 268)
+#define __NR_get_robust_list           (__NR_Linux + 269)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            267
+#define __NR_Linux_syscalls            269
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         267
+#define __NR_64_Linux_syscalls         269
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_mknodat                   (__NR_Linux + 253)
 #define __NR_fchownat                  (__NR_Linux + 254)
 #define __NR_futimesat                 (__NR_Linux + 255)
-#define __NR_fstatat                   (__NR_Linux + 256)
+#define __NR_newfstatat                        (__NR_Linux + 256)
 #define __NR_unlinkat                  (__NR_Linux + 257)
 #define __NR_renameat                  (__NR_Linux + 258)
 #define __NR_linkat                    (__NR_Linux + 259)
 #define __NR_tee                       (__NR_Linux + 269)
 #define __NR_vmsplice                  (__NR_Linux + 270)
 #define __NR_move_pages                        (__NR_Linux + 271)
+#define __NR_set_robust_list           (__NR_Linux + 272)
+#define __NR_get_robust_list           (__NR_Linux + 273)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            271
+#define __NR_Linux_syscalls            273
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                271
+#define __NR_N32_Linux_syscalls                273
 
 #ifdef __KERNEL__
 
index 89bf8b4cab3c333b07c0388f546dc2bc1ed1286a..61f2a093b91befa8476bbafd52cb291d5588db45 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _ASM_USER_H
 #define _ASM_USER_H
 
+#ifdef __KERNEL__
+
 #include <asm/page.h>
 #include <asm/reg.h>
 
@@ -55,4 +57,6 @@ struct user {
 #define HOST_DATA_START_ADDR   (u.start_data)
 #define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
 
+#endif /* __KERNEL__ */
+
 #endif /* _ASM_USER_H */
index a93960e232cffabb43de39d78a97dc9d7542f154..e1825530365d3d1724b925fabb54a125429cd564 100644 (file)
@@ -152,4 +152,8 @@ static __inline__ int __raw_write_can_lock(raw_rwlock_t *rw)
        return !rw->counter;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SPINLOCK_H */
index f44b529e329821a91a2fedf715ac83b55f6f3085..978b2c7e84eaf25f9d32a7ffb06c8744ed65fdf4 100644 (file)
@@ -70,9 +70,10 @@ struct bug_entry *find_bug(unsigned long bugaddr);
                    "i" (__FILE__), "i" (__FUNCTION__));        \
 } while (0)
 
-#define WARN_ON(x) do {                                                \
-       if (__builtin_constant_p(x)) {                          \
-               if (x)                                          \
+#define WARN_ON(x) ({                                          \
+       typeof(x) __ret_warn_on = (x);                          \
+       if (__builtin_constant_p(__ret_warn_on)) {              \
+               if (__ret_warn_on)                              \
                        __WARN();                               \
        } else {                                                \
                __asm__ __volatile__(                           \
@@ -80,11 +81,12 @@ struct bug_entry *find_bug(unsigned long bugaddr);
                ".section __bug_table,\"a\"\n"                  \
                "\t"PPC_LONG"   1b,%1,%2,%3\n"                  \
                ".previous"                                     \
-               : : "r" ((long)(x)),                            \
+               : : "r" (__ret_warn_on),                        \
                    "i" (__LINE__ + BUG_WARNING_TRAP),          \
                    "i" (__FILE__), "i" (__FUNCTION__));        \
        }                                                       \
-} while (0)
+       unlikely(__ret_warn_on);                                \
+})
 
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG_ON
index 46bae1cf385b9e26c2d05b9463bd09f2a7f2119b..19b2ec1ec665c4b016525c5147851f7943c8f2ca 100644 (file)
@@ -11,6 +11,8 @@
 
 /* Check of existence of legacy devices */
 extern int check_legacy_ioport(unsigned long base_port);
+#define PARALLEL_BASE  0x378
+#define PNPBIOS_BASE   0xf000  /* only relevant for PReP */
 
 #ifndef CONFIG_PPC64
 #include <asm-ppc/io.h>
index c31e4382a7759dba58f18f7925e675538a951e5f..cc4cfceac67c16af4dc5326720ec0dda77fd6227 100644 (file)
@@ -285,5 +285,9 @@ static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
        rw->lock = 0;
 }
 
+#define _raw_spin_relax(lock)  __spin_yield(lock)
+#define _raw_read_relax(lock)  __rw_yield(lock)
+#define _raw_write_relax(lock) __rw_yield(lock)
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SPINLOCK_H */
index 5c64b75f0295bb0eec7697dd79a6b4f171269a2a..fccaf5531e579444b83d46192ef4280245a1a8ae 100644 (file)
@@ -161,4 +161,8 @@ static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
        rw->lock = 0;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SPINLOCK_H */
index b1770703b7060baf948721d41ebec79a84a311ca..79283dac8281453419dde45f78a28f4732553469 100644 (file)
@@ -80,7 +80,7 @@ static inline int appldata_asm(struct appldata_product_id *id,
        parm_list.product_id_addr = (unsigned long) id;
        parm_list.buffer_addr = virt_to_phys(buffer);
        asm volatile(
-               "diag %1,%0,0xdc"
+               "       diag    %1,%0,0xdc"
                : "=d" (ry)
                : "d" (&parm_list), "m" (parm_list), "m" (*id)
                : "cc");
index 399bf02894dd10cf5fc320557484eb0fcb27f7cd..af20c7462485f06de1dfb888e6f48769f0e64e9e 100644 (file)
@@ -30,20 +30,43 @@ typedef struct {
 
 #ifdef __KERNEL__
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
 #define __CS_LOOP(ptr, op_val, op_string) ({                           \
        typeof(ptr->counter) old_val, new_val;                          \
-        __asm__ __volatile__("   l     %0,0(%3)\n"                     \
-                             "0: lr    %1,%0\n"                                \
-                             op_string "  %1,%4\n"                     \
-                             "   cs    %0,%1,0(%3)\n"                  \
-                             "   jl    0b"                             \
-                             : "=&d" (old_val), "=&d" (new_val),       \
-                              "=m" (((atomic_t *)(ptr))->counter)      \
-                            : "a" (ptr), "d" (op_val),                 \
-                              "m" (((atomic_t *)(ptr))->counter)       \
-                            : "cc", "memory" );                        \
+       asm volatile(                                                   \
+               "       l       %0,%2\n"                                \
+               "0:     lr      %1,%0\n"                                \
+               op_string "     %1,%3\n"                                \
+               "       cs      %0,%1,%2\n"                             \
+               "       jl      0b"                                     \
+               : "=&d" (old_val), "=&d" (new_val),                     \
+                 "=Q" (((atomic_t *)(ptr))->counter)                   \
+               : "d" (op_val),  "Q" (((atomic_t *)(ptr))->counter)     \
+               : "cc", "memory");                                      \
        new_val;                                                        \
 })
+
+#else /* __GNUC__ */
+
+#define __CS_LOOP(ptr, op_val, op_string) ({                           \
+       typeof(ptr->counter) old_val, new_val;                          \
+       asm volatile(                                                   \
+               "       l       %0,0(%3)\n"                             \
+               "0:     lr      %1,%0\n"                                \
+               op_string "     %1,%4\n"                                \
+               "       cs      %0,%1,0(%3)\n"                          \
+               "       jl      0b"                                     \
+               : "=&d" (old_val), "=&d" (new_val),                     \
+                 "=m" (((atomic_t *)(ptr))->counter)                   \
+               : "a" (ptr), "d" (op_val),                              \
+                 "m" (((atomic_t *)(ptr))->counter)                    \
+               : "cc", "memory");                                      \
+       new_val;                                                        \
+})
+
+#endif /* __GNUC__ */
+
 #define atomic_read(v)          ((v)->counter)
 #define atomic_set(v,i)         (((v)->counter) = (i))
 
@@ -81,10 +104,19 @@ static __inline__ void atomic_set_mask(unsigned long mask, atomic_t * v)
 
 static __inline__ int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
-       __asm__ __volatile__("  cs   %0,%3,0(%2)\n"
-                            : "+d" (old), "=m" (v->counter)
-                            : "a" (v), "d" (new), "m" (v->counter)
-                            : "cc", "memory" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+       asm volatile(
+               "       cs      %0,%2,%1"
+               : "+d" (old), "=Q" (v->counter)
+               : "d" (new), "Q" (v->counter)
+               : "cc", "memory");
+#else /* __GNUC__ */
+       asm volatile(
+               "       cs      %0,%3,0(%2)"
+               : "+d" (old), "=m" (v->counter)
+               : "a" (v), "d" (new), "m" (v->counter)
+               : "cc", "memory");
+#endif /* __GNUC__ */
        return old;
 }
 
@@ -113,20 +145,43 @@ typedef struct {
 } __attribute__ ((aligned (8))) atomic64_t;
 #define ATOMIC64_INIT(i)  { (i) }
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
 #define __CSG_LOOP(ptr, op_val, op_string) ({                          \
        typeof(ptr->counter) old_val, new_val;                          \
-        __asm__ __volatile__("   lg    %0,0(%3)\n"                     \
-                             "0: lgr   %1,%0\n"                                \
-                             op_string "  %1,%4\n"                     \
-                             "   csg   %0,%1,0(%3)\n"                  \
-                             "   jl    0b"                             \
-                             : "=&d" (old_val), "=&d" (new_val),       \
-                              "=m" (((atomic_t *)(ptr))->counter)      \
-                            : "a" (ptr), "d" (op_val),                 \
-                              "m" (((atomic_t *)(ptr))->counter)       \
-                            : "cc", "memory" );                        \
+       asm volatile(                                                   \
+               "       lg      %0,%2\n"                                \
+               "0:     lgr     %1,%0\n"                                \
+               op_string "     %1,%3\n"                                \
+               "       csg     %0,%1,%2\n"                             \
+               "       jl      0b"                                     \
+               : "=&d" (old_val), "=&d" (new_val),                     \
+                 "=Q" (((atomic_t *)(ptr))->counter)                   \
+               : "d" (op_val), "Q" (((atomic_t *)(ptr))->counter)      \
+               : "cc", "memory" );                                     \
        new_val;                                                        \
 })
+
+#else /* __GNUC__ */
+
+#define __CSG_LOOP(ptr, op_val, op_string) ({                          \
+       typeof(ptr->counter) old_val, new_val;                          \
+       asm volatile(                                                   \
+               "       lg      %0,0(%3)\n"                             \
+               "0:     lgr     %1,%0\n"                                \
+               op_string "     %1,%4\n"                                \
+               "       csg     %0,%1,0(%3)\n"                          \
+               "       jl      0b"                                     \
+               : "=&d" (old_val), "=&d" (new_val),                     \
+                 "=m" (((atomic_t *)(ptr))->counter)                   \
+               : "a" (ptr), "d" (op_val),                              \
+                 "m" (((atomic_t *)(ptr))->counter)                    \
+               : "cc", "memory" );                                     \
+       new_val;                                                        \
+})
+
+#endif /* __GNUC__ */
+
 #define atomic64_read(v)          ((v)->counter)
 #define atomic64_set(v,i)         (((v)->counter) = (i))
 
@@ -163,10 +218,19 @@ static __inline__ void atomic64_set_mask(unsigned long mask, atomic64_t * v)
 static __inline__ long long atomic64_cmpxchg(atomic64_t *v,
                                             long long old, long long new)
 {
-       __asm__ __volatile__("  csg  %0,%3,0(%2)\n"
-                            : "+d" (old), "=m" (v->counter)
-                            : "a" (v), "d" (new), "m" (v->counter)
-                            : "cc", "memory" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+       asm volatile(
+               "       csg     %0,%2,%1"
+               : "+d" (old), "=Q" (v->counter)
+               : "d" (new), "Q" (v->counter)
+               : "cc", "memory");
+#else /* __GNUC__ */
+       asm volatile(
+               "       csg     %0,%3,0(%2)"
+               : "+d" (old), "=m" (v->counter)
+               : "a" (v), "d" (new), "m" (v->counter)
+               : "cc", "memory");
+#endif /* __GNUC__ */
        return old;
 }
 
index 0ddcdba79e4a91b6b04b140810994f31bd5636a8..f79c9b792af1d88d0d54ed7f5762bc232c96b51d 100644 (file)
@@ -67,16 +67,35 @@ extern const char _sb_findmap[];
 #define __BITOPS_AND           "nr"
 #define __BITOPS_XOR           "xr"
 
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)                \
-       __asm__ __volatile__("   l   %0,0(%4)\n"                        \
-                            "0: lr  %1,%0\n"                           \
-                            __op_string "  %1,%3\n"                    \
-                            "   cs  %0,%1,0(%4)\n"                     \
-                            "   jl  0b"                                \
-                            : "=&d" (__old), "=&d" (__new),            \
-                              "=m" (*(unsigned long *) __addr)         \
-                            : "d" (__val), "a" (__addr),               \
-                              "m" (*(unsigned long *) __addr) : "cc" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)        \
+       asm volatile(                                           \
+               "       l       %0,%2\n"                        \
+               "0:     lr      %1,%0\n"                        \
+               __op_string "   %1,%3\n"                        \
+               "       cs      %0,%1,%2\n"                     \
+               "       jl      0b"                             \
+               : "=&d" (__old), "=&d" (__new),                 \
+                 "=Q" (*(unsigned long *) __addr)              \
+               : "d" (__val), "Q" (*(unsigned long *) __addr)  \
+               : "cc");
+
+#else /* __GNUC__ */
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)        \
+       asm volatile(                                           \
+               "       l       %0,0(%4)\n"                     \
+               "0:     lr      %1,%0\n"                        \
+               __op_string "   %1,%3\n"                        \
+               "       cs      %0,%1,0(%4)\n"                  \
+               "       jl      0b"                             \
+               : "=&d" (__old), "=&d" (__new),                 \
+                 "=m" (*(unsigned long *) __addr)              \
+               : "d" (__val), "a" (__addr),                    \
+                 "m" (*(unsigned long *) __addr) : "cc");
+
+#endif /* __GNUC__ */
 
 #else /* __s390x__ */
 
@@ -86,21 +105,41 @@ extern const char _sb_findmap[];
 #define __BITOPS_AND           "ngr"
 #define __BITOPS_XOR           "xgr"
 
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)                \
-       __asm__ __volatile__("   lg  %0,0(%4)\n"                        \
-                            "0: lgr %1,%0\n"                           \
-                            __op_string "  %1,%3\n"                    \
-                            "   csg %0,%1,0(%4)\n"                     \
-                            "   jl  0b"                                \
-                            : "=&d" (__old), "=&d" (__new),            \
-                              "=m" (*(unsigned long *) __addr)         \
-                            : "d" (__val), "a" (__addr),               \
-                              "m" (*(unsigned long *) __addr) : "cc" );
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)        \
+       asm volatile(                                           \
+               "       lg      %0,%2\n"                        \
+               "0:     lgr     %1,%0\n"                        \
+               __op_string "   %1,%3\n"                        \
+               "       csg     %0,%1,%2\n"                     \
+               "       jl      0b"                             \
+               : "=&d" (__old), "=&d" (__new),                 \
+                 "=Q" (*(unsigned long *) __addr)              \
+               : "d" (__val), "Q" (*(unsigned long *) __addr)  \
+               : "cc");
+
+#else /* __GNUC__ */
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)        \
+       asm volatile(                                           \
+               "       lg      %0,0(%4)\n"                     \
+               "0:     lgr     %1,%0\n"                        \
+               __op_string "   %1,%3\n"                        \
+               "       csg     %0,%1,0(%4)\n"                  \
+               "       jl      0b"                             \
+               : "=&d" (__old), "=&d" (__new),                 \
+                 "=m" (*(unsigned long *) __addr)              \
+               : "d" (__val), "a" (__addr),                    \
+                 "m" (*(unsigned long *) __addr) : "cc");
+
+
+#endif /* __GNUC__ */
 
 #endif /* __s390x__ */
 
 #define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
-#define __BITOPS_BARRIER() __asm__ __volatile__ ( "" : : : "memory" )
+#define __BITOPS_BARRIER() asm volatile("" : : : "memory")
 
 #ifdef CONFIG_SMP
 /*
@@ -217,10 +256,10 @@ static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
 
        addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-        asm volatile("oc 0(1,%1),0(%2)"
-                    : "=m" (*(char *) addr)
-                    : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-                      "m" (*(char *) addr) : "cc" );
+       asm volatile(
+               "       oc      0(1,%1),0(%2)"
+               : "=m" (*(char *) addr) : "a" (addr),
+                 "a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
 }
 
 static inline void 
@@ -229,40 +268,7 @@ __constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
 
        addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-       switch (nr&7) {
-       case 0:
-               asm volatile ("oi 0(%1),0x01" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 1:
-               asm volatile ("oi 0(%1),0x02" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 2:
-               asm volatile ("oi 0(%1),0x04" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 3:
-               asm volatile ("oi 0(%1),0x08" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 4:
-               asm volatile ("oi 0(%1),0x10" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 5:
-               asm volatile ("oi 0(%1),0x20" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 6:
-               asm volatile ("oi 0(%1),0x40" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 7:
-               asm volatile ("oi 0(%1),0x80" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       }
+       *(unsigned char *) addr |= 1 << (nr & 7);
 }
 
 #define set_bit_simple(nr,addr) \
@@ -279,10 +285,10 @@ __clear_bit(unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
 
        addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-        asm volatile("nc 0(1,%1),0(%2)"
-                    : "=m" (*(char *) addr)
-                    : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
-                      "m" (*(char *) addr) : "cc" );
+       asm volatile(
+               "       nc      0(1,%1),0(%2)"
+               : "=m" (*(char *) addr) : "a" (addr),
+                 "a" (_ni_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc");
 }
 
 static inline void 
@@ -291,40 +297,7 @@ __constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
 
        addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-       switch (nr&7) {
-       case 0:
-               asm volatile ("ni 0(%1),0xFE" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 1:
-               asm volatile ("ni 0(%1),0xFD": "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 2:
-               asm volatile ("ni 0(%1),0xFB" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 3:
-               asm volatile ("ni 0(%1),0xF7" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 4:
-               asm volatile ("ni 0(%1),0xEF" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 5:
-               asm volatile ("ni 0(%1),0xDF" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 6:
-               asm volatile ("ni 0(%1),0xBF" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 7:
-               asm volatile ("ni 0(%1),0x7F" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       }
+       *(unsigned char *) addr &= ~(1 << (nr & 7));
 }
 
 #define clear_bit_simple(nr,addr) \
@@ -340,10 +313,10 @@ static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
 
        addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-        asm volatile("xc 0(1,%1),0(%2)"
-                    :  "=m" (*(char *) addr)
-                    : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-                      "m" (*(char *) addr) : "cc" );
+       asm volatile(
+               "       xc      0(1,%1),0(%2)"
+               :  "=m" (*(char *) addr) : "a" (addr),
+                  "a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
 }
 
 static inline void 
@@ -352,40 +325,7 @@ __constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
        unsigned long addr;
 
        addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
-       switch (nr&7) {
-       case 0:
-               asm volatile ("xi 0(%1),0x01" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 1:
-               asm volatile ("xi 0(%1),0x02" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 2:
-               asm volatile ("xi 0(%1),0x04" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 3:
-               asm volatile ("xi 0(%1),0x08" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 4:
-               asm volatile ("xi 0(%1),0x10" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 5:
-               asm volatile ("xi 0(%1),0x20" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 6:
-               asm volatile ("xi 0(%1),0x40" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       case 7:
-               asm volatile ("xi 0(%1),0x80" : "=m" (*(char *) addr)
-                             : "a" (addr), "m" (*(char *) addr) : "cc" );
-               break;
-       }
+       *(unsigned char *) addr ^= 1 << (nr & 7);
 }
 
 #define change_bit_simple(nr,addr) \
@@ -404,10 +344,11 @@ test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
        ch = *(unsigned char *) addr;
-        asm volatile("oc 0(1,%1),0(%2)"
-                    : "=m" (*(char *) addr)
-                    : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-                      "m" (*(char *) addr) : "cc", "memory" );
+       asm volatile(
+               "       oc      0(1,%1),0(%2)"
+               : "=m" (*(char *) addr)
+               : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+                 "m" (*(char *) addr) : "cc", "memory");
        return (ch >> (nr & 7)) & 1;
 }
 #define __test_and_set_bit(X,Y)                test_and_set_bit_simple(X,Y)
@@ -423,10 +364,11 @@ test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
        ch = *(unsigned char *) addr;
-        asm volatile("nc 0(1,%1),0(%2)"
-                    : "=m" (*(char *) addr)
-                    : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
-                      "m" (*(char *) addr) : "cc", "memory" );
+       asm volatile(
+               "       nc      0(1,%1),0(%2)"
+               : "=m" (*(char *) addr)
+               : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
+                 "m" (*(char *) addr) : "cc", "memory");
        return (ch >> (nr & 7)) & 1;
 }
 #define __test_and_clear_bit(X,Y)      test_and_clear_bit_simple(X,Y)
@@ -442,10 +384,11 @@ test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
 
        addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
        ch = *(unsigned char *) addr;
-        asm volatile("xc 0(1,%1),0(%2)"
-                    : "=m" (*(char *) addr)
-                    : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
-                      "m" (*(char *) addr) : "cc", "memory" );
+       asm volatile(
+               "       xc      0(1,%1),0(%2)"
+               : "=m" (*(char *) addr)
+               : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+                 "m" (*(char *) addr) : "cc", "memory");
        return (ch >> (nr & 7)) & 1;
 }
 #define __test_and_change_bit(X,Y)     test_and_change_bit_simple(X,Y)
@@ -557,35 +500,36 @@ find_first_zero_bit(const unsigned long * addr, unsigned long size)
 
         if (!size)
                 return 0;
-        __asm__("   lhi  %1,-1\n"
-                "   lr   %2,%3\n"
-                "   slr  %0,%0\n"
-                "   ahi  %2,31\n"
-                "   srl  %2,5\n"
-                "0: c    %1,0(%0,%4)\n"
-                "   jne  1f\n"
-                "   la   %0,4(%0)\n"
-                "   brct %2,0b\n"
-                "   lr   %0,%3\n"
-                "   j    4f\n"
-                "1: l    %2,0(%0,%4)\n"
-                "   sll  %0,3\n"
-                "   lhi  %1,0xff\n"
-                "   tml  %2,0xffff\n"
-                "   jno  2f\n"
-                "   ahi  %0,16\n"
-                "   srl  %2,16\n"
-                "2: tml  %2,0x00ff\n"
-                "   jno  3f\n"
-                "   ahi  %0,8\n"
-                "   srl  %2,8\n"
-                "3: nr   %2,%1\n"
-                "   ic   %2,0(%2,%5)\n"
-                "   alr  %0,%2\n"
-                "4:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
-                : "a" (size), "a" (addr), "a" (&_zb_findmap),
-                 "m" (*(addrtype *) addr) : "cc" );
+       asm volatile(
+               "       lhi     %1,-1\n"
+               "       lr      %2,%3\n"
+               "       slr     %0,%0\n"
+               "       ahi     %2,31\n"
+               "       srl     %2,5\n"
+               "0:     c       %1,0(%0,%4)\n"
+               "       jne     1f\n"
+               "       la      %0,4(%0)\n"
+               "       brct    %2,0b\n"
+               "       lr      %0,%3\n"
+               "       j       4f\n"
+               "1:     l       %2,0(%0,%4)\n"
+               "       sll     %0,3\n"
+               "       lhi     %1,0xff\n"
+               "       tml     %2,0xffff\n"
+               "       jno     2f\n"
+               "       ahi     %0,16\n"
+               "       srl     %2,16\n"
+               "2:     tml     %2,0x00ff\n"
+               "       jno     3f\n"
+               "       ahi     %0,8\n"
+               "       srl     %2,8\n"
+               "3:     nr      %2,%1\n"
+               "       ic      %2,0(%2,%5)\n"
+               "       alr     %0,%2\n"
+               "4:"
+               : "=&a" (res), "=&d" (cmp), "=&a" (count)
+               : "a" (size), "a" (addr), "a" (&_zb_findmap),
+                 "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -598,35 +542,36 @@ find_first_bit(const unsigned long * addr, unsigned long size)
 
         if (!size)
                 return 0;
-        __asm__("   slr  %1,%1\n"
-                "   lr   %2,%3\n"
-                "   slr  %0,%0\n"
-                "   ahi  %2,31\n"
-                "   srl  %2,5\n"
-                "0: c    %1,0(%0,%4)\n"
-                "   jne  1f\n"
-                "   la   %0,4(%0)\n"
-                "   brct %2,0b\n"
-                "   lr   %0,%3\n"
-                "   j    4f\n"
-                "1: l    %2,0(%0,%4)\n"
-                "   sll  %0,3\n"
-                "   lhi  %1,0xff\n"
-                "   tml  %2,0xffff\n"
-                "   jnz  2f\n"
-                "   ahi  %0,16\n"
-                "   srl  %2,16\n"
-                "2: tml  %2,0x00ff\n"
-                "   jnz  3f\n"
-                "   ahi  %0,8\n"
-                "   srl  %2,8\n"
-                "3: nr   %2,%1\n"
-                "   ic   %2,0(%2,%5)\n"
-                "   alr  %0,%2\n"
-                "4:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
-                : "a" (size), "a" (addr), "a" (&_sb_findmap),
-                 "m" (*(addrtype *) addr) : "cc" );
+       asm volatile(
+               "       slr     %1,%1\n"
+               "       lr      %2,%3\n"
+               "       slr     %0,%0\n"
+               "       ahi     %2,31\n"
+               "       srl     %2,5\n"
+               "0:     c       %1,0(%0,%4)\n"
+               "       jne     1f\n"
+               "       la      %0,4(%0)\n"
+               "       brct    %2,0b\n"
+               "       lr      %0,%3\n"
+               "       j       4f\n"
+               "1:     l       %2,0(%0,%4)\n"
+               "       sll     %0,3\n"
+               "       lhi     %1,0xff\n"
+               "       tml     %2,0xffff\n"
+               "       jnz     2f\n"
+               "       ahi     %0,16\n"
+               "       srl     %2,16\n"
+               "2:     tml     %2,0x00ff\n"
+               "       jnz     3f\n"
+               "       ahi     %0,8\n"
+               "       srl     %2,8\n"
+               "3:     nr      %2,%1\n"
+               "       ic      %2,0(%2,%5)\n"
+               "       alr     %0,%2\n"
+               "4:"
+               : "=&a" (res), "=&d" (cmp), "=&a" (count)
+               : "a" (size), "a" (addr), "a" (&_sb_findmap),
+                 "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -640,39 +585,40 @@ find_first_zero_bit(const unsigned long * addr, unsigned long size)
 
         if (!size)
                 return 0;
-        __asm__("   lghi  %1,-1\n"
-                "   lgr   %2,%3\n"
-                "   slgr  %0,%0\n"
-                "   aghi  %2,63\n"
-                "   srlg  %2,%2,6\n"
-                "0: cg    %1,0(%0,%4)\n"
-                "   jne   1f\n"
-                "   la    %0,8(%0)\n"
-                "   brct  %2,0b\n"
-                "   lgr   %0,%3\n"
-                "   j     5f\n"
-                "1: lg    %2,0(%0,%4)\n"
-                "   sllg  %0,%0,3\n"
-                "   clr   %2,%1\n"
-               "   jne   2f\n"
-               "   aghi  %0,32\n"
-                "   srlg  %2,%2,32\n"
-               "2: lghi  %1,0xff\n"
-                "   tmll  %2,0xffff\n"
-                "   jno   3f\n"
-                "   aghi  %0,16\n"
-                "   srl   %2,16\n"
-                "3: tmll  %2,0x00ff\n"
-                "   jno   4f\n"
-                "   aghi  %0,8\n"
-                "   srl   %2,8\n"
-                "4: ngr   %2,%1\n"
-                "   ic    %2,0(%2,%5)\n"
-                "   algr  %0,%2\n"
-                "5:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
+       asm volatile(
+               "       lghi    %1,-1\n"
+               "       lgr     %2,%3\n"
+               "       slgr    %0,%0\n"
+               "       aghi    %2,63\n"
+               "       srlg    %2,%2,6\n"
+               "0:     cg      %1,0(%0,%4)\n"
+               "       jne     1f\n"
+               "       la      %0,8(%0)\n"
+               "       brct    %2,0b\n"
+               "       lgr     %0,%3\n"
+               "       j       5f\n"
+               "1:     lg      %2,0(%0,%4)\n"
+               "       sllg    %0,%0,3\n"
+               "       clr     %2,%1\n"
+               "       jne     2f\n"
+               "       aghi    %0,32\n"
+               "       srlg    %2,%2,32\n"
+               "2:     lghi    %1,0xff\n"
+               "       tmll    %2,0xffff\n"
+               "       jno     3f\n"
+               "       aghi    %0,16\n"
+               "       srl     %2,16\n"
+               "3:     tmll    %2,0x00ff\n"
+               "       jno     4f\n"
+               "       aghi    %0,8\n"
+               "       srl     %2,8\n"
+               "4:     ngr     %2,%1\n"
+               "       ic      %2,0(%2,%5)\n"
+               "       algr    %0,%2\n"
+               "5:"
+               : "=&a" (res), "=&d" (cmp), "=&a" (count)
                : "a" (size), "a" (addr), "a" (&_zb_findmap),
-                 "m" (*(addrtype *) addr) : "cc" );
+                 "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -684,39 +630,40 @@ find_first_bit(const unsigned long * addr, unsigned long size)
 
         if (!size)
                 return 0;
-        __asm__("   slgr  %1,%1\n"
-                "   lgr   %2,%3\n"
-                "   slgr  %0,%0\n"
-                "   aghi  %2,63\n"
-                "   srlg  %2,%2,6\n"
-                "0: cg    %1,0(%0,%4)\n"
-                "   jne   1f\n"
-                "   aghi  %0,8\n"
-                "   brct  %2,0b\n"
-                "   lgr   %0,%3\n"
-                "   j     5f\n"
-                "1: lg    %2,0(%0,%4)\n"
-                "   sllg  %0,%0,3\n"
-                "   clr   %2,%1\n"
-               "   jne   2f\n"
-               "   aghi  %0,32\n"
-                "   srlg  %2,%2,32\n"
-               "2: lghi  %1,0xff\n"
-                "   tmll  %2,0xffff\n"
-                "   jnz   3f\n"
-                "   aghi  %0,16\n"
-                "   srl   %2,16\n"
-                "3: tmll  %2,0x00ff\n"
-                "   jnz   4f\n"
-                "   aghi  %0,8\n"
-                "   srl   %2,8\n"
-                "4: ngr   %2,%1\n"
-                "   ic    %2,0(%2,%5)\n"
-                "   algr  %0,%2\n"
-                "5:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
+       asm volatile(
+               "       slgr    %1,%1\n"
+               "       lgr     %2,%3\n"
+               "       slgr    %0,%0\n"
+               "       aghi    %2,63\n"
+               "       srlg    %2,%2,6\n"
+               "0:     cg      %1,0(%0,%4)\n"
+               "       jne     1f\n"
+               "       aghi    %0,8\n"
+               "       brct    %2,0b\n"
+               "       lgr     %0,%3\n"
+               "       j       5f\n"
+               "1:     lg      %2,0(%0,%4)\n"
+               "       sllg    %0,%0,3\n"
+               "       clr     %2,%1\n"
+               "       jne     2f\n"
+               "       aghi    %0,32\n"
+               "       srlg    %2,%2,32\n"
+               "2:     lghi    %1,0xff\n"
+               "       tmll    %2,0xffff\n"
+               "       jnz     3f\n"
+               "       aghi    %0,16\n"
+               "       srl     %2,16\n"
+               "3:     tmll    %2,0x00ff\n"
+               "       jnz     4f\n"
+               "       aghi    %0,8\n"
+               "       srl     %2,8\n"
+               "4:     ngr     %2,%1\n"
+               "       ic      %2,0(%2,%5)\n"
+               "       algr    %0,%2\n"
+               "5:"
+               : "=&a" (res), "=&d" (cmp), "=&a" (count)
                : "a" (size), "a" (addr), "a" (&_sb_findmap),
-                 "m" (*(addrtype *) addr) : "cc" );
+                 "m" (*(addrtype *) addr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -832,36 +779,37 @@ ext2_find_first_zero_bit(void *vaddr, unsigned int size)
 
         if (!size)
                 return 0;
-        __asm__("   lhi  %1,-1\n"
-                "   lr   %2,%3\n"
-                "   ahi  %2,31\n"
-                "   srl  %2,5\n"
-                "   slr  %0,%0\n"
-                "0: cl   %1,0(%0,%4)\n"
-                "   jne  1f\n"
-                "   ahi  %0,4\n"
-                "   brct %2,0b\n"
-                "   lr   %0,%3\n"
-                "   j    4f\n"
-                "1: l    %2,0(%0,%4)\n"
-                "   sll  %0,3\n"
-                "   ahi  %0,24\n"
-                "   lhi  %1,0xff\n"
-                "   tmh  %2,0xffff\n"
-                "   jo   2f\n"
-                "   ahi  %0,-16\n"
-                "   srl  %2,16\n"
-                "2: tml  %2,0xff00\n"
-                "   jo   3f\n"
-                "   ahi  %0,-8\n"
-                "   srl  %2,8\n"
-                "3: nr   %2,%1\n"
-                "   ic   %2,0(%2,%5)\n"
-                "   alr  %0,%2\n"
-                "4:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
-                : "a" (size), "a" (vaddr), "a" (&_zb_findmap),
-                 "m" (*(addrtype *) vaddr) : "cc" );
+       asm volatile(
+               "       lhi     %1,-1\n"
+               "       lr      %2,%3\n"
+               "       ahi     %2,31\n"
+               "       srl     %2,5\n"
+               "       slr     %0,%0\n"
+               "0:     cl      %1,0(%0,%4)\n"
+               "       jne     1f\n"
+               "       ahi     %0,4\n"
+               "       brct    %2,0b\n"
+               "       lr      %0,%3\n"
+               "       j       4f\n"
+               "1:     l       %2,0(%0,%4)\n"
+               "       sll     %0,3\n"
+               "       ahi     %0,24\n"
+               "       lhi     %1,0xff\n"
+               "       tmh     %2,0xffff\n"
+               "       jo      2f\n"
+               "       ahi     %0,-16\n"
+               "       srl     %2,16\n"
+               "2:     tml     %2,0xff00\n"
+               "       jo      3f\n"
+               "       ahi     %0,-8\n"
+               "       srl     %2,8\n"
+               "3:     nr      %2,%1\n"
+               "       ic      %2,0(%2,%5)\n"
+               "       alr     %0,%2\n"
+               "4:"
+               : "=&a" (res), "=&d" (cmp), "=&a" (count)
+               : "a" (size), "a" (vaddr), "a" (&_zb_findmap),
+                 "m" (*(addrtype *) vaddr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -875,39 +823,40 @@ ext2_find_first_zero_bit(void *vaddr, unsigned long size)
 
         if (!size)
                 return 0;
-        __asm__("   lghi  %1,-1\n"
-                "   lgr   %2,%3\n"
-                "   aghi  %2,63\n"
-                "   srlg  %2,%2,6\n"
-                "   slgr  %0,%0\n"
-                "0: clg   %1,0(%0,%4)\n"
-                "   jne   1f\n"
-                "   aghi  %0,8\n"
-                "   brct  %2,0b\n"
-                "   lgr   %0,%3\n"
-                "   j     5f\n"
-                "1: cl    %1,0(%0,%4)\n"
-               "   jne   2f\n"
-               "   aghi  %0,4\n"
-               "2: l     %2,0(%0,%4)\n"
-                "   sllg  %0,%0,3\n"
-                "   aghi  %0,24\n"
-                "   lghi  %1,0xff\n"
-                "   tmlh  %2,0xffff\n"
-                "   jo    3f\n"
-                "   aghi  %0,-16\n"
-                "   srl   %2,16\n"
-                "3: tmll  %2,0xff00\n"
-                "   jo    4f\n"
-                "   aghi  %0,-8\n"
-                "   srl   %2,8\n"
-                "4: ngr   %2,%1\n"
-                "   ic    %2,0(%2,%5)\n"
-                "   algr  %0,%2\n"
-                "5:"
-                : "=&a" (res), "=&d" (cmp), "=&a" (count)
+       asm volatile(
+               "       lghi    %1,-1\n"
+               "       lgr     %2,%3\n"
+               "       aghi    %2,63\n"
+               "       srlg    %2,%2,6\n"
+               "       slgr    %0,%0\n"
+               "0:     clg     %1,0(%0,%4)\n"
+               "       jne     1f\n"
+               "       aghi    %0,8\n"
+               "       brct    %2,0b\n"
+               "       lgr     %0,%3\n"
+               "       j       5f\n"
+               "1:     cl      %1,0(%0,%4)\n"
+               "       jne     2f\n"
+               "       aghi    %0,4\n"
+               "2:     l       %2,0(%0,%4)\n"
+               "       sllg    %0,%0,3\n"
+               "       aghi    %0,24\n"
+               "       lghi    %1,0xff\n"
+               "       tmlh    %2,0xffff\n"
+               "       jo      3f\n"
+               "       aghi    %0,-16\n"
+               "       srl     %2,16\n"
+               "3:     tmll    %2,0xff00\n"
+               "       jo      4f\n"
+               "       aghi    %0,-8\n"
+               "       srl     %2,8\n"
+               "4:     ngr     %2,%1\n"
+               "       ic      %2,0(%2,%5)\n"
+               "       algr    %0,%2\n"
+               "5:"
+               : "=&a" (res), "=&d" (cmp), "=&a" (count)
                : "a" (size), "a" (vaddr), "a" (&_zb_findmap),
-                 "m" (*(addrtype *) vaddr) : "cc" );
+                 "m" (*(addrtype *) vaddr) : "cc");
         return (res < size) ? res : size;
 }
 
@@ -927,13 +876,16 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
        p = addr + offset / __BITOPS_WORDSIZE;
         if (bit) {
 #ifndef __s390x__
-                asm("   ic   %0,0(%1)\n"
-                   "   icm  %0,2,1(%1)\n"
-                   "   icm  %0,4,2(%1)\n"
-                   "   icm  %0,8,3(%1)"
-                   : "=&a" (word) : "a" (p), "m" (*p) : "cc" );
+               asm volatile(
+                       "       ic      %0,0(%1)\n"
+                       "       icm     %0,2,1(%1)\n"
+                       "       icm     %0,4,2(%1)\n"
+                       "       icm     %0,8,3(%1)"
+                       : "=&a" (word) : "a" (p), "m" (*p) : "cc");
 #else
-                asm("   lrvg %0,%1" : "=a" (word) : "m" (*p) );
+               asm volatile(
+                       "       lrvg    %0,%1"
+                       : "=a" (word) : "m" (*p) );
 #endif
                /*
                 * s390 version of ffz returns __BITOPS_WORDSIZE
index 2cc35a0e188e1712def6878400af75694d5b92e4..1fe2492baa8d141414c66f343f6ddae3e30eeed5 100644 (file)
 #ifdef __GNUC__
 
 #ifdef __s390x__
-static __inline__ __u64 ___arch__swab64p(const __u64 *x)
+static inline __u64 ___arch__swab64p(const __u64 *x)
 {
        __u64 result;
 
-       __asm__ __volatile__ (
-               "   lrvg %0,%1"
-               : "=d" (result) : "m" (*x) );
+       asm volatile("lrvg %0,%1" : "=d" (result) : "m" (*x));
        return result;
 }
 
-static __inline__ __u64 ___arch__swab64(__u64 x)
+static inline __u64 ___arch__swab64(__u64 x)
 {
        __u64 result;
 
-       __asm__ __volatile__ (
-               "   lrvgr %0,%1"
-               : "=d" (result) : "d" (x) );
+       asm volatile("lrvgr %0,%1" : "=d" (result) : "d" (x));
        return result;
 }
 
-static __inline__ void ___arch__swab64s(__u64 *x)
+static inline void ___arch__swab64s(__u64 *x)
 {
        *x = ___arch__swab64p(x);
 }
 #endif /* __s390x__ */
 
-static __inline__ __u32 ___arch__swab32p(const __u32 *x)
+static inline __u32 ___arch__swab32p(const __u32 *x)
 {
        __u32 result;
        
-       __asm__ __volatile__ (
+       asm volatile(
 #ifndef __s390x__
-               "        icm   %0,8,3(%1)\n"
-               "        icm   %0,4,2(%1)\n"
-               "        icm   %0,2,1(%1)\n"
-               "        ic    %0,0(%1)"
-               : "=&d" (result) : "a" (x), "m" (*x) : "cc" );
+               "       icm     %0,8,3(%1)\n"
+               "       icm     %0,4,2(%1)\n"
+               "       icm     %0,2,1(%1)\n"
+               "       ic      %0,0(%1)"
+               : "=&d" (result) : "a" (x), "m" (*x) : "cc");
 #else /* __s390x__ */
-               "   lrv  %0,%1"
-               : "=d" (result) : "m" (*x) );
+               "       lrv     %0,%1"
+               : "=d" (result) : "m" (*x));
 #endif /* __s390x__ */
        return result;
 }
 
-static __inline__ __u32 ___arch__swab32(__u32 x)
+static inline __u32 ___arch__swab32(__u32 x)
 {
 #ifndef __s390x__
        return ___arch__swab32p(&x);
 #else /* __s390x__ */
        __u32 result;
        
-       __asm__ __volatile__ (
-               "   lrvr  %0,%1"
-               : "=d" (result) : "d" (x) );
+       asm volatile("lrvr  %0,%1" : "=d" (result) : "d" (x));
        return result;
 #endif /* __s390x__ */
 }
@@ -81,14 +75,14 @@ static __inline__ __u16 ___arch__swab16p(const __u16 *x)
 {
        __u16 result;
        
-       __asm__ __volatile__ (
+       asm volatile(
 #ifndef __s390x__
-               "        icm   %0,2,1(%1)\n"
-               "        ic    %0,0(%1)\n"
-               : "=&d" (result) : "a" (x), "m" (*x) : "cc" );
+               "       icm     %0,2,1(%1)\n"
+               "       ic      %0,0(%1)\n"
+               : "=&d" (result) : "a" (x), "m" (*x) : "cc");
 #else /* __s390x__ */
-               "   lrvh %0,%1"
-               : "=d" (result) : "m" (*x) );
+               "       lrvh    %0,%1"
+               : "=d" (result) : "m" (*x));
 #endif /* __s390x__ */
        return result;
 }
index 471f2af2b16ae58d91a214402da3d416d1f0e435..37c362d89fad62210c78d8068b953c66679f11dc 100644 (file)
 static inline unsigned int
 csum_partial(const unsigned char * buff, int len, unsigned int sum)
 {
-       /*
-        * Experiments with ethernet and slip connections show that buf
-        * is aligned on either a 2-byte or 4-byte boundary.
-        */
-#ifndef __s390x__
-       register_pair rp;
-
-       rp.subreg.even = (unsigned long) buff;
-       rp.subreg.odd = (unsigned long) len;
-       __asm__ __volatile__ (
-               "0:  cksm %0,%1\n"      /* do checksum on longs */
-               "    jo   0b\n"
-               : "+&d" (sum), "+&a" (rp) : : "cc", "memory" );
-#else /* __s390x__ */
-        __asm__ __volatile__ (
-                "    lgr  2,%1\n"    /* address in gpr 2 */
-                "    lgfr 3,%2\n"    /* length in gpr 3 */
-                "0:  cksm %0,2\n"    /* do checksum on longs */
-                "    jo   0b\n"
-                : "+&d" (sum)
-                : "d" (buff), "d" (len)
-                : "cc", "memory", "2", "3" );
-#endif /* __s390x__ */
-       return sum;
-}
-
-/*
- * csum_partial as an inline function
- */
-static inline unsigned int 
-csum_partial_inline(const unsigned char * buff, int len, unsigned int sum)
-{
-#ifndef __s390x__
-       register_pair rp;
+       register unsigned long reg2 asm("2") = (unsigned long) buff;
+       register unsigned long reg3 asm("3") = (unsigned long) len;
 
-       rp.subreg.even = (unsigned long) buff;
-       rp.subreg.odd = (unsigned long) len;
-       __asm__ __volatile__ (
-               "0:  cksm %0,%1\n"    /* do checksum on longs */
-               "    jo   0b\n"
-                : "+&d" (sum), "+&a" (rp) : : "cc", "memory" );
-#else /* __s390x__ */
-       __asm__ __volatile__ (
-               "    lgr  2,%1\n"    /* address in gpr 2 */
-               "    lgfr 3,%2\n"    /* length in gpr 3 */
-               "0:  cksm %0,2\n"    /* do checksum on longs */
-               "    jo   0b\n"
-                : "+&d" (sum)
-               : "d" (buff), "d" (len)
-                : "cc", "memory", "2", "3" );
-#endif /* __s390x__ */
+       asm volatile(
+               "0:     cksm    %0,%1\n"        /* do checksum on longs */
+               "       jo      0b\n"
+               : "+d" (sum), "+d" (reg2), "+d" (reg3) : : "cc", "memory");
        return sum;
 }
 
@@ -114,7 +70,7 @@ static inline unsigned int
 csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum)
 {
         memcpy(dst,src,len);
-        return csum_partial_inline(dst, len, sum);
+       return csum_partial(dst, len, sum);
 }
 
 /*
@@ -126,22 +82,22 @@ csum_fold(unsigned int sum)
 #ifndef __s390x__
        register_pair rp;
 
-       __asm__ __volatile__ (
-               "    slr  %N1,%N1\n" /* %0 = H L */
-               "    lr   %1,%0\n"   /* %0 = H L, %1 = H L 0 0 */
-               "    srdl %1,16\n"   /* %0 = H L, %1 = 0 H L 0 */
-               "    alr  %1,%N1\n"  /* %0 = H L, %1 = L H L 0 */
-               "    alr  %0,%1\n"   /* %0 = H+L+C L+H */
-               "    srl  %0,16\n"   /* %0 = H+L+C */
-               : "+&d" (sum), "=d" (rp) : : "cc" );
+       asm volatile(
+               "       slr     %N1,%N1\n"      /* %0 = H L */
+               "       lr      %1,%0\n"        /* %0 = H L, %1 = H L 0 0 */
+               "       srdl    %1,16\n"        /* %0 = H L, %1 = 0 H L 0 */
+               "       alr     %1,%N1\n"       /* %0 = H L, %1 = L H L 0 */
+               "       alr     %0,%1\n"        /* %0 = H+L+C L+H */
+               "       srl     %0,16\n"        /* %0 = H+L+C */
+               : "+&d" (sum), "=d" (rp) : : "cc");
 #else /* __s390x__ */
-       __asm__ __volatile__ (
-               "    sr   3,3\n"   /* %0 = H*65536 + L */
-               "    lr   2,%0\n"  /* %0 = H L, R2/R3 = H L / 0 0 */
-               "    srdl 2,16\n"  /* %0 = H L, R2/R3 = 0 H / L 0 */
-               "    alr  2,3\n"   /* %0 = H L, R2/R3 = L H / L 0 */
-               "    alr  %0,2\n"  /* %0 = H+L+C L+H */
-                "    srl  %0,16\n" /* %0 = H+L+C */
+       asm volatile(
+               "       sr      3,3\n"          /* %0 = H*65536 + L */
+               "       lr      2,%0\n"         /* %0 = H L, 2/3 = H L / 0 0 */
+               "       srdl    2,16\n"         /* %0 = H L, 2/3 = 0 H / L 0 */
+               "       alr     2,3\n"          /* %0 = H L, 2/3 = L H / L 0 */
+               "       alr     %0,2\n"         /* %0 = H+L+C L+H */
+               "       srl     %0,16\n"        /* %0 = H+L+C */
                : "+&d" (sum) : : "cc", "2", "3");
 #endif /* __s390x__ */
        return ((unsigned short) ~sum);
@@ -155,29 +111,7 @@ csum_fold(unsigned int sum)
 static inline unsigned short
 ip_fast_csum(unsigned char *iph, unsigned int ihl)
 {
-       unsigned long sum;
-#ifndef __s390x__
-       register_pair rp;
-
-       rp.subreg.even = (unsigned long) iph;
-       rp.subreg.odd = (unsigned long) ihl*4;
-        __asm__ __volatile__ (
-               "    sr   %0,%0\n"   /* set sum to zero */
-                "0:  cksm %0,%1\n"   /* do checksum on longs */
-                "    jo   0b\n"
-                : "=&d" (sum), "+&a" (rp) : : "cc", "memory" );
-#else /* __s390x__ */
-        __asm__ __volatile__ (
-               "    slgr %0,%0\n"   /* set sum to zero */
-                "    lgr  2,%1\n"    /* address in gpr 2 */
-                "    lgfr 3,%2\n"    /* length in gpr 3 */
-                "0:  cksm %0,2\n"    /* do checksum on ints */
-                "    jo   0b\n"
-                : "=&d" (sum)
-                : "d" (iph), "d" (ihl*4)
-                : "cc", "memory", "2", "3" );
-#endif /* __s390x__ */
-        return csum_fold(sum);
+       return csum_fold(csum_partial(iph, ihl*4, 0));
 }
 
 /*
@@ -190,47 +124,47 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
                    unsigned int sum)
 {
 #ifndef __s390x__
-       __asm__ __volatile__ (
-                "    alr   %0,%1\n"  /* sum += saddr */
-                "    brc   12,0f\n"
-               "    ahi   %0,1\n"   /* add carry */
+       asm volatile(
+               "       alr     %0,%1\n" /* sum += saddr */
+               "       brc     12,0f\n"
+               "       ahi     %0,1\n"  /* add carry */
                "0:"
-               : "+&d" (sum) : "d" (saddr) : "cc" );
-       __asm__ __volatile__ (
-                "    alr   %0,%1\n"  /* sum += daddr */
-                "    brc   12,1f\n"
-                "    ahi   %0,1\n"   /* add carry */
+               : "+&d" (sum) : "d" (saddr) : "cc");
+       asm volatile(
+               "       alr     %0,%1\n" /* sum += daddr */
+               "       brc     12,1f\n"
+               "       ahi     %0,1\n"  /* add carry */
                "1:"
-               : "+&d" (sum) : "d" (daddr) : "cc" );
-       __asm__ __volatile__ (
-                "    alr   %0,%1\n"  /* sum += (len<<16) + (proto<<8) */
-               "    brc   12,2f\n"
-               "    ahi   %0,1\n"   /* add carry */
+               : "+&d" (sum) : "d" (daddr) : "cc");
+       asm volatile(
+               "       alr     %0,%1\n" /* sum += (len<<16) + (proto<<8) */
+               "       brc     12,2f\n"
+               "       ahi     %0,1\n"  /* add carry */
                "2:"
                : "+&d" (sum)
                : "d" (((unsigned int) len<<16) + (unsigned int) proto)
-               : "cc" );
+               : "cc");
 #else /* __s390x__ */
-       __asm__ __volatile__ (
-                "    lgfr  %0,%0\n"
-                "    algr  %0,%1\n"  /* sum += saddr */
-                "    brc   12,0f\n"
-               "    aghi  %0,1\n"   /* add carry */
-               "0:  algr  %0,%2\n"  /* sum += daddr */
-                "    brc   12,1f\n"
-                "    aghi  %0,1\n"   /* add carry */
-               "1:  algfr %0,%3\n"  /* sum += (len<<16) + proto */
-               "    brc   12,2f\n"
-               "    aghi  %0,1\n"   /* add carry */
-               "2:  srlg  0,%0,32\n"
-                "    alr   %0,0\n"   /* fold to 32 bits */
-                "    brc   12,3f\n"
-                "    ahi   %0,1\n"   /* add carry */
-                "3:  llgfr %0,%0"
+       asm volatile(
+               "       lgfr    %0,%0\n"
+               "       algr    %0,%1\n"  /* sum += saddr */
+               "       brc     12,0f\n"
+               "       aghi    %0,1\n"   /* add carry */
+               "0:     algr    %0,%2\n"  /* sum += daddr */
+               "       brc     12,1f\n"
+               "       aghi    %0,1\n"   /* add carry */
+               "1:     algfr   %0,%3\n"  /* sum += (len<<16) + proto */
+               "       brc     12,2f\n"
+               "       aghi    %0,1\n"   /* add carry */
+               "2:     srlg    0,%0,32\n"
+               "       alr     %0,0\n"   /* fold to 32 bits */
+               "       brc     12,3f\n"
+               "       ahi     %0,1\n"   /* add carry */
+               "3:     llgfr   %0,%0"
                : "+&d" (sum)
                : "d" (saddr), "d" (daddr),
                  "d" (((unsigned int) len<<16) + (unsigned int) proto)
-               : "cc", "0" );
+               : "cc", "0");
 #endif /* __s390x__ */
        return sum;
 }
index af098dc3cf59b614aedb59f80fb85d83d46e8217..6cd978cefb2850be383e462f77a05c23ff7adc33 100644 (file)
@@ -1,49 +1 @@
-#ifndef __S390_DIV64
-#define __S390_DIV64
-
-#ifndef __s390x__
-
-/* for do_div "base" needs to be smaller than 2^31-1 */
-#define do_div(n, base) ({                                      \
-       unsigned long long __n = (n);                           \
-       unsigned long __r;                                      \
-                                                               \
-       asm ("   slr  0,0\n"                                    \
-            "   l    1,%1\n"                                   \
-            "   srdl 0,1\n"                                    \
-            "   dr   0,%2\n"                                   \
-            "   alr  1,1\n"                                    \
-            "   alr  0,0\n"                                    \
-            "   lhi  2,1\n"                                    \
-            "   n    2,%1\n"                                   \
-            "   alr  0,2\n"                                    \
-            "   clr  0,%2\n"                                   \
-            "   jl   0f\n"                                     \
-            "   slr  0,%2\n"                                   \
-             "   ahi  1,1\n"                                   \
-            "0: st   1,%1\n"                                   \
-            "   l    1,4+%1\n"                                 \
-            "   srdl 0,1\n"                                    \
-             "   dr   0,%2\n"                                  \
-            "   alr  1,1\n"                                    \
-            "   alr  0,0\n"                                    \
-            "   lhi  2,1\n"                                    \
-            "   n    2,4+%1\n"                                 \
-            "   alr  0,2\n"                                    \
-            "   clr  0,%2\n"                                   \
-             "   jl   1f\n"                                    \
-            "   slr  0,%2\n"                                   \
-            "   ahi  1,1\n"                                    \
-            "1: st   1,4+%1\n"                                 \
-             "   lr   %0,0"                                    \
-            : "=d" (__r), "=m" (__n)                           \
-            : "d" (base), "m" (__n) : "0", "1", "2", "cc" );   \
-       (n) = (__n);                                            \
-        __r;                                                    \
-})
-
-#else /* __s390x__ */
 #include <asm-generic/div64.h>
-#endif /* __s390x__ */
-
-#endif
index 15fd2eda6c90191913581024465d59fcfb694e88..7f6f641d32f4b3b42e0eaeacbc03eef3beaf7855 100644 (file)
@@ -26,16 +26,16 @@ codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr)
 {
        if (nr-- <= 0)
                return;
-        __asm__ __volatile__(
-               "   bras 1,1f\n"
-               "   tr   0(1,%0),0(%2)\n"
-                "0: tr   0(256,%0),0(%2)\n"
-               "   la   %0,256(%0)\n"
-               "1: ahi  %1,-256\n"
-               "   jnm  0b\n"
-               "   ex   %1,0(1)"
-                : "+&a" (addr), "+&a" (nr)
-                : "a" (codepage) : "cc", "memory", "1" );
+       asm volatile(
+               "       bras    1,1f\n"
+               "       tr      0(1,%0),0(%2)\n"
+               "0:     tr      0(256,%0),0(%2)\n"
+               "       la      %0,256(%0)\n"
+               "1:     ahi     %1,-256\n"
+               "       jnm     0b\n"
+               "       ex      %1,0(1)"
+               : "+&a" (addr), "+&a" (nr)
+               : "a" (codepage) : "cc", "memory", "1");
 }
 
 #define ASCEBC(addr,nr) codepage_convert(_ascebc, addr, nr)
index a6cc27e7700741adcaaee09e4fdfaec81260d1a5..63c78b9399c489b4fdee65ed05aec791e798e82d 100644 (file)
 static inline unsigned long virt_to_phys(volatile void * address)
 {
        unsigned long real_address;
-       __asm__ (
+       asm volatile(
 #ifndef __s390x__
-                "   lra    %0,0(%1)\n"
-                 "   jz     0f\n"
-                 "   sr     %0,%0\n"
+                "      lra     %0,0(%1)\n"
 #else /* __s390x__ */
-                "   lrag   %0,0(%1)\n"
-                 "   jz     0f\n"
-                 "   slgr   %0,%0\n"
+                "      lrag    %0,0(%1)\n"
 #endif /* __s390x__ */
+                "      jz      0f\n"
+                "      la      %0,0\n"
                  "0:"
-                 : "=a" (real_address) : "a" (address) : "cc" );
+                : "=a" (real_address) : "a" (address) : "cc");
         return real_address;
 }
 
index bd1a721f7aa2e82f1da34afb8d7f7771e260033c..7da991a858f8c97f1f390fd8285ebb3ab9e3c592 100644 (file)
@@ -19,8 +19,5 @@ enum interruption_class {
        NR_IRQS,
 };
 
-#define touch_nmi_watchdog() do { } while(0)
-
 #endif /* __KERNEL__ */
 #endif
-
index 3b566a5b3cc73e19d2487931283da12a0b008d65..3f26131120b746c47c81e7d370d76a2422b46153 100644 (file)
 
 #ifdef __KERNEL__
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
+/* store then or system mask. */
+#define __raw_local_irq_stosm(__or)                                    \
+({                                                                     \
+       unsigned long __mask;                                           \
+       asm volatile(                                                   \
+               "       stosm   %0,%1"                                  \
+               : "=Q" (__mask) : "i" (__or) : "memory");               \
+       __mask;                                                         \
+})
+
+/* store then and system mask. */
+#define __raw_local_irq_stnsm(__and)                                   \
+({                                                                     \
+       unsigned long __mask;                                           \
+       asm volatile(                                                   \
+               "       stnsm   %0,%1"                                  \
+               : "=Q" (__mask) : "i" (__and) : "memory");              \
+       __mask;                                                         \
+})
+
+/* set system mask. */
+#define __raw_local_irq_ssm(__mask)                                    \
+({                                                                     \
+       asm volatile("ssm   %0" : : "Q" (__mask) : "memory");           \
+})
+
+#else /* __GNUC__ */
+
+/* store then or system mask. */
+#define __raw_local_irq_stosm(__or)                                    \
+({                                                                     \
+       unsigned long __mask;                                           \
+       asm volatile(                                                   \
+               "       stosm   0(%1),%2"                               \
+               : "=m" (__mask)                                         \
+               : "a" (&__mask), "i" (__or) : "memory");                \
+       __mask;                                                         \
+})
+
+/* store then and system mask. */
+#define __raw_local_irq_stnsm(__and)                                   \
+({                                                                     \
+       unsigned long __mask;                                           \
+       asm volatile(                                                   \
+               "       stnsm   0(%1),%2"                               \
+               : "=m" (__mask)                                         \
+               : "a" (&__mask), "i" (__and) : "memory");               \
+       __mask;                                                         \
+})
+
+/* set system mask. */
+#define __raw_local_irq_ssm(__mask)                                    \
+({                                                                     \
+       asm volatile(                                                   \
+               "       ssm     0(%0)"                                  \
+               : : "a" (&__mask), "m" (__mask) : "memory");            \
+})
+
+#endif /* __GNUC__ */
+
 /* interrupt control.. */
-#define raw_local_irq_enable() ({ \
-       unsigned long  __dummy; \
-       __asm__ __volatile__ ( \
-               "stosm 0(%1),0x03" \
-               : "=m" (__dummy) : "a" (&__dummy) : "memory" ); \
-       })
-
-#define raw_local_irq_disable() ({ \
-       unsigned long __flags; \
-       __asm__ __volatile__ ( \
-               "stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \
-       __flags; \
-       })
-
-#define raw_local_save_flags(x)                                                        \
-do {                                                                           \
-       typecheck(unsigned long, x);                                            \
-       __asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) );  \
-} while (0)
+static inline unsigned long raw_local_irq_enable(void)
+{
+       return __raw_local_irq_stosm(0x03);
+}
 
-#define raw_local_irq_restore(x)                                               \
-do {                                                                           \
-       typecheck(unsigned long, x);                                            \
-       __asm__ __volatile__("ssm   0(%0)" : : "a" (&x), "m" (x) : "memory");   \
+static inline unsigned long raw_local_irq_disable(void)
+{
+       return __raw_local_irq_stnsm(0xfc);
+}
+
+#define raw_local_save_flags(x)                                                \
+do {                                                                   \
+       typecheck(unsigned long, x);                                    \
+       (x) = __raw_local_irq_stosm(0x00);                              \
 } while (0)
 
-#define raw_irqs_disabled()            \
-({                                     \
-       unsigned long flags;            \
-       raw_local_save_flags(flags);    \
-       !((flags >> __FLAG_SHIFT) & 3); \
-})
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+       __raw_local_irq_ssm(flags);
+}
 
 static inline int raw_irqs_disabled_flags(unsigned long flags)
 {
-       return !((flags >> __FLAG_SHIFT) & 3);
+       return !(flags & (3UL << (BITS_PER_LONG - 8)));
 }
 
 /* For spinlocks etc */
index 18695d10dedfdd6477973ca18efce6ff08cebd2d..06583ed0bde7bbc97a124a66fc92cf041f6acfb8 100644 (file)
@@ -359,7 +359,7 @@ extern struct _lowcore *lowcore_ptr[];
 
 static inline void set_prefix(__u32 address)
 {
-        __asm__ __volatile__ ("spx %0" : : "m" (address) : "memory" );
+       asm volatile("spx %0" : : "m" (address) : "memory");
 }
 
 #define __PANIC_MAGIC           0xDEADC0DE
index b2628dc5c49075d0841c9b440c2b8a8288f4cd6e..796c400f2b79963c5f63f2bf7a5640d3a4e6880f 100644 (file)
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
-#ifndef __s390x__
-
-static inline void clear_page(void *page)
-{
-       register_pair rp;
-
-       rp.subreg.even = (unsigned long) page;
-       rp.subreg.odd = (unsigned long) 4096;
-        asm volatile ("   slr  1,1\n"
-                     "   mvcl %0,0"
-                     : "+&a" (rp) : : "memory", "cc", "1" );
-}
-
-static inline void copy_page(void *to, void *from)
-{
-        if (MACHINE_HAS_MVPG)
-               asm volatile ("   sr   0,0\n"
-                             "   mvpg %0,%1"
-                             : : "a" ((void *)(to)), "a" ((void *)(from))
-                             : "memory", "cc", "0" );
-       else
-               asm volatile ("   mvc  0(256,%0),0(%1)\n"
-                             "   mvc  256(256,%0),256(%1)\n"
-                             "   mvc  512(256,%0),512(%1)\n"
-                             "   mvc  768(256,%0),768(%1)\n"
-                             "   mvc  1024(256,%0),1024(%1)\n"
-                             "   mvc  1280(256,%0),1280(%1)\n"
-                             "   mvc  1536(256,%0),1536(%1)\n"
-                             "   mvc  1792(256,%0),1792(%1)\n"
-                             "   mvc  2048(256,%0),2048(%1)\n"
-                             "   mvc  2304(256,%0),2304(%1)\n"
-                             "   mvc  2560(256,%0),2560(%1)\n"
-                             "   mvc  2816(256,%0),2816(%1)\n"
-                             "   mvc  3072(256,%0),3072(%1)\n"
-                             "   mvc  3328(256,%0),3328(%1)\n"
-                             "   mvc  3584(256,%0),3584(%1)\n"
-                             "   mvc  3840(256,%0),3840(%1)\n"
-                             : : "a"((void *)(to)),"a"((void *)(from)) 
-                             : "memory" );
-}
-
-#else /* __s390x__ */
-
 static inline void clear_page(void *page)
 {
-        asm volatile ("   lgr  2,%0\n"
-                      "   lghi 3,4096\n"
-                      "   slgr 1,1\n"
-                      "   mvcl 2,0"
-                      : : "a" ((void *) (page))
-                     : "memory", "cc", "1", "2", "3" );
+       register unsigned long reg1 asm ("1") = 0;
+       register void *reg2 asm ("2") = page;
+       register unsigned long reg3 asm ("3") = 4096;
+       asm volatile(
+               "       mvcl    2,0"
+               : "+d" (reg2), "+d" (reg3) : "d" (reg1) : "memory", "cc");
 }
 
 static inline void copy_page(void *to, void *from)
 {
-        if (MACHINE_HAS_MVPG)
-               asm volatile ("   sgr  0,0\n"
-                             "   mvpg %0,%1"
-                             : : "a" ((void *)(to)), "a" ((void *)(from))
-                             : "memory", "cc", "0" );
-       else
-               asm volatile ("   mvc  0(256,%0),0(%1)\n"
-                             "   mvc  256(256,%0),256(%1)\n"
-                             "   mvc  512(256,%0),512(%1)\n"
-                             "   mvc  768(256,%0),768(%1)\n"
-                             "   mvc  1024(256,%0),1024(%1)\n"
-                             "   mvc  1280(256,%0),1280(%1)\n"
-                             "   mvc  1536(256,%0),1536(%1)\n"
-                             "   mvc  1792(256,%0),1792(%1)\n"
-                             "   mvc  2048(256,%0),2048(%1)\n"
-                             "   mvc  2304(256,%0),2304(%1)\n"
-                             "   mvc  2560(256,%0),2560(%1)\n"
-                             "   mvc  2816(256,%0),2816(%1)\n"
-                             "   mvc  3072(256,%0),3072(%1)\n"
-                             "   mvc  3328(256,%0),3328(%1)\n"
-                             "   mvc  3584(256,%0),3584(%1)\n"
-                             "   mvc  3840(256,%0),3840(%1)\n"
-                             : : "a"((void *)(to)),"a"((void *)(from)) 
-                             : "memory" );
+       if (MACHINE_HAS_MVPG) {
+               register unsigned long reg0 asm ("0") = 0;
+               asm volatile(
+                       "       mvpg    %0,%1"
+                       : : "a" (to), "a" (from), "d" (reg0)
+                       : "memory", "cc");
+       } else
+               asm volatile(
+                       "       mvc     0(256,%0),0(%1)\n"
+                       "       mvc     256(256,%0),256(%1)\n"
+                       "       mvc     512(256,%0),512(%1)\n"
+                       "       mvc     768(256,%0),768(%1)\n"
+                       "       mvc     1024(256,%0),1024(%1)\n"
+                       "       mvc     1280(256,%0),1280(%1)\n"
+                       "       mvc     1536(256,%0),1536(%1)\n"
+                       "       mvc     1792(256,%0),1792(%1)\n"
+                       "       mvc     2048(256,%0),2048(%1)\n"
+                       "       mvc     2304(256,%0),2304(%1)\n"
+                       "       mvc     2560(256,%0),2560(%1)\n"
+                       "       mvc     2816(256,%0),2816(%1)\n"
+                       "       mvc     3072(256,%0),3072(%1)\n"
+                       "       mvc     3328(256,%0),3328(%1)\n"
+                       "       mvc     3584(256,%0),3584(%1)\n"
+                       "       mvc     3840(256,%0),3840(%1)\n"
+                       : : "a" (to), "a" (from) : "memory");
 }
 
-#endif /* __s390x__ */
-
 #define clear_user_page(page, vaddr, pg)       clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
 
@@ -159,7 +115,7 @@ extern unsigned int default_storage_key;
 static inline void
 page_set_storage_key(unsigned long addr, unsigned int skey)
 {
-       asm volatile ( "sske %0,%1" : : "d" (skey), "a" (addr) );
+       asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
 }
 
 static inline unsigned int
@@ -167,8 +123,7 @@ page_get_storage_key(unsigned long addr)
 {
        unsigned int skey;
 
-       asm volatile ( "iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0) );
-
+       asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0));
        return skey;
 }
 
index e965309fedac640486c65a130a59ada9c0eb6caf..ecdff13b250512839a494c7d4432b5de2bd2dddc 100644 (file)
@@ -31,9 +31,9 @@
  * the S390 page table tree.
  */
 #ifndef __ASSEMBLY__
+#include <linux/mm_types.h>
 #include <asm/bug.h>
 #include <asm/processor.h>
-#include <linux/threads.h>
 
 struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
 struct mm_struct;
@@ -554,9 +554,10 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
                /* ipte in zarch mode can do the math */
                pte_t *pto = ptep;
 #endif
-               asm volatile ("ipte %2,%3"
-                             : "=m" (*ptep) : "m" (*ptep),
-                               "a" (pto), "a" (address) );
+               asm volatile(
+                       "       ipte    %2,%3"
+                       : "=m" (*ptep) : "m" (*ptep),
+                         "a" (pto), "a" (address));
        }
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
 }
@@ -596,30 +597,31 @@ ptep_establish(struct vm_area_struct *vma,
  * should therefore only be called if it is not mapped in any
  * address space.
  */
-#define page_test_and_clear_dirty(_page)                                 \
-({                                                                       \
-       struct page *__page = (_page);                                    \
-       unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-       int __skey = page_get_storage_key(__physpage);                    \
-       if (__skey & _PAGE_CHANGED)                                       \
-               page_set_storage_key(__physpage, __skey & ~_PAGE_CHANGED);\
-       (__skey & _PAGE_CHANGED);                                         \
-})
+static inline int page_test_and_clear_dirty(struct page *page)
+{
+       unsigned long physpage = __pa((page - mem_map) << PAGE_SHIFT);
+       int skey = page_get_storage_key(physpage);
+
+       if (skey & _PAGE_CHANGED)
+               page_set_storage_key(physpage, skey & ~_PAGE_CHANGED);
+       return skey & _PAGE_CHANGED;
+}
 
 /*
  * Test and clear referenced bit in storage key.
  */
-#define page_test_and_clear_young(page)                                          \
-({                                                                       \
-       struct page *__page = (page);                                     \
-       unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-       int __ccode;                                                      \
-       asm volatile ("rrbe 0,%1\n\t"                                     \
-                     "ipm  %0\n\t"                                       \
-                     "srl  %0,28\n\t"                                    \
-                      : "=d" (__ccode) : "a" (__physpage) : "cc" );      \
-       (__ccode & 2);                                                    \
-})
+static inline int page_test_and_clear_young(struct page *page)
+{
+       unsigned long physpage = __pa((page - mem_map) << PAGE_SHIFT);
+       int ccode;
+
+       asm volatile (
+               "rrbe 0,%1\n"
+               "ipm  %0\n"
+               "srl  %0,28\n"
+               : "=d" (ccode) : "a" (physpage) : "cc" );
+       return ccode & 2;
+}
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
@@ -632,32 +634,28 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
        return __pte;
 }
 
-#define mk_pte(pg, pgprot)                                                \
-({                                                                        \
-       struct page *__page = (pg);                                       \
-       pgprot_t __pgprot = (pgprot);                                     \
-       unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-       pte_t __pte = mk_pte_phys(__physpage, __pgprot);                  \
-       __pte;                                                            \
-})
+static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+       unsigned long physpage = __pa((page - mem_map) << PAGE_SHIFT);
 
-#define pfn_pte(pfn, pgprot)                                              \
-({                                                                        \
-       pgprot_t __pgprot = (pgprot);                                     \
-       unsigned long __physpage = __pa((pfn) << PAGE_SHIFT);             \
-       pte_t __pte = mk_pte_phys(__physpage, __pgprot);                  \
-       __pte;                                                            \
-})
+       return mk_pte_phys(physpage, pgprot);
+}
+
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
+{
+       unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
+
+       return mk_pte_phys(physpage, pgprot);
+}
 
 #ifdef __s390x__
 
-#define pfn_pmd(pfn, pgprot)                                              \
-({                                                                        \
-       pgprot_t __pgprot = (pgprot);                                     \
-       unsigned long __physpage = __pa((pfn) << PAGE_SHIFT);             \
-       pmd_t __pmd = __pmd(__physpage + pgprot_val(__pgprot));           \
-       __pmd;                                                            \
-})
+static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
+{
+       unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
+
+       return __pmd(physpage + pgprot_val(pgprot));
+}
 
 #endif /* __s390x__ */
 
index 578c2209fa76c269587b0b9507217bf3fa9d0563..cbbedc63ba25bac653aba4363ea5e1c6c2822fbb 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __ASM_S390_PROCESSOR_H
 #define __ASM_S390_PROCESSOR_H
 
-#include <asm/page.h>
 #include <asm/ptrace.h>
 
 #ifdef __KERNEL__
@@ -21,7 +20,7 @@
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
  */
-#define current_text_addr() ({ void *pc; __asm__("basr %0,0":"=a"(pc)); pc; })
+#define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; })
 
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
@@ -202,7 +201,7 @@ unsigned long get_wchan(struct task_struct *p);
 static inline void cpu_relax(void)
 {
        if (MACHINE_HAS_DIAG44)
-               asm volatile ("diag 0,0,68" : : : "memory");
+               asm volatile("diag 0,0,68" : : : "memory");
        else
                barrier();
 }
@@ -213,9 +212,9 @@ static inline void cpu_relax(void)
 static inline void __load_psw(psw_t psw)
 {
 #ifndef __s390x__
-       asm volatile ("lpsw  0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+       asm volatile("lpsw  0(%0)" : : "a" (&psw), "m" (psw) : "cc");
 #else
-       asm volatile ("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+       asm volatile("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc");
 #endif
 }
 
@@ -232,20 +231,20 @@ static inline void __load_psw_mask (unsigned long mask)
        psw.mask = mask;
 
 #ifndef __s390x__
-       asm volatile (
-               "    basr %0,0\n"
-               "0:  ahi  %0,1f-0b\n"
-               "    st   %0,4(%1)\n"
-               "    lpsw 0(%1)\n"
+       asm volatile(
+               "       basr    %0,0\n"
+               "0:     ahi     %0,1f-0b\n"
+               "       st      %0,4(%1)\n"
+               "       lpsw    0(%1)\n"
                "1:"
-               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" );
+               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc");
 #else /* __s390x__ */
-       asm volatile (
-               "    larl  %0,1f\n"
-               "    stg   %0,8(%1)\n"
-               "    lpswe 0(%1)\n"
+       asm volatile(
+               "       larl    %0,1f\n"
+               "       stg     %0,8(%1)\n"
+               "       lpswe   0(%1)\n"
                "1:"
-               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" );
+               : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc");
 #endif /* __s390x__ */
 }
  
@@ -274,56 +273,57 @@ static inline void disabled_wait(unsigned long code)
          * the processor is dead afterwards
          */
 #ifndef __s390x__
-        asm volatile ("    stctl 0,0,0(%2)\n"
-                      "    ni    0(%2),0xef\n" /* switch off protection */
-                      "    lctl  0,0,0(%2)\n"
-                      "    stpt  0xd8\n"       /* store timer */
-                      "    stckc 0xe0\n"       /* store clock comparator */
-                      "    stpx  0x108\n"      /* store prefix register */
-                      "    stam  0,15,0x120\n" /* store access registers */
-                      "    std   0,0x160\n"    /* store f0 */
-                      "    std   2,0x168\n"    /* store f2 */
-                      "    std   4,0x170\n"    /* store f4 */
-                      "    std   6,0x178\n"    /* store f6 */
-                      "    stm   0,15,0x180\n" /* store general registers */
-                      "    stctl 0,15,0x1c0\n" /* store control registers */
-                      "    oi    0x1c0,0x10\n" /* fake protection bit */
-                      "    lpsw 0(%1)"
-                      : "=m" (ctl_buf)
-                     : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
+       asm volatile(
+               "       stctl   0,0,0(%2)\n"
+               "       ni      0(%2),0xef\n"   /* switch off protection */
+               "       lctl    0,0,0(%2)\n"
+               "       stpt    0xd8\n"         /* store timer */
+               "       stckc   0xe0\n"         /* store clock comparator */
+               "       stpx    0x108\n"        /* store prefix register */
+               "       stam    0,15,0x120\n"   /* store access registers */
+               "       std     0,0x160\n"      /* store f0 */
+               "       std     2,0x168\n"      /* store f2 */
+               "       std     4,0x170\n"      /* store f4 */
+               "       std     6,0x178\n"      /* store f6 */
+               "       stm     0,15,0x180\n"   /* store general registers */
+               "       stctl   0,15,0x1c0\n"   /* store control registers */
+               "       oi      0x1c0,0x10\n"   /* fake protection bit */
+               "       lpsw    0(%1)"
+               : "=m" (ctl_buf)
+               : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc");
 #else /* __s390x__ */
-        asm volatile ("    stctg 0,0,0(%2)\n"
-                      "    ni    4(%2),0xef\n" /* switch off protection */
-                      "    lctlg 0,0,0(%2)\n"
-                      "    lghi  1,0x1000\n"
-                      "    stpt  0x328(1)\n"      /* store timer */
-                      "    stckc 0x330(1)\n"      /* store clock comparator */
-                      "    stpx  0x318(1)\n"      /* store prefix register */
-                      "    stam  0,15,0x340(1)\n" /* store access registers */
-                      "    stfpc 0x31c(1)\n"      /* store fpu control */
-                      "    std   0,0x200(1)\n"    /* store f0 */
-                      "    std   1,0x208(1)\n"    /* store f1 */
-                      "    std   2,0x210(1)\n"    /* store f2 */
-                      "    std   3,0x218(1)\n"    /* store f3 */
-                      "    std   4,0x220(1)\n"    /* store f4 */
-                      "    std   5,0x228(1)\n"    /* store f5 */
-                      "    std   6,0x230(1)\n"    /* store f6 */
-                      "    std   7,0x238(1)\n"    /* store f7 */
-                      "    std   8,0x240(1)\n"    /* store f8 */
-                      "    std   9,0x248(1)\n"    /* store f9 */
-                      "    std   10,0x250(1)\n"   /* store f10 */
-                      "    std   11,0x258(1)\n"   /* store f11 */
-                      "    std   12,0x260(1)\n"   /* store f12 */
-                      "    std   13,0x268(1)\n"   /* store f13 */
-                      "    std   14,0x270(1)\n"   /* store f14 */
-                      "    std   15,0x278(1)\n"   /* store f15 */
-                      "    stmg  0,15,0x280(1)\n" /* store general registers */
-                      "    stctg 0,15,0x380(1)\n" /* store control registers */
-                      "    oi    0x384(1),0x10\n" /* fake protection bit */
-                      "    lpswe 0(%1)"
-                      : "=m" (ctl_buf)
-                     : "a" (&dw_psw), "a" (&ctl_buf),
-                       "m" (dw_psw) : "cc", "0", "1");
+       asm volatile(
+               "       stctg   0,0,0(%2)\n"
+               "       ni      4(%2),0xef\n"   /* switch off protection */
+               "       lctlg   0,0,0(%2)\n"
+               "       lghi    1,0x1000\n"
+               "       stpt    0x328(1)\n"     /* store timer */
+               "       stckc   0x330(1)\n"     /* store clock comparator */
+               "       stpx    0x318(1)\n"     /* store prefix register */
+               "       stam    0,15,0x340(1)\n"/* store access registers */
+               "       stfpc   0x31c(1)\n"     /* store fpu control */
+               "       std     0,0x200(1)\n"   /* store f0 */
+               "       std     1,0x208(1)\n"   /* store f1 */
+               "       std     2,0x210(1)\n"   /* store f2 */
+               "       std     3,0x218(1)\n"   /* store f3 */
+               "       std     4,0x220(1)\n"   /* store f4 */
+               "       std     5,0x228(1)\n"   /* store f5 */
+               "       std     6,0x230(1)\n"   /* store f6 */
+               "       std     7,0x238(1)\n"   /* store f7 */
+               "       std     8,0x240(1)\n"   /* store f8 */
+               "       std     9,0x248(1)\n"   /* store f9 */
+               "       std     10,0x250(1)\n"  /* store f10 */
+               "       std     11,0x258(1)\n"  /* store f11 */
+               "       std     12,0x260(1)\n"  /* store f12 */
+               "       std     13,0x268(1)\n"  /* store f13 */
+               "       std     14,0x270(1)\n"  /* store f14 */
+               "       std     15,0x278(1)\n"  /* store f15 */
+               "       stmg    0,15,0x280(1)\n"/* store general registers */
+               "       stctg   0,15,0x380(1)\n"/* store control registers */
+               "       oi      0x384(1),0x10\n"/* fake protection bit */
+               "       lpswe   0(%1)"
+               : "=m" (ctl_buf)
+               : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0");
 #endif /* __s390x__ */
 }
 
index 4d75d77b0f9960cad73cedb09adaae4e85a6c5c1..8d2bf65b0b6487a4c64df4444f3740d16c0428cb 100644 (file)
@@ -479,7 +479,7 @@ extern void show_regs(struct pt_regs * regs);
 static inline void
 psw_set_key(unsigned int key)
 {
-       asm volatile ( "spka 0(%0)" : : "d" (key) );
+       asm volatile("spka 0(%0)" : : "d" (key));
 }
 
 #endif /* __ASSEMBLY__ */
index 13ec16965150af1ca147ff4426b81b351d234c24..90f4eccaa290eb936de85dca4a6e96825f5e20bf 100644 (file)
@@ -122,23 +122,23 @@ static inline void __down_read(struct rw_semaphore *sem)
 {
        signed long old, new;
 
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   ahi  %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       ahi     %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   aghi %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       aghi    %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count),
-                 "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" );
+                 "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory");
        if (old < 0)
                rwsem_down_read_failed(sem);
 }
@@ -150,27 +150,27 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
 {
        signed long old, new;
 
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: ltr  %1,%0\n"
-               "   jm   1f\n"
-               "   ahi  %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b\n"
+               "       l       %0,0(%3)\n"
+               "0:     ltr     %1,%0\n"
+               "       jm      1f\n"
+               "       ahi     %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b\n"
                "1:"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: ltgr %1,%0\n"
-               "   jm   1f\n"
-               "   aghi %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b\n"
+               "       lg      %0,0(%3)\n"
+               "0:     ltgr    %1,%0\n"
+               "       jm      1f\n"
+               "       aghi    %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b\n"
                "1:"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count),
-                 "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" );
+                 "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory");
        return old >= 0 ? 1 : 0;
 }
 
@@ -182,23 +182,23 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
        signed long old, new, tmp;
 
        tmp = RWSEM_ACTIVE_WRITE_BIAS;
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   a    %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       a       %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   ag   %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       ag      %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count), "m" (tmp)
-               : "cc", "memory" );
+               : "cc", "memory");
        if (old != 0)
                rwsem_down_write_failed(sem);
 }
@@ -215,24 +215,24 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
        signed long old;
 
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%2)\n"
-               "0: ltr  %0,%0\n"
-               "   jnz  1f\n"
-               "   cs   %0,%4,0(%2)\n"
-               "   jl   0b\n"
+               "       l       %0,0(%2)\n"
+               "0:     ltr     %0,%0\n"
+               "       jnz     1f\n"
+               "       cs      %0,%4,0(%2)\n"
+               "       jl      0b\n"
 #else /* __s390x__ */
-               "   lg   %0,0(%2)\n"
-               "0: ltgr %0,%0\n"
-               "   jnz  1f\n"
-               "   csg  %0,%4,0(%2)\n"
-               "   jl   0b\n"
+               "       lg      %0,0(%2)\n"
+               "0:     ltgr    %0,%0\n"
+               "       jnz     1f\n"
+               "       csg     %0,%4,0(%2)\n"
+               "       jl      0b\n"
 #endif /* __s390x__ */
                "1:"
-                : "=&d" (old), "=m" (sem->count)
+               : "=&d" (old), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count),
-                 "d" (RWSEM_ACTIVE_WRITE_BIAS) : "cc", "memory" );
+                 "d" (RWSEM_ACTIVE_WRITE_BIAS) : "cc", "memory");
        return (old == RWSEM_UNLOCKED_VALUE) ? 1 : 0;
 }
 
@@ -243,24 +243,24 @@ static inline void __up_read(struct rw_semaphore *sem)
 {
        signed long old, new;
 
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   ahi  %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       ahi     %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   aghi %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       aghi    %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count),
                  "i" (-RWSEM_ACTIVE_READ_BIAS)
-               : "cc", "memory" );
+               : "cc", "memory");
        if (new < 0)
                if ((new & RWSEM_ACTIVE_MASK) == 0)
                        rwsem_wake(sem);
@@ -274,23 +274,23 @@ static inline void __up_write(struct rw_semaphore *sem)
        signed long old, new, tmp;
 
        tmp = -RWSEM_ACTIVE_WRITE_BIAS;
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   a    %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       a       %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   ag   %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       ag      %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count), "m" (tmp)
-               : "cc", "memory" );
+               : "cc", "memory");
        if (new < 0)
                if ((new & RWSEM_ACTIVE_MASK) == 0)
                        rwsem_wake(sem);
@@ -304,23 +304,23 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
        signed long old, new, tmp;
 
        tmp = -RWSEM_WAITING_BIAS;
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   a    %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       a       %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   ag   %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       ag      %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count), "m" (tmp)
-               : "cc", "memory" );
+               : "cc", "memory");
        if (new > 1)
                rwsem_downgrade_wake(sem);
 }
@@ -332,23 +332,23 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
 {
        signed long old, new;
 
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   ar   %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       ar      %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   agr  %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       agr     %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count), "d" (delta)
-               : "cc", "memory" );
+               : "cc", "memory");
 }
 
 /*
@@ -358,23 +358,23 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
        signed long old, new;
 
-       __asm__ __volatile__(
+       asm volatile(
 #ifndef __s390x__
-               "   l    %0,0(%3)\n"
-               "0: lr   %1,%0\n"
-               "   ar   %1,%5\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       l       %0,0(%3)\n"
+               "0:     lr      %1,%0\n"
+               "       ar      %1,%5\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b"
 #else /* __s390x__ */
-               "   lg   %0,0(%3)\n"
-               "0: lgr  %1,%0\n"
-               "   agr  %1,%5\n"
-               "   csg  %0,%1,0(%3)\n"
-               "   jl   0b"
+               "       lg      %0,0(%3)\n"
+               "0:     lgr     %1,%0\n"
+               "       agr     %1,%5\n"
+               "       csg     %0,%1,0(%3)\n"
+               "       jl      0b"
 #endif /* __s390x__ */
-                : "=&d" (old), "=&d" (new), "=m" (sem->count)
+               : "=&d" (old), "=&d" (new), "=m" (sem->count)
                : "a" (&sem->count), "m" (sem->count), "d" (delta)
-               : "cc", "memory" );
+               : "cc", "memory");
        return new;
 }
 
index 32cdc69f39f4dd28c42521e67d77a7b536356cdc..dbce058aefa92a6ed2f6781d1a5b1c147e1eae27 100644 (file)
@@ -85,17 +85,17 @@ static inline int down_trylock(struct semaphore * sem)
         *       sem->count.counter = --new_val;
         * In the ppc code this is called atomic_dec_if_positive.
         */
-       __asm__ __volatile__ (
-               "   l    %0,0(%3)\n"
-               "0: ltr  %1,%0\n"
-               "   jle  1f\n"
-               "   ahi  %1,-1\n"
-               "   cs   %0,%1,0(%3)\n"
-               "   jl   0b\n"
+       asm volatile(
+               "       l       %0,0(%3)\n"
+               "0:     ltr     %1,%0\n"
+               "       jle     1f\n"
+               "       ahi     %1,-1\n"
+               "       cs      %0,%1,0(%3)\n"
+               "       jl      0b\n"
                "1:"
                : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count.counter)
                : "a" (&sem->count.counter), "m" (sem->count.counter)
-               : "cc", "memory" );
+               : "cc", "memory");
        return old_val <= 0;
 }
 
index f1959732b6fdeb731608eea88da206c97ade05c1..5d72eda8a11b7b4a813b97d25c2734c192618ed0 100644 (file)
@@ -39,6 +39,7 @@ extern unsigned long machine_flags;
 #define MACHINE_IS_P390                (machine_flags & 4)
 #define MACHINE_HAS_MVPG       (machine_flags & 16)
 #define MACHINE_HAS_IDTE       (machine_flags & 128)
+#define MACHINE_HAS_DIAG9C     (machine_flags & 256)
 
 #ifndef __s390x__
 #define MACHINE_HAS_IEEE       (machine_flags & 2)
index de69dfa46fbba0baee8e305a61639adb1614d167..8ca8c77b2d04c75fa3d0498217d521f2001d66f1 100644 (file)
        unsigned int __r2 = (x2) + (y2);                        \
        unsigned int __r1 = (x1);                               \
        unsigned int __r0 = (x0);                               \
-       __asm__ ("   alr %2,%3\n"                               \
-                "   brc 12,0f\n"                               \
-                "   lhi 0,1\n"                                 \
-                "   alr %1,0\n"                                \
-                "   brc 12,0f\n"                               \
-                "   alr %0,0\n"                                \
-                "0:"                                           \
-                : "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)     \
-                : "d" (y0), "i" (1) : "cc", "0" );             \
-       __asm__ ("   alr %1,%2\n"                               \
-                "   brc 12,0f\n"                               \
-                "   ahi %0,1\n"                                \
-                "0:"                                           \
-                : "+&d" (__r2), "+&d" (__r1)                   \
-                : "d" (y1) : "cc" );                           \
+       asm volatile(                                           \
+               "       alr     %2,%3\n"                        \
+               "       brc     12,0f\n"                        \
+               "       lhi     0,1\n"                          \
+               "       alr     %1,0\n"                         \
+               "       brc     12,0f\n"                        \
+               "       alr     %0,0\n"                         \
+               "0:"                                            \
+               : "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)      \
+               : "d" (y0), "i" (1) : "cc", "0" );              \
+       asm volatile(                                           \
+               "       alr     %1,%2\n"                        \
+               "       brc     12,0f\n"                        \
+               "       ahi     %0,1\n"                         \
+               "0:"                                            \
+               : "+&d" (__r2), "+&d" (__r1)                    \
+               : "d" (y1) : "cc");                             \
        (r2) = __r2;                                            \
        (r1) = __r1;                                            \
        (r0) = __r0;                                            \
        unsigned int __r2 = (x2) - (y2);                        \
        unsigned int __r1 = (x1);                               \
        unsigned int __r0 = (x0);                               \
-       __asm__ ("   slr %2,%3\n"                               \
-                "   brc 3,0f\n"                                \
-                "   lhi 0,1\n"                                 \
-                "   slr %1,0\n"                                \
-                "   brc 3,0f\n"                                \
-                "   slr %0,0\n"                                \
-                "0:"                                           \
-                : "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)     \
-                : "d" (y0) : "cc", "0" );                      \
-       __asm__ ("   slr %1,%2\n"                               \
-                "   brc 3,0f\n"                                \
-                "   ahi %0,-1\n"                               \
-                "0:"                                           \
-                : "+&d" (__r2), "+&d" (__r1)                   \
-                : "d" (y1) : "cc" );                           \
+       asm volatile(                                           \
+               "       slr   %2,%3\n"                          \
+               "       brc     3,0f\n"                         \
+               "       lhi     0,1\n"                          \
+               "       slr     %1,0\n"                         \
+               "       brc     3,0f\n"                         \
+               "       slr     %0,0\n"                         \
+               "0:"                                            \
+               : "+&d" (__r2), "+&d" (__r1), "+&d" (__r0)      \
+               : "d" (y0) : "cc", "0");                        \
+       asm volatile(                                           \
+               "       slr     %1,%2\n"                        \
+               "       brc     3,0f\n"                         \
+               "       ahi     %0,-1\n"                        \
+               "0:"                                            \
+               : "+&d" (__r2), "+&d" (__r1)                    \
+               : "d" (y1) : "cc");                             \
        (r2) = __r2;                                            \
        (r1) = __r1;                                            \
        (r0) = __r0;                                            \
index fc56458aff66b8e52470235c6d11923d8ea027a2..e16d56f8dfe1dd01864c3993c60a2f0a43757799 100644 (file)
@@ -70,16 +70,16 @@ typedef enum
 static inline sigp_ccode
 signal_processor(__u16 cpu_addr, sigp_order_code order_code)
 {
+       register unsigned long reg1 asm ("1") = 0;
        sigp_ccode ccode;
 
-       __asm__ __volatile__(
-               "    sr     1,1\n"        /* parameter=0 in gpr 1 */
-               "    sigp   1,%1,0(%2)\n"
-               "    ipm    %0\n"
-               "    srl    %0,28\n"
-               : "=d" (ccode)
-               : "d" (__cpu_logical_map[cpu_addr]), "a" (order_code)
-               : "cc" , "memory", "1" );
+       asm volatile(
+               "       sigp    %1,%2,0(%3)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
+               :       "=d"    (ccode)
+               : "d" (reg1), "d" (__cpu_logical_map[cpu_addr]),
+                 "a" (order_code) : "cc" , "memory");
        return ccode;
 }
 
@@ -87,20 +87,18 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code)
  * Signal processor with parameter
  */
 static inline sigp_ccode
-signal_processor_p(__u32 parameter, __u16 cpu_addr,
-                  sigp_order_code order_code)
+signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code)
 {
+       register unsigned int reg1 asm ("1") = parameter;
        sigp_ccode ccode;
-       
-       __asm__ __volatile__(
-               "    lr     1,%1\n"       /* parameter in gpr 1 */
-               "    sigp   1,%2,0(%3)\n"
-               "    ipm    %0\n"
-               "    srl    %0,28\n"
+
+       asm volatile(
+               "       sigp    %1,%2,0(%3)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
                : "=d" (ccode)
-               : "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
-                  "a" (order_code)
-               : "cc" , "memory", "1" );
+               : "d" (reg1), "d" (__cpu_logical_map[cpu_addr]),
+                 "a" (order_code) : "cc" , "memory");
        return ccode;
 }
 
@@ -108,24 +106,21 @@ signal_processor_p(__u32 parameter, __u16 cpu_addr,
  * Signal processor with parameter and return status
  */
 static inline sigp_ccode
-signal_processor_ps(__u32 *statusptr, __u32 parameter,
-                   __u16 cpu_addr, sigp_order_code order_code)
+signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr,
+                   sigp_order_code order_code)
 {
+       register unsigned int reg1 asm ("1") = parameter;
        sigp_ccode ccode;
-       
-       __asm__ __volatile__(
-               "    sr     2,2\n"        /* clear status */
-               "    lr     3,%2\n"       /* parameter in gpr 3 */
-               "    sigp   2,%3,0(%4)\n"
-               "    st     2,%1\n"
-               "    ipm    %0\n"
-               "    srl    %0,28\n"
-               : "=d" (ccode), "=m" (*statusptr)
-               : "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
-                  "a" (order_code)
-               : "cc" , "memory", "2" , "3"
-               );
-   return ccode;
+
+       asm volatile(
+               "       sigp    %1,%2,0(%3)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
+               : "=d" (ccode), "+d" (reg1)
+               : "d" (__cpu_logical_map[cpu_addr]), "a" (order_code)
+               : "cc" , "memory");
+       *statusptr = reg1;
+       return ccode;
 }
 
 #endif /* __SIGP__ */
index 9fb02e9779c9fe470d9386f02901a0ee16f46062..c3cf030ada4d480bebcf788d5ce688fe1de37d91 100644 (file)
@@ -56,7 +56,7 @@ static inline __u16 hard_smp_processor_id(void)
 {
         __u16 cpu_address;
  
-        __asm__ ("stap %0\n" : "=m" (cpu_address));
+       asm volatile("stap %0" : "=m" (cpu_address));
         return cpu_address;
 }
 
index 273dbecf8acef0465060133bbac01bab72118fc5..6b78af16999be895b31a08f3386ddd3c532d64ae 100644 (file)
 #ifndef __ASM_SPINLOCK_H
 #define __ASM_SPINLOCK_H
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+
+#include <linux/smp.h>
+
 static inline int
 _raw_compare_and_swap(volatile unsigned int *lock,
                      unsigned int old, unsigned int new)
 {
-       asm volatile ("cs %0,%3,0(%4)"
-                     : "=d" (old), "=m" (*lock)
-                     : "0" (old), "d" (new), "a" (lock), "m" (*lock)
-                     : "cc", "memory" );
+       asm volatile(
+               "       cs      %0,%3,%1"
+               : "=d" (old), "=Q" (*lock)
+               : "0" (old), "d" (new), "Q" (*lock)
+               : "cc", "memory" );
        return old;
 }
 
+#else /* __GNUC__ */
+
+static inline int
+_raw_compare_and_swap(volatile unsigned int *lock,
+                     unsigned int old, unsigned int new)
+{
+       asm volatile(
+               "       cs      %0,%3,0(%4)"
+               : "=d" (old), "=m" (*lock)
+               : "0" (old), "d" (new), "a" (lock), "m" (*lock)
+               : "cc", "memory" );
+       return old;
+}
+
+#endif /* __GNUC__ */
+
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
@@ -31,34 +52,46 @@ _raw_compare_and_swap(volatile unsigned int *lock,
  * (the type definitions are in asm/spinlock_types.h)
  */
 
-#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_is_locked(x) ((x)->owner_cpu != 0)
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 #define __raw_spin_unlock_wait(lock) \
-       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+       do { while (__raw_spin_is_locked(lock)) \
+                _raw_spin_relax(lock); } while (0)
 
-extern void _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc);
-extern int _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc);
+extern void _raw_spin_lock_wait(raw_spinlock_t *, unsigned int pc);
+extern int _raw_spin_trylock_retry(raw_spinlock_t *, unsigned int pc);
+extern void _raw_spin_relax(raw_spinlock_t *lock);
 
 static inline void __raw_spin_lock(raw_spinlock_t *lp)
 {
        unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
-
-       if (unlikely(_raw_compare_and_swap(&lp->lock, 0, pc) != 0))
-               _raw_spin_lock_wait(lp, pc);
+       int old;
+
+       old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
+       if (likely(old == 0)) {
+               lp->owner_pc = pc;
+               return;
+       }
+       _raw_spin_lock_wait(lp, pc);
 }
 
 static inline int __raw_spin_trylock(raw_spinlock_t *lp)
 {
        unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
+       int old;
 
-       if (likely(_raw_compare_and_swap(&lp->lock, 0, pc) == 0))
+       old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
+       if (likely(old == 0)) {
+               lp->owner_pc = pc;
                return 1;
+       }
        return _raw_spin_trylock_retry(lp, pc);
 }
 
 static inline void __raw_spin_unlock(raw_spinlock_t *lp)
 {
-       _raw_compare_and_swap(&lp->lock, lp->lock, 0);
+       lp->owner_pc = 0;
+       _raw_compare_and_swap(&lp->owner_cpu, lp->owner_cpu, 0);
 }
                
 /*
@@ -135,4 +168,7 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
        return _raw_write_trylock_retry(rw);
 }
 
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SPINLOCK_H */
index f79a2216204f523bac490f3d0009dd01a33b307f..b7ac13f7aa373e0c2c21412579d9e0f5f3215103 100644 (file)
@@ -6,16 +6,16 @@
 #endif
 
 typedef struct {
-       volatile unsigned int lock;
+       volatile unsigned int owner_cpu;
+       volatile unsigned int owner_pc;
 } __attribute__ ((aligned (4))) raw_spinlock_t;
 
 #define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
 
 typedef struct {
        volatile unsigned int lock;
-       volatile unsigned int owner_pc;
 } raw_rwlock_t;
 
-#define __RAW_RW_LOCK_UNLOCKED         { 0, 0 }
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
 
 #endif
index 23a4c390489f0fd448ae8dc5f42b6cdeeebe9e02..d074673a6d9b500010e3c7f4ad25cfbaea5b2d68 100644 (file)
@@ -60,12 +60,13 @@ static inline void *memchr(const void * s, int c, size_t n)
        register int r0 asm("0") = (char) c;
        const void *ret = s + n;
 
-       asm volatile ("0: srst  %0,%1\n"
-                     "   jo    0b\n"
-                     "   jl    1f\n"
-                     "   la    %0,0\n"
-                     "1:"
-                     : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
+       asm volatile(
+               "0:     srst    %0,%1\n"
+               "       jo      0b\n"
+               "       jl      1f\n"
+               "       la      %0,0\n"
+               "1:"
+               : "+a" (ret), "+&a" (s) : "d" (r0) : "cc");
        return (void *) ret;
 }
 
@@ -74,9 +75,10 @@ static inline void *memscan(void *s, int c, size_t n)
        register int r0 asm("0") = (char) c;
        const void *ret = s + n;
 
-       asm volatile ("0: srst  %0,%1\n"
-                     "   jo    0b\n"
-                     : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
+       asm volatile(
+               "0:     srst    %0,%1\n"
+               "       jo      0b\n"
+               : "+a" (ret), "+&a" (s) : "d" (r0) : "cc");
        return (void *) ret;
 }
 
@@ -86,12 +88,13 @@ static inline char *strcat(char *dst, const char *src)
        unsigned long dummy;
        char *ret = dst;
 
-       asm volatile ("0: srst  %0,%1\n"
-                     "   jo    0b\n"
-                     "1: mvst  %0,%2\n"
-                     "   jo    1b"
-                     : "=&a" (dummy), "+a" (dst), "+a" (src)
-                     : "d" (r0), "0" (0) : "cc", "memory" );
+       asm volatile(
+               "0:     srst    %0,%1\n"
+               "       jo      0b\n"
+               "1:     mvst    %0,%2\n"
+               "       jo      1b"
+               : "=&a" (dummy), "+a" (dst), "+a" (src)
+               : "d" (r0), "0" (0) : "cc", "memory" );
        return ret;
 }
 
@@ -100,10 +103,11 @@ static inline char *strcpy(char *dst, const char *src)
        register int r0 asm("0") = 0;
        char *ret = dst;
 
-       asm volatile ("0: mvst  %0,%1\n"
-                     "   jo    0b"
-                     : "+&a" (dst), "+&a" (src) : "d" (r0)
-                     : "cc", "memory" );
+       asm volatile(
+               "0:     mvst    %0,%1\n"
+               "       jo      0b"
+               : "+&a" (dst), "+&a" (src) : "d" (r0)
+               : "cc", "memory");
        return ret;
 }
 
@@ -112,9 +116,10 @@ static inline size_t strlen(const char *s)
        register unsigned long r0 asm("0") = 0;
        const char *tmp = s;
 
-       asm volatile ("0: srst  %0,%1\n"
-                     "   jo    0b"
-                     : "+d" (r0), "+a" (tmp) :  : "cc" );
+       asm volatile(
+               "0:     srst    %0,%1\n"
+               "       jo      0b"
+               : "+d" (r0), "+a" (tmp) :  : "cc");
        return r0 - (unsigned long) s;
 }
 
@@ -124,9 +129,10 @@ static inline size_t strnlen(const char * s, size_t n)
        const char *tmp = s;
        const char *end = s + n;
 
-       asm volatile ("0: srst  %0,%1\n"
-                     "   jo    0b"
-                     : "+a" (end), "+a" (tmp) : "d" (r0)  : "cc" );
+       asm volatile(
+               "0:     srst    %0,%1\n"
+               "       jo      0b"
+               : "+a" (end), "+a" (tmp) : "d" (r0)  : "cc");
        return end - s;
 }
 
index 16040048cd1b3498ba48761adb7daa11cddb6d76..ccbafe4bf2cbf229614d053a29d66212f78cb558 100644 (file)
@@ -23,74 +23,68 @@ struct task_struct;
 
 extern struct task_struct *__switch_to(void *, void *);
 
-#ifdef __s390x__
-#define __FLAG_SHIFT 56
-#else /* ! __s390x__ */
-#define __FLAG_SHIFT 24
-#endif /* ! __s390x__ */
-
 static inline void save_fp_regs(s390_fp_regs *fpregs)
 {
-       asm volatile (
-               "   std   0,8(%1)\n"
-               "   std   2,24(%1)\n"
-               "   std   4,40(%1)\n"
-               "   std   6,56(%1)"
-               : "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory" );
+       asm volatile(
+               "       std     0,8(%1)\n"
+               "       std     2,24(%1)\n"
+               "       std     4,40(%1)\n"
+               "       std     6,56(%1)"
+               : "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory");
        if (!MACHINE_HAS_IEEE)
                return;
        asm volatile(
-               "   stfpc 0(%1)\n"
-               "   std   1,16(%1)\n"
-               "   std   3,32(%1)\n"
-               "   std   5,48(%1)\n"
-               "   std   7,64(%1)\n"
-               "   std   8,72(%1)\n"
-               "   std   9,80(%1)\n"
-               "   std   10,88(%1)\n"
-               "   std   11,96(%1)\n"
-               "   std   12,104(%1)\n"
-               "   std   13,112(%1)\n"
-               "   std   14,120(%1)\n"
-               "   std   15,128(%1)\n"
-               : "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory" );
+               "       stfpc   0(%1)\n"
+               "       std     1,16(%1)\n"
+               "       std     3,32(%1)\n"
+               "       std     5,48(%1)\n"
+               "       std     7,64(%1)\n"
+               "       std     8,72(%1)\n"
+               "       std     9,80(%1)\n"
+               "       std     10,88(%1)\n"
+               "       std     11,96(%1)\n"
+               "       std     12,104(%1)\n"
+               "       std     13,112(%1)\n"
+               "       std     14,120(%1)\n"
+               "       std     15,128(%1)\n"
+               : "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory");
 }
 
 static inline void restore_fp_regs(s390_fp_regs *fpregs)
 {
-       asm volatile (
-               "   ld    0,8(%0)\n"
-               "   ld    2,24(%0)\n"
-               "   ld    4,40(%0)\n"
-               "   ld    6,56(%0)"
-               : : "a" (fpregs), "m" (*fpregs) );
+       asm volatile(
+               "       ld      0,8(%0)\n"
+               "       ld      2,24(%0)\n"
+               "       ld      4,40(%0)\n"
+               "       ld      6,56(%0)"
+               : : "a" (fpregs), "m" (*fpregs));
        if (!MACHINE_HAS_IEEE)
                return;
        asm volatile(
-               "   lfpc  0(%0)\n"
-               "   ld    1,16(%0)\n"
-               "   ld    3,32(%0)\n"
-               "   ld    5,48(%0)\n"
-               "   ld    7,64(%0)\n"
-               "   ld    8,72(%0)\n"
-               "   ld    9,80(%0)\n"
-               "   ld    10,88(%0)\n"
-               "   ld    11,96(%0)\n"
-               "   ld    12,104(%0)\n"
-               "   ld    13,112(%0)\n"
-               "   ld    14,120(%0)\n"
-               "   ld    15,128(%0)\n"
-               : : "a" (fpregs), "m" (*fpregs) );
+               "       lfpc    0(%0)\n"
+               "       ld      1,16(%0)\n"
+               "       ld      3,32(%0)\n"
+               "       ld      5,48(%0)\n"
+               "       ld      7,64(%0)\n"
+               "       ld      8,72(%0)\n"
+               "       ld      9,80(%0)\n"
+               "       ld      10,88(%0)\n"
+               "       ld      11,96(%0)\n"
+               "       ld      12,104(%0)\n"
+               "       ld      13,112(%0)\n"
+               "       ld      14,120(%0)\n"
+               "       ld      15,128(%0)\n"
+               : : "a" (fpregs), "m" (*fpregs));
 }
 
 static inline void save_access_regs(unsigned int *acrs)
 {
-       asm volatile ("stam 0,15,0(%0)" : : "a" (acrs) : "memory" );
+       asm volatile("stam 0,15,0(%0)" : : "a" (acrs) : "memory");
 }
 
 static inline void restore_access_regs(unsigned int *acrs)
 {
-       asm volatile ("lam 0,15,0(%0)" : : "a" (acrs) );
+       asm volatile("lam 0,15,0(%0)" : : "a" (acrs));
 }
 
 #define switch_to(prev,next,last) do {                                      \
@@ -126,7 +120,7 @@ extern void account_system_vtime(struct task_struct *);
        account_vtime(prev);                                                 \
 } while (0)
 
-#define nop() __asm__ __volatile__ ("nop")
+#define nop() asm volatile("nop")
 
 #define xchg(ptr,x)                                                      \
 ({                                                                       \
@@ -147,15 +141,15 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
                shift = (3 ^ (addr & 3)) << 3;
                addr ^= addr & 3;
                asm volatile(
-                       "    l   %0,0(%4)\n"
-                       "0:  lr  0,%0\n"
-                       "    nr  0,%3\n"
-                       "    or  0,%2\n"
-                       "    cs  %0,0,0(%4)\n"
-                       "    jl  0b\n"
+                       "       l       %0,0(%4)\n"
+                       "0:     lr      0,%0\n"
+                       "       nr      0,%3\n"
+                       "       or      0,%2\n"
+                       "       cs      %0,0,0(%4)\n"
+                       "       jl      0b\n"
                        : "=&d" (old), "=m" (*(int *) addr)
                        : "d" (x << shift), "d" (~(255 << shift)), "a" (addr),
-                         "m" (*(int *) addr) : "memory", "cc", "0" );
+                         "m" (*(int *) addr) : "memory", "cc", "0");
                x = old >> shift;
                break;
        case 2:
@@ -163,36 +157,36 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
                shift = (2 ^ (addr & 2)) << 3;
                addr ^= addr & 2;
                asm volatile(
-                       "    l   %0,0(%4)\n"
-                       "0:  lr  0,%0\n"
-                       "    nr  0,%3\n"
-                       "    or  0,%2\n"
-                       "    cs  %0,0,0(%4)\n"
-                       "    jl  0b\n"
+                       "       l       %0,0(%4)\n"
+                       "0:     lr      0,%0\n"
+                       "       nr      0,%3\n"
+                       "       or      0,%2\n"
+                       "       cs      %0,0,0(%4)\n"
+                       "       jl      0b\n"
                        : "=&d" (old), "=m" (*(int *) addr)
                        : "d" (x << shift), "d" (~(65535 << shift)), "a" (addr),
-                         "m" (*(int *) addr) : "memory", "cc", "0" );
+                         "m" (*(int *) addr) : "memory", "cc", "0");
                x = old >> shift;
                break;
        case 4:
-               asm volatile (
-                       "    l   %0,0(%3)\n"
-                       "0:  cs  %0,%2,0(%3)\n"
-                       "    jl  0b\n"
+               asm volatile(
+                       "       l       %0,0(%3)\n"
+                       "0:     cs      %0,%2,0(%3)\n"
+                       "       jl      0b\n"
                        : "=&d" (old), "=m" (*(int *) ptr)
                        : "d" (x), "a" (ptr), "m" (*(int *) ptr)
-                       : "memory", "cc" );
+                       : "memory", "cc");
                x = old;
                break;
 #ifdef __s390x__
        case 8:
-               asm volatile (
-                       "    lg  %0,0(%3)\n"
-                       "0:  csg %0,%2,0(%3)\n"
-                       "    jl  0b\n"
+               asm volatile(
+                       "       lg      %0,0(%3)\n"
+                       "0:     csg     %0,%2,0(%3)\n"
+                       "       jl      0b\n"
                        : "=&d" (old), "=m" (*(long *) ptr)
                        : "d" (x), "a" (ptr), "m" (*(long *) ptr)
-                       : "memory", "cc" );
+                       : "memory", "cc");
                x = old;
                break;
 #endif /* __s390x__ */
@@ -224,55 +218,55 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
                shift = (3 ^ (addr & 3)) << 3;
                addr ^= addr & 3;
                asm volatile(
-                       "    l   %0,0(%4)\n"
-                       "0:  nr  %0,%5\n"
-                        "    lr  %1,%0\n"
-                       "    or  %0,%2\n"
-                       "    or  %1,%3\n"
-                       "    cs  %0,%1,0(%4)\n"
-                       "    jnl 1f\n"
-                       "    xr  %1,%0\n"
-                       "    nr  %1,%5\n"
-                       "    jnz 0b\n"
+                       "       l       %0,0(%4)\n"
+                       "0:     nr      %0,%5\n"
+                       "       lr      %1,%0\n"
+                       "       or      %0,%2\n"
+                       "       or      %1,%3\n"
+                       "       cs      %0,%1,0(%4)\n"
+                       "       jnl     1f\n"
+                       "       xr      %1,%0\n"
+                       "       nr      %1,%5\n"
+                       "       jnz     0b\n"
                        "1:"
                        : "=&d" (prev), "=&d" (tmp)
                        : "d" (old << shift), "d" (new << shift), "a" (ptr),
                          "d" (~(255 << shift))
-                       : "memory", "cc" );
+                       : "memory", "cc");
                return prev >> shift;
        case 2:
                addr = (unsigned long) ptr;
                shift = (2 ^ (addr & 2)) << 3;
                addr ^= addr & 2;
                asm volatile(
-                       "    l   %0,0(%4)\n"
-                       "0:  nr  %0,%5\n"
-                        "    lr  %1,%0\n"
-                       "    or  %0,%2\n"
-                       "    or  %1,%3\n"
-                       "    cs  %0,%1,0(%4)\n"
-                       "    jnl 1f\n"
-                       "    xr  %1,%0\n"
-                       "    nr  %1,%5\n"
-                       "    jnz 0b\n"
+                       "       l       %0,0(%4)\n"
+                       "0:     nr      %0,%5\n"
+                       "       lr      %1,%0\n"
+                       "       or      %0,%2\n"
+                       "       or      %1,%3\n"
+                       "       cs      %0,%1,0(%4)\n"
+                       "       jnl     1f\n"
+                       "       xr      %1,%0\n"
+                       "       nr      %1,%5\n"
+                       "       jnz     0b\n"
                        "1:"
                        : "=&d" (prev), "=&d" (tmp)
                        : "d" (old << shift), "d" (new << shift), "a" (ptr),
                          "d" (~(65535 << shift))
-                       : "memory", "cc" );
+                       : "memory", "cc");
                return prev >> shift;
        case 4:
-               asm volatile (
-                       "    cs  %0,%2,0(%3)\n"
+               asm volatile(
+                       "       cs      %0,%2,0(%3)\n"
                        : "=&d" (prev) : "0" (old), "d" (new), "a" (ptr)
-                       : "memory", "cc" );
+                       : "memory", "cc");
                return prev;
 #ifdef __s390x__
        case 8:
-               asm volatile (
-                       "    csg %0,%2,0(%3)\n"
+               asm volatile(
+                       "       csg     %0,%2,0(%3)\n"
                        : "=&d" (prev) : "0" (old), "d" (new), "a" (ptr)
-                       : "memory", "cc" );
+                       : "memory", "cc");
                return prev;
 #endif /* __s390x__ */
         }
@@ -289,8 +283,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
  * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
  */
 
-#define eieio()  __asm__ __volatile__ ( "bcr 15,0" : : : "memory" ) 
-# define SYNC_OTHER_CORES(x)   eieio() 
+#define eieio()        asm volatile("bcr 15,0" : : : "memory")
+#define SYNC_OTHER_CORES(x)   eieio()
 #define mb()    eieio()
 #define rmb()   eieio()
 #define wmb()   eieio()
@@ -307,117 +301,56 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 
 #ifdef __s390x__
 
-#define __ctl_load(array, low, high) ({ \
-       typedef struct { char _[sizeof(array)]; } addrtype; \
-       __asm__ __volatile__ ( \
-               "   bras  1,0f\n" \
-                "   lctlg 0,0,0(%0)\n" \
-               "0: ex    %1,0(1)" \
-               : : "a" (&array), "a" (((low)<<4)+(high)), \
-                   "m" (*(addrtype *)(array)) : "1" ); \
+#define __ctl_load(array, low, high) ({                                \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       lctlg   %1,%2,0(%0)\n"                  \
+               : : "a" (&array), "i" (low), "i" (high),        \
+                   "m" (*(addrtype *)(array)));                \
        })
 
-#define __ctl_store(array, low, high) ({ \
-       typedef struct { char _[sizeof(array)]; } addrtype; \
-       __asm__ __volatile__ ( \
-               "   bras  1,0f\n" \
-               "   stctg 0,0,0(%1)\n" \
-               "0: ex    %2,0(1)" \
-               : "=m" (*(addrtype *)(array)) \
-               : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+#define __ctl_store(array, low, high) ({                       \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       stctg   %2,%3,0(%1)\n"                  \
+               : "=m" (*(addrtype *)(array))                   \
+               : "a" (&array), "i" (low), "i" (high));         \
        })
 
-#define __ctl_set_bit(cr, bit) ({ \
-        __u8 __dummy[24]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctg 0,0,0(%1)\n" \
-                "    lctlg 0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    lg    0,0(%1)\n" \
-                "    ogr   0,%3\n"       /* set the bit */ \
-                "    stg   0,0(%1)\n" \
-                "1:  ex    %2,6(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-               : "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-                 "a" (cr*17), "a" (1L<<(bit)) \
-                : "cc", "0", "1" ); \
-        })
-
-#define __ctl_clear_bit(cr, bit) ({ \
-        __u8 __dummy[16]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctg 0,0,0(%1)\n" \
-                "    lctlg 0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    lg    0,0(%1)\n" \
-                "    ngr   0,%3\n"       /* set the bit */ \
-                "    stg   0,0(%1)\n" \
-                "1:  ex    %2,6(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-               : "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-                 "a" (cr*17), "a" (~(1L<<(bit))) \
-                : "cc", "0", "1" ); \
-        })
-
 #else /* __s390x__ */
 
-#define __ctl_load(array, low, high) ({ \
-       typedef struct { char _[sizeof(array)]; } addrtype; \
-       __asm__ __volatile__ ( \
-               "   bras  1,0f\n" \
-                "   lctl 0,0,0(%0)\n" \
-               "0: ex    %1,0(1)" \
-               : : "a" (&array), "a" (((low)<<4)+(high)), \
-                   "m" (*(addrtype *)(array)) : "1" ); \
-       })
+#define __ctl_load(array, low, high) ({                                \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       lctl    %1,%2,0(%0)\n"                  \
+               : : "a" (&array), "i" (low), "i" (high),        \
+                   "m" (*(addrtype *)(array)));                \
+})
 
-#define __ctl_store(array, low, high) ({ \
-       typedef struct { char _[sizeof(array)]; } addrtype; \
-       __asm__ __volatile__ ( \
-               "   bras  1,0f\n" \
-               "   stctl 0,0,0(%1)\n" \
-               "0: ex    %2,0(1)" \
-               : "=m" (*(addrtype *)(array)) \
-               : "a" (&array), "a" (((low)<<4)+(high)): "1" ); \
+#define __ctl_store(array, low, high) ({                       \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       stctl   %2,%3,0(%1)\n"                  \
+               : "=m" (*(addrtype *)(array))                   \
+               : "a" (&array), "i" (low), "i" (high));         \
        })
 
-#define __ctl_set_bit(cr, bit) ({ \
-        __u8 __dummy[16]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctl 0,0,0(%1)\n" \
-                "    lctl  0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    l     0,0(%1)\n" \
-                "    or    0,%3\n"       /* set the bit */ \
-                "    st    0,0(%1)\n" \
-                "1:  ex    %2,4(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-               : "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-                 "a" (cr*17), "a" (1<<(bit)) \
-                : "cc", "0", "1" ); \
-        })
-
-#define __ctl_clear_bit(cr, bit) ({ \
-        __u8 __dummy[16]; \
-        __asm__ __volatile__ ( \
-                "    bras  1,0f\n"       /* skip indirect insns */ \
-                "    stctl 0,0,0(%1)\n" \
-                "    lctl  0,0,0(%1)\n" \
-                "0:  ex    %2,0(1)\n"    /* execute stctl */ \
-                "    l     0,0(%1)\n" \
-                "    nr    0,%3\n"       /* set the bit */ \
-                "    st    0,0(%1)\n" \
-                "1:  ex    %2,4(1)"      /* execute lctl */ \
-                : "=m" (__dummy) \
-               : "a" ((((unsigned long) &__dummy) + 7) & ~7UL), \
-                 "a" (cr*17), "a" (~(1<<(bit))) \
-                : "cc", "0", "1" ); \
-        })
 #endif /* __s390x__ */
 
+#define __ctl_set_bit(cr, bit) ({      \
+       unsigned long __dummy;          \
+       __ctl_store(__dummy, cr, cr);   \
+       __dummy |= 1UL << (bit);        \
+       __ctl_load(__dummy, cr, cr);    \
+})
+
+#define __ctl_clear_bit(cr, bit) ({    \
+       unsigned long __dummy;          \
+       __ctl_store(__dummy, cr, cr);   \
+       __dummy &= ~(1UL << (bit));     \
+       __ctl_load(__dummy, cr, cr);    \
+})
+
 #include <linux/irqflags.h>
 
 /*
@@ -427,8 +360,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 static inline void
 __set_psw_mask(unsigned long mask)
 {
-       local_save_flags(mask);
-       __load_psw_mask(mask);
+       __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
 }
 
 #define local_mcck_enable()  __set_psw_mask(PSW_KERNEL_BITS)
index 5d0332a4c2bdd0b8d737aea0f8fd5d4fa96e546b..4df4a41029a32d22bb5c5ce618c8743637f2db77 100644 (file)
 
 typedef unsigned long long cycles_t;
 
-static inline cycles_t get_cycles(void)
-{
-       cycles_t cycles;
-
-       __asm__ __volatile__ ("stck 0(%1)" : "=m" (cycles) : "a" (&cycles) : "cc");
-       return cycles >> 2;
-}
-
 static inline unsigned long long get_clock (void)
 {
        unsigned long long clk;
 
-       __asm__ __volatile__ ("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+       asm volatile("stck %0" : "=Q" (clk) : : "cc");
+#else /* __GNUC__ */
+       asm volatile("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
+#endif /* __GNUC__ */
        return clk;
 }
 
+static inline cycles_t get_cycles(void)
+{
+       return (cycles_t) get_clock() >> 2;
+}
+
 #endif
index 73cd85bebfb2ade78de40e577452ff86054bbb14..fa4dc916a9bfe5de40fd2bb5f1bc31dd8015dadb 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #define local_flush_tlb() \
-do {  __asm__ __volatile__("ptlb": : :"memory"); } while (0)
+do {  asm volatile("ptlb": : :"memory"); } while (0)
 
 #ifndef CONFIG_SMP
 
@@ -68,24 +68,24 @@ extern void smp_ptlb_all(void);
 
 static inline void global_flush_tlb(void)
 {
+       register unsigned long reg2 asm("2");
+       register unsigned long reg3 asm("3");
+       register unsigned long reg4 asm("4");
+       long dummy;
+
 #ifndef __s390x__
        if (!MACHINE_HAS_CSP) {
                smp_ptlb_all();
                return;
        }
 #endif /* __s390x__ */
-       {
-               register unsigned long addr asm("4");
-               long dummy;
-
-               dummy = 0;
-               addr = ((unsigned long) &dummy) + 1;
-               __asm__ __volatile__ (
-                       "    slr  2,2\n"
-                       "    slr  3,3\n"
-                       "    csp  2,%0"
-                       : : "a" (addr), "m" (dummy) : "cc", "2", "3" );
-       }
+
+       dummy = 0;
+       reg2 = reg3 = 0;
+       reg4 = ((unsigned long) &dummy) + 1;
+       asm volatile(
+               "       csp     %0,%2"
+               : : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
 }
 
 /*
@@ -102,9 +102,9 @@ static inline void __flush_tlb_mm(struct mm_struct * mm)
        if (unlikely(cpus_empty(mm->cpu_vm_mask)))
                return;
        if (MACHINE_HAS_IDTE) {
-               asm volatile (".insn rrf,0xb98e0000,0,%0,%1,0"
-                             : : "a" (2048),
-                             "a" (__pa(mm->pgd)&PAGE_MASK) : "cc" );
+               asm volatile(
+                       "       .insn   rrf,0xb98e0000,0,%0,%1,0"
+                       : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc");
                return;
        }
        preempt_disable();
index e2047b0c90921a1898c1b6a94dadede886d25ec3..72ae4efddb49017af8c3a2ca7d619c531506a158 100644 (file)
 #define get_ds()        (KERNEL_DS)
 #define get_fs()        (current->thread.mm_segment)
 
-#ifdef __s390x__
 #define set_fs(x) \
 ({                                                                     \
        unsigned long __pto;                                            \
        current->thread.mm_segment = (x);                               \
        __pto = current->thread.mm_segment.ar4 ?                        \
                S390_lowcore.user_asce : S390_lowcore.kernel_asce;      \
-       asm volatile ("lctlg 7,7,%0" : : "m" (__pto) );                 \
+       __ctl_load(__pto, 7, 7);                                        \
 })
-#else /* __s390x__ */
-#define set_fs(x) \
-({                                                                     \
-       unsigned long __pto;                                            \
-       current->thread.mm_segment = (x);                               \
-       __pto = current->thread.mm_segment.ar4 ?                        \
-               S390_lowcore.user_asce : S390_lowcore.kernel_asce;      \
-       asm volatile ("lctl  7,7,%0" : : "m" (__pto) );                 \
-})
-#endif /* __s390x__ */
 
 #define segment_eq(a,b) ((a).ar4 == (b).ar4)
 
index 02b942d85c377369abea006db9d932bef89b1cce..0361ac5dcde38333183b8e1e89676b61d28c37bf 100644 (file)
 
 #ifdef __KERNEL__
 
+#include <linux/err.h>
+
 #define __syscall_return(type, res)                         \
 do {                                                        \
-       if ((unsigned long)(res) >= (unsigned long)(-4095)) {\
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
                errno = -(res);                              \
                res = -1;                                    \
        }                                                    \
@@ -353,145 +355,145 @@ do {                                                         \
 
 #define _svc_clobber "1", "cc", "memory"
 
-#define _syscall0(type,name)                                \
-type name(void) {                                           \
-       register long __svcres asm("2");                     \
-       long __res;                                          \
-       __asm__ __volatile__ (                               \
-               "    .if %1 < 256\n"                         \
-               "    svc %b1\n"                              \
-               "    .else\n"                                \
-               "    la  %%r1,%1\n"                          \
-               "    svc 0\n"                                \
-               "    .endif"                                 \
-               : "=d" (__svcres)                            \
-               : "i" (__NR_##name)                          \
-               : _svc_clobber );                            \
-       __res = __svcres;                                    \
-       __syscall_return(type,__res);                        \
+#define _syscall0(type,name)                                   \
+type name(void) {                                              \
+       register long __svcres asm("2");                        \
+       long __res;                                             \
+       asm volatile(                                           \
+               "       .if     %1 < 256\n"                     \
+               "       svc     %b1\n"                          \
+               "       .else\n"                                \
+               "       la      %%r1,%1\n"                      \
+               "       svc     0\n"                            \
+               "       .endif"                                 \
+               : "=d" (__svcres)                               \
+               : "i" (__NR_##name)                             \
+               : _svc_clobber);                                \
+       __res = __svcres;                                       \
+       __syscall_return(type,__res);                           \
 }
 
-#define _syscall1(type,name,type1,arg1)                             \
-type name(type1 arg1) {                                             \
-       register type1 __arg1 asm("2") = arg1;               \
-       register long __svcres asm("2");                     \
-       long __res;                                          \
-       __asm__ __volatile__ (                               \
-               "    .if %1 < 256\n"                         \
-               "    svc %b1\n"                              \
-               "    .else\n"                                \
-               "    la  %%r1,%1\n"                          \
-               "    svc 0\n"                                \
-               "    .endif"                                 \
-               : "=d" (__svcres)                            \
-               : "i" (__NR_##name),                         \
-                 "0" (__arg1)                               \
-               : _svc_clobber );                            \
-       __res = __svcres;                                    \
-       __syscall_return(type,__res);                        \
+#define _syscall1(type,name,type1,arg1)                                \
+type name(type1 arg1) {                                                \
+       register type1 __arg1 asm("2") = arg1;                  \
+       register long __svcres asm("2");                        \
+       long __res;                                             \
+       asm volatile(                                           \
+               "       .if     %1 < 256\n"                     \
+               "       svc     %b1\n"                          \
+               "       .else\n"                                \
+               "       la      %%r1,%1\n"                      \
+               "       svc     0\n"                            \
+               "       .endif"                                 \
+               : "=d" (__svcres)                               \
+               : "i" (__NR_##name),                            \
+                 "0" (__arg1)                                  \
+               : _svc_clobber);                                \
+       __res = __svcres;                                       \
+       __syscall_return(type,__res);                           \
 }
 
-#define _syscall2(type,name,type1,arg1,type2,arg2)          \
-type name(type1 arg1, type2 arg2) {                         \
-       register type1 __arg1 asm("2") = arg1;               \
-       register type2 __arg2 asm("3") = arg2;               \
-       register long __svcres asm("2");                     \
-       long __res;                                          \
-       __asm__ __volatile__ (                               \
-               "    .if %1 < 256\n"                         \
-               "    svc %b1\n"                              \
-               "    .else\n"                                \
-               "    la %%r1,%1\n"                           \
-               "    svc 0\n"                                \
-               "    .endif"                                 \
-               : "=d" (__svcres)                            \
-               : "i" (__NR_##name),                         \
-                 "0" (__arg1),                              \
-                 "d" (__arg2)                               \
-               : _svc_clobber );                            \
-       __res = __svcres;                                    \
-       __syscall_return(type,__res);                        \
+#define _syscall2(type,name,type1,arg1,type2,arg2)             \
+type name(type1 arg1, type2 arg2) {                            \
+       register type1 __arg1 asm("2") = arg1;                  \
+       register type2 __arg2 asm("3") = arg2;                  \
+       register long __svcres asm("2");                        \
+       long __res;                                             \
+       asm volatile(                                           \
+               "       .if     %1 < 256\n"                     \
+               "       svc     %b1\n"                          \
+               "       .else\n"                                \
+               "       la      %%r1,%1\n"                      \
+               "       svc     0\n"                            \
+               "       .endif"                                 \
+               : "=d" (__svcres)                               \
+               : "i" (__NR_##name),                            \
+                 "0" (__arg1),                                 \
+                 "d" (__arg2)                                  \
+               : _svc_clobber );                               \
+       __res = __svcres;                                       \
+       __syscall_return(type,__res);                           \
 }
 
-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)\
-type name(type1 arg1, type2 arg2, type3 arg3) {                     \
-       register type1 __arg1 asm("2") = arg1;               \
-       register type2 __arg2 asm("3") = arg2;               \
-       register type3 __arg3 asm("4") = arg3;               \
-       register long __svcres asm("2");                     \
-       long __res;                                          \
-       __asm__ __volatile__ (                               \
-               "    .if %1 < 256\n"                         \
-               "    svc %b1\n"                              \
-               "    .else\n"                                \
-               "    la  %%r1,%1\n"                          \
-               "    svc 0\n"                                \
-               "    .endif"                                 \
-               : "=d" (__svcres)                            \
-               : "i" (__NR_##name),                         \
-                 "0" (__arg1),                              \
-                 "d" (__arg2),                              \
-                 "d" (__arg3)                               \
-               : _svc_clobber );                            \
-       __res = __svcres;                                    \
-       __syscall_return(type,__res);                        \
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)  \
+type name(type1 arg1, type2 arg2, type3 arg3) {                        \
+       register type1 __arg1 asm("2") = arg1;                  \
+       register type2 __arg2 asm("3") = arg2;                  \
+       register type3 __arg3 asm("4") = arg3;                  \
+       register long __svcres asm("2");                        \
+       long __res;                                             \
+       asm volatile(                                           \
+               "       .if     %1 < 256\n"                     \
+               "       svc     %b1\n"                          \
+               "       .else\n"                                \
+               "       la      %%r1,%1\n"                      \
+               "       svc     0\n"                            \
+               "       .endif"                                 \
+               : "=d" (__svcres)                               \
+               : "i" (__NR_##name),                            \
+                 "0" (__arg1),                                 \
+                 "d" (__arg2),                                 \
+                 "d" (__arg3)                                  \
+               : _svc_clobber);                                \
+       __res = __svcres;                                       \
+       __syscall_return(type,__res);                           \
 }
 
-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,\
-                 type4,name4)                               \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {  \
-       register type1 __arg1 asm("2") = arg1;               \
-       register type2 __arg2 asm("3") = arg2;               \
-       register type3 __arg3 asm("4") = arg3;               \
-       register type4 __arg4 asm("5") = arg4;               \
-       register long __svcres asm("2");                     \
-       long __res;                                          \
-       __asm__ __volatile__ (                               \
-               "    .if %1 < 256\n"                         \
-               "    svc %b1\n"                              \
-               "    .else\n"                                \
-               "    la  %%r1,%1\n"                          \
-               "    svc 0\n"                                \
-               "    .endif"                                 \
-               : "=d" (__svcres)                            \
-               : "i" (__NR_##name),                         \
-                 "0" (__arg1),                              \
-                 "d" (__arg2),                              \
-                 "d" (__arg3),                              \
-                 "d" (__arg4)                               \
-               : _svc_clobber );                            \
-       __res = __svcres;                                    \
-       __syscall_return(type,__res);                        \
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,  \
+                 type4,name4)                                  \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {    \
+       register type1 __arg1 asm("2") = arg1;                  \
+       register type2 __arg2 asm("3") = arg2;                  \
+       register type3 __arg3 asm("4") = arg3;                  \
+       register type4 __arg4 asm("5") = arg4;                  \
+       register long __svcres asm("2");                        \
+       long __res;                                             \
+       asm volatile(                                           \
+               "       .if     %1 < 256\n"                     \
+               "       svc     %b1\n"                          \
+               "       .else\n"                                \
+               "       la      %%r1,%1\n"                      \
+               "       svc     0\n"                            \
+               "       .endif"                                 \
+               : "=d" (__svcres)                               \
+               : "i" (__NR_##name),                            \
+                 "0" (__arg1),                                 \
+                 "d" (__arg2),                                 \
+                 "d" (__arg3),                                 \
+                 "d" (__arg4)                                  \
+               : _svc_clobber);                                \
+       __res = __svcres;                                       \
+       __syscall_return(type,__res);                           \
 }
 
-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,\
-                 type4,name4,type5,name5)                   \
-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
-         type5 arg5) {                                      \
-       register type1 __arg1 asm("2") = arg1;               \
-       register type2 __arg2 asm("3") = arg2;               \
-       register type3 __arg3 asm("4") = arg3;               \
-       register type4 __arg4 asm("5") = arg4;               \
-       register type5 __arg5 asm("6") = arg5;               \
-       register long __svcres asm("2");                     \
-       long __res;                                          \
-       __asm__ __volatile__ (                               \
-               "    .if %1 < 256\n"                         \
-               "    svc %b1\n"                              \
-               "    .else\n"                                \
-               "    la  %%r1,%1\n"                          \
-               "    svc 0\n"                                \
-               "    .endif"                                 \
-               : "=d" (__svcres)                            \
-               : "i" (__NR_##name),                         \
-                 "0" (__arg1),                              \
-                 "d" (__arg2),                              \
-                 "d" (__arg3),                              \
-                 "d" (__arg4),                              \
-                 "d" (__arg5)                               \
-               : _svc_clobber );                            \
-       __res = __svcres;                                    \
-       __syscall_return(type,__res);                        \
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,  \
+                 type4,name4,type5,name5)                      \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,      \
+         type5 arg5) {                                         \
+       register type1 __arg1 asm("2") = arg1;                  \
+       register type2 __arg2 asm("3") = arg2;                  \
+       register type3 __arg3 asm("4") = arg3;                  \
+       register type4 __arg4 asm("5") = arg4;                  \
+       register type5 __arg5 asm("6") = arg5;                  \
+       register long __svcres asm("2");                        \
+       long __res;                                             \
+       asm volatile(                                           \
+               "       .if     %1 < 256\n"                     \
+               "       svc     %b1\n"                          \
+               "       .else\n"                                \
+               "       la      %%r1,%1\n"                      \
+               "       svc     0\n"                            \
+               "       .endif"                                 \
+               : "=d" (__svcres)                               \
+               : "i" (__NR_##name),                            \
+                 "0" (__arg1),                                 \
+                 "d" (__arg2),                                 \
+                 "d" (__arg3),                                 \
+                 "d" (__arg4),                                 \
+                 "d" (__arg5)                                  \
+               : _svc_clobber);                                \
+       __res = __svcres;                                       \
+       __syscall_return(type,__res);                           \
 }
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
index 720afc11c2caf7c4e95d7943894337ef25ec154d..b860218e402e88622a311a6036424f1ba3e6aa19 100644 (file)
 #include <asm/cpu/addrspace.h>
 
 /* Memory segments (32bit Privileged mode addresses)  */
+#ifndef CONFIG_CPU_SH2A
 #define P0SEG          0x00000000
 #define P1SEG          0x80000000
 #define P2SEG          0xa0000000
 #define P3SEG          0xc0000000
 #define P4SEG          0xe0000000
+#else
+#define P0SEG          0x00000000
+#define P1SEG          0x00000000
+#define P2SEG          0x20000000
+#define P3SEG          0x00000000
+#define P4SEG          0x80000000
+#endif
 
 /* Returns the privileged segment base of a given address  */
 #define PXSEG(a)       (((unsigned long)(a)) & 0xe0000000)
diff --git a/include/asm-sh/adx/io.h b/include/asm-sh/adx/io.h
deleted file mode 100644 (file)
index ab1225f..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * include/asm-sh/io_adx.h
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * This file may be copied or modified under the terms of the GNU
- * General Public License.  See linux/COPYING for more information.
- *
- * IO functions for an A&D ADX Board
- */
-
-#ifndef _ASM_SH_IO_ADX_H
-#define _ASM_SH_IO_ADX_H
-
-#include <asm/io_generic.h>
-
-extern unsigned char adx_inb(unsigned long port);
-extern unsigned short adx_inw(unsigned long port);
-extern unsigned int adx_inl(unsigned long port);
-
-extern void adx_outb(unsigned char value, unsigned long port);
-extern void adx_outw(unsigned short value, unsigned long port);
-extern void adx_outl(unsigned int value, unsigned long port);
-
-extern unsigned char adx_inb_p(unsigned long port);
-extern void adx_outb_p(unsigned char value, unsigned long port);
-
-extern void adx_insb(unsigned long port, void *addr, unsigned long count);
-extern void adx_insw(unsigned long port, void *addr, unsigned long count);
-extern void adx_insl(unsigned long port, void *addr, unsigned long count);
-extern void adx_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void adx_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void adx_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char adx_readb(unsigned long addr);
-extern unsigned short adx_readw(unsigned long addr);
-extern unsigned int adx_readl(unsigned long addr);
-extern void adx_writeb(unsigned char b, unsigned long addr);
-extern void adx_writew(unsigned short b, unsigned long addr);
-extern void adx_writel(unsigned int b, unsigned long addr);
-
-extern void * adx_ioremap(unsigned long offset, unsigned long size);
-extern void adx_iounmap(void *addr);
-
-extern unsigned long adx_isa_port2addr(unsigned long offset);
-
-extern void setup_adx(void);
-extern void init_adx_IRQ(void);
-
-#ifdef __WANT_IO_DEF
-
-#define __inb          adx_inb
-#define __inw          adx_inw
-#define __inl          adx_inl
-#define __outb         adx_outb
-#define __outw         adx_outw
-#define __outl         adx_outl
-
-#define __inb_p                adx_inb_p
-#define __inw_p                adx_inw
-#define __inl_p                adx_inl
-#define __outb_p       adx_outb_p
-#define __outw_p       adx_outw
-#define __outl_p       adx_outl
-
-#define __insb         adx_insb
-#define __insw         adx_insw
-#define __insl         adx_insl
-#define __outsb                adx_outsb
-#define __outsw                adx_outsw
-#define __outsl                adx_outsl
-
-#define __readb                adx_readb
-#define __readw                adx_readw
-#define __readl                adx_readl
-#define __writeb       adx_writeb
-#define __writew       adx_writew
-#define __writel       adx_writel
-
-#define __isa_port2addr        adx_isa_port2addr
-#define __ioremap      adx_ioremap
-#define __iounmap      adx_iounmap
-
-#endif
-
-#endif /* _ASM_SH_IO_AANDD_H */
diff --git a/include/asm-sh/apm.h b/include/asm-sh/apm.h
new file mode 100644 (file)
index 0000000..8b091e9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 (c) Andriy Skulysh <askulysh@gmail.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 __ASM_SH_APM_H
+#define __ASM_SH_APM_H
+
+#define APM_AC_OFFLINE                 0
+#define APM_AC_ONLINE                  1
+#define APM_AC_BACKUP                  2
+#define APM_AC_UNKNOWN                 0xff
+
+#define APM_BATTERY_STATUS_HIGH                0
+#define APM_BATTERY_STATUS_LOW         1
+#define APM_BATTERY_STATUS_CRITICAL    2
+#define APM_BATTERY_STATUS_CHARGING    3
+#define APM_BATTERY_STATUS_NOT_PRESENT 4
+#define APM_BATTERY_STATUS_UNKNOWN     0xff
+
+#define APM_BATTERY_LIFE_UNKNOWN       0xFFFF
+#define APM_BATTERY_LIFE_MINUTES       0x8000
+#define APM_BATTERY_LIFE_VALUE_MASK    0x7FFF
+
+#define APM_BATTERY_FLAG_HIGH          (1 << 0)
+#define APM_BATTERY_FLAG_LOW           (1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL      (1 << 2)
+#define APM_BATTERY_FLAG_CHARGING      (1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT   (1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN       0xff
+
+#define APM_UNITS_MINS                 0
+#define APM_UNITS_SECS                 1
+#define APM_UNITS_UNKNOWN              -1
+
+
+extern int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
+extern int apm_suspended;
+
+void apm_queue_event(apm_event_t event);
+
+#endif
index fb627de217f2e3bd9668e9de53c48139527113d9..8bdc1ba56f736570788c445bf5ef4f4dc1bde5a8 100644 (file)
@@ -14,6 +14,7 @@ typedef struct { volatile int counter; } atomic_t;
 #define atomic_read(v)         ((v)->counter)
 #define atomic_set(v,i)                ((v)->counter = (i))
 
+#include <linux/compiler.h>
 #include <asm/system.h>
 
 /*
@@ -21,49 +22,110 @@ typedef struct { volatile int counter; } atomic_t;
  * forward to code at the end of this object's .text section, then
  * branch back to restart the operation.
  */
-
-static __inline__ void atomic_add(int i, atomic_t * v)
+static inline void atomic_add(int i, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_add    \n"
+"      add     %2, %0                          \n"
+"      movco.l %0, @%3                         \n"
+"      bf      1b                              \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v += i;
        local_irq_restore(flags);
+#endif
 }
 
-static __inline__ void atomic_sub(int i, atomic_t *v)
+static inline void atomic_sub(int i, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_sub    \n"
+"      sub     %2, %0                          \n"
+"      movco.l %0, @%3                         \n"
+"      bf      1b                              \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v -= i;
        local_irq_restore(flags);
+#endif
 }
 
-static __inline__ int atomic_add_return(int i, atomic_t * v)
+/*
+ * SH-4A note:
+ *
+ * We basically get atomic_xxx_return() for free compared with
+ * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
+ * encoding, so the retval is automatically set without having to
+ * do any special work.
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
 {
-       unsigned long temp, flags;
+       unsigned long temp;
+
+#ifdef CONFIG_CPU_SH4A
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_add_return     \n"
+"      add     %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+"      synco                                           \n"
+       : "=&z" (temp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
+       unsigned long flags;
 
        local_irq_save(flags);
        temp = *(long *)v;
        temp += i;
        *(long *)v = temp;
        local_irq_restore(flags);
+#endif
 
        return temp;
 }
 
 #define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
 
-static __inline__ int atomic_sub_return(int i, atomic_t * v)
+static inline int atomic_sub_return(int i, atomic_t *v)
 {
-       unsigned long temp, flags;
+       unsigned long temp;
+
+#ifdef CONFIG_CPU_SH4A
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_sub_return     \n"
+"      sub     %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+"      synco                                           \n"
+       : "=&z" (temp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
+       unsigned long flags;
 
        local_irq_save(flags);
        temp = *(long *)v;
        temp -= i;
        *(long *)v = temp;
        local_irq_restore(flags);
+#endif
 
        return temp;
 }
@@ -118,22 +180,48 @@ static inline int atomic_add_unless(atomic_t *v, int a, int 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)
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_clear_mask     \n"
+"      and     %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (~mask), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v &= ~mask;
        local_irq_restore(flags);
+#endif
 }
 
-static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_set_mask       \n"
+"      or      %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (mask), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v |= mask;
        local_irq_restore(flags);
+#endif
 }
 
 /* Atomic operations are already serializing on SH */
index fc21e4db588142a606e7130d3bc5caaa7c4e9155..1b6916e63e90884fd7b058510903a28379462aba 100644 (file)
@@ -1,4 +1,18 @@
 #ifndef __ASM_SH_AUXVEC_H
 #define __ASM_SH_AUXVEC_H
 
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them.
+ */
+
+#ifdef CONFIG_VSYSCALL
+/*
+ * Only define this in the vsyscall case, the entry point to
+ * the vsyscall page gets placed here. The kernel will attempt
+ * to build a gate VMA we don't care about otherwise..
+ */
+#define AT_SYSINFO_EHDR                33
+#endif
+
 #endif /* __ASM_SH_AUXVEC_H */
index e34f8250856897b7ee4c5f960cf444fd03f21646..1c16792cee1dbaf239948ac8971dd2ad7290865e 100644 (file)
@@ -6,7 +6,7 @@
 /* For __swab32 */
 #include <asm/byteorder.h>
 
-static __inline__ void set_bit(int nr, volatile void * addr)
+static inline void set_bit(int nr, volatile void * addr)
 {
        int     mask;
        volatile unsigned int *a = addr;
@@ -24,7 +24,7 @@ static __inline__ void set_bit(int nr, volatile void * addr)
  */
 #define smp_mb__before_clear_bit()     barrier()
 #define smp_mb__after_clear_bit()      barrier()
-static __inline__ void clear_bit(int nr, volatile void * addr)
+static inline void clear_bit(int nr, volatile void * addr)
 {
        int     mask;
        volatile unsigned int *a = addr;
@@ -37,7 +37,7 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
        local_irq_restore(flags);
 }
 
-static __inline__ void change_bit(int nr, volatile void * addr)
+static inline void change_bit(int nr, volatile void * addr)
 {
        int     mask;
        volatile unsigned int *a = addr;
@@ -50,7 +50,7 @@ static __inline__ void change_bit(int nr, volatile void * addr)
        local_irq_restore(flags);
 }
 
-static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+static inline int test_and_set_bit(int nr, volatile void * addr)
 {
        int     mask, retval;
        volatile unsigned int *a = addr;
@@ -66,7 +66,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
        return retval;
 }
 
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+static inline int test_and_clear_bit(int nr, volatile void * addr)
 {
        int     mask, retval;
        volatile unsigned int *a = addr;
@@ -82,7 +82,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
        return retval;
 }
 
-static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+static inline int test_and_change_bit(int nr, volatile void * addr)
 {
        int     mask, retval;
        volatile unsigned int *a = addr;
@@ -100,7 +100,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 
 #include <asm-generic/bitops/non-atomic.h>
 
-static __inline__ unsigned long ffz(unsigned long word)
+static inline unsigned long ffz(unsigned long word)
 {
        unsigned long result;
 
@@ -120,7 +120,7 @@ static __inline__ unsigned long ffz(unsigned long word)
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static __inline__ unsigned long __ffs(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
        unsigned long result;
 
index a6de3d06a3d9832a40db41ad704188e45be3b20b..b4000c8bf31b8b76161b93c227a9bfa24c8ad0a3 100644 (file)
@@ -32,6 +32,10 @@ static void __init check_bugs(void)
        case CPU_SH7750 ... CPU_SH4_501:
                *p++ = '4';
                break;
+       case CPU_SH7770 ... CPU_SH7781:
+               *p++ = '4';
+               *p++ = 'a';
+               break;
        default:
                *p++ = '?';
                *p++ = '!';
index 656fdfe9e8b445ee16e6f833e62f7e10bc783a20..e3a180cf506285dbffe07273c60bc35837f54ce9 100644 (file)
@@ -10,7 +10,6 @@
 #ifdef __KERNEL__
 
 #include <asm/cpu/cache.h>
-#include <asm/cpu/cacheflush.h>
 
 #define SH_CACHE_VALID         1
 #define SH_CACHE_UPDATED       2
 #define L1_CACHE_ALIGN(x)      (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
 struct cache_info {
-       unsigned int ways;
-       unsigned int sets;
-       unsigned int linesz;
+       unsigned int ways;              /* Number of cache ways */
+       unsigned int sets;              /* Number of cache sets */
+       unsigned int linesz;            /* Cache line size (bytes) */
 
-       unsigned int way_incr;
+       unsigned int way_size;          /* sets * line size */
 
+       /*
+        * way_incr is the address offset for accessing the next way
+        * in memory mapped cache array ops.
+        */
+       unsigned int way_incr;
        unsigned int entry_shift;
        unsigned int entry_mask;
 
+       /*
+        * Compute a mask which selects the address bits which overlap between
+        * 1. those used to select the cache set during indexing
+        * 2. those in the physical page number.
+        */
+       unsigned int alias_mask;
+
+       unsigned int n_aliases;         /* Number of aliases */
+
        unsigned long flags;
 };
 
-/* Flush (write-back only) a region (smaller than a page) */
-extern void __flush_wback_region(void *start, int size);
-/* Flush (write-back & invalidate) a region (smaller than a page) */
-extern void __flush_purge_region(void *start, int size);
-/* Flush (invalidate only) a region (smaller than a page) */
-extern void __flush_invalidate_region(void *start, int size);
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHE_H */
index 9dfb33edb00813368fdbfd87758358aed60a767c..07f62ec9ff0c8b9309d223f0424b0926afb86f4b 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_SH_CACHEFLUSH_H
 #ifdef __KERNEL__
 
+#include <linux/mm.h>
 #include <asm/cpu/cacheflush.h>
 
 /* Flush (write-back only) a region (smaller than a page) */
@@ -27,5 +28,7 @@ extern void __flush_invalidate_region(void *start, int size);
                memcpy(dst, src, len);                          \
        } while (0)
 
+#define HAVE_ARCH_UNMAPPED_AREA
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff --git a/include/asm-sh/cat68701/io.h b/include/asm-sh/cat68701/io.h
deleted file mode 100644 (file)
index 753b846..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * include/asm-sh/io_cat68701.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *           2001 Yutarou Ebihar (ebihara@si-linux.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an AONE Corp. CAT-68701 SH7708 Borad
- */
-
-#ifndef _ASM_SH_IO_CAT68701_H
-#define _ASM_SH_IO_CAT68701_H
-
-extern unsigned long cat68701_isa_port2addr(unsigned long offset);
-extern int cat68701_irq_demux(int irq);
-
-extern void init_cat68701_IRQ(void);
-extern void heartbeat_cat68701(void);
-
-#endif /* _ASM_SH_IO_CAT68701_H */
index fa03b30c4269f6ee60080ba2982c4c986ca8417a..08168afe6746a3d43a6e93da269566dad4c8bcc3 100644 (file)
@@ -159,6 +159,7 @@ static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
 }
 
 #define _HAVE_ARCH_IPV6_CSUM
+#ifdef CONFIG_IPV6
 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
                                                     struct in6_addr *daddr,
                                                     __u32 len,
@@ -194,6 +195,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
 
        return csum_fold(sum);
 }
+#endif
 
 /* 
  *     Copy and checksum to user
diff --git a/include/asm-sh/cpu-features.h b/include/asm-sh/cpu-features.h
new file mode 100644 (file)
index 0000000..4bccd7c
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH_CPU_FEATURES_H
+#define __ASM_SH_CPU_FEATURES_H
+
+/*
+ * Processor flags
+ *
+ * Note: When adding a new flag, keep cpu_flags[] in
+ * arch/sh/kernel/setup.c in sync so symbolic name
+ * mapping of the processor flags has a chance of being
+ * reasonably accurate.
+ *
+ * These flags are also available through the ELF
+ * auxiliary vector as AT_HWCAP.
+ */
+#define CPU_HAS_FPU            0x0001  /* Hardware FPU support */
+#define CPU_HAS_P2_FLUSH_BUG   0x0002  /* Need to flush the cache in P2 area */
+#define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
+#define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
+#define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
+#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 */
+
+#endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/include/asm-sh/cpu-sh2/shmparam.h b/include/asm-sh/cpu-sh2/shmparam.h
deleted file mode 100644 (file)
index 817c182..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-sh/cpu-sh2/shmparam.h
- *
- * Copyright (C) 2003  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.
- */
-#ifndef __ASM_CPU_SH2_SHMPARAM_H
-#define __ASM_CPU_SH2_SHMPARAM_H
-
-#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
-
-#endif /* __ASM_CPU_SH2_SHMPARAM_H */
-
index 406aa8d9b9476ceb93edb0a58d2fbc31b084b3d6..ffe08d2813f996152b5cdba1fb626372ecbcabdb 100644 (file)
 #define CCR_CACHE_ENABLE       CCR_CACHE_CE
 #define CCR_CACHE_INVALIDATE   CCR_CACHE_CF
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7705) || defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define CCR3   0xa40000b4
 #define CCR_CACHE_16KB  0x00010000
 #define CCR_CACHE_32KB 0x00020000
 #endif
 
-
 #endif /* __ASM_CPU_SH3_CACHE_H */
-
index f51aed00c68f762132c14e9173f4579c6fac6171..03fde97a7fd0eaf9d5ba8f6237f0b3aa5d76958e 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __ASM_CPU_SH3_CACHEFLUSH_H
 #define __ASM_CPU_SH3_CACHEFLUSH_H
 
-/* 
+/*
  * Cache flushing:
  *
  *  - flush_cache_all() flushes entire cache
  /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
 #define CACHE_ALIAS 0x00001000
 
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                              unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
-extern void flush_dcache_page(struct page *pg);
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
-
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-
-/* SH3 has unified cache so no special action needed here */
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
-#define flush_page_to_ram(page)                        do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-
-#define p3_cache_init()                                do { } while (0)
-
 #define PG_mapped      PG_arch_1
 
-/* We provide our own get_unmapped_area to avoid cache alias issue */
-#define HAVE_ARCH_UNMAPPED_AREA
-
+void flush_cache_all(void);
+void flush_cache_mm(struct mm_struct *mm);
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                              unsigned long end);
+void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
+void flush_dcache_page(struct page *pg);
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_icache_page(struct vm_area_struct *vma, struct page *page);
 #else
-
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 #define flush_icache_range(start, end)         do { } while (0)
 #define flush_icache_page(vma,pg)              do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
+#endif
 
-#define p3_cache_init()                                do { } while (0)
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-#define HAVE_ARCH_UNMAPPED_AREA
+/* SH3 has unified cache so no special action needed here */
+#define flush_cache_sigtramp(vaddr)            do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
-#endif
+#define p3_cache_init()                                do { } while (0)
 
 #endif /* __ASM_CPU_SH3_CACHEFLUSH_H */
-
index b61b6e331df0efa74342de3dbc93c477a10c81b5..273f3229785cfb93076c9ad810b7b68feb474492 100644 (file)
@@ -18,5 +18,9 @@
 #define MIN_DIVISOR_NR         0
 #define MAX_DIVISOR_NR         4
 
+#define FRQCR_CKOEN    0x0100
+#define FRQCR_PLLEN    0x0080
+#define FRQCR_PSTBY    0x0040
+
 #endif /* __ASM_CPU_SH3_FREQ_H */
 
index a844ea0965b6bb10d861e8eff63d045559334532..bccb7ddb438b9ca10bbe7f3d86a9dc9fa3d69255 100644 (file)
 #define TRA    0xffffffd0
 #define EXPEVT 0xffffffd4
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define INTEVT 0xa4000000      /* INTEVTE2(0xa4000000) */
 #else
 #define INTEVT 0xffffffd8
diff --git a/include/asm-sh/cpu-sh3/shmparam.h b/include/asm-sh/cpu-sh3/shmparam.h
deleted file mode 100644 (file)
index da5b5ee..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-sh/cpu-sh3/shmparam.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- *
- * 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 __ASM_CPU_SH3_SHMPARAM_H
-#define __ASM_CPU_SH3_SHMPARAM_H
-
-#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
-
-#endif /* __ASM_CPU_SH3_SHMPARAM_H */
-
index 3d8e95e8d10ccd8c8d1666b47759c87b543ff696..b2394cf76f491e21012853302efcf401f6bd8f44 100644 (file)
  *     SH7710
  *     SH7720
  *     SH7300
+ *     SH7710
  * ---------------------------------------------------------------------------
  */
 
+#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#define TMU_TOCR       0xfffffe90      /* Byte access */
+#endif
+
 #if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define TMU_TSTR       0xa412fe92      /* Byte access */
 
@@ -39,9 +44,6 @@
 #define TMU2_TCR       0xa412feb4      /* Word access */
 
 #else
-#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
-#define TMU_TOCR       0xfffffe90      /* Byte access */
-#endif
 #define TMU_TSTR       0xfffffe92      /* Byte access */
 
 #define TMU0_TCOR      0xfffffe94      /* Long access */
index 0f809dec4e171a15e55c7b7db4ae05cc70b7c4f0..9d308cbe9b29240064030fb9004a456123e46dba 100644 (file)
 #ifndef __ASM_CPU_SH3_UBC_H
 #define __ASM_CPU_SH3_UBC_H
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define UBC_BARA               0xa4ffffb0
+#define UBC_BAMRA              0xa4ffffb4
+#define UBC_BBRA               0xa4ffffb8
+#define UBC_BASRA              0xffffffe4
+#define UBC_BARB               0xa4ffffa0
+#define UBC_BAMRB              0xa4ffffa4
+#define UBC_BBRB               0xa4ffffa8
+#define UBC_BASRB              0xffffffe8
+#define UBC_BDRB               0xa4ffff90
+#define UBC_BDMRB              0xa4ffff94
+#define UBC_BRCR               0xa4ffff98
+#else
 #define UBC_BARA                0xffffffb0
 #define UBC_BAMRA               0xffffffb4
 #define UBC_BBRA                0xffffffb8
@@ -22,6 +35,6 @@
 #define UBC_BDRB                0xffffff90
 #define UBC_BDMRB               0xffffff94
 #define UBC_BRCR                0xffffff98
+#endif
 
 #endif /* __ASM_CPU_SH3_UBC_H */
-
index 727634d886cecdef1fc859e0889d23dbaf7f289b..bb2e1b03060c98b0497527d6ea95413010b302aa 100644 (file)
@@ -22,5 +22,8 @@
 #define P4SEG_TLB_DATA 0xf7000000
 #define P4SEG_REG_BASE 0xff000000
 
+#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
+#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
+
 #endif /* __ASM_CPU_SH4_ADDRSPACE_H */
 
index 1fe20359312c774be67ac4ccd2cebcf1dccb9e85..6e9c7e6ee8e4e025d749ad1dbbce65a2cdb76198 100644 (file)
@@ -22,7 +22,9 @@
 #define CCR_CACHE_ICE  0x0100  /* Instruction Cache Enable */
 #define CCR_CACHE_ICI  0x0800  /* IC Invalidate */
 #define CCR_CACHE_IIX  0x8000  /* IC Index Enable */
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
 #define CCR_CACHE_EMODE        0x80000000      /* EMODE Enable */
+#endif
 
 /* Default CCR setup: 8k+16k-byte cache,P1-wb,enable */
 #define CCR_CACHE_ENABLE       (CCR_CACHE_OCE|CCR_CACHE_ICE)
index f323567e085f408f5a3efc5b04a56eb64998b97f..515fd574267c100dba1394ddf48445f67914aeb8 100644 (file)
  *  caching; in which case they're only semi-broken),
  *  so we need them.
  */
-
-/* Page is 4K, OC size is 16K, there are four lines. */
-#define CACHE_ALIAS 0x00003000
-
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                             unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
-extern void flush_dcache_page(struct page *pg);
+void flush_cache_all(void);
+void flush_cache_mm(struct mm_struct *mm);
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end);
+void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
+                     unsigned long pfn);
+void flush_dcache_page(struct page *pg);
 
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void flush_cache_sigtramp(unsigned long addr);
-extern void flush_icache_user_range(struct vm_area_struct *vma,
-                                   struct page *page, unsigned long addr,
-                                   int len);
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_cache_sigtramp(unsigned long addr);
+void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+                            unsigned long addr, int len);
 
 #define flush_icache_page(vma,pg)              do { } while (0)
 
 /* Initialization of P3 area for copy_user_page */
-extern void p3_cache_init(void);
+void p3_cache_init(void);
 
 #define PG_mapped      PG_arch_1
 
-/* We provide our own get_unmapped_area to avoid cache alias issue */
-#define HAVE_ARCH_UNMAPPED_AREA
-
 #ifdef CONFIG_MMU
 extern int remap_area_pages(unsigned long addr, unsigned long phys_addr,
                            unsigned long size, unsigned long flags);
@@ -61,4 +50,3 @@ static inline int remap_area_pages(unsigned long addr, unsigned long phys_addr,
 }
 #endif /* CONFIG_MMU */
 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
-
diff --git a/include/asm-sh/cpu-sh4/dma-sh7780.h b/include/asm-sh/cpu-sh4/dma-sh7780.h
new file mode 100644 (file)
index 0000000..6c90d28
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H
+#define __ASM_SH_CPU_SH4_DMA_SH7780_H
+
+#define REQ_HE 0x000000C0
+#define REQ_H  0x00000080
+#define REQ_LE 0x00000040
+#define TM_BURST 0x0000020
+#define TS_8   0x00000000
+#define TS_16  0x00000008
+#define TS_32  0x00000010
+#define TS_16BLK       0x00000018
+#define TS_32BLK       0x00100000
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ *
+ * Defaults to a 64-bit transfer size.
+ */
+enum {
+       XMIT_SZ_8BIT,
+       XMIT_SZ_16BIT,
+       XMIT_SZ_32BIT,
+       XMIT_SZ_128BIT,
+       XMIT_SZ_256BIT,
+};
+
+/*
+ * The DMA count is defined as the number of bytes to transfer.
+ */
+static unsigned int __attribute__ ((used)) ts_shift[] = {
+       [XMIT_SZ_8BIT]          = 0,
+       [XMIT_SZ_16BIT]         = 1,
+       [XMIT_SZ_32BIT]         = 2,
+       [XMIT_SZ_128BIT]        = 4,
+       [XMIT_SZ_256BIT]        = 5,
+};
+
+#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
index 0dfe61f14802168b3a6526f821447d0955dc7336..3e4b3e6d80c02fb81b8e03dd882eb10c11ca99ab 100644 (file)
@@ -1,11 +1,17 @@
 #ifndef __ASM_CPU_SH4_DMA_H
 #define __ASM_CPU_SH4_DMA_H
 
+#define DMAOR_INIT     ( 0x8000 | DMAOR_DME )
+
 #ifdef CONFIG_CPU_SH4A
 #define SH_DMAC_BASE   0xfc808020
+
+#define CHCR_TS_MASK   0x18
+#define CHCR_TS_SHIFT  3
+
+#include <asm/cpu/dma-sh7780.h>
 #else
 #define SH_DMAC_BASE   0xffa00000
-#endif
 
 /* Definitions for the SuperH DMAC */
 #define TM_BURST       0x0000080
@@ -19,8 +25,6 @@
 
 #define DMAOR_COD      0x00000008
 
-#define DMAOR_INIT     ( 0x8000 | DMAOR_DME )
-
 /*
  * The SuperH DMAC supports a number of transmit sizes, we list them here,
  * with their respective values as they appear in the CHCR registers.
@@ -45,5 +49,6 @@ static unsigned int ts_shift[] __attribute__ ((used)) = {
        [XMIT_SZ_32BIT]         = 2,
        [XMIT_SZ_256BIT]        = 5,
 };
+#endif
 
 #endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/include/asm-sh/cpu-sh4/shmparam.h b/include/asm-sh/cpu-sh4/shmparam.h
deleted file mode 100644 (file)
index a5a0aa9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/shmparam.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- *
- * 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 __ASM_CPU_SH4_SHMPARAM_H
-#define __ASM_CPU_SH4_SHMPARAM_H
-
-/*
- * SH-4 has D-cache alias issue
- */
-#define        SHMLBA (PAGE_SIZE*4)             /* attach addr a multiple of this */
-
-#endif /* __ASM_CPU_SH4_SHMPARAM_H */
-
index 366b09166d3b738bd7e56bbd52a5a47a8eeb107c..586d6491816aed1fa0741eeaffeab31fb4eb0586 100644 (file)
@@ -17,7 +17,7 @@
  * Store queues range from e0000000-e3fffffc, allowing approx. 64MB to be
  * mapped to any physical address space. Since data is written (and aligned)
  * to 32-byte boundaries, we need to be sure that all allocations are aligned.
- */ 
+ */
 #define SQ_SIZE                 32
 #define SQ_ALIGN_MASK           (~(SQ_SIZE - 1))
 #define SQ_ALIGN(addr)          (((addr)+SQ_SIZE-1) & SQ_ALIGN_MASK)
 #define SQ_QACR1               (P4SEG_REG_BASE  + 0x3c)
 #define SQ_ADDRMAX              (P4SEG_STORE_QUE + 0x04000000)
 
-struct sq_mapping {
-       const char *name;
-
-       unsigned long sq_addr;
-       unsigned long addr;
-       unsigned int size;
-
-       struct list_head list;
-};
-
 /* arch/sh/kernel/cpu/sh4/sq.c */
-extern struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name);
-extern void sq_unmap(struct sq_mapping *map);
-
-extern void sq_clear(unsigned long addr, unsigned int len);
-extern void sq_flush(void *addr);
-extern void sq_flush_range(unsigned long start, unsigned int len);
+unsigned long sq_remap(unsigned long phys, unsigned int size,
+                      const char *name, unsigned long flags);
+void sq_unmap(unsigned long vaddr);
+void sq_flush_range(unsigned long start, unsigned int len);
 
 #endif /* __ASM_CPU_SH4_SQ_H */
-
diff --git a/include/asm-sh/cqreek/cqreek.h b/include/asm-sh/cqreek/cqreek.h
deleted file mode 100644 (file)
index 09aecc0..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __ASM_SH_CQREEK_CQREEK_H
-#define __ASM_SH_CQREEK_CQREEK_H
-
-#define BRIDGE_FEATURE         0x0002
-
-#define BRIDGE_IDE_CTRL                0x0018
-#define BRIDGE_IDE_INTR_LVL            0x001A
-#define BRIDGE_IDE_INTR_MASK   0x001C
-#define BRIDGE_IDE_INTR_STAT   0x001E
-
-#define BRIDGE_ISA_CTRL                0x0028
-#define BRIDGE_ISA_INTR_LVL            0x002A
-#define BRIDGE_ISA_INTR_MASK   0x002C
-#define BRIDGE_ISA_INTR_STAT   0x002E
-
-/* arch/sh/boards/cqreek/setup.c */
-extern void setup_cqreek(void);
-
-/* arch/sh/boards/cqreek/irq.c */
-extern int cqreek_has_ide, cqreek_has_isa;
-extern void init_cqreek_IRQ(void);
-
-/* arch/sh/boards/cqreek/io.c */
-extern unsigned long cqreek_port2addr(unsigned long port);
-
-#endif /* __ASM_SH_CQREEK_CQREEK_H */
-
index 124968f9866e9f2cabeb0d78474a3c2dcaf1f2e0..56cd4b97723212bd2a3cd988464f202b34911f91 100644 (file)
@@ -141,25 +141,35 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
        }
 }
 
-static void dma_sync_single_for_cpu(struct device *dev,
-                                   dma_addr_t dma_handle, size_t size,
-                                   enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_single")));
+static inline void dma_sync_single_for_cpu(struct device *dev,
+                                          dma_addr_t dma_handle, size_t size,
+                                          enum dma_data_direction dir)
+{
+       dma_sync_single(dev, dma_handle, size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+                                             dma_addr_t dma_handle,
+                                             size_t size,
+                                             enum dma_data_direction dir)
+{
+       dma_sync_single(dev, dma_handle, size, dir);
+}
 
-static void dma_sync_single_for_device(struct device *dev,
-                                      dma_addr_t dma_handle, size_t size,
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+                                      struct scatterlist *sg, int nelems,
                                       enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_single")));
+{
+       dma_sync_sg(dev, sg, nelems, dir);
+}
 
-static void dma_sync_sg_for_cpu(struct device *dev,
-                               struct scatterlist *sg, int nelems,
-                               enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_sg")));
+static inline void dma_sync_sg_for_device(struct device *dev,
+                                         struct scatterlist *sg, int nelems,
+                                         enum dma_data_direction dir)
+{
+       dma_sync_sg(dev, sg, nelems, dir);
+}
 
-static void dma_sync_sg_for_device(struct device *dev,
-                                  struct scatterlist *sg, int nelems,
-                                  enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_sg")));
 
 static inline int dma_get_cache_alignment(void)
 {
@@ -174,6 +184,4 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
 {
        return dma_addr == 0;
 }
-
 #endif /* __ASM_SH_DMA_MAPPING_H */
-
index e62a6d0ed932cec3631ee42e1d3e51331d09ae23..d9daa028689f91b675583c892c00aa48925b4534 100644 (file)
@@ -89,6 +89,7 @@ struct dma_channel {
        wait_queue_head_t wait_queue;
 
        struct sys_device dev;
+       char *name;
 };
 
 struct dma_info {
diff --git a/include/asm-sh/dmida/io.h b/include/asm-sh/dmida/io.h
deleted file mode 100644 (file)
index 21bd416..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SH_DMIDA_IO_H
-#define __ASM_SH_DMIDA_IO_H
-
-/*
- * Nothing special here.. just use the generic cchip io routines.
- */
-#include <asm/hd64465/io.h>
-
-#endif /* __ASM_SH_DMIDA_IO_H */
-
index 0dee7b05b49d9b069bd820e4d5e9a7977553e4e8..c1253a6831974c7bc4e60435af44cf3f02ad6789 100644 (file)
@@ -6,8 +6,6 @@ extern char ec3104_kbd_unexpected_up(unsigned char);
 extern void ec3104_kbd_leds(unsigned char);
 extern void ec3104_kbd_init_hw(void);
 
-#define SYSRQ_KEY 0x54
-
 #define kbd_sysrq_xlate ec3104_kbd_sysrq_xlate
 #define kbd_setkeycode ec3104_kbd_setkeycode
 #define kbd_getkeycode ec3104_kbd_getkeycode
index 1b63dfeea4f2b3e165a4689e80c130a46b6eb1c0..3a07ab40ac4d0a66eab64eb094f538e08fef68bb 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __ASM_SH_ELF_H
 #define __ASM_SH_ELF_H
 
+#include <asm/processor.h>
+#include <asm/auxvec.h>
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
 /* SH relocation types  */
 #define        R_SH_NONE               0
 #define        R_SH_DIR32              1
@@ -46,9 +51,6 @@
  * ELF register definitions..
  */
 
-#include <asm/ptrace.h>
-#include <asm/user.h>
-
 typedef unsigned long elf_greg_t;
 
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
@@ -91,7 +93,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
    instruction set this CPU supports.  This could be done in user space,
    but it's not easy, and we've already done it here.  */
 
-#define ELF_HWCAP      (0)
+#define ELF_HWCAP      (boot_cpu_data.flags)
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
@@ -119,4 +121,24 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 #endif
 
+#ifdef CONFIG_VSYSCALL
+/* vDSO has arch_setup_additional_pages */
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+                                      int executable_stack);
+
+extern unsigned int vdso_enabled;
+extern void __kernel_vsyscall;
+
+#define VDSO_BASE              ((unsigned long)current->mm->context.vdso)
+#define VDSO_SYM(x)            (VDSO_BASE + (unsigned long)(x))
+
+#define ARCH_DLINFO                                            \
+do {                                                           \
+       if (vdso_enabled)                                       \
+               NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);        \
+} while (0)
+#endif /* CONFIG_VSYSCALL */
+
 #endif /* __ASM_SH_ELF_H */
index 412bccaa07e6ee8ffddaf7e7afc0570df0db9f2f..458e9fa59545e309225c10d11a6f1e1575816926 100644 (file)
@@ -25,7 +25,7 @@
  * addresses. The point is to have a constant address at
  * compile time, but to set the physical address only
  * in the boot process. We allocate these special  addresses
- * from the end of virtual memory (0xfffff000) backwards.
+ * from the end of P3 backwards.
  * Also this lets us do fail-safe vmalloc(), we
  * can guarantee that these special addresses and
  * vmalloc()-ed addresses never overlap.
index f29072e1c87e97e8ab3227d09f67cee4c0b22d68..0d5cc04ab005db06809770d4b551c4475382569e 100644 (file)
@@ -13,7 +13,7 @@
 #define __ASM_SH_FLAT_H
 
 #define        flat_stack_align(sp)                    /* nothing needed */
-#define        flat_argvp_envp_on_stack()              1
+#define        flat_argvp_envp_on_stack()              0
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
 #define        flat_get_addr_from_rp(rp, relval, flags)        get_unaligned(rp)
diff --git a/include/asm-sh/harp/harp.h b/include/asm-sh/harp/harp.h
deleted file mode 100644 (file)
index b2fbcfa..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Defintions applicable to the STMicroelectronics ST40STB1 HARP and
- * compatible boards.
- */
-
-#if defined(CONFIG_SH_STB1_HARP)
-
-#define EPLD_BASE     0xa0800000
-
-#define EPLD_LED      (EPLD_BASE+0x000c0000)
-#define EPLD_INTSTAT0 (EPLD_BASE+0x00200000)
-#define EPLD_INTSTAT1 (EPLD_BASE+0x00240000)
-#define EPLD_INTMASK0 (EPLD_BASE+0x00280000)
-#define EPLD_INTMASK1 (EPLD_BASE+0x002c0000)
-#define EPLD_PAGEADDR (EPLD_BASE+0x00300000)
-#define EPLD_REVID1   (EPLD_BASE+0x00380000)
-#define EPLD_REVID2   (EPLD_BASE+0x003c0000)
-
-#define EPLD_LED_ON  1
-#define EPLD_LED_OFF 0
-
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-
-#define EPLD_BASE     0xa7000000
-
-#define EPLD_REVID    (EPLD_BASE+0x00000000)
-#define EPLD_LED      (EPLD_BASE+0x00040000)
-#define EPLD_INTMASK0 (EPLD_BASE+0x001c0000)
-#define EPLD_INTMASK1 (EPLD_BASE+0x00200000)
-#define EPLD_INTSTAT0 (EPLD_BASE+0x00240000)
-#define EPLD_INTSTAT1 (EPLD_BASE+0x00280000)
-
-#define EPLD_LED_ON  0
-#define EPLD_LED_OFF 1
-
-#else
-#error Unknown board
-#endif
diff --git a/include/asm-sh/harp/io.h b/include/asm-sh/harp/io.h
deleted file mode 100644 (file)
index 68f39e0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SH_HARP_IO_H
-#define __ASM_SH_HARP_IO_H
-
-/*
- * Nothing special here.. just use the generic cchip io routines.
- */
-#include <asm/hd64465/io.h>
-
-#endif /* __ASM_SH_HARP_IO_H */
-
diff --git a/include/asm-sh/hd64461.h b/include/asm-sh/hd64461.h
new file mode 100644 (file)
index 0000000..27e5c34
--- /dev/null
@@ -0,0 +1,208 @@
+#ifndef __ASM_SH_HD64461
+#define __ASM_SH_HD64461
+/*
+ *     $Id: hd64461.h,v 1.5 2004/03/16 00:07:51 lethal Exp $
+ *     Copyright (C) 2000 YAEGASHI Takeshi
+ *     Hitachi HD64461 companion chip support
+ */
+
+/* Constants for PCMCIA mappings */
+#define HD64461_PCC_WINDOW     0x01000000
+
+#define HD64461_PCC0_BASE      0xb8000000      /* area 6 */
+#define HD64461_PCC0_ATTR      (HD64461_PCC0_BASE)
+#define HD64461_PCC0_COMM      (HD64461_PCC0_BASE+HD64461_PCC_WINDOW)
+#define HD64461_PCC0_IO                (HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)
+
+#define HD64461_PCC1_BASE      0xb4000000      /* area 5 */
+#define HD64461_PCC1_ATTR      (HD64461_PCC1_BASE)
+#define HD64461_PCC1_COMM      (HD64461_PCC1_BASE+HD64461_PCC_WINDOW)
+
+#define HD64461_STBCR  0x10000
+#define HD64461_STBCR_CKIO_STBY                        0x2000
+#define HD64461_STBCR_SAFECKE_IST              0x1000
+#define HD64461_STBCR_SLCKE_IST                        0x0800
+#define HD64461_STBCR_SAFECKE_OST              0x0400
+#define HD64461_STBCR_SLCKE_OST                        0x0200
+#define HD64461_STBCR_SMIAST                   0x0100
+#define HD64461_STBCR_SLCDST                   0x0080
+#define HD64461_STBCR_SPC0ST                   0x0040
+#define HD64461_STBCR_SPC1ST                   0x0020
+#define HD64461_STBCR_SAFEST                   0x0010
+#define HD64461_STBCR_STM0ST                   0x0008
+#define HD64461_STBCR_STM1ST                   0x0004
+#define HD64461_STBCR_SIRST                            0x0002
+#define HD64461_STBCR_SURTST                   0x0001
+
+#define HD64461_SYSCR  0x10002
+#define HD64461_SCPUCR 0x10004
+
+#define HD64461_LCDCBAR                0x11000
+#define HD64461_LCDCLOR                0x11002
+#define HD64461_LCDCCR         0x11004
+#define HD64461_LCDCCR_STBACK  0x0400
+#define HD64461_LCDCCR_STREQ   0x0100
+#define HD64461_LCDCCR_MOFF    0x0080
+#define HD64461_LCDCCR_REFSEL  0x0040
+#define HD64461_LCDCCR_EPON    0x0020
+#define HD64461_LCDCCR_SPON    0x0010
+
+#define        HD64461_LDR1            0x11010
+#define        HD64461_LDR1_DON        0x01
+#define        HD64461_LDR1_DINV       0x80
+
+#define        HD64461_LDR2            0x11012
+#define        HD64461_LDHNCR          0x11014
+#define        HD64461_LDHNSR          0x11016
+#define HD64461_LDVNTR         0x11018
+#define HD64461_LDVNDR         0x1101a
+#define HD64461_LDVSPR         0x1101c
+#define HD64461_LDR3           0x1101e
+
+#define HD64461_CPTWAR         0x11030
+#define HD64461_CPTWDR         0x11032
+#define HD64461_CPTRAR         0x11034
+#define HD64461_CPTRDR         0x11036
+
+#define HD64461_GRDOR          0x11040
+#define HD64461_GRSCR          0x11042
+#define HD64461_GRCFGR         0x11044
+#define HD64461_GRCFGR_ACCSTATUS               0x10
+#define HD64461_GRCFGR_ACCRESET                        0x08
+#define HD64461_GRCFGR_ACCSTART_BITBLT 0x06
+#define HD64461_GRCFGR_ACCSTART_LINE   0x04
+#define HD64461_GRCFGR_COLORDEPTH16            0x01
+
+#define HD64461_LNSARH         0x11046
+#define HD64461_LNSARL         0x11048
+#define HD64461_LNAXLR         0x1104a
+#define HD64461_LNDGR          0x1104c
+#define HD64461_LNAXR          0x1104e
+#define HD64461_LNERTR         0x11050
+#define HD64461_LNMDR          0x11052
+#define HD64461_BBTSSARH       0x11054
+#define HD64461_BBTSSARL       0x11056
+#define HD64461_BBTDSARH       0x11058
+#define HD64461_BBTDSARL       0x1105a
+#define HD64461_BBTDWR         0x1105c
+#define HD64461_BBTDHR         0x1105e
+#define HD64461_BBTPARH                0x11060
+#define HD64461_BBTPARL                0x11062
+#define HD64461_BBTMARH                0x11064
+#define HD64461_BBTMARL                0x11066
+#define HD64461_BBTROPR                0x11068
+#define HD64461_BBTMDR         0x1106a
+
+/* PC Card Controller Registers */
+#define HD64461_PCC0ISR         0x12000 /* socket 0 interface status */
+#define HD64461_PCC0GCR         0x12002 /* socket 0 general control */
+#define HD64461_PCC0CSCR        0x12004 /* socket 0 card status change */
+#define HD64461_PCC0CSCIER      0x12006 /* socket 0 card status change interrupt enable */
+#define HD64461_PCC0SCR         0x12008 /* socket 0 software control */
+#define HD64461_PCC1ISR         0x12010 /* socket 1 interface status */
+#define HD64461_PCC1GCR         0x12012 /* socket 1 general control */
+#define HD64461_PCC1CSCR        0x12014 /* socket 1 card status change */
+#define HD64461_PCC1CSCIER      0x12016 /* socket 1 card status change interrupt enable */
+#define HD64461_PCC1SCR         0x12018 /* socket 1 software control */
+
+/* PCC Interface Status Register */
+#define HD64461_PCCISR_READY           0x80    /* card ready */
+#define HD64461_PCCISR_MWP             0x40    /* card write-protected */
+#define HD64461_PCCISR_VS2             0x20    /* voltage select pin 2 */
+#define HD64461_PCCISR_VS1             0x10    /* voltage select pin 1 */
+#define HD64461_PCCISR_CD2             0x08    /* card detect 2 */
+#define HD64461_PCCISR_CD1             0x04    /* card detect 1 */
+#define HD64461_PCCISR_BVD2            0x02    /* battery 1 */
+#define HD64461_PCCISR_BVD1            0x01    /* battery 1 */
+
+#define HD64461_PCCISR_PCD_MASK                0x0c    /* card detect */
+#define HD64461_PCCISR_BVD_MASK                0x03    /* battery voltage */
+#define HD64461_PCCISR_BVD_BATGOOD     0x03    /* battery good */
+#define HD64461_PCCISR_BVD_BATWARN     0x01    /* battery low warning */
+#define HD64461_PCCISR_BVD_BATDEAD1    0x02    /* battery dead */
+#define HD64461_PCCISR_BVD_BATDEAD2    0x00    /* battery dead */
+
+/* PCC General Control Register */
+#define HD64461_PCCGCR_DRVE            0x80    /* output drive */
+#define HD64461_PCCGCR_PCCR            0x40    /* PC card reset */
+#define HD64461_PCCGCR_PCCT            0x20    /* PC card type, 1=IO&mem, 0=mem */
+#define HD64461_PCCGCR_VCC0            0x10    /* voltage control pin VCC0SEL0 */
+#define HD64461_PCCGCR_PMMOD           0x08    /* memory mode */
+#define HD64461_PCCGCR_PA25            0x04    /* pin A25 */
+#define HD64461_PCCGCR_PA24            0x02    /* pin A24 */
+#define HD64461_PCCGCR_REG             0x01    /* pin PCC0REG# */
+
+/* PCC Card Status Change Register */
+#define HD64461_PCCCSCR_SCDI           0x80    /* sw card detect intr */
+#define HD64461_PCCCSCR_SRV1           0x40    /* reserved */
+#define HD64461_PCCCSCR_IREQ           0x20    /* IREQ intr req */
+#define HD64461_PCCCSCR_SC             0x10    /* STSCHG (status change) pin */
+#define HD64461_PCCCSCR_CDC            0x08    /* CD (card detect) change */
+#define HD64461_PCCCSCR_RC             0x04    /* READY change */
+#define HD64461_PCCCSCR_BW             0x02    /* battery warning change */
+#define HD64461_PCCCSCR_BD             0x01    /* battery dead change */
+
+/* PCC Card Status Change Interrupt Enable Register */
+#define HD64461_PCCCSCIER_CRE          0x80    /* change reset enable */
+#define HD64461_PCCCSCIER_IREQE_MASK   0x60   /* IREQ enable */
+#define HD64461_PCCCSCIER_IREQE_DISABLED       0x00   /* IREQ disabled */
+#define HD64461_PCCCSCIER_IREQE_LEVEL  0x20   /* IREQ level-triggered */
+#define HD64461_PCCCSCIER_IREQE_FALLING        0x40   /* IREQ falling-edge-trig */
+#define HD64461_PCCCSCIER_IREQE_RISING 0x60   /* IREQ rising-edge-trig */
+
+#define HD64461_PCCCSCIER_SCE          0x10    /* status change enable */
+#define HD64461_PCCCSCIER_CDE          0x08    /* card detect change enable */
+#define HD64461_PCCCSCIER_RE           0x04    /* ready change enable */
+#define HD64461_PCCCSCIER_BWE          0x02    /* battery warn change enable */
+#define HD64461_PCCCSCIER_BDE          0x01    /* battery dead change enable*/
+
+/* PCC Software Control Register */
+#define HD64461_PCCSCR_VCC1            0x02    /* voltage control pin 1 */
+#define HD64461_PCCSCR_SWP             0x01    /* write protect */
+
+#define HD64461_P0OCR           0x1202a
+#define HD64461_P1OCR           0x1202c
+#define HD64461_PGCR            0x1202e
+
+#define HD64461_GPACR          0x14000
+#define HD64461_GPBCR          0x14002
+#define HD64461_GPCCR          0x14004
+#define HD64461_GPDCR          0x14006
+#define HD64461_GPADR          0x14010
+#define HD64461_GPBDR          0x14012
+#define HD64461_GPCDR          0x14014
+#define HD64461_GPDDR          0x14016
+#define HD64461_GPAICR         0x14020
+#define HD64461_GPBICR         0x14022
+#define HD64461_GPCICR         0x14024
+#define HD64461_GPDICR         0x14026
+#define HD64461_GPAISR         0x14040
+#define HD64461_GPBISR         0x14042
+#define HD64461_GPCISR         0x14044
+#define HD64461_GPDISR         0x14046
+
+#define HD64461_NIRR           0x15000
+#define HD64461_NIMR           0x15002
+
+#define HD64461_IRQBASE                OFFCHIP_IRQ_BASE
+#define HD64461_IRQ_NUM                16
+
+#define HD64461_IRQ_UART       (HD64461_IRQBASE+5)
+#define HD64461_IRQ_IRDA       (HD64461_IRQBASE+6)
+#define HD64461_IRQ_TMU1       (HD64461_IRQBASE+9)
+#define HD64461_IRQ_TMU0       (HD64461_IRQBASE+10)
+#define HD64461_IRQ_GPIO       (HD64461_IRQBASE+11)
+#define HD64461_IRQ_AFE                (HD64461_IRQBASE+12)
+#define HD64461_IRQ_PCC1       (HD64461_IRQBASE+13)
+#define HD64461_IRQ_PCC0       (HD64461_IRQBASE+14)
+
+#define __IO_PREFIX    hd64461
+#include <asm/io_generic.h>
+
+/* arch/sh/cchips/hd6446x/hd64461/setup.c */
+int hd64461_irq_demux(int irq);
+void hd64461_register_irq_demux(int irq,
+                               int (*demux) (int irq, void *dev), void *dev);
+void hd64461_unregister_irq_demux(int irq);
+
+#endif
diff --git a/include/asm-sh/hd64461/hd64461.h b/include/asm-sh/hd64461/hd64461.h
deleted file mode 100644 (file)
index 87f13d2..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-#ifndef __ASM_SH_HD64461
-#define __ASM_SH_HD64461
-/*
- *     $Id: hd64461.h,v 1.5 2004/03/16 00:07:51 lethal Exp $
- *     Copyright (C) 2000 YAEGASHI Takeshi
- *     Hitachi HD64461 companion chip support
- */
-
-/* Constants for PCMCIA mappings */
-#define HD64461_PCC_WINDOW     0x01000000
-
-#define HD64461_PCC0_BASE      0xb8000000      /* area 6 */
-#define HD64461_PCC0_ATTR      (HD64461_PCC0_BASE)
-#define HD64461_PCC0_COMM      (HD64461_PCC0_BASE+HD64461_PCC_WINDOW)
-#define HD64461_PCC0_IO                (HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)
-
-#define HD64461_PCC1_BASE      0xb4000000      /* area 5 */
-#define HD64461_PCC1_ATTR      (HD64461_PCC1_BASE)
-#define HD64461_PCC1_COMM      (HD64461_PCC1_BASE+HD64461_PCC_WINDOW)
-
-#define HD64461_STBCR  0x10000
-#define HD64461_STBCR_CKIO_STBY                        0x2000
-#define HD64461_STBCR_SAFECKE_IST              0x1000
-#define HD64461_STBCR_SLCKE_IST                        0x0800
-#define HD64461_STBCR_SAFECKE_OST              0x0400
-#define HD64461_STBCR_SLCKE_OST                        0x0200
-#define HD64461_STBCR_SMIAST                   0x0100
-#define HD64461_STBCR_SLCDST                   0x0080
-#define HD64461_STBCR_SPC0ST                   0x0040
-#define HD64461_STBCR_SPC1ST                   0x0020
-#define HD64461_STBCR_SAFEST                   0x0010
-#define HD64461_STBCR_STM0ST                   0x0008
-#define HD64461_STBCR_STM1ST                   0x0004
-#define HD64461_STBCR_SIRST                            0x0002
-#define HD64461_STBCR_SURTST                   0x0001
-
-#define HD64461_SYSCR  0x10002
-#define HD64461_SCPUCR 0x10004
-
-#define HD64461_LCDCBAR                0x11000
-#define HD64461_LCDCLOR                0x11002
-#define HD64461_LCDCCR         0x11004
-#define HD64461_LCDCCR_MOFF    0x80
-
-#define        HD64461_LDR1            0x11010
-#define        HD64461_LDR1_DON        0x01
-#define        HD64461_LDR1_DINV       0x80
-
-#define        HD64461_LDR2            0x11012
-#define        HD64461_LDHNCR          0x11014
-#define        HD64461_LDHNSR          0x11016
-#define HD64461_LDVNTR         0x11018
-#define HD64461_LDVNDR         0x1101a
-#define HD64461_LDVSPR         0x1101c
-#define HD64461_LDR3           0x1101e
-
-#define HD64461_CPTWAR         0x11030 
-#define HD64461_CPTWDR         0x11032
-#define HD64461_CPTRAR         0x11034 
-#define HD64461_CPTRDR         0x11036
-
-#define HD64461_GRDOR          0x11040
-#define HD64461_GRSCR          0x11042
-#define HD64461_GRCFGR         0x11044
-#define HD64461_GRCFGR_ACCSTATUS               0x10
-#define HD64461_GRCFGR_ACCRESET                        0x08
-#define HD64461_GRCFGR_ACCSTART_BITBLT 0x06
-#define HD64461_GRCFGR_ACCSTART_LINE   0x04
-#define HD64461_GRCFGR_COLORDEPTH16            0x01
-
-#define HD64461_LNSARH         0x11046
-#define HD64461_LNSARL         0x11048
-#define HD64461_LNAXLR         0x1104a
-#define HD64461_LNDGR          0x1104c
-#define HD64461_LNAXR          0x1104e
-#define HD64461_LNERTR         0x11050
-#define HD64461_LNMDR          0x11052
-#define HD64461_BBTSSARH       0x11054
-#define HD64461_BBTSSARL       0x11056
-#define HD64461_BBTDSARH       0x11058
-#define HD64461_BBTDSARL       0x1105a
-#define HD64461_BBTDWR         0x1105c
-#define HD64461_BBTDHR         0x1105e
-#define HD64461_BBTPARH                0x11060
-#define HD64461_BBTPARL                0x11062
-#define HD64461_BBTMARH                0x11064
-#define HD64461_BBTMARL                0x11066
-#define HD64461_BBTROPR                0x11068
-#define HD64461_BBTMDR         0x1106a
-
-/* PC Card Controller Registers */
-#define HD64461_PCC0ISR         0x12000 /* socket 0 interface status */
-#define HD64461_PCC0GCR         0x12002 /* socket 0 general control */
-#define HD64461_PCC0CSCR        0x12004 /* socket 0 card status change */
-#define HD64461_PCC0CSCIER      0x12006 /* socket 0 card status change interrupt enable */
-#define HD64461_PCC0SCR         0x12008 /* socket 0 software control */
-#define HD64461_PCC1ISR         0x12010 /* socket 1 interface status */
-#define HD64461_PCC1GCR         0x12012 /* socket 1 general control */
-#define HD64461_PCC1CSCR        0x12014 /* socket 1 card status change */
-#define HD64461_PCC1CSCIER      0x12016 /* socket 1 card status change interrupt enable */
-#define HD64461_PCC1SCR         0x12018 /* socket 1 software control */
-
-/* PCC Interface Status Register */
-#define HD64461_PCCISR_READY           0x80    /* card ready */
-#define HD64461_PCCISR_MWP             0x40    /* card write-protected */
-#define HD64461_PCCISR_VS2             0x20    /* voltage select pin 2 */
-#define HD64461_PCCISR_VS1             0x10    /* voltage select pin 1 */
-#define HD64461_PCCISR_CD2             0x08    /* card detect 2 */
-#define HD64461_PCCISR_CD1             0x04    /* card detect 1 */
-#define HD64461_PCCISR_BVD2            0x02    /* battery 1 */
-#define HD64461_PCCISR_BVD1            0x01    /* battery 1 */
-
-#define HD64461_PCCISR_PCD_MASK                0x0c    /* card detect */
-#define HD64461_PCCISR_BVD_MASK        0x03    /* battery voltage */
-#define HD64461_PCCISR_BVD_BATGOOD     0x03    /* battery good */
-#define HD64461_PCCISR_BVD_BATWARN     0x01    /* battery low warning */
-#define HD64461_PCCISR_BVD_BATDEAD1    0x02    /* battery dead */
-#define HD64461_PCCISR_BVD_BATDEAD2    0x00    /* battery dead */
-
-/* PCC General Control Register */
-#define HD64461_PCCGCR_DRVE            0x80    /* output drive */
-#define HD64461_PCCGCR_PCCR            0x40    /* PC card reset */
-#define HD64461_PCCGCR_PCCT            0x20    /* PC card type, 1=IO&mem, 0=mem */
-#define HD64461_PCCGCR_VCC0            0x10    /* voltage control pin VCC0SEL0 */
-#define HD64461_PCCGCR_PMMOD           0x08    /* memory mode */
-#define HD64461_PCCGCR_PA25            0x04    /* pin A25 */
-#define HD64461_PCCGCR_PA24            0x02    /* pin A24 */
-#define HD64461_PCCGCR_REG             0x01    /* pin PCC0REG# */
-
-/* PCC Card Status Change Register */
-#define HD64461_PCCCSCR_SCDI           0x80    /* sw card detect intr */
-#define HD64461_PCCCSCR_SRV1           0x40    /* reserved */
-#define HD64461_PCCCSCR_IREQ           0x20    /* IREQ intr req */
-#define HD64461_PCCCSCR_SC             0x10    /* STSCHG (status change) pin */
-#define HD64461_PCCCSCR_CDC            0x08    /* CD (card detect) change */
-#define HD64461_PCCCSCR_RC             0x04    /* READY change */
-#define HD64461_PCCCSCR_BW             0x02    /* battery warning change */
-#define HD64461_PCCCSCR_BD             0x01    /* battery dead change */
-
-/* PCC Card Status Change Interrupt Enable Register */
-#define HD64461_PCCCSCIER_CRE          0x80    /* change reset enable */
-#define HD64461_PCCCSCIER_IREQE_MASK           0x60   /* IREQ enable */
-#define HD64461_PCCCSCIER_IREQE_DISABLED       0x00   /* IREQ disabled */
-#define HD64461_PCCCSCIER_IREQE_LEVEL          0x20   /* IREQ level-triggered */
-#define HD64461_PCCCSCIER_IREQE_FALLING        0x40   /* IREQ falling-edge-trig */
-#define HD64461_PCCCSCIER_IREQE_RISING         0x60   /* IREQ rising-edge-trig */
-
-#define HD64461_PCCCSCIER_SCE          0x10    /* status change enable */
-#define HD64461_PCCCSCIER_CDE          0x08    /* card detect change enable */
-#define HD64461_PCCCSCIER_RE           0x04    /* ready change enable */
-#define HD64461_PCCCSCIER_BWE          0x02    /* battery warn change enable */
-#define HD64461_PCCCSCIER_BDE          0x01    /* battery dead change enable*/
-
-/* PCC Software Control Register */
-#define HD64461_PCCSCR_VCC1            0x02    /* voltage control pin 1 */
-#define HD64461_PCCSCR_SWP             0x01    /* write protect */
-
-
-#define HD64461_P0OCR           0x1202a
-#define HD64461_P1OCR           0x1202c
-#define HD64461_PGCR            0x1202e
-
-#define HD64461_GPACR          0x14000
-#define HD64461_GPBCR          0x14002
-#define HD64461_GPCCR          0x14004
-#define HD64461_GPDCR          0x14006
-#define HD64461_GPADR          0x14010
-#define HD64461_GPBDR          0x14012
-#define HD64461_GPCDR          0x14014
-#define HD64461_GPDDR          0x14016
-#define HD64461_GPAICR         0x14020
-#define HD64461_GPBICR         0x14022
-#define HD64461_GPCICR         0x14024
-#define HD64461_GPDICR         0x14026
-#define HD64461_GPAISR         0x14040
-#define HD64461_GPBISR         0x14042
-#define HD64461_GPCISR         0x14044
-#define HD64461_GPDISR         0x14046
-
-#define HD64461_NIRR           0x15000
-#define HD64461_NIMR           0x15002
-
-#ifndef CONFIG_HD64461_IOBASE
-#define CONFIG_HD64461_IOBASE  0xb0000000
-#endif
-#ifndef CONFIG_HD64461_IRQ
-#define CONFIG_HD64461_IRQ     36
-#endif
-
-#define HD64461_IRQBASE                OFFCHIP_IRQ_BASE
-#define HD64461_IRQ_NUM        16
-
-#define HD64461_IRQ_UART       (HD64461_IRQBASE+5)
-#define HD64461_IRQ_IRDA       (HD64461_IRQBASE+6)
-#define HD64461_IRQ_TMU1       (HD64461_IRQBASE+9)
-#define HD64461_IRQ_TMU0       (HD64461_IRQBASE+10)
-#define HD64461_IRQ_GPIO       (HD64461_IRQBASE+11)
-#define HD64461_IRQ_AFE        (HD64461_IRQBASE+12)
-#define HD64461_IRQ_PCC1       (HD64461_IRQBASE+13)
-#define HD64461_IRQ_PCC0       (HD64461_IRQBASE+14)
-
-#endif
diff --git a/include/asm-sh/hd64461/io.h b/include/asm-sh/hd64461/io.h
deleted file mode 100644 (file)
index 67f2489..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * include/asm-sh/io_hd64461.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an HD64461
- */
-
-#ifndef _ASM_SH_IO_HD64461_H
-#define _ASM_SH_IO_HD64461_H
-
-extern unsigned char hd64461_inb(unsigned long port);
-extern unsigned short hd64461_inw(unsigned long port);
-extern unsigned int hd64461_inl(unsigned long port);
-
-extern void hd64461_outb(unsigned char value, unsigned long port);
-extern void hd64461_outw(unsigned short value, unsigned long port);
-extern void hd64461_outl(unsigned int value, unsigned long port);
-
-extern unsigned char hd64461_inb_p(unsigned long port);
-extern void hd64461_outb_p(unsigned char value, unsigned long port);
-
-extern void hd64461_insb(unsigned long port, void *addr, unsigned long count);
-extern void hd64461_insw(unsigned long port, void *addr, unsigned long count);
-extern void hd64461_insl(unsigned long port, void *addr, unsigned long count);
-
-extern void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count);
-extern void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count);
-extern void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count);
-
-extern unsigned short hd64461_readw(unsigned long addr);
-extern void hd64461_writew(unsigned short b, unsigned long addr);
-
-
-extern int hd64461_irq_demux(int irq);
-extern void hd64461_register_irq_demux(int irq,
-               int (*demux)(int irq, void *dev), void *dev);
-extern void hd64461_unregister_irq_demux(int irq);
-
-#endif /* _ASM_SH_IO_HD64461_H */
index a26247fd3d87ca744ca0d91ae451808a9b242cc9..f35134c159dd103aec724d75d61be8f923fda357 100644 (file)
@@ -2,16 +2,33 @@
 #define __ASM_SH_HP6XX_H
 
 /*
- * Copyright (C) 2003  Andriy Skulysh
+ * Copyright (C) 2003, 2004, 2005  Andriy Skulysh
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
  */
 
-#define HP680_TS_IRQ IRQ3_IRQ
+#define HP680_BTN_IRQ          IRQ0_IRQ
+#define HP680_TS_IRQ           IRQ3_IRQ
+#define HP680_HD64461_IRQ      IRQ4_IRQ
 
 #define DAC_LCD_BRIGHTNESS     0
 #define DAC_SPEAKER_VOLUME     1
 
+#define PGDR_OPENED            0x01
+#define PGDR_MAIN_BATTERY_OUT  0x04
+#define PGDR_PLAY_BUTTON       0x08
+#define PGDR_REWIND_BUTTON     0x10
+#define PGDR_RECORD_BUTTON     0x20
+
 #define PHDR_TS_PEN_DOWN       0x08
 
+#define PJDR_LED_BLINK         0x02
+
+#define PKDR_LED_GREEN         0x10
+
 #define SCPDR_TS_SCAN_ENABLE   0x20
 #define SCPDR_TS_SCAN_Y                0x02
 #define SCPDR_TS_SCAN_X                0x01
 
 #define ADC_CHANNEL_TS_Y       1
 #define ADC_CHANNEL_TS_X       2
+#define ADC_CHANNEL_BATTERY    3
+#define ADC_CHANNEL_BACKUP     4
+#define ADC_CHANNEL_CHARGE     5
 
 #define HD64461_GPADR_SPEAKER  0x01
 #define HD64461_GPADR_PCMCIA0  (0x02|0x08)
+
 #define HD64461_GPBDR_LCDOFF   0x01
+#define HD64461_GPBDR_LCD_CONTRAST_MASK        0x78
 #define HD64461_GPBDR_LED_RED  0x80
 
+#include <asm/hd64461.h>
+#include <asm/io.h>
+
+#define PJDR   0xa4000130
+#define PKDR   0xa4000132
+
+static inline void hp6xx_led_red(int on)
+{
+       u16 v16;
+       v16 = ctrl_inw(CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000);
+       if (on)
+           ctrl_outw(v16 & (~HD64461_GPBDR_LED_RED), CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000);
+       else
+           ctrl_outw(v16 | HD64461_GPBDR_LED_RED, CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000);
+}
+
+static inline void hp6xx_led_green(int on)
+{
+       u8 v8;
+
+       v8 = ctrl_inb(PKDR);
+       if (on)
+           ctrl_outb(v8 & (~PKDR_LED_GREEN), PKDR);
+       else
+           ctrl_outb(v8 | PKDR_LED_GREEN, PKDR);
+}
+
 
 #endif /* __ASM_SH_HP6XX_H */
index 7317980035503c0690ccf20eb561fa644b248da9..2044476ab199ea2952cdee71831a4617254f648b 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * Nothing special here.. just use the generic cchip io routines.
  */
-#include <asm/hd64461/io.h>
+#include <asm/hd64461.h>
 
 #endif /* __ASM_SH_HP6XX_IO_H */
 
index 5f995f937a441dc207f1d88960077752b2604444..c4cff9d33927d95bfe234487b01b8cb4caecc9df 100644 (file)
@@ -19,8 +19,6 @@
 #define PA_OUTPORTR    0xa400000e      /* Output Port Reguster */
 #define PA_VERREG      0xa4000014      /* FPGA Version Register */
 
-#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
-#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
 #define PA_IDE_OFFSET  0x1f0           /* CF IDE Offset */
 
 #define IRLCNTR1       (PA_BCR + 0)    /* Interrupt Control Register1 */
 #define        IRQ_RINGING     4               /* Ringing IRQ */
 #define        IRQ_CODEC       5               /* CODEC IRQ */
 
+#define __IO_PREFIX    hs7751rvoip
+#include <asm/io_generic.h>
+
+/* arch/sh/boards/renesas/hs7751rvoip/irq.c */
+void init_hs7751rvoip_IRQ(void);
+
+/* arch/sh/boards/renesas/hs7751rvoip/io.c */
+void *hs7751rvoip_ioremap(unsigned long, unsigned long);
+
 #endif  /* __ASM_SH_RENESAS_HS7751RVOIP */
index 894e64b2d5f0a0f066c50f2fca4a9dc554f172dd..ed12d38e8c0082dda8db85613bf578f4819e3ef9 100644 (file)
 #define __raw_writew(v, a)     __writew(v, (void __iomem *)(a))
 #define __raw_writel(v, a)     __writel(v, (void __iomem *)(a))
 
+void __raw_writesl(unsigned long addr, const void *data, int longlen);
+void __raw_readsl(unsigned long addr, void *data, int longlen);
+
 /*
  * The platform header files may define some of these macros to use
  * the inlined versions where appropriate.  These macros may also be
 # define writel(v,a)   ({ __raw_writel((v),(a)); mb(); })
 #endif
 
+#define writesl __raw_writesl
+#define readsl  __raw_readsl
+
 #define readb_relaxed(a) readb(a)
 #define readw_relaxed(a) readw(a)
 #define readl_relaxed(a) readl(a)
@@ -209,8 +215,14 @@ static inline void ctrl_outl(unsigned int b, unsigned long addr)
         *(volatile unsigned long*)addr = b;
 }
 
+static inline void ctrl_delay(void)
+{
+       ctrl_inw(P2SEG);
+}
+
 #define IO_SPACE_LIMIT 0xffffffff
 
+#ifdef CONFIG_MMU
 /*
  * Change virtual addresses to physical addresses and vv.
  * These are trivial on the 1:1 Linux/SuperH mapping
@@ -224,6 +236,10 @@ static inline void *phys_to_virt(unsigned long address)
 {
        return (void *)P1SEGADDR(address);
 }
+#else
+#define phys_to_virt(address)  ((void *)(address))
+#define virt_to_phys(address)  ((unsigned long)(address))
+#endif
 
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
index d705252be260018902a68df8464b1730f7f0cdc9..b28af9a69d728d7dbc074f10bac3b91de9481845 100644 (file)
 #define IRQ6_PRIORITY  1
 #define IRQ7_PRIORITY  1
 
-int shmse_irq_demux(int irq);
-
 #endif /* __ASM_SH_IRQ_SH73180_H */
diff --git a/include/asm-sh/irq-sh7343.h b/include/asm-sh/irq-sh7343.h
new file mode 100644 (file)
index 0000000..5d15419
--- /dev/null
@@ -0,0 +1,317 @@
+#ifndef __ASM_SH_IRQ_SH7343_H
+#define __ASM_SH_IRQ_SH7343_H
+
+/*
+ * linux/include/asm-sh/irq-sh7343.h
+ *
+ * Copyright (C) 2006 Kenati Technologies Inc.
+ * Andre Mccurdy <andre@kenati.com>
+ * Ranjit Deshpande <ranjit@kenati.com>
+ */
+
+#undef INTC_IPRA
+#undef INTC_IPRB
+#undef INTC_IPRC
+#undef INTC_IPRD
+
+#undef DMTE0_IRQ
+#undef DMTE1_IRQ
+#undef DMTE2_IRQ
+#undef DMTE3_IRQ
+#undef DMTE4_IRQ
+#undef DMTE5_IRQ
+#undef DMTE6_IRQ
+#undef DMTE7_IRQ
+#undef DMAE_IRQ
+#undef DMA_IPR_ADDR
+#undef DMA_IPR_POS
+#undef DMA_PRIORITY
+
+#undef INTC_IMCR0
+#undef INTC_IMCR1
+#undef INTC_IMCR2
+#undef INTC_IMCR3
+#undef INTC_IMCR4
+#undef INTC_IMCR5
+#undef INTC_IMCR6
+#undef INTC_IMCR7
+#undef INTC_IMCR8
+#undef INTC_IMCR9
+#undef INTC_IMCR10
+
+
+#define INTC_IPRA      0xA4080000UL
+#define INTC_IPRB      0xA4080004UL
+#define INTC_IPRC      0xA4080008UL
+#define INTC_IPRD      0xA408000CUL
+#define INTC_IPRE      0xA4080010UL
+#define INTC_IPRF      0xA4080014UL
+#define INTC_IPRG      0xA4080018UL
+#define INTC_IPRH      0xA408001CUL
+#define INTC_IPRI      0xA4080020UL
+#define INTC_IPRJ      0xA4080024UL
+#define INTC_IPRK      0xA4080028UL
+#define INTC_IPRL      0xA408002CUL
+
+#define INTC_IMR0      0xA4080080UL
+#define INTC_IMR1      0xA4080084UL
+#define INTC_IMR2      0xA4080088UL
+#define INTC_IMR3      0xA408008CUL
+#define INTC_IMR4      0xA4080090UL
+#define INTC_IMR5      0xA4080094UL
+#define INTC_IMR6      0xA4080098UL
+#define INTC_IMR7      0xA408009CUL
+#define INTC_IMR8      0xA40800A0UL
+#define INTC_IMR9      0xA40800A4UL
+#define INTC_IMR10     0xA40800A8UL
+#define INTC_IMR11     0xA40800ACUL
+
+#define INTC_IMCR0     0xA40800C0UL
+#define INTC_IMCR1     0xA40800C4UL
+#define INTC_IMCR2     0xA40800C8UL
+#define INTC_IMCR3     0xA40800CCUL
+#define INTC_IMCR4     0xA40800D0UL
+#define INTC_IMCR5     0xA40800D4UL
+#define INTC_IMCR6     0xA40800D8UL
+#define INTC_IMCR7     0xA40800DCUL
+#define INTC_IMCR8     0xA40800E0UL
+#define INTC_IMCR9     0xA40800E4UL
+#define INTC_IMCR10    0xA40800E8UL
+#define INTC_IMCR11    0xA40800ECUL
+
+#define INTC_ICR0      0xA4140000UL
+#define INTC_ICR1      0xA414001CUL
+
+#define INTMSK0                0xa4140044
+#define INTMSKCLR0     0xa4140064
+#define INTC_INTPRI0   0xa4140010
+
+/*
+  NOTE:
+
+  *_IRQ = (INTEVT2 - 0x200)/0x20
+*/
+
+/* TMU0 */
+#define TMU0_IRQ       16
+#define TMU0_IPR_ADDR  INTC_IPRA
+#define TMU0_IPR_POS    3
+#define TMU0_PRIORITY   2
+
+#define TIMER_IRQ       16
+#define TIMER_IPR_ADDR  INTC_IPRA
+#define TIMER_IPR_POS    3
+#define TIMER_PRIORITY   2
+
+/* TMU1 */
+#define TMU1_IRQ       17
+#define TMU1_IPR_ADDR  INTC_IPRA
+#define TMU1_IPR_POS    2
+#define TMU1_PRIORITY   2
+
+/* TMU2 */
+#define TMU2_IRQ       18
+#define TMU2_IPR_ADDR  INTC_IPRA
+#define TMU2_IPR_POS    1
+#define TMU2_PRIORITY   2
+
+/* LCDC */
+#define LCDC_IRQ       28
+#define LCDC_IPR_ADDR  INTC_IPRB
+#define LCDC_IPR_POS    2
+#define LCDC_PRIORITY   2
+
+/* VIO (Video I/O) */
+#define CEU_IRQ                52
+#define BEU_IRQ                53
+#define VEU_IRQ                54
+#define VOU_IRQ                55
+#define VIO_IPR_ADDR   INTC_IPRE
+#define VIO_IPR_POS     2
+#define VIO_PRIORITY    2
+
+/* MFI (Multi Functional Interface) */
+#define MFI_IRQ                56
+#define MFI_IPR_ADDR   INTC_IPRE
+#define MFI_IPR_POS     1
+#define MFI_PRIORITY    2
+
+/* VPU (Video Processing Unit) */
+#define VPU_IRQ                60
+#define VPU_IPR_ADDR   INTC_IPRE
+#define VPU_IPR_POS     0
+#define VPU_PRIORITY    2
+
+/* 3DG */
+#define TDG_IRQ                63
+#define TDG_IPR_ADDR   INTC_IPRJ
+#define TDG_IPR_POS     2
+#define TDG_PRIORITY    2
+
+/* DMAC(1) */
+#define DMTE0_IRQ      48
+#define DMTE1_IRQ      49
+#define DMTE2_IRQ      50
+#define DMTE3_IRQ      51
+#define DMA1_IPR_ADDR  INTC_IPRE
+#define DMA1_IPR_POS   3
+#define DMA1_PRIORITY  7
+
+/* DMAC(2) */
+#define DMTE4_IRQ      76
+#define DMTE5_IRQ      77
+#define DMA2_IPR_ADDR  INTC_IPRF
+#define DMA2_IPR_POS   2
+#define DMA2_PRIORITY  7
+
+/* SCIF0 */
+#define SCIF_ERI_IRQ   80
+#define SCIF_RXI_IRQ   81
+#define SCIF_BRI_IRQ   82
+#define SCIF_TXI_IRQ   83
+#define SCIF_IPR_ADDR  INTC_IPRG
+#define SCIF_IPR_POS   3
+#define SCIF_PRIORITY  3
+
+/* SIOF0 */
+#define SIOF0_IRQ      84
+#define SIOF0_IPR_ADDR INTC_IPRH
+#define SIOF0_IPR_POS  3
+#define SIOF0_PRIORITY 3
+
+/* FLCTL (Flash Memory Controller) */
+#define FLSTE_IRQ      92
+#define FLTEND_IRQ     93
+#define FLTRQ0_IRQ     94
+#define FLTRQ1_IRQ     95
+#define FLCTL_IPR_ADDR INTC_IPRH
+#define FLCTL_IPR_POS  1
+#define FLCTL_PRIORITY 3
+
+/* IIC(0) (IIC Bus Interface) */
+#define IIC0_ALI_IRQ   96
+#define IIC0_TACKI_IRQ 97
+#define IIC0_WAITI_IRQ 98
+#define IIC0_DTEI_IRQ  99
+#define IIC0_IPR_ADDR  INTC_IPRH
+#define IIC0_IPR_POS   0
+#define IIC0_PRIORITY  3
+
+/* IIC(1) (IIC Bus Interface) */
+#define IIC1_ALI_IRQ   44
+#define IIC1_TACKI_IRQ 45
+#define IIC1_WAITI_IRQ 46
+#define IIC1_DTEI_IRQ  47
+#define IIC1_IPR_ADDR  INTC_IPRI
+#define IIC1_IPR_POS   0
+#define IIC1_PRIORITY  3
+
+/* SIO0 */
+#define SIO0_IRQ       88
+#define SIO0_IPR_ADDR  INTC_IPRI
+#define SIO0_IPR_POS   3
+#define SIO0_PRIORITY  3
+
+/* SDHI */
+#define SDHI_SDHII0_IRQ        100
+#define SDHI_SDHII1_IRQ        101
+#define SDHI_SDHII2_IRQ        102
+#define SDHI_SDHII3_IRQ        103
+#define SDHI_IPR_ADDR  INTC_IPRK
+#define SDHI_IPR_POS   0
+#define SDHI_PRIORITY  3
+
+/* SIU (Sound Interface Unit) */
+#define SIU_IRQ                108
+#define SIU_IPR_ADDR   INTC_IPRJ
+#define SIU_IPR_POS    1
+#define SIU_PRIORITY   3
+
+#define PORT_PACR      0xA4050100UL
+#define PORT_PBCR      0xA4050102UL
+#define PORT_PCCR      0xA4050104UL
+#define PORT_PDCR      0xA4050106UL
+#define PORT_PECR      0xA4050108UL
+#define PORT_PFCR      0xA405010AUL
+#define PORT_PGCR      0xA405010CUL
+#define PORT_PHCR      0xA405010EUL
+#define PORT_PJCR      0xA4050110UL
+#define PORT_PKCR      0xA4050112UL
+#define PORT_PLCR      0xA4050114UL
+#define PORT_SCPCR     0xA4050116UL
+#define PORT_PMCR      0xA4050118UL
+#define PORT_PNCR      0xA405011AUL
+#define PORT_PQCR      0xA405011CUL
+#define PORT_PRCR      0xA405011EUL
+#define PORT_PTCR      0xA405014CUL
+#define PORT_PUCR      0xA405014EUL
+#define PORT_PVCR      0xA4050150UL
+
+#define PORT_PSELA     0xA4050140UL
+#define PORT_PSELB     0xA4050142UL
+#define PORT_PSELC     0xA4050144UL
+#define PORT_PSELE     0xA4050158UL
+
+#define PORT_HIZCRA    0xA4050146UL
+#define PORT_HIZCRB    0xA4050148UL
+#define PORT_DRVCR     0xA405014AUL
+
+#define PORT_PADR      0xA4050120UL
+#define PORT_PBDR      0xA4050122UL
+#define PORT_PCDR      0xA4050124UL
+#define PORT_PDDR      0xA4050126UL
+#define PORT_PEDR      0xA4050128UL
+#define PORT_PFDR      0xA405012AUL
+#define PORT_PGDR      0xA405012CUL
+#define PORT_PHDR      0xA405012EUL
+#define PORT_PJDR      0xA4050130UL
+#define PORT_PKDR      0xA4050132UL
+#define PORT_PLDR      0xA4050134UL
+#define PORT_SCPDR     0xA4050136UL
+#define PORT_PMDR      0xA4050138UL
+#define PORT_PNDR      0xA405013AUL
+#define PORT_PQDR      0xA405013CUL
+#define PORT_PRDR      0xA405013EUL
+#define PORT_PTDR      0xA405016CUL
+#define PORT_PUDR      0xA405016EUL
+#define PORT_PVDR      0xA4050170UL
+
+#define IRQ0_IRQ       32
+#define IRQ1_IRQ       33
+#define IRQ2_IRQ       34
+#define IRQ3_IRQ       35
+#define IRQ4_IRQ       36
+#define IRQ5_IRQ       37
+#define IRQ6_IRQ       38
+#define IRQ7_IRQ       39
+
+#define INTPRI00       0xA4140010UL
+
+#define IRQ0_IPR_ADDR  INTPRI00
+#define IRQ1_IPR_ADDR  INTPRI00
+#define IRQ2_IPR_ADDR  INTPRI00
+#define IRQ3_IPR_ADDR  INTPRI00
+#define IRQ4_IPR_ADDR  INTPRI00
+#define IRQ5_IPR_ADDR  INTPRI00
+#define IRQ6_IPR_ADDR  INTPRI00
+#define IRQ7_IPR_ADDR  INTPRI00
+
+#define IRQ0_IPR_POS   7
+#define IRQ1_IPR_POS   6
+#define IRQ2_IPR_POS   5
+#define IRQ3_IPR_POS   4
+#define IRQ4_IPR_POS   3
+#define IRQ5_IPR_POS   2
+#define IRQ6_IPR_POS   1
+#define IRQ7_IPR_POS   0
+
+#define IRQ0_PRIORITY  1
+#define IRQ1_PRIORITY  1
+#define IRQ2_PRIORITY  1
+#define IRQ3_PRIORITY  1
+#define IRQ4_PRIORITY  1
+#define IRQ5_PRIORITY  1
+#define IRQ6_PRIORITY  1
+#define IRQ7_PRIORITY  1
+
+#endif /* __ASM_SH_IRQ_SH7343_H */
index 7f90315cd8304359c9d35653fb9709822c3c8ef1..895c5780e45473150ad02217a860e254b7fac648 100644 (file)
 #define        TMU_CH5_IPR_POS         1
 #define TMU_CH5_PRIORITY       2
 
-#define        RTC_IRQ         22
-#define        RTC_IPR_ADDR    INTC_INT2PRI1
-#define        RTC_IPR_POS     0
-#define        RTC_PRIORITY    TIMER_PRIORITY
-
 /* SCIF0 */
 #define SCIF0_ERI_IRQ  40
 #define SCIF0_RXI_IRQ  41
index 611e67cd062728bf08726717ee3ec96858eaf057..0e5f365aff70a63e2f2e639101e5b46e26708ce7 100644 (file)
 
 #if defined (CONFIG_CPU_SUBTYPE_SH7707) || defined (CONFIG_CPU_SUBTYPE_SH7708) || \
     defined (CONFIG_CPU_SUBTYPE_SH7709) || defined (CONFIG_CPU_SUBTYPE_SH7750) || \
-    defined (CONFIG_CPU_SUBTYPE_SH7751)
+    defined (CONFIG_CPU_SUBTYPE_SH7751) || defined (CONFIG_CPU_SUBTYPE_SH7706)
 #define SCI_ERI_IRQ    23
 #define SCI_RXI_IRQ    24
 #define SCI_TXI_IRQ    25
 #define SCIF0_IPR_POS  3
 #define SCIF0_PRIORITY 3
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
       defined(CONFIG_CPU_SUBTYPE_SH7707) || \
       defined(CONFIG_CPU_SUBTYPE_SH7709)
 #define SCIF_ERI_IRQ   56
 #elif defined(CONFIG_CPU_SUBTYPE_SH7708)
 # define ONCHIP_NR_IRQS 32
 #elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
       defined(CONFIG_CPU_SUBTYPE_SH7705)
 # define ONCHIP_NR_IRQS 64     // Actually 61
 # define PINT_NR_IRQS   16
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+# define ONCHIP_NR_IRQS 104
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750)
 # define ONCHIP_NR_IRQS 48     // Actually 44
 #elif defined(CONFIG_CPU_SUBTYPE_SH7751)
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 # define ONCHIP_NR_IRQS 144
 #elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-      defined(CONFIG_CPU_SUBTYPE_SH73180)
+      defined(CONFIG_CPU_SUBTYPE_SH73180) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7343)
 # define ONCHIP_NR_IRQS 109
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define ONCHIP_NR_IRQS 111
 # define OFFCHIP_NR_IRQS 4
 #elif defined(CONFIG_SH_R7780RP)
 # define OFFCHIP_NR_IRQS 16
+#elif defined(CONFIG_SH_7343_SOLUTION_ENGINE)
+# define OFFCHIP_NR_IRQS 12
 #elif defined(CONFIG_SH_UNKNOWN)
 # define OFFCHIP_NR_IRQS 16    /* Must also be last */
 #else
@@ -334,6 +341,11 @@ extern void enable_irq(unsigned int);
 extern void make_maskreg_irq(unsigned int irq);
 extern unsigned short *irq_mask_register;
 
+/*
+ * PINT IRQs
+ */
+void init_IRQ_pint(void);
+
 /*
  * Function for "on chip support modules".
  */
@@ -471,8 +483,10 @@ extern int ipr_irq_demux(int irq);
 
 #define INTC_ICR       0xfffffee0UL
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
       defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7709)
+      defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define INTC_IRR0      0xa4000004UL
 #define INTC_IRR1      0xa4000006UL
 #define INTC_IRR2      0xa4000008UL
@@ -491,8 +505,105 @@ extern int ipr_irq_demux(int irq);
 #define INTC_IPRF      0xa4080000UL
 #define INTC_IPRG      0xa4080002UL
 #define INTC_IPRH      0xa4080004UL
-#endif
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+/* Interrupt Controller Registers */
+#undef INTC_IPRA
+#undef INTC_IPRB
+#define INTC_IPRA      0xA414FEE2UL
+#define INTC_IPRB      0xA414FEE4UL
+#define INTC_IPRF      0xA4080000UL
+#define INTC_IPRG      0xA4080002UL
+#define INTC_IPRH      0xA4080004UL
+#define INTC_IPRI      0xA4080006UL
+
+#undef INTC_ICR0
+#undef INTC_ICR1
+#define INTC_ICR0      0xA414FEE0UL
+#define INTC_ICR1      0xA4140010UL
+
+#define INTC_IRR0      0xa4000004UL
+#define INTC_IRR1      0xa4000006UL
+#define INTC_IRR2      0xa4000008UL
+#define INTC_IRR3      0xa400000AUL
+#define INTC_IRR4      0xa400000CUL
+#define INTC_IRR5      0xa4080020UL
+#define INTC_IRR7      0xa4080024UL
+#define INTC_IRR8      0xa4080026UL
+
+/* Interrupt numbers */
+#define TIMER2_IRQ      18
+#define TIMER2_IPR_ADDR INTC_IPRA
+#define TIMER2_IPR_POS   1
+#define TIMER2_PRIORITY  2
+
+/* WDT */
+#define WDT_IRQ                27
+#define WDT_IPR_ADDR   INTC_IPRB
+#define WDT_IPR_POS     3
+#define WDT_PRIORITY    2
+
+#define SCIF0_ERI_IRQ  52
+#define SCIF0_RXI_IRQ  53
+#define SCIF0_BRI_IRQ  54
+#define SCIF0_TXI_IRQ  55
+#define SCIF0_IPR_ADDR INTC_IPRE
+#define SCIF0_IPR_POS  2
+#define SCIF0_PRIORITY 3
+
+#define DMTE4_IRQ      76
+#define DMTE5_IRQ      77
+#define DMA2_IPR_ADDR  INTC_IPRF
+#define DMA2_IPR_POS   2
+#define DMA2_PRIORITY  7
 
+#define IPSEC_IRQ      79
+#define IPSEC_IPR_ADDR INTC_IPRF
+#define IPSEC_IPR_POS  3
+#define IPSEC_PRIORITY 3
+
+/* EDMAC */
+#define EDMAC0_IRQ     80
+#define EDMAC0_IPR_ADDR        INTC_IPRG
+#define EDMAC0_IPR_POS 3
+#define EDMAC0_PRIORITY        3
+
+#define EDMAC1_IRQ     81
+#define EDMAC1_IPR_ADDR        INTC_IPRG
+#define EDMAC1_IPR_POS 2
+#define EDMAC1_PRIORITY        3
+
+#define EDMAC2_IRQ     82
+#define EDMAC2_IPR_ADDR        INTC_IPRG
+#define EDMAC2_IPR_POS 1
+#define EDMAC2_PRIORITY        3
+
+/* SIOF */
+#define SIOF0_ERI_IRQ  96
+#define SIOF0_TXI_IRQ  97
+#define SIOF0_RXI_IRQ  98
+#define SIOF0_CCI_IRQ  99
+#define SIOF0_IPR_ADDR INTC_IPRH
+#define SIOF0_IPR_POS  0
+#define SIOF0_PRIORITY 7
+
+#define SIOF1_ERI_IRQ  100
+#define SIOF1_TXI_IRQ  101
+#define SIOF1_RXI_IRQ  102
+#define SIOF1_CCI_IRQ  103
+#define SIOF1_IPR_ADDR INTC_IPRI
+#define SIOF1_IPR_POS  1
+#define SIOF1_PRIORITY 7
+#endif /* CONFIG_CPU_SUBTYPE_SH7710 */
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define PORT_PACR      0xa4050100UL
+#define PORT_PBCR      0xa4050102UL
+#define PORT_PCCR      0xa4050104UL
+#define PORT_PETCR     0xa4050106UL
+#define PORT_PADR      0xa4050120UL
+#define PORT_PBDR      0xa4050122UL
+#define PORT_PCDR      0xa4050124UL
+#else
 #define PORT_PACR      0xa4000100UL
 #define PORT_PBCR      0xa4000102UL
 #define PORT_PCCR      0xa4000104UL
@@ -501,6 +612,7 @@ extern int ipr_irq_demux(int irq);
 #define PORT_PBDR      0xa4000122UL
 #define PORT_PCDR      0xa4000124UL
 #define PORT_PFDR      0xa400012aUL
+#endif
 
 #define IRQ0_IRQ       32
 #define IRQ1_IRQ       33
@@ -577,7 +689,7 @@ extern int ipr_irq_demux(int irq);
 #define NR_INTC2_IRQS  64
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define INTC2_BASE     0xffd40000
-#define INTC2_FIRST_IRQ        22
+#define INTC2_FIRST_IRQ        21
 #define INTC2_INTMSK_OFFSET    (0x38)
 #define INTC2_INTMSKCLR_OFFSET (0x3c)
 #define NR_INTC2_IRQS  60
@@ -594,6 +706,8 @@ void intc2_add_clear_irq(int irq, int (*fn)(int));
 
 #endif
 
+extern int shmse_irq_demux(int irq);
+
 static inline int generic_irq_demux(int irq)
 {
        return irq;
@@ -605,8 +719,21 @@ static inline int generic_irq_demux(int irq)
 #define irq_canonicalize(irq)  (irq)
 #define irq_demux(irq)         __irq_demux(sh_mv.mv_irq_demux(irq))
 
+#ifdef CONFIG_4KSTACKS
+extern void irq_ctx_init(int cpu);
+extern void irq_ctx_exit(int cpu);
+# define __ARCH_HAS_DO_SOFTIRQ
+#else
+# define irq_ctx_init(cpu) do { } while (0)
+# define irq_ctx_exit(cpu) do { } while (0)
+#endif
+
 #if defined(CONFIG_CPU_SUBTYPE_SH73180)
 #include <asm/irq-sh73180.h>
 #endif
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7343)
+#include <asm/irq-sh7343.h>
+#endif
+
 #endif /* __ASM_SH_IRQ_H */
index 9dfe59f6fcb5c01a6ac2bc20ef6da871c31c04c9..9d235af20cdd551136beefd6968e72e4984c0f5b 100644 (file)
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_SH
 
-#ifndef __ASSEMBLY__
+#define MAX_NOTE_BYTES 1024
 
-extern void machine_shutdown(void);
-extern void *crash_notes;
-
-#endif /* __ASSEMBLY__ */
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                       struct pt_regs *oldregs) { }
 
 #endif /* _SH_KEXEC_H */
index 1653ffb75fbe75f857aebee1ad645b69f1d45446..7b26f53fe343f5711f97bbecdec0dd563be36ba6 100644 (file)
@@ -128,4 +128,19 @@ extern int     setjmp(jmp_buf __jmpb);
 #define KGDB_ASSERT(condition, message)
 #endif
 
+/* Taken from sh-stub.c of GDB 4.18 */
+static const char hexchars[] = "0123456789abcdef";
+
+/* Get high hex bits */
+static inline char highhex(const int x)
+{
+       return hexchars[(x >> 4) & 0xf];
+}
+
+/* Get low hex bits */
+static inline char lowhex(const int x)
+{
+       return hexchars[x & 0xf];
+}
+
 #endif
diff --git a/include/asm-sh/landisk/gio.h b/include/asm-sh/landisk/gio.h
new file mode 100644 (file)
index 0000000..3fce4c4
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __ASM_SH_LANDISK_GIO_H
+#define __ASM_SH_LANDISK_GIO_H
+
+#include <linux/ioctl.h>
+
+/* version */
+#define VERSION_STR    "1.00"
+
+/* Driver name */
+#define GIO_DRIVER_NAME                "/dev/giodrv"
+
+/* Use 'k' as magic number */
+#define GIODRV_IOC_MAGIC  'k'
+
+#define GIODRV_IOCRESET    _IO(GIODRV_IOC_MAGIC, 0)
+/*
+ * S means "Set" through a ptr,
+ * T means "Tell" directly
+ * G means "Get" (to a pointed var)
+ * Q means "Query", response is on the return value
+ * X means "eXchange": G and S atomically
+ * H means "sHift": T and Q atomically
+ */
+#define GIODRV_IOCSGIODATA1   _IOW(GIODRV_IOC_MAGIC,  1, unsigned char *)
+#define GIODRV_IOCGGIODATA1   _IOR(GIODRV_IOC_MAGIC,  2, unsigned char *)
+#define GIODRV_IOCSGIODATA2   _IOW(GIODRV_IOC_MAGIC,  3, unsigned short *)
+#define GIODRV_IOCGGIODATA2   _IOR(GIODRV_IOC_MAGIC,  4, unsigned short *)
+#define GIODRV_IOCSGIODATA4   _IOW(GIODRV_IOC_MAGIC,  5, unsigned long *)
+#define GIODRV_IOCGGIODATA4   _IOR(GIODRV_IOC_MAGIC,  6, unsigned long *)
+#define GIODRV_IOCSGIOSETADDR _IOW(GIODRV_IOC_MAGIC,  7, unsigned long *)
+#define GIODRV_IOCHARDRESET   _IO(GIODRV_IOC_MAGIC, 8) /* debugging tool */
+
+#define GIODRV_IOCSGIO_LED    _IOW(GIODRV_IOC_MAGIC,  9, unsigned long *)
+#define GIODRV_IOCGGIO_LED    _IOR(GIODRV_IOC_MAGIC,  10, unsigned long *)
+#define GIODRV_IOCSGIO_BUZZER _IOW(GIODRV_IOC_MAGIC,  11, unsigned long *)
+#define GIODRV_IOCGGIO_LANDISK _IOR(GIODRV_IOC_MAGIC,  14, unsigned long *)
+#define GIODRV_IOCGGIO_BTN _IOR(GIODRV_IOC_MAGIC,  22, unsigned long *)
+#define GIODRV_IOCSGIO_BTNPID _IOW(GIODRV_IOC_MAGIC,  23, unsigned long *)
+#define GIODRV_IOCGGIO_BTNPID _IOR(GIODRV_IOC_MAGIC,  24, unsigned long *)
+
+#define GIODRV_IOC_MAXNR 8
+#define GIO_READ 0x00000000
+#define GIO_WRITE 0x00000001
+
+#endif /* __ASM_SH_LANDISK_GIO_H  */
diff --git a/include/asm-sh/landisk/ide.h b/include/asm-sh/landisk/ide.h
new file mode 100644 (file)
index 0000000..6490e28
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * modifed by kogiidena
+ * 2005.03.03
+ */
+
+#ifndef __ASM_SH_LANDISK_IDE_H
+#define __ASM_SH_LANDISK_IDE_H
+
+/* Nothing to see here.. */
+#include <asm/landisk/iodata_landisk.h>
+#define IRQ_CFCARD     IRQ_FATA        /* CF Card IRQ */
+#define IRQ_PCMCIA     IRQ_ATA         /* PCMCIA IRQ */
+
+#endif /* __ASM_SH_LANDISK_IDE_H  */
diff --git a/include/asm-sh/landisk/iodata_landisk.h b/include/asm-sh/landisk/iodata_landisk.h
new file mode 100644 (file)
index 0000000..c74d3c7
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __ASM_SH_IODATA_LANDISK_H
+#define __ASM_SH_IODATA_LANDISK_H
+
+/*
+ * linux/include/asm-sh/landisk/iodata_landisk.h
+ *
+ * Copyright (C) 2000  Atom Create Engineering Co., Ltd.
+ *
+ * IO-DATA LANDISK support
+ */
+
+/* Box specific addresses.  */
+
+#define PA_USB         0xa4000000      /* USB Controller M66590 */
+
+#define PA_ATARST      0xb0000000      /* ATA/FATA Access Control Register */
+#define PA_LED         0xb0000001      /* LED Control Register */
+#define PA_STATUS      0xb0000002      /* Switch Status Register */
+#define PA_SHUTDOWN    0xb0000003      /* Shutdown Control Register */
+#define PA_PCIPME      0xb0000004      /* PCI PME Status Register */
+#define PA_IMASK       0xb0000005      /* Interrupt Mask Register */
+/* 2003.10.31 I-O DATA NSD NWG add.    for shutdown port clear */
+#define PA_PWRINT_CLR  0xb0000006      /* Shutdown Interrupt clear Register */
+
+#define PA_LCD_CLRDSP  0x00            /* LCD Clear Display Offset */
+#define PA_LCD_RTNHOME 0x00            /* LCD Return Home Offset */
+#define PA_LCD_ENTMODE 0x00            /* LCD Entry Mode Offset */
+#define PA_LCD_DSPCTL  0x00            /* LCD Display ON/OFF Control Offset */
+#define PA_LCD_FUNC    0x00            /* LCD Function Set Offset */
+#define PA_LCD_CGRAM   0x00            /* LCD Set CGRAM Address Offset */
+#define PA_LCD_DDRAM   0x00            /* LCD Set DDRAM Address Offset */
+#define PA_LCD_RDFLAG  0x01            /* LCD Read Busy Flag Offset */
+#define PA_LCD_WTDATA  0x02            /* LCD Write Datat to RAM Offset */
+#define PA_LCD_RDDATA  0x03            /* LCD Read Data from RAM Offset */
+#define PA_PIDE_OFFSET 0x40            /* CF IDE Offset */
+#define PA_SIDE_OFFSET 0x40            /* HDD IDE Offset */
+
+#define IRQ_PCIINTA    5               /* PCI INTA IRQ */
+#define IRQ_PCIINTB    6               /* PCI INTB IRQ */
+#define IRQ_PCIINDC    7               /* PCI INTC IRQ */
+#define IRQ_PCIINTD    8               /* PCI INTD IRQ */
+#define IRQ_ATA                9               /* ATA IRQ */
+#define IRQ_FATA       10              /* FATA IRQ */
+#define IRQ_POWER      11              /* Power Switch IRQ */
+#define IRQ_BUTTON     12              /* USL-5P Button IRQ */
+#define IRQ_FAULT      13              /* USL-5P Fault  IRQ */
+
+#define SHUTDOWN_BTN_MAJOR     99      /* Shutdown button device major no. */
+
+#define SHUTDOWN_LOOP_CNT      5       /* Shutdown button Detection loop */
+#define SHUTDOWN_DELAY         200     /* Shutdown button delay value(ms) */
+
+
+/* added by kogiidena */
+/*
+ *  landisk_ledparam
+ *
+ * led  ------10 -6543210 -6543210 -6543210
+ *     |000000..|0.......|0.......|U.......|
+ *     |  HARD  |fastblik| blink  |   on   |
+ *
+ *   led0: power       U:update flag
+ *   led1: error
+ *   led2: usb1
+ *   led3: usb2
+ *   led4: usb3
+ *   led5: usb4
+ *   led6: usb5
+ *
+ */
+extern int landisk_ledparam;    /* from setup.c */
+extern int landisk_buzzerparam; /* from setup.c */
+extern int landisk_arch;        /* from setup.c */
+
+#define __IO_PREFIX landisk
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_IODATA_LANDISK_H */
+
index 550501fa4fede12048f4a288e6880fc9311bab78..70389b72ffef9dce063f55f576aa01fa2c40bdee 100644 (file)
@@ -8,17 +8,18 @@
  */
 
 #ifndef _ASM_SH_MACHVEC_H
-#define _ASM_SH_MACHVEC_H 1
+#define _ASM_SH_MACHVEC_H
 
 #include <linux/types.h>
 #include <linux/time.h>
-
 #include <asm/machtypes.h>
 #include <asm/machvec_init.h>
 
 struct device;
 
 struct sh_machine_vector {
+       void (*mv_setup)(char **cmdline_p);
+       const char *mv_name;
        int mv_nr_irqs;
 
        u8 (*mv_inb)(unsigned long);
@@ -65,4 +66,6 @@ struct sh_machine_vector {
 
 extern struct sh_machine_vector sh_mv;
 
+#define get_system_type()      sh_mv.mv_name
+
 #endif /* _ASM_SH_MACHVEC_H */
index 1707cfb2915d04fcccf357035689881ef71d2133..0aee96a973304d0a816100b750ceda899005505f 100644 (file)
@@ -4,173 +4,4 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
-#ifdef CONFIG_SH_MPC1211
-#undef  _ASM_MC146818RTC_H
-#undef  RTC_IRQ
-#include <asm/mpc1211/mc146818rtc.h>
-#else
-
-#include <asm/rtc.h>
-
-#define RTC_ALWAYS_BCD 1
-
-/* FIXME:RTC Interrupt feature is not implemented yet. */
-#undef  RTC_IRQ
-#define RTC_IRQ                0
-
-#if defined(CONFIG_CPU_SH3)
-#define RTC_PORT(n)            (R64CNT+(n)*2)
-#define CMOS_READ(addr)                __CMOS_READ(addr,b)
-#define CMOS_WRITE(val,addr)   __CMOS_WRITE(val,addr,b)
-
-#elif defined(CONFIG_SH_SECUREEDGE5410)
-#include <asm/snapgear/io.h>
-
-#define RTC_PORT(n)             SECUREEDGE_IOPORT_ADDR
-#define CMOS_READ(addr)         secureedge5410_cmos_read(addr)
-#define CMOS_WRITE(val,addr)    secureedge5410_cmos_write(val,addr)
-extern unsigned char secureedge5410_cmos_read(int addr);
-extern void secureedge5410_cmos_write(unsigned char val, int addr);
-
-#elif defined(CONFIG_CPU_SH4)
-#define RTC_PORT(n)            (R64CNT+(n)*4)
-#define CMOS_READ(addr)                __CMOS_READ(addr,w)
-#define CMOS_WRITE(val,addr)   __CMOS_WRITE(val,addr,w)
-#endif
-
-#define __CMOS_READ(addr, s) ({                                                \
-       unsigned char val=0, rcr1, rcr2, r64cnt, retry;                 \
-       switch(addr) {                                                  \
-               case RTC_SECONDS:                                       \
-                       val = ctrl_inb(RSECCNT);                        \
-                       break;                                          \
-               case RTC_SECONDS_ALARM:                                 \
-                       val = ctrl_inb(RSECAR);                         \
-                       break;                                          \
-               case RTC_MINUTES:                                       \
-                       val = ctrl_inb(RMINCNT);                        \
-                       break;                                          \
-               case RTC_MINUTES_ALARM:                                 \
-                       val = ctrl_inb(RMINAR);                         \
-                       break;                                          \
-               case RTC_HOURS:                                         \
-                       val = ctrl_inb(RHRCNT);                         \
-                       break;                                          \
-               case RTC_HOURS_ALARM:                                   \
-                       val = ctrl_inb(RHRAR);                          \
-                       break;                                          \
-               case RTC_DAY_OF_WEEK:                                   \
-                       val = ctrl_inb(RWKCNT);                         \
-                       break;                                          \
-               case RTC_DAY_OF_MONTH:                                  \
-                       val = ctrl_inb(RDAYCNT);                        \
-                       break;                                          \
-               case RTC_MONTH:                                         \
-                       val = ctrl_inb(RMONCNT);                        \
-                       break;                                          \
-               case RTC_YEAR:                                          \
-                       val = ctrl_in##s(RYRCNT);                       \
-                       break;                                          \
-               case RTC_REG_A: /* RTC_FREQ_SELECT */                   \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       val = (rcr2 & RCR2_PESMASK) >> 4;               \
-                       rcr1 = ctrl_inb(RCR1);                          \
-                       rcr1 = (rcr1 & (RCR1_CIE | RCR1_AIE)) | RCR1_AF;\
-                       retry = 0;                                      \
-                       do {                                            \
-                               ctrl_outb(rcr1, RCR1); /* clear CF */   \
-                               r64cnt = ctrl_inb(R64CNT);              \
-                       } while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\
-                       r64cnt ^= RTC_BIT_INVERTED;                     \
-                       if(r64cnt == 0x7f || r64cnt == 0)               \
-                               val |= RTC_UIP;                         \
-                       break;                                          \
-               case RTC_REG_B: /* RTC_CONTROL */                       \
-                       rcr1 = ctrl_inb(RCR1);                          \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       if(rcr1 & RCR1_CIE)     val |= RTC_UIE;         \
-                       if(rcr1 & RCR1_AIE)     val |= RTC_AIE;         \
-                       if(rcr2 & RCR2_PESMASK) val |= RTC_PIE;         \
-                       if(!(rcr2 & RCR2_START))val |= RTC_SET;         \
-                       val |= RTC_24H;                                 \
-                       break;                                          \
-               case RTC_REG_C: /* RTC_INTR_FLAGS */                    \
-                       rcr1 = ctrl_inb(RCR1);                          \
-                       rcr1 &= ~(RCR1_CF | RCR1_AF);                   \
-                       ctrl_outb(rcr1, RCR1);                          \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       rcr2 &= ~RCR2_PEF;                              \
-                       ctrl_outb(rcr2, RCR2);                          \
-                       break;                                          \
-               case RTC_REG_D: /* RTC_VALID */                         \
-                       /* Always valid ... */                          \
-                       val = RTC_VRT;                                  \
-                       break;                                          \
-               default:                                                \
-                       break;                                          \
-       }                                                               \
-       val;                                                            \
-})
-
-#define __CMOS_WRITE(val, addr, s) ({                                  \
-       unsigned char rcr1,rcr2;                                        \
-       switch(addr) {                                                  \
-               case RTC_SECONDS:                                       \
-                       ctrl_outb(val, RSECCNT);                        \
-                       break;                                          \
-               case RTC_SECONDS_ALARM:                                 \
-                       ctrl_outb(val, RSECAR);                         \
-                       break;                                          \
-               case RTC_MINUTES:                                       \
-                       ctrl_outb(val, RMINCNT);                        \
-                       break;                                          \
-               case RTC_MINUTES_ALARM:                                 \
-                       ctrl_outb(val, RMINAR);                         \
-                       break;                                          \
-               case RTC_HOURS:                                         \
-                       ctrl_outb(val, RHRCNT);                         \
-                       break;                                          \
-               case RTC_HOURS_ALARM:                                   \
-                       ctrl_outb(val, RHRAR);                          \
-                       break;                                          \
-               case RTC_DAY_OF_WEEK:                                   \
-                       ctrl_outb(val, RWKCNT);                         \
-                       break;                                          \
-               case RTC_DAY_OF_MONTH:                                  \
-                       ctrl_outb(val, RDAYCNT);                        \
-                       break;                                          \
-               case RTC_MONTH:                                         \
-                       ctrl_outb(val, RMONCNT);                        \
-                       break;                                          \
-               case RTC_YEAR:                                          \
-                       ctrl_out##s((ctrl_in##s(RYRCNT) & 0xff00) | (val & 0xff), RYRCNT);\
-                       break;                                          \
-               case RTC_REG_A: /* RTC_FREQ_SELECT */                   \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       if((val & RTC_DIV_CTL) == RTC_DIV_RESET2)       \
-                               rcr2 |= RCR2_RESET;                     \
-                       ctrl_outb(rcr2, RCR2);                          \
-                       break;                                          \
-               case RTC_REG_B: /* RTC_CONTROL */                       \
-                       rcr1 = (ctrl_inb(RCR1) & 0x99) | RCR1_AF;       \
-                       if(val & RTC_AIE) rcr1 |= RCR1_AIE;             \
-                       else              rcr1 &= ~RCR1_AIE;            \
-                       if(val & RTC_UIE) rcr1 |= RCR1_CIE;             \
-                       else              rcr1 &= ~RCR1_CIE;            \
-                       ctrl_outb(rcr1, RCR1);                          \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       if(val & RTC_SET) rcr2 &= ~RCR2_START;          \
-                       else              rcr2 |= RCR2_START;           \
-                       ctrl_outb(rcr2, RCR2);                          \
-                       break;                                          \
-               case RTC_REG_C: /* RTC_INTR_FLAGS */                    \
-                       break;                                          \
-               case RTC_REG_D: /* RTC_VALID */                         \
-                       break;                                          \
-               default:                                                \
-                       break;                                          \
-       }                                                               \
-})
-
-#endif /* CONFIG_SH_MPC1211 */
 #endif /* _ASM_MC146818RTC_H */
index 72f07be6117fa23bbaaeb91d9c8e8a882fbaa57e..cf47df79bb9415c43a310c16c3c93737ebc2c1d2 100644 (file)
@@ -3,27 +3,76 @@
 
 #if !defined(CONFIG_MMU)
 
-struct mm_rblock_struct {
-       int     size;
-       int     refcount;
-       void    *kblock;
-};
-
-struct mm_tblock_struct {
-       struct mm_rblock_struct *rblock;
-       struct mm_tblock_struct *next;
-};
-
 typedef struct {
-       struct mm_tblock_struct tblock;
+       struct vm_list_struct   *vmlist;
        unsigned long           end_brk;
 } mm_context_t;
 
 #else
 
 /* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+typedef unsigned long mm_context_id_t;
+
+typedef struct {
+       mm_context_id_t id;
+       void *vdso;
+} mm_context_t;
 
 #endif /* CONFIG_MMU */
-#endif /* __MMH_H */
+
+/*
+ * Privileged Space Mapping Buffer (PMB) definitions
+ */
+#define PMB_PASCR              0xff000070
+#define PMB_IRMCR              0xff000078
+
+#define PMB_ADDR               0xf6100000
+#define PMB_DATA               0xf7100000
+#define PMB_ENTRY_MAX          16
+#define PMB_E_MASK             0x0000000f
+#define PMB_E_SHIFT            8
+
+#define PMB_SZ_16M             0x00000000
+#define PMB_SZ_64M             0x00000010
+#define PMB_SZ_128M            0x00000080
+#define PMB_SZ_512M            0x00000090
+#define PMB_SZ_MASK            PMB_SZ_512M
+#define PMB_C                  0x00000008
+#define PMB_WT                 0x00000001
+#define PMB_UB                 0x00000200
+#define PMB_V                  0x00000100
+
+#define PMB_NO_ENTRY           (-1)
+
+struct pmb_entry;
+
+struct pmb_entry {
+       unsigned long vpn;
+       unsigned long ppn;
+       unsigned long flags;
+
+       /*
+        * 0 .. NR_PMB_ENTRIES for specific entry selection, or
+        * PMB_NO_ENTRY to search for a free one
+        */
+       int entry;
+
+       struct pmb_entry *next;
+       /* Adjacent entry link for contiguous multi-entry mappings */
+       struct pmb_entry *link;
+};
+
+/* arch/sh/mm/pmb.c */
+int __set_pmb_entry(unsigned long vpn, unsigned long ppn,
+                   unsigned long flags, int *entry);
+int set_pmb_entry(struct pmb_entry *pmbe);
+void clear_pmb_entry(struct pmb_entry *pmbe);
+struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
+                           unsigned long flags);
+void pmb_free(struct pmb_entry *pmbe);
+long pmb_remap(unsigned long virt, unsigned long phys,
+              unsigned long size, unsigned long flags);
+void pmb_unmap(unsigned long addr);
+
+#endif /* __MMU_H */
 
index 6760d064bd0233bfca2ac5217a5e42cf9b113283..c7088efe579add81dae62e2a3dd54134b06fef3b 100644 (file)
@@ -49,7 +49,7 @@ get_mmu_context(struct mm_struct *mm)
        unsigned long mc = mmu_context_cache;
 
        /* Check if we have old version of context. */
-       if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
+       if (((mm->context.id ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
                /* It's up to date, do nothing */
                return;
 
@@ -68,7 +68,7 @@ get_mmu_context(struct mm_struct *mm)
                if (!mc)
                        mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
        }
-       mm->context = mc;
+       mm->context.id = mc;
 }
 
 /*
@@ -78,7 +78,7 @@ get_mmu_context(struct mm_struct *mm)
 static __inline__ int init_new_context(struct task_struct *tsk,
                                       struct mm_struct *mm)
 {
-       mm->context = NO_CONTEXT;
+       mm->context.id = NO_CONTEXT;
 
        return 0;
 }
@@ -123,7 +123,7 @@ static __inline__ unsigned long get_asid(void)
 static __inline__ void activate_context(struct mm_struct *mm)
 {
        get_mmu_context(mm);
-       set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
+       set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK);
 }
 
 /* MMU_TTB can be used for optimizing the fault handling.
@@ -174,9 +174,7 @@ static inline void enable_mmu(void)
 {
        /* Enable MMU */
        ctrl_outl(MMU_CONTROL_INIT, MMUCR);
-
-       /* The manual suggests doing some nops after turning on the MMU */
-       __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
+       ctrl_barrier();
 
        if (mmu_context_cache == NO_CONTEXT)
                mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
@@ -191,7 +189,8 @@ static inline void disable_mmu(void)
        cr = ctrl_inl(MMUCR);
        cr &= ~MMU_CONTROL_INIT;
        ctrl_outl(cr, MMUCR);
-       __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
+
+       ctrl_barrier();
 }
 #else
 /*
index 71ef4cf4242dd5770e416e62eef01a48e2939a4f..9020feee7b4c472327cb758555ba7f0c8db51c88 100644 (file)
@@ -24,7 +24,6 @@ extern void pckbd_leds(unsigned char leds);
 extern void pckbd_init_hw(void);
 extern int pckbd_pm_resume(struct pm_dev *, pm_request_t, void *);
 extern pm_callback pm_kbd_request_override;
-extern unsigned char pckbd_sysrq_xlate[128];
 
 #define kbd_setkeycode         pckbd_setkeycode
 #define kbd_getkeycode         pckbd_getkeycode
@@ -32,9 +31,6 @@ extern unsigned char pckbd_sysrq_xlate[128];
 #define kbd_unexpected_up      pckbd_unexpected_up
 #define kbd_leds               pckbd_leds
 #define kbd_init_hw            pckbd_init_hw
-#define kbd_sysrq_xlate                pckbd_sysrq_xlate
-
-#define SYSRQ_KEY 0x54
 
 /* resource allocation */
 #define kbd_request_region()
diff --git a/include/asm-sh/overdrive/fpga.h b/include/asm-sh/overdrive/fpga.h
deleted file mode 100644 (file)
index 1cd8799..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- */
-
-#ifndef __FPGA_OD_H__
-#define __FPGA_OD_H__
-
-/* This routine will program up the fpga which interfaces to the galileo */
-int init_overdrive_fpga(void);
-
-#endif
diff --git a/include/asm-sh/overdrive/gt64111.h b/include/asm-sh/overdrive/gt64111.h
deleted file mode 100644 (file)
index 01d58bc..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef _GT64111_H_
-#define _GT64111_H_
-
-#define MASTER_INTERFACE         0x0
-#define RAS10_LO_DEC_ADR         0x8        
-#define RAS10_HI_DEC_ADR         0x10
-#define RAS32_LO_DEC_ADR         0x18
-#define RAS32_HI_DEC_ADR         0x20
-#define CS20_LO_DEC_ADR          0x28
-#define CS20_HI_DEC_ADR          0x30
-#define CS3_LO_DEC_ADR           0x38
-#define CS3_HI_DEC_ADR           0x40
-#define PCI_IO_LO_DEC_ADR        0x48
-#define PCI_IO_HI_DEC_ADR        0x50
-#define PCI_MEM0_LO_DEC_ADR      0x58
-#define PCI_MEM0_HI_DEC_ADR      0x60
-#define INTERNAL_SPACE_DEC       0x68
-#define BUS_ERR_ADR_LO_CPU       0x70
-#define READONLY0                0x78
-#define PCI_MEM1_LO_DEC_ADR      0x80
-#define PCI_MEM1_HI_DEC_ADR      0x88
-#define RAS0_LO_DEC_ADR          0x400   
-#define RAS0_HI_DEC_ADR          0x404
-#define RAS1_LO_DEC_ADR          0x408
-#define RAS1_HI_DEC_ADR          0x40c
-#define RAS2_LO_DEC_ADR          0x410
-#define RAS2_HI_DEC_ADR          0x414
-#define RAS3_LO_DEC_ADR          0x418
-#define RAS3_HI_DEC_ADR          0x41c
-#define DEV_CS0_LO_DEC_ADR       0x420
-#define DEV_CS0_HI_DEC_ADR       0x424
-#define DEV_CS1_LO_DEC_ADR       0x428
-#define DEV_CS1_HI_DEC_ADR       0x42c
-#define DEV_CS2_LO_DEC_ADR       0x430
-#define DEV_CS2_HI_DEC_ADR       0x434
-#define DEV_CS3_LO_DEC_ADR       0x438
-#define DEV_CS3_HI_DEC_ADR       0x43c
-#define DEV_BOOTCS_LO_DEC_ADR    0x440
-#define DEV_BOOTCS_HI_DEC_ADR    0x444
-#define DEV_ADR_DEC_ERR          0x470
-#define DRAM_CFG                 0x448   
-#define DRAM_BANK0_PARMS         0x44c   
-#define DRAM_BANK1_PARMS         0x450
-#define DRAM_BANK2_PARMS         0x454
-#define DRAM_BANK3_PARMS         0x458
-#define DEV_BANK0_PARMS          0x45c
-#define DEV_BANK1_PARMS          0x460
-#define DEV_BANK2_PARMS          0x464
-#define DEV_BANK3_PARMS          0x468
-#define DEV_BOOT_BANK_PARMS      0x46c
-#define CH0_DMA_BYTECOUNT        0x800
-#define CH1_DMA_BYTECOUNT        0x804
-#define CH2_DMA_BYTECOUNT        0x808
-#define CH3_DMA_BYTECOUNT        0x80c
-#define CH0_DMA_SRC_ADR          0x810
-#define CH1_DMA_SRC_ADR          0x814
-#define CH2_DMA_SRC_ADR          0x818
-#define CH3_DMA_SRC_ADR          0x81c
-#define CH0_DMA_DST_ADR          0x820
-#define CH1_DMA_DST_ADR          0x824
-#define CH2_DMA_DST_ADR          0x828
-#define CH3_DMA_DST_ADR          0x82c
-#define CH0_NEXT_REC_PTR         0x830
-#define CH1_NEXT_REC_PTR         0x834
-#define CH2_NEXT_REC_PTR         0x838
-#define CH3_NEXT_REC_PTR         0x83c
-#define CH0_CTRL                 0x840
-#define CH1_CTRL                 0x844
-#define CH2_CTRL                 0x848
-#define CH3_CTRL                 0x84c
-#define DMA_ARBITER              0x860
-#define TIMER0                   0x850
-#define TIMER1                   0x854
-#define TIMER2                   0x858
-#define TIMER3                   0x85c
-#define TIMER_CTRL               0x864
-#define PCI_CMD                  0xc00
-#define PCI_TIMEOUT              0xc04
-#define PCI_RAS10_BANK_SIZE      0xc08
-#define PCI_RAS32_BANK_SIZE      0xc0c
-#define PCI_CS20_BANK_SIZE       0xc10
-#define PCI_CS3_BANK_SIZE        0xc14
-#define PCI_SERRMASK             0xc28
-#define PCI_INTACK               0xc34
-#define PCI_BAR_EN               0xc3c
-#define PCI_CFG_ADR              0xcf8
-#define PCI_CFG_DATA             0xcfc
-#define PCI_INTCAUSE             0xc18
-#define PCI_MAST_MASK            0xc1c
-#define PCI_PCIMASK              0xc24
-#define BAR_ENABLE_ADR           0xc3c
-
-/* These are config registers, accessible via PCI space */
-#define PCI_CONFIG_RAS10_BASE_ADR   0x010
-#define PCI_CONFIG_RAS32_BASE_ADR   0x014
-#define PCI_CONFIG_CS20_BASE_ADR    0x018
-#define PCI_CONFIG_CS3_BASE_ADR     0x01c
-#define PCI_CONFIG_INT_REG_MM_ADR   0x020
-#define PCI_CONFIG_INT_REG_IO_ADR   0x024
-#define PCI_CONFIG_BOARD_VENDOR     0x02c
-#define PCI_CONFIG_ROM_ADR          0x030
-#define PCI_CONFIG_INT_PIN_LINE     0x03c
-
-
-
-
-
-#endif
-
diff --git a/include/asm-sh/overdrive/io.h b/include/asm-sh/overdrive/io.h
deleted file mode 100644 (file)
index 0dba700..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-sh/io_od.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an STMicroelectronics Overdrive
- */
-
-#ifndef _ASM_SH_IO_OD_H
-#define _ASM_SH_IO_OD_H
-
-extern unsigned char od_inb(unsigned long port);
-extern unsigned short od_inw(unsigned long port);
-extern unsigned int od_inl(unsigned long port);
-
-extern void od_outb(unsigned char value, unsigned long port);
-extern void od_outw(unsigned short value, unsigned long port);
-extern void od_outl(unsigned int value, unsigned long port);
-
-extern unsigned char od_inb_p(unsigned long port);
-extern unsigned short od_inw_p(unsigned long port);
-extern unsigned int od_inl_p(unsigned long port);
-extern void od_outb_p(unsigned char value, unsigned long port);
-extern void od_outw_p(unsigned short value, unsigned long port);
-extern void od_outl_p(unsigned int value, unsigned long port);
-
-extern void od_insb(unsigned long port, void *addr, unsigned long count);
-extern void od_insw(unsigned long port, void *addr, unsigned long count);
-extern void od_insl(unsigned long port, void *addr, unsigned long count);
-extern void od_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void od_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void od_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned long od_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_OD_H */
diff --git a/include/asm-sh/overdrive/overdrive.h b/include/asm-sh/overdrive/overdrive.h
deleted file mode 100644 (file)
index fc746c2..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- */
-
-
-#ifndef __OVERDRIVE_H__
-#define __OVERDRIVE_H__
-
-#define OVERDRIVE_INT_CT 0xa3a00000
-#define OVERDRIVE_INT_DT 0xa3b00000
-
-#define OVERDRIVE_CTRL    0xa3000000
-
-/* Shoving all these bits into the same register is not a good idea. 
- * As soon as I get a spare moment, I'll change the FPGA and put each 
- * bit in a separate register
- */
-
-#define VALID_CTRL_BITS                          0x1f
-
-#define ENABLE_RS232_MASK                0x1e
-#define DISABLE_RS232_BIT                0x01
-
-#define ENABLE_NMI_MASK                          0x1d
-#define DISABLE_NMI_BIT                          0x02
-
-#define RESET_PCI_MASK                   0x1b
-#define ENABLE_PCI_BIT                   0x04
-
-#define ENABLE_LED_MASK                          0x17
-#define DISABLE_LED_BIT                          0x08
-
-#define RESET_FPGA_MASK                          0x0f
-#define ENABLE_FPGA_BIT                          0x10
-
-
-#define FPGA_DCLK_ADDRESS           0xA3C00000
-
-#define FPGA_DATA        0x01  /*   W */
-#define FPGA_CONFDONE    0x02  /* R   */
-#define FPGA_NOT_STATUS  0x04  /* R   */
-#define FPGA_INITDONE    0x08  /* R   */
-
-#define FPGA_TIMEOUT     100000
-
-
-/* Interrupts for the overdrive. Note that these numbers have 
- * nothing to do with the actual IRQ numbers they appear on, 
- * this is all programmable. This is simply the position in the 
- * INT_CT register.
- */
-
-#define OVERDRIVE_PCI_INTA              0
-#define OVERDRIVE_PCI_INTB              1
-#define OVERDRIVE_PCI_INTC              2
-#define OVERDRIVE_PCI_INTD              3
-#define OVERDRIVE_GALILEO_INT           4
-#define OVERDRIVE_GALILEO_LOCAL_INT     5
-#define OVERDRIVE_AUDIO_INT             6
-#define OVERDRIVE_KEYBOARD_INT          7
-
-/* Which Linux IRQ should we assign to each interrupt source? */
-#define OVERDRIVE_PCI_IRQ1              2
-#ifdef CONFIG_HACKED_NE2K
-#define OVERDRIVE_PCI_IRQ2              7
-#else
-#define OVERDRIVE_PCI_IRQ2              2
-#undef OVERDRIVE_PCI_INTB 
-#define OVERDRIVE_PCI_INTB OVERDRIVE_PCI_INTA
-
-#endif
-
-/* Put the ESS solo audio chip on IRQ 4 */
-#define OVERDRIVE_ESS_IRQ               4
-
-/* Where the memory behind the PCI bus appears */
-#define PCI_DRAM_BASE   0xb7000000
-#define PCI_DRAM_SIZE (16*1024*1024)
-#define PCI_DRAM_FINISH (PCI_DRAM_BASE+PCI_DRAM_SIZE-1)
-
-/* Where the IO region appears in the memory */
-#define PCI_GTIO_BASE   0xb8000000
-
-#endif
index 6f7eb8a3aba53203c57d697c0aaca70185855304..ca8b26d90475937f0d80dde07cd2b2c12e44127c 100644 (file)
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
+
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE      (1 << PAGE_SHIFT)
+#else
 #define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#endif
+
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 #define PTE_MASK       PAGE_MASK
 
@@ -30,7 +36,6 @@
 #define HPAGE_SIZE             (1UL << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE-1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT-PAGE_SHIFT)
-#define ARCH_HAS_SETCLEAR_HUGE_PTE
 #endif
 
 #ifdef __KERNEL__
 extern void (*clear_page)(void *to);
 extern void (*copy_page)(void *to, void *from);
 
+extern unsigned long shm_align_mask;
+
+#ifdef CONFIG_MMU
 extern void clear_page_slow(void *to);
 extern void copy_page_slow(void *to, void *from);
+#else
+extern void clear_page_nommu(void *to);
+extern void copy_page_nommu(void *to, void *from);
+#endif
 
-#if defined(CONFIG_SH7705_CACHE_32KB) && defined(CONFIG_MMU)
+#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \
+       defined(CONFIG_SH7705_CACHE_32KB))
 struct page;
 extern void clear_user_page(void *to, unsigned long address, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
@@ -51,29 +64,20 @@ extern void __copy_user_page(void *to, void *from, void *orig_to);
 #elif defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH3) || !defined(CONFIG_MMU)
 #define clear_user_page(page, vaddr, pg)       clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
-#elif defined(CONFIG_CPU_SH4)
-struct page;
-extern void clear_user_page(void *to, unsigned long address, struct page *pg);
-extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
-extern void __clear_user_page(void *to, void *orig_to);
-extern void __copy_user_page(void *to, void *from, void *orig_to);
 #endif
 
 /*
  * These are used to make use of C type-checking..
  */
 typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define pte_val(x)     ((x).pte)
-#define pmd_val(x)     ((x).pmd)
 #define pgd_val(x)     ((x).pgd)
 #define pgprot_val(x)  ((x).pgprot)
 
 #define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
 #define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
@@ -93,7 +97,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define __MEMORY_START         CONFIG_MEMORY_START
 #define __MEMORY_SIZE          CONFIG_MEMORY_SIZE
 
-#define PAGE_OFFSET            (0x80000000UL)
+#define PAGE_OFFSET            CONFIG_PAGE_OFFSET
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
 
@@ -115,5 +119,10 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+/* vDSO support */
+#ifdef CONFIG_VSYSCALL
+#define __HAVE_ARCH_GATE_AREA
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PAGE_H */
index 0a523c85b11cf855fd42da11ddc00bf1984ef0da..6ccc948fe216e003aee84018b519c09a8708e848 100644 (file)
@@ -32,6 +32,34 @@ extern struct pci_channel board_pci_channels[];
 #define PCIBIOS_MIN_IO         board_pci_channels->io_resource->start
 #define PCIBIOS_MIN_MEM                board_pci_channels->mem_resource->start
 
+/*
+ * I/O routine helpers
+ */
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#define PCI_IO_AREA            0xFE400000
+#define PCI_IO_SIZE            0x00400000
+#else
+#define PCI_IO_AREA            0xFE240000
+#define PCI_IO_SIZE            0X00040000
+#endif
+
+#define PCI_MEM_SIZE           0x01000000
+
+#define SH4_PCIIOBR_MASK       0xFFFC0000
+#define pci_ioaddr(addr)       (PCI_IO_AREA + (addr & ~SH4_PCIIOBR_MASK))
+
+#if defined(CONFIG_PCI)
+#define is_pci_ioaddr(port)            \
+       (((port) >= PCIBIOS_MIN_IO) &&  \
+        ((port) < (PCIBIOS_MIN_IO + PCI_IO_SIZE)))
+#define is_pci_memaddr(port)           \
+       (((port) >= PCIBIOS_MIN_MEM) && \
+        ((port) < (PCIBIOS_MIN_MEM + PCI_MEM_SIZE)))
+#else
+#define is_pci_ioaddr(port)    (0)
+#define is_pci_memaddr(port)   (0)
+#endif
+
 struct pci_dev;
 
 extern void pcibios_set_master(struct pci_dev *dev);
@@ -87,15 +115,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
  */
 #define pci_dac_dma_supported(pci_dev, mask) (0)
 
-/* These macros should be used after a pci_map_sg call has been done
- * to get bus addresses of each of the SG entries and their lengths.
- * You should only work with the number of sg entries pci_map_sg
- * returns, or alternatively stop on the first sg_dma_len(sg) which
- * is 0.
- */
-#define sg_dma_address(sg)     (virt_to_bus((sg)->dma_address))
-#define sg_dma_len(sg)         ((sg)->length)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -107,11 +126,12 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 #endif
 
 /* Board-specific fixup routines. */
-extern void pcibios_fixup(void);
-extern void pcibios_fixup_irqs(void);
+void pcibios_fixup(void);
+int pcibios_init_platform(void);
+int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
 
 #ifdef CONFIG_PCI_AUTO
-extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
+int pciauto_assign_resources(int busno, struct pci_channel *hose);
 #endif
 
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
index f4f233f7a4f575cfec243ee081046f29e2a71ff9..e841465ab4d24214955704852dde0b99a3da35e8 100644 (file)
@@ -1,15 +1,6 @@
 #ifndef __ASM_SH_PGALLOC_H
 #define __ASM_SH_PGALLOC_H
 
-#include <linux/threads.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-
-#define pgd_quicklist ((unsigned long *)0)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist ((unsigned long *)0)
-#define pgtable_cache_size 0L
-
 #define pmd_populate_kernel(mm, pmd, pte) \
                set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
 
@@ -24,38 +15,24 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
-       pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
-
-       if (pgd)
-               memset(pgd, 0, pgd_size);
-
-       return pgd;
+       return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
-       kfree(pgd);
+       free_page((unsigned long)pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       pte_t *pte;
-
-       pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
-
-       return pte;
+       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)
 {
-       struct page *pte;
-
-       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
-
-       return pte;
+       return alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
 }
 
 static inline void pte_free_kernel(pte_t *pte)
@@ -75,14 +52,8 @@ static inline void pte_free(struct page *pte)
  * inside the pgd, so has no extra memory associated with it.
  */
 
-#define pmd_alloc_one(mm, addr)                ({ 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()
 #define check_pgt_cache()              do { } while (0)
 
-#ifdef CONFIG_CPU_SH4
-#define PG_mapped                      PG_arch_1
-#endif
-
 #endif /* __ASM_SH_PGALLOC_H */
index 40d41a78041eaa2ed56abf0d668422870ed54e8e..2c8682ad1012531dcaaf54644865fea6b4a52ea0 100644 (file)
@@ -1,42 +1,42 @@
-#ifndef __ASM_SH_PGTABLE_H
-#define __ASM_SH_PGTABLE_H
-
-#include <asm-generic/4level-fixup.h>
-
 /*
+ * This file contains the functions and defines necessary to modify and
+ * use the SuperH page table tree.
+ *
  * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 - 2005 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.
  */
+#ifndef __ASM_SH_PGTABLE_H
+#define __ASM_SH_PGTABLE_H
 
-#include <asm/pgtable-2level.h>
+#include <asm-generic/pgtable-nopmd.h>
+#include <asm/page.h>
+
+#define PTRS_PER_PGD           1024
 
-/*
- * This file contains the functions and defines necessary to modify and use
- * the SuperH page table tree.
- */
 #ifndef __ASSEMBLY__
-#include <asm/processor.h>
 #include <asm/addrspace.h>
 #include <asm/fixmap.h>
-#include <linux/threads.h>
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 
-/*
- * Basically we have the same two-level (which is the logical three level
- * Linux page table layout folded) page tables as the i386.
- */
-
 /*
  * 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];
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
 #endif /* !__ASSEMBLY__ */
 
+/* traditional two-level paging structure */
+#define PGDIR_SHIFT    22
+#define PTRS_PER_PMD   1
+#define PTRS_PER_PTE   1024
 #define PMD_SIZE       (1UL << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
@@ -47,7 +47,6 @@ extern unsigned long empty_zero_page[1024];
 
 #define PTE_PHYS_MASK  0x1ffff000
 
-#ifndef __ASSEMBLY__
 /*
  * First 1MB map is used by fixed purpose.
  * Currently only 4-enty (16kB) is used (see arch/sh/mm/cache.c)
@@ -55,20 +54,41 @@ extern unsigned long empty_zero_page[1024];
 #define VMALLOC_START  (P3SEG+0x00100000)
 #define VMALLOC_END    (FIXADDR_START-2*PAGE_SIZE)
 
-#define        _PAGE_WT        0x001  /* WT-bit on SH-4, 0 on SH-3 */
-#define _PAGE_HW_SHARED        0x002  /* SH-bit  : page is shared among processes */
-#define _PAGE_DIRTY    0x004  /* D-bit   : page changed */
-#define _PAGE_CACHABLE 0x008  /* C-bit   : cachable */
-#define _PAGE_SZ0      0x010  /* SZ0-bit : Size of page */
-#define _PAGE_RW       0x020  /* PR0-bit : write access allowed */
-#define _PAGE_USER     0x040  /* PR1-bit : user space access allowed */
-#define _PAGE_SZ1      0x080  /* SZ1-bit : Size of page (on SH-4) */
-#define _PAGE_PRESENT  0x100  /* V-bit   : page is valid */
-#define _PAGE_PROTNONE 0x200  /* software: if not present  */
-#define _PAGE_ACCESSED         0x400  /* software: page referenced */
-#define _PAGE_U0_SHARED 0x800  /* software: page is shared in user space */
-
-#define        _PAGE_FILE      _PAGE_WT  /* software: pagecache or swap? */
+/*
+ * Linux PTEL encoding.
+ *
+ * Hardware and software bit definitions for the PTEL value:
+ *
+ * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4).
+ *
+ * - Bit 1 is the SH-bit, but is unused on SH-3 due to an MMU bug (the
+ *   hardware PTEL value can't have the SH-bit set when MMUCR.IX is set,
+ *   which is the default in cpu-sh3/mmu_context.h:MMU_CONTROL_INIT).
+ *
+ *   In order to keep this relatively clean, do not use these for defining
+ *   SH-3 specific flags until all of the other unused bits have been
+ *   exhausted.
+ *
+ * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE.
+ *
+ * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages.
+ *   Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused.
+ *
+ * - Bits 31, 30, and 29 remain unused by everyone and can be used for future
+ *   software flags, although care must be taken to update _PAGE_CLEAR_FLAGS.
+ */
+#define        _PAGE_WT        0x001           /* WT-bit on SH-4, 0 on SH-3 */
+#define _PAGE_HW_SHARED        0x002           /* SH-bit  : shared among processes */
+#define _PAGE_DIRTY    0x004           /* D-bit   : page changed */
+#define _PAGE_CACHABLE 0x008           /* C-bit   : cachable */
+#define _PAGE_SZ0      0x010           /* SZ0-bit : Size of page */
+#define _PAGE_RW       0x020           /* PR0-bit : write access allowed */
+#define _PAGE_USER     0x040           /* PR1-bit : user space access allowed */
+#define _PAGE_SZ1      0x080           /* SZ1-bit : Size of page (on SH-4) */
+#define _PAGE_PRESENT  0x100           /* V-bit   : page is valid */
+#define _PAGE_PROTNONE 0x200           /* software: if not present  */
+#define _PAGE_ACCESSED 0x400           /* software: page referenced */
+#define _PAGE_FILE     _PAGE_WT        /* software: pagecache or swap? */
 
 /* software: moves to PTEA.TC (Timing Control) */
 #define _PAGE_PCC_AREA5        0x00000000      /* use BSC registers for area5 */
@@ -83,23 +103,17 @@ extern unsigned long empty_zero_page[1024];
 #define _PAGE_PCC_ATR8 0x60000000      /* Attribute Memory space, 8 bit bus */
 #define _PAGE_PCC_ATR16        0x60000001      /* Attribute Memory space, 6 bit bus */
 
-
-/* Mask which drop software flags
- * We also drop WT bit since it is used for _PAGE_FILE
- * bit in this implementation.
- */
-#define _PAGE_CLEAR_FLAGS      (_PAGE_WT | _PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_U0_SHARED)
-
-#if defined(CONFIG_CPU_SH3)
-/*
- * MMU on SH-3 has bug on SH-bit: We can't use it if MMUCR.IX=1.
- * Work around: Just drop SH-bit.
- */
-#define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS | _PAGE_HW_SHARED))
+/* Mask which drops unused bits from the PTEL value */
+#ifdef CONFIG_CPU_SH3
+#define _PAGE_CLEAR_FLAGS      (_PAGE_PROTNONE | _PAGE_ACCESSED| \
+                                _PAGE_FILE     | _PAGE_SZ1     | \
+                                _PAGE_HW_SHARED)
 #else
-#define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS))
+#define _PAGE_CLEAR_FLAGS      (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE)
 #endif
 
+#define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS))
+
 /* Hardware flags: SZ0=1 (4k-byte) */
 #define _PAGE_FLAGS_HARD       _PAGE_SZ0
 
@@ -109,15 +123,15 @@ extern unsigned long empty_zero_page[1024];
 #define _PAGE_SZHUGE   (_PAGE_SZ0 | _PAGE_SZ1)
 #endif
 
-#define _PAGE_SHARED   _PAGE_U0_SHARED
-
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE  (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_SHARED)
+#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY)
+
+#ifndef __ASSEMBLY__
 
 #ifdef CONFIG_MMU
 #define PAGE_NONE      __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD)
-#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_SHARED | _PAGE_FLAGS_HARD)
+#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_COPY      __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_READONLY  __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
@@ -137,12 +151,13 @@ extern unsigned long empty_zero_page[1024];
 #define PAGE_KERNEL_PCC                __pgprot(0)
 #endif
 
+#endif /* __ASSEMBLY__ */
+
 /*
  * As i386 and MIPS, SuperH can't do page protection for execute, and
  * considers that the same as a read.  Also, write permissions imply
- * read permissions. This is the closest we can get..  
+ * read permissions. This is the closest we can get..
  */
-
 #define __P000 PAGE_NONE
 #define __P001 PAGE_READONLY
 #define __P010 PAGE_COPY
@@ -161,6 +176,26 @@ extern unsigned long empty_zero_page[1024];
 #define __S110 PAGE_SHARED
 #define __S111 PAGE_SHARED
 
+#ifndef __ASSEMBLY__
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+/*
+ * (pmds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+
+#define pte_pfn(x)             ((unsigned long)(((x).pte >> PAGE_SHIFT)))
+#define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)     __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
 #define pte_none(x)    (!pte_val(x))
 #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(mm,addr,xp)  do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
@@ -171,7 +206,7 @@ extern unsigned long empty_zero_page[1024];
 #define        pmd_bad(x)      ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-#define pte_page(x)    phys_to_page(pte_val(x)&PTE_PHYS_MASK)
+#define pte_page(x)    phys_to_page(pte_val(x)&PTE_PHYS_MASK)
 
 /*
  * The following only work if pte_present() is true.
@@ -248,6 +283,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define pte_unmap(pte)         do { } while (0)
 #define pte_unmap_nested(pte)  do { } while (0)
 
+#define pte_ERROR(e) \
+       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
 struct vm_area_struct;
 extern void update_mmu_cache(struct vm_area_struct * vma,
                             unsigned long address, pte_t pte);
@@ -272,8 +312,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
 
 typedef pte_t *pte_addr_t;
 
-#endif /* !__ASSEMBLY__ */
-
 #define kern_addr_valid(addr)  (1)
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
@@ -301,5 +339,5 @@ extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t
 
 #include <asm-generic/pgtable.h>
 
+#endif /* !__ASSEMBLY__ */
 #endif /* __ASM_SH_PAGE_H */
-
diff --git a/include/asm-sh/pm.h b/include/asm-sh/pm.h
new file mode 100644 (file)
index 0000000..56fdbd6
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright 2006 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ */
+#ifndef __ASM_SH_PM_H
+#define __ASM_SH_PM_H
+
+extern u8 wakeup_start;
+extern u8 wakeup_end;
+
+void pm_enter(void);
+
+#endif
index eeb0f48bb99ead4f5b8d71d92d22df7f7a1d0fbb..474773853cd1a71f3184d85daf62468f3cfc2de0 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/types.h>
 #include <asm/cache.h>
 #include <asm/ptrace.h>
+#include <asm/cpu-features.h>
 
 /*
  * Default implementation of macro that returns current
@@ -38,27 +39,30 @@ enum cpu_type {
        CPU_SH7604,
 
        /* SH-3 types */
-       CPU_SH7705, CPU_SH7707,  CPU_SH7708, CPU_SH7708S, CPU_SH7708R,
-       CPU_SH7709, CPU_SH7709A, CPU_SH7729, CPU_SH7300,
+       CPU_SH7705, CPU_SH7706, CPU_SH7707,
+       CPU_SH7708, CPU_SH7708S, CPU_SH7708R,
+       CPU_SH7709, CPU_SH7709A, CPU_SH7710,
+       CPU_SH7729, CPU_SH7300,
 
        /* SH-4 types */
        CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R,
        CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
-       CPU_SH73180, CPU_SH7770, CPU_SH7780, CPU_SH7781,
+       CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781,
 
        /* Unknown subtype */
        CPU_SH_NONE
 };
 
 struct sh_cpuinfo {
-       enum cpu_type type;
+       unsigned int type;
        unsigned long loops_per_jiffy;
 
-       struct cache_info icache;
-       struct cache_info dcache;
+       struct cache_info icache;       /* Primary I-cache */
+       struct cache_info dcache;       /* Primary D-cache */
+       struct cache_info scache;       /* Secondary cache */
 
        unsigned long flags;
-};
+} __attribute__ ((aligned(SMP_CACHE_BYTES)));
 
 extern struct sh_cpuinfo boot_cpu_data;
 
@@ -125,17 +129,6 @@ union sh_fpu_union {
        struct sh_fpu_soft_struct soft;
 };
 
-/*
- * Processor flags
- */
-
-#define CPU_HAS_FPU            0x0001  /* Hardware FPU support */
-#define CPU_HAS_P2_FLUSH_BUG   0x0002  /* Need to flush the cache in P2 area */
-#define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
-#define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
-#define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
-#define CPU_HAS_PTEA           0x0020  /* PTEA register */
-
 struct thread_struct {
        unsigned long sp;
        unsigned long pc;
@@ -149,6 +142,10 @@ struct thread_struct {
        union sh_fpu_union fpu;
 };
 
+typedef struct {
+       unsigned long seg;
+} mm_segment_t;
+
 /* Count of active tasks with UBC settings */
 extern int ubc_usercnt;
 
@@ -266,5 +263,24 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define cpu_sleep()    __asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()    barrier()
 
+#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \
+    defined(CONFIG_CPU_SH4)
+#define PREFETCH_STRIDE                L1_CACHE_BYTES
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+static inline void prefetch(void *x)
+{
+       __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory");
+}
+
+#define prefetchw(x)   prefetch(x)
+#endif
+
+#ifdef CONFIG_VSYSCALL
+extern int vsyscall_init(void);
+#else
+#define vsyscall_init() do { } while (0)
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PROCESSOR_H */
diff --git a/include/asm-sh/r7780rp/ide.h b/include/asm-sh/r7780rp/ide.h
new file mode 100644 (file)
index 0000000..a1ed78e
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ASM_SH_R7780RP_IDE_H
+#define __ASM_SH_R7780RP_IDE_H
+
+/* Nothing to see here.. */
+#include <asm/mach/r7780rp.h>
+
+#endif /* __ASM_SH_R7780RP_IDE_H */
+
diff --git a/include/asm-sh/r7780rp/r7780rp.h b/include/asm-sh/r7780rp/r7780rp.h
new file mode 100644 (file)
index 0000000..f95d9db
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef __ASM_SH_RENESAS_R7780RP_H
+#define __ASM_SH_RENESAS_R7780RP_H
+
+/*
+ * linux/include/asm-sh/r7780rp.h
+ *
+ * Copyright (C) 2000  Atom Create Engineering Co., Ltd.
+ *
+ * Renesas Solutions Highlander R7780RP support
+ */
+
+/* Box specific addresses.  */
+#if defined(CONFIG_SH_R7780MP)
+#define PA_BCR          0xa4000000      /* FPGA */
+#define PA_IRLMSK       (PA_BCR+0x0000) /* Interrupt Mask control */
+#define PA_IRLMON       (PA_BCR+0x0002) /* Interrupt Status control */
+#define PA_IRLPRI1      (PA_BCR+0x0004) /* Interrupt Priorty 1 */
+#define PA_IRLPRI2      (PA_BCR+0x0006) /* Interrupt Priorty 2 */
+#define PA_IRLPRI3      (PA_BCR+0x0008) /* Interrupt Priorty 3 */
+#define PA_IRLPRI4      (PA_BCR+0x000a) /* Interrupt Priorty 4 */
+#define PA_RSTCTL       (PA_BCR+0x000c) /* Reset Control */
+#define PA_PCIBD        (PA_BCR+0x000e) /* PCI Board detect control */
+#define PA_PCICD        (PA_BCR+0x0010) /* PCI Conector detect control */
+#define PA_EXTGIO       (PA_BCR+0x0016) /* Extension GPIO Control */
+#define PA_IVDRMON      (PA_BCR+0x0018) /* iVDR Moniter control */
+#define PA_IVDRCTL      (PA_BCR+0x001a) /* iVDR control */
+#define PA_OBLED        (PA_BCR+0x001c) /* On Board LED control */
+#define PA_OBSW         (PA_BCR+0x001e) /* On Board Switch control */
+#define PA_AUDIOSEL     (PA_BCR+0x0020) /* Sound Interface Select control */
+#define PA_EXTPLR       (PA_BCR+0x001e) /* Extention Pin Polarity control */
+#define PA_TPCTL        (PA_BCR+0x0100) /* Touch Panel Access control */
+#define PA_TPDCKCTL     (PA_BCR+0x0102) /* Touch Panel Access data control */
+#define PA_TPCTLCLR     (PA_BCR+0x0104) /* Touch Panel Access control */
+#define PA_TPXPOS       (PA_BCR+0x0106) /* Touch Panel X position control */
+#define PA_TPYPOS       (PA_BCR+0x0108) /* Touch Panel Y position control */
+#define PA_DBSW         (PA_BCR+0x0200) /* Debug Board Switch control */
+#define PA_CFCTL        (PA_BCR+0x0300) /* CF Timing control */
+#define PA_CFPOW        (PA_BCR+0x0302) /* CF Power control */
+#define PA_CFCDINTCLR   (PA_BCR+0x0304) /* CF Insert Interrupt clear */
+#define PA_SCSMR0       (PA_BCR+0x0400) /* SCIF0 Serial mode control */
+#define PA_SCBRR0       (PA_BCR+0x0404) /* SCIF0 Bit rate control */
+#define PA_SCSCR0       (PA_BCR+0x0408) /* SCIF0 Serial control */
+#define PA_SCFTDR0      (PA_BCR+0x040c) /* SCIF0 Send FIFO control */
+#define PA_SCFSR0       (PA_BCR+0x0410) /* SCIF0 Serial status control */
+#define PA_SCFRDR0      (PA_BCR+0x0414) /* SCIF0 Receive FIFO control */
+#define PA_SCFCR0       (PA_BCR+0x0418) /* SCIF0 FIFO control */
+#define PA_SCTFDR0      (PA_BCR+0x041c) /* SCIF0 Send FIFO data control */
+#define PA_SCRFDR0      (PA_BCR+0x0420) /* SCIF0 Receive FIFO data control */
+#define PA_SCSPTR0      (PA_BCR+0x0424) /* SCIF0 Serial Port control */
+#define PA_SCLSR0       (PA_BCR+0x0428) /* SCIF0 Line Status control */
+#define PA_SCRER0       (PA_BCR+0x042c) /* SCIF0 Serial Error control */
+#define PA_SCSMR1       (PA_BCR+0x0500) /* SCIF1 Serial mode control */
+#define PA_SCBRR1       (PA_BCR+0x0504) /* SCIF1 Bit rate control */
+#define PA_SCSCR1       (PA_BCR+0x0508) /* SCIF1 Serial control */
+#define PA_SCFTDR1      (PA_BCR+0x050c) /* SCIF1 Send FIFO control */
+#define PA_SCFSR1       (PA_BCR+0x0510) /* SCIF1 Serial status control */
+#define PA_SCFRDR1      (PA_BCR+0x0514) /* SCIF1 Receive FIFO control */
+#define PA_SCFCR1       (PA_BCR+0x0518) /* SCIF1 FIFO control */
+#define PA_SCTFDR1      (PA_BCR+0x051c) /* SCIF1 Send FIFO data control */
+#define PA_SCRFDR1      (PA_BCR+0x0520) /* SCIF1 Receive FIFO data control */
+#define PA_SCSPTR1      (PA_BCR+0x0524) /* SCIF1 Serial Port control */
+#define PA_SCLSR1       (PA_BCR+0x0528) /* SCIF1 Line Status control */
+#define PA_SCRER1       (PA_BCR+0x052c) /* SCIF1 Serial Error control */
+#define PA_ICCR         (PA_BCR+0x0600) /* Serial control */
+#define PA_SAR          (PA_BCR+0x0602) /* Serial Slave control */
+#define PA_MDR          (PA_BCR+0x0604) /* Serial Mode control */
+#define PA_ADR1         (PA_BCR+0x0606) /* Serial Address1 control */
+#define PA_DAR1         (PA_BCR+0x0646) /* Serial Data1 control */
+#define PA_VERREG       (PA_BCR+0x0700) /* FPGA Version Register */
+#define PA_POFF         (PA_BCR+0x0800) /* System Power Off control */
+#define PA_PMR          (PA_BCR+0x0900) /*  */
+
+#define PA_AX88796L     0xa4100400      /* AX88796L Area */
+#define PA_SC1602BSLB   0xa6000000      /* SC1602BSLB Area */
+#define PA_AREA5_IO     0xb4000000      /* Area 5 IO Memory */
+#define PA_AREA6_IO     0xb8000000      /* Area 6 IO Memory */
+#define PA_IDE_OFFSET   0x1f0           /* CF IDE Offset */
+#define AX88796L_IO_BASE        0x1000  /* AX88796L IO Base Address */
+
+#define IRLCNTR1        (PA_BCR + 0)    /* Interrupt Control Register1 */
+
+#define IRQ_PCISLOT1    65              /* PCI Slot #1 IRQ */
+#define IRQ_PCISLOT2    66              /* PCI Slot #2 IRQ */
+#define IRQ_PCISLOT3    67              /* PCI Slot #3 IRQ */
+#define IRQ_PCISLOT4    68              /* PCI Slot #4 IRQ */
+#define IRQ_CFCARD      1               /* CF Card IRQ */
+// #define IRQ_CFINST   0               /* CF Card Insert IRQ */
+#define IRQ_TP          2               /* Touch Panel IRQ */
+#define IRQ_SCI1        3               /* SCI1 IRQ */
+#define IRQ_SCI0        4               /* SCI0 IRQ */
+#define IRQ_2SERIAL     5               /* Serial IRQ */
+#define IRQ_RTC         6               /* RTC A / B IRQ */
+#define IRQ_EXTENTION6  7               /* EXT6n IRQ */
+#define IRQ_EXTENTION5  8               /* EXT5n IRQ */
+#define IRQ_EXTENTION4  9               /* EXT4n IRQ */
+#define IRQ_EXTENTION2  10              /* EXT2n IRQ */
+#define IRQ_EXTENTION1  11              /* EXT1n IRQ */
+#define IRQ_ONETH       13              /* On board Ethernet IRQ */
+#define IRQ_PSW         14              /* Push Switch IRQ */
+
+#else /* R7780RP */
+
+#define PA_BCR         0xa5000000      /* FPGA */
+#define        PA_IRLMSK       (PA_BCR+0x0000) /* Interrupt Mask control */
+#define PA_IRLMON      (PA_BCR+0x0002) /* Interrupt Status control */
+#define        PA_SDPOW        (PA_BCR+0x0004) /* SD Power control */
+#define        PA_RSTCTL       (PA_BCR+0x0006) /* Device Reset control */
+#define        PA_PCIBD        (PA_BCR+0x0008) /* PCI Board detect control */
+#define        PA_PCICD        (PA_BCR+0x000a) /* PCI Conector detect control */
+#define        PA_ZIGIO1       (PA_BCR+0x000c) /* Zigbee IO control 1 */
+#define        PA_ZIGIO2       (PA_BCR+0x000e) /* Zigbee IO control 2 */
+#define        PA_ZIGIO3       (PA_BCR+0x0010) /* Zigbee IO control 3 */
+#define        PA_ZIGIO4       (PA_BCR+0x0012) /* Zigbee IO control 4 */
+#define        PA_IVDRMON      (PA_BCR+0x0014) /* iVDR Moniter control */
+#define        PA_IVDRCTL      (PA_BCR+0x0016) /* iVDR control */
+#define PA_OBLED       (PA_BCR+0x0018) /* On Board LED control */
+#define PA_OBSW                (PA_BCR+0x001a) /* On Board Switch control */
+#define PA_AUDIOSEL    (PA_BCR+0x001c) /* Sound Interface Select control */
+#define PA_EXTPLR      (PA_BCR+0x001e) /* Extention Pin Polarity control */
+#define PA_TPCTL       (PA_BCR+0x0100) /* Touch Panel Access control */
+#define PA_TPDCKCTL    (PA_BCR+0x0102) /* Touch Panel Access data control */
+#define PA_TPCTLCLR    (PA_BCR+0x0104) /* Touch Panel Access control */
+#define PA_TPXPOS      (PA_BCR+0x0106) /* Touch Panel X position control */
+#define PA_TPYPOS      (PA_BCR+0x0108) /* Touch Panel Y position control */
+#define PA_DBDET       (PA_BCR+0x0200) /* Debug Board detect control */
+#define PA_DBDISPCTL   (PA_BCR+0x0202) /* Debug Board Dot timing control */
+#define PA_DBSW                (PA_BCR+0x0204) /* Debug Board Switch control */
+#define PA_CFCTL       (PA_BCR+0x0300) /* CF Timing control */
+#define PA_CFPOW       (PA_BCR+0x0302) /* CF Power control */
+#define PA_CFCDINTCLR  (PA_BCR+0x0304) /* CF Insert Interrupt clear */
+#define PA_SCSMR       (PA_BCR+0x0400) /* SCIF Serial mode control */
+#define PA_SCBRR       (PA_BCR+0x0402) /* SCIF Bit rate control */
+#define PA_SCSCR       (PA_BCR+0x0404) /* SCIF Serial control */
+#define PA_SCFDTR      (PA_BCR+0x0406) /* SCIF Send FIFO control */
+#define PA_SCFSR       (PA_BCR+0x0408) /* SCIF Serial status control */
+#define PA_SCFRDR      (PA_BCR+0x040a) /* SCIF Receive FIFO control */
+#define PA_SCFCR       (PA_BCR+0x040c) /* SCIF FIFO control */
+#define PA_SCFDR       (PA_BCR+0x040e) /* SCIF FIFO data control */
+#define PA_SCLSR       (PA_BCR+0x0412) /* SCIF Line Status control */
+#define PA_ICCR                (PA_BCR+0x0500) /* Serial control */
+#define PA_SAR         (PA_BCR+0x0502) /* Serial Slave control */
+#define PA_MDR         (PA_BCR+0x0504) /* Serial Mode control */
+#define PA_ADR1                (PA_BCR+0x0506) /* Serial Address1 control */
+#define PA_DAR1                (PA_BCR+0x0546) /* Serial Data1 control */
+#define PA_VERREG      (PA_BCR+0x0600) /* FPGA Version Register */
+
+#define PA_AX88796L    0xa5800400      /* AX88796L Area */
+#define PA_SC1602BSLB  0xa6000000      /* SC1602BSLB Area */
+#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
+#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
+#define PA_IDE_OFFSET  0x1f0           /* CF IDE Offset */
+#define AX88796L_IO_BASE       0x1000  /* AX88796L IO Base Address */
+
+#define IRLCNTR1       (PA_BCR + 0)    /* Interrupt Control Register1 */
+
+#define IRQ_PCISLOT1   0               /* PCI Slot #1 IRQ */
+#define IRQ_PCISLOT2   1               /* PCI Slot #2 IRQ */
+#define IRQ_PCISLOT3   2               /* PCI Slot #3 IRQ */
+#define IRQ_PCISLOT4   3               /* PCI Slot #4 IRQ */
+#define IRQ_CFCARD     4               /* CF Card IRQ */
+#define IRQ_CFINST     5               /* CF Card Insert IRQ */
+#define IRQ_M66596     6               /* M66596 IRQ */
+#define IRQ_SDCARD     7               /* SD Card IRQ */
+#define IRQ_TUCHPANEL  8               /* Touch Panel IRQ */
+#define IRQ_SCI                9               /* SCI IRQ */
+#define IRQ_2SERIAL    10              /* Serial IRQ */
+#define        IRQ_EXTENTION   11              /* EXTn IRQ */
+#define IRQ_ONETH      12              /* On board Ethernet IRQ */
+#define IRQ_PSW                13              /* Push Switch IRQ */
+#define IRQ_ZIGBEE     14              /* Ziggbee IO IRQ */
+
+#endif  /* CONFIG_SH_R7780MP */
+
+#define __IO_PREFIX    r7780rp
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_RENESAS_R7780RP */
index cea9cdf9b9252d7037c940594bfac4f0ab60caeb..91aacc96151b2fab63a10aa1eb87f92bf0a80d66 100644 (file)
@@ -1,29 +1,8 @@
 #ifndef _ASM_RTC_H
 #define _ASM_RTC_H
-#ifdef __KERNEL__
 
-#include <asm/machvec.h>
-#include <asm/cpu/rtc.h>
-
-extern void sh_rtc_gettimeofday(struct timespec *ts);
-extern int sh_rtc_settimeofday(const time_t secs);
 extern void (*board_time_init)(void);
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
-
-/* RCR1 Bits */
-#define RCR1_CF                0x80    /* Carry Flag             */
-#define RCR1_CIE       0x10    /* Carry Interrupt Enable */
-#define RCR1_AIE       0x08    /* Alarm Interrupt Enable */
-#define RCR1_AF                0x01    /* Alarm Flag             */
-
-/* RCR2 Bits */
-#define RCR2_PEF       0x80    /* PEriodic interrupt Flag */
-#define RCR2_PESMASK   0x70    /* Periodic interrupt Set  */
-#define RCR2_RTCEN     0x08    /* ENable RTC              */
-#define RCR2_ADJ       0x04    /* ADJustment (30-second)  */
-#define RCR2_RESET     0x02    /* Reset bit               */
-#define RCR2_START     0x01    /* Start bit               */
+extern void (*rtc_sh_get_time)(struct timespec *);
+extern int (*rtc_sh_set_time)(const time_t);
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_RTC_H */
index 4e09ba597e9a06e5746074144081c97df85103c6..b112ae221fd1f4ca0b6ac87cb50909df83037544 100644 (file)
@@ -41,8 +41,6 @@
 
 #define PA_AX88796L    0xaa000400      /* AX88796L Area */
 #define PA_VOYAGER     0xab000000      /* VOYAGER GX Area */
-#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
-#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
 #define PA_IDE_OFFSET  0x1f0           /* CF IDE Offset */
 #define AX88796L_IO_BASE       0x1000  /* AX88796L IO Base Address */
 
diff --git a/include/asm-sh/rts7751r2d/voyagergx_reg.h b/include/asm-sh/rts7751r2d/voyagergx_reg.h
deleted file mode 100644 (file)
index f031b5d..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/* -------------------------------------------------------------------- */
-/* voyagergx_reg.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.
-
-    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.
-
-    Copyright 2003 (c) Lineo uSolutions,Inc.
-*/
-/* -------------------------------------------------------------------- */
-
-#ifndef _VOYAGER_GX_REG_H
-#define _VOYAGER_GX_REG_H
-
-#define VOYAGER_BASE                   0xb3e00000
-#define VOYAGER_USBH_BASE              (0x40000 + VOYAGER_BASE)
-#define VOYAGER_UART_BASE              (0x30000 + VOYAGER_BASE)
-#define        VOYAGER_AC97_BASE               (0xa0000 + VOYAGER_BASE)
-
-#define VOYAGER_IRQ_NUM                        32
-#define VOYAGER_IRQ_BASE               50
-#define VOYAGER_USBH_IRQ               VOYAGER_IRQ_BASE + 6
-#define VOYAGER_8051_IRQ               VOYAGER_IRQ_BASE + 10
-#define VOYAGER_UART0_IRQ              VOYAGER_IRQ_BASE + 12
-#define VOYAGER_UART1_IRQ              VOYAGER_IRQ_BASE + 13
-#define        VOYAGER_AC97_IRQ                VOYAGER_IRQ_BASE + 17
-
-/* ----- MISC controle  register ------------------------------ */
-#define MISC_CTRL                      (0x000004 + VOYAGER_BASE)
-#define MISC_CTRL_USBCLK_48            (3 << 28)
-#define MISC_CTRL_USBCLK_96            (2 << 28)
-#define MISC_CTRL_USBCLK_CRYSTAL       (1 << 28)
-
-/* ----- GPIO[31:0] register --------------------------------- */
-#define GPIO_MUX_LOW                   (0x000008 + VOYAGER_BASE)
-#define GPIO_MUX_LOW_AC97              0x1F000000
-#define GPIO_MUX_LOW_8051              0x0000ffff
-#define GPIO_MUX_LOW_PWM               (1 << 29)
-
-/* ----- GPIO[63:32] register --------------------------------- */
-#define GPIO_MUX_HIGH                  (0x00000C + VOYAGER_BASE)
-
-/* ----- DRAM controle  register ------------------------------- */
-#define DRAM_CTRL                      (0x000010 + VOYAGER_BASE)
-#define DRAM_CTRL_EMBEDDED             (1 << 31)
-#define DRAM_CTRL_CPU_BURST_1          (0 << 28)
-#define DRAM_CTRL_CPU_BURST_2          (1 << 28)
-#define DRAM_CTRL_CPU_BURST_4          (2 << 28)
-#define DRAM_CTRL_CPU_BURST_8          (3 << 28)
-#define DRAM_CTRL_CPU_CAS_LATENCY      (1 << 27)
-#define DRAM_CTRL_CPU_SIZE_2           (0 << 24)
-#define DRAM_CTRL_CPU_SIZE_4           (1 << 24)
-#define DRAM_CTRL_CPU_SIZE_64          (4 << 24)
-#define DRAM_CTRL_CPU_SIZE_32          (5 << 24)
-#define DRAM_CTRL_CPU_SIZE_16          (6 << 24)
-#define DRAM_CTRL_CPU_SIZE_8           (7 << 24)
-#define DRAM_CTRL_CPU_COLUMN_SIZE_1024 (0 << 22)
-#define DRAM_CTRL_CPU_COLUMN_SIZE_512  (2 << 22)
-#define DRAM_CTRL_CPU_COLUMN_SIZE_256  (3 << 22)
-#define DRAM_CTRL_CPU_ACTIVE_PRECHARGE (1 << 21)
-#define DRAM_CTRL_CPU_RESET            (1 << 20)
-#define DRAM_CTRL_CPU_BANKS            (1 << 19)
-#define DRAM_CTRL_CPU_WRITE_PRECHARGE  (1 << 18)
-#define DRAM_CTRL_BLOCK_WRITE          (1 << 17)
-#define DRAM_CTRL_REFRESH_COMMAND      (1 << 16)
-#define DRAM_CTRL_SIZE_4               (0 << 13)
-#define DRAM_CTRL_SIZE_8               (1 << 13)
-#define DRAM_CTRL_SIZE_16              (2 << 13)
-#define DRAM_CTRL_SIZE_32              (3 << 13)
-#define DRAM_CTRL_SIZE_64              (4 << 13)
-#define DRAM_CTRL_SIZE_2               (5 << 13)
-#define DRAM_CTRL_COLUMN_SIZE_256      (0 << 11)
-#define DRAM_CTRL_COLUMN_SIZE_512      (2 << 11)
-#define DRAM_CTRL_COLUMN_SIZE_1024     (3 << 11)
-#define DRAM_CTRL_BLOCK_WRITE_TIME     (1 << 10)
-#define DRAM_CTRL_BLOCK_WRITE_PRECHARGE        (1 << 9)
-#define DRAM_CTRL_ACTIVE_PRECHARGE     (1 << 8)
-#define DRAM_CTRL_RESET                        (1 << 7)
-#define DRAM_CTRL_REMAIN_ACTIVE                (1 << 6)
-#define DRAM_CTRL_BANKS                        (1 << 1)
-#define DRAM_CTRL_WRITE_PRECHARGE      (1 << 0)
-
-/* ----- Arvitration control register -------------------------- */
-#define ARBITRATION_CTRL               (0x000014 + VOYAGER_BASE)
-#define ARBITRATION_CTRL_CPUMEM                (1 << 29)
-#define ARBITRATION_CTRL_INTMEM                (1 << 28)
-#define ARBITRATION_CTRL_USB_OFF       (0 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_1        (1 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_2        (2 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_3        (3 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_4        (4 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_5        (5 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_6        (6 << 24)
-#define ARBITRATION_CTRL_USB_PRIORITY_7        (7 << 24)
-#define ARBITRATION_CTRL_PANEL_OFF     (0 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_1      (1 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_2      (2 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_3      (3 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_4      (4 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_5      (5 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_6      (6 << 20)
-#define ARBITRATION_CTRL_PANEL_PRIORITY_7      (7 << 20)
-#define ARBITRATION_CTRL_ZVPORT_OFF    (0 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_1    (1 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_2    (2 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_3    (3 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_4    (4 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_5    (5 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_6    (6 << 16)
-#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_7    (7 << 16)
-#define ARBITRATION_CTRL_CMD_INTPR_OFF (0 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_1  (1 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_2  (2 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_3  (3 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_4  (4 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_5  (5 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_6  (6 << 12)
-#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_7  (7 << 12)
-#define ARBITRATION_CTRL_DMA_OFF       (0 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_1        (1 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_2        (2 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_3        (3 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_4        (4 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_5        (5 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_6        (6 << 8)
-#define ARBITRATION_CTRL_DMA_PRIORITY_7        (7 << 8)
-#define ARBITRATION_CTRL_VIDEO_OFF     (0 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_1      (1 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_2      (2 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_3      (3 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_4      (4 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_5      (5 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_6      (6 << 4)
-#define ARBITRATION_CTRL_VIDEO_PRIORITY_7      (7 << 4)
-#define ARBITRATION_CTRL_CRT_OFF       (0 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_1        (1 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_2        (2 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_3        (3 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_4        (4 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_5        (5 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_6        (6 << 0)
-#define ARBITRATION_CTRL_CRT_PRIORITY_7        (7 << 0)
-
-/* ----- Command list status register -------------------------- */
-#define CMD_INTPR_STATUS               (0x000024 + VOYAGER_BASE)
-
-/* ----- Interrupt status register ----------------------------- */
-#define INT_STATUS                     (0x00002c + VOYAGER_BASE)
-#define INT_STATUS_UH                  (1 << 6)
-#define INT_STATUS_MC                  (1 << 10)
-#define INT_STATUS_U0                  (1 << 12)
-#define INT_STATUS_U1                  (1 << 13)
-#define        INT_STATUS_AC                   (1 << 17)
-
-/* ----- Interrupt mask register ------------------------------ */
-#define VOYAGER_INT_MASK               (0x000030 + VOYAGER_BASE)
-#define VOYAGER_INT_MASK_AC            (1 << 17)
-
-/* ----- Current Gate register ---------------------------------*/
-#define CURRENT_GATE                   (0x000038 + VOYAGER_BASE)
-
-/* ----- Power mode 0 gate register --------------------------- */
-#define POWER_MODE0_GATE               (0x000040 + VOYAGER_BASE)
-#define POWER_MODE0_GATE_G             (1 << 6)
-#define POWER_MODE0_GATE_U0            (1 << 7)
-#define POWER_MODE0_GATE_U1            (1 << 8)
-#define POWER_MODE0_GATE_UH            (1 << 11)
-#define        POWER_MODE0_GATE_AC             (1 << 18)
-
-/* ----- Power mode 1 gate register --------------------------- */
-#define POWER_MODE1_GATE               (0x000048 + VOYAGER_BASE)
-#define POWER_MODE1_GATE_G             (1 << 6)
-#define POWER_MODE1_GATE_U0            (1 << 7)
-#define POWER_MODE1_GATE_U1            (1 << 8)
-#define POWER_MODE1_GATE_UH            (1 << 11)
-#define        POWER_MODE1_GATE_AC             (1 << 18)
-
-/* ----- Power mode 0 clock register -------------------------- */
-#define POWER_MODE0_CLOCK              (0x000044 + VOYAGER_BASE)
-
-/* ----- Power mode 1 clock register -------------------------- */
-#define POWER_MODE1_CLOCK              (0x00004C + VOYAGER_BASE)
-
-/* ----- Power mode controll register ------------------------- */
-#define POWER_MODE_CTRL                        (0x000054 + VOYAGER_BASE)
-
-/* ----- Miscellaneous Timing register ------------------------ */
-#define SYSTEM_DRAM_CTRL               (0x000068 + VOYAGER_BASE)
-
-/* ----- PWM register ------------------------------------------*/
-#define PWM_0                          (0x010020 + VOYAGER_BASE)
-#define PWM_0_HC(x)                    (((x)&0x0fff)<<20)
-#define PWM_0_LC(x)                    (((x)&0x0fff)<<8 )
-#define PWM_0_CLK_DEV(x)               (((x)&0x000f)<<4 )
-#define PWM_0_EN                       (1<<0)
-
-/* ----- I2C register ----------------------------------------- */
-#define I2C_BYTECOUNT                  (0x010040 + VOYAGER_BASE)
-#define I2C_CONTROL                    (0x010041 + VOYAGER_BASE)
-#define I2C_STATUS                     (0x010042 + VOYAGER_BASE)
-#define I2C_RESET                      (0x010042 + VOYAGER_BASE)
-#define I2C_SADDRESS                   (0x010043 + VOYAGER_BASE)
-#define I2C_DATA                       (0x010044 + VOYAGER_BASE)
-
-/* ----- Controle register bits ----------------------------------------- */
-#define I2C_CONTROL_E                  (1 << 0)
-#define I2C_CONTROL_MODE               (1 << 1)
-#define I2C_CONTROL_STATUS             (1 << 2)
-#define I2C_CONTROL_INT                        (1 << 4)
-#define I2C_CONTROL_INTACK             (1 << 5)
-#define I2C_CONTROL_REPEAT             (1 << 6)
-
-/* ----- Status register bits ----------------------------------------- */
-#define I2C_STATUS_BUSY                        (1 << 0)
-#define I2C_STATUS_ACK                 (1 << 1)
-#define I2C_STATUS_ERROR               (1 << 2)
-#define I2C_STATUS_COMPLETE            (1 << 3)
-
-/* ----- Reset register  ---------------------------------------------- */
-#define I2C_RESET_ERROR                        (1 << 2)
-
-/* ----- transmission frequencies ------------------------------------- */
-#define I2C_SADDRESS_SELECT            (1 << 0)
-
-/* ----- Display Controll register ----------------------------------------- */
-#define PANEL_DISPLAY_CTRL             (0x080000 + VOYAGER_BASE)
-#define PANEL_DISPLAY_CTRL_BIAS         (1<<26)
-#define PANEL_PAN_CTRL                 (0x080004 + VOYAGER_BASE)
-#define PANEL_COLOR_KEY                        (0x080008 + VOYAGER_BASE)
-#define PANEL_FB_ADDRESS               (0x08000C + VOYAGER_BASE)
-#define PANEL_FB_WIDTH                 (0x080010 + VOYAGER_BASE)
-#define PANEL_WINDOW_WIDTH             (0x080014 + VOYAGER_BASE)
-#define PANEL_WINDOW_HEIGHT            (0x080018 + VOYAGER_BASE)
-#define PANEL_PLANE_TL                 (0x08001C + VOYAGER_BASE)
-#define PANEL_PLANE_BR                 (0x080020 + VOYAGER_BASE)
-#define PANEL_HORIZONTAL_TOTAL         (0x080024 + VOYAGER_BASE)
-#define PANEL_HORIZONTAL_SYNC          (0x080028 + VOYAGER_BASE)
-#define PANEL_VERTICAL_TOTAL           (0x08002C + VOYAGER_BASE)
-#define PANEL_VERTICAL_SYNC            (0x080030 + VOYAGER_BASE)
-#define PANEL_CURRENT_LINE             (0x080034 + VOYAGER_BASE)
-#define VIDEO_DISPLAY_CTRL             (0x080040 + VOYAGER_BASE)
-#define VIDEO_FB_0_ADDRESS             (0x080044 + VOYAGER_BASE)
-#define VIDEO_FB_WIDTH                 (0x080048 + VOYAGER_BASE)
-#define VIDEO_FB_0_LAST_ADDRESS                (0x08004C + VOYAGER_BASE)
-#define VIDEO_PLANE_TL                 (0x080050 + VOYAGER_BASE)
-#define VIDEO_PLANE_BR                 (0x080054 + VOYAGER_BASE)
-#define VIDEO_SCALE                    (0x080058 + VOYAGER_BASE)
-#define VIDEO_INITIAL_SCALE            (0x08005C + VOYAGER_BASE)
-#define VIDEO_YUV_CONSTANTS            (0x080060 + VOYAGER_BASE)
-#define VIDEO_FB_1_ADDRESS             (0x080064 + VOYAGER_BASE)
-#define VIDEO_FB_1_LAST_ADDRESS                (0x080068 + VOYAGER_BASE)
-#define VIDEO_ALPHA_DISPLAY_CTRL       (0x080080 + VOYAGER_BASE)
-#define VIDEO_ALPHA_FB_ADDRESS         (0x080084 + VOYAGER_BASE)
-#define VIDEO_ALPHA_FB_WIDTH           (0x080088 + VOYAGER_BASE)
-#define VIDEO_ALPHA_FB_LAST_ADDRESS    (0x08008C + VOYAGER_BASE)
-#define VIDEO_ALPHA_PLANE_TL           (0x080090 + VOYAGER_BASE)
-#define VIDEO_ALPHA_PLANE_BR           (0x080094 + VOYAGER_BASE)
-#define VIDEO_ALPHA_SCALE              (0x080098 + VOYAGER_BASE)
-#define VIDEO_ALPHA_INITIAL_SCALE      (0x08009C + VOYAGER_BASE)
-#define VIDEO_ALPHA_CHROMA_KEY         (0x0800A0 + VOYAGER_BASE)
-#define PANEL_HWC_ADDRESS              (0x0800F0 + VOYAGER_BASE)
-#define PANEL_HWC_LOCATION             (0x0800F4 + VOYAGER_BASE)
-#define PANEL_HWC_COLOR_12             (0x0800F8 + VOYAGER_BASE)
-#define PANEL_HWC_COLOR_3              (0x0800FC + VOYAGER_BASE)
-#define ALPHA_DISPLAY_CTRL             (0x080100 + VOYAGER_BASE)
-#define ALPHA_FB_ADDRESS               (0x080104 + VOYAGER_BASE)
-#define ALPHA_FB_WIDTH                 (0x080108 + VOYAGER_BASE)
-#define ALPHA_PLANE_TL                 (0x08010C + VOYAGER_BASE)
-#define ALPHA_PLANE_BR                 (0x080110 + VOYAGER_BASE)
-#define ALPHA_CHROMA_KEY               (0x080114 + VOYAGER_BASE)
-#define CRT_DISPLAY_CTRL               (0x080200 + VOYAGER_BASE)
-#define CRT_FB_ADDRESS                 (0x080204 + VOYAGER_BASE)
-#define CRT_FB_WIDTH                   (0x080208 + VOYAGER_BASE)
-#define CRT_HORIZONTAL_TOTAL           (0x08020C + VOYAGER_BASE)
-#define CRT_HORIZONTAL_SYNC            (0x080210 + VOYAGER_BASE)
-#define CRT_VERTICAL_TOTAL             (0x080214 + VOYAGER_BASE)
-#define CRT_VERTICAL_SYNC              (0x080218 + VOYAGER_BASE)
-#define CRT_SIGNATURE_ANALYZER         (0x08021C + VOYAGER_BASE)
-#define CRT_CURRENT_LINE               (0x080220 + VOYAGER_BASE)
-#define CRT_MONITOR_DETECT             (0x080224 + VOYAGER_BASE)
-#define CRT_HWC_ADDRESS                        (0x080230 + VOYAGER_BASE)
-#define CRT_HWC_LOCATION               (0x080234 + VOYAGER_BASE)
-#define CRT_HWC_COLOR_12               (0x080238 + VOYAGER_BASE)
-#define CRT_HWC_COLOR_3                        (0x08023C + VOYAGER_BASE)
-#define CRT_PALETTE_RAM                        (0x080400 + VOYAGER_BASE)
-#define PANEL_PALETTE_RAM              (0x080800 + VOYAGER_BASE)
-#define VIDEO_PALETTE_RAM              (0x080C00 + VOYAGER_BASE)
-
-/* ----- 8051 Controle register ----------------------------------------- */
-#define VOYAGER_8051_BASE              (0x000c0000 + VOYAGER_BASE)
-#define VOYAGER_8051_RESET             (0x000b0000 + VOYAGER_BASE)
-#define VOYAGER_8051_SELECT            (0x000b0004 + VOYAGER_BASE)
-#define VOYAGER_8051_CPU_INT           (0x000b000c + VOYAGER_BASE)
-
-/* ----- AC97 Controle register ----------------------------------------- */
-#define AC97_TX_SLOT0                  (0x00000000 + VOYAGER_AC97_BASE)
-#define AC97_CONTROL_STATUS            (0x00000080 + VOYAGER_AC97_BASE)
-#define AC97C_READ                     (1 << 19)
-#define AC97C_WD_BIT                   (1 << 2)
-#define AC97C_INDEX_MASK               0x7f
-/* -------------------------------------------------------------------- */
-
-#endif /* _VOYAGER_GX_REG_H */
index 7b91df140022be81858b656f7497f61c637f731a..d19e7cd3b0235759723f3236a03b80ed83a8e29b 100644 (file)
@@ -10,4 +10,13 @@ struct scatterlist {
 
 #define ISA_DMA_THRESHOLD (0x1fffffff)
 
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg)     ((sg)->dma_address)
+#define sg_dma_len(sg)         ((sg)->length)
+
 #endif /* !(__ASM_SH_SCATTERLIST_H) */
diff --git a/include/asm-sh/sci.h b/include/asm-sh/sci.h
new file mode 100644 (file)
index 0000000..52e7366
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __ASM_SH_SCI_H
+#define __ASM_SH_SCI_H
+
+#include <linux/serial_core.h>
+
+/*
+ * Generic header for SuperH SCI(F)
+ *
+ * Do not place SH-specific parts in here, sh64 and h8300 depend on this too.
+ */
+
+/* Offsets into the sci_port->irqs array */
+enum {
+       SCIx_ERI_IRQ,
+       SCIx_RXI_IRQ,
+       SCIx_TXI_IRQ,
+       SCIx_BRI_IRQ,
+       SCIx_NR_IRQS,
+};
+
+/*
+ * Platform device specific platform_data struct
+ */
+struct plat_sci_port {
+       void __iomem    *membase;               /* io cookie */
+       unsigned long   mapbase;                /* resource base */
+       unsigned int    irqs[SCIx_NR_IRQS];     /* ERI, RXI, TXI, BRI */
+       unsigned int    type;                   /* SCI / SCIF / IRDA */
+       upf_t           flags;                  /* UPF_* flags */
+};
+
+int early_sci_setup(struct uart_port *port);
+
+#endif /* __ASM_SH_SCI_H */
diff --git a/include/asm-sh/se.h b/include/asm-sh/se.h
new file mode 100644 (file)
index 0000000..a183215
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __ASM_SH_HITACHI_SE_H
+#define __ASM_SH_HITACHI_SE_H
+
+/*
+ * linux/include/asm-sh/hitachi_se.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine support
+ */
+
+/* Box specific addresses.  */
+
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
+#define PA_FROM                0x01000000      /* EPROM */
+#define PA_FROM_SIZE   0x00400000      /* EPROM size 4M byte */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+
+#define PA_EXT4                0x12000000
+#define PA_EXT4_SIZE   0x02000000
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+#define PA_PCIC                0x18000000      /* MR-SHPC-01 PCMCIA */
+
+#define PA_83902       0xb0000000      /* DP83902A */
+#define PA_83902_IF    0xb0040000      /* DP83902A remote io port */
+#define PA_83902_RST   0xb0080000      /* DP83902A reset port */
+
+#define PA_SUPERIO     0xb0400000      /* SMC37C935A super io chip */
+#define PA_DIPSW0      0xb0800000      /* Dip switch 5,6 */
+#define PA_DIPSW1      0xb0800002      /* Dip switch 7,8 */
+#define PA_LED         0xb0c00000      /* LED */
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define PA_BCR         0xb0e00000
+#else
+#define PA_BCR         0xb1400000      /* FPGA */
+#endif
+
+#define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2  0xb8500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO   0xb8600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+
+#define BCR_ILCRA      (PA_BCR + 0)
+#define BCR_ILCRB      (PA_BCR + 2)
+#define BCR_ILCRC      (PA_BCR + 4)
+#define BCR_ILCRD      (PA_BCR + 6)
+#define BCR_ILCRE      (PA_BCR + 8)
+#define BCR_ILCRF      (PA_BCR + 10)
+#define BCR_ILCRG      (PA_BCR + 12)
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#define IRQ_STNIC   12
+#else
+#define IRQ_STNIC      10
+#endif
+
+#define __IO_PREFIX    se
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_HITACHI_SE_H */
diff --git a/include/asm-sh/se/io.h b/include/asm-sh/se/io.h
deleted file mode 100644 (file)
index 9eeb86c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-sh/io_se.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an Hitachi SolutionEngine
- */
-
-#ifndef _ASM_SH_IO_SE_H
-#define _ASM_SH_IO_SE_H
-
-extern unsigned char se_inb(unsigned long port);
-extern unsigned short se_inw(unsigned long port);
-extern unsigned int se_inl(unsigned long port);
-
-extern void se_outb(unsigned char value, unsigned long port);
-extern void se_outw(unsigned short value, unsigned long port);
-extern void se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char se_inb_p(unsigned long port);
-extern void se_outb_p(unsigned char value, unsigned long port);
-
-extern void se_insb(unsigned long port, void *addr, unsigned long count);
-extern void se_insw(unsigned long port, void *addr, unsigned long count);
-extern void se_insl(unsigned long port, void *addr, unsigned long count);
-extern void se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned long se_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_SE_H */
diff --git a/include/asm-sh/se/se.h b/include/asm-sh/se/se.h
deleted file mode 100644 (file)
index 791c5da..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef __ASM_SH_HITACHI_SE_H
-#define __ASM_SH_HITACHI_SE_H
-
-/*
- * linux/include/asm-sh/hitachi_se.h
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
- * Hitachi SolutionEngine support
- */
-
-/* Box specific addresses.  */
-
-#define PA_ROM         0x00000000      /* EPROM */
-#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
-#define PA_FROM                0x01000000      /* EPROM */
-#define PA_FROM_SIZE   0x00400000      /* EPROM size 4M byte */
-#define PA_EXT1                0x04000000
-#define PA_EXT1_SIZE   0x04000000
-#define PA_EXT2                0x08000000
-#define PA_EXT2_SIZE   0x04000000
-#define PA_SDRAM       0x0c000000
-#define PA_SDRAM_SIZE  0x04000000
-
-#define PA_EXT4                0x12000000
-#define PA_EXT4_SIZE   0x02000000
-#define PA_EXT5                0x14000000
-#define PA_EXT5_SIZE   0x04000000
-#define PA_PCIC                0x18000000      /* MR-SHPC-01 PCMCIA */
-
-#define PA_83902       0xb0000000      /* DP83902A */
-#define PA_83902_IF    0xb0040000      /* DP83902A remote io port */
-#define PA_83902_RST   0xb0080000      /* DP83902A reset port */
-
-#define PA_SUPERIO     0xb0400000      /* SMC37C935A super io chip */
-#define PA_DIPSW0      0xb0800000      /* Dip switch 5,6 */
-#define PA_DIPSW1      0xb0800002      /* Dip switch 7,8 */
-#define PA_LED         0xb0c00000      /* LED */
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define PA_BCR         0xb0e00000
-#else
-#define PA_BCR         0xb1400000      /* FPGA */
-#endif
-
-#define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controller */
-#define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
-#define PA_MRSHPC_MW2  0xb8500000      /* MR-SHPC-01 attribute window base */
-#define PA_MRSHPC_IO   0xb8600000      /* MR-SHPC-01 I/O window base */
-#define MRSHPC_OPTION   (PA_MRSHPC + 6)
-#define MRSHPC_CSR      (PA_MRSHPC + 8)
-#define MRSHPC_ISR      (PA_MRSHPC + 10)
-#define MRSHPC_ICR      (PA_MRSHPC + 12)
-#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
-#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
-#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
-#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
-#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
-#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
-#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
-#define MRSHPC_CDCR     (PA_MRSHPC + 28)
-#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
-
-#define BCR_ILCRA      (PA_BCR + 0)
-#define BCR_ILCRB      (PA_BCR + 2)
-#define BCR_ILCRC      (PA_BCR + 4)
-#define BCR_ILCRD      (PA_BCR + 6)
-#define BCR_ILCRE      (PA_BCR + 8)
-#define BCR_ILCRF      (PA_BCR + 10)
-#define BCR_ILCRG      (PA_BCR + 12)
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
-#define IRQ_STNIC   12
-#else
-#define IRQ_STNIC      10
-#endif
-
-#endif  /* __ASM_SH_HITACHI_SE_H */
diff --git a/include/asm-sh/se/smc37c93x.h b/include/asm-sh/se/smc37c93x.h
deleted file mode 100644 (file)
index 585da2a..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-#ifndef __ASM_SH_SMC37C93X_H
-#define __ASM_SH_SMC37C93X_H
-
-/*
- * linux/include/asm-sh/smc37c93x.h
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
- * SMSC 37C93x Super IO Chip support
- */
-
-/* Default base I/O address */
-#define FDC_PRIMARY_BASE       0x3f0
-#define IDE1_PRIMARY_BASE      0x1f0
-#define IDE1_SECONDARY_BASE    0x170
-#define PARPORT_PRIMARY_BASE   0x378
-#define COM1_PRIMARY_BASE      0x2f8
-#define COM2_PRIMARY_BASE      0x3f8
-#define RTC_PRIMARY_BASE       0x070
-#define KBC_PRIMARY_BASE       0x060
-#define AUXIO_PRIMARY_BASE     0x000   /* XXX */
-
-/* Logical device number */
-#define LDN_FDC                        0
-#define LDN_IDE1               1
-#define LDN_IDE2               2
-#define LDN_PARPORT            3
-#define LDN_COM1               4
-#define LDN_COM2               5
-#define LDN_RTC                        6
-#define LDN_KBC                        7
-#define LDN_AUXIO              8
-
-/* Configuration port and key */
-#define CONFIG_PORT            0x3f0
-#define INDEX_PORT             CONFIG_PORT
-#define DATA_PORT              0x3f1
-#define CONFIG_ENTER           0x55
-#define CONFIG_EXIT            0xaa
-
-/* Configuration index */
-#define CURRENT_LDN_INDEX      0x07
-#define POWER_CONTROL_INDEX    0x22
-#define ACTIVATE_INDEX         0x30
-#define IO_BASE_HI_INDEX       0x60
-#define IO_BASE_LO_INDEX       0x61
-#define IRQ_SELECT_INDEX       0x70
-#define DMA_SELECT_INDEX       0x74
-
-#define GPIO46_INDEX           0xc6
-#define GPIO47_INDEX           0xc7
-
-/* UART stuff. Only for debugging.  */
-/* UART Register */
-
-#define UART_RBR       0x0     /* Receiver Buffer Register (Read Only) */
-#define UART_THR       0x0     /* Transmitter Holding Register (Write Only) */
-#define UART_IER       0x2     /* Interrupt Enable Register */
-#define UART_IIR       0x4     /* Interrupt Ident Register (Read Only) */
-#define UART_FCR       0x4     /* FIFO Control Register (Write Only) */
-#define UART_LCR       0x6     /* Line Control Register */
-#define UART_MCR       0x8     /* MODEM Control Register */
-#define UART_LSR       0xa     /* Line Status Register */
-#define UART_MSR       0xc     /* MODEM Status Register */
-#define UART_SCR       0xe     /* Scratch Register */
-#define UART_DLL       0x0     /* Divisor Latch (LS) */
-#define UART_DLM       0x2     /* Divisor Latch (MS) */
-
-#ifndef __ASSEMBLY__
-typedef struct uart_reg {
-       volatile __u16 rbr;
-       volatile __u16 ier;
-       volatile __u16 iir;
-       volatile __u16 lcr;
-       volatile __u16 mcr;
-       volatile __u16 lsr;
-       volatile __u16 msr;
-       volatile __u16 scr;
-} uart_reg;
-#endif /* ! __ASSEMBLY__ */
-
-/* Alias for Write Only Register */
-
-#define thr    rbr
-#define tcr    iir
-
-/* Alias for Divisor Latch Register */
-
-#define dll    rbr
-#define dlm    ier
-#define fcr    iir
-
-/* Interrupt Enable Register */
-
-#define IER_ERDAI      0x0100  /* Enable Received Data Available Interrupt */
-#define IER_ETHREI     0x0200  /* Enable Transmitter Holding Register Empty Interrupt */
-#define IER_ELSI       0x0400  /* Enable Receiver Line Status Interrupt */
-#define IER_EMSI       0x0800  /* Enable MODEM Status Interrupt */
-
-/* Interrupt Ident Register */
-
-#define IIR_IP         0x0100  /* "0" if Interrupt Pending */
-#define IIR_IIB0       0x0200  /* Interrupt ID Bit 0 */
-#define IIR_IIB1       0x0400  /* Interrupt ID Bit 1 */
-#define IIR_IIB2       0x0800  /* Interrupt ID Bit 2 */
-#define IIR_FIFO       0xc000  /* FIFOs enabled */
-
-/* FIFO Control Register */
-
-#define FCR_FEN                0x0100  /* FIFO enable */
-#define FCR_RFRES      0x0200  /* Receiver FIFO reset */
-#define FCR_TFRES      0x0400  /* Transmitter FIFO reset */
-#define FCR_DMA                0x0800  /* DMA mode select */
-#define FCR_RTL                0x4000  /* Receiver triger (LSB) */
-#define FCR_RTM                0x8000  /* Receiver triger (MSB) */
-
-/* Line Control Register */
-
-#define LCR_WLS0       0x0100  /* Word Length Select Bit 0 */
-#define LCR_WLS1       0x0200  /* Word Length Select Bit 1 */
-#define LCR_STB                0x0400  /* Number of Stop Bits */
-#define LCR_PEN                0x0800  /* Parity Enable */
-#define LCR_EPS                0x1000  /* Even Parity Select */
-#define LCR_SP         0x2000  /* Stick Parity */
-#define LCR_SB         0x4000  /* Set Break */
-#define LCR_DLAB       0x8000  /* Divisor Latch Access Bit */
-
-/* MODEM Control Register */
-
-#define MCR_DTR                0x0100  /* Data Terminal Ready */
-#define MCR_RTS                0x0200  /* Request to Send */
-#define MCR_OUT1       0x0400  /* Out 1 */
-#define MCR_IRQEN      0x0800  /* IRQ Enable */
-#define MCR_LOOP       0x1000  /* Loop */
-
-/* Line Status Register */
-
-#define LSR_DR         0x0100  /* Data Ready */
-#define LSR_OE         0x0200  /* Overrun Error */
-#define LSR_PE         0x0400  /* Parity Error */
-#define LSR_FE         0x0800  /* Framing Error */
-#define LSR_BI         0x1000  /* Break Interrupt */
-#define LSR_THRE       0x2000  /* Transmitter Holding Register Empty */
-#define LSR_TEMT       0x4000  /* Transmitter Empty */
-#define LSR_FIFOE      0x8000  /* Receiver FIFO error */
-
-/* MODEM Status Register */
-
-#define MSR_DCTS       0x0100  /* Delta Clear to Send */
-#define MSR_DDSR       0x0200  /* Delta Data Set Ready */
-#define MSR_TERI       0x0400  /* Trailing Edge Ring Indicator */
-#define MSR_DDCD       0x0800  /* Delta Data Carrier Detect */
-#define MSR_CTS                0x1000  /* Clear to Send */
-#define MSR_DSR                0x2000  /* Data Set Ready */
-#define MSR_RI         0x4000  /* Ring Indicator */
-#define MSR_DCD                0x8000  /* Data Carrier Detect */
-
-/* Baud Rate Divisor */
-
-#define UART_CLK       (1843200)       /* 1.8432 MHz */
-#define UART_BAUD(x)   (UART_CLK / (16 * (x)))
-
-/* RTC register definition */
-#define RTC_SECONDS             0
-#define RTC_SECONDS_ALARM       1
-#define RTC_MINUTES             2
-#define RTC_MINUTES_ALARM       3
-#define RTC_HOURS               4
-#define RTC_HOURS_ALARM         5
-#define RTC_DAY_OF_WEEK         6
-#define RTC_DAY_OF_MONTH        7
-#define RTC_MONTH               8
-#define RTC_YEAR                9
-#define RTC_FREQ_SELECT                10
-# define RTC_UIP 0x80
-# define RTC_DIV_CTL 0x70
-/* This RTC can work under 32.768KHz clock only.  */
-# define RTC_OSC_ENABLE 0x20
-# define RTC_OSC_DISABLE 0x00
-#define RTC_CONTROL            11
-# define RTC_SET 0x80
-# define RTC_PIE 0x40
-# define RTC_AIE 0x20
-# define RTC_UIE 0x10
-# define RTC_SQWE 0x08
-# define RTC_DM_BINARY 0x04
-# define RTC_24H 0x02
-# define RTC_DST_EN 0x01
-
-#endif  /* __ASM_SH_SMC37C93X_H */
diff --git a/include/asm-sh/se7300.h b/include/asm-sh/se7300.h
new file mode 100644 (file)
index 0000000..4e24edc
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __ASM_SH_HITACHI_SE7300_H
+#define __ASM_SH_HITACHI_SE7300_H
+
+/*
+ * linux/include/asm-sh/se/se7300.h
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * SH-Mobile SolutionEngine 7300 support
+ */
+
+/* Box specific addresses.  */
+
+/* Area 0 */
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte(Actually 2MB) */
+#define PA_FROM                0x00400000      /* Flash ROM */
+#define PA_FROM_SIZE   0x00400000      /* Flash size 4M byte */
+#define PA_SRAM                0x00800000      /* SRAM */
+#define PA_FROM_SIZE   0x00400000      /* SRAM size 4M byte */
+/* Area 1 */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+/* Area 2 */
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+/* Area 3 */
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+/* Area 4 */
+#define PA_PCIC                0x10000000      /* MR-SHPC-01 PCMCIA */
+#define PA_MRSHPC       0xb03fffe0      /* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1   0xb0400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2   0xb0500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO    0xb0600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+#define PA_LED         0xb0800000      /* LED */
+#define PA_DIPSW       0xb0900000      /* Dip switch 31 */
+#define PA_EPLD_MODESET        0xb0a00000      /* FPGA Mode set register */
+#define PA_EPLD_ST1    0xb0a80000      /* FPGA Interrupt status register1 */
+#define PA_EPLD_ST2    0xb0ac0000      /* FPGA Interrupt status register2 */
+/* Area 5 */
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+/* Area 6 */
+#define PA_LCD1                0xb8000000
+#define PA_LCD2                0xb8800000
+
+#define __IO_PREFIX    sh7300se
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_HITACHI_SE7300_H */
diff --git a/include/asm-sh/se7300/io.h b/include/asm-sh/se7300/io.h
deleted file mode 100644 (file)
index c6af855..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-sh/se7300/io.h
- *
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * IO functions for SH-Mobile(SH7300) SolutionEngine
- */
-
-#ifndef _ASM_SH_IO_7300SE_H
-#define _ASM_SH_IO_7300SE_H
-
-extern unsigned char sh7300se_inb(unsigned long port);
-extern unsigned short sh7300se_inw(unsigned long port);
-extern unsigned int sh7300se_inl(unsigned long port);
-
-extern void sh7300se_outb(unsigned char value, unsigned long port);
-extern void sh7300se_outw(unsigned short value, unsigned long port);
-extern void sh7300se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh7300se_inb_p(unsigned long port);
-extern void sh7300se_outb_p(unsigned char value, unsigned long port);
-
-extern void sh7300se_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh7300se_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh7300se_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh7300se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh7300se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh7300se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-#endif /* _ASM_SH_IO_7300SE_H */
diff --git a/include/asm-sh/se7300/se7300.h b/include/asm-sh/se7300/se7300.h
deleted file mode 100644 (file)
index 3ec1ded..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __ASM_SH_HITACHI_SE7300_H
-#define __ASM_SH_HITACHI_SE7300_H
-
-/*
- * linux/include/asm-sh/se/se7300.h
- *
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- *
- * SH-Mobile SolutionEngine 7300 support
- */
-
-/* Box specific addresses.  */
-
-/* Area 0 */
-#define PA_ROM         0x00000000      /* EPROM */
-#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte(Actually 2MB) */
-#define PA_FROM                0x00400000      /* Flash ROM */
-#define PA_FROM_SIZE   0x00400000      /* Flash size 4M byte */
-#define PA_SRAM                0x00800000      /* SRAM */
-#define PA_FROM_SIZE   0x00400000      /* SRAM size 4M byte */
-/* Area 1 */
-#define PA_EXT1                0x04000000
-#define PA_EXT1_SIZE   0x04000000
-/* Area 2 */
-#define PA_EXT2                0x08000000
-#define PA_EXT2_SIZE   0x04000000
-/* Area 3 */
-#define PA_SDRAM       0x0c000000
-#define PA_SDRAM_SIZE  0x04000000
-/* Area 4 */
-#define PA_PCIC                0x10000000      /* MR-SHPC-01 PCMCIA */
-#define PA_MRSHPC       0xb03fffe0      /* MR-SHPC-01 PCMCIA controller */
-#define PA_MRSHPC_MW1   0xb0400000      /* MR-SHPC-01 memory window base */
-#define PA_MRSHPC_MW2   0xb0500000      /* MR-SHPC-01 attribute window base */
-#define PA_MRSHPC_IO    0xb0600000      /* MR-SHPC-01 I/O window base */
-#define MRSHPC_OPTION   (PA_MRSHPC + 6)
-#define MRSHPC_CSR      (PA_MRSHPC + 8)
-#define MRSHPC_ISR      (PA_MRSHPC + 10)
-#define MRSHPC_ICR      (PA_MRSHPC + 12)
-#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
-#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
-#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
-#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
-#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
-#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
-#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
-#define MRSHPC_CDCR     (PA_MRSHPC + 28)
-#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
-#define PA_LED         0xb0800000      /* LED */
-#define PA_DIPSW       0xb0900000      /* Dip switch 31 */
-#define PA_EPLD_MODESET        0xb0a00000      /* FPGA Mode set register */
-#define PA_EPLD_ST1    0xb0a80000      /* FPGA Interrupt status register1 */
-#define PA_EPLD_ST2    0xb0ac0000      /* FPGA Interrupt status register2 */
-/* Area 5 */
-#define PA_EXT5                0x14000000
-#define PA_EXT5_SIZE   0x04000000
-/* Area 6 */
-#define PA_LCD1                0xb8000000
-#define PA_LCD2                0xb8800000
-
-#endif  /* __ASM_SH_HITACHI_SE7300_H */
diff --git a/include/asm-sh/se73180.h b/include/asm-sh/se73180.h
new file mode 100644 (file)
index 0000000..3a4acb3
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __ASM_SH_HITACHI_SE73180_H
+#define __ASM_SH_HITACHI_SE73180_H
+
+/*
+ * include/asm-sh/se/se73180.h
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * SH-Mobile SolutionEngine 73180 support
+ */
+
+/* Box specific addresses.  */
+
+/* Area 0 */
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte(Actually 2MB) */
+#define PA_FROM                0x00400000      /* Flash ROM */
+#define PA_FROM_SIZE   0x00400000      /* Flash size 4M byte */
+#define PA_SRAM                0x00800000      /* SRAM */
+#define PA_FROM_SIZE   0x00400000      /* SRAM size 4M byte */
+/* Area 1 */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+/* Area 2 */
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+/* Area 3 */
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+/* Area 4 */
+#define PA_PCIC                0x10000000      /* MR-SHPC-01 PCMCIA */
+#define PA_MRSHPC       0xb03fffe0      /* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1   0xb0400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2   0xb0500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO    0xb0600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+#define PA_LED         0xb0C00000      /* LED */
+#define LED_SHIFT       0
+#define PA_DIPSW       0xb0900000      /* Dip switch 31 */
+#define PA_EPLD_MODESET        0xb0a00000      /* FPGA Mode set register */
+#define PA_EPLD_ST1    0xb0a80000      /* FPGA Interrupt status register1 */
+#define PA_EPLD_ST2    0xb0ac0000      /* FPGA Interrupt status register2 */
+/* Area 5 */
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+/* Area 6 */
+#define PA_LCD1                0xb8000000
+#define PA_LCD2                0xb8800000
+
+#define __IO_PREFIX    sh73180se
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_HITACHI_SE73180_H */
diff --git a/include/asm-sh/se73180/io.h b/include/asm-sh/se73180/io.h
deleted file mode 100644 (file)
index c9cb1b9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-sh/se73180/io.h
- *
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * Based on include/asm-sh/se7300/io.h
- *
- * IO functions for SH-Mobile3(SH73180) SolutionEngine
- *
- */
-
-#ifndef _ASM_SH_IO_73180SE_H
-#define _ASM_SH_IO_73180SE_H
-
-extern unsigned char sh73180se_inb(unsigned long port);
-extern unsigned short sh73180se_inw(unsigned long port);
-extern unsigned int sh73180se_inl(unsigned long port);
-
-extern void sh73180se_outb(unsigned char value, unsigned long port);
-extern void sh73180se_outw(unsigned short value, unsigned long port);
-extern void sh73180se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh73180se_inb_p(unsigned long port);
-extern void sh73180se_outb_p(unsigned char value, unsigned long port);
-
-extern void sh73180se_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh73180se_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh73180se_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh73180se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh73180se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh73180se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-#endif /* _ASM_SH_IO_73180SE_H */
diff --git a/include/asm-sh/se73180/se73180.h b/include/asm-sh/se73180/se73180.h
deleted file mode 100644 (file)
index f5b93e3..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef __ASM_SH_HITACHI_SE73180_H
-#define __ASM_SH_HITACHI_SE73180_H
-
-/*
- * include/asm-sh/se/se73180.h
- *
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- *
- * SH-Mobile SolutionEngine 73180 support
- */
-
-/* Box specific addresses.  */
-
-/* Area 0 */
-#define PA_ROM         0x00000000      /* EPROM */
-#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte(Actually 2MB) */
-#define PA_FROM                0x00400000      /* Flash ROM */
-#define PA_FROM_SIZE   0x00400000      /* Flash size 4M byte */
-#define PA_SRAM                0x00800000      /* SRAM */
-#define PA_FROM_SIZE   0x00400000      /* SRAM size 4M byte */
-/* Area 1 */
-#define PA_EXT1                0x04000000
-#define PA_EXT1_SIZE   0x04000000
-/* Area 2 */
-#define PA_EXT2                0x08000000
-#define PA_EXT2_SIZE   0x04000000
-/* Area 3 */
-#define PA_SDRAM       0x0c000000
-#define PA_SDRAM_SIZE  0x04000000
-/* Area 4 */
-#define PA_PCIC                0x10000000      /* MR-SHPC-01 PCMCIA */
-#define PA_MRSHPC       0xb03fffe0      /* MR-SHPC-01 PCMCIA controller */
-#define PA_MRSHPC_MW1   0xb0400000      /* MR-SHPC-01 memory window base */
-#define PA_MRSHPC_MW2   0xb0500000      /* MR-SHPC-01 attribute window base */
-#define PA_MRSHPC_IO    0xb0600000      /* MR-SHPC-01 I/O window base */
-#define MRSHPC_OPTION   (PA_MRSHPC + 6)
-#define MRSHPC_CSR      (PA_MRSHPC + 8)
-#define MRSHPC_ISR      (PA_MRSHPC + 10)
-#define MRSHPC_ICR      (PA_MRSHPC + 12)
-#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
-#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
-#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
-#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
-#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
-#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
-#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
-#define MRSHPC_CDCR     (PA_MRSHPC + 28)
-#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
-#define PA_LED         0xb0C00000      /* LED */
-#define LED_SHIFT       0
-#define PA_DIPSW       0xb0900000      /* Dip switch 31 */
-#define PA_EPLD_MODESET        0xb0a00000      /* FPGA Mode set register */
-#define PA_EPLD_ST1    0xb0a80000      /* FPGA Interrupt status register1 */
-#define PA_EPLD_ST2    0xb0ac0000      /* FPGA Interrupt status register2 */
-/* Area 5 */
-#define PA_EXT5                0x14000000
-#define PA_EXT5_SIZE   0x04000000
-/* Area 6 */
-#define PA_LCD1                0xb8000000
-#define PA_LCD2                0xb8800000
-
-#endif  /* __ASM_SH_HITACHI_SE73180_H */
diff --git a/include/asm-sh/se7343.h b/include/asm-sh/se7343.h
new file mode 100644 (file)
index 0000000..e7914a5
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __ASM_SH_HITACHI_SE7343_H
+#define __ASM_SH_HITACHI_SE7343_H
+
+/*
+ * include/asm-sh/se/se7343.h
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * SH-Mobile SolutionEngine 7343 support
+ */
+
+/* Box specific addresses.  */
+
+/* Area 0 */
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte(Actually 2MB) */
+#define PA_FROM                0x00400000      /* Flash ROM */
+#define PA_FROM_SIZE   0x00400000      /* Flash size 4M byte */
+#define PA_SRAM                0x00800000      /* SRAM */
+#define PA_FROM_SIZE   0x00400000      /* SRAM size 4M byte */
+/* Area 1 */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+/* Area 2 */
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+/* Area 3 */
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+/* Area 4 */
+#define PA_PCIC                0x10000000      /* MR-SHPC-01 PCMCIA */
+#define PA_MRSHPC       0xb03fffe0      /* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1   0xb0400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2   0xb0500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO    0xb0600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+#define PA_LED         0xb0C00000      /* LED */
+#define LED_SHIFT       0
+#define PA_DIPSW       0xb0900000      /* Dip switch 31 */
+#define PA_CPLD_MODESET        0xb1400004      /* CPLD Mode set register */
+#define PA_CPLD_ST     0xb1400008      /* CPLD Interrupt status register */
+#define PA_CPLD_IMSK   0xb140000a      /* CPLD Interrupt mask register */
+/* Area 5 */
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+/* Area 6 */
+#define PA_LCD1                0xb8000000
+#define PA_LCD2                0xb8800000
+
+#define __IO_PREFIX    sh7343se
+#include <asm/io_generic.h>
+
+/* External Multiplexed interrupts */
+#define PC_IRQ0                OFFCHIP_IRQ_BASE
+#define PC_IRQ1                (PC_IRQ0 + 1)
+#define PC_IRQ2                (PC_IRQ1 + 1)
+#define PC_IRQ3                (PC_IRQ2 + 1)
+
+#define EXT_IRQ0       (PC_IRQ3 + 1)
+#define EXT_IRQ1       (EXT_IRQ0 + 1)
+#define EXT_IRQ2       (EXT_IRQ1 + 1)
+#define EXT_IRQ3       (EXT_IRQ2 + 1)
+
+#define USB_IRQ0       (EXT_IRQ3 + 1)
+#define USB_IRQ1       (USB_IRQ0 + 1)
+
+#define UART_IRQ0      (USB_IRQ1 + 1)
+#define UART_IRQ1      (UART_IRQ0 + 1)
+
+#endif  /* __ASM_SH_HITACHI_SE7343_H */
diff --git a/include/asm-sh/se7751.h b/include/asm-sh/se7751.h
new file mode 100644 (file)
index 0000000..88cd379
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __ASM_SH_HITACHI_7751SE_H
+#define __ASM_SH_HITACHI_7751SE_H
+
+/*
+ * linux/include/asm-sh/hitachi_7751se.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine support
+
+ * Modified for 7751 Solution Engine by
+ * Ian da Silva and Jeremy Siegel, 2001.
+ */
+
+/* Box specific addresses.  */
+
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
+#define PA_FROM                0x01000000      /* EPROM */
+#define PA_FROM_SIZE   0x00400000      /* EPROM size 4M byte */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+
+#define PA_EXT4                0x12000000
+#define PA_EXT4_SIZE   0x02000000
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+#define PA_PCIC                0x18000000      /* MR-SHPC-01 PCMCIA */
+
+#define PA_DIPSW0      0xb9000000      /* Dip switch 5,6 */
+#define PA_DIPSW1      0xb9000002      /* Dip switch 7,8 */
+#define PA_LED         0xba000000      /* LED */
+#define        PA_BCR          0xbb000000      /* FPGA on the MS7751SE01 */
+
+#define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2  0xb8500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO   0xb8600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_MODE     (PA_MRSHPC + 4)
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+
+#define BCR_ILCRA      (PA_BCR + 0)
+#define BCR_ILCRB      (PA_BCR + 2)
+#define BCR_ILCRC      (PA_BCR + 4)
+#define BCR_ILCRD      (PA_BCR + 6)
+#define BCR_ILCRE      (PA_BCR + 8)
+#define BCR_ILCRF      (PA_BCR + 10)
+#define BCR_ILCRG      (PA_BCR + 12)
+
+#define IRQ_79C973     13
+
+#define __IO_PREFIX    sh7751se
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_HITACHI_7751SE_H */
diff --git a/include/asm-sh/se7751/io.h b/include/asm-sh/se7751/io.h
deleted file mode 100644 (file)
index 78d8f57..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * include/asm-sh/io_7751se.h
- *
- * Modified version of io_se.h for the 7751se-specific functions.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an Hitachi SolutionEngine
- */
-
-#ifndef _ASM_SH_IO_7751SE_H
-#define _ASM_SH_IO_7751SE_H
-
-extern unsigned char sh7751se_inb(unsigned long port);
-extern unsigned short sh7751se_inw(unsigned long port);
-extern unsigned int sh7751se_inl(unsigned long port);
-
-extern void sh7751se_outb(unsigned char value, unsigned long port);
-extern void sh7751se_outw(unsigned short value, unsigned long port);
-extern void sh7751se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh7751se_inb_p(unsigned long port);
-extern void sh7751se_outb_p(unsigned char value, unsigned long port);
-
-extern void sh7751se_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh7751se_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh7751se_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char sh7751se_readb(unsigned long addr);
-extern unsigned short sh7751se_readw(unsigned long addr);
-extern unsigned int sh7751se_readl(unsigned long addr);
-extern void sh7751se_writeb(unsigned char b, unsigned long addr);
-extern void sh7751se_writew(unsigned short b, unsigned long addr);
-extern void sh7751se_writel(unsigned int b, unsigned long addr);
-
-extern unsigned long sh7751se_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_7751SE_H */
diff --git a/include/asm-sh/se7751/se7751.h b/include/asm-sh/se7751/se7751.h
deleted file mode 100644 (file)
index 738e22b..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef __ASM_SH_HITACHI_7751SE_H
-#define __ASM_SH_HITACHI_7751SE_H
-
-/*
- * linux/include/asm-sh/hitachi_7751se.h
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
- * Hitachi SolutionEngine support
-
- * Modified for 7751 Solution Engine by
- * Ian da Silva and Jeremy Siegel, 2001.
- */
-
-/* Box specific addresses.  */
-
-#define PA_ROM         0x00000000      /* EPROM */
-#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
-#define PA_FROM                0x01000000      /* EPROM */
-#define PA_FROM_SIZE   0x00400000      /* EPROM size 4M byte */
-#define PA_EXT1                0x04000000
-#define PA_EXT1_SIZE   0x04000000
-#define PA_EXT2                0x08000000
-#define PA_EXT2_SIZE   0x04000000
-#define PA_SDRAM       0x0c000000
-#define PA_SDRAM_SIZE  0x04000000
-
-#define PA_EXT4                0x12000000
-#define PA_EXT4_SIZE   0x02000000
-#define PA_EXT5                0x14000000
-#define PA_EXT5_SIZE   0x04000000
-#define PA_PCIC                0x18000000      /* MR-SHPC-01 PCMCIA */
-
-#define PA_DIPSW0      0xb9000000      /* Dip switch 5,6 */
-#define PA_DIPSW1      0xb9000002      /* Dip switch 7,8 */
-#define PA_LED         0xba000000      /* LED */
-#define        PA_BCR          0xbb000000      /* FPGA on the MS7751SE01 */
-
-#define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controler */
-#define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
-#define PA_MRSHPC_MW2  0xb8500000      /* MR-SHPC-01 attribute window base */
-#define PA_MRSHPC_IO   0xb8600000      /* MR-SHPC-01 I/O window base */
-#define MRSHPC_MODE     (PA_MRSHPC + 4)
-#define MRSHPC_OPTION   (PA_MRSHPC + 6)
-#define MRSHPC_CSR      (PA_MRSHPC + 8)
-#define MRSHPC_ISR      (PA_MRSHPC + 10)
-#define MRSHPC_ICR      (PA_MRSHPC + 12)
-#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
-#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
-#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
-#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
-#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
-#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
-#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
-#define MRSHPC_CDCR     (PA_MRSHPC + 28)
-#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
-
-#define BCR_ILCRA      (PA_BCR + 0)
-#define BCR_ILCRB      (PA_BCR + 2)
-#define BCR_ILCRC      (PA_BCR + 4)
-#define BCR_ILCRD      (PA_BCR + 6)
-#define BCR_ILCRE      (PA_BCR + 8)
-#define BCR_ILCRF      (PA_BCR + 10)
-#define BCR_ILCRG      (PA_BCR + 12)
-
-#define IRQ_79C973     13
-
-#endif  /* __ASM_SH_HITACHI_7751SE_H */
index d19de7c8df4e258066a8911ddc9064467392c0c5..34ca8a7f06ba86bec5bfc45b2f778c71b3164536 100644 (file)
@@ -4,5 +4,7 @@
 
 #define COMMAND_LINE_SIZE 256
 
+int setup_early_printk(char *);
+
 #endif /* _SH_SETUP_H */
 #endif /* __KERNEL__ */
diff --git a/include/asm-sh/sfp-machine.h b/include/asm-sh/sfp-machine.h
new file mode 100644 (file)
index 0000000..8a6399a
--- /dev/null
@@ -0,0 +1,86 @@
+/* Machine-dependent software floating-point definitions.
+   SuperH kernel version.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+                 Jakub Jelinek (jj@ultra.linux.cz),
+                 David S. Miller (davem@redhat.com) and
+                 Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   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 _SFP_MACHINE_H
+#define _SFP_MACHINE_H
+
+#include <linux/config.h>
+
+#define _FP_W_TYPE_SIZE                32
+#define _FP_W_TYPE             unsigned long
+#define _FP_WS_TYPE            signed long
+#define _FP_I_TYPE             long
+
+#define _FP_MUL_MEAT_S(R,X,Y)                                  \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)                                  \
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)                                  \
+  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S          ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D          ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q          ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S          0
+#define _FP_NANSIGN_D          0
+#define _FP_NANSIGN_Q          0
+
+#define _FP_KEEPNANFRACP 1
+
+/*
+ * If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                      \
+  do {                                                          \
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)          \
+        && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs))     \
+      {                                                         \
+        R##_s = Y##_s;                                          \
+        _FP_FRAC_COPY_##wc(R,Y);                                \
+      }                                                         \
+    else                                                        \
+      {                                                         \
+        R##_s = X##_s;                                          \
+        _FP_FRAC_COPY_##wc(R,X);                                \
+      }                                                         \
+    R##_c = FP_CLS_NAN;                                         \
+  } while (0)
+
+//#define FP_ROUNDMODE         FPSCR_RM
+#define FP_DENORM_ZERO         1/*FPSCR_DN*/
+
+/* Exception flags. */
+#define FP_EX_INVALID          (1<<4)
+#define FP_EX_DIVZERO          (1<<3)
+#define FP_EX_OVERFLOW         (1<<2)
+#define FP_EX_UNDERFLOW                (1<<1)
+#define FP_EX_INEXACT          (1<<0)
+
+#endif
+
index 25792e9831ea4ab86e65b5cae37e5138e74b6b79..df3b187ef8836e7168264e5546ae0017b494964b 100644 (file)
 #define IRL3_IPR_POS   0
 #define IRL3_PRIORITY  4
 
-
-extern unsigned long sh03_isa_port2addr(unsigned long offset);
-
-extern void setup_sh03(void);
-extern void init_sh03_IRQ(void);
-extern void heartbeat_sh03(void);
-
-extern void sh03_rtc_gettimeofday(struct timeval *tv);
-extern int sh03_rtc_settimeofday(const struct timeval *tv);
+void heartbeat_sh03(void);
 
 #endif /* _ASM_SH_IO_SH03_H */
diff --git a/include/asm-sh/sh2000/sh2000.h b/include/asm-sh/sh2000/sh2000.h
deleted file mode 100644 (file)
index 8d54732..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_SH_SH2000_SH2000_H
-#define __ASM_SH_SH2000_SH2000_H
-
-/* arch/sh/boards/sh2000/setup.c */
-extern int setup_sh2000(void);
-
-#endif /* __ASM_SH_SH2000_SH2000_H */
-
diff --git a/include/asm-sh/shmin/shmin.h b/include/asm-sh/shmin/shmin.h
new file mode 100644 (file)
index 0000000..36ba138
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __ASM_SH_SHMIN_H
+#define __ASM_SH_SHMIN_H
+
+#define SHMIN_IO_BASE 0xb0000000UL
+
+#define SHMIN_NE_IRQ IRQ2_IRQ
+#define SHMIN_NE_BASE 0x300
+
+#endif
index 0a95604b9b66d9fdfe8704e943b366be471d0303..ba1758d90106267f23ea1c05362e59f1805ff40d 100644 (file)
@@ -1,8 +1,22 @@
+/*
+ * include/asm-sh/shmparam.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 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.
+ */
 #ifndef __ASM_SH_SHMPARAM_H
 #define __ASM_SH_SHMPARAM_H
-#ifdef __KERNEL__
 
-#include <asm/cpu/shmparam.h>
+/*
+ * SH-4 and SH-3 7705 have an aliasing dcache. Bump this up to a sensible value
+ * for everyone, and work out the specifics from the probed cache descriptor.
+ */
+#define        SHMLBA  0x4000           /* attach addr a multiple of this */
+
+#define __ARCH_FORCE_SHMLBA
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_SH_SHMPARAM_H */
diff --git a/include/asm-sh/smc37c93x.h b/include/asm-sh/smc37c93x.h
new file mode 100644 (file)
index 0000000..585da2a
--- /dev/null
@@ -0,0 +1,190 @@
+#ifndef __ASM_SH_SMC37C93X_H
+#define __ASM_SH_SMC37C93X_H
+
+/*
+ * linux/include/asm-sh/smc37c93x.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * SMSC 37C93x Super IO Chip support
+ */
+
+/* Default base I/O address */
+#define FDC_PRIMARY_BASE       0x3f0
+#define IDE1_PRIMARY_BASE      0x1f0
+#define IDE1_SECONDARY_BASE    0x170
+#define PARPORT_PRIMARY_BASE   0x378
+#define COM1_PRIMARY_BASE      0x2f8
+#define COM2_PRIMARY_BASE      0x3f8
+#define RTC_PRIMARY_BASE       0x070
+#define KBC_PRIMARY_BASE       0x060
+#define AUXIO_PRIMARY_BASE     0x000   /* XXX */
+
+/* Logical device number */
+#define LDN_FDC                        0
+#define LDN_IDE1               1
+#define LDN_IDE2               2
+#define LDN_PARPORT            3
+#define LDN_COM1               4
+#define LDN_COM2               5
+#define LDN_RTC                        6
+#define LDN_KBC                        7
+#define LDN_AUXIO              8
+
+/* Configuration port and key */
+#define CONFIG_PORT            0x3f0
+#define INDEX_PORT             CONFIG_PORT
+#define DATA_PORT              0x3f1
+#define CONFIG_ENTER           0x55
+#define CONFIG_EXIT            0xaa
+
+/* Configuration index */
+#define CURRENT_LDN_INDEX      0x07
+#define POWER_CONTROL_INDEX    0x22
+#define ACTIVATE_INDEX         0x30
+#define IO_BASE_HI_INDEX       0x60
+#define IO_BASE_LO_INDEX       0x61
+#define IRQ_SELECT_INDEX       0x70
+#define DMA_SELECT_INDEX       0x74
+
+#define GPIO46_INDEX           0xc6
+#define GPIO47_INDEX           0xc7
+
+/* UART stuff. Only for debugging.  */
+/* UART Register */
+
+#define UART_RBR       0x0     /* Receiver Buffer Register (Read Only) */
+#define UART_THR       0x0     /* Transmitter Holding Register (Write Only) */
+#define UART_IER       0x2     /* Interrupt Enable Register */
+#define UART_IIR       0x4     /* Interrupt Ident Register (Read Only) */
+#define UART_FCR       0x4     /* FIFO Control Register (Write Only) */
+#define UART_LCR       0x6     /* Line Control Register */
+#define UART_MCR       0x8     /* MODEM Control Register */
+#define UART_LSR       0xa     /* Line Status Register */
+#define UART_MSR       0xc     /* MODEM Status Register */
+#define UART_SCR       0xe     /* Scratch Register */
+#define UART_DLL       0x0     /* Divisor Latch (LS) */
+#define UART_DLM       0x2     /* Divisor Latch (MS) */
+
+#ifndef __ASSEMBLY__
+typedef struct uart_reg {
+       volatile __u16 rbr;
+       volatile __u16 ier;
+       volatile __u16 iir;
+       volatile __u16 lcr;
+       volatile __u16 mcr;
+       volatile __u16 lsr;
+       volatile __u16 msr;
+       volatile __u16 scr;
+} uart_reg;
+#endif /* ! __ASSEMBLY__ */
+
+/* Alias for Write Only Register */
+
+#define thr    rbr
+#define tcr    iir
+
+/* Alias for Divisor Latch Register */
+
+#define dll    rbr
+#define dlm    ier
+#define fcr    iir
+
+/* Interrupt Enable Register */
+
+#define IER_ERDAI      0x0100  /* Enable Received Data Available Interrupt */
+#define IER_ETHREI     0x0200  /* Enable Transmitter Holding Register Empty Interrupt */
+#define IER_ELSI       0x0400  /* Enable Receiver Line Status Interrupt */
+#define IER_EMSI       0x0800  /* Enable MODEM Status Interrupt */
+
+/* Interrupt Ident Register */
+
+#define IIR_IP         0x0100  /* "0" if Interrupt Pending */
+#define IIR_IIB0       0x0200  /* Interrupt ID Bit 0 */
+#define IIR_IIB1       0x0400  /* Interrupt ID Bit 1 */
+#define IIR_IIB2       0x0800  /* Interrupt ID Bit 2 */
+#define IIR_FIFO       0xc000  /* FIFOs enabled */
+
+/* FIFO Control Register */
+
+#define FCR_FEN                0x0100  /* FIFO enable */
+#define FCR_RFRES      0x0200  /* Receiver FIFO reset */
+#define FCR_TFRES      0x0400  /* Transmitter FIFO reset */
+#define FCR_DMA                0x0800  /* DMA mode select */
+#define FCR_RTL                0x4000  /* Receiver triger (LSB) */
+#define FCR_RTM                0x8000  /* Receiver triger (MSB) */
+
+/* Line Control Register */
+
+#define LCR_WLS0       0x0100  /* Word Length Select Bit 0 */
+#define LCR_WLS1       0x0200  /* Word Length Select Bit 1 */
+#define LCR_STB                0x0400  /* Number of Stop Bits */
+#define LCR_PEN                0x0800  /* Parity Enable */
+#define LCR_EPS                0x1000  /* Even Parity Select */
+#define LCR_SP         0x2000  /* Stick Parity */
+#define LCR_SB         0x4000  /* Set Break */
+#define LCR_DLAB       0x8000  /* Divisor Latch Access Bit */
+
+/* MODEM Control Register */
+
+#define MCR_DTR                0x0100  /* Data Terminal Ready */
+#define MCR_RTS                0x0200  /* Request to Send */
+#define MCR_OUT1       0x0400  /* Out 1 */
+#define MCR_IRQEN      0x0800  /* IRQ Enable */
+#define MCR_LOOP       0x1000  /* Loop */
+
+/* Line Status Register */
+
+#define LSR_DR         0x0100  /* Data Ready */
+#define LSR_OE         0x0200  /* Overrun Error */
+#define LSR_PE         0x0400  /* Parity Error */
+#define LSR_FE         0x0800  /* Framing Error */
+#define LSR_BI         0x1000  /* Break Interrupt */
+#define LSR_THRE       0x2000  /* Transmitter Holding Register Empty */
+#define LSR_TEMT       0x4000  /* Transmitter Empty */
+#define LSR_FIFOE      0x8000  /* Receiver FIFO error */
+
+/* MODEM Status Register */
+
+#define MSR_DCTS       0x0100  /* Delta Clear to Send */
+#define MSR_DDSR       0x0200  /* Delta Data Set Ready */
+#define MSR_TERI       0x0400  /* Trailing Edge Ring Indicator */
+#define MSR_DDCD       0x0800  /* Delta Data Carrier Detect */
+#define MSR_CTS                0x1000  /* Clear to Send */
+#define MSR_DSR                0x2000  /* Data Set Ready */
+#define MSR_RI         0x4000  /* Ring Indicator */
+#define MSR_DCD                0x8000  /* Data Carrier Detect */
+
+/* Baud Rate Divisor */
+
+#define UART_CLK       (1843200)       /* 1.8432 MHz */
+#define UART_BAUD(x)   (UART_CLK / (16 * (x)))
+
+/* RTC register definition */
+#define RTC_SECONDS             0
+#define RTC_SECONDS_ALARM       1
+#define RTC_MINUTES             2
+#define RTC_MINUTES_ALARM       3
+#define RTC_HOURS               4
+#define RTC_HOURS_ALARM         5
+#define RTC_DAY_OF_WEEK         6
+#define RTC_DAY_OF_MONTH        7
+#define RTC_MONTH               8
+#define RTC_YEAR                9
+#define RTC_FREQ_SELECT                10
+# define RTC_UIP 0x80
+# define RTC_DIV_CTL 0x70
+/* This RTC can work under 32.768KHz clock only.  */
+# define RTC_OSC_ENABLE 0x20
+# define RTC_OSC_DISABLE 0x00
+#define RTC_CONTROL            11
+# define RTC_SET 0x80
+# define RTC_PIE 0x40
+# define RTC_AIE 0x20
+# define RTC_UIE 0x10
+# define RTC_SQWE 0x08
+# define RTC_DM_BINARY 0x04
+# define RTC_24H 0x02
+# define RTC_DST_EN 0x01
+
+#endif  /* __ASM_SH_SMC37C93X_H */
index f57c4fe9692a97d27557bdeaabc9f33b0791badc..71ecddf70db382f7153b6f6888eec216056914b9 100644 (file)
 #include <asm/atomic.h>
 #include <asm/current.h>
 
-extern cpumask_t cpu_online_map;
-extern cpumask_t cpu_possible_map;
-
-#define cpu_online(cpu)                cpu_isset(cpu, cpu_online_map)
-
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* I've no idea what the real meaning of this is */
diff --git a/include/asm-sh/snapgear.h b/include/asm-sh/snapgear.h
new file mode 100644 (file)
index 0000000..6b5e4dd
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * include/asm-sh/snapgear/io.h
+ *
+ * Modified version of io_se.h for the snapgear-specific functions.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for a SnapGear
+ */
+
+#ifndef _ASM_SH_IO_SNAPGEAR_H
+#define _ASM_SH_IO_SNAPGEAR_H
+
+#if defined(CONFIG_CPU_SH4)
+/*
+ * The external interrupt lines, these take up ints 0 - 15 inclusive
+ * depending on the priority for the interrupt.  In fact the priority
+ * is the interrupt :-)
+ */
+
+#define IRL0_IRQ               2
+#define IRL0_IPR_ADDR  INTC_IPRD
+#define IRL0_IPR_POS   3
+#define IRL0_PRIORITY  13
+
+#define IRL1_IRQ               5
+#define IRL1_IPR_ADDR  INTC_IPRD
+#define IRL1_IPR_POS   2
+#define IRL1_PRIORITY  10
+
+#define IRL2_IRQ               8
+#define IRL2_IPR_ADDR  INTC_IPRD
+#define IRL2_IPR_POS   1
+#define IRL2_PRIORITY  7
+
+#define IRL3_IRQ               11
+#define IRL3_IPR_ADDR  INTC_IPRD
+#define IRL3_IPR_POS   0
+#define IRL3_PRIORITY  4
+#endif
+
+#define __IO_PREFIX    snapgear
+#include <asm/io_generic.h>
+
+#ifdef CONFIG_SH_SECUREEDGE5410
+/*
+ * We need to remember what was written to the ioport as some bits
+ * are shared with other functions and you cannot read back what was
+ * written :-|
+ *
+ * Bit        Read                   Write
+ * -----------------------------------------------
+ * D0         DCD on ttySC1          power
+ * D1         Reset Switch           heatbeat
+ * D2         ttySC0 CTS (7100)      LAN
+ * D3         -                      WAN
+ * D4         ttySC0 DCD (7100)      CONSOLE
+ * D5         -                      ONLINE
+ * D6         -                      VPN
+ * D7         -                      DTR on ttySC1
+ * D8         -                      ttySC0 RTS (7100)
+ * D9         -                      ttySC0 DTR (7100)
+ * D10        -                      RTC SCLK
+ * D11        RTC DATA               RTC DATA
+ * D12        -                      RTS RESET
+ */
+
+#define SECUREEDGE_IOPORT_ADDR ((volatile short *) 0xb0000000)
+extern unsigned short secureedge5410_ioport;
+
+#define SECUREEDGE_WRITE_IOPORT(val, mask) (*SECUREEDGE_IOPORT_ADDR = \
+        (secureedge5410_ioport = \
+                       ((secureedge5410_ioport & ~(mask)) | ((val) & (mask)))))
+#define SECUREEDGE_READ_IOPORT() \
+        ((*SECUREEDGE_IOPORT_ADDR&0x0817) | (secureedge5410_ioport&~0x0817))
+#endif
+
+#endif /* _ASM_SH_IO_SNAPGEAR_H */
diff --git a/include/asm-sh/snapgear/io.h b/include/asm-sh/snapgear/io.h
deleted file mode 100644 (file)
index bfa97ac..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * include/asm-sh/snapgear/io.h
- *
- * Modified version of io_se.h for the snapgear-specific functions.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for a SnapGear
- */
-
-#ifndef _ASM_SH_IO_SNAPGEAR_H
-#define _ASM_SH_IO_SNAPGEAR_H
-
-#if defined(CONFIG_CPU_SH4)
-/*
- * The external interrupt lines, these take up ints 0 - 15 inclusive
- * depending on the priority for the interrupt.  In fact the priority
- * is the interrupt :-)
- */
-
-#define IRL0_IRQ               2
-#define IRL0_IPR_ADDR  INTC_IPRD
-#define IRL0_IPR_POS   3
-#define IRL0_PRIORITY  13
-
-#define IRL1_IRQ               5
-#define IRL1_IPR_ADDR  INTC_IPRD
-#define IRL1_IPR_POS   2
-#define IRL1_PRIORITY  10
-
-#define IRL2_IRQ               8
-#define IRL2_IPR_ADDR  INTC_IPRD
-#define IRL2_IPR_POS   1
-#define IRL2_PRIORITY  7
-
-#define IRL3_IRQ               11
-#define IRL3_IPR_ADDR  INTC_IPRD
-#define IRL3_IPR_POS   0
-#define IRL3_PRIORITY  4
-#endif
-
-extern unsigned char snapgear_inb(unsigned long port);
-extern unsigned short snapgear_inw(unsigned long port);
-extern unsigned int snapgear_inl(unsigned long port);
-
-extern void snapgear_outb(unsigned char value, unsigned long port);
-extern void snapgear_outw(unsigned short value, unsigned long port);
-extern void snapgear_outl(unsigned int value, unsigned long port);
-
-extern unsigned char snapgear_inb_p(unsigned long port);
-extern void snapgear_outb_p(unsigned char value, unsigned long port);
-
-extern void snapgear_insl(unsigned long port, void *addr, unsigned long count);
-extern void snapgear_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned long snapgear_isa_port2addr(unsigned long offset);
-
-#ifdef CONFIG_SH_SECUREEDGE5410
-/*
- * We need to remember what was written to the ioport as some bits
- * are shared with other functions and you cannot read back what was
- * written :-|
- *
- * Bit        Read                   Write
- * -----------------------------------------------
- * D0         DCD on ttySC1          power
- * D1         Reset Switch           heatbeat
- * D2         ttySC0 CTS (7100)      LAN
- * D3         -                      WAN
- * D4         ttySC0 DCD (7100)      CONSOLE
- * D5         -                      ONLINE
- * D6         -                      VPN
- * D7         -                      DTR on ttySC1
- * D8         -                      ttySC0 RTS (7100)
- * D9         -                      ttySC0 DTR (7100)
- * D10        -                      RTC SCLK
- * D11        RTC DATA               RTC DATA
- * D12        -                      RTS RESET
- */
-
- #define SECUREEDGE_IOPORT_ADDR ((volatile short *) 0xb0000000)
- extern unsigned short secureedge5410_ioport;
-
- #define SECUREEDGE_WRITE_IOPORT(val, mask) (*SECUREEDGE_IOPORT_ADDR = \
-                (secureedge5410_ioport = \
-                               ((secureedge5410_ioport & ~(mask)) | ((val) & (mask)))))
- #define SECUREEDGE_READ_IOPORT() \
-                ((*SECUREEDGE_IOPORT_ADDR&0x0817) | (secureedge5410_ioport&~0x0817))
-#endif
-
-#endif /* _ASM_SH_IO_SNAPGEAR_H */
index 846322d4c35d489daf86e337518dbee79f5c738f..54458fd2498150ce964e159748faac8339c1f235 100644 (file)
@@ -100,4 +100,8 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
        return 0;
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SH_SPINLOCK_H */
index ad35ad4958f44df04d7abda10e132c92d707e8bd..6c1f8fde5ac4a8e6a73c6d5059491db8c7e56554 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2002 Paul Mundt
  */
 
+#include <asm/types.h>
 
 /*
  *     switch_to() should switch tasks to task nr n, first
@@ -66,13 +67,20 @@ static inline void sched_cacheflush(void)
 {
 }
 
-#define nop() __asm__ __volatile__ ("nop")
-
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#ifdef CONFIG_CPU_SH4A
+#define __icbi()                       \
+{                                      \
+       unsigned long __addr;           \
+       __addr = 0xa8000000;            \
+       __asm__ __volatile__(           \
+               "icbi   %0\n\t"         \
+               : /* no output */       \
+               : "m" (__m(__addr)));   \
+}
+#endif
 
-static __inline__ unsigned long tas(volatile int *m)
-{ /* #define tas(ptr) (xchg((ptr),1)) */
+static inline unsigned long tas(volatile int *m)
+{
        unsigned long retval;
 
        __asm__ __volatile__ ("tas.b    @%1\n\t"
@@ -81,12 +89,33 @@ static __inline__ unsigned long tas(volatile int *m)
        return retval;
 }
 
-extern void __xchg_called_with_bad_pointer(void);
-
-#define mb()   __asm__ __volatile__ ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  __asm__ __volatile__ ("": : :"memory")
+/*
+ * A brief note on ctrl_barrier(), the control register write barrier.
+ *
+ * Legacy SH cores typically require a sequence of 8 nops after
+ * modification of a control register in order for the changes to take
+ * effect. On newer cores (like the sh4a and sh5) this is accomplished
+ * with icbi.
+ *
+ * Also note that on sh4a in the icbi case we can forego a synco for the
+ * write barrier, as it's not necessary for control registers.
+ *
+ * Historically we have only done this type of barrier for the MMUCR, but
+ * it's also necessary for the CCR, so we make it generic here instead.
+ */
+#ifdef CONFIG_CPU_SH4A
+#define mb()           __asm__ __volatile__ ("synco": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
+#define ctrl_barrier() __icbi()
+#define read_barrier_depends() do { } while(0)
+#else
+#define mb()           __asm__ __volatile__ ("": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("": : :"memory")
+#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
 #define read_barrier_depends() do { } while(0)
+#endif
 
 #ifdef CONFIG_SMP
 #define smp_mb()       mb()
@@ -103,7 +132,8 @@ extern void __xchg_called_with_bad_pointer(void);
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 
 /* Interrupt Control */
-static __inline__ void local_irq_enable(void)
+#ifdef CONFIG_CPU_HAS_SR_RB
+static inline void local_irq_enable(void)
 {
        unsigned long __dummy0, __dummy1;
 
@@ -116,8 +146,22 @@ static __inline__ void local_irq_enable(void)
                             : "1" (~0x000000f0)
                             : "memory");
 }
+#else
+static inline void local_irq_enable(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "and    %1, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "1" (~0x000000f0)
+               : "memory");
+}
+#endif
 
-static __inline__ void local_irq_disable(void)
+static inline void local_irq_disable(void)
 {
        unsigned long __dummy;
        __asm__ __volatile__("stc       sr, %0\n\t"
@@ -128,6 +172,31 @@ static __inline__ void local_irq_disable(void)
                             : "memory");
 }
 
+static inline void set_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ ("stc      sr, %0\n\t"
+                            "or        %2, %0\n\t"
+                            "and       %3, %0\n\t"
+                            "ldc       %0, sr"
+                            : "=&r" (__dummy0), "=r" (__dummy1)
+                            : "r" (0x10000000), "r" (0xffffff0f)
+                            : "memory");
+}
+
+static inline void clear_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ ("stc      sr, %0\n\t"
+                            "and       %2, %0\n\t"
+                            "ldc       %0, sr"
+                            : "=&r" (__dummy0), "=r" (__dummy1)
+                            : "1" (~0x10000000)
+                            : "memory");
+}
+
 #define local_save_flags(x) \
        __asm__("stc sr, %0; and #0xf0, %0" : "=&z" (x) :/**/: "memory" )
 
@@ -138,7 +207,7 @@ static __inline__ void local_irq_disable(void)
        (flags != 0);                   \
 })
 
-static __inline__ unsigned long local_irq_save(void)
+static inline unsigned long local_irq_save(void)
 {
        unsigned long flags, __dummy;
 
@@ -154,35 +223,9 @@ static __inline__ unsigned long local_irq_save(void)
        return flags;
 }
 
-#ifdef DEBUG_CLI_STI
-static __inline__ void  local_irq_restore(unsigned long x)
-{
-       if ((x & 0x000000f0) != 0x000000f0)
-               local_irq_enable();
-       else {
-               unsigned long flags;
-               local_save_flags(flags);
-
-               if (flags == 0) {
-                       extern void dump_stack(void);
-                       printk(KERN_ERR "BUG!\n");
-                       dump_stack();
-                       local_irq_disable();
-               }
-       }
-}
-#else
-#define local_irq_restore(x) do {                      \
-       if ((x & 0x000000f0) != 0x000000f0)             \
-               local_irq_enable();                             \
-} while (0)
-#endif
-
-#define really_restore_flags(x) do {                   \
+#define local_irq_restore(x) do {                      \
        if ((x & 0x000000f0) != 0x000000f0)             \
-               local_irq_enable();                             \
-       else                                            \
-               local_irq_disable();                            \
+               local_irq_enable();                     \
 } while (0)
 
 /*
@@ -210,8 +253,8 @@ do {                                        \
 #define back_to_P1()                                   \
 do {                                                   \
        unsigned long __dummy;                          \
+       ctrl_barrier();                                 \
        __asm__ __volatile__(                           \
-               "nop;nop;nop;nop;nop;nop;nop\n\t"       \
                "mov.l  1f, %0\n\t"                     \
                "jmp    @%0\n\t"                        \
                " nop\n\t"                              \
@@ -224,7 +267,7 @@ do {                                                        \
 /* For spinlocks etc */
 #define local_irq_save(x)      x = local_irq_save()
 
-static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
 {
        unsigned long flags, retval;
 
@@ -235,7 +278,7 @@ static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
        return retval;
 }
 
-static __inline__ unsigned long xchg_u8(volatile unsigned char * m, unsigned long val)
+static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
 {
        unsigned long flags, retval;
 
@@ -246,20 +289,70 @@ static __inline__ unsigned long xchg_u8(volatile unsigned char * m, unsigned lon
        return retval;
 }
 
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+extern void __xchg_called_with_bad_pointer(void);
+
+#define __xchg(ptr, x, size)                           \
+({                                                     \
+       unsigned long __xchg__res;                      \
+       volatile void *__xchg_ptr = (ptr);              \
+       switch (size) {                                 \
+       case 4:                                         \
+               __xchg__res = xchg_u32(__xchg_ptr, x);  \
+               break;                                  \
+       case 1:                                         \
+               __xchg__res = xchg_u8(__xchg_ptr, x);   \
+               break;                                  \
+       default:                                        \
+               __xchg_called_with_bad_pointer();       \
+               __xchg__res = x;                        \
+               break;                                  \
+       }                                               \
+                                                       \
+       __xchg__res;                                    \
+})
+
+#define xchg(ptr,x)    \
+       ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
+
+static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
+       unsigned long new)
+{
+       __u32 retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       if (retval == old)
+               *m = new;
+       local_irq_restore(flags);       /* implies memory barrier  */
+       return retval;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+               unsigned long new, int size)
 {
        switch (size) {
        case 4:
-               return xchg_u32(ptr, x);
-               break;
-       case 1:
-               return xchg_u8(ptr, x);
-               break;
+               return __cmpxchg_u32(ptr, old, new);
        }
-       __xchg_called_with_bad_pointer();
-       return x;
+       __cmpxchg_called_with_bad_pointer();
+       return old;
 }
 
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */
diff --git a/include/asm-sh/systemh/7751systemh.h b/include/asm-sh/systemh/7751systemh.h
deleted file mode 100644 (file)
index 4170531..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef __ASM_SH_SYSTEMH_7751SYSTEMH_H
-#define __ASM_SH_SYSTEMH_7751SYSTEMH_H
-
-/*
- * linux/include/asm-sh/systemh/7751systemh.h
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
- * Hitachi SystemH support
-
- * Modified for 7751 SystemH by
- * Jonathan Short, 2002.
- */
-
-/* Box specific addresses.  */
-
-#define PA_ROM         0x00000000      /* EPROM */
-#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
-#define PA_FROM                0x01000000      /* EPROM */
-#define PA_FROM_SIZE   0x00400000      /* EPROM size 4M byte */
-#define PA_EXT1                0x04000000
-#define PA_EXT1_SIZE   0x04000000
-#define PA_EXT2                0x08000000
-#define PA_EXT2_SIZE   0x04000000
-#define PA_SDRAM       0x0c000000
-#define PA_SDRAM_SIZE  0x04000000
-
-#define PA_EXT4                0x12000000
-#define PA_EXT4_SIZE   0x02000000
-#define PA_EXT5                0x14000000
-#define PA_EXT5_SIZE   0x04000000
-#define PA_PCIC                0x18000000      /* MR-SHPC-01 PCMCIA */
-
-#define PA_DIPSW0      0xb9000000      /* Dip switch 5,6 */
-#define PA_DIPSW1      0xb9000002      /* Dip switch 7,8 */
-#define PA_LED         0xba000000      /* LED */
-#define        PA_BCR          0xbb000000      /* FPGA on the MS7751SE01 */
-
-#define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controler */
-#define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
-#define PA_MRSHPC_MW2  0xb8500000      /* MR-SHPC-01 attribute window base */
-#define PA_MRSHPC_IO   0xb8600000      /* MR-SHPC-01 I/O window base */
-#define MRSHPC_MODE     (PA_MRSHPC + 4)
-#define MRSHPC_OPTION   (PA_MRSHPC + 6)
-#define MRSHPC_CSR      (PA_MRSHPC + 8)
-#define MRSHPC_ISR      (PA_MRSHPC + 10)
-#define MRSHPC_ICR      (PA_MRSHPC + 12)
-#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
-#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
-#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
-#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
-#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
-#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
-#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
-#define MRSHPC_CDCR     (PA_MRSHPC + 28)
-#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
-
-#define BCR_ILCRA      (PA_BCR + 0)
-#define BCR_ILCRB      (PA_BCR + 2)
-#define BCR_ILCRC      (PA_BCR + 4)
-#define BCR_ILCRD      (PA_BCR + 6)
-#define BCR_ILCRE      (PA_BCR + 8)
-#define BCR_ILCRF      (PA_BCR + 10)
-#define BCR_ILCRG      (PA_BCR + 12)
-
-#define IRQ_79C973     13
-
-#endif  /* __ASM_SH_SYSTEMH_7751SYSTEMH_H */
diff --git a/include/asm-sh/systemh/io.h b/include/asm-sh/systemh/io.h
deleted file mode 100644 (file)
index 327849b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * include/asm-sh/systemh/io.h
- *
- * Stupid I/O definitions for SystemH, cloned from SE7751.
- *
- * Copyright (C) 2003  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.
- */
-#ifndef __ASM_SH_SYSTEMH_IO_H
-#define __ASM_SH_SYSTEMH_IO_H
-
-extern unsigned char sh7751systemh_inb(unsigned long port);
-extern unsigned short sh7751systemh_inw(unsigned long port);
-extern unsigned int sh7751systemh_inl(unsigned long port);
-
-extern void sh7751systemh_outb(unsigned char value, unsigned long port);
-extern void sh7751systemh_outw(unsigned short value, unsigned long port);
-extern void sh7751systemh_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh7751systemh_inb_p(unsigned long port);
-extern void sh7751systemh_outb_p(unsigned char value, unsigned long port);
-
-extern void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char sh7751systemh_readb(unsigned long addr);
-extern unsigned short sh7751systemh_readw(unsigned long addr);
-extern unsigned int sh7751systemh_readl(unsigned long addr);
-extern void sh7751systemh_writeb(unsigned char b, unsigned long addr);
-extern void sh7751systemh_writew(unsigned short b, unsigned long addr);
-extern void sh7751systemh_writel(unsigned int b, unsigned long addr);
-
-extern unsigned long sh7751systemh_isa_port2addr(unsigned long offset);
-
-#endif /* __ASM_SH_SYSTEMH_IO_H */
-
diff --git a/include/asm-sh/systemh7751.h b/include/asm-sh/systemh7751.h
new file mode 100644 (file)
index 0000000..b143bb2
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __ASM_SH_SYSTEMH_7751SYSTEMH_H
+#define __ASM_SH_SYSTEMH_7751SYSTEMH_H
+
+/*
+ * linux/include/asm-sh/systemh/7751systemh.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SystemH support
+
+ * Modified for 7751 SystemH by
+ * Jonathan Short, 2002.
+ */
+
+/* Box specific addresses.  */
+
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte */
+#define PA_FROM                0x01000000      /* EPROM */
+#define PA_FROM_SIZE   0x00400000      /* EPROM size 4M byte */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+
+#define PA_EXT4                0x12000000
+#define PA_EXT4_SIZE   0x02000000
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+#define PA_PCIC                0x18000000      /* MR-SHPC-01 PCMCIA */
+
+#define PA_DIPSW0      0xb9000000      /* Dip switch 5,6 */
+#define PA_DIPSW1      0xb9000002      /* Dip switch 7,8 */
+#define PA_LED         0xba000000      /* LED */
+#define        PA_BCR          0xbb000000      /* FPGA on the MS7751SE01 */
+
+#define PA_MRSHPC      0xb83fffe0      /* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC_MW1  0xb8400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2  0xb8500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO   0xb8600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_MODE     (PA_MRSHPC + 4)
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+
+#define BCR_ILCRA      (PA_BCR + 0)
+#define BCR_ILCRB      (PA_BCR + 2)
+#define BCR_ILCRC      (PA_BCR + 4)
+#define BCR_ILCRD      (PA_BCR + 6)
+#define BCR_ILCRE      (PA_BCR + 8)
+#define BCR_ILCRF      (PA_BCR + 10)
+#define BCR_ILCRG      (PA_BCR + 12)
+
+#define IRQ_79C973     13
+
+#define __IO_PREFIX    sh7751systemh
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_SYSTEMH_7751SYSTEMH_H */
index 7345350d98c0c2fe16a3b6029c0f071e1a2fd157..3ebc3f9039ebe3f6cebdaa43c913c5c93dbd0547 100644 (file)
@@ -9,8 +9,8 @@
  *  Copyright (C) 2002  David Howells (dhowells@redhat.com)
  *  - Incorporating suggestions made by Linus Torvalds and Dave Miller
  */
-
 #ifdef __KERNEL__
+#include <asm/page.h>
 
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
@@ -21,7 +21,10 @@ struct thread_info {
        unsigned long           flags;          /* low level flags */
        __u32                   cpu;
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
+       mm_segment_t            addr_limit;     /* thread address space */
        struct restart_block    restart_block;
+       unsigned long           previous_sp;    /* sp of previous stack in case
+                                                  of nested IRQ stacks */
        __u8                    supervisor_stack[0];
 };
 
@@ -29,6 +32,13 @@ struct thread_info {
 
 #define PREEMPT_ACTIVE         0x10000000
 
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE            (PAGE_SIZE)
+#else
+#define THREAD_SIZE            (PAGE_SIZE * 2)
+#endif
+#define STACK_WARN             (THREAD_SIZE / 8)
+
 /*
  * macros/functions for gaining access to the thread information structure
  */
@@ -40,6 +50,7 @@ struct thread_info {
        .flags          = 0,                    \
        .cpu            = 0,                    \
        .preempt_count  = 1,                    \
+       .addr_limit     = KERNEL_DS,            \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
        },                                      \
@@ -48,24 +59,42 @@ struct thread_info {
 #define init_thread_info       (init_thread_union.thread_info)
 #define init_stack             (init_thread_union.stack)
 
+/* how to get the current stack pointer from C */
+register unsigned long current_stack_pointer asm("r15") __attribute_used__;
+
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
        struct thread_info *ti;
+#ifdef CONFIG_CPU_HAS_SR_RB
        __asm__("stc    r7_bank, %0" : "=r" (ti));
+#else
+       unsigned long __dummy;
+
+       __asm__ __volatile__ (
+               "mov    r15, %0\n\t"
+               "and    %1, %0\n\t"
+               : "=&r" (ti), "=r" (__dummy)
+               : "1" (~(THREAD_SIZE - 1))
+               : "memory");
+#endif
+
        return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(ti)  kzalloc(THREAD_SIZE, GFP_KERNEL)
+#else
+#define alloc_thread_info(ti)  kmalloc(THREAD_SIZE, GFP_KERNEL)
+#endif
+#define free_thread_info(ti)   kfree(ti)
 
 #else /* !__ASSEMBLY__ */
 
 /* how to get the thread information struct from ASM */
 #define GET_THREAD_INFO(reg) \
-       stc     r7_bank, reg
+       stc     r7_bank, reg
 
 #endif
 
@@ -79,18 +108,18 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18
-#define TIF_USERSPACE          31      /* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_USERSPACE         (1<<TIF_USERSPACE)
 
 #define _TIF_WORK_MASK         0x000000FE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x000000FF      /* work to do on any return to u-space */
index dd6579c0b04cf01cca86ad41238394d74697e244..c7ab28095ba0ea4ffabe410108d57a33c9f5e56b 100644 (file)
@@ -6,6 +6,8 @@
 
 struct sys_timer_ops {
        int (*init)(void);
+       int (*start)(void);
+       int (*stop)(void);
        unsigned long (*get_offset)(void);
        unsigned long (*get_frequency)(void);
 };
diff --git a/include/asm-sh/titan.h b/include/asm-sh/titan.h
new file mode 100644 (file)
index 0000000..270a4f4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Platform defintions for Titan
+ */
+
+#ifndef _ASM_SH_TITAN_TITAN_H
+#define _ASM_SH_TITAN_TITAN_H
+
+#define __IO_PREFIX titan
+#include <asm/io_generic.h>
+
+/* IRQ assignments */
+#define TITAN_IRQ_WAN          2       /* eth0 (WAN) */
+#define TITAN_IRQ_LAN          5       /* eth1 (LAN) */
+#define TITAN_IRQ_MPCIA                8       /* mPCI A */
+#define TITAN_IRQ_MPCIB                11      /* mPCI B */
+#define TITAN_IRQ_USB          11      /* USB */
+
+/*
+ * The external interrupt lines, these take up ints 0 - 15 inclusive
+ * depending on the priority for the interrupt.  In fact the priority
+ * is the interrupt :-)
+ */
+#define IRL0_IRQ       0
+#define IRL0_IPR_ADDR  INTC_IPRD
+#define IRL0_IPR_POS   3
+#define IRL0_PRIORITY  8
+
+#define IRL1_IRQ       1
+#define IRL1_IPR_ADDR  INTC_IPRD
+#define IRL1_IPR_POS   2
+#define IRL1_PRIORITY  8
+
+#define IRL2_IRQ       2
+#define IRL2_IPR_ADDR  INTC_IPRD
+#define IRL2_IPR_POS   1
+#define IRL2_PRIORITY  8
+
+#define IRL3_IRQ       3
+#define IRL3_IPR_ADDR  INTC_IPRD
+#define IRL3_IPR_POS   0
+#define IRL3_PRIORITY  8
+
+#endif
index 2cb01861e7c550babe2e44409aa0be3942d2415a..5c49ed6715f2a620a6d75d02583d76c16e1a6ee7 100644 (file)
 #include <linux/errno.h>
 #include <linux/sched.h>
 
-/*
- * NOTE: Macro/functions in this file depends on threads_info.h implementation.
- * Assumes:
- * TI_FLAGS == 8
- * TIF_USERSPACE == 31
- * USER_ADDR_LIMIT == 0x80000000
- */
-
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
-typedef struct {
-       unsigned int is_user_space;
-} mm_segment_t;
-
 /*
  * The fs value determines whether argument validity checking should be
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
@@ -40,16 +28,18 @@ typedef struct {
  */
 
 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-#define segment_eq(a,b)        ((a).is_user_space == (b).is_user_space)
 
-#define USER_ADDR_LIMIT        0x80000000
+#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFFUL)
+#define USER_DS                MAKE_MM_SEG(PAGE_OFFSET)
 
-#define KERNEL_DS      MAKE_MM_SEG(0)
-#define USER_DS                MAKE_MM_SEG(1)
+#define segment_eq(a,b)        ((a).seg == (b).seg)
 
 #define get_ds()       (KERNEL_DS)
 
 #if !defined(CONFIG_MMU)
+/* NOMMU is always true */
+#define __addr_ok(addr) (1)
+
 static inline mm_segment_t get_fs(void)
 {
        return USER_DS;
@@ -76,31 +66,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
        return ((addr >= memory_start) && ((addr + size) < memory_end));
 }
 #else /* CONFIG_MMU */
-static inline mm_segment_t get_fs(void)
-{
-       return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE));
-}
+#define __addr_ok(addr) \
+       ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
 
-static inline void set_fs(mm_segment_t s)
-{
-       unsigned long ti, flag;
-       __asm__ __volatile__(
-               "stc    r7_bank, %0\n\t"
-               "mov.l  @(8,%0), %1\n\t"
-               "shal   %1\n\t"
-               "cmp/pl %2\n\t"
-               "rotcr  %1\n\t"
-               "mov.l  %1, @(8,%0)"
-               : "=&r" (ti), "=&r" (flag)
-               : "r" (s.is_user_space)
-               : "t");
-/****
-       if (s.is_user_space)
-               set_thread_flag(TIF_USERSPACE);
-       else
-               clear_thread_flag(TIF_USERSPACE);
-****/
-}
+#define get_fs()       (current_thread_info()->addr_limit)
+#define set_fs(x)      (current_thread_info()->addr_limit = (x))
 
 /*
  * __access_ok: Check if address with size is OK or not.
@@ -108,7 +78,7 @@ static inline void set_fs(mm_segment_t s)
  * We do three checks:
  * (1) is it user space? 
  * (2) addr + size --> carry?
- * (3) addr + size >= 0x80000000  (USER_ADDR_LIMIT)
+ * (3) addr + size >= 0x80000000  (PAGE_OFFSET)
  *
  * (1) (2) (3) | RESULT
  *  0   0   0  |  ok
@@ -201,6 +171,7 @@ do {                                                                \
        __gu_err;                                               \
 })
 
+#ifdef CONFIG_MMU
 #define __get_user_check(x,ptr,size)                           \
 ({                                                             \
        long __gu_err, __gu_val;                                \
@@ -290,6 +261,18 @@ __asm__("stc       r7_bank, %1\n\t"                \
        : "r" (addr)                            \
        : "t");                                 \
 })
+#else /* CONFIG_MMU */
+#define __get_user_check(x,ptr,size)                                   \
+({                                                                     \
+       long __gu_err, __gu_val;                                        \
+       if (__access_ok((unsigned long)(ptr), (size))) {                \
+               __get_user_size(__gu_val, (ptr), (size), __gu_err);     \
+               (x) = (__typeof__(*(ptr)))__gu_val;                     \
+       } else                                                          \
+               __gu_err = -EFAULT;                                     \
+       __gu_err;                                                       \
+})
+#endif
 
 #define __get_user_asm(x, addr, err, insn) \
 ({ \
@@ -541,7 +524,7 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
                "3:\n\t"
                "mov.l  4f, %1\n\t"
                "jmp    @%1\n\t"
-               " mov   %5, %0\n"
+               " mov   #0, %0\n"
                ".balign 4\n"
                "4:     .long 2b\n"
                ".previous\n"
@@ -550,26 +533,20 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
                "       .long 1b,3b\n"
                ".previous"
                : "=z" (res), "=&r" (__dummy)
-               : "0" (0), "r" (__s), "r" (__n), "i" (-EFAULT)
+               : "0" (0), "r" (__s), "r" (__n)
                : "t");
        return res;
 }
 
 static __inline__ long strnlen_user(const char __user *s, long n)
 {
-       if (!access_ok(VERIFY_READ, s, n))
+       if (!__addr_ok(s))
                return 0;
        else
                return __strnlen_user(s, n);
 }
 
-static __inline__ long strlen_user(const char __user *s)
-{
-       if (!access_ok(VERIFY_READ, s, 0))
-               return 0;
-       else
-               return __strnlen_user(s, ~0UL >> 1);
-}
+#define strlen_user(str)       strnlen_user(str, ~0UL >> 1)
 
 /*
  * The exception table consists of pairs of addresses: the first is the
index 76b5430cb4580ae09995ce8979a078ceb4ba84e9..5d5e9f94def587192e726bb59c5079585580629f 100644 (file)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
 #define __NR_kexec_load                283
 #define __NR_waitid            284
-#define __NR_add_key           285
-#define __NR_request_key       286
-#define __NR_keyctl            287
-#define __NR_ioprio_set                288
-#define __NR_ioprio_get                289
-#define __NR_inotify_init      290
-#define __NR_inotify_add_watch 291
-#define __NR_inotify_rm_watch  292
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_add_key           286
+#define __NR_request_key       287
+#define __NR_keyctl            288
+#define __NR_ioprio_set                289
+#define __NR_ioprio_get                290
+#define __NR_inotify_init      291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch  293
+#define __NR_migrate_pages     294
+#define __NR_openat            295
+#define __NR_mkdirat           296
+#define __NR_mknodat           297
+#define __NR_fchownat          298
+#define __NR_futimesat         299
+#define __NR_newfstatat                300
+#define __NR_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#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_syscalls 293
+#define NR_syscalls 317
 
 #ifdef __KERNEL__
 
-/* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
+#include <linux/err.h>
+
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO:
+ * see <asm-sh/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-124)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* Avoid using "res" which is declared to be in register r0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
@@ -444,6 +470,7 @@ __syscall_return(type,__sc0); \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 #ifdef __KERNEL_SYSCALLS__
 
diff --git a/include/asm-sh/voyagergx.h b/include/asm-sh/voyagergx.h
new file mode 100644 (file)
index 0000000..99b0807
--- /dev/null
@@ -0,0 +1,313 @@
+/* -------------------------------------------------------------------- */
+/* voyagergx.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.
+
+    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.
+
+    Copyright 2003 (c) Lineo uSolutions,Inc.
+*/
+/* -------------------------------------------------------------------- */
+
+#ifndef _VOYAGER_GX_REG_H
+#define _VOYAGER_GX_REG_H
+
+#define VOYAGER_BASE                   0xb3e00000
+#define VOYAGER_USBH_BASE              (0x40000 + VOYAGER_BASE)
+#define VOYAGER_UART_BASE              (0x30000 + VOYAGER_BASE)
+#define        VOYAGER_AC97_BASE               (0xa0000 + VOYAGER_BASE)
+
+#define VOYAGER_IRQ_NUM                        32
+#define VOYAGER_IRQ_BASE               50
+#define VOYAGER_USBH_IRQ               VOYAGER_IRQ_BASE + 6
+#define VOYAGER_8051_IRQ               VOYAGER_IRQ_BASE + 10
+#define VOYAGER_UART0_IRQ              VOYAGER_IRQ_BASE + 12
+#define VOYAGER_UART1_IRQ              VOYAGER_IRQ_BASE + 13
+#define        VOYAGER_AC97_IRQ                VOYAGER_IRQ_BASE + 17
+
+/* ----- MISC controle  register ------------------------------ */
+#define MISC_CTRL                      (0x000004 + VOYAGER_BASE)
+#define MISC_CTRL_USBCLK_48            (3 << 28)
+#define MISC_CTRL_USBCLK_96            (2 << 28)
+#define MISC_CTRL_USBCLK_CRYSTAL       (1 << 28)
+
+/* ----- GPIO[31:0] register --------------------------------- */
+#define GPIO_MUX_LOW                   (0x000008 + VOYAGER_BASE)
+#define GPIO_MUX_LOW_AC97              0x1F000000
+#define GPIO_MUX_LOW_8051              0x0000ffff
+#define GPIO_MUX_LOW_PWM               (1 << 29)
+
+/* ----- GPIO[63:32] register --------------------------------- */
+#define GPIO_MUX_HIGH                  (0x00000C + VOYAGER_BASE)
+
+/* ----- DRAM controle  register ------------------------------- */
+#define DRAM_CTRL                      (0x000010 + VOYAGER_BASE)
+#define DRAM_CTRL_EMBEDDED             (1 << 31)
+#define DRAM_CTRL_CPU_BURST_1          (0 << 28)
+#define DRAM_CTRL_CPU_BURST_2          (1 << 28)
+#define DRAM_CTRL_CPU_BURST_4          (2 << 28)
+#define DRAM_CTRL_CPU_BURST_8          (3 << 28)
+#define DRAM_CTRL_CPU_CAS_LATENCY      (1 << 27)
+#define DRAM_CTRL_CPU_SIZE_2           (0 << 24)
+#define DRAM_CTRL_CPU_SIZE_4           (1 << 24)
+#define DRAM_CTRL_CPU_SIZE_64          (4 << 24)
+#define DRAM_CTRL_CPU_SIZE_32          (5 << 24)
+#define DRAM_CTRL_CPU_SIZE_16          (6 << 24)
+#define DRAM_CTRL_CPU_SIZE_8           (7 << 24)
+#define DRAM_CTRL_CPU_COLUMN_SIZE_1024 (0 << 22)
+#define DRAM_CTRL_CPU_COLUMN_SIZE_512  (2 << 22)
+#define DRAM_CTRL_CPU_COLUMN_SIZE_256  (3 << 22)
+#define DRAM_CTRL_CPU_ACTIVE_PRECHARGE (1 << 21)
+#define DRAM_CTRL_CPU_RESET            (1 << 20)
+#define DRAM_CTRL_CPU_BANKS            (1 << 19)
+#define DRAM_CTRL_CPU_WRITE_PRECHARGE  (1 << 18)
+#define DRAM_CTRL_BLOCK_WRITE          (1 << 17)
+#define DRAM_CTRL_REFRESH_COMMAND      (1 << 16)
+#define DRAM_CTRL_SIZE_4               (0 << 13)
+#define DRAM_CTRL_SIZE_8               (1 << 13)
+#define DRAM_CTRL_SIZE_16              (2 << 13)
+#define DRAM_CTRL_SIZE_32              (3 << 13)
+#define DRAM_CTRL_SIZE_64              (4 << 13)
+#define DRAM_CTRL_SIZE_2               (5 << 13)
+#define DRAM_CTRL_COLUMN_SIZE_256      (0 << 11)
+#define DRAM_CTRL_COLUMN_SIZE_512      (2 << 11)
+#define DRAM_CTRL_COLUMN_SIZE_1024     (3 << 11)
+#define DRAM_CTRL_BLOCK_WRITE_TIME     (1 << 10)
+#define DRAM_CTRL_BLOCK_WRITE_PRECHARGE        (1 << 9)
+#define DRAM_CTRL_ACTIVE_PRECHARGE     (1 << 8)
+#define DRAM_CTRL_RESET                        (1 << 7)
+#define DRAM_CTRL_REMAIN_ACTIVE                (1 << 6)
+#define DRAM_CTRL_BANKS                        (1 << 1)
+#define DRAM_CTRL_WRITE_PRECHARGE      (1 << 0)
+
+/* ----- Arvitration control register -------------------------- */
+#define ARBITRATION_CTRL               (0x000014 + VOYAGER_BASE)
+#define ARBITRATION_CTRL_CPUMEM                (1 << 29)
+#define ARBITRATION_CTRL_INTMEM                (1 << 28)
+#define ARBITRATION_CTRL_USB_OFF       (0 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_1        (1 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_2        (2 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_3        (3 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_4        (4 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_5        (5 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_6        (6 << 24)
+#define ARBITRATION_CTRL_USB_PRIORITY_7        (7 << 24)
+#define ARBITRATION_CTRL_PANEL_OFF     (0 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_1      (1 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_2      (2 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_3      (3 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_4      (4 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_5      (5 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_6      (6 << 20)
+#define ARBITRATION_CTRL_PANEL_PRIORITY_7      (7 << 20)
+#define ARBITRATION_CTRL_ZVPORT_OFF    (0 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_1    (1 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_2    (2 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_3    (3 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_4    (4 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_5    (5 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_6    (6 << 16)
+#define ARBITRATION_CTRL_ZVPORTL_PRIORITY_7    (7 << 16)
+#define ARBITRATION_CTRL_CMD_INTPR_OFF (0 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_1  (1 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_2  (2 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_3  (3 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_4  (4 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_5  (5 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_6  (6 << 12)
+#define ARBITRATION_CTRL_CMD_INTPR_PRIORITY_7  (7 << 12)
+#define ARBITRATION_CTRL_DMA_OFF       (0 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_1        (1 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_2        (2 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_3        (3 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_4        (4 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_5        (5 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_6        (6 << 8)
+#define ARBITRATION_CTRL_DMA_PRIORITY_7        (7 << 8)
+#define ARBITRATION_CTRL_VIDEO_OFF     (0 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_1      (1 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_2      (2 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_3      (3 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_4      (4 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_5      (5 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_6      (6 << 4)
+#define ARBITRATION_CTRL_VIDEO_PRIORITY_7      (7 << 4)
+#define ARBITRATION_CTRL_CRT_OFF       (0 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_1        (1 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_2        (2 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_3        (3 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_4        (4 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_5        (5 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_6        (6 << 0)
+#define ARBITRATION_CTRL_CRT_PRIORITY_7        (7 << 0)
+
+/* ----- Command list status register -------------------------- */
+#define CMD_INTPR_STATUS               (0x000024 + VOYAGER_BASE)
+
+/* ----- Interrupt status register ----------------------------- */
+#define INT_STATUS                     (0x00002c + VOYAGER_BASE)
+#define INT_STATUS_UH                  (1 << 6)
+#define INT_STATUS_MC                  (1 << 10)
+#define INT_STATUS_U0                  (1 << 12)
+#define INT_STATUS_U1                  (1 << 13)
+#define        INT_STATUS_AC                   (1 << 17)
+
+/* ----- Interrupt mask register ------------------------------ */
+#define VOYAGER_INT_MASK               (0x000030 + VOYAGER_BASE)
+#define VOYAGER_INT_MASK_AC            (1 << 17)
+
+/* ----- Current Gate register ---------------------------------*/
+#define CURRENT_GATE                   (0x000038 + VOYAGER_BASE)
+
+/* ----- Power mode 0 gate register --------------------------- */
+#define POWER_MODE0_GATE               (0x000040 + VOYAGER_BASE)
+#define POWER_MODE0_GATE_G             (1 << 6)
+#define POWER_MODE0_GATE_U0            (1 << 7)
+#define POWER_MODE0_GATE_U1            (1 << 8)
+#define POWER_MODE0_GATE_UH            (1 << 11)
+#define        POWER_MODE0_GATE_AC             (1 << 18)
+
+/* ----- Power mode 1 gate register --------------------------- */
+#define POWER_MODE1_GATE               (0x000048 + VOYAGER_BASE)
+#define POWER_MODE1_GATE_G             (1 << 6)
+#define POWER_MODE1_GATE_U0            (1 << 7)
+#define POWER_MODE1_GATE_U1            (1 << 8)
+#define POWER_MODE1_GATE_UH            (1 << 11)
+#define        POWER_MODE1_GATE_AC             (1 << 18)
+
+/* ----- Power mode 0 clock register -------------------------- */
+#define POWER_MODE0_CLOCK              (0x000044 + VOYAGER_BASE)
+
+/* ----- Power mode 1 clock register -------------------------- */
+#define POWER_MODE1_CLOCK              (0x00004C + VOYAGER_BASE)
+
+/* ----- Power mode controll register ------------------------- */
+#define POWER_MODE_CTRL                        (0x000054 + VOYAGER_BASE)
+
+/* ----- Miscellaneous Timing register ------------------------ */
+#define SYSTEM_DRAM_CTRL               (0x000068 + VOYAGER_BASE)
+
+/* ----- PWM register ------------------------------------------*/
+#define PWM_0                          (0x010020 + VOYAGER_BASE)
+#define PWM_0_HC(x)                    (((x)&0x0fff)<<20)
+#define PWM_0_LC(x)                    (((x)&0x0fff)<<8 )
+#define PWM_0_CLK_DEV(x)               (((x)&0x000f)<<4 )
+#define PWM_0_EN                       (1<<0)
+
+/* ----- I2C register ----------------------------------------- */
+#define I2C_BYTECOUNT                  (0x010040 + VOYAGER_BASE)
+#define I2C_CONTROL                    (0x010041 + VOYAGER_BASE)
+#define I2C_STATUS                     (0x010042 + VOYAGER_BASE)
+#define I2C_RESET                      (0x010042 + VOYAGER_BASE)
+#define I2C_SADDRESS                   (0x010043 + VOYAGER_BASE)
+#define I2C_DATA                       (0x010044 + VOYAGER_BASE)
+
+/* ----- Controle register bits ----------------------------------------- */
+#define I2C_CONTROL_E                  (1 << 0)
+#define I2C_CONTROL_MODE               (1 << 1)
+#define I2C_CONTROL_STATUS             (1 << 2)
+#define I2C_CONTROL_INT                        (1 << 4)
+#define I2C_CONTROL_INTACK             (1 << 5)
+#define I2C_CONTROL_REPEAT             (1 << 6)
+
+/* ----- Status register bits ----------------------------------------- */
+#define I2C_STATUS_BUSY                        (1 << 0)
+#define I2C_STATUS_ACK                 (1 << 1)
+#define I2C_STATUS_ERROR               (1 << 2)
+#define I2C_STATUS_COMPLETE            (1 << 3)
+
+/* ----- Reset register  ---------------------------------------------- */
+#define I2C_RESET_ERROR                        (1 << 2)
+
+/* ----- transmission frequencies ------------------------------------- */
+#define I2C_SADDRESS_SELECT            (1 << 0)
+
+/* ----- Display Controll register ----------------------------------------- */
+#define PANEL_DISPLAY_CTRL             (0x080000 + VOYAGER_BASE)
+#define PANEL_DISPLAY_CTRL_BIAS         (1<<26)
+#define PANEL_PAN_CTRL                 (0x080004 + VOYAGER_BASE)
+#define PANEL_COLOR_KEY                        (0x080008 + VOYAGER_BASE)
+#define PANEL_FB_ADDRESS               (0x08000C + VOYAGER_BASE)
+#define PANEL_FB_WIDTH                 (0x080010 + VOYAGER_BASE)
+#define PANEL_WINDOW_WIDTH             (0x080014 + VOYAGER_BASE)
+#define PANEL_WINDOW_HEIGHT            (0x080018 + VOYAGER_BASE)
+#define PANEL_PLANE_TL                 (0x08001C + VOYAGER_BASE)
+#define PANEL_PLANE_BR                 (0x080020 + VOYAGER_BASE)
+#define PANEL_HORIZONTAL_TOTAL         (0x080024 + VOYAGER_BASE)
+#define PANEL_HORIZONTAL_SYNC          (0x080028 + VOYAGER_BASE)
+#define PANEL_VERTICAL_TOTAL           (0x08002C + VOYAGER_BASE)
+#define PANEL_VERTICAL_SYNC            (0x080030 + VOYAGER_BASE)
+#define PANEL_CURRENT_LINE             (0x080034 + VOYAGER_BASE)
+#define VIDEO_DISPLAY_CTRL             (0x080040 + VOYAGER_BASE)
+#define VIDEO_FB_0_ADDRESS             (0x080044 + VOYAGER_BASE)
+#define VIDEO_FB_WIDTH                 (0x080048 + VOYAGER_BASE)
+#define VIDEO_FB_0_LAST_ADDRESS                (0x08004C + VOYAGER_BASE)
+#define VIDEO_PLANE_TL                 (0x080050 + VOYAGER_BASE)
+#define VIDEO_PLANE_BR                 (0x080054 + VOYAGER_BASE)
+#define VIDEO_SCALE                    (0x080058 + VOYAGER_BASE)
+#define VIDEO_INITIAL_SCALE            (0x08005C + VOYAGER_BASE)
+#define VIDEO_YUV_CONSTANTS            (0x080060 + VOYAGER_BASE)
+#define VIDEO_FB_1_ADDRESS             (0x080064 + VOYAGER_BASE)
+#define VIDEO_FB_1_LAST_ADDRESS                (0x080068 + VOYAGER_BASE)
+#define VIDEO_ALPHA_DISPLAY_CTRL       (0x080080 + VOYAGER_BASE)
+#define VIDEO_ALPHA_FB_ADDRESS         (0x080084 + VOYAGER_BASE)
+#define VIDEO_ALPHA_FB_WIDTH           (0x080088 + VOYAGER_BASE)
+#define VIDEO_ALPHA_FB_LAST_ADDRESS    (0x08008C + VOYAGER_BASE)
+#define VIDEO_ALPHA_PLANE_TL           (0x080090 + VOYAGER_BASE)
+#define VIDEO_ALPHA_PLANE_BR           (0x080094 + VOYAGER_BASE)
+#define VIDEO_ALPHA_SCALE              (0x080098 + VOYAGER_BASE)
+#define VIDEO_ALPHA_INITIAL_SCALE      (0x08009C + VOYAGER_BASE)
+#define VIDEO_ALPHA_CHROMA_KEY         (0x0800A0 + VOYAGER_BASE)
+#define PANEL_HWC_ADDRESS              (0x0800F0 + VOYAGER_BASE)
+#define PANEL_HWC_LOCATION             (0x0800F4 + VOYAGER_BASE)
+#define PANEL_HWC_COLOR_12             (0x0800F8 + VOYAGER_BASE)
+#define PANEL_HWC_COLOR_3              (0x0800FC + VOYAGER_BASE)
+#define ALPHA_DISPLAY_CTRL             (0x080100 + VOYAGER_BASE)
+#define ALPHA_FB_ADDRESS               (0x080104 + VOYAGER_BASE)
+#define ALPHA_FB_WIDTH                 (0x080108 + VOYAGER_BASE)
+#define ALPHA_PLANE_TL                 (0x08010C + VOYAGER_BASE)
+#define ALPHA_PLANE_BR                 (0x080110 + VOYAGER_BASE)
+#define ALPHA_CHROMA_KEY               (0x080114 + VOYAGER_BASE)
+#define CRT_DISPLAY_CTRL               (0x080200 + VOYAGER_BASE)
+#define CRT_FB_ADDRESS                 (0x080204 + VOYAGER_BASE)
+#define CRT_FB_WIDTH                   (0x080208 + VOYAGER_BASE)
+#define CRT_HORIZONTAL_TOTAL           (0x08020C + VOYAGER_BASE)
+#define CRT_HORIZONTAL_SYNC            (0x080210 + VOYAGER_BASE)
+#define CRT_VERTICAL_TOTAL             (0x080214 + VOYAGER_BASE)
+#define CRT_VERTICAL_SYNC              (0x080218 + VOYAGER_BASE)
+#define CRT_SIGNATURE_ANALYZER         (0x08021C + VOYAGER_BASE)
+#define CRT_CURRENT_LINE               (0x080220 + VOYAGER_BASE)
+#define CRT_MONITOR_DETECT             (0x080224 + VOYAGER_BASE)
+#define CRT_HWC_ADDRESS                        (0x080230 + VOYAGER_BASE)
+#define CRT_HWC_LOCATION               (0x080234 + VOYAGER_BASE)
+#define CRT_HWC_COLOR_12               (0x080238 + VOYAGER_BASE)
+#define CRT_HWC_COLOR_3                        (0x08023C + VOYAGER_BASE)
+#define CRT_PALETTE_RAM                        (0x080400 + VOYAGER_BASE)
+#define PANEL_PALETTE_RAM              (0x080800 + VOYAGER_BASE)
+#define VIDEO_PALETTE_RAM              (0x080C00 + VOYAGER_BASE)
+
+/* ----- 8051 Controle register ----------------------------------------- */
+#define VOYAGER_8051_BASE              (0x000c0000 + VOYAGER_BASE)
+#define VOYAGER_8051_RESET             (0x000b0000 + VOYAGER_BASE)
+#define VOYAGER_8051_SELECT            (0x000b0004 + VOYAGER_BASE)
+#define VOYAGER_8051_CPU_INT           (0x000b000c + VOYAGER_BASE)
+
+/* ----- AC97 Controle register ----------------------------------------- */
+#define AC97_TX_SLOT0                  (0x00000000 + VOYAGER_AC97_BASE)
+#define AC97_CONTROL_STATUS            (0x00000080 + VOYAGER_AC97_BASE)
+#define AC97C_READ                     (1 << 19)
+#define AC97C_WD_BIT                   (1 << 2)
+#define AC97C_INDEX_MASK               0x7f
+/* -------------------------------------------------------------------- */
+
+#endif /* _VOYAGER_GX_REG_H */
index 09ca41972a11ce49d091fdc52d672a4e48e9af81..d19ea62ef8c674c953c5e89cdd62c75359778f5a 100644 (file)
@@ -62,7 +62,6 @@
 
 /**
  *     sh_wdt_read_cnt - Read from Counter
- *
  *     Reads back the WTCNT value.
  */
 static inline __u8 sh_wdt_read_cnt(void)
@@ -72,7 +71,6 @@ static inline __u8 sh_wdt_read_cnt(void)
 
 /**
  *     sh_wdt_write_cnt - Write to Counter
- *
  *     @val: Value to write
  *
  *     Writes the given value @val to the lower byte of the timer counter.
@@ -95,7 +93,6 @@ static inline __u8 sh_wdt_read_csr(void)
 
 /**
  *     sh_wdt_write_csr - Write to Control/Status Register
- *
  *     @val: Value to write
  *
  *     Writes the given value @val to the lower byte of the control/status
index 1fab96d792bff9452cd2335db32f7abdddc11ce3..0b01c3beb2f8625cf1da858c4b61c246b5944b8a 100644 (file)
@@ -30,7 +30,6 @@ extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
 extern char pckbd_unexpected_up(unsigned char keycode);
 extern void pckbd_leds(unsigned char leds);
 extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[128];
 
 #define kbd_setkeycode         pckbd_setkeycode
 #define kbd_getkeycode         pckbd_getkeycode
@@ -38,9 +37,6 @@ extern unsigned char pckbd_sysrq_xlate[128];
 #define kbd_unexpected_up      pckbd_unexpected_up
 #define kbd_leds               pckbd_leds
 #define kbd_init_hw            pckbd_init_hw
-#define kbd_sysrq_xlate                pckbd_sysrq_xlate
-
-#define SYSRQ_KEY 0x54
 
 /* resource allocation */
 #define kbd_request_region()
index af0b792696615058268ce878567f7f23f6ae31dc..163e2b62fe278be34955a30468073af09334913f 100644 (file)
@@ -17,9 +17,6 @@
 
 #define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
 #define CLOCK_TICK_FACTOR      20      /* Factor of both 1000000 and CLOCK_TICK_RATE */
-#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
-       (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
-               << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
 
 typedef unsigned long cycles_t;
 
index 9a1590fffc1533d86ef6f1c670df551b7874f4d4..c113566bef3320b348f337a684688323b3e723f6 100644 (file)
 #ifdef __KERNEL__ 
 
 #define NR_syscalls 321
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO:
+ * see <asm-sh64/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
@@ -358,7 +360,7 @@ do { \
        **       life easier in the system call epilogue (see entry.S)      \
        */                                                                  \
         register unsigned long __sr2 __asm__ ("r2") = res;                 \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {          \
                errno = -(res);                                             \
                __sr2 = -1;                                                 \
        } \
index 1c75474ba1df706b1abb5e9c96b50f8fc18dfc5b..557d08959d2f319ce90b491672c9d4ba518ec471 100644 (file)
@@ -154,6 +154,10 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 #define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #define __raw_read_can_lock(rw) (!((rw)->lock & 0xff))
 #define __raw_write_can_lock(rw) (!(rw)->lock)
 
index bd5ffc76bc7e6774274b596ca8b43154c894ed08..0006fe9f8c7a03cab556cec5119ad5c016608e74 100644 (file)
@@ -241,6 +241,10 @@ static int inline __write_trylock(raw_rwlock_t *lock)
 #define __raw_read_can_lock(rw)                (!((rw)->lock & 0x80000000UL))
 #define __raw_write_can_lock(rw)       (!(rw)->lock)
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_SPINLOCK_H) */
index 4862daf8b9068390c31e247d7fc2ed34dce7f9e7..188f726217766f8e45bc7dce5a130e509d9b2f68 100644 (file)
@@ -274,12 +274,6 @@ static inline pte_t pte_mkread(pte_t pte)
        return(pte_mknewprot(pte)); 
 }
 
-static inline pte_t pte_mkexec(pte_t pte)
-{ 
-       pte_set_bits(pte, _PAGE_USER);
-       return(pte_mknewprot(pte)); 
-}
-
 static inline pte_t pte_mkdirty(pte_t pte)
 { 
        pte_set_bits(pte, _PAGE_DIRTY);
index afa4fe1ca9f13eaba82ebd9b33df0602e47ca022..d99bbddffdb99781730f50d66155abf80d80afc1 100644 (file)
@@ -13,6 +13,7 @@ struct task_struct;
 #include "asm/ptrace.h"
 #include "choose-mode.h"
 #include "registers.h"
+#include "sysdep/archsetjmp.h"
 
 struct mm_struct;
 
@@ -43,8 +44,7 @@ struct thread_struct {
 #endif
 #ifdef CONFIG_MODE_SKAS
                struct {
-                       void *switch_buf;
-                       void *fork_buf;
+                       jmp_buf switch_buf;
                        int mm_count;
                } skas;
 #endif
@@ -138,7 +138,7 @@ extern struct cpuinfo_um cpu_data[];
 
 #ifdef CONFIG_MODE_SKAS
 #define KSTK_REG(tsk, reg) \
-       get_thread_reg(reg, tsk->thread.mode.skas.switch_buf)
+       get_thread_reg(reg, &tsk->thread.mode.skas.switch_buf)
 #else
 #define KSTK_REG(tsk, reg) (0xbadbabe)
 #endif
index 2074483e6ca4a2b9306234131bbea080c77dd309..03b4af4ac09a3c82509e93dc835ee84bb7f7d111 100644 (file)
 
 #define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
 
+/* Also defined in sysdep/ptrace.h, so may already be defined. */
+#ifndef FS_BASE
 #define FS_BASE (21 * sizeof(unsigned long))
 #define GS_BASE (22 * sizeof(unsigned long))
 #define DS (23 * sizeof(unsigned long))
 #define ES (24 * sizeof(unsigned long))
 #define FS (25 * sizeof(unsigned long))
 #define GS (26 * sizeof(unsigned long))
+#endif
 
 #define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
 #define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
index bcb44bfe577a58c257b22d591ce9840427e74821..552b7c873a5702790d913ed85a4270baa4b3455e 100644 (file)
 #ifdef __KERNEL__
 
 #include <asm/clinkage.h>
+#include <linux/err.h>
 
 #define __syscall_return(type, res)                                          \
   do {                                                                       \
-         /* user-visible error numbers are in the range -1 - -124:           \
+         /* user-visible error numbers are in the range -1 - -MAX_ERRNO:      \
             see <asm-v850/errno.h> */                                        \
-         if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-125), 0)) { \
+         if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO), 0)) { \
                  errno = -(res);                                             \
                  res = -1;                                                   \
          }                                                                   \
index b6da83dcc7a6690e81bde6956cd16acf6ef12a15..10174b110a5cf9bb332b531c24f2cedef3b35c0a 100644 (file)
@@ -55,13 +55,6 @@ extern dma_addr_t bad_dma_address;
 extern struct dma_mapping_ops* dma_ops;
 extern int iommu_merge;
 
-static inline int valid_dma_direction(int dma_direction)
-{
-       return ((dma_direction == DMA_BIDIRECTIONAL) ||
-               (dma_direction == DMA_TO_DEVICE) ||
-               (dma_direction == DMA_FROM_DEVICE));
-}
-
 static inline int dma_mapping_error(dma_addr_t dma_addr)
 {
        if (dma_ops->mapping_error)
index e15d3c8628f3effcb47aec000b0278ac29ff966f..fa2086774105500f5ac2d7a5f8e1a6bbef219d38 100644 (file)
@@ -47,10 +47,9 @@ extern void e820_print_map(char *who);
 extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
 extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
 
-extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
 extern void e820_setup_gap(void);
-extern unsigned long e820_hole_size(unsigned long start_pfn,
-                                   unsigned long end_pfn);
+extern void e820_register_active_regions(int nid,
+                               unsigned long start_pfn, unsigned long end_pfn);
 
 extern void finish_e820_parsing(void);
 
index cbf2669bca71505013227528f9f779c87c81492a..f367d4014b423b5298df04dfc556ff4d5aeaf3fb 100644 (file)
@@ -70,4 +70,11 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC 2
 #define NMI_INVALID    3
 
+struct ctl_table;
+struct file;
+extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+                       void __user *, size_t *, loff_t *);
+
+extern int unknown_nmi_panic;
+
 #endif /* ASM_NMI_H */
index b73d0c76613c3dabb9be4da43077b6bd0d43ac08..c28fc2db217197e30a99b956aaa523aaefe4bc9b 100644 (file)
@@ -24,8 +24,6 @@ extern void mtrr_bp_init(void);
 #define mtrr_bp_init() do {} while (0)
 #endif
 extern void init_memory_mapping(unsigned long start, unsigned long end);
-extern void size_zones(unsigned long *z, unsigned long *h,
-                       unsigned long start_pfn, unsigned long end_pfn);
 
 extern void system_call(void); 
 extern int kernel_syscall(void);
index 107bd90429e86e14e47185895d9ab222be3b0652..1194888536b93736f3d2616c6cb4eddfd2803e56 100644 (file)
@@ -132,7 +132,7 @@ static inline int down_interruptible(struct semaphore * sem)
                "jns 2f\n\t"
                "call __down_failed_interruptible\n"
                "2:\n"
-               :"=a" (result), "=m" (sem->count)
+               :"=&a" (result), "=m" (sem->count)
                :"D" (sem)
                :"memory");
        return result;
@@ -153,7 +153,7 @@ static inline int down_trylock(struct semaphore * sem)
                "jns 2f\n\t"
                "call __down_failed_trylock\n\t"
                "2:\n"
-               :"=a" (result), "=m" (sem->count)
+               :"=&a" (result), "=m" (sem->count)
                :"D" (sem)
                :"memory","cc");
        return result;
index be7a9e629fb262ebecef04fe3bd454752816c7ae..05ef097ba55b26dccd45d997417228ad79a110ba 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
+#include <asm/processor.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
@@ -132,4 +133,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
                                : "=m" (rw->lock) : : "memory");
 }
 
+#define _raw_spin_relax(lock)  cpu_relax()
+#define _raw_read_relax(lock)  cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
 #endif /* __ASM_SPINLOCK_H */
index e856570c068952045b73bd25a2cf45d22ed7aeb2..19f99178fe83735cc17bff14516f529c17e479c3 100644 (file)
@@ -361,6 +361,11 @@ __must_check unsigned long clear_user(void __user *mem, unsigned long len);
 __must_check unsigned long __clear_user(void __user *mem, unsigned long len);
 
 __must_check long __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size);
-#define __copy_to_user_inatomic copy_user_generic
+
+static __must_check __always_inline int
+__copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+{
+       return copy_user_generic((__force void *)dst, src, size);
+}
 
 #endif /* __X86_64_UACCESS_H */
index eeb98c168e98eaff463a21e2629d575690022d8e..6137146516d3905ef58c931f56fc7951a26ad194 100644 (file)
@@ -623,16 +623,17 @@ __SYSCALL(__NR_move_pages, sys_move_pages)
 #ifdef __KERNEL__
 
 #define __NR_syscall_max __NR_move_pages
+#include <linux/err.h>
 
 #ifndef __NO_STUBS
 
-/* user-visible error numbers are in the range -1 - -4095 */
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO */
 
 #define __syscall_clobber "r11","rcx","memory" 
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-127)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
                errno = -(res); \
                res = -1; \
        } \
index 2281e9399b9677ddf64211164f06d221604c542a..fd452fc2c037d7b08765905161ede0df52ccdef9 100644 (file)
@@ -17,7 +17,6 @@ enum vsyscall_num {
 
 #define __section_vxtime __attribute__ ((unused, __section__ (".vxtime"), aligned(16)))
 #define __section_vgetcpu_mode __attribute__ ((unused, __section__ (".vgetcpu_mode"), aligned(16)))
-#define __section_wall_jiffies __attribute__ ((unused, __section__ (".wall_jiffies"), aligned(16)))
 #define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
 #define __section_sys_tz __attribute__ ((unused, __section__ (".sys_tz"), aligned(16)))
 #define __section_sysctl_vsyscall __attribute__ ((unused, __section__ (".sysctl_vsyscall"), aligned(16)))
@@ -48,14 +47,12 @@ extern struct vxtime_data __vxtime;
 extern int __vgetcpu_mode;
 extern struct timespec __xtime;
 extern volatile unsigned long __jiffies;
-extern unsigned long __wall_jiffies;
 extern struct timezone __sys_tz;
 extern seqlock_t __xtime_lock;
 
 /* kernel space (writeable) */
 extern struct vxtime_data vxtime;
 extern int vgetcpu_mode;
-extern unsigned long wall_jiffies;
 extern struct timezone sys_tz;
 extern int sysctl_vsyscall;
 extern seqlock_t xtime_lock;
index d14a3755a12b96a739f88b5b99303c6b92d700f5..c7b705e66655746a2efce6fdeefbd76f128d0acd 100644 (file)
@@ -31,9 +31,6 @@
 
 #define CLOCK_TICK_RATE        1193180 /* (everyone is using this value) */
 #define CLOCK_TICK_FACTOR       20 /* Factor of both 10^6 and CLOCK_TICK_RATE */
-#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
-       (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
-               << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
 
 #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
 extern unsigned long ccount_per_jiffy;
index 1df2ac30a4d2650fc952b0c0e9862abaac547852..f7a52e19b4bee532fd3fc988ac6421867e123a0f 100644 (file)
@@ -58,6 +58,7 @@ header-y += elf-em.h
 header-y += fadvise.h
 header-y += fd.h
 header-y += fdreg.h
+header-y += fib_rules.h
 header-y += ftape-header-segment.h
 header-y += ftape-vendors.h
 header-y += fuse.h
@@ -70,6 +71,7 @@ header-y += hysdn_if.h
 header-y += i2c-dev.h
 header-y += i8k.h
 header-y += icmp.h
+header-y += if_addr.h
 header-y += if_arcnet.h
 header-y += if_arp.h
 header-y += if_bonding.h
@@ -79,6 +81,7 @@ header-y += if_fddi.h
 header-y += if.h
 header-y += if_hippi.h
 header-y += if_infiniband.h
+header-y += if_link.h
 header-y += if_packet.h
 header-y += if_plip.h
 header-y += if_ppp.h
@@ -110,6 +113,7 @@ header-y += mmtimer.h
 header-y += mqueue.h
 header-y += mtio.h
 header-y += ncp_no.h
+header-y += neighbour.h
 header-y += netfilter_arp.h
 header-y += netrom.h
 header-y += nfs2.h
index e86bae7324d2f7eac86826f6686c69f66b532977..0496d1f0995212b4c8ae873ac5e7159fcab318cb 100644 (file)
@@ -124,16 +124,12 @@ extern void acct_auto_close(struct super_block *sb);
 extern void acct_init_pacct(struct pacct_struct *pacct);
 extern void acct_collect(long exitcode, int group_dead);
 extern void acct_process(void);
-extern void acct_update_integrals(struct task_struct *tsk);
-extern void acct_clear_integrals(struct task_struct *tsk);
 #else
 #define acct_auto_close_mnt(x) do { } while (0)
 #define acct_auto_close(x)     do { } while (0)
 #define acct_init_pacct(x)     do { } while (0)
 #define acct_collect(x,y)      do { } while (0)
 #define acct_process()         do { } while (0)
-#define acct_update_integrals(x)               do { } while (0)
-#define acct_clear_integrals(task)     do { } while (0)
 #endif
 
 /*
diff --git a/include/linux/aer.h b/include/linux/aer.h
new file mode 100644 (file)
index 0000000..402e178
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ */
+
+#ifndef _AER_H_
+#define _AER_H_
+
+#if defined(CONFIG_PCIEAER)
+/* pci-e port driver needs this function to enable aer */
+extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+extern int pci_find_aer_capability(struct pci_dev *dev);
+extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+#else
+#define pci_enable_pcie_error_reporting(dev)           do { } while (0)
+#define pci_find_aer_capability(dev)                   do { } while (0)
+#define pci_disable_pcie_error_reporting(dev)          do { } while (0)
+#define pci_cleanup_aer_uncorrect_error_status(dev)    do { } while (0)
+#endif
+
+#endif //_AER_H_
+
index 00c8efa95cc3ade224b9e7b61033c414f3dfb464..0d71c0041f137e09eb48c06017af91fafb84c22d 100644 (file)
@@ -4,8 +4,10 @@
 #include <linux/list.h>
 #include <linux/workqueue.h>
 #include <linux/aio_abi.h>
+#include <linux/uio.h>
 
 #include <asm/atomic.h>
+#include <linux/uio.h>
 
 #define AIO_MAXSEGS            4
 #define AIO_KIOGRP_NR_ATOMIC   8
@@ -110,8 +112,10 @@ struct kiocb {
        char                    __user *ki_buf; /* remaining iocb->aio_buf */
        size_t                  ki_left;        /* remaining bytes */
        long                    ki_retried;     /* just for testing */
-       long                    ki_kicked;      /* just for testing */
-       long                    ki_queued;      /* just for testing */
+       struct iovec            ki_inline_vec;  /* inline vector */
+       struct iovec            *ki_iovec;
+       unsigned long           ki_nr_segs;
+       unsigned long           ki_cur_seg;
 
        struct list_head        ki_list;        /* the aio core uses this
                                                 * for cancellation */
@@ -213,11 +217,11 @@ int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                                  struct iocb *iocb));
 
 #define get_ioctx(kioctx) do {                                         \
-       BUG_ON(unlikely(atomic_read(&(kioctx)->users) <= 0));           \
+       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
        atomic_inc(&(kioctx)->users);                                   \
 } while (0)
 #define put_ioctx(kioctx) do {                                         \
-       BUG_ON(unlikely(atomic_read(&(kioctx)->users) <= 0));           \
+       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
        if (unlikely(atomic_dec_and_test(&(kioctx)->users)))            \
                __put_ioctx(kioctx);                                    \
 } while (0)
index 30fdcc89d14213fecec5ff69c8dfa98f7e4fa5f2..3466b1d0ffd29ca6bbd8cbed53bac00e861cc94f 100644 (file)
@@ -41,6 +41,8 @@ enum {
         * IOCB_CMD_POLL = 5,
         */
        IOCB_CMD_NOOP = 6,
+       IOCB_CMD_PREADV = 7,
+       IOCB_CMD_PWRITEV = 8,
 };
 
 /* read() from /dev/aio returns these structures. */
index 6ba3aa8a81f4953b84cb1ef0edf093ed1b7af8ad..75b8baca08f3a999d0b84da8d30ea80a35b479ed 100644 (file)
@@ -88,15 +88,7 @@ static inline struct atalk_sock *at_sk(struct sock *sk)
 #include <asm/byteorder.h>
 
 struct ddpehdr {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-       __u16   deh_len:10,
-               deh_hops:4,
-               deh_pad:2;
-#else
-       __u16   deh_pad:2,
-               deh_hops:4,
-               deh_len:10;
-#endif
+       __be16  deh_len_hops;   /* lower 10 bits are length, next 4 - hops */
        __be16  deh_sum;
        __be16  deh_dnet;
        __be16  deh_snet;
@@ -112,36 +104,6 @@ static __inline__ struct ddpehdr *ddp_hdr(struct sk_buff *skb)
        return (struct ddpehdr *)skb->h.raw;
 }
 
-/*
- *     Don't drop the struct into the struct above.  You'll get some
- *     surprise padding.
- */
-struct ddpebits {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-       __u16   deh_len:10,
-               deh_hops:4,
-               deh_pad:2;
-#else
-       __u16   deh_pad:2,
-               deh_hops:4,
-               deh_len:10;
-#endif
-};
-
-/* Short form header */
-struct ddpshdr {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-       __u16   dsh_len:10,
-               dsh_pad:6;
-#else
-       __u16   dsh_pad:6,
-               dsh_len:10;
-#endif
-       __u8    dsh_dport;
-       __u8    dsh_sport;
-       /* And netatalk apps expect to stick the type in themselves */
-};
-
 /* AppleTalk AARP headers */
 struct elapaarp {
        __be16  hw_type;
index f267f2442766d9c07123dfffe7959bfc52685ae3..6f5a1bab8f5012705e0b1d0de7bde0a021962f84 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * 
- * ATM Lan Emulation Daemon vs. driver interface
- *
- * mkiiskila@yahoo.com
+ * ATM Lan Emulation Daemon driver interface
  *
+ * Marko Kiiskila <mkiiskila@yahoo.com>
  */
 
 #ifndef _ATMLEC_H_
 #include <linux/atmioc.h>
 #include <linux/atm.h>
 #include <linux/if_ether.h>
+
 /* ATM lec daemon control socket */
-#define ATMLEC_CTRL _IO('a',ATMIOC_LANE)
-#define ATMLEC_DATA _IO('a',ATMIOC_LANE+1)
-#define ATMLEC_MCAST _IO('a',ATMIOC_LANE+2)
+#define ATMLEC_CTRL    _IO('a', ATMIOC_LANE)
+#define ATMLEC_DATA    _IO('a', ATMIOC_LANE+1)
+#define ATMLEC_MCAST   _IO('a', ATMIOC_LANE+2)
 
 /* Maximum number of LEC interfaces (tweakable) */
 #define MAX_LEC_ITF 48
 
-/* From the total of MAX_LEC_ITF, last NUM_TR_DEVS are reserved for Token Ring.
+/*
+ * From the total of MAX_LEC_ITF, last NUM_TR_DEVS are reserved for Token Ring.
  * E.g. if MAX_LEC_ITF = 48 and NUM_TR_DEVS = 8, then lec0-lec39 are for
  * Ethernet ELANs and lec40-lec47 are for Token Ring ELANS.
  */
 #define NUM_TR_DEVS 8
 
-typedef enum { 
-        l_set_mac_addr,   l_del_mac_addr, 
-        l_svc_setup, 
-        l_addr_delete,    l_topology_change, 
-        l_flush_complete, l_arp_update,
-        l_narp_req, /* LANE2 mandates the use of this */
-        l_config,         l_flush_tran_id, 
-        l_set_lecid,      l_arp_xmt,
-        l_rdesc_arp_xmt,
-        l_associate_req,
-        l_should_bridge   /* should we bridge this MAC? */
+typedef enum {
+       l_set_mac_addr,
+       l_del_mac_addr,
+       l_svc_setup,
+       l_addr_delete,
+       l_topology_change,
+       l_flush_complete,
+       l_arp_update,
+       l_narp_req,             /* LANE2 mandates the use of this */
+       l_config,
+       l_flush_tran_id,
+       l_set_lecid,
+       l_arp_xmt,
+       l_rdesc_arp_xmt,
+       l_associate_req,
+       l_should_bridge         /* should we bridge this MAC? */
 } atmlec_msg_type;
 
 #define ATMLEC_MSG_TYPE_MAX l_should_bridge
 
 struct atmlec_config_msg {
-        unsigned int maximum_unknown_frame_count;
-        unsigned int max_unknown_frame_time;
-        unsigned short max_retry_count;
-        unsigned int aging_time;
-        unsigned int forward_delay_time;
-        unsigned int arp_response_time;
-        unsigned int flush_timeout;
-        unsigned int path_switching_delay;
-        unsigned int  lane_version; /* LANE2: 1 for LANEv1, 2 for LANEv2 */
-        int mtu;
-        int is_proxy;
+       unsigned int maximum_unknown_frame_count;
+       unsigned int max_unknown_frame_time;
+       unsigned short max_retry_count;
+       unsigned int aging_time;
+       unsigned int forward_delay_time;
+       unsigned int arp_response_time;
+       unsigned int flush_timeout;
+       unsigned int path_switching_delay;
+       unsigned int lane_version;      /* LANE2: 1 for LANEv1, 2 for LANEv2 */
+       int mtu;
+       int is_proxy;
 };
+
 struct atmlec_msg {
-        atmlec_msg_type type;
-        int             sizeoftlvs;        /* LANE2: if != 0, tlvs follow */ 
-        union {
-                struct {
-                        unsigned char mac_addr[ETH_ALEN];
-                        unsigned char atm_addr[ATM_ESA_LEN];
-                        unsigned int flag;/* Topology_change flag, 
-                                              remoteflag, permanent flag,
-                                              lecid, transaction id */
-                        unsigned int targetless_le_arp; /* LANE2 */
-                        unsigned int no_source_le_narp; /* LANE2 */
-                } normal;
-                struct atmlec_config_msg config;
-                struct {
-                        uint16_t lec_id;                     /* requestor lec_id  */
-                        uint32_t tran_id;                    /* transaction id    */
-                        unsigned char mac_addr[ETH_ALEN];    /* dst mac addr      */
-                        unsigned char atm_addr[ATM_ESA_LEN]; /* reqestor ATM addr */
-                } proxy;
-                    /* For mapping LE_ARP requests to responses. Filled by */
-        } content;       /* zeppelin, returned by kernel. Used only when proxying */ 
+       atmlec_msg_type type;
+       int sizeoftlvs;         /* LANE2: if != 0, tlvs follow */
+       union {
+               struct {
+                       unsigned char mac_addr[ETH_ALEN];
+                       unsigned char atm_addr[ATM_ESA_LEN];
+                       unsigned int flag;      /*
+                                                * Topology_change flag,
+                                                * remoteflag, permanent flag,
+                                                * lecid, transaction id
+                                                */
+                       unsigned int targetless_le_arp; /* LANE2 */
+                       unsigned int no_source_le_narp; /* LANE2 */
+               } normal;
+               struct atmlec_config_msg config;
+               struct {
+                       uint16_t lec_id;                        /* requestor lec_id  */
+                       uint32_t tran_id;                       /* transaction id    */
+                       unsigned char mac_addr[ETH_ALEN];       /* dst mac addr      */
+                       unsigned char atm_addr[ATM_ESA_LEN];    /* reqestor ATM addr */
+               } proxy;        /*
+                                * For mapping LE_ARP requests to responses. Filled by
+                                * zeppelin, returned by kernel. Used only when proxying
+                                */
+       } content;
 } __ATM_API_ALIGN;
 
 struct atmlec_ioc {
-        int dev_num;
-        unsigned char atm_addr[ATM_ESA_LEN];
-        unsigned char receive;    /* 1= receive vcc, 0 = send vcc */
+       int dev_num;
+       unsigned char atm_addr[ATM_ESA_LEN];
+       unsigned char receive;  /* 1= receive vcc, 0 = send vcc */
 };
 #endif /* _ATMLEC_H_ */
index 40a6c26294ae9fda282d26f27b8f7c9cac622d30..c3aa097518144c14556fef3e9998dbd3e5a46c69 100644 (file)
 #define AUDIT_MAC_POLICY_LOAD  1403    /* Policy file load */
 #define AUDIT_MAC_STATUS       1404    /* Changed enforcing,permissive,off */
 #define AUDIT_MAC_CONFIG_CHANGE        1405    /* Changes to booleans */
+#define AUDIT_MAC_UNLBL_ALLOW  1406    /* NetLabel: allow unlabeled traffic */
+#define AUDIT_MAC_CIPSOV4_ADD  1407    /* NetLabel: add CIPSOv4 DOI entry */
+#define AUDIT_MAC_CIPSOV4_DEL  1408    /* NetLabel: del CIPSOv4 DOI entry */
+#define AUDIT_MAC_MAP_ADD      1409    /* NetLabel: add LSM domain mapping */
+#define AUDIT_MAC_MAP_DEL      1410    /* NetLabel: del LSM domain mapping */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
index 76bdaeab6f622240fe8f898a9caf0815770f7c38..711c321a70119f07b6bc1d6192caec4f64aa017c 100644 (file)
@@ -148,6 +148,7 @@ struct bio {
 #define BIO_RW_BARRIER 2
 #define BIO_RW_FAILFAST        3
 #define BIO_RW_SYNC    4
+#define BIO_RW_META    5
 
 /*
  * upper 16 bits of bi_rw define the io priority of this bio
@@ -178,6 +179,7 @@ struct bio {
 #define bio_sync(bio)          ((bio)->bi_rw & (1 << BIO_RW_SYNC))
 #define bio_failfast(bio)      ((bio)->bi_rw & (1 << BIO_RW_FAILFAST))
 #define bio_rw_ahead(bio)      ((bio)->bi_rw & (1 << BIO_RW_AHEAD))
+#define bio_rw_meta(bio)       ((bio)->bi_rw & (1 << BIO_RW_META))
 
 /*
  * will die
index c773ee545ebd046a7256c3c13a44a1bb894760b2..1d79b8d4ca6dcc21f2e9f80775883350eb389547 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_BLKDEV_H
 #define _LINUX_BLKDEV_H
 
+#include <linux/sched.h>
 #include <linux/major.h>
 #include <linux/genhd.h>
 #include <linux/list.h>
 
 #include <asm/scatterlist.h>
 
+#ifdef CONFIG_LBD
+# include <asm/div64.h>
+# define sector_div(a, b) do_div(a, b)
+#else
+# define sector_div(n, b)( \
+{ \
+       int _res; \
+       _res = (n) % (b); \
+       (n) /= (b); \
+       _res; \
+} \
+)
+#endif
+
+#ifdef CONFIG_BLOCK
+
 struct scsi_ioctl_command;
 
 struct request_queue;
@@ -90,7 +107,7 @@ struct io_context {
        atomic_t refcount;
        struct task_struct *task;
 
-       int (*set_ioprio)(struct io_context *, unsigned int);
+       unsigned int ioprio_changed;
 
        /*
         * For request batching
@@ -104,8 +121,7 @@ struct io_context {
 
 void put_io_context(struct io_context *ioc);
 void exit_io_context(void);
-struct io_context *current_io_context(gfp_t gfp_flags);
-struct io_context *get_io_context(gfp_t gfp_flags);
+struct io_context *get_io_context(gfp_t gfp_flags, int node);
 void copy_io_context(struct io_context **pdst, struct io_context **psrc);
 void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
 
@@ -120,6 +136,90 @@ struct request_list {
        wait_queue_head_t wait[2];
 };
 
+/*
+ * request command types
+ */
+enum rq_cmd_type_bits {
+       REQ_TYPE_FS             = 1,    /* fs request */
+       REQ_TYPE_BLOCK_PC,              /* scsi command */
+       REQ_TYPE_SENSE,                 /* sense request */
+       REQ_TYPE_PM_SUSPEND,            /* suspend request */
+       REQ_TYPE_PM_RESUME,             /* resume request */
+       REQ_TYPE_PM_SHUTDOWN,           /* shutdown request */
+       REQ_TYPE_FLUSH,                 /* flush request */
+       REQ_TYPE_SPECIAL,               /* driver defined type */
+       REQ_TYPE_LINUX_BLOCK,           /* generic block layer message */
+       /*
+        * for ATA/ATAPI devices. this really doesn't belong here, ide should
+        * use REQ_TYPE_SPECIAL and use rq->cmd[0] with the range of driver
+        * private REQ_LB opcodes to differentiate what type of request this is
+        */
+       REQ_TYPE_ATA_CMD,
+       REQ_TYPE_ATA_TASK,
+       REQ_TYPE_ATA_TASKFILE,
+};
+
+/*
+ * For request of type REQ_TYPE_LINUX_BLOCK, rq->cmd[0] is the opcode being
+ * sent down (similar to how REQ_TYPE_BLOCK_PC means that ->cmd[] holds a
+ * SCSI cdb.
+ *
+ * 0x00 -> 0x3f are driver private, to be used for whatever purpose they need,
+ * typically to differentiate REQ_TYPE_SPECIAL requests.
+ *
+ */
+enum {
+       /*
+        * just examples for now
+        */
+       REQ_LB_OP_EJECT = 0x40,         /* eject request */
+       REQ_LB_OP_FLUSH = 0x41,         /* flush device */
+};
+
+/*
+ * request type modified bits. first three bits match BIO_RW* bits, important
+ */
+enum rq_flag_bits {
+       __REQ_RW,               /* not set, read. set, write */
+       __REQ_FAILFAST,         /* no low level driver retries */
+       __REQ_SORTED,           /* elevator knows about this request */
+       __REQ_SOFTBARRIER,      /* may not be passed by ioscheduler */
+       __REQ_HARDBARRIER,      /* may not be passed by drive either */
+       __REQ_FUA,              /* forced unit access */
+       __REQ_NOMERGE,          /* don't touch this for merging */
+       __REQ_STARTED,          /* drive already may have started this one */
+       __REQ_DONTPREP,         /* don't call prep for this one */
+       __REQ_QUEUED,           /* uses queueing */
+       __REQ_ELVPRIV,          /* elevator private data attached */
+       __REQ_FAILED,           /* set if the request failed */
+       __REQ_QUIET,            /* don't worry about errors */
+       __REQ_PREEMPT,          /* set for "ide_preempt" requests */
+       __REQ_ORDERED_COLOR,    /* is before or after barrier */
+       __REQ_RW_SYNC,          /* request is sync (O_DIRECT) */
+       __REQ_ALLOCED,          /* request came from our alloc pool */
+       __REQ_RW_META,          /* metadata io request */
+       __REQ_NR_BITS,          /* stops here */
+};
+
+#define REQ_RW         (1 << __REQ_RW)
+#define REQ_FAILFAST   (1 << __REQ_FAILFAST)
+#define REQ_SORTED     (1 << __REQ_SORTED)
+#define REQ_SOFTBARRIER        (1 << __REQ_SOFTBARRIER)
+#define REQ_HARDBARRIER        (1 << __REQ_HARDBARRIER)
+#define REQ_FUA                (1 << __REQ_FUA)
+#define REQ_NOMERGE    (1 << __REQ_NOMERGE)
+#define REQ_STARTED    (1 << __REQ_STARTED)
+#define REQ_DONTPREP   (1 << __REQ_DONTPREP)
+#define REQ_QUEUED     (1 << __REQ_QUEUED)
+#define REQ_ELVPRIV    (1 << __REQ_ELVPRIV)
+#define REQ_FAILED     (1 << __REQ_FAILED)
+#define REQ_QUIET      (1 << __REQ_QUIET)
+#define REQ_PREEMPT    (1 << __REQ_PREEMPT)
+#define REQ_ORDERED_COLOR      (1 << __REQ_ORDERED_COLOR)
+#define REQ_RW_SYNC    (1 << __REQ_RW_SYNC)
+#define REQ_ALLOCED    (1 << __REQ_ALLOCED)
+#define REQ_RW_META    (1 << __REQ_RW_META)
+
 #define BLK_MAX_CDB    16
 
 /*
@@ -129,30 +229,46 @@ struct request {
        struct list_head queuelist;
        struct list_head donelist;
 
-       unsigned long flags;            /* see REQ_ bits below */
+       request_queue_t *q;
+
+       unsigned int cmd_flags;
+       enum rq_cmd_type_bits cmd_type;
 
        /* Maintain bio traversal state for part by part I/O submission.
         * hard_* are block layer internals, no driver should touch them!
         */
 
        sector_t sector;                /* next sector to submit */
+       sector_t hard_sector;           /* next sector to complete */
        unsigned long nr_sectors;       /* no. of sectors left to submit */
+       unsigned long hard_nr_sectors;  /* no. of sectors left to complete */
        /* no. of sectors left to submit in the current segment */
        unsigned int current_nr_sectors;
 
-       sector_t hard_sector;           /* next sector to complete */
-       unsigned long hard_nr_sectors;  /* no. of sectors left to complete */
        /* no. of sectors left to complete in the current segment */
        unsigned int hard_cur_sectors;
 
        struct bio *bio;
        struct bio *biotail;
 
+       struct hlist_node hash; /* merge hash */
+       /*
+        * The rb_node is only used inside the io scheduler, requests
+        * are pruned when moved to the dispatch queue. So let the
+        * completion_data share space with the rb_node.
+        */
+       union {
+               struct rb_node rb_node; /* sort/lookup */
+               void *completion_data;
+       };
+
+       /*
+        * two pointers are available for the IO schedulers, if they need
+        * more they have to dynamically allocate it.
+        */
        void *elevator_private;
-       void *completion_data;
+       void *elevator_private2;
 
-       int rq_status;  /* should split this into a few status bits */
-       int errors;
        struct gendisk *rq_disk;
        unsigned long start_time;
 
@@ -170,15 +286,13 @@ struct request {
 
        unsigned short ioprio;
 
+       void *special;
+       char *buffer;
+
        int tag;
+       int errors;
 
        int ref_count;
-       request_queue_t *q;
-       struct request_list *rl;
-
-       struct completion *waiting;
-       void *special;
-       char *buffer;
 
        /*
         * when request is used as a packet command carrier
@@ -195,80 +309,14 @@ struct request {
        int retries;
 
        /*
-        * completion callback. end_io_data should be folded in with waiting
+        * completion callback.
         */
        rq_end_io_fn *end_io;
        void *end_io_data;
 };
 
 /*
- * first three bits match BIO_RW* bits, important
- */
-enum rq_flag_bits {
-       __REQ_RW,               /* not set, read. set, write */
-       __REQ_FAILFAST,         /* no low level driver retries */
-       __REQ_SORTED,           /* elevator knows about this request */
-       __REQ_SOFTBARRIER,      /* may not be passed by ioscheduler */
-       __REQ_HARDBARRIER,      /* may not be passed by drive either */
-       __REQ_FUA,              /* forced unit access */
-       __REQ_CMD,              /* is a regular fs rw request */
-       __REQ_NOMERGE,          /* don't touch this for merging */
-       __REQ_STARTED,          /* drive already may have started this one */
-       __REQ_DONTPREP,         /* don't call prep for this one */
-       __REQ_QUEUED,           /* uses queueing */
-       __REQ_ELVPRIV,          /* elevator private data attached */
-       /*
-        * for ATA/ATAPI devices
-        */
-       __REQ_PC,               /* packet command (special) */
-       __REQ_BLOCK_PC,         /* queued down pc from block layer */
-       __REQ_SENSE,            /* sense retrival */
-
-       __REQ_FAILED,           /* set if the request failed */
-       __REQ_QUIET,            /* don't worry about errors */
-       __REQ_SPECIAL,          /* driver suplied command */
-       __REQ_DRIVE_CMD,
-       __REQ_DRIVE_TASK,
-       __REQ_DRIVE_TASKFILE,
-       __REQ_PREEMPT,          /* set for "ide_preempt" requests */
-       __REQ_PM_SUSPEND,       /* suspend request */
-       __REQ_PM_RESUME,        /* resume request */
-       __REQ_PM_SHUTDOWN,      /* shutdown request */
-       __REQ_ORDERED_COLOR,    /* is before or after barrier */
-       __REQ_RW_SYNC,          /* request is sync (O_DIRECT) */
-       __REQ_NR_BITS,          /* stops here */
-};
-
-#define REQ_RW         (1 << __REQ_RW)
-#define REQ_FAILFAST   (1 << __REQ_FAILFAST)
-#define REQ_SORTED     (1 << __REQ_SORTED)
-#define REQ_SOFTBARRIER        (1 << __REQ_SOFTBARRIER)
-#define REQ_HARDBARRIER        (1 << __REQ_HARDBARRIER)
-#define REQ_FUA                (1 << __REQ_FUA)
-#define REQ_CMD                (1 << __REQ_CMD)
-#define REQ_NOMERGE    (1 << __REQ_NOMERGE)
-#define REQ_STARTED    (1 << __REQ_STARTED)
-#define REQ_DONTPREP   (1 << __REQ_DONTPREP)
-#define REQ_QUEUED     (1 << __REQ_QUEUED)
-#define REQ_ELVPRIV    (1 << __REQ_ELVPRIV)
-#define REQ_PC         (1 << __REQ_PC)
-#define REQ_BLOCK_PC   (1 << __REQ_BLOCK_PC)
-#define REQ_SENSE      (1 << __REQ_SENSE)
-#define REQ_FAILED     (1 << __REQ_FAILED)
-#define REQ_QUIET      (1 << __REQ_QUIET)
-#define REQ_SPECIAL    (1 << __REQ_SPECIAL)
-#define REQ_DRIVE_CMD  (1 << __REQ_DRIVE_CMD)
-#define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK)
-#define REQ_DRIVE_TASKFILE     (1 << __REQ_DRIVE_TASKFILE)
-#define REQ_PREEMPT    (1 << __REQ_PREEMPT)
-#define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND)
-#define REQ_PM_RESUME  (1 << __REQ_PM_RESUME)
-#define REQ_PM_SHUTDOWN        (1 << __REQ_PM_SHUTDOWN)
-#define REQ_ORDERED_COLOR      (1 << __REQ_ORDERED_COLOR)
-#define REQ_RW_SYNC    (1 << __REQ_RW_SYNC)
-
-/*
- * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
+ * State information carried for REQ_TYPE_PM_SUSPEND and REQ_TYPE_PM_RESUME
  * requests. Some step values could eventually be made generic.
  */
 struct request_pm_state
@@ -417,9 +465,9 @@ struct request_queue
        unsigned int            sg_timeout;
        unsigned int            sg_reserved_size;
        int                     node;
-
+#ifdef CONFIG_BLK_DEV_IO_TRACE
        struct blk_trace        *blk_trace;
-
+#endif
        /*
         * reserved for flush operations
         */
@@ -432,9 +480,6 @@ struct request_queue
        struct mutex            sysfs_lock;
 };
 
-#define RQ_INACTIVE            (-1)
-#define RQ_ACTIVE              1
-
 #define QUEUE_FLAG_CLUSTER     0       /* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
 #define QUEUE_FLAG_STOPPED     2       /* queue is stopped */
@@ -490,25 +535,34 @@ enum {
 #define blk_queue_stopped(q)   test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
 #define blk_queue_flushing(q)  ((q)->ordseq)
 
-#define blk_fs_request(rq)     ((rq)->flags & REQ_CMD)
-#define blk_pc_request(rq)     ((rq)->flags & REQ_BLOCK_PC)
-#define blk_noretry_request(rq)        ((rq)->flags & REQ_FAILFAST)
-#define blk_rq_started(rq)     ((rq)->flags & REQ_STARTED)
+#define blk_fs_request(rq)     ((rq)->cmd_type == REQ_TYPE_FS)
+#define blk_pc_request(rq)     ((rq)->cmd_type == REQ_TYPE_BLOCK_PC)
+#define blk_special_request(rq)        ((rq)->cmd_type == REQ_TYPE_SPECIAL)
+#define blk_sense_request(rq)  ((rq)->cmd_type == REQ_TYPE_SENSE)
+
+#define blk_noretry_request(rq)        ((rq)->cmd_flags & REQ_FAILFAST)
+#define blk_rq_started(rq)     ((rq)->cmd_flags & REQ_STARTED)
 
 #define blk_account_rq(rq)     (blk_rq_started(rq) && blk_fs_request(rq))
 
-#define blk_pm_suspend_request(rq)     ((rq)->flags & REQ_PM_SUSPEND)
-#define blk_pm_resume_request(rq)      ((rq)->flags & REQ_PM_RESUME)
+#define blk_pm_suspend_request(rq)     ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND)
+#define blk_pm_resume_request(rq)      ((rq)->cmd_type == REQ_TYPE_PM_RESUME)
 #define blk_pm_request(rq)     \
-       ((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME))
+       (blk_pm_suspend_request(rq) || blk_pm_resume_request(rq))
 
-#define blk_sorted_rq(rq)      ((rq)->flags & REQ_SORTED)
-#define blk_barrier_rq(rq)     ((rq)->flags & REQ_HARDBARRIER)
-#define blk_fua_rq(rq)         ((rq)->flags & REQ_FUA)
+#define blk_sorted_rq(rq)      ((rq)->cmd_flags & REQ_SORTED)
+#define blk_barrier_rq(rq)     ((rq)->cmd_flags & REQ_HARDBARRIER)
+#define blk_fua_rq(rq)         ((rq)->cmd_flags & REQ_FUA)
 
 #define list_entry_rq(ptr)     list_entry((ptr), struct request, queuelist)
 
-#define rq_data_dir(rq)                ((rq)->flags & 1)
+#define rq_data_dir(rq)                ((rq)->cmd_flags & 1)
+
+/*
+ * We regard a request as sync, if it's a READ or a SYNC write.
+ */
+#define rq_is_sync(rq)         (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
+#define rq_is_meta(rq)         ((rq)->cmd_flags & REQ_RW_META)
 
 static inline int blk_queue_full(struct request_queue *q, int rw)
 {
@@ -541,13 +595,7 @@ static inline void blk_clear_queue_full(struct request_queue *q, int rw)
 #define RQ_NOMERGE_FLAGS       \
        (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER)
 #define rq_mergeable(rq)       \
-       (!((rq)->flags & RQ_NOMERGE_FLAGS) && blk_fs_request((rq)))
-
-/*
- * noop, requests are automagically marked as active/inactive by I/O
- * scheduler -- see elv_next_request
- */
-#define blk_queue_headactive(q, head_active)
+       (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && blk_fs_request((rq)))
 
 /*
  * q->prep_rq_fn return values
@@ -586,11 +634,6 @@ static inline void blk_queue_bounce(request_queue_t *q, struct bio **bio)
        if ((rq->bio))                  \
                for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next)
 
-struct sec_size {
-       unsigned block_size;
-       unsigned block_size_bits;
-};
-
 extern int blk_register_queue(struct gendisk *disk);
 extern void blk_unregister_queue(struct gendisk *disk);
 extern void register_disk(struct gendisk *dev);
@@ -612,6 +655,7 @@ extern void blk_stop_queue(request_queue_t *q);
 extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(request_queue_t *q);
 extern void blk_run_queue(request_queue_t *);
+extern void blk_start_queueing(request_queue_t *);
 extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
 extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
 extern int blk_rq_unmap_user(struct bio *, unsigned int);
@@ -655,16 +699,6 @@ extern void end_that_request_last(struct request *, int);
 extern void end_request(struct request *req, int uptodate);
 extern void blk_complete_request(struct request *);
 
-static inline int rq_all_done(struct request *rq, unsigned int nr_bytes)
-{
-       if (blk_fs_request(rq))
-               return (nr_bytes >= (rq->hard_nr_sectors << 9));
-       else if (blk_pc_request(rq))
-               return nr_bytes >= rq->data_len;
-
-       return 0;
-}
-
 /*
  * end_that_request_first/chunk() takes an uptodate argument. we account
  * any value <= as an io error. 0 means -EIO for compatability reasons,
@@ -678,21 +712,6 @@ static inline void blkdev_dequeue_request(struct request *req)
        elv_dequeue_request(req->q, req);
 }
 
-/*
- * This should be in elevator.h, but that requires pulling in rq and q
- */
-static inline void elv_dispatch_add_tail(struct request_queue *q,
-                                        struct request *rq)
-{
-       if (q->last_merge == rq)
-               q->last_merge = NULL;
-       q->nr_sorted--;
-
-       q->end_sector = rq_end_sector(rq);
-       q->boundary_rq = rq;
-       list_add_tail(&rq->queuelist, &q->queue_head);
-}
-
 /*
  * Access functions for manipulating queue properties
  */
@@ -737,7 +756,7 @@ extern void blk_put_queue(request_queue_t *);
  */
 #define blk_queue_tag_depth(q)         ((q)->queue_tags->busy)
 #define blk_queue_tag_queue(q)         ((q)->queue_tags->busy < (q)->queue_tags->max_depth)
-#define blk_rq_tagged(rq)              ((rq)->flags & REQ_QUEUED)
+#define blk_rq_tagged(rq)              ((rq)->cmd_flags & REQ_QUEUED)
 extern int blk_queue_start_tag(request_queue_t *, struct request *);
 extern struct request *blk_queue_find_tag(request_queue_t *, int);
 extern void blk_queue_end_tag(request_queue_t *, struct request *);
@@ -787,14 +806,6 @@ static inline int queue_dma_alignment(request_queue_t *q)
        return retval;
 }
 
-static inline int bdev_dma_aligment(struct block_device *bdev)
-{
-       return queue_dma_alignment(bdev_get_queue(bdev));
-}
-
-#define blk_finished_io(nsects)        do { } while (0)
-#define blk_started_io(nsects) do { } while (0)
-
 /* assumes size > 256 */
 static inline unsigned int blksize_bits(unsigned int size)
 {
@@ -824,24 +835,32 @@ struct work_struct;
 int kblockd_schedule_work(struct work_struct *work);
 void kblockd_flush(void);
 
-#ifdef CONFIG_LBD
-# include <asm/div64.h>
-# define sector_div(a, b) do_div(a, b)
-#else
-# define sector_div(n, b)( \
-{ \
-       int _res; \
-       _res = (n) % (b); \
-       (n) /= (b); \
-       _res; \
-} \
-)
-#endif 
-
 #define MODULE_ALIAS_BLOCKDEV(major,minor) \
        MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
        MODULE_ALIAS("block-major-" __stringify(major) "-*")
 
 
+#else /* CONFIG_BLOCK */
+/*
+ * stubs for when the block layer is configured out
+ */
+#define buffer_heads_over_limit 0
+
+static inline long blk_congestion_wait(int rw, long timeout)
+{
+       return io_schedule_timeout(timeout);
+}
+
+static inline long nr_blockdev_pages(void)
+{
+       return 0;
+}
+
+static inline void exit_io_context(void)
+{
+}
+
+#endif /* CONFIG_BLOCK */
+
 #endif
index 7520cc1ff9e2b9d3947f3cb1ace868b329394555..b99a714fcac67adf74e85650abcfa7ecaf6ef7ab 100644 (file)
@@ -20,6 +20,7 @@ enum blktrace_cat {
        BLK_TC_PC       = 1 << 9,       /* pc requests */
        BLK_TC_NOTIFY   = 1 << 10,      /* special message */
        BLK_TC_AHEAD    = 1 << 11,      /* readahead */
+       BLK_TC_META     = 1 << 12,      /* metadata */
 
        BLK_TC_END      = 1 << 15,      /* only 16-bits, reminder */
 };
@@ -148,7 +149,7 @@ static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq,
                                    u32 what)
 {
        struct blk_trace *bt = q->blk_trace;
-       int rw = rq->flags & 0x03;
+       int rw = rq->cmd_flags & 0x03;
 
        if (likely(!bt))
                return;
index 737e407d0cd11e7479e6d38d3cf48562eec4f596..131ffd37e716fb7ac4a386eaea9ff58c26bf639d 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/wait.h>
 #include <asm/atomic.h>
 
+#ifdef CONFIG_BLOCK
+
 enum bh_state_bits {
        BH_Uptodate,    /* Contains valid data */
        BH_Dirty,       /* Is dirty */
@@ -190,9 +192,7 @@ extern int buffer_heads_over_limit;
  * Generic address_space_operations implementations for buffer_head-backed
  * address_spaces.
  */
-int try_to_release_page(struct page * page, gfp_t gfp_mask);
 void block_invalidatepage(struct page *page, unsigned long offset);
-void do_invalidatepage(struct page *page, unsigned long offset);
 int block_write_full_page(struct page *page, get_block_t *get_block,
                                struct writeback_control *wbc);
 int block_read_full_page(struct page*, get_block_t*);
@@ -302,4 +302,19 @@ static inline void lock_buffer(struct buffer_head *bh)
                __lock_buffer(bh);
 }
 
+extern int __set_page_dirty_buffers(struct page *page);
+
+#else /* CONFIG_BLOCK */
+
+static inline void buffer_init(void) {}
+static inline int try_to_free_buffers(struct page *page) { return 1; }
+static inline int sync_blockdev(struct block_device *bdev) { return 0; }
+static inline int inode_has_buffers(struct inode *inode) { return 0; }
+static inline void invalidate_inode_buffers(struct inode *inode) {}
+static inline int remove_inode_buffers(struct inode *inode) { return 1; }
+static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }
+static inline void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) {}
+
+
+#endif /* CONFIG_BLOCK */
 #endif /* _LINUX_BUFFER_HEAD_H */
index 2216638962d2790fa8d5e4776d17559c3717a69a..ee5f53f2ca15a171c74cf3ec392b2b407dc22b8c 100644 (file)
@@ -23,5 +23,7 @@ void cdev_del(struct cdev *);
 
 void cd_forget(struct inode *);
 
+extern struct backing_dev_info directly_mappable_cdev_bdi;
+
 #endif
 #endif
index bea0255196c435c5c1ba986c7c9361034f36ad86..d5b7abc4f409c34ea3e2af5a79369c1e52d7ede0 100644 (file)
@@ -90,6 +90,7 @@ COMPATIBLE_IOCTL(FDTWADDLE)
 COMPATIBLE_IOCTL(FDFMTTRK)
 COMPATIBLE_IOCTL(FDRAWCMD)
 /* 0x12 */
+#ifdef CONFIG_BLOCK
 COMPATIBLE_IOCTL(BLKRASET)
 COMPATIBLE_IOCTL(BLKROSET)
 COMPATIBLE_IOCTL(BLKROGET)
@@ -103,6 +104,7 @@ COMPATIBLE_IOCTL(BLKTRACESETUP)
 COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
 ULONG_IOCTL(BLKRASET)
 ULONG_IOCTL(BLKFRASET)
+#endif
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION)
 COMPATIBLE_IOCTL(GET_ARRAY_INFO)
@@ -395,12 +397,6 @@ COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
 COMPATIBLE_IOCTL(DVD_AUTH)
 /* pktcdvd */
 COMPATIBLE_IOCTL(PACKET_CTRL_CMD)
-/* Big L */
-ULONG_IOCTL(LOOP_SET_FD)
-ULONG_IOCTL(LOOP_CHANGE_FD)
-COMPATIBLE_IOCTL(LOOP_CLR_FD)
-COMPATIBLE_IOCTL(LOOP_GET_STATUS64)
-COMPATIBLE_IOCTL(LOOP_SET_STATUS64)
 /* Big A */
 /* sparc only */
 /* Big Q for sound/OSS */
@@ -573,18 +569,6 @@ COMPATIBLE_IOCTL(RAW_SETBIND)
 COMPATIBLE_IOCTL(RAW_GETBIND)
 /* SMB ioctls which do not need any translations */
 COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
-/* NCP ioctls which do not need any translations */
-COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN)
-COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT)
-COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED)
-COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED)
-COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK)
-COMPATIBLE_IOCTL(NCP_IOC_GETROOT)
-COMPATIBLE_IOCTL(NCP_IOC_SETROOT)
-COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS)
-COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS)
-COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL)
-COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL)
 /* Little a */
 COMPATIBLE_IOCTL(ATMSIGD_CTRL)
 COMPATIBLE_IOCTL(ATMARPD_CTRL)
index 060b96112ec66fcfebcd6e8f5ea4c86f4bec5dde..538423d4a865de29981ff7a2208fb1afc77ccd43 100644 (file)
 # define __force       __attribute__((force))
 # define __nocast      __attribute__((nocast))
 # define __iomem       __attribute__((noderef, address_space(2)))
-# define __acquires(x) __attribute__((context(0,1)))
-# define __releases(x) __attribute__((context(1,0)))
-# define __acquire(x)  __context__(1)
-# define __release(x)  __context__(-1)
-# define __cond_lock(x)        ((x) ? ({ __context__(1); 1; }) : 0)
+# define __acquires(x) __attribute__((context(x,0,1)))
+# define __releases(x) __attribute__((context(x,1,0)))
+# define __acquire(x)  __context__(x,1)
+# define __release(x)  __context__(x,-1)
+# define __cond_lock(x,c)      ((c) ? ({ __acquire(x); 1; }) : 0)
 extern void __chk_user_ptr(void __user *);
 extern void __chk_io_ptr(void __iomem *);
 #else
@@ -31,7 +31,7 @@ extern void __chk_io_ptr(void __iomem *);
 # define __releases(x)
 # define __acquire(x) (void)0
 # define __release(x) (void)0
-# define __cond_lock(x) (x)
+# define __cond_lock(x,c) (c)
 #endif
 
 #ifdef __KERNEL__
index 9354722a9217807cb0d4d6a2d3e716a0db73bb25..4d8adf6636810875b00f070dd548193e620b7015 100644 (file)
@@ -63,6 +63,8 @@ static inline int cpuset_do_slab_mem_spread(void)
        return current->flags & PF_SPREAD_SLAB;
 }
 
+extern void cpuset_track_online_nodes(void);
+
 #else /* !CONFIG_CPUSETS */
 
 static inline int cpuset_init_early(void) { return 0; }
@@ -126,6 +128,8 @@ static inline int cpuset_do_slab_mem_spread(void)
        return 0;
 }
 
+static inline void cpuset_track_online_nodes(void) {}
+
 #endif /* !CONFIG_CPUSETS */
 
 #endif /* _LINUX_CPUSET_H */
index a41f38428c37d794ac80f947502c4142123a4afc..1dba681e428d27e1750652e94b9a84c080cb1b59 100644 (file)
@@ -87,6 +87,6 @@ struct cramfs_super {
 /* Uncompression interfaces to the underlying zlib */
 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
 int cramfs_uncompress_init(void);
-int cramfs_uncompress_exit(void);
+void cramfs_uncompress_exit(void);
 
 #endif
index 635690cf3e3dc77ff54f8d07555da2ffc4dff165..ff203c465fed260f75de3c0d80a71e7d90f101d2 100644 (file)
@@ -24,6 +24,13 @@ enum dma_data_direction {
 #define DMA_28BIT_MASK 0x000000000fffffffULL
 #define DMA_24BIT_MASK 0x0000000000ffffffULL
 
+static inline int valid_dma_direction(int dma_direction)
+{
+       return ((dma_direction == DMA_BIDIRECTIONAL) ||
+               (dma_direction == DMA_TO_DEVICE) ||
+               (dma_direction == DMA_FROM_DEVICE));
+}
+
 #include <asm/dma-mapping.h>
 
 /* Backwards compat, remove in 2.7.x */
index b2cd2071d432d137b8d913134c21b0b93a920b25..38dc403be70b5bc4f49aee4132ba7ea85ca61399 100644 (file)
@@ -27,7 +27,8 @@ enum dmi_device_type {
        DMI_DEV_TYPE_ETHERNET,
        DMI_DEV_TYPE_TOKENRING,
        DMI_DEV_TYPE_SOUND,
-       DMI_DEV_TYPE_IPMI = -1
+       DMI_DEV_TYPE_IPMI = -1,
+       DMI_DEV_TYPE_OEM_STRING = -2
 };
 
 struct dmi_header {
index 4079242dced874a79caf77bb86313a5e1a658bd6..1ff7c1392525884b0f7ee005ae21ff822b01ae56 100644 (file)
@@ -3,8 +3,8 @@
 
 #include <linux/ioport.h>
 #include <linux/device.h>
+#include <linux/mod_devicetable.h>
 
-#define EISA_SIG_LEN   8
 #define EISA_MAX_SLOTS 8
 
 #define EISA_MAX_RESOURCES 4
 #define EISA_CONFIG_ENABLED         1
 #define EISA_CONFIG_FORCED          2
 
-/* The EISA signature, in ASCII form, null terminated */
-struct eisa_device_id {
-       char          sig[EISA_SIG_LEN];
-       unsigned long driver_data;
-};
-
 /* There is not much we can say about an EISA device, apart from
  * signature, slot number, and base address. dma_mask is set by
  * default to parent device mask..*/
index 1713ace808bfb4d581ccfff53aa4b0c42ebfa9ef..b3370ef5164d0589d3300e91162c0b5599045de1 100644 (file)
@@ -1,12 +1,16 @@
 #ifndef _LINUX_ELEVATOR_H
 #define _LINUX_ELEVATOR_H
 
+#include <linux/percpu.h>
+
+#ifdef CONFIG_BLOCK
+
 typedef int (elevator_merge_fn) (request_queue_t *, struct request **,
                                 struct bio *);
 
 typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *);
 
-typedef void (elevator_merged_fn) (request_queue_t *, struct request *);
+typedef void (elevator_merged_fn) (request_queue_t *, struct request *, int);
 
 typedef int (elevator_dispatch_fn) (request_queue_t *, int);
 
@@ -14,9 +18,9 @@ typedef void (elevator_add_req_fn) (request_queue_t *, struct request *);
 typedef int (elevator_queue_empty_fn) (request_queue_t *);
 typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
 typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
-typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *);
+typedef int (elevator_may_queue_fn) (request_queue_t *, int);
 
-typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, gfp_t);
+typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, gfp_t);
 typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
@@ -82,19 +86,21 @@ struct elevator_queue
        struct kobject kobj;
        struct elevator_type *elevator_type;
        struct mutex sysfs_lock;
+       struct hlist_head *hash;
 };
 
 /*
  * block elevator interface
  */
 extern void elv_dispatch_sort(request_queue_t *, struct request *);
+extern void elv_dispatch_add_tail(request_queue_t *, struct request *);
 extern void elv_add_request(request_queue_t *, struct request *, int, int);
 extern void __elv_add_request(request_queue_t *, struct request *, int, int);
 extern void elv_insert(request_queue_t *, struct request *, int);
 extern int elv_merge(request_queue_t *, struct request **, struct bio *);
 extern void elv_merge_requests(request_queue_t *, struct request *,
                               struct request *);
-extern void elv_merged_request(request_queue_t *, struct request *);
+extern void elv_merged_request(request_queue_t *, struct request *, int);
 extern void elv_dequeue_request(request_queue_t *, struct request *);
 extern void elv_requeue_request(request_queue_t *, struct request *);
 extern int elv_queue_empty(request_queue_t *);
@@ -103,9 +109,9 @@ extern struct request *elv_former_request(request_queue_t *, struct request *);
 extern struct request *elv_latter_request(request_queue_t *, struct request *);
 extern int elv_register_queue(request_queue_t *q);
 extern void elv_unregister_queue(request_queue_t *q);
-extern int elv_may_queue(request_queue_t *, int, struct bio *);
+extern int elv_may_queue(request_queue_t *, int);
 extern void elv_completed_request(request_queue_t *, struct request *);
-extern int elv_set_request(request_queue_t *, struct request *, struct bio *, gfp_t);
+extern int elv_set_request(request_queue_t *, struct request *, gfp_t);
 extern void elv_put_request(request_queue_t *, struct request *);
 
 /*
@@ -124,6 +130,19 @@ extern int elevator_init(request_queue_t *, char *);
 extern void elevator_exit(elevator_t *);
 extern int elv_rq_merge_ok(struct request *, struct bio *);
 
+/*
+ * Helper functions.
+ */
+extern struct request *elv_rb_former_request(request_queue_t *, struct request *);
+extern struct request *elv_rb_latter_request(request_queue_t *, struct request *);
+
+/*
+ * rb support functions.
+ */
+extern struct request *elv_rb_add(struct rb_root *, struct request *);
+extern void elv_rb_del(struct rb_root *, struct request *);
+extern struct request *elv_rb_find(struct rb_root *, sector_t);
+
 /*
  * Return values from elevator merger
  */
@@ -149,5 +168,42 @@ enum {
 };
 
 #define rq_end_sector(rq)      ((rq)->sector + (rq)->nr_sectors)
+#define rb_entry_rq(node)      rb_entry((node), struct request, rb_node)
+
+/*
+ * Hack to reuse the donelist list_head as the fifo time holder while
+ * the request is in the io scheduler. Saves an unsigned long in rq.
+ */
+#define rq_fifo_time(rq)       ((unsigned long) (rq)->donelist.next)
+#define rq_set_fifo_time(rq,exp)       ((rq)->donelist.next = (void *) (exp))
+#define rq_entry_fifo(ptr)     list_entry((ptr), struct request, queuelist)
+#define rq_fifo_clear(rq)      do {            \
+       list_del_init(&(rq)->queuelist);        \
+       INIT_LIST_HEAD(&(rq)->donelist);        \
+       } while (0)
 
+/*
+ * io context count accounting
+ */
+#define elv_ioc_count_mod(name, __val)                         \
+       do {                                                    \
+               preempt_disable();                              \
+               __get_cpu_var(name) += (__val);                 \
+               preempt_enable();                               \
+       } while (0)
+
+#define elv_ioc_count_inc(name)        elv_ioc_count_mod(name, 1)
+#define elv_ioc_count_dec(name)        elv_ioc_count_mod(name, -1)
+
+#define elv_ioc_count_read(name)                               \
+({                                                             \
+       unsigned long __val = 0;                                \
+       int __cpu;                                              \
+       smp_wmb();                                              \
+       for_each_possible_cpu(__cpu)                            \
+               __val += per_cpu(name, __cpu);                  \
+       __val;                                                  \
+})
+
+#endif /* CONFIG_BLOCK */
 #endif
index cd3b367f7445e5aa0f25ddbf2f0b96c44a19b94f..1ab1d44f8d3be7a28c8a1a849c72e1f841424015 100644 (file)
@@ -15,6 +15,8 @@
  */
 #define MAX_ERRNO      4095
 
+#ifndef __ASSEMBLY__
+
 #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
 
 static inline void *ERR_PTR(long error)
@@ -32,4 +34,6 @@ static inline long IS_ERR(const void *ptr)
        return IS_ERR_VALUE((unsigned long)ptr);
 }
 
+#endif
+
 #endif /* _LINUX_ERR_H */
index 408118a07763fecc3718d8dcc6569857d3aa52e4..92f8d4fab32be96bd86e29612b78c6a8cb1b952b 100644 (file)
@@ -38,7 +38,7 @@ struct sock_exterr_skb
        } header;
        struct sock_extended_err        ee;
        u16                             addr_offset;
-       u16                             port;
+       __be16                          port;
 };
 
 #endif
index 33a1aa10732916e222347728888b979b69c98b07..153d755376a42344d046482e7c7606dcea4bb373 100644 (file)
@@ -165,41 +165,49 @@ struct ext2_group_desc
 #define        EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
 
 /*
- * Inode flags
+ * Inode flags (GETFLAGS/SETFLAGS)
  */
-#define        EXT2_SECRM_FL                   0x00000001 /* Secure deletion */
-#define        EXT2_UNRM_FL                    0x00000002 /* Undelete */
-#define        EXT2_COMPR_FL                   0x00000004 /* Compress file */
-#define EXT2_SYNC_FL                   0x00000008 /* Synchronous updates */
-#define EXT2_IMMUTABLE_FL              0x00000010 /* Immutable file */
-#define EXT2_APPEND_FL                 0x00000020 /* writes to file may only append */
-#define EXT2_NODUMP_FL                 0x00000040 /* do not dump file */
-#define EXT2_NOATIME_FL                        0x00000080 /* do not update atime */
+#define        EXT2_SECRM_FL                   FS_SECRM_FL     /* Secure deletion */
+#define        EXT2_UNRM_FL                    FS_UNRM_FL      /* Undelete */
+#define        EXT2_COMPR_FL                   FS_COMPR_FL     /* Compress file */
+#define EXT2_SYNC_FL                   FS_SYNC_FL      /* Synchronous updates */
+#define EXT2_IMMUTABLE_FL              FS_IMMUTABLE_FL /* Immutable file */
+#define EXT2_APPEND_FL                 FS_APPEND_FL    /* writes to file may only append */
+#define EXT2_NODUMP_FL                 FS_NODUMP_FL    /* do not dump file */
+#define EXT2_NOATIME_FL                        FS_NOATIME_FL   /* do not update atime */
 /* Reserved for compression usage... */
-#define EXT2_DIRTY_FL                  0x00000100
-#define EXT2_COMPRBLK_FL               0x00000200 /* One or more compressed clusters */
-#define EXT2_NOCOMP_FL                 0x00000400 /* Don't compress */
-#define EXT2_ECOMPR_FL                 0x00000800 /* Compression error */
+#define EXT2_DIRTY_FL                  FS_DIRTY_FL
+#define EXT2_COMPRBLK_FL               FS_COMPRBLK_FL  /* One or more compressed clusters */
+#define EXT2_NOCOMP_FL                 FS_NOCOMP_FL    /* Don't compress */
+#define EXT2_ECOMPR_FL                 FS_ECOMPR_FL    /* Compression error */
 /* End compression flags --- maybe not all used */     
-#define EXT2_BTREE_FL                  0x00001000 /* btree format dir */
-#define EXT2_INDEX_FL                  0x00001000 /* hash-indexed directory */
-#define EXT2_IMAGIC_FL                 0x00002000 /* AFS directory */
-#define EXT2_JOURNAL_DATA_FL           0x00004000 /* Reserved for ext3 */
-#define EXT2_NOTAIL_FL                 0x00008000 /* file tail should not be merged */
-#define EXT2_DIRSYNC_FL                        0x00010000 /* dirsync behaviour (directories only) */
-#define EXT2_TOPDIR_FL                 0x00020000 /* Top of directory hierarchies*/
-#define EXT2_RESERVED_FL               0x80000000 /* reserved for ext2 lib */
-
-#define EXT2_FL_USER_VISIBLE           0x0003DFFF /* User visible flags */
-#define EXT2_FL_USER_MODIFIABLE                0x000380FF /* User modifiable flags */
+#define EXT2_BTREE_FL                  FS_BTREE_FL     /* btree format dir */
+#define EXT2_INDEX_FL                  FS_INDEX_FL     /* hash-indexed directory */
+#define EXT2_IMAGIC_FL                 FS_IMAGIC_FL    /* AFS directory */
+#define EXT2_JOURNAL_DATA_FL           FS_JOURNAL_DATA_FL /* Reserved for ext3 */
+#define EXT2_NOTAIL_FL                 FS_NOTAIL_FL    /* file tail should not be merged */
+#define EXT2_DIRSYNC_FL                        FS_DIRSYNC_FL   /* dirsync behaviour (directories only) */
+#define EXT2_TOPDIR_FL                 FS_TOPDIR_FL    /* Top of directory hierarchies*/
+#define EXT2_RESERVED_FL               FS_RESERVED_FL  /* reserved for ext2 lib */
+
+#define EXT2_FL_USER_VISIBLE           FS_FL_USER_VISIBLE      /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE                FS_FL_USER_MODIFIABLE   /* User modifiable flags */
 
 /*
  * ioctl commands
  */
-#define        EXT2_IOC_GETFLAGS               _IOR('f', 1, long)
-#define        EXT2_IOC_SETFLAGS               _IOW('f', 2, long)
-#define        EXT2_IOC_GETVERSION             _IOR('v', 1, long)
-#define        EXT2_IOC_SETVERSION             _IOW('v', 2, long)
+#define        EXT2_IOC_GETFLAGS               FS_IOC_GETFLAGS
+#define        EXT2_IOC_SETFLAGS               FS_IOC_SETFLAGS
+#define        EXT2_IOC_GETVERSION             FS_IOC_GETVERSION
+#define        EXT2_IOC_SETVERSION             FS_IOC_SETVERSION
+
+/*
+ * ioctl commands in 32 bit emulation
+ */
+#define EXT2_IOC32_GETFLAGS            FS_IOC32_GETFLAGS
+#define EXT2_IOC32_SETFLAGS            FS_IOC32_SETFLAGS
+#define EXT2_IOC32_GETVERSION          FS_IOC32_GETVERSION
+#define EXT2_IOC32_SETVERSION          FS_IOC32_SETVERSION
 
 /*
  * Structure of an inode on the disk
index 0eed918b38168a05a3847a641243a3622862aa10..11cca1bdc0c79840ab69c12b2a538d2a9770fb65 100644 (file)
@@ -216,20 +216,37 @@ struct ext3_new_group_data {
 /*
  * ioctl commands
  */
-#define        EXT3_IOC_GETFLAGS               _IOR('f', 1, long)
-#define        EXT3_IOC_SETFLAGS               _IOW('f', 2, long)
+#define        EXT3_IOC_GETFLAGS               FS_IOC_GETFLAGS
+#define        EXT3_IOC_SETFLAGS               FS_IOC_SETFLAGS
 #define        EXT3_IOC_GETVERSION             _IOR('f', 3, long)
 #define        EXT3_IOC_SETVERSION             _IOW('f', 4, long)
 #define EXT3_IOC_GROUP_EXTEND          _IOW('f', 7, unsigned long)
 #define EXT3_IOC_GROUP_ADD             _IOW('f', 8,struct ext3_new_group_input)
-#define        EXT3_IOC_GETVERSION_OLD         _IOR('v', 1, long)
-#define        EXT3_IOC_SETVERSION_OLD         _IOW('v', 2, long)
+#define        EXT3_IOC_GETVERSION_OLD         FS_IOC_GETVERSION
+#define        EXT3_IOC_SETVERSION_OLD         FS_IOC_SETVERSION
 #ifdef CONFIG_JBD_DEBUG
 #define EXT3_IOC_WAIT_FOR_READONLY     _IOR('f', 99, long)
 #endif
 #define EXT3_IOC_GETRSVSZ              _IOR('f', 5, long)
 #define EXT3_IOC_SETRSVSZ              _IOW('f', 6, long)
 
+/*
+ * ioctl commands in 32 bit emulation
+ */
+#define EXT3_IOC32_GETFLAGS            FS_IOC32_GETFLAGS
+#define EXT3_IOC32_SETFLAGS            FS_IOC32_SETFLAGS
+#define EXT3_IOC32_GETVERSION          _IOR('f', 3, int)
+#define EXT3_IOC32_SETVERSION          _IOW('f', 4, int)
+#define EXT3_IOC32_GETRSVSZ            _IOR('f', 5, int)
+#define EXT3_IOC32_SETRSVSZ            _IOW('f', 6, int)
+#define EXT3_IOC32_GROUP_EXTEND                _IOW('f', 7, unsigned int)
+#ifdef CONFIG_JBD_DEBUG
+#define EXT3_IOC32_WAIT_FOR_READONLY   _IOR('f', 99, int)
+#endif
+#define EXT3_IOC32_GETVERSION_OLD      FS_IOC32_GETVERSION
+#define EXT3_IOC32_SETVERSION_OLD      FS_IOC32_SETVERSION
+
+
 /*
  *  Mount options
  */
@@ -460,7 +477,7 @@ struct ext3_super_block {
         */
        __u8    s_prealloc_blocks;      /* Nr of blocks to try to preallocate*/
        __u8    s_prealloc_dir_blocks;  /* Nr to preallocate for dirs */
-       __u16   s_reserved_gdt_blocks;  /* Per group desc for online growth */
+       __le16  s_reserved_gdt_blocks;  /* Per group desc for online growth */
        /*
         * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
         */
@@ -473,7 +490,7 @@ struct ext3_super_block {
        __u8    s_reserved_char_pad;
        __u16   s_reserved_word_pad;
        __le32  s_default_mount_opts;
-       __le32  s_first_meta_bg;        /* First metablock block group */
+       __le32  s_first_meta_bg;        /* First metablock block group */
        __u32   s_reserved[190];        /* Padding to the end of the block */
 };
 
@@ -812,6 +829,7 @@ extern void ext3_set_aops(struct inode *inode);
 /* ioctl.c */
 extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
                       unsigned long);
+extern long ext3_compat_ioctl (struct file *, unsigned int, unsigned long);
 
 /* namei.c */
 extern int ext3_orphan_add(handle_t *, struct inode *);
index 2f18b9511f211f728bf1e631a554b53d1dd124ee..4395e5206746b33be79bd57bef264da8a74bcd0a 100644 (file)
@@ -35,7 +35,7 @@ struct ext3_reserve_window {
 };
 
 struct ext3_reserve_window_node {
-       struct rb_node          rsv_node;
+       struct rb_node          rsv_node;
        __u32                   rsv_goal_size;
        __u32                   rsv_alloc_hit;
        struct ext3_reserve_window      rsv_window;
index c8307c02dd07103c19bfd2dd38ece06470d12278..ce0e6109aff0cdb83e05cd350909da82b5a50d99 100644 (file)
@@ -23,7 +23,7 @@
 
 /* Define the number of blocks we need to account to a transaction to
  * modify one block of data.
- * 
+ *
  * We may have to touch one inode, one bitmap buffer, up to three
  * indirection blocks, the group and superblock summaries, and the data
  * block to complete the transaction.  */
 #endif
 
 int
-ext3_mark_iloc_dirty(handle_t *handle, 
+ext3_mark_iloc_dirty(handle_t *handle,
                     struct inode *inode,
                     struct ext3_iloc *iloc);
 
-/* 
+/*
  * On success, We end up with an outstanding reference count against
- * iloc->bh.  This _must_ be cleaned up later. 
+ * iloc->bh.  This _must_ be cleaned up later.
  */
 
-int ext3_reserve_inode_write(handle_t *handle, struct inode *inode, 
+int ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
                        struct ext3_iloc *iloc);
 
 int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode);
index 9f7c2513866f4d1a857398711f09864239b7162c..74183e6f7f458052c72d0bf3e8297c83a32ff18c 100644 (file)
@@ -112,5 +112,6 @@ struct task_struct;
 
 struct files_struct *get_files_struct(struct task_struct *);
 void FASTCALL(put_files_struct(struct files_struct *fs));
+void reset_files_struct(struct task_struct *, struct files_struct *);
 
 #endif /* __LINUX_FILE_H */
index 1d3e601ece7396263ef5cc40c14c6c0691548452..2e29a2edaeecb2173deffdbce1c4fc9f9e1e4d0f 100644 (file)
@@ -79,8 +79,8 @@ extern int dir_notify_enable;
 #define WRITE 1
 #define READA 2                /* read-ahead  - don't block if no resources */
 #define SWRITE 3       /* for ll_rw_block() - wait for buffer lock */
-#define SPECIAL 4      /* For non-blockdevice requests in request queue */
 #define READ_SYNC      (READ | (1 << BIO_RW_SYNC))
+#define READ_META      (READ | (1 << BIO_RW_META))
 #define WRITE_SYNC     (WRITE | (1 << BIO_RW_SYNC))
 #define WRITE_BARRIER  ((1 << BIO_RW) | (1 << BIO_RW_BARRIER))
 
@@ -217,6 +217,45 @@ extern int dir_notify_enable;
 #define FIBMAP    _IO(0x00,1)  /* bmap access */
 #define FIGETBSZ   _IO(0x00,2) /* get the block size used for bmap */
 
+#define        FS_IOC_GETFLAGS                 _IOR('f', 1, long)
+#define        FS_IOC_SETFLAGS                 _IOW('f', 2, long)
+#define        FS_IOC_GETVERSION               _IOR('v', 1, long)
+#define        FS_IOC_SETVERSION               _IOW('v', 2, long)
+#define FS_IOC32_GETFLAGS              _IOR('f', 1, int)
+#define FS_IOC32_SETFLAGS              _IOW('f', 2, int)
+#define FS_IOC32_GETVERSION            _IOR('v', 1, int)
+#define FS_IOC32_SETVERSION            _IOW('v', 2, int)
+
+/*
+ * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
+ */
+#define        FS_SECRM_FL                     0x00000001 /* Secure deletion */
+#define        FS_UNRM_FL                      0x00000002 /* Undelete */
+#define        FS_COMPR_FL                     0x00000004 /* Compress file */
+#define FS_SYNC_FL                     0x00000008 /* Synchronous updates */
+#define FS_IMMUTABLE_FL                        0x00000010 /* Immutable file */
+#define FS_APPEND_FL                   0x00000020 /* writes to file may only append */
+#define FS_NODUMP_FL                   0x00000040 /* do not dump file */
+#define FS_NOATIME_FL                  0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define FS_DIRTY_FL                    0x00000100
+#define FS_COMPRBLK_FL                 0x00000200 /* One or more compressed clusters */
+#define FS_NOCOMP_FL                   0x00000400 /* Don't compress */
+#define FS_ECOMPR_FL                   0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */
+#define FS_BTREE_FL                    0x00001000 /* btree format dir */
+#define FS_INDEX_FL                    0x00001000 /* hash-indexed directory */
+#define FS_IMAGIC_FL                   0x00002000 /* AFS directory */
+#define FS_JOURNAL_DATA_FL             0x00004000 /* Reserved for ext3 */
+#define FS_NOTAIL_FL                   0x00008000 /* file tail should not be merged */
+#define FS_DIRSYNC_FL                  0x00010000 /* dirsync behaviour (directories only) */
+#define FS_TOPDIR_FL                   0x00020000 /* Top of directory hierarchies*/
+#define FS_RESERVED_FL                 0x80000000 /* reserved for ext2 lib */
+
+#define FS_FL_USER_VISIBLE             0x0003DFFF /* User visible flags */
+#define FS_FL_USER_MODIFIABLE          0x000380FF /* User modifiable flags */
+
+
 #define SYNC_FILE_RANGE_WAIT_BEFORE    1
 #define SYNC_FILE_RANGE_WRITE          2
 #define SYNC_FILE_RANGE_WAIT_AFTER     4
@@ -512,7 +551,6 @@ struct inode {
        struct timespec         i_mtime;
        struct timespec         i_ctime;
        unsigned int            i_blkbits;
-       unsigned long           i_blksize;
        unsigned long           i_version;
        blkcnt_t                i_blocks;
        unsigned short          i_bytes;
@@ -528,11 +566,12 @@ struct inode {
 #ifdef CONFIG_QUOTA
        struct dquot            *i_dquot[MAXQUOTAS];
 #endif
-       /* These three should probably be a union */
        struct list_head        i_devices;
-       struct pipe_inode_info  *i_pipe;
-       struct block_device     *i_bdev;
-       struct cdev             *i_cdev;
+       union {
+               struct pipe_inode_info  *i_pipe;
+               struct block_device     *i_bdev;
+               struct cdev             *i_cdev;
+       };
        int                     i_cindex;
 
        __u32                   i_generation;
@@ -553,10 +592,10 @@ struct inode {
        unsigned int            i_flags;
 
        atomic_t                i_writecount;
+#ifdef CONFIG_SECURITY
        void                    *i_security;
-       union {
-               void            *generic_ip;
-       } u;
+#endif
+       void                    *i_private; /* fs or device private pointer */
 #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t              i_size_seqcount;
 #endif
@@ -647,7 +686,6 @@ struct fown_struct {
        rwlock_t lock;          /* protects pid, uid, euid fields */
        int pid;                /* pid or -pgrp where SIGIO should be sent */
        uid_t uid, euid;        /* uid/euid of process setting the owner */
-       void *security;
        int signum;             /* posix.1b rt signal to be delivered on IO */
 };
 
@@ -690,8 +728,9 @@ struct file {
        struct file_ra_state    f_ra;
 
        unsigned long           f_version;
+#ifdef CONFIG_SECURITY
        void                    *f_security;
-
+#endif
        /* needed for tty driver, and maybe others */
        void                    *private_data;
 
@@ -879,7 +918,9 @@ struct super_block {
        int                     s_syncing;
        int                     s_need_sync_fs;
        atomic_t                s_active;
+#ifdef CONFIG_SECURITY
        void                    *s_security;
+#endif
        struct xattr_handler    **s_xattr;
 
        struct list_head        s_inodes;       /* all inodes */
@@ -1056,9 +1097,9 @@ struct file_operations {
        struct module *owner;
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
-       ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
-       ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+       ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+       ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
@@ -1072,8 +1113,6 @@ struct file_operations {
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
-       ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
-       ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
        ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
        ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
@@ -1111,6 +1150,11 @@ struct inode_operations {
 
 struct seq_file;
 
+ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
+                               unsigned long nr_segs, unsigned long fast_segs,
+                               struct iovec *fast_pointer,
+                               struct iovec **ret_pointer);
+
 extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
 extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
 extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
@@ -1145,9 +1189,10 @@ struct super_operations {
 
        int (*show_options)(struct seq_file *, struct vfsmount *);
        int (*show_stats)(struct seq_file *, struct vfsmount *);
-
+#ifdef CONFIG_QUOTA
        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+#endif
 };
 
 /* Inode state bits.  Protected by inode_lock. */
@@ -1174,15 +1219,30 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
        __mark_inode_dirty(inode, I_DIRTY_SYNC);
 }
 
-static inline void inode_inc_link_count(struct inode *inode)
+static inline void inc_nlink(struct inode *inode)
 {
        inode->i_nlink++;
+}
+
+static inline void inode_inc_link_count(struct inode *inode)
+{
+       inc_nlink(inode);
        mark_inode_dirty(inode);
 }
 
-static inline void inode_dec_link_count(struct inode *inode)
+static inline void drop_nlink(struct inode *inode)
 {
        inode->i_nlink--;
+}
+
+static inline void clear_nlink(struct inode *inode)
+{
+       inode->i_nlink = 0;
+}
+
+static inline void inode_dec_link_count(struct inode *inode)
+{
+       drop_nlink(inode);
        mark_inode_dirty(inode);
 }
 
@@ -1440,6 +1500,7 @@ extern void __init vfs_caches_init(unsigned long);
 extern void putname(const char *name);
 #endif
 
+#ifdef CONFIG_BLOCK
 extern int register_blkdev(unsigned int, const char *);
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
@@ -1448,11 +1509,15 @@ extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern struct block_device *open_by_devnum(dev_t, unsigned);
 extern struct block_device *open_partition_by_devnum(dev_t, unsigned);
-extern const struct file_operations def_blk_fops;
 extern const struct address_space_operations def_blk_aops;
+#else
+static inline void bd_forget(struct inode *inode) {}
+#endif
+extern const struct file_operations def_blk_fops;
 extern const struct file_operations def_chr_fops;
 extern const struct file_operations bad_sock_fops;
 extern const struct file_operations def_fifo_fops;
+#ifdef CONFIG_BLOCK
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long);
 extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
@@ -1468,6 +1533,7 @@ extern void bd_release_from_disk(struct block_device *, struct gendisk *);
 #define bd_claim_by_disk(bdev, holder, disk)   bd_claim(bdev, holder)
 #define bd_release_from_disk(bdev, disk)       bd_release(bdev)
 #endif
+#endif
 
 /* fs/char_dev.c */
 #define CHRDEV_MAJOR_HASH_SIZE 255
@@ -1481,14 +1547,19 @@ extern int chrdev_open(struct inode *, struct file *);
 extern void chrdev_show(struct seq_file *,off_t);
 
 /* fs/block_dev.c */
-#define BLKDEV_MAJOR_HASH_SIZE 255
 #define BDEVNAME_SIZE  32      /* Largest string for a blockdev identifier */
+
+#ifdef CONFIG_BLOCK
+#define BLKDEV_MAJOR_HASH_SIZE 255
 extern const char *__bdevname(dev_t, char *buffer);
 extern const char *bdevname(struct block_device *bdev, char *buffer);
 extern struct block_device *lookup_bdev(const char *);
 extern struct block_device *open_bdev_excl(const char *, int, void *);
 extern void close_bdev_excl(struct block_device *);
 extern void blkdev_show(struct seq_file *,off_t);
+#else
+#define BLKDEV_MAJOR_HASH_SIZE 0
+#endif
 
 extern void init_special_inode(struct inode *, umode_t, dev_t);
 
@@ -1502,6 +1573,7 @@ extern const struct file_operations rdwr_fifo_fops;
 
 extern int fs_may_remount_ro(struct super_block *);
 
+#ifdef CONFIG_BLOCK
 /*
  * return READ, READA, or WRITE
  */
@@ -1513,9 +1585,10 @@ extern int fs_may_remount_ro(struct super_block *);
 #define bio_data_dir(bio)      ((bio)->bi_rw & 1)
 
 extern int check_disk_change(struct block_device *);
-extern int invalidate_inodes(struct super_block *);
 extern int __invalidate_device(struct block_device *);
 extern int invalidate_partition(struct gendisk *, int);
+#endif
+extern int invalidate_inodes(struct super_block *);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
                                        pgoff_t start, pgoff_t end);
 unsigned long invalidate_inode_pages(struct address_space *mapping);
@@ -1543,11 +1616,14 @@ extern int __filemap_fdatawrite_range(struct address_space *mapping,
 extern long do_fsync(struct file *file, int datasync);
 extern void sync_supers(void);
 extern void sync_filesystems(int wait);
+extern void __fsync_super(struct super_block *sb);
 extern void emergency_sync(void);
 extern void emergency_remount(void);
 extern int do_remount_sb(struct super_block *sb, int flags,
                         void *data, int force);
+#ifdef CONFIG_BLOCK
 extern sector_t bmap(struct inode *, sector_t);
+#endif
 extern int notify_change(struct dentry *, struct iattr *);
 extern int permission(struct inode *, int, struct nameidata *);
 extern int generic_permission(struct inode *, int,
@@ -1565,6 +1641,9 @@ static inline void allow_write_access(struct file *file)
                atomic_inc(&file->f_dentry->d_inode->i_writecount);
 }
 extern int do_pipe(int *);
+extern struct file *create_read_pipe(struct file *f);
+extern struct file *create_write_pipe(void);
+extern void free_write_pipe(struct file *);
 
 extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
 extern int may_open(struct nameidata *, int, int);
@@ -1630,9 +1709,11 @@ static inline void insert_inode_hash(struct inode *inode) {
 extern struct file * get_empty_filp(void);
 extern void file_move(struct file *f, struct list_head *list);
 extern void file_kill(struct file *f);
+#ifdef CONFIG_BLOCK
 struct bio;
 extern void submit_bio(int, struct bio *);
 extern int bdev_read_only(struct block_device *);
+#endif
 extern int set_blocksize(struct block_device *, int);
 extern int sb_set_blocksize(struct super_block *, int);
 extern int sb_min_blocksize(struct super_block *, int);
@@ -1641,22 +1722,17 @@ extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
-extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *);
 int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
-extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *);
-extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t);
-extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
-extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t);
+extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
 extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
-               unsigned long, loff_t *);
+               unsigned long, loff_t);
 extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
                unsigned long *, loff_t, loff_t *, size_t, size_t);
 extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
                unsigned long, loff_t, loff_t *, size_t, ssize_t);
 extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
 extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
-ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t *ppos);
 extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 extern void do_generic_mapping_read(struct address_space *mapping,
                                    struct file_ra_state *, struct file *,
@@ -1674,10 +1750,6 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
-extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
-       unsigned long nr_segs, loff_t *ppos);
-ssize_t generic_file_writev(struct file *filp, const struct iovec *iov, 
-                       unsigned long nr_segs, loff_t *ppos);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t remote_llseek(struct file *file, loff_t offset, int origin);
@@ -1713,6 +1785,7 @@ static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
                                actor);
 }
 
+#ifdef CONFIG_BLOCK
 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        struct block_device *bdev, const struct iovec *iov, loff_t offset,
        unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
@@ -1750,6 +1823,7 @@ static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb,
        return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
                                nr_segs, get_block, end_io, DIO_OWN_LOCKING);
 }
+#endif
 
 extern const struct file_operations generic_ro_fops;
 
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h
new file mode 100644 (file)
index 0000000..80764f4
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * fs/generic_acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef GENERIC_ACL_H
+#define GENERIC_ACL_H
+
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+
+/**
+ * struct generic_acl_operations  -  filesystem operations
+ *
+ * Filesystems must make these operations available to the generic
+ * operations.
+ */
+struct generic_acl_operations {
+       struct posix_acl *(*getacl)(struct inode *, int);
+       void (*setacl)(struct inode *, int, struct posix_acl *);
+};
+
+size_t generic_acl_list(struct inode *, struct generic_acl_operations *, int,
+                       char *, size_t);
+int generic_acl_get(struct inode *, struct generic_acl_operations *, int,
+                   void *, size_t);
+int generic_acl_set(struct inode *, struct generic_acl_operations *, int,
+                   const void *, size_t);
+int generic_acl_init(struct inode *, struct inode *,
+                    struct generic_acl_operations *);
+int generic_acl_chmod(struct inode *, struct generic_acl_operations *);
+
+#endif
index e4af57e87c178ab0bff22b97b2e710e72a870428..41f276fdd185f6b16b4edb280041a23fa642440c 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <linux/types.h>
 
+#ifdef CONFIG_BLOCK
+
 enum {
 /* These three have identical behaviour; use the second one if DOS FDISK gets
    confused about extended/logical partitions starting past cylinder 1023. */
@@ -420,3 +422,5 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index)
 #endif
 
 #endif
+
+#endif
index 031ed3780e45bf779a7dc3cd681c76e7b3d72f84..c7372d7a97be34a22874f38c388284640ae29512 100644 (file)
@@ -1,16 +1,18 @@
 #ifndef _LINUX_GETCPU_H
 #define _LINUX_GETCPU_H 1
 
-/* Cache for getcpu() to speed it up. Results might be upto a jiffie
+/* Cache for getcpu() to speed it up. Results might be a short time
    out of date, but will be faster.
+
    User programs should not refer to the contents of this structure.
-   It is only a cache for vgetcpu(). It might change in future kernels.
+   I repeat they should not refer to it. If they do they will break
+   in future kernels.
+
+   It is only a private cache for vgetcpu(). It will change in future kernels.
    The user program must store this information per thread (__thread)
    If you want 100% accurate information pass NULL instead. */
 struct getcpu_cache {
-       unsigned long t0;
-       unsigned long t1;
-       unsigned long res[4];
+       unsigned long blob[128 / sizeof(long)];
 };
 
 #endif
index 8b34aabfe4c61129c78e378365372ae6831bc6c8..bf2b6bc3f6fd4fc35dec4dc8072b26c160458dfe 100644 (file)
@@ -67,7 +67,12 @@ struct vm_area_struct;
 #define GFP_HIGHUSER   (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
                         __GFP_HIGHMEM)
 
+#ifdef CONFIG_NUMA
 #define GFP_THISNODE   (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
+#else
+#define GFP_THISNODE   0
+#endif
+
 
 /* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
    platforms, used as appropriate on others */
index d5ebbb29aeaebc339fe893456bc2dba507f80453..d4b333938f73277790ae2a512b374da747512fae 100644 (file)
 #ifndef __HDLC_H
 #define __HDLC_H
 
-#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */
-
-#define CLOCK_DEFAULT   0      /* Default setting */
-#define CLOCK_EXT      1       /* External TX and RX clock - DTE */
-#define CLOCK_INT      2       /* Internal TX and RX clock - DCE */
-#define CLOCK_TXINT    3       /* Internal TX and external RX clock */
-#define CLOCK_TXFROMRX 4       /* TX clock derived from external RX clock */
-
-
-#define ENCODING_DEFAULT       0 /* Default setting */
-#define ENCODING_NRZ           1
-#define ENCODING_NRZI          2
-#define ENCODING_FM_MARK       3
-#define ENCODING_FM_SPACE      4
-#define ENCODING_MANCHESTER    5
-
-
-#define PARITY_DEFAULT         0 /* Default setting */
-#define PARITY_NONE            1 /* No parity */
-#define PARITY_CRC16_PR0       2 /* CRC16, initial value 0x0000 */
-#define PARITY_CRC16_PR1       3 /* CRC16, initial value 0xFFFF */
-#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */
-#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */
-#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
-#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
-
-#define LMI_DEFAULT            0 /* Default setting */
-#define LMI_NONE               1 /* No LMI, all PVCs are static */
-#define LMI_ANSI               2 /* ANSI Annex D */
-#define LMI_CCITT              3 /* ITU-T Annex A */
-#define LMI_CISCO              4 /* The "original" LMI, aka Gang of Four */
 
 #define HDLC_MAX_MTU 1500      /* Ethernet 1500 bytes */
+#if 0
 #define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */
+#else
+#define HDLC_MAX_MRU 1600 /* as required for FR network */
+#endif
 
 
 #ifdef __KERNEL__
 
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
-#include <net/syncppp.h>
 #include <linux/hdlc/ioctl.h>
 
 
-typedef struct {               /* Used in Cisco and PPP mode */
-       u8 address;
-       u8 control;
-       u16 protocol;
-}__attribute__ ((packed)) hdlc_header;
-
-
-
-typedef struct {
-       u32 type;               /* code */
-       u32 par1;
-       u32 par2;
-       u16 rel;                /* reliability */
-       u32 time;
-}__attribute__ ((packed)) cisco_packet;
-#define        CISCO_PACKET_LEN        18
-#define        CISCO_BIG_PACKET_LEN    20
-
-
-
-typedef struct pvc_device_struct {
-       struct net_device *master;
-       struct net_device *main;
-       struct net_device *ether; /* bridged Ethernet interface */
-       struct pvc_device_struct *next; /* Sorted in ascending DLCI order */
-       int dlci;
-       int open_count;
-
-       struct {
-               unsigned int new: 1;
-               unsigned int active: 1;
-               unsigned int exist: 1;
-               unsigned int deleted: 1;
-               unsigned int fecn: 1;
-               unsigned int becn: 1;
-               unsigned int bandwidth; /* Cisco LMI reporting only */
-       }state;
-}pvc_device;
-
-
-
-typedef struct hdlc_device_struct {
-       /* To be initialized by hardware driver */
+/* Used by all network devices here, pointed to by netdev_priv(dev) */
+struct hdlc_device_desc {
+       int (*netif_rx)(struct sk_buff *skb);
        struct net_device_stats stats;
-
+};
+
+/* This structure is a private property of HDLC protocols.
+   Hardware drivers have no interest here */
+
+struct hdlc_proto {
+       int (*open)(struct net_device *dev);
+       void (*close)(struct net_device *dev);
+       void (*start)(struct net_device *dev); /* if open & DCD */
+       void (*stop)(struct net_device *dev); /* if open & !DCD */
+       void (*detach)(struct net_device *dev);
+       int (*ioctl)(struct net_device *dev, struct ifreq *ifr);
+       unsigned short (*type_trans)(struct sk_buff *skb,
+                                    struct net_device *dev);
+       struct module *module;
+       struct hdlc_proto *next; /* next protocol in the list */
+};
+
+
+typedef struct hdlc_device {
        /* used by HDLC layer to take control over HDLC device from hw driver*/
        int (*attach)(struct net_device *dev,
                      unsigned short encoding, unsigned short parity);
@@ -107,82 +58,18 @@ typedef struct hdlc_device_struct {
        /* hardware driver must handle this instead of dev->hard_start_xmit */
        int (*xmit)(struct sk_buff *skb, struct net_device *dev);
 
-
        /* Things below are for HDLC layer internal use only */
-       struct {
-               int (*open)(struct net_device *dev);
-               void (*close)(struct net_device *dev);
-
-               /* if open & DCD */
-               void (*start)(struct net_device *dev);
-               /* if open & !DCD */
-               void (*stop)(struct net_device *dev);
-
-               void (*detach)(struct hdlc_device_struct *hdlc);
-               int (*netif_rx)(struct sk_buff *skb);
-               unsigned short (*type_trans)(struct sk_buff *skb,
-                                            struct net_device *dev);
-               int id;         /* IF_PROTO_HDLC/CISCO/FR/etc. */
-       }proto;
-
+       const struct hdlc_proto *proto;
        int carrier;
        int open;
        spinlock_t state_lock;
-
-       union {
-               struct {
-                       fr_proto settings;
-                       pvc_device *first_pvc;
-                       int dce_pvc_count;
-
-                       struct timer_list timer;
-                       unsigned long last_poll;
-                       int reliable;
-                       int dce_changed;
-                       int request;
-                       int fullrep_sent;
-                       u32 last_errors; /* last errors bit list */
-                       u8 n391cnt;
-                       u8 txseq; /* TX sequence number */
-                       u8 rxseq; /* RX sequence number */
-               }fr;
-
-               struct {
-                       cisco_proto settings;
-
-                       struct timer_list timer;
-                       unsigned long last_poll;
-                       int up;
-                       int request_sent;
-                       u32 txseq; /* TX sequence number */
-                       u32 rxseq; /* RX sequence number */
-               }cisco;
-
-               struct {
-                       raw_hdlc_proto settings;
-               }raw_hdlc;
-
-               struct {
-                       struct ppp_device pppdev;
-                       struct ppp_device *syncppp_ptr;
-                       int (*old_change_mtu)(struct net_device *dev,
-                                             int new_mtu);
-               }ppp;
-       }state;
+       void *state;
        void *priv;
 }hdlc_device;
 
 
 
-int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr);
-
-
-/* Exported from hdlc.o */
+/* Exported from hdlc module */
 
 /* Called by hardware driver when a user requests HDLC service */
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -191,17 +78,21 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 #define register_hdlc_device(dev)      register_netdev(dev)
 void unregister_hdlc_device(struct net_device *dev);
 
+
+void register_hdlc_protocol(struct hdlc_proto *proto);
+void unregister_hdlc_protocol(struct hdlc_proto *proto);
+
 struct net_device *alloc_hdlcdev(void *priv);
 
-static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
+
+static __inline__ struct hdlc_device_desc* dev_to_desc(struct net_device *dev)
 {
        return netdev_priv(dev);
 }
 
-
-static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
 {
-       return (pvc_device*)dev->priv;
+       return netdev_priv(dev) + sizeof(struct hdlc_device_desc);
 }
 
 
@@ -225,18 +116,14 @@ int hdlc_open(struct net_device *dev);
 /* Must be called by hardware driver when HDLC device is being closed */
 void hdlc_close(struct net_device *dev);
 
+int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
+                        int (*rx)(struct sk_buff *skb), size_t size);
 /* May be used by hardware driver to gain control over HDLC device */
-static __inline__ void hdlc_proto_detach(hdlc_device *hdlc)
-{
-       if (hdlc->proto.detach)
-               hdlc->proto.detach(hdlc);
-       hdlc->proto.detach = NULL;
-}
-
+void detach_hdlc_protocol(struct net_device *dev);
 
 static __inline__ struct net_device_stats *hdlc_stats(struct net_device *dev)
 {
-       return &dev_to_hdlc(dev)->stats;
+       return &dev_to_desc(dev)->stats;
 }
 
 
@@ -248,8 +135,8 @@ static __inline__ __be16 hdlc_type_trans(struct sk_buff *skb,
        skb->mac.raw  = skb->data;
        skb->dev      = dev;
 
-       if (hdlc->proto.type_trans)
-               return hdlc->proto.type_trans(skb, dev);
+       if (hdlc->proto->type_trans)
+               return hdlc->proto->type_trans(skb, dev);
        else
                return htons(ETH_P_HDLC);
 }
index 78430ba3ea69ecb6adbcf31888473a867529af8f..583972364357764ec38d4ef91a95b080ed808659 100644 (file)
@@ -1,6 +1,39 @@
 #ifndef __HDLC_IOCTL_H__
 #define __HDLC_IOCTL_H__
 
+
+#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0      /* Default setting */
+#define CLOCK_EXT      1       /* External TX and RX clock - DTE */
+#define CLOCK_INT      2       /* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT    3       /* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX 4       /* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT       0 /* Default setting */
+#define ENCODING_NRZ           1
+#define ENCODING_NRZI          2
+#define ENCODING_FM_MARK       3
+#define ENCODING_FM_SPACE      4
+#define ENCODING_MANCHESTER    5
+
+
+#define PARITY_DEFAULT         0 /* Default setting */
+#define PARITY_NONE            1 /* No parity */
+#define PARITY_CRC16_PR0       2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1       3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT            0 /* Default setting */
+#define LMI_NONE               1 /* No LMI, all PVCs are static */
+#define LMI_ANSI               2 /* ANSI Annex D */
+#define LMI_CCITT              3 /* ITU-T Annex A */
+#define LMI_CISCO              4 /* The "original" LMI, aka Gang of Four */
+
 typedef struct { 
        unsigned int clock_rate; /* bits per second */
        unsigned int clock_type; /* internal, external, TX-internal etc. */
index 4fc379de6c2ffceea015fa9b80ba987cfc42742e..fca93025ab5191db9a1d4aeb9734dbfa2f574a20 100644 (file)
@@ -138,6 +138,7 @@ extern long hrtimer_nanosleep(struct timespec *rqtp,
                              struct timespec __user *rmtp,
                              const enum hrtimer_mode mode,
                              const clockid_t clockid);
+extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
 
 extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
                                 struct task_struct *tsk);
index c0e7fab28ce345dc0c48c0a430fc640077caa181..c8f8df25c7e0faa1e19ef06e53bdc4d5442d573c 100644 (file)
@@ -40,7 +40,6 @@ struct i2c_algo_bit_data {
        /* local settings */
        int udelay;             /* half-clock-cycle time in microsecs */
                                /* i.e. clock is (500 / udelay) KHz */
-       int mdelay;             /* in millisecs, unused */
        int timeout;            /* in jiffies */
 };
 
index 18b0adf57a3d7d9ca26ac8b2ece2187fe9f35b2b..9908f3fc48396289f9d831c1ae33e4a4a26db932 100644 (file)
@@ -35,7 +35,6 @@ struct i2c_algo_pcf_data {
 
        /* local settings */
        int udelay;
-       int mdelay;
        int timeout;
 };
 
diff --git a/include/linux/i2c-algo-sibyte.h b/include/linux/i2c-algo-sibyte.h
deleted file mode 100644 (file)
index 03914de..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001,2002,2003 Broadcom 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.
- */
-
-#ifndef I2C_ALGO_SIBYTE_H
-#define I2C_ALGO_SIBYTE_H 1
-
-#include <linux/i2c.h>
-
-struct i2c_algo_sibyte_data {
-       void *data;             /* private data */
-        int   bus;             /* which bus */
-        void *reg_base;                /* CSR base */
-};
-
-int i2c_sibyte_add_bus(struct i2c_adapter *, int speed);
-int i2c_sibyte_del_bus(struct i2c_adapter *);
-
-#endif /* I2C_ALGO_SIBYTE_H */
index 9418519a55d16e936cf593e472e953d294f68ea7..0a8f750cbede9e9c963515ca09e60f121081c05e 100644 (file)
 #define I2C_HW_B_RADEON                0x01001e /* radeon framebuffer driver */
 #define I2C_HW_B_EM28XX                0x01001f /* em28xx video capture cards */
 #define I2C_HW_B_CX2341X       0x010020 /* Conexant CX2341X MPEG encoder cards */
+#define I2C_HW_B_INTELFB       0x010021 /* intel framebuffer driver */
 
 /* --- PCF 8584 based algorithms                                       */
 #define I2C_HW_P_LP            0x020000 /* Parallel port interface */
index eb0628a7ecc637ec71e18714105ac814f679f718..9b5d04768c2c103b1b745ab329ce3e19ded36e1d 100644 (file)
@@ -64,14 +64,6 @@ extern int i2c_master_recv(struct i2c_client *,char* ,int);
  */
 extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
 
-/*
- * Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor. 
- * This is not tested/implemented yet and will change in the future.
- */
-extern int i2c_slave_send(struct i2c_client *,char*,int);
-extern int i2c_slave_recv(struct i2c_client *,char*,int);
-
-
 
 /* This is the very generalized SMBus access routine. You probably do not
    want to use this, though; one of the functions below may be much easier,
@@ -201,10 +193,6 @@ struct i2c_algorithm {
                           unsigned short flags, char read_write,
                           u8 command, int size, union i2c_smbus_data * data);
 
-       /* --- these optional/future use for some adapter types.*/
-       int (*slave_send)(struct i2c_adapter *,char*,int);
-       int (*slave_recv)(struct i2c_adapter *,char*,int);
-
        /* --- ioctl like call to set div. parameters. */
        int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
 
@@ -220,7 +208,7 @@ struct i2c_adapter {
        struct module *owner;
        unsigned int id;
        unsigned int class;
-       struct i2c_algorithm *algo;/* the algorithm to access the bus   */
+       const struct i2c_algorithm *algo; /* the algorithm to access the bus */
        void *algo_data;
 
        /* --- administration stuff. */
index f0b571f1060ba23aa0542d1bc33943e2fbd0ef75..878cfe4e587f29d0d5dd3129180227bed8bf8990 100644 (file)
 struct icmphdr {
   __u8         type;
   __u8         code;
-  __u16                checksum;
+  __be16       checksum;
   union {
        struct {
-               __u16   id;
-               __u16   sequence;
+               __be16  id;
+               __be16  sequence;
        } echo;
-       __u32   gateway;
+       __be32  gateway;
        struct {
-               __u16   __unused;
-               __u16   mtu;
+               __be16  __unused;
+               __be16  mtu;
        } frag;
   } un;
 };
index cd080d76532477f5dbbf71965e74243fd422bf39..32bf419351f184242dfd5af400dd1859f297282d 100644 (file)
@@ -59,6 +59,8 @@
 #define IFF_SLAVE_INACTIVE     0x4     /* bonding slave not the curr. active */
 #define IFF_MASTER_8023AD      0x8     /* bonding master, 802.3ad.     */
 #define IFF_MASTER_ALB 0x10            /* bonding master, balance-alb. */
+#define IFF_BONDING    0x20            /* bonding master or slave      */
+#define IFF_SLAVE_NEEDARP 0x40         /* need ARPs for validation     */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
@@ -212,134 +214,4 @@ struct ifconf
 #define        ifc_buf ifc_ifcu.ifcu_buf               /* buffer address       */
 #define        ifc_req ifc_ifcu.ifcu_req               /* array of structures  */
 
-/* The struct should be in sync with struct net_device_stats */
-struct rtnl_link_stats
-{
-       __u32   rx_packets;             /* total packets received       */
-       __u32   tx_packets;             /* total packets transmitted    */
-       __u32   rx_bytes;               /* total bytes received         */
-       __u32   tx_bytes;               /* total bytes transmitted      */
-       __u32   rx_errors;              /* bad packets received         */
-       __u32   tx_errors;              /* packet transmit problems     */
-       __u32   rx_dropped;             /* no space in linux buffers    */
-       __u32   tx_dropped;             /* no space available in linux  */
-       __u32   multicast;              /* multicast packets received   */
-       __u32   collisions;
-
-       /* detailed rx_errors: */
-       __u32   rx_length_errors;
-       __u32   rx_over_errors;         /* receiver ring buff overflow  */
-       __u32   rx_crc_errors;          /* recved pkt with crc error    */
-       __u32   rx_frame_errors;        /* recv'd frame alignment error */
-       __u32   rx_fifo_errors;         /* recv'r fifo overrun          */
-       __u32   rx_missed_errors;       /* receiver missed packet       */
-
-       /* detailed tx_errors */
-       __u32   tx_aborted_errors;
-       __u32   tx_carrier_errors;
-       __u32   tx_fifo_errors;
-       __u32   tx_heartbeat_errors;
-       __u32   tx_window_errors;
-
-       /* for cslip etc */
-       __u32   rx_compressed;
-       __u32   tx_compressed;
-};
-
-/* The struct should be in sync with struct ifmap */
-struct rtnl_link_ifmap
-{
-       __u64   mem_start;
-       __u64   mem_end;
-       __u64   base_addr;
-       __u16   irq;
-       __u8    dma;
-       __u8    port;
-};
-
-enum
-{
-       IFLA_UNSPEC,
-       IFLA_ADDRESS,
-       IFLA_BROADCAST,
-       IFLA_IFNAME,
-       IFLA_MTU,
-       IFLA_LINK,
-       IFLA_QDISC,
-       IFLA_STATS,
-       IFLA_COST,
-#define IFLA_COST IFLA_COST
-       IFLA_PRIORITY,
-#define IFLA_PRIORITY IFLA_PRIORITY
-       IFLA_MASTER,
-#define IFLA_MASTER IFLA_MASTER
-       IFLA_WIRELESS,          /* Wireless Extension event - see wireless.h */
-#define IFLA_WIRELESS IFLA_WIRELESS
-       IFLA_PROTINFO,          /* Protocol specific information for a link */
-#define IFLA_PROTINFO IFLA_PROTINFO
-       IFLA_TXQLEN,
-#define IFLA_TXQLEN IFLA_TXQLEN
-       IFLA_MAP,
-#define IFLA_MAP IFLA_MAP
-       IFLA_WEIGHT,
-#define IFLA_WEIGHT IFLA_WEIGHT
-       IFLA_OPERSTATE,
-       IFLA_LINKMODE,
-       __IFLA_MAX
-};
-
-
-#define IFLA_MAX (__IFLA_MAX - 1)
-
-/* ifi_flags.
-
-   IFF_* flags.
-
-   The only change is:
-   IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
-   more not changeable by user. They describe link media
-   characteristics and set by device driver.
-
-   Comments:
-   - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
-   - If neither of these three flags are set;
-     the interface is NBMA.
-
-   - IFF_MULTICAST does not mean anything special:
-   multicasts can be used on all not-NBMA links.
-   IFF_MULTICAST means that this media uses special encapsulation
-   for multicast frames. Apparently, all IFF_POINTOPOINT and
-   IFF_BROADCAST devices are able to use multicasts too.
- */
-
-/* IFLA_LINK.
-   For usual devices it is equal ifi_index.
-   If it is a "virtual interface" (f.e. tunnel), ifi_link
-   can point to real physical interface (f.e. for bandwidth calculations),
-   or maybe 0, what means, that real media is unknown (usual
-   for IPIP tunnels, when route to endpoint is allowed to change)
- */
-
-/* Subtype attributes for IFLA_PROTINFO */
-enum
-{
-       IFLA_INET6_UNSPEC,
-       IFLA_INET6_FLAGS,       /* link flags                   */
-       IFLA_INET6_CONF,        /* sysctl parameters            */
-       IFLA_INET6_STATS,       /* statistics                   */
-       IFLA_INET6_MCAST,       /* MC things. What of them?     */
-       IFLA_INET6_CACHEINFO,   /* time values and max reasm size */
-       __IFLA_INET6_MAX
-};
-
-#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
-
-struct ifla_cacheinfo
-{
-       __u32   max_reasm_len;
-       __u32   tstamp;         /* ipv6InterfaceTable updated timestamp */
-       __u32   reachable_time;
-       __u32   retrans_time;
-};
-
 #endif /* _LINUX_IF_H */
index a8b1a2071838f70794fc7605b0b44f5def7f44d4..7f5714214ee35e787aa77dfbd3b8cf63d21ca620 100644 (file)
@@ -130,11 +130,11 @@ struct arpreq_old {
 
 struct arphdr
 {
-       unsigned short  ar_hrd;         /* format of hardware address   */
-       unsigned short  ar_pro;         /* format of protocol address   */
+       __be16          ar_hrd;         /* format of hardware address   */
+       __be16          ar_pro;         /* format of protocol address   */
        unsigned char   ar_hln;         /* length of hardware address   */
        unsigned char   ar_pln;         /* length of protocol address   */
-       unsigned short  ar_op;          /* ARP opcode (command)         */
+       __be16          ar_op;          /* ARP opcode (command)         */
 
 #if 0
         /*
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
new file mode 100644 (file)
index 0000000..e963a07
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef _LINUX_IF_LINK_H
+#define _LINUX_IF_LINK_H
+
+#include <linux/netlink.h>
+
+/* The struct should be in sync with struct net_device_stats */
+struct rtnl_link_stats
+{
+       __u32   rx_packets;             /* total packets received       */
+       __u32   tx_packets;             /* total packets transmitted    */
+       __u32   rx_bytes;               /* total bytes received         */
+       __u32   tx_bytes;               /* total bytes transmitted      */
+       __u32   rx_errors;              /* bad packets received         */
+       __u32   tx_errors;              /* packet transmit problems     */
+       __u32   rx_dropped;             /* no space in linux buffers    */
+       __u32   tx_dropped;             /* no space available in linux  */
+       __u32   multicast;              /* multicast packets received   */
+       __u32   collisions;
+
+       /* detailed rx_errors: */
+       __u32   rx_length_errors;
+       __u32   rx_over_errors;         /* receiver ring buff overflow  */
+       __u32   rx_crc_errors;          /* recved pkt with crc error    */
+       __u32   rx_frame_errors;        /* recv'd frame alignment error */
+       __u32   rx_fifo_errors;         /* recv'r fifo overrun          */
+       __u32   rx_missed_errors;       /* receiver missed packet       */
+
+       /* detailed tx_errors */
+       __u32   tx_aborted_errors;
+       __u32   tx_carrier_errors;
+       __u32   tx_fifo_errors;
+       __u32   tx_heartbeat_errors;
+       __u32   tx_window_errors;
+
+       /* for cslip etc */
+       __u32   rx_compressed;
+       __u32   tx_compressed;
+};
+
+/* The struct should be in sync with struct ifmap */
+struct rtnl_link_ifmap
+{
+       __u64   mem_start;
+       __u64   mem_end;
+       __u64   base_addr;
+       __u16   irq;
+       __u8    dma;
+       __u8    port;
+};
+
+enum
+{
+       IFLA_UNSPEC,
+       IFLA_ADDRESS,
+       IFLA_BROADCAST,
+       IFLA_IFNAME,
+       IFLA_MTU,
+       IFLA_LINK,
+       IFLA_QDISC,
+       IFLA_STATS,
+       IFLA_COST,
+#define IFLA_COST IFLA_COST
+       IFLA_PRIORITY,
+#define IFLA_PRIORITY IFLA_PRIORITY
+       IFLA_MASTER,
+#define IFLA_MASTER IFLA_MASTER
+       IFLA_WIRELESS,          /* Wireless Extension event - see wireless.h */
+#define IFLA_WIRELESS IFLA_WIRELESS
+       IFLA_PROTINFO,          /* Protocol specific information for a link */
+#define IFLA_PROTINFO IFLA_PROTINFO
+       IFLA_TXQLEN,
+#define IFLA_TXQLEN IFLA_TXQLEN
+       IFLA_MAP,
+#define IFLA_MAP IFLA_MAP
+       IFLA_WEIGHT,
+#define IFLA_WEIGHT IFLA_WEIGHT
+       IFLA_OPERSTATE,
+       IFLA_LINKMODE,
+       __IFLA_MAX
+};
+
+
+#define IFLA_MAX (__IFLA_MAX - 1)
+
+/* ifi_flags.
+
+   IFF_* flags.
+
+   The only change is:
+   IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
+   more not changeable by user. They describe link media
+   characteristics and set by device driver.
+
+   Comments:
+   - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
+   - If neither of these three flags are set;
+     the interface is NBMA.
+
+   - IFF_MULTICAST does not mean anything special:
+   multicasts can be used on all not-NBMA links.
+   IFF_MULTICAST means that this media uses special encapsulation
+   for multicast frames. Apparently, all IFF_POINTOPOINT and
+   IFF_BROADCAST devices are able to use multicasts too.
+ */
+
+/* IFLA_LINK.
+   For usual devices it is equal ifi_index.
+   If it is a "virtual interface" (f.e. tunnel), ifi_link
+   can point to real physical interface (f.e. for bandwidth calculations),
+   or maybe 0, what means, that real media is unknown (usual
+   for IPIP tunnels, when route to endpoint is allowed to change)
+ */
+
+/* Subtype attributes for IFLA_PROTINFO */
+enum
+{
+       IFLA_INET6_UNSPEC,
+       IFLA_INET6_FLAGS,       /* link flags                   */
+       IFLA_INET6_CONF,        /* sysctl parameters            */
+       IFLA_INET6_STATS,       /* statistics                   */
+       IFLA_INET6_MCAST,       /* MC things. What of them?     */
+       IFLA_INET6_CACHEINFO,   /* time values and max reasm size */
+       __IFLA_INET6_MAX
+};
+
+#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
+
+struct ifla_cacheinfo
+{
+       __u32   max_reasm_len;
+       __u32   tstamp;         /* ipv6InterfaceTable updated timestamp */
+       __u32   reachable_time;
+       __u32   retrans_time;
+};
+
+#endif /* _LINUX_IF_LINK_H */
index 899c3d4776f3dffc690274bd3dfb44224c6608ab..03f43e2893a4a6110c55bd50372aeee716e9d113 100644 (file)
@@ -30,8 +30,8 @@ struct igmphdr
 {
        __u8 type;
        __u8 code;              /* For newer IGMP */
-       __u16 csum;
-       __u32 group;
+       __be16 csum;
+       __be32 group;
 };
 
 /* V3 group record types [grec_type] */
@@ -45,25 +45,25 @@ struct igmphdr
 struct igmpv3_grec {
        __u8    grec_type;
        __u8    grec_auxwords;
-       __u16   grec_nsrcs;
-       __u32   grec_mca;
-       __u32   grec_src[0];
+       __be16  grec_nsrcs;
+       __be32  grec_mca;
+       __be32  grec_src[0];
 };
 
 struct igmpv3_report {
        __u8 type;
        __u8 resv1;
-       __u16 csum;
-       __u16 resv2;
-       __u16 ngrec;
+       __be16 csum;
+       __be16 resv2;
+       __be16 ngrec;
        struct igmpv3_grec grec[0];
 };
 
 struct igmpv3_query {
        __u8 type;
        __u8 code;
-       __u16 csum;
-       __u32 group;
+       __be16 csum;
+       __be32 group;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        __u8 qrv:3,
             suppress:1,
@@ -76,8 +76,8 @@ struct igmpv3_query {
 #error "Please fix <asm/byteorder.h>"
 #endif
        __u8 qqic;
-       __u16 nsrcs;
-       __u32 srcs[0];
+       __be16 nsrcs;
+       __be32 srcs[0];
 };
 
 #define IGMP_HOST_MEMBERSHIP_QUERY     0x11    /* From RFC1112 */
@@ -136,11 +136,11 @@ struct ip_sf_socklist
 {
        unsigned int            sl_max;
        unsigned int            sl_count;
-       __u32                   sl_addr[0];
+       __be32                  sl_addr[0];
 };
 
 #define IP_SFLSIZE(count)      (sizeof(struct ip_sf_socklist) + \
-       (count) * sizeof(__u32))
+       (count) * sizeof(__be32))
 
 #define IP_SFBLOCK     10      /* allocate this many at once */
 
@@ -159,7 +159,7 @@ struct ip_mc_socklist
 struct ip_sf_list
 {
        struct ip_sf_list       *sf_next;
-       __u32                   sf_inaddr;
+       __be32                  sf_inaddr;
        unsigned long           sf_count[2];    /* include/exclude counts */
        unsigned char           sf_gsresp;      /* include in g & s response? */
        unsigned char           sf_oldin;       /* change state */
@@ -197,7 +197,7 @@ struct ip_mc_list
 #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
 #define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value)
 
-extern int ip_check_mc(struct in_device *dev, u32 mc_addr, u32 src_addr, u16 proto);
+extern int ip_check_mc(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u16 proto);
 extern int igmp_rcv(struct sk_buff *);
 extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
 extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
@@ -209,13 +209,13 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
                struct ip_msfilter __user *optval, int __user *optlen);
 extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
                struct group_filter __user *optval, int __user *optlen);
-extern int ip_mc_sf_allow(struct sock *sk, u32 local, u32 rmt, int dif);
+extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
 extern void ip_mr_init(void);
 extern void ip_mc_init_dev(struct in_device *);
 extern void ip_mc_destroy_dev(struct in_device *);
 extern void ip_mc_up(struct in_device *);
 extern void ip_mc_down(struct in_device *);
-extern void ip_mc_dec_group(struct in_device *in_dev, u32 addr);
-extern void ip_mc_inc_group(struct in_device *in_dev, u32 addr);
+extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
+extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
 #endif
 #endif
index bcaca8399aed62006eb601272771dbfe7c997039..d79fc75fa7c2c3d86dbf0c38f1834bc437aa524a 100644 (file)
@@ -123,17 +123,17 @@ struct ip_mreqn
 };
 
 struct ip_mreq_source {
-       __u32           imr_multiaddr;
-       __u32           imr_interface;
-       __u32           imr_sourceaddr;
+       __be32          imr_multiaddr;
+       __be32          imr_interface;
+       __be32          imr_sourceaddr;
 };
 
 struct ip_msfilter {
-       __u32           imsf_multiaddr;
-       __u32           imsf_interface;
+       __be32          imsf_multiaddr;
+       __be32          imsf_interface;
        __u32           imsf_fmode;
        __u32           imsf_numsrc;
-       __u32           imsf_slist[1];
+       __be32          imsf_slist[1];
 };
 
 #define IP_MSFILTER_SIZE(numsrc) \
index d776829b443f57e52f24e0bb8b45909936f4fd48..9be6a4756f0b39fc6cb22b7c80e3da310b52f77f 100644 (file)
@@ -32,8 +32,8 @@ struct in6_addr
        union 
        {
                __u8            u6_addr8[16];
-               __u16           u6_addr16[8];
-               __u32           u6_addr32[4];
+               __be16          u6_addr16[8];
+               __be32          u6_addr32[4];
        } in6_u;
 #define s6_addr                        in6_u.u6_addr8
 #define s6_addr16              in6_u.u6_addr16
@@ -53,7 +53,7 @@ extern const struct in6_addr in6addr_loopback;
 
 struct sockaddr_in6 {
        unsigned short int      sin6_family;    /* AF_INET6 */
-       __u16                   sin6_port;      /* Transport layer port # */
+       __be16                  sin6_port;      /* Transport layer port # */
        __u32                   sin6_flowinfo;  /* IPv6 flow information */
        struct in6_addr         sin6_addr;      /* IPv6 address */
        __u32                   sin6_scope_id;  /* scope id (new in RFC2553) */
index a4606e5810e570ae28158f6b73839f81585b231f..6e8bc548635af6a2cb1a685158751ca437dff476 100644 (file)
@@ -9,10 +9,10 @@
 
 /* Socket identity */
 struct inet_diag_sockid {
-       __u16   idiag_sport;
-       __u16   idiag_dport;
-       __u32   idiag_src[4];
-       __u32   idiag_dst[4];
+       __be16  idiag_sport;
+       __be16  idiag_dport;
+       __be32  idiag_src[4];
+       __be32  idiag_dst[4];
        __u32   idiag_if;
        __u32   idiag_cookie[2];
 #define INET_DIAG_NOCOOKIE (~0U)
@@ -67,7 +67,7 @@ struct inet_diag_hostcond {
        __u8    family;
        __u8    prefix_len;
        int     port;
-       __u32   addr[0];
+       __be32  addr[0];
 };
 
 /* Base info structure. It contains socket identity (addrs/ports/cookie)
index 92297ff24e8525de2617dff728b3420a4649f66a..5a0ab04627bc19a0c6dfd364fe56e6927db57f33 100644 (file)
@@ -90,11 +90,11 @@ struct in_ifaddr
        struct in_ifaddr        *ifa_next;
        struct in_device        *ifa_dev;
        struct rcu_head         rcu_head;
-       u32                     ifa_local;
-       u32                     ifa_address;
-       u32                     ifa_mask;
-       u32                     ifa_broadcast;
-       u32                     ifa_anycast;
+       __be32                  ifa_local;
+       __be32                  ifa_address;
+       __be32                  ifa_mask;
+       __be32                  ifa_broadcast;
+       __be32                  ifa_anycast;
        unsigned char           ifa_scope;
        unsigned char           ifa_flags;
        unsigned char           ifa_prefixlen;
@@ -104,18 +104,18 @@ struct in_ifaddr
 extern int register_inetaddr_notifier(struct notifier_block *nb);
 extern int unregister_inetaddr_notifier(struct notifier_block *nb);
 
-extern struct net_device       *ip_dev_find(u32 addr);
-extern int             inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b);
+extern struct net_device       *ip_dev_find(__be32 addr);
+extern int             inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
 extern int             devinet_ioctl(unsigned int cmd, void __user *);
 extern void            devinet_init(void);
 extern struct in_device *inetdev_init(struct net_device *dev);
 extern struct in_device        *inetdev_by_index(int);
-extern u32             inet_select_addr(const struct net_device *dev, u32 dst, int scope);
-extern u32             inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope);
-extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
+extern __be32          inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
+extern __be32          inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
+extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask);
 extern void            inet_forward_change(void);
 
-static __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa)
+static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
 {
        return !((addr^ifa->ifa_address)&ifa->ifa_mask);
 }
@@ -183,7 +183,7 @@ static inline void in_dev_put(struct in_device *idev)
 
 #endif /* __KERNEL__ */
 
-static __inline__ __u32 inet_make_mask(int logmask)
+static __inline__ __be32 inet_make_mask(int logmask)
 {
        if (logmask)
                return htonl(~((1<<(32-logmask))-1));
index 6667785dd1ff22d7452b716b380e7475158ee8b9..e92b1455d7afd8c908bfc0722be018a09c46c226 100644 (file)
@@ -68,6 +68,7 @@ extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
 /* Defined in init/main.c */
 extern char saved_command_line[];
+extern unsigned int reset_devices;
 
 /* used by init/main.c */
 extern void setup_arch(char **);
index d5afee95fd435294f2ee894cd75a31b7cc96be7b..1f97e3d92639e75aaed86a8066518e2526fa1dee 100644 (file)
@@ -123,6 +123,14 @@ static inline void disable_irq_nosync_lockdep(unsigned int irq)
 #endif
 }
 
+static inline void disable_irq_nosync_lockdep_irqsave(unsigned int irq, unsigned long *flags)
+{
+       disable_irq_nosync(irq);
+#ifdef CONFIG_LOCKDEP
+       local_irq_save(*flags);
+#endif
+}
+
 static inline void disable_irq_lockdep(unsigned int irq)
 {
        disable_irq(irq);
@@ -139,6 +147,14 @@ static inline void enable_irq_lockdep(unsigned int irq)
        enable_irq(irq);
 }
 
+static inline void enable_irq_lockdep_irqrestore(unsigned int irq, unsigned long *flags)
+{
+#ifdef CONFIG_LOCKDEP
+       local_irq_restore(*flags);
+#endif
+       enable_irq(irq);
+}
+
 /* IRQ wakeup (PM) control: */
 extern int set_irq_wake(unsigned int irq, unsigned int on);
 
index 420e2fdf26f654a4d89b7853340783dad432fffe..aa3f5af670b579bc9de78a9d1a4075daa6c039c2 100644 (file)
 #define _LINUX_IO_H
 
 #include <asm/io.h>
+#include <asm/page.h>
 
 void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
 void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
 
+int ioremap_page_range(unsigned long addr, unsigned long end,
+                      unsigned long phys_addr, pgprot_t prot);
+
 #endif /* _LINUX_IO_H */
index 2f4600146f833a509e3d7cac68b97013142c9e09..6b25d36fc54c481779a0d15b708e9bcca9c713a4 100644 (file)
@@ -96,7 +96,7 @@ struct iphdr {
        __be16  frag_off;
        __u8    ttl;
        __u8    protocol;
-       __u16   check;
+       __be16  check;
        __be32  saddr;
        __be32  daddr;
        /*The options start here. */
@@ -105,22 +105,22 @@ struct iphdr {
 struct ip_auth_hdr {
        __u8  nexthdr;
        __u8  hdrlen;           /* This one is measured in 32 bit units! */
-       __u16 reserved;
-       __u32 spi;
-       __u32 seq_no;           /* Sequence number */
+       __be16 reserved;
+       __be32 spi;
+       __be32 seq_no;          /* Sequence number */
        __u8  auth_data[0];     /* Variable len but >=4. Mind the 64 bit alignment! */
 };
 
 struct ip_esp_hdr {
-       __u32 spi;
-       __u32 seq_no;           /* Sequence number */
+       __be32 spi;
+       __be32 seq_no;          /* Sequence number */
        __u8  enc_data[0];      /* Variable len but >=8. Mind the 64 bit alignment! */
 };
 
 struct ip_comp_hdr {
        __u8 nexthdr;
        __u8 flags;
-       __u16 cpi;
+       __be16 cpi;
 };
 
 #endif /* _LINUX_IP_H */
index d09fbeabf1dc976539384f1889299bfc2e69383e..796ca009fd468a8716cd8d6b31570bcc83ca4faf 100644 (file)
@@ -148,6 +148,13 @@ struct ipmi_lan_addr
 #define IPMI_BMC_CHANNEL  0xf
 #define IPMI_NUM_CHANNELS 0x10
 
+/*
+ * Used to signify an "all channel" bitmask.  This is more than the
+ * actual number of channels because this is used in userland and
+ * will cover us if the number of channels is extended.
+ */
+#define IPMI_CHAN_ALL     (~0)
+
 
 /*
  * A raw IPMI message without any addressing.  This covers both
@@ -350,18 +357,21 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
 
 /*
  * When commands come in to the SMS, the user can register to receive
- * them.  Only one user can be listening on a specific netfn/cmd pair
+ * them.  Only one user can be listening on a specific netfn/cmd/chan tuple
  * at a time, you will get an EBUSY error if the command is already
  * registered.  If a command is received that does not have a user
  * registered, the driver will automatically return the proper
- * error.
+ * error.  Channels are specified as a bitfield, use IPMI_CHAN_ALL to
+ * mean all channels.
  */
 int ipmi_register_for_cmd(ipmi_user_t   user,
                          unsigned char netfn,
-                         unsigned char cmd);
+                         unsigned char cmd,
+                         unsigned int  chans);
 int ipmi_unregister_for_cmd(ipmi_user_t   user,
                            unsigned char netfn,
-                           unsigned char cmd);
+                           unsigned char cmd,
+                           unsigned int  chans);
 
 /*
  * Allow run-to-completion mode to be set for the interface of
@@ -571,6 +581,36 @@ struct ipmi_cmdspec
 #define IPMICTL_UNREGISTER_FOR_CMD     _IOR(IPMI_IOC_MAGIC, 15,        \
                                             struct ipmi_cmdspec)
 
+/*
+ * Register to get commands from other entities on specific channels.
+ * This way, you can only listen on specific channels, or have messages
+ * from some channels go to one place and other channels to someplace
+ * else.  The chans field is a bitmask, (1 << channel) for each channel.
+ * It may be IPMI_CHAN_ALL for all channels.
+ */
+struct ipmi_cmdspec_chans
+{
+       unsigned int netfn;
+       unsigned int cmd;
+       unsigned int chans;
+};
+
+/*
+ * Register to receive a specific command on specific channels.  error values:
+ *   - EFAULT - an address supplied was invalid.
+ *   - EBUSY - One of the netfn/cmd/chans supplied was already in use.
+ *   - ENOMEM - could not allocate memory for the entry.
+ */
+#define IPMICTL_REGISTER_FOR_CMD_CHANS _IOR(IPMI_IOC_MAGIC, 28,        \
+                                            struct ipmi_cmdspec_chans)
+/*
+ * Unregister some netfn/cmd/chans.  error values:
+ *  - EFAULT - an address supplied was invalid.
+ *  - ENOENT - None of the netfn/cmd/chans were found registered for this user.
+ */
+#define IPMICTL_UNREGISTER_FOR_CMD_CHANS _IOR(IPMI_IOC_MAGIC, 29,      \
+                                            struct ipmi_cmdspec_chans)
+
 /* 
  * Set whether this interface receives events.  Note that the first
  * user registered for events will get all pending events for the
index caca57df0d7d5f23039d961878dae5753e22718d..4f435c59de06775b5a1a5ba831ca3f0089006b80 100644 (file)
@@ -99,22 +99,22 @@ struct ipv6_destopt_hao {
 struct ipv6_auth_hdr {
        __u8  nexthdr;
        __u8  hdrlen;           /* This one is measured in 32 bit units! */
-       __u16 reserved;
-       __u32 spi;
-       __u32 seq_no;           /* Sequence number */
+       __be16 reserved;
+       __be32 spi;
+       __be32 seq_no;           /* Sequence number */
        __u8  auth_data[0];     /* Length variable but >=4. Mind the 64 bit alignment! */
 };
 
 struct ipv6_esp_hdr {
-       __u32 spi;
-       __u32 seq_no;           /* Sequence number */
+       __be32 spi;
+       __be32 seq_no;           /* Sequence number */
        __u8  enc_data[0];      /* Length variable but >=8. Mind the 64 bit alignment! */
 };
 
 struct ipv6_comp_hdr {
        __u8 nexthdr;
        __u8 flags;
-       __u16 cpi;
+       __be16 cpi;
 };
 
 /*
@@ -136,7 +136,7 @@ struct ipv6hdr {
 #endif
        __u8                    flow_lbl[3];
 
-       __u16                   payload_len;
+       __be16                  payload_len;
        __u8                    nexthdr;
        __u8                    hop_limit;
 
@@ -461,7 +461,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
 
 #define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\
        (((__sk)->sk_hash == (__hash))                          && \
-        ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   && \
+        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      && \
         ((__sk)->sk_family             == AF_INET6)            && \
         ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))     && \
         ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
index a04c154c5207954c39d58ba2ce95169b37ea57ae..fe89444b1c6f32145f4a0a02d1e8f13258e3f299 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/include/linux/jbd.h
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>
  *
  * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
@@ -64,7 +64,7 @@ extern int journal_enable_debug;
                if ((n) <= journal_enable_debug) {                      \
                        printk (KERN_DEBUG "(%s, %d): %s: ",            \
                                __FILE__, __LINE__, __FUNCTION__);      \
-                       printk (f, ## a);                               \
+                       printk (f, ## a);                               \
                }                                                       \
        } while (0)
 #else
@@ -97,8 +97,8 @@ extern void jbd_slab_free(void *ptr, size_t size);
  * number of outstanding buffers possible at any time.  When the
  * operation completes, any buffer credits not used are credited back to
  * the transaction, so that at all times we know how many buffers the
- * outstanding updates on a transaction might possibly touch. 
- * 
+ * outstanding updates on a transaction might possibly touch.
+ *
  * This is an opaque datatype.
  **/
 typedef struct handle_s                handle_t;       /* Atomic operation type */
@@ -108,7 +108,7 @@ typedef struct handle_s             handle_t;       /* Atomic operation type */
  * typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem.
  *
  * journal_t is linked to from the fs superblock structure.
- * 
+ *
  * We use the journal_t to keep track of all outstanding transaction
  * activity on the filesystem, and to manage the state of the log
  * writing process.
@@ -128,7 +128,7 @@ typedef struct journal_s    journal_t;      /* Journal control structure */
  * On-disk structures
  */
 
-/* 
+/*
  * Descriptor block types:
  */
 
@@ -149,8 +149,8 @@ typedef struct journal_header_s
 } journal_header_t;
 
 
-/* 
- * The block tag: used to describe a single buffer in the journal 
+/*
+ * The block tag: used to describe a single buffer in the journal
  */
 typedef struct journal_block_tag_s
 {
@@ -158,9 +158,9 @@ typedef struct journal_block_tag_s
        __be32          t_flags;        /* See below */
 } journal_block_tag_t;
 
-/* 
+/*
  * The revoke descriptor: used on disk to describe a series of blocks to
- * be revoked from the log 
+ * be revoked from the log
  */
 typedef struct journal_revoke_header_s
 {
@@ -201,9 +201,9 @@ typedef struct journal_superblock_s
 
 /* 0x0024 */
        /* Remaining fields are only valid in a version-2 superblock */
-       __be32  s_feature_compat;       /* compatible feature set */
-       __be32  s_feature_incompat;     /* incompatible feature set */
-       __be32  s_feature_ro_compat;    /* readonly-compatible feature set */
+       __be32  s_feature_compat;       /* compatible feature set */
+       __be32  s_feature_incompat;     /* incompatible feature set */
+       __be32  s_feature_ro_compat;    /* readonly-compatible feature set */
 /* 0x0030 */
        __u8    s_uuid[16];             /* 128-bit uuid for journal */
 
@@ -374,10 +374,10 @@ struct jbd_revoke_table_s;
  **/
 
 /* Docbook can't yet cope with the bit fields, but will leave the documentation
- * in so it can be fixed later. 
+ * in so it can be fixed later.
  */
 
-struct handle_s 
+struct handle_s
 {
        /* Which compound transaction is this update a part of? */
        transaction_t           *h_transaction;
@@ -435,7 +435,7 @@ struct handle_s
  *
  */
 
-struct transaction_s 
+struct transaction_s
 {
        /* Pointer to the journal for this transaction. [no locking] */
        journal_t               *t_journal;
@@ -455,7 +455,7 @@ struct transaction_s
                T_RUNDOWN,
                T_FLUSH,
                T_COMMIT,
-               T_FINISHED 
+               T_FINISHED
        }                       t_state;
 
        /*
@@ -569,7 +569,7 @@ struct transaction_s
  *     journal_t.
  * @j_flags:  General journaling state flags
  * @j_errno:  Is there an outstanding uncleared error on the journal (from a
- *     prior abort)? 
+ *     prior abort)?
  * @j_sb_buffer: First part of superblock buffer
  * @j_superblock: Second part of superblock buffer
  * @j_format_version: Version of the superblock format
@@ -583,7 +583,7 @@ struct transaction_s
  * @j_wait_transaction_locked: Wait queue for waiting for a locked transaction
  *  to start committing, or for a barrier lock to be released
  * @j_wait_logspace: Wait queue for waiting for checkpointing to complete
- * @j_wait_done_commit: Wait queue for waiting for commit to complete 
+ * @j_wait_done_commit: Wait queue for waiting for commit to complete
  * @j_wait_checkpoint:  Wait queue to trigger checkpointing
  * @j_wait_commit: Wait queue to trigger commit
  * @j_wait_updates: Wait queue to wait for updates to complete
@@ -592,7 +592,7 @@ struct transaction_s
  * @j_tail: Journal tail - identifies the oldest still-used block in the
  *  journal.
  * @j_free: Journal free - how many free blocks are there in the journal?
- * @j_first: The block number of the first usable block 
+ * @j_first: The block number of the first usable block
  * @j_last: The block number one beyond the last usable block
  * @j_dev: Device where we store the journal
  * @j_blocksize: blocksize for the location where we store the journal.
@@ -604,12 +604,12 @@ struct transaction_s
  * @j_list_lock: Protects the buffer lists and internal buffer state.
  * @j_inode: Optional inode where we store the journal.  If present, all journal
  *     block numbers are mapped into this inode via bmap().
- * @j_tail_sequence:  Sequence number of the oldest transaction in the log 
+ * @j_tail_sequence:  Sequence number of the oldest transaction in the log
  * @j_transaction_sequence: Sequence number of the next transaction to grant
  * @j_commit_sequence: Sequence number of the most recently committed
  *  transaction
  * @j_commit_request: Sequence number of the most recent transaction wanting
- *     commit 
+ *     commit
  * @j_uuid: Uuid of client object.
  * @j_task: Pointer to the current commit thread for this journal
  * @j_max_transaction_buffers:  Maximum number of metadata buffers to allow in a
@@ -699,7 +699,7 @@ struct journal_s
        wait_queue_head_t       j_wait_updates;
 
        /* Semaphore for locking against concurrent checkpoints */
-       struct mutex            j_checkpoint_mutex;
+       struct mutex            j_checkpoint_mutex;
 
        /*
         * Journal head: identifies the first unused block in the journal.
@@ -732,7 +732,7 @@ struct journal_s
         */
        struct block_device     *j_dev;
        int                     j_blocksize;
-       unsigned int            j_blk_offset;
+       unsigned long           j_blk_offset;
 
        /*
         * Device which holds the client fs.  For internal journal this will be
@@ -823,8 +823,8 @@ struct journal_s
        void *j_private;
 };
 
-/* 
- * Journal flag definitions 
+/*
+ * Journal flag definitions
  */
 #define JFS_UNMOUNT    0x001   /* Journal thread is being destroyed */
 #define JFS_ABORT      0x002   /* Journaling has been aborted for errors. */
@@ -833,7 +833,7 @@ struct journal_s
 #define JFS_LOADED     0x010   /* The journal superblock has been loaded */
 #define JFS_BARRIER    0x020   /* Use IDE barriers */
 
-/* 
+/*
  * Function declarations for the journaling transaction and buffer
  * management
  */
@@ -862,11 +862,11 @@ int __journal_remove_checkpoint(struct journal_head *);
 void __journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
 /* Buffer IO */
-extern int 
+extern int
 journal_write_metadata_buffer(transaction_t      *transaction,
                              struct journal_head  *jh_in,
                              struct journal_head **jh_out,
-                             int                  blocknr);
+                             unsigned long        blocknr);
 
 /* Transaction locking */
 extern void            __wait_on_journal (journal_t *);
@@ -890,7 +890,7 @@ static inline handle_t *journal_current_handle(void)
 /* The journaling code user interface:
  *
  * Create and destroy handles
- * Register buffer modifications against the current transaction. 
+ * Register buffer modifications against the current transaction.
  */
 
 extern handle_t *journal_start(journal_t *, int nblocks);
@@ -917,11 +917,11 @@ extern journal_t * journal_init_dev(struct block_device *bdev,
                                int start, int len, int bsize);
 extern journal_t * journal_init_inode (struct inode *);
 extern int        journal_update_format (journal_t *);
-extern int        journal_check_used_features 
+extern int        journal_check_used_features
                   (journal_t *, unsigned long, unsigned long, unsigned long);
-extern int        journal_check_available_features 
+extern int        journal_check_available_features
                   (journal_t *, unsigned long, unsigned long, unsigned long);
-extern int        journal_set_features 
+extern int        journal_set_features
                   (journal_t *, unsigned long, unsigned long, unsigned long);
 extern int        journal_create     (journal_t *);
 extern int        journal_load       (journal_t *journal);
@@ -977,7 +977,6 @@ extern void    journal_write_revoke_records(journal_t *, transaction_t *);
 extern int     journal_set_revoke(journal_t *, unsigned long, tid_t);
 extern int     journal_test_revoke(journal_t *, unsigned long, tid_t);
 extern void    journal_clear_revoke(journal_t *);
-extern void    journal_brelse_array(struct buffer_head *b[], int n);
 extern void    journal_switch_revoke_table(journal_t *journal);
 
 /*
@@ -1015,7 +1014,7 @@ do {                                                                         \
  * bit, when set, indicates that we have had a fatal error somewhere,
  * either inside the journaling layer or indicated to us by the client
  * (eg. ext3), and that we and should not commit any further
- * transactions.  
+ * transactions.
  */
 
 static inline int is_journal_aborted(journal_t *journal)
@@ -1082,7 +1081,7 @@ static inline int jbd_space_needed(journal_t *journal)
 #define BJ_Reserved    7       /* Buffer is reserved for access by journal */
 #define BJ_Locked      8       /* Locked for I/O during commit */
 #define BJ_Types       9
+
 extern int jbd_blocks_per_page(struct inode *inode);
 
 #ifdef __KERNEL__
index 4fa373bb18acb7c48ba69fd0628377b58382778a..4d00988dad039ebc5f871d6323b2b7d1676da9dc 100644 (file)
@@ -350,4 +350,11 @@ struct sysinfo {
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
 
+/* This helps us to avoid #ifdef CONFIG_NUMA */
+#ifdef CONFIG_NUMA
+#define NUMA_BUILD 1
+#else
+#define NUMA_BUILD 0
+#endif
+
 #endif
index 0db22a1ab474d94edfa5e4f79f95e3f286d7c51e..10f505c8431dc320f46d77a88095df20cb475cb8 100644 (file)
@@ -47,4 +47,8 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait)
 
 extern void usermodehelper_init(void);
 
+struct file;
+extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[],
+                                   struct file **filp);
+
 #endif /* __LINUX_KMOD_H__ */
diff --git a/include/linux/latency.h b/include/linux/latency.h
new file mode 100644 (file)
index 0000000..c08b52b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * latency.h: Explicit system-wide latency-expectation infrastructure
+ *
+ * (C) Copyright 2006 Intel Corporation
+ * Author: Arjan van de Ven <arjan@linux.intel.com>
+ *
+ */
+
+#ifndef _INCLUDE_GUARD_LATENCY_H_
+#define _INCLUDE_GUARD_LATENCY_H_
+
+#include <linux/notifier.h>
+
+void set_acceptable_latency(char *identifier, int usecs);
+void modify_acceptable_latency(char *identifier, int usecs);
+void remove_acceptable_latency(char *identifier);
+void synchronize_acceptable_latency(void);
+int system_latency_constraint(void);
+
+int register_latency_notifier(struct notifier_block * nb);
+int unregister_latency_notifier(struct notifier_block * nb);
+
+#define INFINITE_LATENCY 1000000
+
+#endif
index dc23c7c639f321f9bbb857d2176130c3316c4489..88afceffb7cb45df03ecbcd1045af2117f429fb1 100644 (file)
@@ -12,6 +12,9 @@
 #ifndef __LINUX_LEDS_H_INCLUDED
 #define __LINUX_LEDS_H_INCLUDED
 
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
 struct device;
 struct class_device;
 /*
index 65a5b5ceda4947d1478bba79abbda826963d128e..a9c90287c0ffef0509a6ed74719a39a7dcee28ba 100644 (file)
@@ -39,6 +39,7 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
+#ifndef CONFIG_DEBUG_LIST
 static inline void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
@@ -48,6 +49,11 @@ static inline void __list_add(struct list_head *new,
        new->prev = prev;
        prev->next = new;
 }
+#else
+extern void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next);
+#endif
 
 /**
  * list_add - add a new entry
@@ -57,10 +63,15 @@ static inline void __list_add(struct list_head *new,
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
  */
+#ifndef CONFIG_DEBUG_LIST
 static inline void list_add(struct list_head *new, struct list_head *head)
 {
        __list_add(new, head, head->next);
 }
+#else
+extern void list_add(struct list_head *new, struct list_head *head);
+#endif
+
 
 /**
  * list_add_tail - add a new entry
@@ -153,12 +164,16 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
  * Note: list_empty on entry does not return true after this, the entry is
  * in an undefined state.
  */
+#ifndef CONFIG_DEBUG_LIST
 static inline void list_del(struct list_head *entry)
 {
        __list_del(entry->prev, entry->next);
        entry->next = LIST_POISON1;
        entry->prev = LIST_POISON2;
 }
+#else
+extern void list_del(struct list_head *entry);
+#endif
 
 /**
  * list_del_rcu - deletes entry from list without re-initialization
index c040a8c969aa503d2904b88cb61921aac212496a..1314ca0f29be78f637f027614d09d5a062e091a2 100644 (file)
@@ -8,13 +8,13 @@
 #ifndef __LINUX_LOCKDEP_H
 #define __LINUX_LOCKDEP_H
 
+#ifdef CONFIG_LOCKDEP
+
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/debug_locks.h>
 #include <linux/stacktrace.h>
 
-#ifdef CONFIG_LOCKDEP
-
 /*
  * Lock-class usage-state bits:
  */
index e76c7611d6cc56e115ad71a49aa25861cc2208f6..191a595055f0063db70032a2074d8addb5eb0ad9 100644 (file)
@@ -59,10 +59,9 @@ struct loop_device {
        struct bio              *lo_bio;
        struct bio              *lo_biotail;
        int                     lo_state;
-       struct completion       lo_done;
-       struct completion       lo_bh_done;
        struct mutex            lo_ctl_mutex;
-       int                     lo_pending;
+       struct task_struct      *lo_thread;
+       wait_queue_head_t       lo_event;
 
        request_queue_t         *lo_queue;
 };
index 8f04143ca36357e3330ae2cc23c9c9595f890c8e..654ef55448780905fbdfb31d7eda298afb805b97 100644 (file)
@@ -57,7 +57,7 @@ struct memory_block {
 struct notifier_block;
 struct mem_section;
 
-#ifndef CONFIG_MEMORY_HOTPLUG
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
 static inline int memory_dev_init(void)
 {
        return 0;
@@ -78,7 +78,7 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int);
 #define CONFIG_MEM_BLOCK_SIZE  (PAGES_PER_SECTION<<PAGE_SHIFT)
 
 
-#endif /* CONFIG_MEMORY_HOTPLUG */
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
 #define hotplug_memory_notifier(fn, pri) {                     \
        static struct notifier_block fn##_mem_nb =              \
index 218501cfaeb9255ed62ca9fbf2a197cbb6993f53..7b54666cea8e9d3ea1b5c66682f2ea7a36e0fc72 100644 (file)
@@ -172,5 +172,7 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
 extern int add_memory(int nid, u64 start, u64 size);
 extern int arch_add_memory(int nid, u64 start, u64 size);
 extern int remove_memory(u64 start, u64 size);
+extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
+                                                               int nr_pages);
 
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
index 856f0ee7e84ab53370f6df38d791547bfbfdcaa8..b7966ab8cb6ac42ebd864c62542e01427d5b99eb 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/debug_locks.h>
 #include <linux/backing-dev.h>
+#include <linux/mm_types.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -198,6 +199,7 @@ struct vm_operations_struct {
        void (*open)(struct vm_area_struct * area);
        void (*close)(struct vm_area_struct * area);
        struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
+       unsigned long (*nopfn)(struct vm_area_struct * area, unsigned long address);
        int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
 
        /* notification that a previously read-only page is about to become
@@ -215,62 +217,6 @@ struct vm_operations_struct {
 struct mmu_gather;
 struct inode;
 
-/*
- * Each physical page in the system has a struct page associated with
- * it to keep track of whatever it is we are using the page for at the
- * moment. Note that we have no way to track which tasks are using
- * a page, though if it is a pagecache page, rmap structures can tell us
- * who is mapping it.
- */
-struct page {
-       unsigned long flags;            /* Atomic flags, some possibly
-                                        * updated asynchronously */
-       atomic_t _count;                /* Usage count, see below. */
-       atomic_t _mapcount;             /* Count of ptes mapped in mms,
-                                        * to show when page is mapped
-                                        * & limit reverse map searches.
-                                        */
-       union {
-           struct {
-               unsigned long private;          /* Mapping-private opaque data:
-                                                * usually used for buffer_heads
-                                                * if PagePrivate set; used for
-                                                * swp_entry_t if PageSwapCache;
-                                                * indicates order in the buddy
-                                                * system if PG_buddy is set.
-                                                */
-               struct address_space *mapping;  /* If low bit clear, points to
-                                                * inode address_space, or NULL.
-                                                * If page mapped as anonymous
-                                                * memory, low bit is set, and
-                                                * it points to anon_vma object:
-                                                * see PAGE_MAPPING_ANON below.
-                                                */
-           };
-#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
-           spinlock_t ptl;
-#endif
-       };
-       pgoff_t index;                  /* Our offset within mapping. */
-       struct list_head lru;           /* Pageout list, eg. active_list
-                                        * protected by zone->lru_lock !
-                                        */
-       /*
-        * On machines where all RAM is mapped into kernel address space,
-        * we can simply calculate the virtual address. On machines with
-        * highmem some memory is mapped into kernel virtual memory
-        * dynamically, so we need a place to store that address.
-        * Note that this field could be 16 bits on x86 ... ;)
-        *
-        * Architectures with slow multiplication can define
-        * WANT_PAGE_VIRTUAL in asm/page.h
-        */
-#if defined(WANT_PAGE_VIRTUAL)
-       void *virtual;                  /* Kernel virtual address (NULL if
-                                          not kmapped, ie. highmem) */
-#endif /* WANT_PAGE_VIRTUAL */
-};
-
 #define page_private(page)             ((page)->private)
 #define set_page_private(page, v)      ((page)->private = (v))
 
@@ -501,7 +447,11 @@ static inline struct zone *page_zone(struct page *page)
 
 static inline unsigned long zone_to_nid(struct zone *zone)
 {
-       return zone->zone_pgdat->node_id;
+#ifdef CONFIG_NUMA
+       return zone->node;
+#else
+       return 0;
+#endif
 }
 
 static inline unsigned long page_to_nid(struct page *page)
@@ -546,11 +496,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
  */
 #include <linux/vmstat.h>
 
-#ifndef CONFIG_DISCONTIGMEM
-/* The array of struct pages - for discontigmem use pgdat->lmem_map */
-extern struct page *mem_map;
-#endif
-
 static __always_inline void *lowmem_page_address(struct page *page)
 {
        return __va(page_to_pfn(page) << PAGE_SHIFT);
@@ -649,6 +594,12 @@ static inline int page_mapped(struct page *page)
 #define NOPAGE_SIGBUS  (NULL)
 #define NOPAGE_OOM     ((struct page *) (-1))
 
+/*
+ * Error return values for the *_nopfn functions
+ */
+#define NOPFN_SIGBUS   ((unsigned long) -1)
+#define NOPFN_OOM      ((unsigned long) -2)
+
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
  * Used to decide whether a process gets delivered SIGBUS or
@@ -792,7 +743,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long
                int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
 void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long);
 
-int __set_page_dirty_buffers(struct page *page);
+extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
+extern void do_invalidatepage(struct page *page, unsigned long offset);
+
 int __set_page_dirty_nobuffers(struct page *page);
 int redirty_page_for_writepage(struct writeback_control *wbc,
                                struct page *page);
@@ -937,12 +890,64 @@ extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, pg_data_t *pgdat,
        unsigned long * zones_size, unsigned long zone_start_pfn, 
        unsigned long *zholes_size);
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+/*
+ * With CONFIG_ARCH_POPULATES_NODE_MAP set, an architecture may initialise its
+ * zones, allocate the backing mem_map and account for memory holes in a more
+ * architecture independent manner. This is a substitute for creating the
+ * zone_sizes[] and zholes_size[] arrays and passing them to
+ * free_area_init_node()
+ *
+ * An architecture is expected to register range of page frames backed by
+ * physical memory with add_active_range() before calling
+ * free_area_init_nodes() passing in the PFN each zone ends at. At a basic
+ * usage, an architecture is expected to do something like
+ *
+ * unsigned long max_zone_pfns[MAX_NR_ZONES] = {max_dma, max_normal_pfn,
+ *                                                      max_highmem_pfn};
+ * for_each_valid_physical_page_range()
+ *     add_active_range(node_id, start_pfn, end_pfn)
+ * free_area_init_nodes(max_zone_pfns);
+ *
+ * If the architecture guarantees that there are no holes in the ranges
+ * registered with add_active_range(), free_bootmem_active_regions()
+ * will call free_bootmem_node() for each registered physical page range.
+ * Similarly sparse_memory_present_with_active_regions() calls
+ * memory_present() for each range when SPARSEMEM is enabled.
+ *
+ * See mm/page_alloc.c for more information on each function exposed by
+ * CONFIG_ARCH_POPULATES_NODE_MAP
+ */
+extern void free_area_init_nodes(unsigned long *max_zone_pfn);
+extern void add_active_range(unsigned int nid, unsigned long start_pfn,
+                                       unsigned long end_pfn);
+extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
+                                               unsigned long new_end_pfn);
+extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn,
+                                       unsigned long end_pfn);
+extern void remove_all_active_ranges(void);
+extern unsigned long absent_pages_in_range(unsigned long start_pfn,
+                                               unsigned long end_pfn);
+extern void get_pfn_range_for_nid(unsigned int nid,
+                       unsigned long *start_pfn, unsigned long *end_pfn);
+extern unsigned long find_min_pfn_with_active_regions(void);
+extern unsigned long find_max_pfn_with_active_regions(void);
+extern void free_bootmem_with_active_regions(int nid,
+                                               unsigned long max_low_pfn);
+extern void sparse_memory_present_with_active_regions(int nid);
+#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+extern int early_pfn_to_nid(unsigned long pfn);
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+extern void set_dma_reserve(unsigned long new_dma_reserve);
 extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
 extern void setup_per_zone_pages_min(void);
 extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
+extern void zonetable_add(struct zone *zone, int nid, enum zone_type zid,
+                                       unsigned long pfn, unsigned long size);
 
 #ifdef CONFIG_NUMA
 extern void setup_per_cpu_pageset(void);
@@ -1130,7 +1135,7 @@ void drop_slab(void);
 extern int randomize_va_space;
 #endif
 
-const char *arch_vma_name(struct vm_area_struct *vma);
+__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
new file mode 100644 (file)
index 0000000..c3852fd
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _LINUX_MM_TYPES_H
+#define _LINUX_MM_TYPES_H
+
+#include <linux/types.h>
+#include <linux/threads.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+struct address_space;
+
+/*
+ * Each physical page in the system has a struct page associated with
+ * it to keep track of whatever it is we are using the page for at the
+ * moment. Note that we have no way to track which tasks are using
+ * a page, though if it is a pagecache page, rmap structures can tell us
+ * who is mapping it.
+ */
+struct page {
+       unsigned long flags;            /* Atomic flags, some possibly
+                                        * updated asynchronously */
+       atomic_t _count;                /* Usage count, see below. */
+       atomic_t _mapcount;             /* Count of ptes mapped in mms,
+                                        * to show when page is mapped
+                                        * & limit reverse map searches.
+                                        */
+       union {
+           struct {
+               unsigned long private;          /* Mapping-private opaque data:
+                                                * usually used for buffer_heads
+                                                * if PagePrivate set; used for
+                                                * swp_entry_t if PageSwapCache;
+                                                * indicates order in the buddy
+                                                * system if PG_buddy is set.
+                                                */
+               struct address_space *mapping;  /* If low bit clear, points to
+                                                * inode address_space, or NULL.
+                                                * If page mapped as anonymous
+                                                * memory, low bit is set, and
+                                                * it points to anon_vma object:
+                                                * see PAGE_MAPPING_ANON below.
+                                                */
+           };
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+           spinlock_t ptl;
+#endif
+       };
+       pgoff_t index;                  /* Our offset within mapping. */
+       struct list_head lru;           /* Pageout list, eg. active_list
+                                        * protected by zone->lru_lock !
+                                        */
+       /*
+        * On machines where all RAM is mapped into kernel address space,
+        * we can simply calculate the virtual address. On machines with
+        * highmem some memory is mapped into kernel virtual memory
+        * dynamically, so we need a place to store that address.
+        * Note that this field could be 16 bits on x86 ... ;)
+        *
+        * Architectures with slow multiplication can define
+        * WANT_PAGE_VIRTUAL in asm/page.h
+        */
+#if defined(WANT_PAGE_VIRTUAL)
+       void *virtual;                  /* Kernel virtual address (NULL if
+                                          not kmapped, ie. highmem) */
+#endif /* WANT_PAGE_VIRTUAL */
+};
+
+#endif /* _LINUX_MM_TYPES_H */
index ba095aebedffb67cf060fa2fc5e0c56c9483a05c..587264a58d5605835319bcfc77912e9763391128 100644 (file)
@@ -85,6 +85,8 @@ struct mmc_host {
        unsigned long           caps;           /* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA     (1 << 0)        /* Can the host do 4 bit transfers */
+#define MMC_CAP_MULTIWRITE     (1 << 1)        /* Can accurately report bytes sent to card on error */
+#define MMC_CAP_BYTEBLOCK      (1 << 2)        /* Can do non-log2 block sizes */
 
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
index 627e2c08ce41d3fe4851c346e061a046dd0dfc20..a3594dfd696399ae8609417cafdc1f0ca844272a 100644 (file)
@@ -68,7 +68,6 @@ struct mmc_command {
 struct mmc_data {
        unsigned int            timeout_ns;     /* data timeout (in ns, max 80ms) */
        unsigned int            timeout_clks;   /* data timeout (in clocks) */
-       unsigned int            blksz_bits;     /* data block size */
        unsigned int            blksz;          /* data block size */
        unsigned int            blocks;         /* number of blocks */
        unsigned int            error;          /* data error */
index 3693f1a5278839c23243691564a5085af0617313..59855b8718a0a4b993a39cb825034ad081dd09cd 100644 (file)
@@ -58,6 +58,7 @@ enum zone_stat_item {
        NR_WRITEBACK,
        NR_UNSTABLE_NFS,        /* NFS unstable pages */
        NR_BOUNCE,
+       NR_VMSCAN_WRITE,
 #ifdef CONFIG_NUMA
        NUMA_HIT,               /* allocated in intended node */
        NUMA_MISS,              /* allocated in non intended node */
@@ -167,6 +168,7 @@ struct zone {
        unsigned long           lowmem_reserve[MAX_NR_ZONES];
 
 #ifdef CONFIG_NUMA
+       int node;
        /*
         * zone reclaim becomes active if more unmapped pages exist.
         */
@@ -305,6 +307,18 @@ struct zonelist {
        struct zone *zones[MAX_NUMNODES * MAX_NR_ZONES + 1]; // NULL delimited
 };
 
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+struct node_active_region {
+       unsigned long start_pfn;
+       unsigned long end_pfn;
+       int nid;
+};
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+
+#ifndef CONFIG_DISCONTIGMEM
+/* The array of struct pages - for discontigmem use pgdat->lmem_map */
+extern struct page *mem_map;
+#endif
 
 /*
  * The pg_data_t structure is used in machines with CONFIG_DISCONTIGMEM
@@ -518,7 +532,8 @@ extern struct zone *next_zone(struct zone *zone);
 
 #endif
 
-#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+#if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \
+       !defined(CONFIG_ARCH_POPULATES_NODE_MAP)
 #define early_pfn_to_nid(nid)  (0UL)
 #endif
 
index f7ca0b09075d960d54315b20c2f2cb1e29e3ec94..e0c393cc724048696b43e0ac4b2af04c3053cca3 100644 (file)
@@ -308,4 +308,16 @@ struct input_device_id {
        kernel_ulong_t driver_info;
 };
 
+/* EISA */
+
+#define EISA_SIG_LEN   8
+
+/* The EISA signature, in ASCII form, null terminated */
+struct eisa_device_id {
+       char          sig[EISA_SIG_LEN];
+       kernel_ulong_t driver_data;
+};
+
+#define EISA_DEVICE_MODALIAS_FMT "eisa:s%s"
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
index d4486cc2e7fe6cdf822d95543610fddee2835185..2c599175c583c36a0bbd71528640489fceb6c149 100644 (file)
@@ -232,17 +232,17 @@ enum module_state
 };
 
 /* Similar stuff for section attributes. */
-#define MODULE_SECT_NAME_LEN 32
 struct module_sect_attr
 {
        struct module_attribute mattr;
-       char name[MODULE_SECT_NAME_LEN];
+       char *name;
        unsigned long address;
 };
 
 struct module_sect_attrs
 {
        struct attribute_group grp;
+       int nsections;
        struct module_sect_attr attrs[0];
 };
 
index 3ca880463c47426029bad70eb02f30ad3ab41015..cc5fb75af78a25e22c55ba868e4612e09331fbe1 100644 (file)
@@ -9,6 +9,7 @@
  * (And no, it doesn't do the #ifdef __MPAGE_H thing, and it doesn't do
  * nested includes.  Get it right in the .c file).
  */
+#ifdef CONFIG_BLOCK
 
 struct writeback_control;
 typedef int (writepage_t)(struct page *page, struct writeback_control *wbc);
@@ -21,8 +22,4 @@ int mpage_writepages(struct address_space *mapping,
 int mpage_writepage(struct page *page, get_block_t *get_block,
                struct writeback_control *wbc);
 
-static inline int
-generic_writepages(struct address_space *mapping, struct writeback_control *wbc)
-{
-       return mpage_writepages(mapping, wbc, NULL);
-}
+#endif
index e05d54a90743e4890a99436c0616ad428142643c..7da2cee8e1328731ef3fccbcb011f2d9524be3b6 100644 (file)
@@ -142,7 +142,7 @@ struct vif_device
        unsigned long   rate_limit;             /* Traffic shaping (NI)         */
        unsigned char   threshold;              /* TTL threshold                */
        unsigned short  flags;                  /* Control flags                */
-       __u32           local,remote;           /* Addresses(remote for tunnels)*/
+       __be32          local,remote;           /* Addresses(remote for tunnels)*/
        int             link;                   /* Physical interface index     */
 };
 
@@ -151,8 +151,8 @@ struct vif_device
 struct mfc_cache 
 {
        struct mfc_cache *next;                 /* Next entry on cache line     */
-       __u32 mfc_mcastgrp;                     /* Group the entry belongs to   */
-       __u32 mfc_origin;                       /* Source of packet             */
+       __be32 mfc_mcastgrp;                    /* Group the entry belongs to   */
+       __be32 mfc_origin;                      /* Source of packet             */
        vifi_t mfc_parent;                      /* Source interface             */
        int mfc_flags;                          /* Flags on line                */
 
@@ -179,9 +179,9 @@ struct mfc_cache
 #define MFC_LINES              64
 
 #ifdef __BIG_ENDIAN
-#define MFC_HASH(a,b)  ((((a)>>24)^((b)>>26))&(MFC_LINES-1))
+#define MFC_HASH(a,b)  (((((__force u32)(__be32)a)>>24)^(((__force u32)(__be32)b)>>26))&(MFC_LINES-1))
 #else
-#define MFC_HASH(a,b)  (((a)^((b)>>2))&(MFC_LINES-1))
+#define MFC_HASH(a,b)  ((((__force u32)(__be32)a)^(((__force u32)(__be32)b)>>2))&(MFC_LINES-1))
 #endif         
 
 #endif
@@ -213,8 +213,8 @@ struct pimreghdr
 {
        __u8    type;
        __u8    reserved;
-       __u16   csum;
-       __u32   flags;
+       __be16  csum;
+       __be32  flags;
 };
 
 extern int pim_rcv_v1(struct sk_buff *);
index bae62d62dc3e07e44b54d54c272f74d28c744c77..ce6c85815cbd17be44e95f9244c84bbc7c5f3b4b 100644 (file)
@@ -204,6 +204,7 @@ struct fat_mount_options {
                 unicode_xlate:1, /* create escape sequences for unhandled Unicode */
                 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*/
 };
 
@@ -412,6 +413,8 @@ extern int fat_sync_inode(struct inode *inode);
 extern int fat_fill_super(struct super_block *sb, void *data, int silent,
                        struct inode_operations *fs_dir_inode_ops, int isvfat);
 
+extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
+                           struct inode *i2);
 /* fat/misc.c */
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
 extern void fat_clusters_flush(struct super_block *sb);
index 45511a5918d3edf6be65188c3b1c64ab650da1e8..f5f19606effbd0c84f74007aaf25c145e76d9eef 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_NAMEI_H
 #define _LINUX_NAMEI_H
 
+#include <linux/dcache.h>
 #include <linux/linkage.h>
 
 struct vfsmount;
@@ -54,6 +55,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_OPEN            (0x0100)
 #define LOOKUP_CREATE          (0x0200)
 #define LOOKUP_ACCESS          (0x0400)
+#define LOOKUP_CHDIR           (0x0800)
 
 extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
 extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
index 02e352be717e93f650743c4ca41dfe271a9027bb..0ea7f89e613c1c6f95ac5fcbb71cdbcfa5f6b9d9 100644 (file)
@@ -212,6 +212,7 @@ void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
 
 /* linux/fs/ncpfs/ioctl.c */
 int ncp_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+long ncp_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 /* linux/fs/ncpfs/sock.c */
 int ncp_request2(struct ncp_server *server, int function,
index 43289127b458345334a961caa6bd269799f00aad..9264139bd8df0ee171c2d52531fa626720c42a1f 100644 (file)
@@ -187,7 +187,7 @@ struct hh_cache
 {
        struct hh_cache *hh_next;       /* Next entry                        */
        atomic_t        hh_refcnt;      /* number of users                   */
-       unsigned short  hh_type;        /* protocol identifier, f.e ETH_P_IP
+       __be16          hh_type;        /* protocol identifier, f.e ETH_P_IP
                                          *  NOTE:  For VLANs, this will be the
                                          *  encapuslated type. --BLG
                                          */
@@ -334,7 +334,6 @@ struct net_device
 
 
        struct net_device_stats* (*get_stats)(struct net_device *dev);
-       struct iw_statistics*   (*get_wireless_stats)(struct net_device *dev);
 
        /* List of functions to handle Wireless Extensions (instead of ioctl).
         * See <net/iw_handler.h> for details. Jean II */
@@ -1016,7 +1015,8 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 }
 
 /* On bonding slaves other than the currently active slave, suppress
- * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
  */
 static inline int skb_bond_should_drop(struct sk_buff *skb)
 {
@@ -1025,6 +1025,10 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)
 
        if (master &&
            (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
+               if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+                   skb->protocol == __constant_htons(ETH_P_ARP))
+                       return 0;
+
                if (master->priv_flags & IFF_MASTER_ALB) {
                        if (skb->pkt_type != PACKET_BROADCAST &&
                            skb->pkt_type != PACKET_MULTICAST)
index 149e87c9ab1367cd95e5f058a40427f2167303f5..44e39b61d9e7e3b11e4b3e863204b4a89bb8cd1b 100644 (file)
@@ -46,11 +46,11 @@ struct arpt_arp {
        struct arpt_devaddr_info tgt_devaddr;
 
        /* ARP operation code. */
-       u_int16_t arpop, arpop_mask;
+       __be16 arpop, arpop_mask;
 
        /* ARP hardware address and protocol address format. */
-       u_int16_t arhrd, arhrd_mask;
-       u_int16_t arpro, arpro_mask;
+       __be16 arhrd, arhrd_mask;
+       __be16 arpro, arpro_mask;
 
        /* The protocol address length is only accepted if it is 4
         * so there is no use in offering a way to do filtering on it.
index 51dbec1892c802c3d313c3593fb0d2967a90ad2e..64e868034c4ab5868f3e2894194a39814bc66993 100644 (file)
@@ -157,7 +157,7 @@ struct ip_conntrack_expect
        unsigned int flags;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
-       u_int32_t saved_ip;
+       __be32 saved_ip;
        /* This is the original per-proto part, used to map the
         * expected connection the way the recipient expects. */
        union ip_conntrack_manip_proto saved_proto;
index 3cbff7379002ced59a07d65ab88587767df8b59e..943cc6a4871d172d96ffc19f622ae5edc226c32f 100644 (file)
@@ -30,7 +30,7 @@ struct ip_ct_h323_master {
 struct ip_conntrack_expect;
 
 extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
-                        u_int32_t * ip, u_int16_t * port);
+                        __be32 * ip, u_int16_t * port);
 extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
                                     struct ip_conntrack_expect *this);
 extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
@@ -38,11 +38,11 @@ extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
 extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
                                  unsigned char **data, int dataoff,
                                  H245_TransportAddress * addr,
-                                 u_int32_t ip, u_int16_t port);
+                                 __be32 ip, u_int16_t port);
 extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
                                  unsigned char **data, int dataoff,
                                  TransportAddress * addr,
-                                 u_int32_t ip, u_int16_t port);
+                                 __be32 ip, u_int16_t port);
 extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
                                 struct ip_conntrack * ct,
                                 enum ip_conntrack_info ctinfo,
index 2fdabdb4c0ef5d0395cab5dc55d75eff1b378dd1..c228bde74c3325c0d26f3319297a63c36f1792dd 100644 (file)
@@ -23,13 +23,13 @@ union ip_conntrack_manip_proto
                __be16 port;
        } tcp;
        struct {
-               u_int16_t port;
+               __be16 port;
        } udp;
        struct {
-               u_int16_t id;
+               __be16 id;
        } icmp;
        struct {
-               u_int16_t port;
+               __be16 port;
        } sctp;
        struct {
                __be16 key;     /* key is 32bit, pptp only uses 16 */
@@ -39,7 +39,7 @@ union ip_conntrack_manip_proto
 /* The manipulable part of the tuple. */
 struct ip_conntrack_manip
 {
-       u_int32_t ip;
+       __be32 ip;
        union ip_conntrack_manip_proto u;
 };
 
@@ -50,22 +50,22 @@ struct ip_conntrack_tuple
 
        /* These are the parts of the tuple which are fixed. */
        struct {
-               u_int32_t ip;
+               __be32 ip;
                union {
                        /* Add other protocols here. */
                        u_int16_t all;
 
                        struct {
-                               u_int16_t port;
+                               __be16 port;
                        } tcp;
                        struct {
-                               u_int16_t port;
+                               __be16 port;
                        } udp;
                        struct {
                                u_int8_t type, code;
                        } icmp;
                        struct {
-                               u_int16_t port;
+                               __be16 port;
                        } sctp;
                        struct {
                                __be16 key;     /* key is 32bit, 
index 98f8407e4cb5011f0d343f241cc4b4741e56962b..bdf553620ca188ddbc53695d14d0389dd386d716 100644 (file)
@@ -33,7 +33,7 @@ struct ip_nat_range
        unsigned int flags;
 
        /* Inclusive: network order. */
-       u_int32_t min_ip, max_ip;
+       __be32 min_ip, max_ip;
 
        /* Inclusive: network order */
        union ip_conntrack_manip_proto min, max;
index aa08d68c4841ebdf265a99494bc9a88933f5d815..a03507f465f8e8be148f1accd413ca4373ff69e7 100644 (file)
@@ -26,7 +26,7 @@ typedef struct ipq_packet_msg {
        unsigned int hook;              /* Netfilter hook we rode in on */
        char indev_name[IFNAMSIZ];      /* Name of incoming interface */
        char outdev_name[IFNAMSIZ];     /* Name of outgoing interface */
-       unsigned short hw_protocol;     /* Hardware protocol (network order) */
+       __be16 hw_protocol;             /* Hardware protocol (network order) */
        unsigned short hw_type;         /* Hardware type */
        unsigned char hw_addrlen;       /* Hardware address length */
        unsigned char hw_addr[8];       /* Hardware address */
index 3ecb3bd63676a118de24f0e7616dfa1f27e0c2ef..34ab0fb736e2f75d057ea3c6e2bd1d9a65410eaf 100644 (file)
@@ -8,7 +8,7 @@
 
 struct ipt_iprange {
        /* Inclusive: network order. */
-       u_int32_t min_ip, max_ip;
+       __be32 min_ip, max_ip;
 };
 
 struct ipt_iprange_info
index 36f5bcf513b09496e14f1f5f7f1dae5877da1ea2..76ff54846ada1e07cab6ca2fa8e0de019a906e85 100644 (file)
@@ -315,10 +315,6 @@ extern void nfs_end_data_update(struct inode *);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode);
-extern struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-                                       const struct dentry *dentry,
-                                       struct nfs_fh *fh,
-                                       struct nfs_fattr *fattr);
 
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
@@ -371,10 +367,12 @@ extern int nfs3_removexattr (struct dentry *, const char *name);
  */
 extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
                        unsigned long);
-extern ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf,
-                       size_t count, loff_t pos);
-extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf,
-                       size_t count, loff_t pos);
+extern ssize_t nfs_file_direct_read(struct kiocb *iocb,
+                       const struct iovec *iov, unsigned long nr_segs,
+                       loff_t pos);
+extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
+                       const struct iovec *iov, unsigned long nr_segs,
+                       loff_t pos);
 
 /*
  * linux/fs/nfs/dir.c
index f9edcd2ff3c828c9496ca4da4f007d326e16ea4e..31a3cb617ce0b02c1129bcba8d58ff1c4bac000a 100644 (file)
@@ -269,14 +269,8 @@ fill_post_wcc(struct svc_fh *fhp)
        fhp->fh_post_uid        = inode->i_uid;
        fhp->fh_post_gid        = inode->i_gid;
        fhp->fh_post_size       = inode->i_size;
-       if (inode->i_blksize) {
-               fhp->fh_post_blksize    = inode->i_blksize;
-               fhp->fh_post_blocks     = inode->i_blocks;
-       } else {
-               fhp->fh_post_blksize    = BLOCK_SIZE;
-               /* how much do we care for accuracy with MinixFS? */
-               fhp->fh_post_blocks     = (inode->i_size+511) >> 9;
-       }
+       fhp->fh_post_blksize    = BLOCK_SIZE;
+       fhp->fh_post_blocks     = inode->i_blocks;
        fhp->fh_post_rdev[0]    = htonl((u32)imajor(inode));
        fhp->fh_post_rdev[1]    = htonl((u32)iminor(inode));
        fhp->fh_post_atime      = inode->i_atime;
index c8f4d2f627d70099019f2e423cb8aec909d48034..e16904e28c3a39b57480d5bc5e64f5923cc5434a 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef LINUX_NMI_H
 #define LINUX_NMI_H
 
+#include <linux/sched.h>
 #include <asm/irq.h>
 
 /**
@@ -16,7 +17,7 @@
 #ifdef ARCH_HAS_NMI_WATCHDOG
 extern void touch_nmi_watchdog(void);
 #else
-# define touch_nmi_watchdog() do { } while(0)
+# define touch_nmi_watchdog() touch_softlockup_watchdog()
 #endif
 
 #endif
index 9d7921dd50f0c19a3d500d4aeb8bc64a7d8242b9..4830a3bedfb240480e1ade7c58d030b0ab12e978 100644 (file)
 
 #define PageUptodate(page)     test_bit(PG_uptodate, &(page)->flags)
 #ifdef CONFIG_S390
-#define SetPageUptodate(_page) \
-       do {                                                                  \
-               struct page *__page = (_page);                                \
-               if (!test_and_set_bit(PG_uptodate, &__page->flags))           \
-                       page_test_and_clear_dirty(_page);                     \
-       } while (0)
+static inline void SetPageUptodate(struct page *page)
+{
+       if (!test_and_set_bit(PG_uptodate, &page->flags))
+               page_test_and_clear_dirty(page);
+}
 #else
 #define SetPageUptodate(page)  set_bit(PG_uptodate, &(page)->flags)
 #endif
index 3ec72551ac31ccb0398667fe0310d61a68d68126..4431ce4e1e6f9fa8d27801cb88a7f9c51049d572 100644 (file)
@@ -356,6 +356,8 @@ struct pci_driver {
        struct pci_error_handlers *err_handler;
        struct device_driver    driver;
        struct pci_dynids dynids;
+
+       int multithread_probe;
 };
 
 #define        to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
@@ -431,7 +433,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn);
 struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
-void pci_bus_add_device(struct pci_dev *dev);
+int __must_check pci_bus_add_device(struct pci_dev *dev);
 void pci_read_bridge_bases(struct pci_bus *child);
 struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
@@ -439,6 +441,7 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_remove_bus_device(struct pci_dev *dev);
+extern void pci_stop_bus_device(struct pci_dev *dev);
 void pci_setup_cardbus(struct pci_bus *bus);
 
 /* Generic PCI functions exported to card drivers */
@@ -784,12 +787,13 @@ enum pci_fixup_pass {
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 
 extern int pci_pci_problems;
-#define PCIPCI_FAIL            1
+#define PCIPCI_FAIL            1       /* No PCI PCI DMA */
 #define PCIPCI_TRITON          2
 #define PCIPCI_NATOMA          4
 #define PCIPCI_VIAETBF         8
 #define PCIPCI_VSFX            16
-#define PCIPCI_ALIMAGIK                32
+#define PCIPCI_ALIMAGIK                32      /* Need low latency setting */
+#define PCIAGP_FAIL            64      /* No PCI to AGP DMA */
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index 6a1e09834559a3b4945803debc64dab2d4363120..c9ffbc3843d57894d44474bf841664203d60091a 100644 (file)
 
 #define PCI_VENDOR_ID_AMD              0x1022
 #define PCI_DEVICE_ID_AMD_K8_NB                0x1100
+#define PCI_DEVICE_ID_AMD_K8_NB_MISC   0x1103
 #define PCI_DEVICE_ID_AMD_LANCE                0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME   0x2001
 #define PCI_DEVICE_ID_AMD_SCSI         0x2020
 #define PCI_DEVICE_ID_AMD_8151_0       0x7454
 #define PCI_DEVICE_ID_AMD_8131_BRIDGE  0x7450
 #define PCI_DEVICE_ID_AMD_8131_APIC    0x7451
+#define PCI_DEVICE_ID_AMD_8132_BRIDGE  0x7458
 #define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
 #define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
 #define PCI_DEVICE_ID_AMD_CS5536_AUDIO  0x2093
 #define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
 #define PCI_DEVICE_ID_SERVERWORKS_EPB    0x0103
+#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE  0x0132
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4   0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5   0x0201
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6    0x0203
 #define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
 #define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
-#define PCI_DEVICE_ID_MARVELL_GT96100  0x9652
-#define PCI_DEVICE_ID_MARVELL_GT96100A 0x9653
-
 
 #define PCI_VENDOR_ID_V3               0x11b0
 #define PCI_DEVICE_ID_V3_V960          0x0001
 #define PCI_DEVICE_ID_TIGON3_5705_2    0x1654
 #define PCI_DEVICE_ID_TIGON3_5720      0x1658
 #define PCI_DEVICE_ID_TIGON3_5721      0x1659
+#define PCI_DEVICE_ID_TIGON3_5722      0x165a
 #define PCI_DEVICE_ID_TIGON3_5705M     0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
 #define PCI_DEVICE_ID_TIGON3_5714      0x1668
 #define PCI_DEVICE_ID_TIGON3_5705F     0x166e
 #define PCI_DEVICE_ID_TIGON3_5754M     0x1672
 #define PCI_DEVICE_ID_TIGON3_5755M     0x1673
+#define PCI_DEVICE_ID_TIGON3_5756      0x1674
 #define PCI_DEVICE_ID_TIGON3_5750      0x1676
 #define PCI_DEVICE_ID_TIGON3_5751      0x1677
 #define PCI_DEVICE_ID_TIGON3_5715      0x1678
 #define PCI_DEVICE_ID_TIGON3_5901      0x170d
 #define PCI_DEVICE_ID_BCM4401B1                0x170c
 #define PCI_DEVICE_ID_TIGON3_5901_2    0x170e
+#define PCI_DEVICE_ID_TIGON3_5906      0x1712
+#define PCI_DEVICE_ID_TIGON3_5906M     0x1713
 #define PCI_DEVICE_ID_BCM4401          0x4401
 #define PCI_DEVICE_ID_BCM4401B0                0x4402
 
index 96930cb5927cddbf04852baca5c7aed50afd04ac..7d0e26cba42051d7230ec7d9ac1723c6569654ff 100644 (file)
 #define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts */
 #define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
 #define  PCI_CAP_ID_PCIX       0x07    /* PCI-X */
-#define  PCI_CAP_ID_HT_IRQCONF 0x08    /* HyperTransport IRQ Configuration */
+#define  PCI_CAP_ID_HT         0x08    /* HyperTransport */
 #define  PCI_CAP_ID_VNDR       0x09    /* Vendor specific capability */
 #define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller */
 #define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
index b44e01a70914a81cccabfdbc4ad4c4df1e3a5afc..6cd91e3f982052df783c2ec9b9df130bff118659 100644 (file)
@@ -62,6 +62,12 @@ struct pcie_port_service_driver {
        int (*suspend) (struct pcie_device *dev, pm_message_t state);
        int (*resume) (struct pcie_device *dev);
 
+       /* Service Error Recovery Handler */
+       struct pci_error_handlers *err_handler;
+
+       /* Link Reset Capability - AER service driver specific */
+       pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+
        const struct pcie_port_service_id *id_table;
        struct device_driver driver;
 };
index 3835a9642f13f3702d31b6dfd3202dd96c194407..46ec72fa2c8435db3e9d8bd17605916aff3b5e54 100644 (file)
@@ -74,7 +74,7 @@ static inline int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
        return 0;
 }
 
-static inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
+static __always_inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
 {
        return kzalloc(size, gfp);
 }
index 29960b03bef75ef031054485c6df960aab0bdc50..93da7e2d9f30bdda2268d8163e3c9f29d73a4a4a 100644 (file)
@@ -76,6 +76,8 @@ extern int FASTCALL(attach_pid(struct task_struct *task,
                                enum pid_type type, int nr));
 
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
+extern void FASTCALL(transfer_pid(struct task_struct *old,
+                                 struct task_struct *new, enum pid_type));
 
 /*
  * look up a PID in the hash table. Must be called with the tasklist_lock
index 95572c434bc991dc23dd5b9074d3bb36bd69b192..a7dd38f30ade61d1cf6fba16d7f7f60b3e8cc944 100644 (file)
@@ -72,6 +72,7 @@ struct k_clock {
        int (*timer_create) (struct k_itimer *timer);
        int (*nsleep) (const clockid_t which_clock, int flags,
                       struct timespec *, struct timespec __user *);
+       long (*nsleep_restart) (struct restart_block *restart_block);
        int (*timer_set) (struct k_itimer * timr, int flags,
                          struct itimerspec * new_setting,
                          struct itimerspec * old_setting);
@@ -97,6 +98,7 @@ int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
 int posix_cpu_timer_create(struct k_itimer *timer);
 int posix_cpu_nsleep(const clockid_t which_clock, int flags,
                     struct timespec *rqtp, struct timespec __user *rmtp);
+long posix_cpu_nsleep_restart(struct restart_block *restart_block);
 int posix_cpu_timer_set(struct k_itimer *timer, int flags,
                        struct itimerspec *new, struct itimerspec *old);
 int posix_cpu_timer_del(struct k_itimer *timer);
@@ -111,4 +113,6 @@ void posix_cpu_timers_exit_group(struct task_struct *task);
 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
                           cputime_t *newval, cputime_t *oldval);
 
+long clock_nanosleep_restart(struct restart_block *restart_block);
+
 #endif
index 3435ca38dd142ee705bc57032d0fd855b8c18635..57f70bc8b24bba1bf3f9e9336a1a10b01945778c 100644 (file)
@@ -268,7 +268,9 @@ static inline struct proc_dir_entry *PDE(const struct inode *inode)
 struct proc_maps_private {
        struct pid *pid;
        struct task_struct *task;
+#ifdef CONFIG_MMU
        struct vm_area_struct *tail_vma;
+#endif
 };
 
 #endif /* _LINUX_PROC_FS_H */
index 8b2749a259dc0a040194b8c353c2e3a56ce7136a..eeb1976ef7bf2069a587c4a042624599c0c59099 100644 (file)
@@ -16,8 +16,8 @@
 #define PTRACE_KILL               8
 #define PTRACE_SINGLESTEP         9
 
-#define PTRACE_ATTACH          0x10
-#define PTRACE_DETACH          0x11
+#define PTRACE_ATTACH            16
+#define PTRACE_DETACH            17
 
 #define PTRACE_SYSCALL           24
 
index eb3e547c8fee37798521949cc4f341df352a6d6d..c588709acbbc90b868681dda826605fa14afb0a5 100644 (file)
@@ -53,6 +53,8 @@
 #include <linux/raid/md_u.h>
 #include <linux/raid/md_k.h>
 
+#ifdef CONFIG_MD
+
 /*
  * Different major versions are not compatible.
  * Different minor versions are only downward compatible.
@@ -95,5 +97,6 @@ extern void md_new_event(mddev_t *mddev);
 
 extern void md_update_sb(mddev_t * mddev);
 
+#endif /* CONFIG_MD */
 #endif 
 
index d28890295852ce4f9be9f6bf0c6529f7b81041e6..920b94fe31fa2ed5184f8cdb4d41683efeeb15f4 100644 (file)
@@ -18,6 +18,8 @@
 /* and dm-bio-list.h is not under include/linux because.... ??? */
 #include "../../../drivers/md/dm-bio-list.h"
 
+#ifdef CONFIG_BLOCK
+
 #define        LEVEL_MULTIPATH         (-4)
 #define        LEVEL_LINEAR            (-1)
 #define        LEVEL_FAULTY            (-5)
@@ -362,5 +364,6 @@ static inline void safe_put_page(struct page *p)
        if (p) put_page(p);
 }
 
+#endif /* CONFIG_BLOCK */
 #endif
 
index 00b340ba66127131b5f4a3790d649b1bc33c5256..b160fb18e8d6ce6f724827fe19fd31dfe748ddb8 100644 (file)
@@ -17,5 +17,6 @@ extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
 
 extern const struct file_operations ramfs_file_operations;
 extern struct vm_operations_struct generic_file_vm_ops;
+extern int __init init_rootfs(void);
 
 #endif
index 8d5382e62c08e8503f5e43e2e62b7215df2dd26b..344bc3495ddbd12548c32ebaf57cd3c6ee7e8be9 100644 (file)
@@ -133,7 +133,7 @@ static inline void rb_set_color(struct rb_node *rb, int color)
 #define        rb_entry(ptr, type, member) container_of(ptr, type, member)
 
 #define RB_EMPTY_ROOT(root)    ((root)->rb_node == NULL)
-#define RB_EMPTY_NODE(node)    (rb_parent(node) != node)
+#define RB_EMPTY_NODE(node)    (rb_parent(node) == node)
 #define RB_CLEAR_NODE(node)    (rb_set_parent(node, node))
 
 extern void rb_insert_color(struct rb_node *, struct rb_root *);
index 806ec5b067075554792d5631996b24595157d697..fe00f781a622ab73a2230414a09b4e6fe6df96ae 100644 (file)
@@ -56,6 +56,16 @@ extern int reiserfs_xattr_posix_acl_init(void) __init;
 extern int reiserfs_xattr_posix_acl_exit(void);
 extern struct reiserfs_xattr_handler posix_acl_default_handler;
 extern struct reiserfs_xattr_handler posix_acl_access_handler;
+
+static inline void reiserfs_init_acl_access(struct inode *inode)
+{
+       REISERFS_I(inode)->i_acl_access = NULL;
+}
+
+static inline void reiserfs_init_acl_default(struct inode *inode)
+{
+       REISERFS_I(inode)->i_acl_default = NULL;
+}
 #else
 
 #define reiserfs_cache_default_acl(inode) 0
@@ -87,4 +97,11 @@ reiserfs_inherit_default_acl(const struct inode *dir, struct dentry *dentry,
        return 0;
 }
 
+static inline void reiserfs_init_acl_access(struct inode *inode)
+{
+}
+
+static inline void reiserfs_init_acl_default(struct inode *inode)
+{
+}
 #endif
index 28493ffaafe7b26e1dfec49fab09333658702d3e..7bc6bfb86253899c9ad088ffa39e9f4c81c71147 100644 (file)
@@ -807,21 +807,19 @@ struct stat_data_v1 {
 #define set_sd_v1_first_direct_byte(sdp,v) \
                                 ((sdp)->sd_first_direct_byte = cpu_to_le32(v))
 
-#include <linux/ext2_fs.h>
-
 /* inode flags stored in sd_attrs (nee sd_reserved) */
 
 /* we want common flags to have the same values as in ext2,
    so chattr(1) will work without problems */
-#define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
-#define REISERFS_APPEND_FL    EXT2_APPEND_FL
-#define REISERFS_SYNC_FL      EXT2_SYNC_FL
-#define REISERFS_NOATIME_FL   EXT2_NOATIME_FL
-#define REISERFS_NODUMP_FL    EXT2_NODUMP_FL
-#define REISERFS_SECRM_FL     EXT2_SECRM_FL
-#define REISERFS_UNRM_FL      EXT2_UNRM_FL
-#define REISERFS_COMPR_FL     EXT2_COMPR_FL
-#define REISERFS_NOTAIL_FL    EXT2_NOTAIL_FL
+#define REISERFS_IMMUTABLE_FL FS_IMMUTABLE_FL
+#define REISERFS_APPEND_FL    FS_APPEND_FL
+#define REISERFS_SYNC_FL      FS_SYNC_FL
+#define REISERFS_NOATIME_FL   FS_NOATIME_FL
+#define REISERFS_NODUMP_FL    FS_NODUMP_FL
+#define REISERFS_SECRM_FL     FS_SECRM_FL
+#define REISERFS_UNRM_FL      FS_UNRM_FL
+#define REISERFS_COMPR_FL     FS_COMPR_FL
+#define REISERFS_NOTAIL_FL    FS_NOTAIL_FL
 
 /* persistent flags that file inherits from the parent directory */
 #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL |        \
@@ -2075,6 +2073,10 @@ void reiserfs_init_alloc_options(struct super_block *s);
  */
 __le32 reiserfs_choose_packing(struct inode *dir);
 
+int reiserfs_init_bitmap_cache(struct super_block *sb);
+void reiserfs_free_bitmap_cache(struct super_block *sb);
+void reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info);
+struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, unsigned int bitmap);
 int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value);
 void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *,
                         b_blocknr_t, int for_unformatted);
@@ -2163,15 +2165,24 @@ __u32 r5_hash(const signed char *msg, int len);
 /* prototypes from ioctl.c */
 int reiserfs_ioctl(struct inode *inode, struct file *filp,
                   unsigned int cmd, unsigned long arg);
+long reiserfs_compat_ioctl(struct file *filp,
+                  unsigned int cmd, unsigned long arg);
 
 /* ioctl's command */
 #define REISERFS_IOC_UNPACK            _IOW(0xCD,1,long)
 /* define following flags to be the same as in ext2, so that chattr(1),
    lsattr(1) will work with us. */
-#define REISERFS_IOC_GETFLAGS          EXT2_IOC_GETFLAGS
-#define REISERFS_IOC_SETFLAGS          EXT2_IOC_SETFLAGS
-#define REISERFS_IOC_GETVERSION                EXT2_IOC_GETVERSION
-#define REISERFS_IOC_SETVERSION                EXT2_IOC_SETVERSION
+#define REISERFS_IOC_GETFLAGS          FS_IOC_GETFLAGS
+#define REISERFS_IOC_SETFLAGS          FS_IOC_SETFLAGS
+#define REISERFS_IOC_GETVERSION                FS_IOC_GETVERSION
+#define REISERFS_IOC_SETVERSION                FS_IOC_SETVERSION
+
+/* the 32 bit compat definitions with int argument */
+#define REISERFS_IOC32_UNPACK          _IOW(0xCD, 1, int)
+#define REISERFS_IOC32_GETFLAGS                FS_IOC32_GETFLAGS
+#define REISERFS_IOC32_SETFLAGS                FS_IOC32_SETFLAGS
+#define REISERFS_IOC32_GETVERSION      FS_IOC32_GETVERSION
+#define REISERFS_IOC32_SETVERSION      FS_IOC32_SETVERSION
 
 /* Locking primitives */
 /* Right now we are still falling back to (un)lock_kernel, but eventually that
index 149be8d9a0c9fe200f59ff809e8005b3ecca3ebc..5b3b297aa2c5b647294e69ac0090cef6c0deeb16 100644 (file)
@@ -52,10 +52,13 @@ struct reiserfs_inode_info {
         ** flushed */
        unsigned long i_trans_id;
        struct reiserfs_journal_list *i_jl;
-
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
        struct posix_acl *i_acl_access;
        struct posix_acl *i_acl_default;
+#endif
+#ifdef CONFIG_REISERFS_FS_XATTR
        struct rw_semaphore xattr_sem;
+#endif
        struct inode vfs_inode;
 };
 
index 31b4c0bd4fa000e94a32f5b8b5f99c9211f68f4e..73e0becec0866d39664b79cae596b712e811b2fe 100644 (file)
@@ -267,7 +267,6 @@ struct reiserfs_bitmap_info {
        // FIXME: Won't work with block sizes > 8K
        __u16 first_zero_hint;
        __u16 free_count;
-       struct buffer_head *bh; /* the actual bitmap */
 };
 
 struct proc_dir_entry;
@@ -414,6 +413,7 @@ struct reiserfs_sb_info {
 /* Definitions of reiserfs on-disk properties: */
 #define REISERFS_3_5 0
 #define REISERFS_3_6 1
+#define REISERFS_OLD_FORMAT 2
 
 enum reiserfs_mount_options {
 /* Mount options */
index 5e961035c72576052cec535a48faf0814719f809..966c35851b2e784a445bac96e1458554ab8784de 100644 (file)
@@ -97,6 +97,11 @@ static inline void reiserfs_mark_inode_private(struct inode *inode)
        inode->i_flags |= S_PRIVATE;
 }
 
+static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
+{
+       init_rwsem(&REISERFS_I(inode)->xattr_sem);
+}
+
 #else
 
 #define is_reiserfs_priv_object(inode) 0
@@ -129,6 +134,9 @@ static inline int reiserfs_xattr_init(struct super_block *sb, int mount_flags)
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL);     /* to be sure */
        return 0;
 };
+static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
+{
+}
 #endif
 
 #endif                         /* __KERNEL__ */
index 5371e4e745958f37e67cba09db7eaa9e49a2ada0..b89f09357054ff13414eade0f14dc0748e98f925 100644 (file)
@@ -141,7 +141,7 @@ struct rtc_device
        int id;
        char name[RTC_DEVICE_NAME_SIZE];
 
-       struct rtc_class_ops *ops;
+       const struct rtc_class_ops *ops;
        struct mutex ops_lock;
 
        struct class_device *rtc_dev;
@@ -172,7 +172,7 @@ struct rtc_device
 
 extern struct rtc_device *rtc_device_register(const char *name,
                                        struct device *dev,
-                                       struct rtc_class_ops *ops,
+                                       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);
index 9c92dc8b9a082616c4bc6622e87ca0176a622b8e..3a18addaed4ccb7436bffc9cf5fd0666f145d35c 100644 (file)
@@ -2,7 +2,7 @@
 #define __LINUX_RTNETLINK_H
 
 #include <linux/netlink.h>
-#include <linux/if.h>
+#include <linux/if_link.h>
 
 /****
  *             Routing/neighbour discovery messages.
index 9d4aa7f95bc8a9172b021f5d1c5137290f51c336..7ef899c47c29296b14f28030cab737fc6dc30700 100644 (file)
@@ -148,6 +148,7 @@ extern unsigned long weighted_cpuload(const int cpu);
 #define EXIT_DEAD              32
 /* in tsk->state again */
 #define TASK_NONINTERACTIVE    64
+#define TASK_DEAD              128
 
 #define __set_task_state(tsk, state_value)             \
        do { (tsk)->state = (state_value); } while (0)
@@ -504,8 +505,8 @@ struct signal_struct {
 #define rt_prio(prio)          unlikely((prio) < MAX_RT_PRIO)
 #define rt_task(p)             rt_prio((p)->prio)
 #define batch_task(p)          (unlikely((p)->policy == SCHED_BATCH))
-#define has_rt_policy(p) \
-       unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH)
+#define is_rt_policy(p)                ((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
+#define has_rt_policy(p)       unlikely(is_rt_policy((p)->policy))
 
 /*
  * Some day this will be a full-fledged user tracking system..
@@ -709,7 +710,6 @@ extern unsigned int max_cache_size;
 
 
 struct io_context;                     /* See blkdev.h */
-void exit_io_context(void);
 struct cpuset;
 
 #define NGROUPS_SMALL          32
@@ -784,8 +784,9 @@ struct task_struct {
        struct prio_array *array;
 
        unsigned short ioprio;
+#ifdef CONFIG_BLK_DEV_IO_TRACE
        unsigned int btrace_seq;
-
+#endif
        unsigned long sleep_avg;
        unsigned long long timestamp, last_ran;
        unsigned long long sched_time; /* sched_clock time spent running */
@@ -886,8 +887,10 @@ struct task_struct {
                                     - initialized normally by flush_old_exec */
 /* file system info */
        int link_count, total_link_count;
+#ifdef CONFIG_SYSVIPC
 /* ipc stuff */
        struct sysv_sem sysvsem;
+#endif
 /* CPU-specific state of this task */
        struct thread_struct thread;
 /* filesystem information */
@@ -978,10 +981,10 @@ struct task_struct {
        wait_queue_t *io_wait;
 /* i/o counters(bytes read/written, #syscalls */
        u64 rchar, wchar, syscr, syscw;
-#if defined(CONFIG_BSD_PROCESS_ACCT)
+#if defined(CONFIG_TASK_XACCT)
        u64 acct_rss_mem1;      /* accumulated rss usage */
        u64 acct_vm_mem1;       /* accumulated virtual memory usage */
-       clock_t acct_stimexpd;  /* clock_t-converted stime since last update */
+       cputime_t acct_stimexpd;/* stime since last update */
 #endif
 #ifdef CONFIG_NUMA
        struct mempolicy *mempolicy;
@@ -1030,6 +1033,16 @@ static inline int pid_alive(struct task_struct *p)
        return p->pids[PIDTYPE_PID].pid != NULL;
 }
 
+/**
+ * is_init - check if a task structure is the first user space
+ *          task the kernel created.
+ * @p: Task structure to be checked.
+ */
+static inline int is_init(struct task_struct *tsk)
+{
+       return tsk->pid == 1;
+}
+
 extern void free_task(struct task_struct *tsk);
 #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 
@@ -1048,7 +1061,6 @@ static inline void put_task_struct(struct task_struct *t)
                                        /* Not implemented yet, only for 486*/
 #define PF_STARTING    0x00000002      /* being created */
 #define PF_EXITING     0x00000004      /* getting shut down */
-#define PF_DEAD                0x00000008      /* Dead */
 #define PF_FORKNOEXEC  0x00000040      /* forked but didn't exec */
 #define PF_SUPERPRIV   0x00000100      /* used super-user privileges */
 #define PF_DUMPCORE    0x00000200      /* dumped core */
@@ -1193,7 +1205,7 @@ extern void switch_uid(struct user_struct *);
 
 #include <asm/current.h>
 
-extern void do_timer(struct pt_regs *);
+extern void do_timer(unsigned long ticks);
 
 extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state));
 extern int FASTCALL(wake_up_process(struct task_struct * tsk));
index 90dd069cc145c4b26a6fefe020aacee17d28aa65..1a82d30c4b17eea493a8f1ff3fd6c293d48dc434 100644 (file)
@@ -4,6 +4,7 @@ u32 scx200_gpio_configure(unsigned index, u32 set, u32 clear);
 
 extern unsigned scx200_gpio_base;
 extern long scx200_gpio_shadow[2];
+extern struct nsc_gpio_ops scx200_gpio_ops;
 
 #define scx200_gpio_present() (scx200_gpio_base!=0)
 
index 9f56fb8a4a6c358091915aa34e5fae8c045a585d..9b5fea81f55e4e96dfdca7fb83a3ecd0834c2137 100644 (file)
@@ -1595,6 +1595,7 @@ static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
 
 static inline int security_inode_alloc (struct inode *inode)
 {
+       inode->i_security = NULL;
        return security_ops->inode_alloc_security (inode);
 }
 
index c057f0b32318bdc40ea879086805e174db29c035..f3c51899117f5e83abb3a44c5b94ff11574df382 100644 (file)
@@ -19,6 +19,10 @@ struct shmem_inode_info {
        swp_entry_t             i_direct[SHMEM_NR_DIRECT]; /* first blocks */
        struct list_head        swaplist;       /* chain of maybes on swap */
        struct inode            vfs_inode;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+       struct posix_acl        *i_acl;
+       struct posix_acl        *i_default_acl;
+#endif
 };
 
 struct shmem_sb_info {
@@ -36,4 +40,24 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
        return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+#ifdef CONFIG_TMPFS_POSIX_ACL
+int shmem_permission(struct inode *, int, struct nameidata *);
+int shmem_acl_init(struct inode *, struct inode *);
+void shmem_acl_destroy_inode(struct inode *);
+
+extern struct xattr_handler shmem_xattr_acl_access_handler;
+extern struct xattr_handler shmem_xattr_acl_default_handler;
+
+extern struct generic_acl_operations shmem_acl_ops;
+
+#else
+static inline int shmem_acl_init(struct inode *inode, struct inode *dir)
+{
+       return 0;
+}
+static inline void shmem_acl_destroy_inode(struct inode *inode)
+{
+}
+#endif  /* CONFIG_TMPFS_POSIX_ACL */
+
 #endif
index 66d6eb78d1c64e1f59691e37ae561f4c670d969b..a96fd9310d55a7dc89176db3cdb4bc7c1ba26950 100644 (file)
@@ -60,7 +60,7 @@ extern void __init kmem_cache_init(void);
 extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
                                       void (*)(void *, kmem_cache_t *, unsigned long),
                                       void (*)(void *, kmem_cache_t *, unsigned long));
-extern int kmem_cache_destroy(kmem_cache_t *);
+extern void kmem_cache_destroy(kmem_cache_t *);
 extern int kmem_cache_shrink(kmem_cache_t *);
 extern void *kmem_cache_alloc(kmem_cache_t *, gfp_t);
 extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
@@ -249,7 +249,7 @@ struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
        unsigned long,
        void (*)(void *, struct kmem_cache *, unsigned long),
        void (*)(void *, struct kmem_cache *, unsigned long));
-int kmem_cache_destroy(struct kmem_cache *c);
+void kmem_cache_destroy(struct kmem_cache *c);
 void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
 void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
 void kmem_cache_free(struct kmem_cache *c, void *b);
index 6df3b1501559aadda5c5c926bc836431a1e0565a..f098dff93f6bc26cd732d15b75a9ff69d894d42e 100644 (file)
@@ -89,7 +89,6 @@ struct smb_fattr {
        struct timespec f_atime;
        struct timespec f_mtime;
        struct timespec f_ctime;
-       unsigned long   f_blksize;
        unsigned long   f_blocks;
        int             f_unix;
 };
index 31473db92d3b68f81663687a55ef9521a19ccdc8..b800d2d68b325d139af36320db55e7d9db1d26f1 100644 (file)
@@ -167,9 +167,9 @@ do {                                                                \
  * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
  * methods are defined as nops in the case they are not required.
  */
-#define spin_trylock(lock)             __cond_lock(_spin_trylock(lock))
-#define read_trylock(lock)             __cond_lock(_read_trylock(lock))
-#define write_trylock(lock)            __cond_lock(_write_trylock(lock))
+#define spin_trylock(lock)             __cond_lock(lock, _spin_trylock(lock))
+#define read_trylock(lock)             __cond_lock(lock, _read_trylock(lock))
+#define write_trylock(lock)            __cond_lock(lock, _write_trylock(lock))
 
 #define spin_lock(lock)                        _spin_lock(lock)
 
@@ -236,19 +236,19 @@ do {                                                              \
                                        _write_unlock_irqrestore(lock, flags)
 #define write_unlock_bh(lock)          _write_unlock_bh(lock)
 
-#define spin_trylock_bh(lock)          __cond_lock(_spin_trylock_bh(lock))
+#define spin_trylock_bh(lock)  __cond_lock(lock, _spin_trylock_bh(lock))
 
 #define spin_trylock_irq(lock) \
 ({ \
        local_irq_disable(); \
-       _spin_trylock(lock) ? \
+       spin_trylock(lock) ? \
        1 : ({ local_irq_enable(); 0;  }); \
 })
 
 #define spin_trylock_irqsave(lock, flags) \
 ({ \
        local_irq_save(flags); \
-       _spin_trylock(lock) ? \
+       spin_trylock(lock) ? \
        1 : ({ local_irq_restore(flags); 0; }); \
 })
 
@@ -264,7 +264,7 @@ do {                                                                \
  */
 extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
 #define atomic_dec_and_lock(atomic, lock) \
-               __cond_lock(_atomic_dec_and_lock(atomic, lock))
+               __cond_lock(lock, _atomic_dec_and_lock(atomic, lock))
 
 /**
  * spin_can_lock - would spin_trylock() succeed?
index b2c4f8299464e86558b2721823bd0723da5f1ea3..8828b8155e9c11db7abb99c8342b7ee66d8e6839 100644 (file)
@@ -19,41 +19,41 @@ int in_lock_functions(unsigned long addr);
 
 #define assert_spin_locked(x)  BUG_ON(!spin_is_locked(x))
 
-void __lockfunc _spin_lock(spinlock_t *lock)           __acquires(spinlock_t);
+void __lockfunc _spin_lock(spinlock_t *lock)           __acquires(lock);
 void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass)
-                                                       __acquires(spinlock_t);
-void __lockfunc _read_lock(rwlock_t *lock)             __acquires(rwlock_t);
-void __lockfunc _write_lock(rwlock_t *lock)            __acquires(rwlock_t);
-void __lockfunc _spin_lock_bh(spinlock_t *lock)                __acquires(spinlock_t);
-void __lockfunc _read_lock_bh(rwlock_t *lock)          __acquires(rwlock_t);
-void __lockfunc _write_lock_bh(rwlock_t *lock)         __acquires(rwlock_t);
-void __lockfunc _spin_lock_irq(spinlock_t *lock)       __acquires(spinlock_t);
-void __lockfunc _read_lock_irq(rwlock_t *lock)         __acquires(rwlock_t);
-void __lockfunc _write_lock_irq(rwlock_t *lock)                __acquires(rwlock_t);
+                                                       __acquires(lock);
+void __lockfunc _read_lock(rwlock_t *lock)             __acquires(lock);
+void __lockfunc _write_lock(rwlock_t *lock)            __acquires(lock);
+void __lockfunc _spin_lock_bh(spinlock_t *lock)                __acquires(lock);
+void __lockfunc _read_lock_bh(rwlock_t *lock)          __acquires(lock);
+void __lockfunc _write_lock_bh(rwlock_t *lock)         __acquires(lock);
+void __lockfunc _spin_lock_irq(spinlock_t *lock)       __acquires(lock);
+void __lockfunc _read_lock_irq(rwlock_t *lock)         __acquires(lock);
+void __lockfunc _write_lock_irq(rwlock_t *lock)                __acquires(lock);
 unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
-                                                       __acquires(spinlock_t);
+                                                       __acquires(lock);
 unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
-                                                       __acquires(rwlock_t);
+                                                       __acquires(lock);
 unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
-                                                       __acquires(rwlock_t);
+                                                       __acquires(lock);
 int __lockfunc _spin_trylock(spinlock_t *lock);
 int __lockfunc _read_trylock(rwlock_t *lock);
 int __lockfunc _write_trylock(rwlock_t *lock);
 int __lockfunc _spin_trylock_bh(spinlock_t *lock);
-void __lockfunc _spin_unlock(spinlock_t *lock)         __releases(spinlock_t);
-void __lockfunc _read_unlock(rwlock_t *lock)           __releases(rwlock_t);
-void __lockfunc _write_unlock(rwlock_t *lock)          __releases(rwlock_t);
-void __lockfunc _spin_unlock_bh(spinlock_t *lock)      __releases(spinlock_t);
-void __lockfunc _read_unlock_bh(rwlock_t *lock)                __releases(rwlock_t);
-void __lockfunc _write_unlock_bh(rwlock_t *lock)       __releases(rwlock_t);
-void __lockfunc _spin_unlock_irq(spinlock_t *lock)     __releases(spinlock_t);
-void __lockfunc _read_unlock_irq(rwlock_t *lock)       __releases(rwlock_t);
-void __lockfunc _write_unlock_irq(rwlock_t *lock)      __releases(rwlock_t);
+void __lockfunc _spin_unlock(spinlock_t *lock)         __releases(lock);
+void __lockfunc _read_unlock(rwlock_t *lock)           __releases(lock);
+void __lockfunc _write_unlock(rwlock_t *lock)          __releases(lock);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock)      __releases(lock);
+void __lockfunc _read_unlock_bh(rwlock_t *lock)                __releases(lock);
+void __lockfunc _write_unlock_bh(rwlock_t *lock)       __releases(lock);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock)     __releases(lock);
+void __lockfunc _read_unlock_irq(rwlock_t *lock)       __releases(lock);
+void __lockfunc _write_unlock_irq(rwlock_t *lock)      __releases(lock);
 void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
-                                                       __releases(spinlock_t);
+                                                       __releases(lock);
 void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
-                                                       __releases(rwlock_t);
+                                                       __releases(lock);
 void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
-                                                       __releases(rwlock_t);
+                                                       __releases(lock);
 
 #endif /* __LINUX_SPINLOCK_API_SMP_H */
index ea65dfb60cd80e19d2a5a1ce9a5f00194017e4c0..6a40c76bdcf1a7732d71675d888e722aa0dc578c 100644 (file)
 #endif
 
 #ifdef __KERNEL__
+
+enum {
+       false   = 0,
+       true    = 1
+};
+
 #undef offsetof
 #ifdef __compiler_offsetof
 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
index e4c7558603167bfffd23cc6966c0d88cb7b45b04..4f69ef9e6eb5098ddafc6ccee368c08af2efd98f 100644 (file)
@@ -99,6 +99,7 @@ extern void * memchr(const void *,int,__kernel_size_t);
 #endif
 
 extern char *kstrdup(const char *s, gfp_t gfp);
+extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
 
 #ifdef __cplusplus
 }
index a6de332e57d456a6243cc4496aa1b3ddf8491d96..862c0d8c83817ce2288dd5cd79f5d46ed7557654 100644 (file)
@@ -109,13 +109,13 @@ struct rpc_credops {
        void                    (*crdestroy)(struct rpc_cred *);
 
        int                     (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
-       u32 *                   (*crmarshal)(struct rpc_task *, u32 *);
+       __be32 *                (*crmarshal)(struct rpc_task *, __be32 *);
        int                     (*crrefresh)(struct rpc_task *);
-       u32 *                   (*crvalidate)(struct rpc_task *, u32 *);
+       __be32 *                (*crvalidate)(struct rpc_task *, __be32 *);
        int                     (*crwrap_req)(struct rpc_task *, kxdrproc_t,
-                                               void *, u32 *, void *);
+                                               void *, __be32 *, void *);
        int                     (*crunwrap_resp)(struct rpc_task *, kxdrproc_t,
-                                               void *, u32 *, void *);
+                                               void *, __be32 *, void *);
 };
 
 extern struct rpc_authops      authunix_ops;
@@ -134,10 +134,10 @@ struct rpc_cred * rpcauth_bindcred(struct rpc_task *);
 void                   rpcauth_holdcred(struct rpc_task *);
 void                   put_rpccred(struct rpc_cred *);
 void                   rpcauth_unbindcred(struct rpc_task *);
-u32 *                  rpcauth_marshcred(struct rpc_task *, u32 *);
-u32 *                  rpcauth_checkverf(struct rpc_task *, u32 *);
-int                    rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, u32 *data, void *obj);
-int                    rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, u32 *data, void *obj);
+__be32 *               rpcauth_marshcred(struct rpc_task *, __be32 *);
+__be32 *               rpcauth_checkverf(struct rpc_task *, __be32 *);
+int                    rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, __be32 *data, void *obj);
+int                    rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, __be32 *data, void *obj);
 int                    rpcauth_refreshcred(struct rpc_task *);
 void                   rpcauth_invalcred(struct rpc_task *);
 int                    rpcauth_uptodatecred(struct rpc_task *);
index f43f237360ae62099997c803b440e2efece721b5..d9f5934ac9fedbbe789fe0da125ac89b979c13b7 100644 (file)
@@ -95,7 +95,7 @@ enum rpc_auth_stat {
  * 2GB.
  */
 
-typedef u32    rpc_fraghdr;
+typedef __be32 rpc_fraghdr;
 
 #define        RPC_LAST_STREAM_FRAGMENT        (1U << 31)
 #define        RPC_FRAGMENT_SIZE_MASK          (~RPC_LAST_STREAM_FRAGMENT)
index 7b27c09b56046e19bef6e499922f628bec5c0a6e..73140ee5c638ab631916ecf6fb697da58384693d 100644 (file)
@@ -78,28 +78,45 @@ struct svc_serv {
  */
 #define RPCSVC_MAXPAGES                ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2)
 
-static inline u32 svc_getu32(struct kvec *iov)
+static inline u32 svc_getnl(struct kvec *iov)
 {
-       u32 val, *vp;
+       __be32 val, *vp;
        vp = iov->iov_base;
        val = *vp++;
        iov->iov_base = (void*)vp;
-       iov->iov_len -= sizeof(u32);
+       iov->iov_len -= sizeof(__be32);
+       return ntohl(val);
+}
+
+static inline void svc_putnl(struct kvec *iov, u32 val)
+{
+       __be32 *vp = iov->iov_base + iov->iov_len;
+       *vp = htonl(val);
+       iov->iov_len += sizeof(__be32);
+}
+
+static inline __be32 svc_getu32(struct kvec *iov)
+{
+       __be32 val, *vp;
+       vp = iov->iov_base;
+       val = *vp++;
+       iov->iov_base = (void*)vp;
+       iov->iov_len -= sizeof(__be32);
        return val;
 }
 
 static inline void svc_ungetu32(struct kvec *iov)
 {
-       u32 *vp = (u32 *)iov->iov_base;
+       __be32 *vp = (__be32 *)iov->iov_base;
        iov->iov_base = (void *)(vp - 1);
        iov->iov_len += sizeof(*vp);
 }
 
-static inline void svc_putu32(struct kvec *iov, u32 val)
+static inline void svc_putu32(struct kvec *iov, __be32 val)
 {
-       u32 *vp = iov->iov_base + iov->iov_len;
+       __be32 *vp = iov->iov_base + iov->iov_len;
        *vp = val;
-       iov->iov_len += sizeof(u32);
+       iov->iov_len += sizeof(__be32);
 }
 
        
@@ -130,7 +147,7 @@ struct svc_rqst {
        short                   rq_arghi;       /* pages available in argument page list */
        short                   rq_resused;     /* pages used for result */
 
-       u32                     rq_xid;         /* transmission id */
+       __be32                  rq_xid;         /* transmission id */
        u32                     rq_prog;        /* program number */
        u32                     rq_vers;        /* program version */
        u32                     rq_proc;        /* procedure number */
@@ -139,7 +156,7 @@ struct svc_rqst {
                                rq_secure  : 1; /* secure port */
 
 
-       __u32                   rq_daddr;       /* dest addr of request - reply from here */
+       __be32                  rq_daddr;       /* dest addr of request - reply from here */
 
        void *                  rq_argp;        /* decoded arguments */
        void *                  rq_resp;        /* xdr'd results */
@@ -169,7 +186,7 @@ struct svc_rqst {
  * Check buffer bounds after decoding arguments
  */
 static inline int
-xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
+xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p)
 {
        char *cp = (char *)p;
        struct kvec *vec = &rqstp->rq_arg.head[0];
@@ -178,7 +195,7 @@ xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
 }
 
 static inline int
-xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
+xdr_ressize_check(struct svc_rqst *rqstp, __be32 *p)
 {
        struct kvec *vec = &rqstp->rq_res.head[0];
        char *cp = (char*)p;
@@ -249,10 +266,10 @@ struct svc_deferred_req {
        u32                     prot;   /* protocol (UDP or TCP) */
        struct sockaddr_in      addr;
        struct svc_sock         *svsk;  /* where reply must go */
-       u32                     daddr;  /* where reply must come from */
+       __be32                  daddr;  /* where reply must come from */
        struct cache_deferred_req handle;
        int                     argslen;
-       u32                     args[0];
+       __be32                  args[0];
 };
 
 /*
@@ -284,7 +301,7 @@ struct svc_version {
         * A return value of 0 means drop the request. 
         * vs_dispatch == NULL means use default dispatcher.
         */
-       int                     (*vs_dispatch)(struct svc_rqst *, u32 *);
+       int                     (*vs_dispatch)(struct svc_rqst *, __be32 *);
 };
 
 /*
index 2fe2087edd665130d75dac0836c5763e853bccf6..a6601650deeb4ef4131a319e4757bcadb313e0b1 100644 (file)
@@ -95,7 +95,7 @@ struct auth_ops {
        char *  name;
        struct module *owner;
        int     flavour;
-       int     (*accept)(struct svc_rqst *rq, u32 *authp);
+       int     (*accept)(struct svc_rqst *rq, __be32 *authp);
        int     (*release)(struct svc_rqst *rq);
        void    (*domain_release)(struct auth_domain *);
        int     (*set_client)(struct svc_rqst *rq);
@@ -112,7 +112,7 @@ struct auth_ops {
 #define        SVC_COMPLETE    9
 
 
-extern int     svc_authenticate(struct svc_rqst *rqstp, u32 *authp);
+extern int     svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
 extern int     svc_authorise(struct svc_rqst *rqstp);
 extern int     svc_set_client(struct svc_rqst *rqstp);
 extern int     svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
index e6d3d349506c6409f0a65e38a89c01723ee1c3ff..953723b09bc6d73cd5ad97bd0143bdf1fbd162f9 100644 (file)
@@ -32,7 +32,7 @@ struct xdr_netobj {
  * side) or svc_rqst pointer (server side).
  * Encode functions always assume there's enough room in the buffer.
  */
-typedef int    (*kxdrproc_t)(void *rqstp, u32 *data, void *obj);
+typedef int    (*kxdrproc_t)(void *rqstp, __be32 *data, void *obj);
 
 /*
  * Basic structure for transmission/reception of a client XDR message.
@@ -88,19 +88,19 @@ struct xdr_buf {
 /*
  * Miscellaneous XDR helper functions
  */
-u32 *  xdr_encode_opaque_fixed(u32 *p, const void *ptr, unsigned int len);
-u32 *  xdr_encode_opaque(u32 *p, const void *ptr, unsigned int len);
-u32 *  xdr_encode_string(u32 *p, const char *s);
-u32 *  xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen);
-u32 *  xdr_encode_netobj(u32 *p, const struct xdr_netobj *);
-u32 *  xdr_decode_netobj(u32 *p, struct xdr_netobj *);
+__be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len);
+__be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len);
+__be32 *xdr_encode_string(__be32 *p, const char *s);
+__be32 *xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen);
+__be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *);
+__be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
 
 void   xdr_encode_pages(struct xdr_buf *, struct page **, unsigned int,
                         unsigned int);
 void   xdr_inline_pages(struct xdr_buf *, unsigned int,
                         struct page **, unsigned int, unsigned int);
 
-static inline u32 *xdr_encode_array(u32 *p, const void *s, unsigned int len)
+static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
 {
        return xdr_encode_opaque(p, s, len);
 }
@@ -108,16 +108,16 @@ static inline u32 *xdr_encode_array(u32 *p, const void *s, unsigned int len)
 /*
  * Decode 64bit quantities (NFSv3 support)
  */
-static inline u32 *
-xdr_encode_hyper(u32 *p, __u64 val)
+static inline __be32 *
+xdr_encode_hyper(__be32 *p, __u64 val)
 {
        *p++ = htonl(val >> 32);
        *p++ = htonl(val & 0xFFFFFFFF);
        return p;
 }
 
-static inline u32 *
-xdr_decode_hyper(u32 *p, __u64 *valp)
+static inline __be32 *
+xdr_decode_hyper(__be32 *p, __u64 *valp)
 {
        *valp  = ((__u64) ntohl(*p++)) << 32;
        *valp |= ntohl(*p++);
@@ -128,7 +128,7 @@ xdr_decode_hyper(u32 *p, __u64 *valp)
  * Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
  */
 static inline int
-xdr_adjust_iovec(struct kvec *iov, u32 *p)
+xdr_adjust_iovec(struct kvec *iov, __be32 *p)
 {
        return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base);
 }
@@ -180,19 +180,19 @@ extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
  * Provide some simple tools for XDR buffer overflow-checking etc.
  */
 struct xdr_stream {
-       uint32_t *p;            /* start of available buffer */
+       __be32 *p;              /* start of available buffer */
        struct xdr_buf *buf;    /* XDR buffer to read/write */
 
-       uint32_t *end;          /* end of available buffer space */
+       __be32 *end;            /* end of available buffer space */
        struct kvec *iov;       /* pointer to the current kvec */
 };
 
-extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p);
-extern uint32_t *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
+extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
                unsigned int base, unsigned int len);
-extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p);
-extern uint32_t *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
+extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
 
index bdeba8538c719892407c0f112e809bb166cc179c..6cf6265807529842e10b3b0553bb8d401d17e84a 100644 (file)
@@ -79,7 +79,7 @@ struct rpc_rqst {
         * This is the private part
         */
        struct rpc_task *       rq_task;        /* RPC task data */
-       __u32                   rq_xid;         /* request XID */
+       __be32                  rq_xid;         /* request XID */
        int                     rq_cong;        /* has incremented xprt->cong */
        int                     rq_received;    /* receive completed */
        u32                     rq_seqno;       /* gss seq no. used on req. */
@@ -171,9 +171,9 @@ struct rpc_xprt {
        /*
         * State of TCP reply receive stuff
         */
-       u32                     tcp_recm,       /* Fragment header */
-                               tcp_xid,        /* Current XID */
-                               tcp_reclen,     /* fragment length */
+       __be32                  tcp_recm,       /* Fragment header */
+                               tcp_xid;        /* Current XID */
+       u32                     tcp_reclen,     /* fragment length */
                                tcp_offset;     /* fragment offset */
        unsigned long           tcp_copied,     /* copied to request */
                                tcp_flags;
@@ -253,7 +253,7 @@ void                        xprt_release(struct rpc_task *task);
 struct rpc_xprt *      xprt_get(struct rpc_xprt *xprt);
 void                   xprt_put(struct rpc_xprt *xprt);
 
-static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
+static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
 {
        return p + xprt->tsh_size;
 }
@@ -268,7 +268,7 @@ void                        xprt_wait_for_buffer_space(struct rpc_task *task);
 void                   xprt_write_space(struct rpc_xprt *xprt);
 void                   xprt_update_rtt(struct rpc_task *task);
 void                   xprt_adjust_cwnd(struct rpc_task *task, int result);
-struct rpc_rqst *      xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
+struct rpc_rqst *      xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid);
 void                   xprt_complete_rqst(struct rpc_task *task, int copied);
 void                   xprt_release_rqst_cong(struct rpc_task *task);
 void                   xprt_disconnect(struct rpc_xprt *xprt);
index 0577f5284cbc9c4f73beb031d9c53834456f354c..c8b042667af1fb70e1326bbec1c0b7b8474017f5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SyncLink Multiprotocol Serial Adapter Driver
  *
- * $Id: synclink.h,v 3.13 2006/05/23 18:25:06 paulkf Exp $
+ * $Id: synclink.h,v 3.14 2006/07/17 20:15:43 paulkf Exp $
  *
  * Copyright (C) 1998-2000 by Microgate Corporation
  *
 
 #define MGSL_MODE_ASYNC                1
 #define MGSL_MODE_HDLC         2
+#define MGSL_MODE_MONOSYNC     3
+#define MGSL_MODE_BISYNC       4
 #define MGSL_MODE_RAW          6
 
 #define MGSL_BUS_TYPE_ISA      1
index 3f0f716225ecd714d1c21fac4076e6ef6fbbce12..2d1c3d5c83acc150d9838c881d4d22d79509fc4b 100644 (file)
@@ -597,6 +597,6 @@ asmlinkage long sys_get_robust_list(int pid,
                                    size_t __user *len_ptr);
 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
                                    size_t len);
-asmlinkage long sys_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache);
+asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
 
 #endif
index 4812ff60561cb44cf66625691059dee49fce6347..e657e523b9bf62b7a6f0d51850e3b9d3292c64fc 100644 (file)
@@ -11,6 +11,8 @@
  *     based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
 
+#ifndef _LINUX_SYSRQ_H
+#define _LINUX_SYSRQ_H
 
 struct pt_regs;
 struct tty_struct;
@@ -57,3 +59,5 @@ static inline int __reterr(void)
 #define unregister_sysrq_key(ig,nore) __reterr()
 
 #endif
+
+#endif /* _LINUX_SYSRQ_H */
index f1cb6cddd19d70959c966e0faaca16de4dcac457..45248806ae9c5916a416102d9bd1a8c9b54a03a2 100644 (file)
@@ -2,6 +2,7 @@
  *
  * Copyright (C) Shailabh Nagar, IBM Corp. 2006
  *           (C) Balbir Singh,   IBM Corp. 2006
+ *           (C) Jay Lan,        SGI, 2006
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2.1 of the GNU Lesser General Public License
  *     c) add new fields after version comment; maintain 64-bit alignment
  */
 
-#define TASKSTATS_VERSION      1
+
+#define TASKSTATS_VERSION      2
+#define TS_COMM_LEN            32      /* should be >= TASK_COMM_LEN
+                                        * in linux/sched.h */
 
 struct taskstats {
 
-       /* Version 1 */
+       /* The version number of this struct. This field is always set to
+        * TAKSTATS_VERSION, which is defined in <linux/taskstats.h>.
+        * Each time the struct is changed, the value should be incremented.
+        */
        __u16   version;
-       __u16   padding[3];     /* Userspace should not interpret the padding
-                                * field which can be replaced by useful
-                                * fields if struct taskstats is extended.
-                                */
+       __u32   ac_exitcode;            /* Exit status */
+
+       /* The accounting flags of a task as defined in <linux/acct.h>
+        * Defined values are AFORK, ASU, ACOMPAT, ACORE, and AXSIG.
+        */
+       __u8    ac_flag;                /* Record flags */
+       __u8    ac_nice;                /* task_nice */
 
        /* Delay accounting fields start
         *
@@ -88,6 +98,48 @@ struct taskstats {
        __u64   cpu_run_virtual_total;
        /* Delay accounting fields end */
        /* version 1 ends here */
+
+       /* Basic Accounting Fields start */
+       char    ac_comm[TS_COMM_LEN];   /* Command name */
+       __u8    ac_sched;               /* Scheduling discipline */
+       __u8    ac_pad[3];
+       __u32   ac_uid;                 /* User ID */
+       __u32   ac_gid;                 /* Group ID */
+       __u32   ac_pid;                 /* Process ID */
+       __u32   ac_ppid;                /* Parent process ID */
+       __u32   ac_btime;               /* Begin time [sec since 1970] */
+       __u64   ac_etime;               /* Elapsed time [usec] */
+       __u64   ac_utime;               /* User CPU time [usec] */
+       __u64   ac_stime;               /* SYstem CPU time [usec] */
+       __u64   ac_minflt;              /* Minor Page Fault Count */
+       __u64   ac_majflt;              /* Major Page Fault Count */
+       /* Basic Accounting Fields end */
+
+       /* Extended accounting fields start */
+       /* Accumulated RSS usage in duration of a task, in MBytes-usecs.
+        * The current rss usage is added to this counter every time
+        * a tick is charged to a task's system time. So, at the end we
+        * will have memory usage multiplied by system time. Thus an
+        * average usage per system time unit can be calculated.
+        */
+       __u64   coremem;                /* accumulated RSS usage in MB-usec */
+       /* Accumulated virtual memory usage in duration of a task.
+        * Same as acct_rss_mem1 above except that we keep track of VM usage.
+        */
+       __u64   virtmem;                /* accumulated VM  usage in MB-usec */
+
+       /* High watermark of RSS and virtual memory usage in duration of
+        * a task, in KBytes.
+        */
+       __u64   hiwater_rss;            /* High-watermark of RSS usage, in KB */
+       __u64   hiwater_vm;             /* High-water VM usage, in KB */
+
+       /* The following four fields are I/O statistics of a task. */
+       __u64   read_char;              /* bytes read */
+       __u64   write_char;             /* bytes written */
+       __u64   read_syscalls;          /* read syscalls */
+       __u64   write_syscalls;         /* write syscalls */
+       /* Extended accounting fields end */
 };
 
 
index 8ebf497907f8ec8cb8e014b8ff2f5f840261a3f5..0e058a2d1c6d72a62ddcef1e733830bff6323269 100644 (file)
 #include <asm/byteorder.h>
 
 struct tcphdr {
-       __u16   source;
-       __u16   dest;
-       __u32   seq;
-       __u32   ack_seq;
+       __be16  source;
+       __be16  dest;
+       __be32  seq;
+       __be32  ack_seq;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        __u16   res1:4,
                doff:4,
@@ -50,9 +50,9 @@ struct tcphdr {
 #else
 #error "Adjust your <asm/byteorder.h> defines"
 #endif 
-       __u16   window;
-       __u16   check;
-       __u16   urg_ptr;
+       __be16  window;
+       __be16  check;
+       __be16  urg_ptr;
 };
 
 /*
@@ -62,7 +62,7 @@ struct tcphdr {
  */
 union tcp_word_hdr { 
        struct tcphdr hdr;
-       __u32             words[5];
+       __be32            words[5];
 }; 
 
 #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
@@ -166,6 +166,11 @@ struct tcp_info
 #include <net/inet_timewait_sock.h>
 
 /* This defines a selective acknowledgement block. */
+struct tcp_sack_block_wire {
+       __be32  start_seq;
+       __be32  end_seq;
+};
+
 struct tcp_sack_block {
        __u32   start_seq;
        __u32   end_seq;
@@ -211,7 +216,7 @@ struct tcp_sock {
  *     Header prediction flags
  *     0x5?10 << 16 + snd_wnd in net byte order
  */
-       __u32   pred_flags;
+       __be32  pred_flags;
 
 /*
  *     RFC793 variables by their proper names. This means you can
index d543d3871e3867d91ff7b5b93497927a00071332..049dfe4a11f2a520399314b50bf3664044b01c46 100644 (file)
  * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
  * respectively.
  */
-#define SHIFT_KG 6             /* phase factor (shift) */
-#define SHIFT_KF 16            /* PLL frequency factor (shift) */
-#define SHIFT_KH 2             /* FLL frequency factor (shift) */
-#define MAXTC 6                        /* maximum time constant (shift) */
+#define SHIFT_PLL      4       /* PLL frequency factor (shift) */
+#define SHIFT_FLL      2       /* FLL frequency factor (shift) */
+#define MAXTC          10      /* maximum time constant (shift) */
 
 /*
- * The SHIFT_SCALE define establishes the decimal point of the time_phase
- * variable which serves as an extension to the low-order bits of the
- * system clock variable. The SHIFT_UPDATE define establishes the decimal
- * point of the time_offset variable which represents the current offset
- * with respect to standard time. The FINENSEC define represents 1 nsec in
- * scaled units.
+ * The SHIFT_UPDATE define establishes the decimal point of the
+ * time_offset variable which represents the current offset with
+ * respect to standard time.
  *
  * SHIFT_USEC defines the scaling (shift) of the time_freq and
  * time_tolerance variables, which represent the current frequency
  * offset and maximum frequency tolerance.
- *
- * FINENSEC is 1 ns in SHIFT_UPDATE units of the time_phase variable.
  */
-#define SHIFT_SCALE 22         /* phase scale (shift) */
-#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */
+#define SHIFT_UPDATE (SHIFT_HZ + 1) /* time offset scale (shift) */
 #define SHIFT_USEC 16          /* frequency offset scale (shift) */
-#define FINENSEC (1L << (SHIFT_SCALE - 10)) /* ~1 ns in phase units */
+#define SHIFT_NSEC 12          /* kernel frequency offset scale */
 
 #define MAXPHASE 512000L        /* max phase error (us) */
 #define MAXFREQ (512L << SHIFT_USEC)  /* max frequency error (ppm) */
-#define MINSEC 16L              /* min interval between updates (s) */
-#define MAXSEC 1200L            /* max interval between updates (s) */
+#define MAXFREQ_NSEC (512000L << SHIFT_NSEC) /* max frequency error (ppb) */
+#define MINSEC 256             /* min interval between updates (s) */
+#define MAXSEC 2048            /* max interval between updates (s) */
 #define        NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */
 
 /*
@@ -204,33 +198,15 @@ extern int tickadj;                       /* amount of adjustment per tick */
 /*
  * phase-lock loop variables
  */
-extern int time_state;         /* clock status */
 extern int time_status;                /* clock synchronization status bits */
-extern long time_offset;       /* time adjustment (us) */
-extern long time_constant;     /* pll time constant */
-extern long time_tolerance;    /* frequency tolerance (ppm) */
-extern long time_precision;    /* clock precision (us) */
 extern long time_maxerror;     /* maximum error */
 extern long time_esterror;     /* estimated error */
 
 extern long time_freq;         /* frequency offset (scaled ppm) */
-extern long time_reftime;      /* time at last adjustment (s) */
 
 extern long time_adjust;       /* The amount of adjtime left */
-extern long time_next_adjust;  /* Value for time_adjust at next tick */
 
-/**
- * ntp_clear - Clears the NTP state variables
- *
- * Must be called while holding a write on the xtime_lock
- */
-static inline void ntp_clear(void)
-{
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
-}
+extern void ntp_clear(void);
 
 /**
  * ntp_synced - Returns 1 if the NTP status is not UNSYNC
@@ -294,11 +270,15 @@ extern void register_time_interpolator(struct time_interpolator *);
 extern void unregister_time_interpolator(struct time_interpolator *);
 extern void time_interpolator_reset(void);
 extern unsigned long time_interpolator_get_offset(void);
+extern void time_interpolator_update(long delta_nsec);
 
 #else /* !CONFIG_TIME_INTERPOLATION */
 
-static inline void
-time_interpolator_reset(void)
+static inline void time_interpolator_reset(void)
+{
+}
+
+static inline void time_interpolator_update(long delta_nsec)
 {
 }
 
@@ -309,6 +289,8 @@ time_interpolator_reset(void)
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 extern u64 current_tick_length(void);
 
+extern void second_overflow(void);
+extern void update_ntp_one_tick(void);
 extern int do_adjtimex(struct timex *);
 
 #endif /* KERNEL */
index 99e02ef54c47db8fa1e9ceff2644acb9c2b98b38..bfc84a7aecc5288a762b8d0d5303f2ba17f34d42 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/if_tr.h>
 
 #ifdef __KERNEL__
-extern unsigned short  tr_type_trans(struct sk_buff *skb, struct net_device *dev);
+extern __be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev);
 extern void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev);
 extern struct net_device *alloc_trdev(int sizeof_priv);
 
diff --git a/include/linux/tsacct_kern.h b/include/linux/tsacct_kern.h
new file mode 100644 (file)
index 0000000..7e50ac7
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * tsacct_kern.h - kernel header for system accounting over taskstats interface
+ *
+ * Copyright (C) Jay Lan       SGI
+ */
+
+#ifndef _LINUX_TSACCT_KERN_H
+#define _LINUX_TSACCT_KERN_H
+
+#include <linux/taskstats.h>
+
+#ifdef CONFIG_TASKSTATS
+extern void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk);
+#else
+static inline void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
+{}
+#endif /* CONFIG_TASKSTATS */
+
+#ifdef CONFIG_TASK_XACCT
+extern void xacct_add_tsk(struct taskstats *stats, struct task_struct *p);
+extern void acct_update_integrals(struct task_struct *tsk);
+extern void acct_clear_integrals(struct task_struct *tsk);
+#else
+static inline void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
+{}
+static inline void acct_update_integrals(struct task_struct *tsk)
+{}
+static inline void acct_clear_integrals(struct task_struct *tsk)
+{}
+#endif /* CONFIG_TASK_XACCT */
+
+#endif
+
+
index 04827ca65781c0a47177a656eece88906ff9069d..44091c0db0b46b473234172a91d983319648e7ce 100644 (file)
@@ -174,7 +174,7 @@ struct tty_struct {
        struct tty_driver *driver;
        int index;
        struct tty_ldisc ldisc;
-       struct semaphore termios_sem;
+       struct mutex termios_mutex;
        struct termios *termios, *termios_locked;
        char name[64];
        int pgrp;
@@ -190,7 +190,6 @@ struct tty_struct {
        struct tty_struct *link;
        struct fasync_struct *fasync;
        struct tty_bufhead buf;
-       int max_flip_cnt;
        int alt_speed;          /* For magic substitution of 38400 bps */
        wait_queue_head_t write_wait;
        wait_queue_head_t read_wait;
@@ -308,6 +307,9 @@ extern void tty_ldisc_put(int);
 extern void tty_wakeup(struct tty_struct *tty);
 extern void tty_ldisc_flush(struct tty_struct *tty);
 
+extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                    unsigned long arg);
+
 extern struct mutex tty_mutex;
 
 /* n_tty.c */
index 3f235660a3cd6a76c4fa0480e649deaa5a4077d3..406d4ae57631709542ad5097b1aba9216fa2a4c3 100644 (file)
@@ -33,6 +33,8 @@ typedef __kernel_clockid_t    clockid_t;
 typedef __kernel_mqd_t         mqd_t;
 
 #ifdef __KERNEL__
+typedef _Bool                  bool;
+
 typedef __kernel_uid32_t       uid_t;
 typedef __kernel_gid32_t       gid_t;
 typedef __kernel_uid16_t        uid16_t;
index 391e7ed1eb3fc05ea2eeb8548e42381c8aefa7e5..a48d7f11c7be06772327604dc40c3f91b0b57145 100644 (file)
@@ -19,4 +19,26 @@ static inline unsigned long __copy_from_user_nocache(void *to,
 
 #endif         /* ARCH_HAS_NOCACHE_UACCESS */
 
+/**
+ * probe_kernel_address(): safely attempt to read from a location
+ * @addr: address to read from - its type is type typeof(retval)*
+ * @retval: read into this variable
+ *
+ * Safely read from address @addr into variable @revtal.  If a kernel fault
+ * happens, handle that and return -EFAULT.
+ * We ensure that the __get_user() is executed in atomic context so that
+ * do_page_fault() doesn't attempt to take mmap_sem.  This makes
+ * probe_kernel_address() suitable for use within regions where the caller
+ * already holds mmap_sem, or other locks which nest inside mmap_sem.
+ */
+#define probe_kernel_address(addr, retval)             \
+       ({                                              \
+               long ret;                               \
+                                                       \
+               inc_preempt_count();                    \
+               ret = __get_user(retval, addr);         \
+               dec_preempt_count();                    \
+               ret;                                    \
+       })
+
 #endif         /* __LINUX_UACCESS_H__ */
index 90223f057d507bd86edf2c8e30333319773e8f23..014b41d1e308ca27f01e7f94bf46d906dc97252d 100644 (file)
 #include <linux/types.h>
 
 struct udphdr {
-       __u16   source;
-       __u16   dest;
-       __u16   len;
-       __u16   check;
+       __be16  source;
+       __be16  dest;
+       __be16  len;
+       __be16  check;
 };
 
 /* UDP socket options */
index ce48e2cd37a28d52c1e15e8497e4b3c74da769ab..73e1751d03dd18e2806d4a018c05f9cf05eaf942 100644 (file)
@@ -12,8 +12,6 @@
  * is not much point in implementing the full Dwarf2 unwind API.
  */
 
-#include <linux/config.h>
-
 struct module;
 
 #ifdef CONFIG_STACK_UNWIND
index d2bd0c8e015408c0152fe7b9927ec2d5deda5100..190cc1b78fe2a29a071b01bb9ff8dbc4bc5490cc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/fs.h>          /* for struct file_operations */
 #include <linux/completion.h>  /* for struct completion */
 #include <linux/sched.h>       /* for current && schedule_timeout */
+#include <linux/mutex.h>       /* for struct mutex */
 
 struct usb_device;
 struct usb_driver;
@@ -102,8 +103,13 @@ enum usb_interface_condition {
  *     number from the USB core by calling usb_register_dev().
  * @condition: binding state of the interface: not bound, binding
  *     (in probe()), bound to a driver, or unbinding (in disconnect())
+ * @is_active: flag set when the interface is bound and not suspended.
+ * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+ *     capability during autosuspend.
  * @dev: driver model's view of this device
  * @class_dev: driver model's class view of this device.
+ * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not
+ *     allowed unless the counter is 0.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -142,8 +148,12 @@ struct usb_interface {
        int minor;                      /* minor number this interface is
                                         * bound to */
        enum usb_interface_condition condition;         /* state of binding */
+       unsigned is_active:1;           /* the interface is not suspended */
+       unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
+
        struct device dev;              /* interface specific device info */
        struct class_device *class_dev;
+       int pm_usage_cnt;               /* usage counter for autosuspend */
 };
 #define        to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define        interface_to_usbdev(intf) \
@@ -254,8 +264,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
 
 /* ----------------------------------------------------------------------- */
 
-struct usb_operations;
-
 /* USB device number allocation bitmap */
 struct usb_devmap {
        unsigned long devicemap[128 / (8*sizeof(unsigned long))];
@@ -268,6 +276,7 @@ struct usb_bus {
        struct device *controller;      /* host/master side hardware */
        int busnum;                     /* Bus number (in order of reg) */
        char *bus_name;                 /* stable id (PCI slot_name etc) */
+       u8 uses_dma;                    /* Does the host controller use DMA? */
        u8 otg_port;                    /* 0, or number of OTG/HNP port */
        unsigned is_b_host:1;           /* true during some HNP roleswitches */
        unsigned b_hnp_enable:1;        /* OTG: did A-Host enable HNP? */
@@ -276,10 +285,8 @@ struct usb_bus {
                                         * round-robin allocation */
 
        struct usb_devmap devmap;       /* device address allocation map */
-       struct usb_operations *op;      /* Operations (specific to the HC) */
        struct usb_device *root_hub;    /* Root hub */
        struct list_head bus_list;      /* list of busses */
-       void *hcpriv;                   /* Host Controller private data */
 
        int bandwidth_allocated;        /* on this bus: how much of the time
                                         * reserved for periodic (intr/iso)
@@ -294,8 +301,6 @@ struct usb_bus {
        struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */
 
        struct class_device *class_dev; /* class device for this bus */
-       struct kref kref;               /* reference counting for this bus */
-       void (*release)(struct usb_bus *bus);
 
 #if defined(CONFIG_USB_MON)
        struct mon_bus *mon_bus;        /* non-null when associated */
@@ -350,6 +355,7 @@ struct usb_device {
 
        unsigned short bus_mA;          /* Current available from the bus */
        u8 portnum;                     /* Parent port number (origin 1) */
+       u8 level;                       /* Number of USB hub ancestors */
 
        int have_langid;                /* whether string_langid is valid */
        int string_langid;              /* language ID for strings */
@@ -373,6 +379,15 @@ struct usb_device {
 
        int maxchild;                   /* Number of ports if hub */
        struct usb_device *children[USB_MAXCHILDREN];
+
+       int pm_usage_cnt;               /* usage counter for autosuspend */
+#ifdef CONFIG_PM
+       struct work_struct autosuspend; /* for delayed autosuspends */
+       struct mutex pm_mutex;          /* protects PM operations */
+
+       unsigned auto_pm:1;             /* autosuspend/resume in progress */
+       unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */
+#endif
 };
 #define        to_usb_device(d) container_of(d, struct usb_device, dev)
 
@@ -384,7 +399,7 @@ extern void usb_put_dev(struct usb_device *dev);
 #define usb_unlock_device(udev)                up(&(udev)->dev.sem)
 #define usb_trylock_device(udev)       down_trylock(&(udev)->dev.sem)
 extern int usb_lock_device_for_reset(struct usb_device *udev,
-               struct usb_interface *iface);
+                                    const struct usb_interface *iface);
 
 /* USB port reset for device reinitialization */
 extern int usb_reset_device(struct usb_device *dev);
@@ -393,6 +408,17 @@ extern int usb_reset_composite_device(struct usb_device *dev,
 
 extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
 
+/* USB autosuspend and autoresume */
+#ifdef CONFIG_USB_SUSPEND
+extern int usb_autopm_get_interface(struct usb_interface *intf);
+extern void usb_autopm_put_interface(struct usb_interface *intf);
+
+#else
+#define usb_autopm_get_interface(intf)         0
+#define usb_autopm_put_interface(intf)         do {} while (0)
+#endif
+
+
 /*-------------------------------------------------------------------------*/
 
 /* for drivers using iso endpoints */
@@ -423,10 +449,10 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 
 extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
                int minor);
-extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev,
+extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
                unsigned ifnum);
 extern struct usb_host_interface *usb_altnum_to_altsetting(
-               struct usb_interface *intf, unsigned int altnum);
+               const struct usb_interface *intf, unsigned int altnum);
 
 
 /**
@@ -464,6 +490,20 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
 
 /*-------------------------------------------------------------------------*/
 
+extern int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd);
+
+/*-------------------------------------------------------------------------*/
+
 #define USB_DEVICE_ID_MATCH_DEVICE \
                (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
 #define USB_DEVICE_ID_MATCH_DEV_RANGE \
@@ -540,7 +580,17 @@ struct usb_dynids {
 };
 
 /**
- * struct usb_driver - identifies USB driver to usbcore
+ * struct usbdrv_wrap - wrapper for driver-model structure
+ * @driver: The driver-model core driver structure.
+ * @for_devices: Non-zero for device drivers, 0 for interface drivers.
+ */
+struct usbdrv_wrap {
+       struct device_driver driver;
+       int for_devices;
+};
+
+/**
+ * struct usb_driver - identifies USB interface driver to usbcore
  * @name: The driver name should be unique among USB drivers,
  *     and should normally be the same as the module name.
  * @probe: Called to see if the driver is willing to manage a particular
@@ -567,12 +617,14 @@ struct usb_dynids {
  *     or your driver's probe function will never get called.
  * @dynids: used internally to hold the list of dynamically added device
  *     ids for this driver.
- * @driver: the driver model core driver structure.
+ * @drvwrap: Driver-model core structure wrapper.
  * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
  *     added to this driver by preventing the sysfs file from being created.
+ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+ *     for interfaces bound to this driver.
  *
- * USB drivers must provide a name, probe() and disconnect() methods,
- * and an id_table.  Other driver fields are optional.
+ * USB interface drivers must provide a name, probe() and disconnect()
+ * methods, and an id_table.  Other driver fields are optional.
  *
  * The id_table is used in hotplugging.  It holds a set of descriptors,
  * and specialized data may be associated with each entry.  That table
@@ -606,10 +658,44 @@ struct usb_driver {
        const struct usb_device_id *id_table;
 
        struct usb_dynids dynids;
-       struct device_driver driver;
+       struct usbdrv_wrap drvwrap;
        unsigned int no_dynamic_id:1;
+       unsigned int supports_autosuspend:1;
 };
-#define        to_usb_driver(d) container_of(d, struct usb_driver, driver)
+#define        to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
+
+/**
+ * struct usb_device_driver - identifies USB device driver to usbcore
+ * @name: The driver name should be unique among USB drivers,
+ *     and should normally be the same as the module name.
+ * @probe: Called to see if the driver is willing to manage a particular
+ *     device.  If it is, probe returns zero and uses dev_set_drvdata()
+ *     to associate driver-specific data with the device.  If unwilling
+ *     to manage the device, return a negative errno value.
+ * @disconnect: Called when the device is no longer accessible, usually
+ *     because it has been (or is being) disconnected or the driver's
+ *     module is being unloaded.
+ * @suspend: Called when the device is going to be suspended by the system.
+ * @resume: Called when the device is being resumed by the system.
+ * @drvwrap: Driver-model core structure wrapper.
+ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+ *     for devices bound to this driver.
+ *
+ * USB drivers must provide all the fields listed above except drvwrap.
+ */
+struct usb_device_driver {
+       const char *name;
+
+       int (*probe) (struct usb_device *udev);
+       void (*disconnect) (struct usb_device *udev);
+
+       int (*suspend) (struct usb_device *udev, pm_message_t message);
+       int (*resume) (struct usb_device *udev);
+       struct usbdrv_wrap drvwrap;
+       unsigned int supports_autosuspend:1;
+};
+#define        to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
+               drvwrap.driver)
 
 extern struct bus_type usb_bus_type;
 
@@ -633,13 +719,17 @@ struct usb_class_driver {
  * use these in module_init()/module_exit()
  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
  */
-int usb_register_driver(struct usb_driver *, struct module *);
+extern int usb_register_driver(struct usb_driver *, struct module *);
 static inline int usb_register(struct usb_driver *driver)
 {
        return usb_register_driver(driver, THIS_MODULE);
 }
 extern void usb_deregister(struct usb_driver *);
 
+extern int usb_register_device_driver(struct usb_device_driver *,
+                       struct module *);
+extern void usb_deregister_device_driver(struct usb_device_driver *);
+
 extern int usb_register_dev(struct usb_interface *intf,
                            struct usb_class_driver *class_driver);
 extern void usb_deregister_dev(struct usb_interface *intf,
@@ -885,7 +975,7 @@ struct urb
  * @setup_packet: pointer to the setup_packet buffer
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  *
  * Initializes a control urb with the proper information needed to submit
@@ -897,7 +987,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
                                         unsigned char *setup_packet,
                                         void *transfer_buffer,
                                         int buffer_length,
-                                        usb_complete_t complete,
+                                        usb_complete_t complete_fn,
                                         void *context)
 {
        spin_lock_init(&urb->lock);
@@ -906,7 +996,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
        urb->setup_packet = setup_packet;
        urb->transfer_buffer = transfer_buffer;
        urb->transfer_buffer_length = buffer_length;
-       urb->complete = complete;
+       urb->complete = complete_fn;
        urb->context = context;
 }
 
@@ -917,7 +1007,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
  * @pipe: the endpoint pipe
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  *
  * Initializes a bulk urb with the proper information needed to submit it
@@ -928,7 +1018,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
                                      unsigned int pipe,
                                      void *transfer_buffer,
                                      int buffer_length,
-                                     usb_complete_t complete,
+                                     usb_complete_t complete_fn,
                                      void *context)
 {
        spin_lock_init(&urb->lock);
@@ -936,7 +1026,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
        urb->pipe = pipe;
        urb->transfer_buffer = transfer_buffer;
        urb->transfer_buffer_length = buffer_length;
-       urb->complete = complete;
+       urb->complete = complete_fn;
        urb->context = context;
 }
 
@@ -947,7 +1037,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
  * @pipe: the endpoint pipe
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  * @interval: what to set the urb interval to, encoded like
  *     the endpoint descriptor's bInterval value.
@@ -963,7 +1053,7 @@ static inline void usb_fill_int_urb (struct urb *urb,
                                     unsigned int pipe,
                                     void *transfer_buffer,
                                     int buffer_length,
-                                    usb_complete_t complete,
+                                    usb_complete_t complete_fn,
                                     void *context,
                                     int interval)
 {
@@ -972,7 +1062,7 @@ static inline void usb_fill_int_urb (struct urb *urb,
        urb->pipe = pipe;
        urb->transfer_buffer = transfer_buffer;
        urb->transfer_buffer_length = buffer_length;
-       urb->complete = complete;
+       urb->complete = complete_fn;
        urb->context = context;
        if (dev->speed == USB_SPEED_HIGH)
                urb->interval = 1 << (interval - 1);
@@ -990,7 +1080,6 @@ extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
-#define HAVE_USB_BUFFERS
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
        gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
@@ -1003,14 +1092,14 @@ void usb_buffer_unmap (struct urb *urb);
 #endif
 
 struct scatterlist;
-int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int nents);
+int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+                     struct scatterlist *sg, int nents);
 #if 0
-void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents);
+void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+                          struct scatterlist *sg, int n_hw_ents);
 #endif
-void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents);
+void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+                        struct scatterlist *sg, int n_hw_ents);
 
 /*-------------------------------------------------------------------*
  *                         SYNCHRONOUS CALL SUPPORT                  *
@@ -1038,6 +1127,9 @@ extern int usb_clear_halt(struct usb_device *dev, int pipe);
 extern int usb_reset_configuration(struct usb_device *dev);
 extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
 
+/* this request isn't really synchronous, but it belongs with the others */
+extern int usb_driver_set_configuration(struct usb_device *udev, int config);
+
 /*
  * timeouts, in milliseconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
new file mode 100644 (file)
index 0000000..6bd2359
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * <linux/usb/audio.h> -- USB Audio definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for Audio Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/audio10.pdf
+ */
+
+#ifndef __LINUX_USB_AUDIO_H
+#define __LINUX_USB_AUDIO_H
+
+#include <linux/types.h>
+
+/* A.2 Audio Interface Subclass Codes */
+#define USB_SUBCLASS_AUDIOCONTROL      0x01
+#define USB_SUBCLASS_AUDIOSTREAMING    0x02
+#define USB_SUBCLASS_MIDISTREAMING     0x03
+
+/* 4.3.2  Class-Specific AC Interface Descriptor */
+struct usb_ac_header_descriptor {
+       __u8  bLength;                  // 8+n
+       __u8  bDescriptorType;          // USB_DT_CS_INTERFACE
+       __u8  bDescriptorSubtype;       // USB_MS_HEADER
+       __le16 bcdADC;                  // 0x0100
+       __le16 wTotalLength;            // includes Unit and Terminal desc.
+       __u8  bInCollection;            // n
+       __u8  baInterfaceNr[];          // [n]
+} __attribute__ ((packed));
+
+#define USB_DT_AC_HEADER_SIZE(n)       (8+(n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_AC_HEADER_DESCRIPTOR(n)                    \
+struct usb_ac_header_descriptor_##n {                          \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __le16 bcdADC;                                          \
+       __le16 wTotalLength;                                    \
+       __u8  bInCollection;                                    \
+       __u8  baInterfaceNr[n];                                 \
+} __attribute__ ((packed))
+
+#endif
diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
new file mode 100644 (file)
index 0000000..11a97d5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * <linux/usb/midi.h> -- USB MIDI definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for MIDI Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#ifndef __LINUX_USB_MIDI_H
+#define __LINUX_USB_MIDI_H
+
+#include <linux/types.h>
+
+/* A.1  MS Class-Specific Interface Descriptor Subtypes */
+#define USB_MS_HEADER          0x01
+#define USB_MS_MIDI_IN_JACK    0x02
+#define USB_MS_MIDI_OUT_JACK   0x03
+#define USB_MS_ELEMENT         0x04
+
+/* A.2  MS Class-Specific Endpoint Descriptor Subtypes */
+#define USB_MS_GENERAL         0x01
+
+/* A.3  MS MIDI IN and OUT Jack Types */
+#define USB_MS_EMBEDDED                0x01
+#define USB_MS_EXTERNAL                0x02
+
+/* 6.1.2.1  Class-Specific MS Interface Header Descriptor */
+struct usb_ms_header_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubtype;
+       __le16 bcdMSC;
+       __le16 wTotalLength;
+} __attribute__ ((packed));
+
+#define USB_DT_MS_HEADER_SIZE  7
+
+/* 6.1.2.2  MIDI IN Jack Descriptor */
+struct usb_midi_in_jack_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;          // USB_DT_CS_INTERFACE
+       __u8  bDescriptorSubtype;       // USB_MS_MIDI_IN_JACK
+       __u8  bJackType;                // USB_MS_EMBEDDED/EXTERNAL
+       __u8  bJackID;
+       __u8  iJack;
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_IN_SIZE    6
+
+struct usb_midi_source_pin {
+       __u8  baSourceID;
+       __u8  baSourcePin;
+} __attribute__ ((packed));
+
+/* 6.1.2.3  MIDI OUT Jack Descriptor */
+struct usb_midi_out_jack_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;          // USB_DT_CS_INTERFACE
+       __u8  bDescriptorSubtype;       // USB_MS_MIDI_OUT_JACK
+       __u8  bJackType;                // USB_MS_EMBEDDED/EXTERNAL
+       __u8  bJackID;
+       __u8  bNrInputPins;             // p
+       struct usb_midi_source_pin pins[]; // [p]
+       /*__u8  iJack;  -- ommitted due to variable-sized pins[] */
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_OUT_SIZE(p)        (7 + 2 * (p))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(p)                        \
+struct usb_midi_out_jack_descriptor_##p {                      \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bJackType;                                        \
+       __u8  bJackID;                                          \
+       __u8  bNrInputPins;                                     \
+       struct usb_midi_source_pin pins[p];                     \
+       __u8  iJack;                                            \
+} __attribute__ ((packed))
+
+/* 6.2.2  Class-Specific MS Bulk Data Endpoint Descriptor */
+struct usb_ms_endpoint_descriptor {
+       __u8  bLength;                  // 4+n
+       __u8  bDescriptorType;          // USB_DT_CS_ENDPOINT
+       __u8  bDescriptorSubtype;       // USB_MS_GENERAL
+       __u8  bNumEmbMIDIJack;          // n
+       __u8  baAssocJackID[];          // [n]
+} __attribute__ ((packed));
+
+#define USB_DT_MS_ENDPOINT_SIZE(n)     (4 + (n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(n)                  \
+struct usb_ms_endpoint_descriptor_##n {                                \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bNumEmbMIDIJack;                                  \
+       __u8  baAssocJackID[n];                                 \
+} __attribute__ ((packed))
+
+#endif
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
new file mode 100644 (file)
index 0000000..9897f7a
--- /dev/null
@@ -0,0 +1,131 @@
+// include/linux/usb/otg.h
+
+/*
+ * These APIs may be used between USB controllers.  USB device drivers
+ * (for either host or peripheral roles) don't use these calls; they
+ * continue to use just usb_device and usb_gadget.
+ */
+
+
+/* OTG defines lots of enumeration states before device reset */
+enum usb_otg_state {
+       OTG_STATE_UNDEFINED = 0,
+
+       /* single-role peripheral, and dual-role default-b */
+       OTG_STATE_B_IDLE,
+       OTG_STATE_B_SRP_INIT,
+       OTG_STATE_B_PERIPHERAL,
+
+       /* extra dual-role default-b states */
+       OTG_STATE_B_WAIT_ACON,
+       OTG_STATE_B_HOST,
+
+       /* dual-role default-a */
+       OTG_STATE_A_IDLE,
+       OTG_STATE_A_WAIT_VRISE,
+       OTG_STATE_A_WAIT_BCON,
+       OTG_STATE_A_HOST,
+       OTG_STATE_A_SUSPEND,
+       OTG_STATE_A_PERIPHERAL,
+       OTG_STATE_A_WAIT_VFALL,
+       OTG_STATE_A_VBUS_ERR,
+};
+
+/*
+ * the otg driver needs to interact with both device side and host side
+ * usb controllers.  it decides which controller is active at a given
+ * moment, using the transceiver, ID signal, HNP and sometimes static
+ * configuration information (including "board isn't wired for otg").
+ */
+struct otg_transceiver {
+       struct device           *dev;
+       const char              *label;
+
+       u8                      default_a;
+       enum usb_otg_state      state;
+
+       struct usb_bus          *host;
+       struct usb_gadget       *gadget;
+
+       /* to pass extra port status to the root hub */
+       u16                     port_status;
+       u16                     port_change;
+
+       /* bind/unbind the host controller */
+       int     (*set_host)(struct otg_transceiver *otg,
+                               struct usb_bus *host);
+
+       /* bind/unbind the peripheral controller */
+       int     (*set_peripheral)(struct otg_transceiver *otg,
+                               struct usb_gadget *gadget);
+
+       /* effective for B devices, ignored for A-peripheral */
+       int     (*set_power)(struct otg_transceiver *otg,
+                               unsigned mA);
+
+       /* for non-OTG B devices: set transceiver into suspend mode */
+       int     (*set_suspend)(struct otg_transceiver *otg,
+                               int suspend);
+
+       /* for B devices only:  start session with A-Host */
+       int     (*start_srp)(struct otg_transceiver *otg);
+
+       /* start or continue HNP role switch */
+       int     (*start_hnp)(struct otg_transceiver *otg);
+
+};
+
+
+/* for board-specific init logic */
+extern int otg_set_transceiver(struct otg_transceiver *);
+
+
+/* for usb host and peripheral controller drivers */
+extern struct otg_transceiver *otg_get_transceiver(void);
+
+static inline int
+otg_start_hnp(struct otg_transceiver *otg)
+{
+       return otg->start_hnp(otg);
+}
+
+
+/* for HCDs */
+static inline int
+otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+       return otg->set_host(otg, host);
+}
+
+
+/* for usb peripheral controller drivers */
+static inline int
+otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
+{
+       return otg->set_peripheral(otg, periph);
+}
+
+static inline int
+otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+       return otg->set_power(otg, mA);
+}
+
+static inline int
+otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+       if (otg->set_suspend != NULL)
+               return otg->set_suspend(otg, suspend);
+       else
+               return 0;
+}
+
+static inline int
+otg_start_srp(struct otg_transceiver *otg)
+{
+       return otg->start_srp(otg);
+}
+
+
+/* for OTG controller drivers (and maybe other stuff) */
+extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
diff --git a/include/linux/usb_otg.h b/include/linux/usb_otg.h
deleted file mode 100644 (file)
index f827f6e..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-// include/linux/usb_otg.h 
-
-/*
- * These APIs may be used between USB controllers.  USB device drivers
- * (for either host or peripheral roles) don't use these calls; they
- * continue to use just usb_device and usb_gadget.
- */
-
-
-/* OTG defines lots of enumeration states before device reset */
-enum usb_otg_state {
-       OTG_STATE_UNDEFINED = 0,
-
-       /* single-role peripheral, and dual-role default-b */
-       OTG_STATE_B_IDLE,
-       OTG_STATE_B_SRP_INIT,
-       OTG_STATE_B_PERIPHERAL,
-
-       /* extra dual-role default-b states */
-       OTG_STATE_B_WAIT_ACON,
-       OTG_STATE_B_HOST,
-
-       /* dual-role default-a */
-       OTG_STATE_A_IDLE,
-       OTG_STATE_A_WAIT_VRISE,
-       OTG_STATE_A_WAIT_BCON,
-       OTG_STATE_A_HOST,
-       OTG_STATE_A_SUSPEND,
-       OTG_STATE_A_PERIPHERAL,
-       OTG_STATE_A_WAIT_VFALL,
-       OTG_STATE_A_VBUS_ERR,
-};
-
-/*
- * the otg driver needs to interact with both device side and host side
- * usb controllers.  it decides which controller is active at a given
- * moment, using the transceiver, ID signal, HNP and sometimes static
- * configuration information (including "board isn't wired for otg").
- */
-struct otg_transceiver {
-       struct device           *dev;
-       const char              *label;
-
-       u8                      default_a;
-       enum usb_otg_state      state;
-
-       struct usb_bus          *host;
-       struct usb_gadget       *gadget;
-
-       /* to pass extra port status to the root hub */
-       u16                     port_status;
-       u16                     port_change;
-
-       /* bind/unbind the host controller */
-       int     (*set_host)(struct otg_transceiver *otg,
-                               struct usb_bus *host);
-
-       /* bind/unbind the peripheral controller */
-       int     (*set_peripheral)(struct otg_transceiver *otg,
-                               struct usb_gadget *gadget);
-
-       /* effective for B devices, ignored for A-peripheral */
-       int     (*set_power)(struct otg_transceiver *otg,
-                               unsigned mA);
-
-       /* for non-OTG B devices: set transceiver into suspend mode */
-       int     (*set_suspend)(struct otg_transceiver *otg,
-                               int suspend);
-
-       /* for B devices only:  start session with A-Host */
-       int     (*start_srp)(struct otg_transceiver *otg);
-
-       /* start or continue HNP role switch */
-       int     (*start_hnp)(struct otg_transceiver *otg);
-
-};
-
-
-/* for board-specific init logic */
-extern int otg_set_transceiver(struct otg_transceiver *);
-
-
-/* for usb host and peripheral controller drivers */
-extern struct otg_transceiver *otg_get_transceiver(void);
-
-static inline int
-otg_start_hnp(struct otg_transceiver *otg)
-{
-       return otg->start_hnp(otg);
-}
-
-
-/* for HCDs */
-static inline int
-otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
-{
-       return otg->set_host(otg, host);
-}
-
-
-/* for usb peripheral controller drivers */
-static inline int
-otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
-{
-       return otg->set_peripheral(otg, periph);
-}
-
-static inline int
-otg_set_power(struct otg_transceiver *otg, unsigned mA)
-{
-       return otg->set_power(otg, mA);
-}
-
-static inline int
-otg_set_suspend(struct otg_transceiver *otg, int suspend)
-{
-       if (otg->set_suspend != NULL)
-               return otg->set_suspend(otg, suspend);
-       else
-               return 0;
-}
-
-static inline int
-otg_start_srp(struct otg_transceiver *otg)
-{
-       return otg->start_srp(otg);
-}
-
-
-/* for OTG controller drivers (and maybe other stuff) */
-extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
index e7fc5fed5b98b8044d940fa4a7ded769a09a0452..2ae76fe52ff75e483806cd48c2f3e29fadfd89ac 100644 (file)
@@ -108,6 +108,9 @@ enum { US_DO_ALL_FLAGS };
 #ifdef CONFIG_USB_STORAGE_ALAUDA
 #define US_PR_ALAUDA    0xf4           /* Alauda chipsets */
 #endif
+#ifdef CONFIG_USB_STORAGE_KARMA
+#define US_PR_KARMA     0xf5           /* Rio Karma */
+#endif
 
 #define US_PR_DEVICE   0xff            /* Use device's value */
 
index c6bf27b7897e79e279446fb2ef9aa887f4b34488..640be6a1959e8074ad79bce56ef71ecbeb779053 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_UTIME_H
 #define _LINUX_UTIME_H
 
+#include <linux/types.h>
+
 struct utimbuf {
        time_t actime;
        time_t modtime;
index e3715d7741977715a34326940033a674fd0b8b15..44c59da26ed2673c10c62fc54e50712cd6f3cff5 100644 (file)
@@ -1135,7 +1135,8 @@ struct v4l2_sliced_vbi_cap
                                 (equals frame lines 313-336 for 625 line video
                                  standards, 263-286 for 525 line standards) */
        __u16   service_lines[2][24];
-       __u32   reserved[4];    /* must be 0 */
+       enum v4l2_buf_type type;
+       __u32   reserved[3];    /* must be 0 */
 };
 
 struct v4l2_sliced_vbi_data
@@ -1242,7 +1243,7 @@ struct v4l2_streamparm
 #define VIDIOC_G_PRIORITY       _IOR  ('V', 67, enum v4l2_priority)
 #define VIDIOC_S_PRIORITY       _IOW  ('V', 68, enum v4l2_priority)
 #if 1
-#define VIDIOC_G_SLICED_VBI_CAP _IO ('V', 69, struct v4l2_sliced_vbi_cap)
+#define VIDIOC_G_SLICED_VBI_CAP _IOWR ('V', 69, struct v4l2_sliced_vbi_cap)
 #endif
 #define VIDIOC_LOG_STATUS       _IO   ('V', 70)
 #define VIDIOC_G_EXT_CTRLS     _IOWR ('V', 71, struct v4l2_ext_controls)
index dee88c6b6fa74e907957e112d2c06f47eb6773a3..ce5f1482e6be4fe2e90589be3822bfeb9da4242e 100644 (file)
@@ -62,7 +62,6 @@ extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 extern struct vm_struct *get_vm_area_node(unsigned long size,
                                        unsigned long flags, int node);
 extern struct vm_struct *remove_vm_area(void *addr);
-extern struct vm_struct *__remove_vm_area(void *addr);
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
                        struct page ***pages);
 extern void unmap_vm_area(struct vm_struct *area);
index 176c7f797339b2aa5d4bca59157b7181bcc5bd97..c89df55f6e035df2ef064726c870911506c7debc 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 #include <linux/percpu.h>
-#include <linux/config.h>
 #include <linux/mmzone.h>
 #include <asm/atomic.h>
 
index 918a29763aea3e0afb58cb78d62db873bad16169..1009d3fe1fc214e8eb920e207483ebdd7d35f1b3 100644 (file)
@@ -33,7 +33,8 @@ extern int fg_console, last_console, want_console;
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
-void vc_disallocate(unsigned int console);
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
+void vc_deallocate(unsigned int console);
 void reset_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
 void do_unblank_screen(int leaving_gfx);
index 13588564b42b04331a107c45fb97a7a9337987b8..a50a0130fd9eb020a6ef8c01f416244fd03e1c19 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :   20      17.2.06
+ * Version :   21      14.3.06
  *
  * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
 
 /***************************** INCLUDES *****************************/
 
+/* This header is used in user-space, therefore need to be sanitised
+ * for that purpose. Those includes are usually not compatible with glibc.
+ * To know which includes to use in user-space, check iwlib.h. */
+#ifdef __KERNEL__
 #include <linux/types.h>               /* for "caddr_t" et al          */
 #include <linux/socket.h>              /* for "struct sockaddr" et al  */
 #include <linux/if.h>                  /* for IFNAMSIZ and co... */
+#endif /* __KERNEL__ */
 
 /***************************** VERSION *****************************/
 /*
@@ -80,7 +85,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT   20
+#define WIRELESS_EXT   21
 
 /*
  * Changes :
  * V19 to V20
  * ----------
  *     - RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ *     - Remove (struct net_device *)->get_wireless_stats()
+ *     - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *     - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ *     - Power/Retry relative values no longer * 100000
+ *     - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
  */
 
 /**************************** CONSTANTS ****************************/
 #define IW_QUAL_QUAL_INVALID   0x10    /* Driver doesn't provide value */
 #define IW_QUAL_LEVEL_INVALID  0x20
 #define IW_QUAL_NOISE_INVALID  0x40
+#define IW_QUAL_RCPI           0x80    /* Level + Noise are 802.11k RCPI */
 #define IW_QUAL_ALL_INVALID    0x70
 
 /* Frequency flags */
 #define IW_RETRY_TYPE          0xF000  /* Type of parameter */
 #define IW_RETRY_LIMIT         0x1000  /* Maximum number of retries*/
 #define IW_RETRY_LIFETIME      0x2000  /* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_RETRY_MODIFIER      0x00FF  /* Modify a parameter */
 #define IW_RETRY_MIN           0x0001  /* Value is a minimum  */
 #define IW_RETRY_MAX           0x0002  /* Value is a maximum */
 #define IW_RETRY_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT         0x0010  /* Value is for short packets  */
+#define IW_RETRY_LONG          0x0020  /* Value is for long packets */
 
 /* Scanning request flags */
 #define IW_SCAN_DEFAULT                0x0000  /* Default scan of the driver */
@@ -1017,7 +1033,7 @@ struct    iw_range
        /* Note : this frequency list doesn't need to fit channel numbers,
         * because each entry contain its channel index */
 
-       __u32           enc_capa; /* IW_ENC_CAPA_* bit field */
+       __u32           enc_capa;       /* IW_ENC_CAPA_* bit field */
 };
 
 /*
index 56a23a0e7f2eb218a91fd889fb86bbdb3471bcef..4f4d98addb448afb61cd3d49b4a2a8cc3a00cbea 100644 (file)
@@ -111,12 +111,15 @@ balance_dirty_pages_ratelimited(struct address_space *mapping)
 }
 
 int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
+extern int generic_writepages(struct address_space *mapping,
+                             struct writeback_control *wbc);
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
 int sync_page_range(struct inode *inode, struct address_space *mapping,
                        loff_t pos, loff_t count);
 int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
                           loff_t pos, loff_t count);
 void set_page_dirty_balance(struct page *page);
+void writeback_set_ratelimit(void);
 
 /* pdflush.c */
 extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
index 14ecd19f4cdc5a7298691951d83c28f8f1ce55a4..430afd05826975e4df9a65afe68e5b9729c1b11c 100644 (file)
@@ -12,8 +12,8 @@
  */
 typedef union
 {
-       __u32           a4;
-       __u32           a6[4];
+       __be32          a4;
+       __be32          a6[4];
 } xfrm_address_t;
 
 /* Ident of a specific xfrm_state. It is used on input to lookup
@@ -23,7 +23,7 @@ typedef union
 struct xfrm_id
 {
        xfrm_address_t  daddr;
-       __u32           spi;
+       __be32          spi;
        __u8            proto;
 };
 
@@ -49,10 +49,10 @@ struct xfrm_selector
 {
        xfrm_address_t  daddr;
        xfrm_address_t  saddr;
-       __u16   dport;
-       __u16   dport_mask;
-       __u16   sport;
-       __u16   sport_mask;
+       __be16  dport;
+       __be16  dport_mask;
+       __be16  sport;
+       __be16  sport_mask;
        __u16   family;
        __u8    prefixlen_d;
        __u8    prefixlen_s;
@@ -281,7 +281,7 @@ struct xfrm_usersa_info {
 
 struct xfrm_usersa_id {
        xfrm_address_t                  daddr;
-       __u32                           spi;
+       __be32                          spi;
        __u16                           family;
        __u8                            proto;
 };
index 7bab09b0ed451ae2f1f1569ceeaeb3ce2b8ab52a..8f58406533c64c6b1ae0fb6ebd0343783963dcd8 100644 (file)
@@ -90,6 +90,8 @@ extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
 
 #endif
 
index 3c43b95f4c0dd5062b07b5d3864027b0ca0aff89..37dad07a8439434c26127c2c766ceb8b2c03354f 100644 (file)
@@ -72,6 +72,9 @@ struct tuner_params {
        unsigned int port2_invert_for_secam_lc:1;
        /* Some cards require PORT1 to be 1 for mono Radio FM and 0 for stereo. */
        unsigned int port1_set_for_fm_mono:1;
+       /* Select 18% (or according to datasheet 0%) L standard PLL gating,
+          vs the driver default of 36%. */
+       unsigned int default_pll_gating_18:1;
        /* Default tda9887 TOP value in dB for the low band. Default is 0.
           Range: -16:+15 */
        signed int default_top_low:5;
index 2f7b00b08e8817224c5827ab09e7f13bd376d883..3116e750132f2e7575e07d2caced3b21bdf34bdb 100644 (file)
@@ -144,6 +144,7 @@ extern int tuner_debug;
 #define TDA9887_DEEMPHASIS_50          (2<<16)
 #define TDA9887_DEEMPHASIS_75          (3<<16)
 #define TDA9887_AUTOMUTE               (1<<18)
+#define TDA9887_GATING_18              (1<<19)
 
 #ifdef __KERNEL__
 
index 5564db13c0d5f1d1897dadb20309c1d06219480a..aecc946980a3a7da00ce0f7b90fbaf70248bf7a1 100644 (file)
@@ -121,10 +121,17 @@ enum v4l2_chip_ident {
        /* general idents: reserved range 0-49 */
        V4L2_IDENT_UNKNOWN = 0,
 
-       /* module saa7115: reserved range 100-149 */
+       /* module saa7110: just ident= 100 */
+       V4L2_IDENT_SAA7110 = 100,
+
+       /* module saa7111: just ident= 101 */
+       V4L2_IDENT_SAA7111 = 101,
+
+       /* module saa7115: reserved range 102-149 */
        V4L2_IDENT_SAA7113 = 103,
        V4L2_IDENT_SAA7114 = 104,
        V4L2_IDENT_SAA7115 = 105,
+       V4L2_IDENT_SAA7118 = 108,
 
        /* module saa7127: reserved range 150-199 */
        V4L2_IDENT_SAA7127 = 157,
@@ -166,11 +173,12 @@ enum v4l2_chip_ident {
 #define VIDIOC_INT_S_STANDBY        _IOW('d', 94, u32)
 
 /* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
-#define        VIDIOC_INT_S_REGISTER           _IOR ('d', 100, struct v4l2_register)
+#define        VIDIOC_INT_S_REGISTER           _IOW ('d', 100, struct v4l2_register)
 #define        VIDIOC_INT_G_REGISTER           _IOWR('d', 101, struct v4l2_register)
 
-/* Reset the I2C chip */
-#define VIDIOC_INT_RESET               _IO  ('d', 102)
+/* Generic reset command. The argument selects which subsystems to reset.
+   Passing 0 will always reset the whole chip. */
+#define VIDIOC_INT_RESET               _IOW ('d', 102, u32)
 
 /* Set the frequency (in Hz) of the audio clock output.
    Used to slave an audio processor to the video decoder, ensuring that audio
index bb495b7f4680b112b96d82bad4a8320a29e91b11..6a11d772700ff649e9a1d81b47db9f8622af3594 100644 (file)
@@ -9,7 +9,8 @@
 #ifndef _V4L2_DEV_H
 #define _V4L2_DEV_H
 
-#define OBSOLETE_OWNER 1 /* to be removed soon */
+#define OBSOLETE_OWNER   1 /* to be removed soon */
+#define OBSOLETE_DEVDATA 1 /* to be removed soon */
 
 #include <linux/poll.h>
 #include <linux/fs.h>
@@ -338,8 +339,6 @@ extern int video_usercopy(struct inode *inode, struct file *file,
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 #include <linux/mm.h>
 
-extern struct video_device* video_devdata(struct file*);
-
 #define to_video_device(cd) container_of(cd, struct video_device, class_dev)
 static inline int __must_check
 video_device_create_file(struct video_device *vfd,
@@ -370,9 +369,14 @@ static inline void video_set_drvdata(struct video_device *dev, void *data)
 {
        dev->priv = data;
 }
+
 #endif
 
+#ifdef OBSOLETE_DEVDATA /* to be removed soon */
+/* Obsolete stuff - Still needed for radio devices and obsolete drivers */
+extern struct video_device* video_devdata(struct file*);
 extern int video_exclusive_open(struct inode *inode, struct file *file);
 extern int video_exclusive_release(struct inode *inode, struct file *file);
+#endif
 
 #endif /* _V4L2_DEV_H */
index 643bded9f557b5556ea159515b7915cf9016484d..6a3d9a7d302b1494f36e38ecfdf1415d3d24d1e3 100644 (file)
@@ -12,15 +12,15 @@ extern struct neigh_table arp_tbl;
 extern void    arp_init(void);
 extern int     arp_find(unsigned char *haddr, struct sk_buff *skb);
 extern int     arp_ioctl(unsigned int cmd, void __user *arg);
-extern void     arp_send(int type, int ptype, u32 dest_ip, 
-                        struct net_device *dev, u32 src_ip, 
+extern void     arp_send(int type, int ptype, __be32 dest_ip,
+                        struct net_device *dev, __be32 src_ip,
                         unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
 extern int     arp_bind_neighbour(struct dst_entry *dst);
 extern int     arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
 extern void    arp_ifdown(struct net_device *dev);
 
-extern struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
-                                 struct net_device *dev, u32 src_ip,
+extern struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+                                 struct net_device *dev, __be32 src_ip,
                                  unsigned char *dest_hw, unsigned char *src_hw,
                                  unsigned char *target_hw);
 extern void arp_xmit(struct sk_buff *skb);
index b2bdb1aa04291c7104113ef93532dcb26c166a44..10a3eec191fd2bf6110fbd0b4dadaa6fbdf2af8a 100644 (file)
 #define HCI_NOTIFY_VOICE_SETTING       3
 
 /* HCI device types */
-#define HCI_VHCI       0
+#define HCI_VIRTUAL    0
 #define HCI_USB                1
 #define HCI_PCCARD     2
 #define HCI_UART       3
 #define HCI_RS232      4
 #define HCI_PCI                5
+#define HCI_SDIO       6
 
 /* HCI device quirks */
 enum {
@@ -296,6 +297,7 @@ struct hci_cp_host_buffer_size {
 
 /* Link Control */
 #define OGF_LINK_CTL   0x01 
+
 #define OCF_CREATE_CONN                0x0005
 struct hci_cp_create_conn {
        bdaddr_t bdaddr;
@@ -306,6 +308,11 @@ struct hci_cp_create_conn {
        __u8     role_switch;
 } __attribute__ ((packed));
 
+#define OCF_CREATE_CONN_CANCEL 0x0008
+struct hci_cp_create_conn_cancel {
+       bdaddr_t bdaddr;
+} __attribute__ ((packed));
+
 #define OCF_ACCEPT_CONN_REQ    0x0009
 struct hci_cp_accept_conn_req {
        bdaddr_t bdaddr;
@@ -339,6 +346,8 @@ struct hci_cp_inquiry {
 
 #define OCF_INQUIRY_CANCEL     0x0002
 
+#define OCF_EXIT_PERIODIC_INQ  0x0004
+
 #define OCF_LINK_KEY_REPLY     0x000B
 struct hci_cp_link_key_reply {
        bdaddr_t bdaddr;
index d84855fe7336d24938e0aed2055aaf316818cefe..df22efcfcc0b7deceb77ee1094a05d24f00c22d2 100644 (file)
@@ -72,6 +72,9 @@ struct hci_dev {
        __u8            type;
        bdaddr_t        bdaddr;
        __u8            features[8];
+       __u8            hci_ver;
+       __u16           hci_rev;
+       __u16           manufacturer;
        __u16           voice_setting;
 
        __u16           pkt_type;
@@ -165,6 +168,10 @@ struct hci_conn {
        struct timer_list disc_timer;
        struct timer_list idle_timer;
 
+       struct work_struct work;
+
+       struct device   dev;
+
        struct hci_dev  *hdev;
        void            *l2cap_data;
        void            *sco_data;
@@ -309,10 +316,13 @@ static inline void hci_conn_put(struct hci_conn *conn)
        if (atomic_dec_and_test(&conn->refcnt)) {
                unsigned long timeo;
                if (conn->type == ACL_LINK) {
-                       timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
-                       if (!conn->out)
-                               timeo *= 2;
                        del_timer(&conn->idle_timer);
+                       if (conn->state == BT_CONNECTED) {
+                               timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
+                               if (!conn->out)
+                                       timeo *= 2;
+                       } else
+                               timeo = msecs_to_jiffies(10);
                } else
                        timeo = msecs_to_jiffies(10);
                mod_timer(&conn->disc_timer, jiffies + timeo);
@@ -412,6 +422,8 @@ static inline int hci_recv_frame(struct sk_buff *skb)
 
 int hci_register_sysfs(struct hci_dev *hdev);
 void hci_unregister_sysfs(struct hci_dev *hdev);
+void hci_conn_add_sysfs(struct hci_conn *conn);
+void hci_conn_del_sysfs(struct hci_conn *conn);
 
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev))
 
index 2d72496c20294a4890d414415167d5c1455ecb3a..718b4d9c891fb4a0898384cb08655b652ceb532b 100644 (file)
@@ -128,7 +128,9 @@ extern int cipso_v4_rbm_strictvalid;
 
 #ifdef CONFIG_NETLABEL
 int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
-int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head));
+int cipso_v4_doi_remove(u32 doi,
+                       struct netlbl_audit *audit_info,
+                       void (*callback) (struct rcu_head * head));
 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
 int cipso_v4_doi_walk(u32 *skip_cnt,
                     int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
@@ -143,6 +145,7 @@ static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
 }
 
 static inline int cipso_v4_doi_remove(u32 doi,
+                                   struct netlbl_audit *audit_info,
                                    void (*callback) (struct rcu_head * head))
 {
        return 0;
index a8d825f90305a751447c207d140853c9bf79c523..e156e38e4ac37db61db754822e59877299e2f9a0 100644 (file)
@@ -84,7 +84,7 @@ struct dst_entry
 struct dst_ops
 {
        unsigned short          family;
-       unsigned short          protocol;
+       __be16                  protocol;
        unsigned                gc_thresh;
 
        int                     (*gc)(void);
index 3ca210ec1379f549e0e2f0d4e3fd821283b70709..ddf5f3ca1720154be67aca197f628f1e7a83fd08 100644 (file)
@@ -16,8 +16,8 @@ struct flowi {
 
        union {
                struct {
-                       __u32                   daddr;
-                       __u32                   saddr;
+                       __be32                  daddr;
+                       __be32                  saddr;
                        __u32                   fwmark;
                        __u8                    tos;
                        __u8                    scope;
@@ -56,8 +56,8 @@ struct flowi {
 #define FLOWI_FLAG_MULTIPATHOLDROUTE 0x01
        union {
                struct {
-                       __u16   sport;
-                       __u16   dport;
+                       __be16  sport;
+                       __be16  dport;
                } ports;
 
                struct {
@@ -73,7 +73,7 @@ struct flowi {
                        __u8    objname[16]; /* Not zero terminated */
                } dnports;
 
-               __u32           spi;
+               __be32          spi;
 
 #ifdef CONFIG_IPV6_MIP6
                struct {
index 4a38d85e4e25d13534b2840809f62a8e62822bef..b619314218a6368ea50dbad83a1208b21cc23312 100644 (file)
@@ -169,4 +169,22 @@ static inline int genlmsg_len(const struct genlmsghdr *gnlh)
        return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
 }
 
+/**
+ * genlmsg_msg_size - length of genetlink message not including padding
+ * @payload: length of message payload
+ */
+static inline int genlmsg_msg_size(int payload)
+{
+       return GENL_HDRLEN + payload;
+}
+
+/**
+ * genlmsg_total_size - length of genetlink message including padding
+ * @payload: length of message payload
+ */
+static inline int genlmsg_total_size(int payload)
+{
+       return NLMSG_ALIGN(genlmsg_msg_size(payload));
+}
+
 #endif /* __NET_GENERIC_NETLINK_H */
index 05f8ff7d9316fe9d881aec2c0238d44221b14b16..dc09474efcf38e2cb02329a4ef0bf2fd8633bf7f 100644 (file)
@@ -38,7 +38,7 @@ struct dst_entry;
 struct net_proto_family;
 struct sk_buff;
 
-extern void    icmp_send(struct sk_buff *skb_in,  int type, int code, u32 info);
+extern void    icmp_send(struct sk_buff *skb_in,  int type, int code, __be32 info);
 extern int     icmp_rcv(struct sk_buff *skb);
 extern int     icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 extern void    icmp_init(struct net_proto_family *ops);
index de4e83b6da4be2024ec04b1cb5fd53139adbc88e..0bcf9f237e1f0de8fc44bac445c290a9078e041a 100644 (file)
@@ -238,9 +238,9 @@ extern struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
 
 extern struct request_sock *inet_csk_search_req(const struct sock *sk,
                                                struct request_sock ***prevp,
-                                               const __u16 rport,
-                                               const __u32 raddr,
-                                               const __u32 laddr);
+                                               const __be16 rport,
+                                               const __be32 raddr,
+                                               const __be32 laddr);
 extern int inet_csk_bind_conflict(const struct sock *sk,
                                  const struct inet_bind_bucket *tb);
 extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
index b4491c9e2a5a028177913e4f21b45401346e5421..a9eb2eaf094eaf1e9d54c61f070359118309aac8 100644 (file)
@@ -272,42 +272,56 @@ static inline int inet_iif(const struct sk_buff *skb)
 }
 
 extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
-                                          const u32 daddr,
+                                          const __be32 daddr,
                                           const unsigned short hnum,
                                           const int dif);
 
 static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
-                                               u32 daddr, u16 dport, int dif)
+                                               __be32 daddr, __be16 dport, int dif)
 {
        return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
 }
 
 /* Socket demux engine toys. */
+/* What happens here is ugly; there's a pair of adjacent fields in
+   struct inet_sock; __be16 dport followed by __u16 num.  We want to
+   search by pair, so we combine the keys into a single 32bit value
+   and compare with 32bit value read from &...->dport.  Let's at least
+   make sure that it's not mixed with anything else...
+   On 64bit targets we combine comparisons with pair of adjacent __be32
+   fields in the same way.
+*/
+typedef __u32 __bitwise __portpair;
 #ifdef __BIG_ENDIAN
 #define INET_COMBINED_PORTS(__sport, __dport) \
-       (((__u32)(__sport) << 16) | (__u32)(__dport))
+       ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
 #else /* __LITTLE_ENDIAN */
 #define INET_COMBINED_PORTS(__sport, __dport) \
-       (((__u32)(__dport) << 16) | (__u32)(__sport))
+       ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport)))
 #endif
 
 #if (BITS_PER_LONG == 64)
+typedef __u64 __bitwise __addrpair;
 #ifdef __BIG_ENDIAN
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
-       const __u64 __name = (((__u64)(__saddr)) << 32) | ((__u64)(__daddr));
+       const __addrpair __name = (__force __addrpair) ( \
+                                  (((__force __u64)(__be32)(__saddr)) << 32) | \
+                                  ((__force __u64)(__be32)(__daddr)));
 #else /* __LITTLE_ENDIAN */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
-       const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr));
+       const __addrpair __name = (__force __addrpair) ( \
+                                  (((__force __u64)(__be32)(__daddr)) << 32) | \
+                                  ((__force __u64)(__be32)(__saddr)));
 #endif /* __BIG_ENDIAN */
 #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
        (((__sk)->sk_hash == (__hash))                          &&      \
-        ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie))  &&      \
-        ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&      \
+        ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))     &&      \
+        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
        (((__sk)->sk_hash == (__hash))                          &&      \
-        ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&  \
-        ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&   \
+        ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&     \
+        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
@@ -315,13 +329,13 @@ static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
        (((__sk)->sk_hash == (__hash))                          &&      \
         (inet_sk(__sk)->daddr          == (__saddr))           &&      \
         (inet_sk(__sk)->rcv_saddr      == (__daddr))           &&      \
-        ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&      \
+        ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
        (((__sk)->sk_hash == (__hash))                          &&      \
         (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
         (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
-        ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&   \
+        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #endif /* 64-bit arch */
 
@@ -333,12 +347,12 @@ static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
  */
 static inline struct sock *
        __inet_lookup_established(struct inet_hashinfo *hashinfo,
-                                 const u32 saddr, const u16 sport,
-                                 const u32 daddr, const u16 hnum,
+                                 const __be32 saddr, const __be16 sport,
+                                 const __be32 daddr, const u16 hnum,
                                  const int dif)
 {
        INET_ADDR_COOKIE(acookie, saddr, daddr)
-       const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+       const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
        struct sock *sk;
        const struct hlist_node *node;
        /* Optimize here for direct hit, only listening connections can
@@ -370,8 +384,8 @@ hit:
 
 static inline struct sock *
        inet_lookup_established(struct inet_hashinfo *hashinfo,
-                               const u32 saddr, const u16 sport,
-                               const u32 daddr, const u16 dport,
+                               const __be32 saddr, const __be16 sport,
+                               const __be32 daddr, const __be16 dport,
                                const int dif)
 {
        return __inet_lookup_established(hashinfo, saddr, sport, daddr,
@@ -379,8 +393,8 @@ static inline struct sock *
 }
 
 static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
-                                        const u32 saddr, const u16 sport,
-                                        const u32 daddr, const u16 dport,
+                                        const __be32 saddr, const __be16 sport,
+                                        const __be32 daddr, const __be16 dport,
                                         const int dif)
 {
        u16 hnum = ntohs(dport);
@@ -390,8 +404,8 @@ static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
 }
 
 static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
-                                      const u32 saddr, const u16 sport,
-                                      const u32 daddr, const u16 dport,
+                                      const __be32 saddr, const __be16 sport,
+                                      const __be32 daddr, const __be16 dport,
                                       const int dif)
 {
        struct sock *sk;
index f6242710f2ffe208906cdb9b5857dbc3ace00eaa..ce6da97bc8489d4fc1e5d8838f0dd3541a78cfc5 100644 (file)
@@ -36,7 +36,7 @@
  * @ts_needaddr - Need to record addr of outgoing dev
  */
 struct ip_options {
-       __u32           faddr;
+       __be32          faddr;
        unsigned char   optlen;
        unsigned char   srr;
        unsigned char   rr;
@@ -62,9 +62,9 @@ struct inet_request_sock {
        u16                     inet6_rsk_offset;
        /* 2 bytes hole, try to pack */
 #endif
-       u32                     loc_addr;
-       u32                     rmt_addr;
-       u16                     rmt_port;
+       __be32                  loc_addr;
+       __be32                  rmt_addr;
+       __be16                  rmt_port;
        u16                     snd_wscale : 4, 
                                rcv_wscale : 4, 
                                tstamp_ok  : 1,
@@ -110,15 +110,15 @@ struct inet_sock {
        struct ipv6_pinfo       *pinet6;
 #endif
        /* Socket demultiplex comparisons on incoming packets. */
-       __u32                   daddr;
-       __u32                   rcv_saddr;
-       __u16                   dport;
+       __be32                  daddr;
+       __be32                  rcv_saddr;
+       __be16                  dport;
        __u16                   num;
-       __u32                   saddr;
+       __be32                  saddr;
        __s16                   uc_ttl;
        __u16                   cmsg_flags;
        struct ip_options       *opt;
-       __u16                   sport;
+       __be16                  sport;
        __u16                   id;
        __u8                    tos;
        __u8                    mc_ttl;
@@ -129,7 +129,7 @@ struct inet_sock {
                                hdrincl:1,
                                mc_loop:1;
        int                     mc_index;
-       __u32                   mc_addr;
+       __be32                  mc_addr;
        struct ip_mc_socklist   *mc_list;
        struct {
                unsigned int            flags;
@@ -137,7 +137,7 @@ struct inet_sock {
                struct ip_options       *opt;
                struct rtable           *rt;
                int                     length; /* Total length of all frames */
-               u32                     addr;
+               __be32                  addr;
                struct flowi            fl;
        } cork;
 };
@@ -167,10 +167,10 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
 
 extern int inet_sk_rebuild_header(struct sock *sk);
 
-static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
-                                       const __u32 faddr, const __u16 fport)
+static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
+                                       const __be32 faddr, const __be16 fport)
 {
-       unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
+       unsigned int h = ((__force __u32)laddr ^ lport) ^ ((__force __u32)faddr ^ (__force __u32)fport);
        h ^= h >> 16;
        h ^= h >> 8;
        return h;
@@ -179,10 +179,10 @@ static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
 static inline int inet_sk_ehashfn(const struct sock *sk)
 {
        const struct inet_sock *inet = inet_sk(sk);
-       const __u32 laddr = inet->rcv_saddr;
+       const __be32 laddr = inet->rcv_saddr;
        const __u16 lport = inet->num;
-       const __u32 faddr = inet->daddr;
-       const __u16 fport = inet->dport;
+       const __be32 faddr = inet->daddr;
+       const __be16 fport = inet->dport;
 
        return inet_ehashfn(laddr, lport, faddr, fport);
 }
index 600cb543550d8b4f13c7b991b5d8dc308ba144fd..6d14c22a00c5e3e9ab750fb0c68434edba86c853 100644 (file)
@@ -120,10 +120,10 @@ struct inet_timewait_sock {
        unsigned char           tw_rcv_wscale;
        /* Socket demultiplex comparisons on incoming packets. */
        /* these five are in inet_sock */
-       __u16                   tw_sport;
-       __u32                   tw_daddr __attribute__((aligned(INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES)));
-       __u32                   tw_rcv_saddr;
-       __u16                   tw_dport;
+       __be16                  tw_sport;
+       __be32                  tw_daddr __attribute__((aligned(INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES)));
+       __be32                  tw_rcv_saddr;
+       __be16                  tw_dport;
        __u16                   tw_num;
        /* And these are ours. */
        __u8                    tw_ipv6only:1;
@@ -186,7 +186,7 @@ static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk)
        return (struct inet_timewait_sock *)sk;
 }
 
-static inline u32 inet_rcv_saddr(const struct sock *sk)
+static inline __be32 inet_rcv_saddr(const struct sock *sk)
 {
        return likely(sk->sk_state != TCP_TIME_WAIT) ?
                inet_sk(sk)->rcv_saddr : inet_twsk(sk)->tw_rcv_saddr;
index 0965515f40cfabba4e3839007ca51ebac6d22113..925573fd2aed04a91e41c0de1b84bf09f68e06c5 100644 (file)
@@ -22,7 +22,7 @@ struct inet_peer
        unsigned long           dtime;          /* the time of last use of not
                                                 * referenced entries */
        atomic_t                refcnt;
-       __u32                   v4daddr;        /* peer's address */
+       __be32                  v4daddr;        /* peer's address */
        __u16                   avl_height;
        __u16                   ip_id_count;    /* IP ID for the next packet */
        atomic_t                rid;            /* Frag reception counter */
@@ -33,7 +33,7 @@ struct inet_peer
 void                   inet_initpeers(void) __init;
 
 /* can be called with or without local BH being disabled */
-struct inet_peer       *inet_getpeer(__u32 daddr, int create);
+struct inet_peer       *inet_getpeer(__be32 daddr, int create);
 
 extern spinlock_t inet_peer_unused_lock;
 extern struct inet_peer **inet_peer_unused_tailp;
index 98f90840077186243bf910db40452ba7cfa881d9..b6d95e5534016c3a3440525bc4ec00d196fcaeb4 100644 (file)
@@ -45,7 +45,7 @@ struct inet_skb_parm
 
 struct ipcm_cookie
 {
-       u32                     addr;
+       __be32                  addr;
        int                     oif;
        struct ip_options       *opt;
 };
@@ -86,7 +86,7 @@ extern int            igmp_mc_proc_init(void);
  */
 
 extern int             ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
-                                             u32 saddr, u32 daddr,
+                                             __be32 saddr, __be32 daddr,
                                              struct ip_options *opt);
 extern int             ip_rcv(struct sk_buff *skb, struct net_device *dev,
                               struct packet_type *pt, struct net_device *orig_dev);
@@ -335,7 +335,7 @@ extern int ip_net_unreachable(struct sk_buff *skb);
  *     Functions provided by ip_options.c
  */
  
-extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 daddr, struct rtable *rt, int is_frag);
+extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag);
 extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
 extern void ip_options_fragment(struct sk_buff *skb);
 extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb);
@@ -363,8 +363,8 @@ extern int  ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(s
 
 extern int     ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
 extern void    ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
-                             u16 port, u32 info, u8 *payload);
-extern void    ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport,
+                             __be16 port, u32 info, u8 *payload);
+extern void    ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
                               u32 info);
 
 /* sysctl helpers - any sysctl which holds a value that ends up being
index fcc159a4ac17f5fd2c9687abf43f6649079fdc1e..82229146bac7f127156050880edc5c150f0de882 100644 (file)
@@ -30,13 +30,13 @@ struct fib_config {
        u8                      fc_type;
        /* 1 byte unused */
        u32                     fc_table;
-       u32                     fc_dst;
-       u32                     fc_src;
-       u32                     fc_gw;
+       __be32                  fc_dst;
+       __be32                  fc_src;
+       __be32                  fc_gw;
        int                     fc_oif;
        u32                     fc_flags;
        u32                     fc_priority;
-       u32                     fc_prefsrc;
+       __be32                  fc_prefsrc;
        struct nlattr           *fc_mx;
        struct rtnexthop        *fc_mp;
        int                     fc_mx_len;
@@ -63,7 +63,7 @@ struct fib_nh {
        __u32                   nh_tclassid;
 #endif
        int                     nh_oif;
-       u32                     nh_gw;
+       __be32                  nh_gw;
 };
 
 /*
@@ -78,7 +78,7 @@ struct fib_info {
        int                     fib_dead;
        unsigned                fib_flags;
        int                     fib_protocol;
-       u32                     fib_prefsrc;
+       __be32                  fib_prefsrc;
        u32                     fib_priority;
        u32                     fib_metrics[RTAX_MAX];
 #define fib_mtu fib_metrics[RTAX_MTU-1]
@@ -107,8 +107,8 @@ struct fib_result {
        unsigned char   type;
        unsigned char   scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-       __u32           network;
-       __u32           netmask;
+       __be32          network;
+       __be32          netmask;
 #endif
        struct fib_info *fi;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -117,7 +117,7 @@ struct fib_result {
 };
 
 struct fib_result_nl {
-       u32             fl_addr;   /* To be looked up*/ 
+       __be32          fl_addr;   /* To be looked up*/
        u32             fl_fwmark; 
        unsigned char   fl_tos;
        unsigned char   fl_scope;
@@ -222,17 +222,17 @@ extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *ar
 extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
-extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-                              struct net_device *dev, u32 *spec_dst, u32 *itag);
+extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
+                              struct net_device *dev, __be32 *spec_dst, u32 *itag);
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 struct rtentry;
 
 /* Exported by fib_semantics.c */
-extern int ip_fib_check_default(u32 gw, struct net_device *dev);
-extern int fib_sync_down(u32 local, struct net_device *dev, int force);
+extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
+extern int fib_sync_down(__be32 local, struct net_device *dev, int force);
 extern int fib_sync_up(struct net_device *dev);
-extern u32  __fib_res_prefsrc(struct fib_result *res);
+extern __be32  __fib_res_prefsrc(struct fib_result *res);
 
 /* Exported by fib_hash.c */
 extern struct fib_table *fib_hash_init(u32 id);
index ac747b64734c56a9c83054cf5af20e81ed6e19d2..beffdd66ad74f81ac2c5a9d40003ff4ad372102f 100644 (file)
@@ -17,7 +17,7 @@ struct ip_mp_alg_ops {
        void    (*mp_alg_select_route)(const struct flowi *flp,
                                       struct rtable *rth, struct rtable **rp);
        void    (*mp_alg_flush)(void);
-       void    (*mp_alg_set_nhinfo)(__u32 network, __u32 netmask,
+       void    (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
                                     unsigned char prefixlen,
                                     const struct fib_nh *nh);
        void    (*mp_alg_remove)(struct rtable *rth);
@@ -59,7 +59,7 @@ static inline void multipath_flush(void)
 }
 
 static inline void multipath_set_nhinfo(struct rtable *rth,
-                                       __u32 network, __u32 netmask,
+                                       __be32 network, __be32 netmask,
                                        unsigned char prefixlen,
                                        const struct fib_nh *nh)
 {
index 3b57b159b653dfe8dee821fef097ca234f73a2d6..49c717e3b040075562728bbda430369adf89aa93 100644 (file)
 struct ip_vs_service_user {
        /* virtual service addresses */
        u_int16_t               protocol;
-       u_int32_t               addr;           /* virtual ip address */
-       u_int16_t               port;
+       __be32                  addr;           /* virtual ip address */
+       __be16                  port;
        u_int32_t               fwmark;         /* firwall mark of service */
 
        /* virtual service options */
        char                    sched_name[IP_VS_SCHEDNAME_MAXLEN];
        unsigned                flags;          /* virtual service flags */
        unsigned                timeout;        /* persistent timeout in sec */
-       u_int32_t               netmask;        /* persistent netmask */
+       __be32                  netmask;        /* persistent netmask */
 };
 
 
 struct ip_vs_dest_user {
        /* destination server address */
-       u_int32_t               addr;
-       u_int16_t               port;
+       __be32                  addr;
+       __be16                  port;
 
        /* real server options */
        unsigned                conn_flags;     /* connection flags */
@@ -163,15 +163,15 @@ struct ip_vs_getinfo {
 struct ip_vs_service_entry {
        /* which service: user fills in these */
        u_int16_t               protocol;
-       u_int32_t               addr;           /* virtual address */
-       u_int16_t               port;
+       __be32                  addr;           /* virtual address */
+       __be16                  port;
        u_int32_t               fwmark;         /* firwall mark of service */
 
        /* service options */
        char                    sched_name[IP_VS_SCHEDNAME_MAXLEN];
        unsigned                flags;          /* virtual service flags */
        unsigned                timeout;        /* persistent timeout */
-       u_int32_t               netmask;        /* persistent netmask */
+       __be32                  netmask;        /* persistent netmask */
 
        /* number of real servers */
        unsigned int            num_dests;
@@ -182,8 +182,8 @@ struct ip_vs_service_entry {
 
 
 struct ip_vs_dest_entry {
-       u_int32_t               addr;           /* destination address */
-       u_int16_t               port;
+       __be32                  addr;           /* destination address */
+       __be16                  port;
        unsigned                conn_flags;     /* connection flags */
        int                     weight;         /* destination weight */
 
@@ -203,8 +203,8 @@ struct ip_vs_dest_entry {
 struct ip_vs_get_dests {
        /* which service: user fills in these */
        u_int16_t               protocol;
-       u_int32_t               addr;           /* virtual address */
-       u_int16_t               port;
+       __be32                  addr;           /* virtual address */
+       __be16                  port;
        u_int32_t               fwmark;         /* firwall mark of service */
 
        /* number of real servers */
@@ -502,12 +502,12 @@ struct ip_vs_conn {
        struct list_head        c_list;         /* hashed list heads */
 
        /* Protocol, addresses and port numbers */
-       __u32                   caddr;          /* client address */
-       __u32                   vaddr;          /* virtual address */
-       __u32                   daddr;          /* destination address */
-       __u16                   cport;
-       __u16                   vport;
-       __u16                   dport;
+       __be32                   caddr;          /* client address */
+       __be32                   vaddr;          /* virtual address */
+       __be32                   daddr;          /* destination address */
+       __be16                   cport;
+       __be16                   vport;
+       __be16                   dport;
        __u16                   protocol;       /* Which protocol (TCP/UDP) */
 
        /* counter and timer */
@@ -554,12 +554,12 @@ struct ip_vs_service {
        atomic_t                usecnt;   /* use counter */
 
        __u16                   protocol; /* which protocol (TCP/UDP) */
-       __u32                   addr;     /* IP address for virtual service */
-       __u16                   port;     /* port number for the service */
+       __be32                  addr;     /* IP address for virtual service */
+       __be16                  port;     /* port number for the service */
        __u32                   fwmark;   /* firewall mark of the service */
        unsigned                flags;    /* service status flags */
        unsigned                timeout;  /* persistent timeout in ticks */
-       __u32                   netmask;  /* grouping granularity */
+       __be32                  netmask;  /* grouping granularity */
 
        struct list_head        destinations;  /* real server d-linked list */
        __u32                   num_dests;     /* number of servers */
@@ -581,8 +581,8 @@ struct ip_vs_dest {
        struct list_head        n_list;   /* for the dests in the service */
        struct list_head        d_list;   /* for table with all the dests */
 
-       __u32                   addr;           /* IP address of the server */
-       __u16                   port;           /* port number of the server */
+       __be32                  addr;           /* IP address of the server */
+       __be16                  port;           /* port number of the server */
        volatile unsigned       flags;          /* dest status flags */
        atomic_t                conn_flags;     /* flags to copy to conn */
        atomic_t                weight;         /* server weight */
@@ -605,8 +605,8 @@ struct ip_vs_dest {
        /* for virtual service */
        struct ip_vs_service    *svc;           /* service it belongs to */
        __u16                   protocol;       /* which protocol (TCP/UDP) */
-       __u32                   vaddr;          /* virtual IP address */
-       __u16                   vport;          /* virtual port number */
+       __be32                  vaddr;          /* virtual IP address */
+       __be16                  vport;          /* virtual port number */
        __u32                   vfwmark;        /* firewall mark of service */
 };
 
@@ -648,7 +648,7 @@ struct ip_vs_app
        /* members for application incarnations */
        struct list_head        p_list;         /* member in proto app list */
        struct ip_vs_app        *app;           /* its real application */
-       __u16                   port;           /* port number in net order */
+       __be16                  port;           /* port number in net order */
        atomic_t                usecnt;         /* usage counter */
 
        /* output hook: return false if can't linearize. diff set for TCP.  */
@@ -740,11 +740,11 @@ enum {
 };
 
 extern struct ip_vs_conn *ip_vs_conn_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
 extern struct ip_vs_conn *ip_vs_ct_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
 extern struct ip_vs_conn *ip_vs_conn_out_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
 
 /* put back the conn without restarting its timer */
 static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
@@ -752,11 +752,11 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
        atomic_dec(&cp->refcnt);
 }
 extern void ip_vs_conn_put(struct ip_vs_conn *cp);
-extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __u16 cport);
+extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
 
 extern struct ip_vs_conn *
-ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport,
-              __u32 daddr, __u16 dport, unsigned flags,
+ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport,
+              __be32 daddr, __be16 dport, unsigned flags,
               struct ip_vs_dest *dest);
 extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
 
@@ -887,7 +887,7 @@ extern int sysctl_ip_vs_nat_icmp_send;
 extern struct ip_vs_stats ip_vs_stats;
 
 extern struct ip_vs_service *
-ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport);
+ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport);
 
 static inline void ip_vs_service_put(struct ip_vs_service *svc)
 {
@@ -895,7 +895,7 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc)
 }
 
 extern struct ip_vs_dest *
-ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport);
+ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport);
 extern int ip_vs_use_count_inc(void);
 extern void ip_vs_use_count_dec(void);
 extern int ip_vs_control_init(void);
index 72bf47b2a4e0c9bfe34583980f429b1d691557c9..8223c4410b4bdb232c505c0e539a4d2cd7a52d2c 100644 (file)
@@ -318,8 +318,8 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx,
 
 #ifndef __HAVE_ARCH_ADDR_SET
 static inline void ipv6_addr_set(struct in6_addr *addr, 
-                                    __u32 w1, __u32 w2,
-                                    __u32 w3, __u32 w4)
+                                    __be32 w1, __be32 w2,
+                                    __be32 w3, __be32 w4)
 {
        addr->s6_addr32[0] = w1;
        addr->s6_addr32[1] = w2;
@@ -337,7 +337,7 @@ static inline int ipv6_addr_equal(const struct in6_addr *a1,
                a1->s6_addr32[3] == a2->s6_addr32[3]);
 }
 
-static inline int __ipv6_prefix_equal(const u32 *a1, const u32 *a2,
+static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
                                      unsigned int prefixlen)
 {
        unsigned pdw, pbi;
index 1c73bdbc3eb3a76332a6312dee8b1e9d7fd58416..9592c374b41d536e182930ff6f16f7a70d71a813 100644 (file)
 #define IRLAN_SHORT  1
 #define IRLAN_ARRAY  2
 
-#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_MAX_HEADER)
+/* IrLAN sits on top if IrTTP */
+#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER)
+/* 1 byte for the command code and 1 byte for the parameter count */
+#define IRLAN_CMD_HEADER 2
+
+#define IRLAN_STRING_PARAMETER_LEN(name, value) (1 + strlen((name)) + 2 \
+                                               + strlen ((value)))
+#define IRLAN_BYTE_PARAMETER_LEN(name)          (1 + strlen((name)) + 2 + 1)
+#define IRLAN_SHORT_PARAMETER_LEN(name)         (1 + strlen((name)) + 2 + 2)
 
 /*
  *  IrLAN client
index 3452ae257c845d1d3f93460ffc4165756cd9b3f1..9dd54a5002b2af123c3118f09db60838cc05add0 100644 (file)
@@ -74,6 +74,19 @@ struct discovery_t;
 
 #define PF_BIT    0x10 /* Poll/final bit */
 
+/* Some IrLAP field lengths */
+/*
+ * Only baud rate triplet is 4 bytes (PV can be 2 bytes).
+ * All others params (7) are 3 bytes, so that's 7*3 + 1*4 bytes.
+ */
+#define IRLAP_NEGOCIATION_PARAMS_LEN 25
+#define IRLAP_DISCOVERY_INFO_LEN     32
+
+struct disc_frame {
+       __u8 caddr;          /* Connection address */
+       __u8 control;
+} IRDA_PACK;
+
 struct xid_frame {
        __u8  caddr; /* Connection address */
        __u8  control;
@@ -95,11 +108,25 @@ struct test_frame {
 struct ua_frame {
        __u8 caddr;
        __u8 control;
-
        __u32 saddr; /* Source device address */
        __u32 daddr; /* Dest device address */
 } IRDA_PACK;
-       
+
+struct dm_frame {
+       __u8 caddr;          /* Connection address */
+       __u8 control;
+} IRDA_PACK;
+
+struct rd_frame {
+       __u8 caddr;          /* Connection address */
+       __u8 control;
+} IRDA_PACK;
+
+struct rr_frame {
+       __u8 caddr;          /* Connection address */
+       __u8 control;
+} IRDA_PACK;
+
 struct i_frame {
        __u8 caddr;
        __u8 control;
index 11ecfa58a648ff3ad145b8138055f6ac5ad9f54f..e212b9bc2503d64439cd70c3ffa4d080d15751dd 100644 (file)
@@ -48,7 +48,7 @@
 #define DEV_ADDR_ANY  0xffffffff
 
 #define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
-#define LMP_CONTROL_HEADER  4
+#define LMP_CONTROL_HEADER  4    /* LMP_HEADER + opcode + parameter */
 #define LMP_PID_HEADER      1    /* Used by Ultra */
 #define LMP_MAX_HEADER      (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
 
index 6692430063fdd4a9357aae7e964d0698c305e615..c63a58058e2170b811e01c446b8781b5f1faa93e 100644 (file)
  *
  */
 
+/* NetLabel audit information */
+struct netlbl_audit {
+       u32 secid;
+       uid_t loginuid;
+};
+
 /* Domain mapping definition struct */
 struct netlbl_dom_map;
 
 /* Domain mapping operations */
-int netlbl_domhsh_remove(const char *domain);
+int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
 
 /* LSM security attributes */
 struct netlbl_lsm_cache {
index 4ab68a7a636a927e915a66139ace5737cab78ed7..ce5cba19c393cf5206643300263e3971e50661d1 100644 (file)
@@ -831,6 +831,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
 #define NLA_PUT_U32(skb, attrtype, value) \
        NLA_PUT_TYPE(skb, u32, attrtype, value)
 
+#define NLA_PUT_BE32(skb, attrtype, value) \
+       NLA_PUT_TYPE(skb, __be32, attrtype, value)
+
 #define NLA_PUT_U64(skb, attrtype, value) \
        NLA_PUT_TYPE(skb, u64, attrtype, value)
 
@@ -852,6 +855,15 @@ static inline u32 nla_get_u32(struct nlattr *nla)
        return *(u32 *) nla_data(nla);
 }
 
+/**
+ * nla_get_be32 - return payload of __be32 attribute
+ * @nla: __be32 netlink attribute
+ */
+static inline __be32 nla_get_be32(struct nlattr *nla)
+{
+       return *(__be32 *) nla_data(nla);
+}
+
 /**
  * nla_get_u16 - return payload of u16 attribute
  * @nla: u16 netlink attribute
index 7f93ac0e089983a0ceed7e4a11c153f2210ce794..486e37aff06ca28751e2a4a1cbf645b52cd3ebee 100644 (file)
@@ -62,18 +62,18 @@ struct rtable
        __u16                   rt_type;
        __u16                   rt_multipath_alg;
 
-       __u32                   rt_dst; /* Path destination     */
-       __u32                   rt_src; /* Path source          */
+       __be32                  rt_dst; /* Path destination     */
+       __be32                  rt_src; /* Path source          */
        int                     rt_iif;
 
        /* Info on neighbour */
-       __u32                   rt_gateway;
+       __be32                  rt_gateway;
 
        /* Cache lookup keys */
        struct flowi            fl;
 
        /* Miscellaneous cached information */
-       __u32                   rt_spec_dst; /* RFC1122 specific destination */
+       __be32                  rt_spec_dst; /* RFC1122 specific destination */
        struct inet_peer        *peer; /* long-living peer info */
 };
 
@@ -109,18 +109,18 @@ extern struct ip_rt_acct *ip_rt_acct;
 
 struct in_device;
 extern int             ip_rt_init(void);
-extern void            ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
-                                      u32 src, struct net_device *dev);
+extern void            ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
+                                      __be32 src, struct net_device *dev);
 extern void            ip_rt_advice(struct rtable **rp, int advice);
 extern void            rt_cache_flush(int how);
 extern int             __ip_route_output_key(struct rtable **, const struct flowi *flp);
 extern int             ip_route_output_key(struct rtable **, struct flowi *flp);
 extern int             ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
-extern int             ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
+extern int             ip_route_input(struct sk_buff*, __be32 dst, __be32 src, u8 tos, struct net_device *devin);
 extern unsigned short  ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
 extern void            ip_rt_send_redirect(struct sk_buff *skb);
 
-extern unsigned                inet_addr_type(u32 addr);
+extern unsigned                inet_addr_type(__be32 addr);
 extern void            ip_rt_multicast_event(struct in_device *);
 extern int             ip_rt_ioctl(unsigned int cmd, void __user *arg);
 extern void            ip_rt_get_source(u8 *src, struct rtable *rt);
@@ -144,9 +144,9 @@ static inline char rt_tos2priority(u8 tos)
        return ip_tos2prio[IPTOS_TOS(tos)>>1];
 }
 
-static inline int ip_route_connect(struct rtable **rp, u32 dst,
-                                  u32 src, u32 tos, int oif, u8 protocol,
-                                  u16 sport, u16 dport, struct sock *sk)
+static inline int ip_route_connect(struct rtable **rp, __be32 dst,
+                                  __be32 src, u32 tos, int oif, u8 protocol,
+                                  __be16 sport, __be16 dport, struct sock *sk)
 {
        struct flowi fl = { .oif = oif,
                            .nl_u = { .ip4_u = { .daddr = dst,
@@ -172,7 +172,7 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst,
 }
 
 static inline int ip_route_newports(struct rtable **rp, u8 protocol,
-                                   u16 sport, u16 dport, struct sock *sk)
+                                   __be16 sport, __be16 dport, struct sock *sk)
 {
        if (sport != (*rp)->fl.fl_ip_sport ||
            dport != (*rp)->fl.fl_ip_dport) {
index edd4d73ce7f5cb4371430942bc542c4c72df84a1..40bb90ebb2d1b24e11134b08c21ab47f59f68e75 100644 (file)
@@ -665,7 +665,6 @@ struct sock_iocb {
        struct sock             *sk;
        struct scm_cookie       *scm;
        struct msghdr           *msg, async_msg;
-       struct iovec            async_iov;
        struct kiocb            *kiocb;
 };
 
index 11e0b1d6bd4734963a8675b7d4c25aa1867607f0..1e2a4ddec96e3c7cfdf8e5ef2010d234c0673821 100644 (file)
@@ -437,8 +437,8 @@ static inline void xfrm_state_hold(struct xfrm_state *x)
 
 static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
 {
-       __u32 *a1 = token1;
-       __u32 *a2 = token2;
+       __be32 *a1 = token1;
+       __be32 *a2 = token2;
        int pdw;
        int pbi;
 
@@ -450,7 +450,7 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
                        return 0;
 
        if (pbi) {
-               __u32 mask;
+               __be32 mask;
 
                mask = htonl((0xffffffff) << (32 - pbi));
 
@@ -462,9 +462,9 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
 }
 
 static __inline__
-u16 xfrm_flowi_sport(struct flowi *fl)
+__be16 xfrm_flowi_sport(struct flowi *fl)
 {
-       u16 port;
+       __be16 port;
        switch(fl->proto) {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
@@ -487,9 +487,9 @@ u16 xfrm_flowi_sport(struct flowi *fl)
 }
 
 static __inline__
-u16 xfrm_flowi_dport(struct flowi *fl)
+__be16 xfrm_flowi_dport(struct flowi *fl)
 {
-       u16 port;
+       __be16 port;
        switch(fl->proto) {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
@@ -912,7 +912,7 @@ extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
 extern int xfrm_state_update(struct xfrm_state *x);
-extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
+extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
 #ifdef CONFIG_XFRM_SUB_POLICY
 extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
@@ -935,8 +935,8 @@ static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **s
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
-extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
-extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
+extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
+extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
@@ -945,7 +945,7 @@ extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
                            xfrm_address_t *saddr, u8 proto);
@@ -989,7 +989,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
 struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
 void xfrm_policy_flush(u8 type);
 u32 xfrm_get_acqseq(void);
-void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
+void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, 
                                  xfrm_address_t *daddr, xfrm_address_t *saddr, 
                                  int create, unsigned short family);
@@ -1004,7 +1004,7 @@ extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pi
 extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
 
 extern void xfrm_input_init(void);
-extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq);
+extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
 
 extern void xfrm_probe_algs(void);
 extern int xfrm_count_auth_supported(void);
index 895d212864cd99bafaaa0240e17b915133beaad1..b401c82036be216edf1dadf0f1ce01c0b1301891 100644 (file)
@@ -298,9 +298,9 @@ extern int scsi_execute_async(struct scsi_device *sdev,
                              void (*done)(void *, char *, int, int),
                              gfp_t gfp);
 
-static inline void scsi_device_reprobe(struct scsi_device *sdev)
+static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev)
 {
-       device_reprobe(&sdev->sdev_gendev);
+       return device_reprobe(&sdev->sdev_gendev);
 }
 
 static inline unsigned int sdev_channel(struct scsi_device *sdev)
index d04d05adfa9b68ca1ccd08e231a81996a316c714..c247a28259bc77fa453994b3492a457f8b99bb7c 100644 (file)
@@ -6,7 +6,6 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 
-
 #define MSG_SIMPLE_TAG 0x20
 #define MSG_HEAD_TAG   0x21
 #define MSG_ORDERED_TAG        0x22
@@ -14,6 +13,7 @@
 #define SCSI_NO_TAG    (-1)    /* identify no tag in use */
 
 
+#ifdef CONFIG_BLOCK
 
 /**
  * scsi_get_tag_type - get the type of tag the device supports
@@ -100,7 +100,7 @@ static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
        struct scsi_device *sdev = cmd->device;
 
         if (blk_rq_tagged(req)) {
-               if (sdev->ordered_tags && req->flags & REQ_HARDBARRIER)
+               if (sdev->ordered_tags && req->cmd_flags & REQ_HARDBARRIER)
                        *msg++ = MSG_ORDERED_TAG;
                else
                        *msg++ = MSG_SIMPLE_TAG;
@@ -144,4 +144,5 @@ static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth)
        return shost->bqt ? 0 : -ENOMEM;
 }
 
+#endif /* CONFIG_BLOCK */
 #endif /* _SCSI_SCSI_TCQ_H */
index 60d40b34efc0fb79241b08ffaf25a876a563c4ba..afaf3e88e086c8712c7cdf8b4d743e1e3674bd97 100644 (file)
@@ -347,6 +347,7 @@ struct snd_pcm_substream {
        int number;
        char name[32];                  /* substream name */
        int stream;                     /* stream (direction) */
+       char latency_id[20];            /* latency identifier */
        size_t buffer_bytes_max;        /* limit ring buffer size */
        struct snd_dma_buffer dma_buffer;
        unsigned int dma_buf_id;
index 9a7656f0b5ecff5a1d83e3a547ad6aafc08dfdc5..f7a04d0daf077450e95926d68a4cb0ae52547c7e 100644 (file)
@@ -92,7 +92,7 @@ config LOCALVERSION_AUTO
 
 config SWAP
        bool "Support for paging of anonymous memory (swap)"
-       depends on MMU
+       depends on MMU && BLOCK
        default y
        help
          This option allows you to choose whether you want to have support
@@ -202,7 +202,7 @@ config AUDITSYSCALL
          ensure that INOTIFY is configured.
 
 config IKCONFIG
-       bool "Kernel .config support"
+       tristate "Kernel .config support"
        ---help---
          This option enables the complete Linux kernel ".config" file
          contents to be saved in the kernel. It provides documentation
@@ -257,6 +257,18 @@ config CC_OPTIMIZE_FOR_SIZE
 
          If unsure, say N.
 
+config TASK_XACCT
+       bool "Enable extended accounting over taskstats (EXPERIMENTAL)"
+       depends on TASKSTATS
+       help
+         Collect extended task accounting data and send the data
+         to userland for processing over the taskstats interface.
+
+         Say N if unsure.
+
+config SYSCTL
+       bool
+
 menuconfig EMBEDDED
        bool "Configure standard kernel features (for small systems)"
        help
@@ -272,22 +284,22 @@ config UID16
        help
          This enables the legacy 16-bit UID syscall wrappers.
 
-config SYSCTL
-       bool "Sysctl support" if EMBEDDED
-       default y
+config SYSCTL_SYSCALL
+       bool "Sysctl syscall support" if EMBEDDED
+       default n
+       select SYSCTL
        ---help---
-         The sysctl interface provides a means of dynamically changing
-         certain kernel parameters and variables on the fly without requiring
-         a recompile of the kernel or reboot of the system.  The primary
-         interface consists of a system call, but if you say Y to "/proc
-         file system support", a tree of modifiable sysctl entries will be
-         generated beneath the /proc/sys directory. They are explained in the
-         files in <file:Documentation/sysctl/>.  Note that enabling this
-         option will enlarge the kernel by at least 8 KB.
-
-         As it is generally a good thing, you should say Y here unless
-         building a kernel for install/rescue disks or your system is very
-         limited in memory.
+         Enable the deprecated sysctl system call.  sys_sysctl uses
+         binary paths that have been found to be a major pain to maintain
+         and use.  The interface in /proc/sys is now the primary and what
+         everyone uses.
+
+         Nothing has been using the binary sysctl interface for some
+         time now so nothing should break if you disable sysctl syscall
+         support, and your kernel will get marginally smaller.
+
+         Unless you have an application that uses the sys_sysctl interface
+         you should probably say N here.
 
 config KALLSYMS
         bool "Load all symbols for debugging/kksymoops" if EMBEDDED
index b290aadb1d3f2a0b1448a06df90bb05f75aed42f..dc1ec0803ef9b93b76c27b9db3a9d3e741f98280 100644 (file)
@@ -285,7 +285,11 @@ void __init mount_block_root(char *name, int flags)
 {
        char *fs_names = __getname();
        char *p;
+#ifdef CONFIG_BLOCK
        char b[BDEVNAME_SIZE];
+#else
+       const char *b = name;
+#endif
 
        get_fs_names(fs_names);
 retry:
@@ -304,7 +308,9 @@ retry:
                 * Allow the user to distinguish between failed sys_open
                 * and bad superblock on root device.
                 */
+#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");
@@ -316,7 +322,10 @@ retry:
        for (p = fs_names; *p; p += strlen(p)+1)
                printk(" %s", p);
        printk("\n");
-       panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b));
+#ifdef CONFIG_BLOCK
+       __bdevname(ROOT_DEV, b);
+#endif
+       panic("VFS: Unable to mount root fs on %s", b);
 out:
        putname(fs_names);
 }
@@ -387,8 +396,10 @@ void __init mount_root(void)
                        change_floppy("root floppy");
        }
 #endif
+#ifdef CONFIG_BLOCK
        create_dev("/dev/root", ROOT_DEV);
        mount_block_root("/dev/root", root_mountflags);
+#endif
 }
 
 /*
index 913e48d658ee1de1938edf62dfee2d497b02448f..0766e69712b2a86efa74caf3c5bd487bbbcd3753 100644 (file)
@@ -127,6 +127,18 @@ static char *ramdisk_execute_command;
 /* Setup configured maximum number of CPUs to activate */
 static unsigned int max_cpus = NR_CPUS;
 
+/*
+ * If set, this is an indication to the drivers that reset the underlying
+ * device before going ahead with the initialization otherwise driver might
+ * rely on the BIOS and skip the reset operation.
+ *
+ * This is useful if kernel is booting in an unreliable environment.
+ * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
+ * skipped and devices will be in unknown state.
+ */
+unsigned int reset_devices;
+EXPORT_SYMBOL(reset_devices);
+
 /*
  * Setup routine for controlling SMP activation
  *
@@ -153,6 +165,14 @@ static int __init maxcpus(char *str)
 
 __setup("maxcpus=", maxcpus);
 
+static int __init set_reset_devices(char *str)
+{
+       reset_devices = 1;
+       return 1;
+}
+
+__setup("reset_devices", set_reset_devices);
+
 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 static const char *panic_later, *panic_param;
index 02e6f679897282d4d16c73ed70ccb9f5e98857e5..d75d0ba833609bd58c6fc7a692f8b934f7b735ff 100644 (file)
@@ -115,7 +115,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mtime = inode->i_ctime = inode->i_atime =
                                CURRENT_TIME;
@@ -169,7 +168,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                        /* all is ok */
                        info->user = get_uid(u);
                } else if (S_ISDIR(mode)) {
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        /* Some things misbehave if size == 0 on a directory */
                        inode->i_size = 2 * DIRENT_SIZE;
                        inode->i_op = &mqueue_dir_inode_operations;
@@ -308,7 +307,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 
        dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
        dir->i_size -= DIRENT_SIZE;
-       inode->i_nlink--;
+       drop_nlink(inode);
        dput(dentry);
        return 0;
 }
@@ -1275,10 +1274,7 @@ out_filesystem:
 out_sysctl:
        if (mq_sysctl_table)
                unregister_sysctl_table(mq_sysctl_table);
-       if (kmem_cache_destroy(mqueue_inode_cachep)) {
-               printk(KERN_INFO
-                       "mqueue_inode_cache: not all structures were freed\n");
-       }
+       kmem_cache_destroy(mqueue_inode_cachep);
        return error;
 }
 
index d62ec66c1af28246946d9a21a52f5fc6df706701..aacaafb28b9d7dca51c09d15af71c119ed51bbf1 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
+           hrtimer.o rwsem.o latency.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
@@ -49,7 +49,7 @@ obj-$(CONFIG_SECCOMP) += seccomp.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
-obj-$(CONFIG_TASKSTATS) += taskstats.o
+obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
 
 ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
index 2a7c933651c7c03b0777fcecdc1ea3e06fed259b..0aad5ca36a8125e205e85978aa32e8712ddc957a 100644 (file)
@@ -483,10 +483,14 @@ static void do_acct_process(struct file *file)
        ac.ac_ppid = current->parent->tgid;
 #endif
 
-       read_lock(&tasklist_lock);      /* pin current->signal */
+       mutex_lock(&tty_mutex);
+       /* FIXME: Whoever is responsible for current->signal locking needs
+          to use the same locking all over the kernel and document it */
+       read_lock(&tasklist_lock);
        ac.ac_tty = current->signal->tty ?
                old_encode_dev(tty_devnum(current->signal->tty)) : 0;
        read_unlock(&tasklist_lock);
+       mutex_unlock(&tty_mutex);
 
        spin_lock_irq(&current->sighand->siglock);
        ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
@@ -598,33 +602,3 @@ void acct_process(void)
        do_acct_process(file);
        fput(file);
 }
-
-
-/**
- * acct_update_integrals - update mm integral fields in task_struct
- * @tsk: task_struct for accounting
- */
-void acct_update_integrals(struct task_struct *tsk)
-{
-       if (likely(tsk->mm)) {
-               long delta =
-                       cputime_to_jiffies(tsk->stime) - tsk->acct_stimexpd;
-
-               if (delta == 0)
-                       return;
-               tsk->acct_stimexpd = tsk->stime;
-               tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
-               tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
-       }
-}
-
-/**
- * acct_clear_integrals - clear the mm integral fields in task_struct
- * @tsk: task_struct whose accounting fields are cleared
- */
-void acct_clear_integrals(struct task_struct *tsk)
-{
-       tsk->acct_stimexpd = 0;
-       tsk->acct_rss_mem1 = 0;
-       tsk->acct_vm_mem1 = 0;
-}
index fb83c5cb8c324226c47fb18ca7c708e61ef4421b..105147631753f1b4f68fc17878a0e4531b436593 100644 (file)
@@ -817,6 +817,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                audit_log_format(ab, " success=%s exit=%ld", 
                                 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
                                 context->return_code);
+
+       mutex_lock(&tty_mutex);
        if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
                tty = tsk->signal->tty->name;
        else
@@ -838,6 +840,9 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->gid,
                  context->euid, context->suid, context->fsuid,
                  context->egid, context->sgid, context->fsgid, tty);
+
+       mutex_unlock(&tty_mutex);
+
        audit_log_task_info(ab, tsk);
        if (context->filterkey) {
                audit_log_format(ab, " key=");
index c7685ad00a97c4ddfd2f47029f0b5b4342da80be..edb845a6e84ae5e649ece39e18384620c5dac74e 100644 (file)
@@ -133,7 +133,7 @@ static inline int cap_set_all(kernel_cap_t *effective,
      int found = 0;
 
      do_each_thread(g, target) {
-             if (target == current || target->pid == 1)
+             if (target == current || is_init(target))
                      continue;
              found = 1;
             if (security_capset_check(target, effective, inheritable,
index 126dee9530aacc13a37d304ee8a4b54f69355a82..b4fbd838cd775ac9007af6e7d566652e1ad629de 100644 (file)
 #include <linux/security.h>
 #include <linux/timex.h>
 #include <linux/migrate.h>
+#include <linux/posix-timers.h>
 
 #include <asm/uaccess.h>
 
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
 int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
 {
        return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
@@ -601,6 +604,30 @@ long compat_sys_clock_getres(clockid_t which_clock,
        return err;
 } 
 
+static long compat_clock_nanosleep_restart(struct restart_block *restart)
+{
+       long err;
+       mm_segment_t oldfs;
+       struct timespec tu;
+       struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1);
+
+       restart->arg1 = (unsigned long) &tu;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       err = clock_nanosleep_restart(restart);
+       set_fs(oldfs);
+
+       if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+           put_compat_timespec(&tu, rmtp))
+               return -EFAULT;
+
+       if (err == -ERESTART_RESTARTBLOCK) {
+               restart->fn = compat_clock_nanosleep_restart;
+               restart->arg1 = (unsigned long) rmtp;
+       }
+       return err;
+}
+
 long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
                            struct compat_timespec __user *rqtp,
                            struct compat_timespec __user *rmtp)
@@ -608,6 +635,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
        long err;
        mm_segment_t oldfs;
        struct timespec in, out; 
+       struct restart_block *restart;
 
        if (get_compat_timespec(&in, rqtp)) 
                return -EFAULT;
@@ -618,9 +646,16 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
                                  (struct timespec __user *) &in,
                                  (struct timespec __user *) &out);
        set_fs(oldfs);
+
        if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
            put_compat_timespec(&out, rmtp))
                return -EFAULT;
+
+       if (err == -ERESTART_RESTARTBLOCK) {
+               restart = &current_thread_info()->restart_block;
+               restart->fn = compat_clock_nanosleep_restart;
+               restart->arg1 = (unsigned long) rmtp;
+       }
        return err;     
 } 
 
index cff41511269f0dbb891fd9f460dfa2fd70c44d7a..9d850ae13b1b61e763d09fc8231c33d1d6e43139 100644 (file)
@@ -240,7 +240,7 @@ static struct super_block *cpuset_sb;
  * A cpuset can only be deleted if both its 'count' of using tasks
  * is zero, and its list of 'children' cpusets is empty.  Since all
  * tasks in the system use _some_ cpuset, and since there is always at
- * least one task in the system (init, pid == 1), therefore, top_cpuset
+ * least one task in the system (init), therefore, top_cpuset
  * always has either children cpusets and/or using tasks.  So we don't
  * need a special hack to ensure that top_cpuset cannot be deleted.
  *
@@ -289,7 +289,6 @@ static struct inode *cpuset_new_inode(mode_t mode)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
@@ -378,7 +377,7 @@ static int cpuset_fill_super(struct super_block *sb, void *unused_data,
                inode->i_op = &simple_dir_inode_operations;
                inode->i_fop = &simple_dir_operations;
                /* directories start off with i_nlink == 2 (for "." entry) */
-               inode->i_nlink++;
+               inc_nlink(inode);
        } else {
                return -ENOMEM;
        }
@@ -913,6 +912,10 @@ static int update_nodemask(struct cpuset *cs, char *buf)
        int fudge;
        int retval;
 
+       /* top_cpuset.mems_allowed tracks node_online_map; it's read-only */
+       if (cs == &top_cpuset)
+               return -EACCES;
+
        trialcs = *cs;
        retval = nodelist_parse(buf, trialcs.mems_allowed);
        if (retval < 0)
@@ -1222,7 +1225,12 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
 
        task_lock(tsk);
        oldcs = tsk->cpuset;
-       if (!oldcs) {
+       /*
+        * After getting 'oldcs' cpuset ptr, be sure still not exiting.
+        * If 'oldcs' might be the top_cpuset due to the_top_cpuset_hack
+        * then fail this attach_task(), to avoid breaking top_cpuset.count.
+        */
+       if (tsk->flags & PF_EXITING) {
                task_unlock(tsk);
                mutex_unlock(&callback_mutex);
                put_task_struct(tsk);
@@ -1557,7 +1565,7 @@ static int cpuset_create_file(struct dentry *dentry, int mode)
                inode->i_fop = &simple_dir_operations;
 
                /* start off with i_nlink == 2 (for "." entry) */
-               inode->i_nlink++;
+               inc_nlink(inode);
        } else if (S_ISREG(mode)) {
                inode->i_size = 0;
                inode->i_fop = &cpuset_file_operations;
@@ -1590,7 +1598,7 @@ static int cpuset_create_dir(struct cpuset *cs, const char *name, int mode)
        error = cpuset_create_file(dentry, S_IFDIR | mode);
        if (!error) {
                dentry->d_fsdata = cs;
-               parent->d_inode->i_nlink++;
+               inc_nlink(parent->d_inode);
                cs->dentry = dentry;
        }
        dput(dentry);
@@ -2025,7 +2033,7 @@ int __init cpuset_init(void)
        }
        root = cpuset_mount->mnt_sb->s_root;
        root->d_fsdata = &top_cpuset;
-       root->d_inode->i_nlink++;
+       inc_nlink(root->d_inode);
        top_cpuset.dentry = root;
        root->d_inode->i_op = &cpuset_dir_inode_operations;
        number_of_cpusets = 1;
@@ -2037,33 +2045,104 @@ out:
        return err;
 }
 
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_MEMORY_HOTPLUG)
 /*
- * The top_cpuset tracks what CPUs and Memory Nodes are online,
- * period.  This is necessary in order to make cpusets transparent
- * (of no affect) on systems that are actively using CPU hotplug
- * but making no active use of cpusets.
- *
- * This handles CPU hotplug (cpuhp) events.  If someday Memory
- * Nodes can be hotplugged (dynamically changing node_online_map)
- * then we should handle that too, perhaps in a similar way.
+ * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs
+ * or memory nodes, we need to walk over the cpuset hierarchy,
+ * removing that CPU or node from all cpusets.  If this removes the
+ * last CPU or node from a cpuset, then the guarantee_online_cpus()
+ * or guarantee_online_mems() code will use that emptied cpusets
+ * parent online CPUs or nodes.  Cpusets that were already empty of
+ * CPUs or nodes are left empty.
+ *
+ * This routine is intentionally inefficient in a couple of regards.
+ * It will check all cpusets in a subtree even if the top cpuset of
+ * the subtree has no offline CPUs or nodes.  It checks both CPUs and
+ * nodes, even though the caller could have been coded to know that
+ * only one of CPUs or nodes needed to be checked on a given call.
+ * This was done to minimize text size rather than cpu cycles.
+ *
+ * Call with both manage_mutex and callback_mutex held.
+ *
+ * Recursive, on depth of cpuset subtree.
  */
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int cpuset_handle_cpuhp(struct notifier_block *nb,
-                               unsigned long phase, void *cpu)
+static void guarantee_online_cpus_mems_in_subtree(const struct cpuset *cur)
+{
+       struct cpuset *c;
+
+       /* Each of our child cpusets mems must be online */
+       list_for_each_entry(c, &cur->children, sibling) {
+               guarantee_online_cpus_mems_in_subtree(c);
+               if (!cpus_empty(c->cpus_allowed))
+                       guarantee_online_cpus(c, &c->cpus_allowed);
+               if (!nodes_empty(c->mems_allowed))
+                       guarantee_online_mems(c, &c->mems_allowed);
+       }
+}
+
+/*
+ * The cpus_allowed and mems_allowed nodemasks in the top_cpuset track
+ * cpu_online_map and node_online_map.  Force the top cpuset to track
+ * whats online after any CPU or memory node hotplug or unplug event.
+ *
+ * To ensure that we don't remove a CPU or node from the top cpuset
+ * that is currently in use by a child cpuset (which would violate
+ * the rule that cpusets must be subsets of their parent), we first
+ * call the recursive routine guarantee_online_cpus_mems_in_subtree().
+ *
+ * Since there are two callers of this routine, one for CPU hotplug
+ * events and one for memory node hotplug events, we could have coded
+ * two separate routines here.  We code it as a single common routine
+ * in order to minimize text size.
+ */
+
+static void common_cpu_mem_hotplug_unplug(void)
 {
        mutex_lock(&manage_mutex);
        mutex_lock(&callback_mutex);
 
+       guarantee_online_cpus_mems_in_subtree(&top_cpuset);
        top_cpuset.cpus_allowed = cpu_online_map;
+       top_cpuset.mems_allowed = node_online_map;
 
        mutex_unlock(&callback_mutex);
        mutex_unlock(&manage_mutex);
+}
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * The top_cpuset tracks what CPUs and Memory Nodes are online,
+ * period.  This is necessary in order to make cpusets transparent
+ * (of no affect) on systems that are actively using CPU hotplug
+ * but making no active use of cpusets.
+ *
+ * This routine ensures that top_cpuset.cpus_allowed tracks
+ * cpu_online_map on each CPU hotplug (cpuhp) event.
+ */
 
+static int cpuset_handle_cpuhp(struct notifier_block *nb,
+                               unsigned long phase, void *cpu)
+{
+       common_cpu_mem_hotplug_unplug();
        return 0;
 }
 #endif
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * Keep top_cpuset.mems_allowed tracking node_online_map.
+ * Call this routine anytime after you change node_online_map.
+ * See also the previous routine cpuset_handle_cpuhp().
+ */
+
+void cpuset_track_online_nodes()
+{
+       common_cpu_mem_hotplug_unplug();
+}
+#endif
+
 /**
  * cpuset_init_smp - initialize cpus_allowed
  *
index d891883420f7bfd64b0cbc29b7003fcd57d526ef..3b47f26985f2bed8a2895a3974ff413c086409f5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/security.h>
 #include <linux/cpu.h>
 #include <linux/acct.h>
+#include <linux/tsacct_kern.h>
 #include <linux/file.h>
 #include <linux/binfmts.h>
 #include <linux/ptrace.h>
@@ -38,6 +39,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/audit.h> /* for audit_free() */
 #include <linux/resource.h>
+#include <linux/blkdev.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -219,7 +221,7 @@ static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task)
        do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
                if (p == ignored_task
                                || p->exit_state
-                               || p->real_parent->pid == 1)
+                               || is_init(p->real_parent))
                        continue;
                if (process_group(p->real_parent) != pgrp
                            && p->real_parent->signal->session == p->signal->session) {
@@ -249,17 +251,6 @@ static int has_stopped_jobs(int pgrp)
        do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
                if (p->state != TASK_STOPPED)
                        continue;
-
-               /* If p is stopped by a debugger on a signal that won't
-                  stop it, then don't count p as stopped.  This isn't
-                  perfect but it's a good approximation.  */
-               if (unlikely (p->ptrace)
-                   && p->exit_code != SIGSTOP
-                   && p->exit_code != SIGTSTP
-                   && p->exit_code != SIGTTOU
-                   && p->exit_code != SIGTTIN)
-                       continue;
-
                retval = 1;
                break;
        } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
@@ -292,9 +283,7 @@ static void reparent_to_init(void)
        /* Set the exit signal to SIGCHLD so we signal init on exit */
        current->exit_signal = SIGCHLD;
 
-       if ((current->policy == SCHED_NORMAL ||
-                       current->policy == SCHED_BATCH)
-                               && (task_nice(current) < 0))
+       if (!has_rt_policy(current) && (task_nice(current) < 0))
                set_user_nice(current, 0);
        /* cpus_allowed? */
        /* rt_priority? */
@@ -487,6 +476,18 @@ void fastcall put_files_struct(struct files_struct *files)
 
 EXPORT_SYMBOL(put_files_struct);
 
+void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
+{
+       struct files_struct *old;
+
+       old = tsk->files;
+       task_lock(tsk);
+       tsk->files = files;
+       task_unlock(tsk);
+       put_files_struct(old);
+}
+EXPORT_SYMBOL(reset_files_struct);
+
 static inline void __exit_files(struct task_struct *tsk)
 {
        struct files_struct * files = tsk->files;
@@ -954,15 +955,15 @@ fastcall NORET_TYPE void do_exit(long code)
        if (tsk->splice_pipe)
                __free_pipe_info(tsk->splice_pipe);
 
-       /* PF_DEAD causes final put_task_struct after we schedule. */
        preempt_disable();
-       BUG_ON(tsk->flags & PF_DEAD);
-       tsk->flags |= PF_DEAD;
+       /* causes final put_task_struct in finish_task_switch(). */
+       tsk->state = TASK_DEAD;
 
        schedule();
        BUG();
        /* Avoid "noreturn function does return".  */
-       for (;;) ;
+       for (;;)
+               cpu_relax();    /* For when BUG is null */
 }
 
 EXPORT_SYMBOL_GPL(do_exit);
@@ -971,7 +972,7 @@ NORET_TYPE void complete_and_exit(struct completion *comp, long code)
 {
        if (comp)
                complete(comp);
-       
+
        do_exit(code);
 }
 
index a0dad84567c9c7effe6b46f98bf077ee5d9f5e22..89f666491d1f91d2ff2c7f4090003465299bcb6a 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/profile.h>
 #include <linux/rmap.h>
 #include <linux/acct.h>
+#include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
@@ -183,7 +184,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        /* One for us, one for whoever does the "release_task()" (usually parent) */
        atomic_set(&tsk->usage,2);
        atomic_set(&tsk->fs_excl, 0);
+#ifdef CONFIG_BLK_DEV_IO_TRACE
        tsk->btrace_seq = 0;
+#endif
        tsk->splice_pipe = NULL;
        return tsk;
 }
@@ -1061,7 +1064,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 #endif
 #ifdef CONFIG_TRACE_IRQFLAGS
        p->irq_events = 0;
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+       p->hardirqs_enabled = 1;
+#else
        p->hardirqs_enabled = 0;
+#endif
        p->hardirq_enable_ip = 0;
        p->hardirq_enable_event = 0;
        p->hardirq_disable_ip = _THIS_IP_;
@@ -1144,7 +1151,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
        /* Our parent execution domain becomes current domain
           These must match for thread signalling to apply */
-          
        p->parent_exec_id = p->self_exec_id;
 
        /* ok, now we should be set up.. */
@@ -1167,6 +1173,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        /* Need tasklist lock for parent etc handling! */
        write_lock_irq(&tasklist_lock);
 
+       /* for sys_ioprio_set(IOPRIO_WHO_PGRP) */
+       p->ioprio = current->ioprio;
+
        /*
         * The task hasn't been attached yet, so its cpus_allowed mask will
         * not be changed, nor will its assigned CPU.
@@ -1226,11 +1235,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                }
        }
 
-       /*
-        * inherit ioprio
-        */
-       p->ioprio = current->ioprio;
-
        if (likely(p->pid)) {
                add_parent(p);
                if (unlikely(p->ptrace & PT_PTRACED))
index 9d260e838cffdca6f951d6625626ab9d62f19d81..4b6770e9806d0c080ef5f9bd542ddb778ddbcff2 100644 (file)
@@ -389,7 +389,7 @@ static struct task_struct * futex_find_get_task(pid_t pid)
 {
        struct task_struct *p;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_task_by_pid(pid);
        if (!p)
                goto out_unlock;
@@ -403,7 +403,7 @@ static struct task_struct * futex_find_get_task(pid_t pid)
        }
        get_task_struct(p);
 out_unlock:
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return p;
 }
@@ -1624,7 +1624,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
                struct task_struct *p;
 
                ret = -ESRCH;
-               read_lock(&tasklist_lock);
+               rcu_read_lock();
                p = find_task_by_pid(pid);
                if (!p)
                        goto err_unlock;
@@ -1633,7 +1633,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
                                !capable(CAP_SYS_PTRACE))
                        goto err_unlock;
                head = p->robust_list;
-               read_unlock(&tasklist_lock);
+               rcu_read_unlock();
        }
 
        if (put_user(sizeof(*head), len_ptr))
@@ -1641,7 +1641,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
        return put_user(head, head_ptr);
 
 err_unlock:
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return ret;
 }
index 21c38a7e666ba74f373b9693770af4b22b63a685..d0ba190dfeb6b9ae81c98f135515b19a145f8206 100644 (file)
@@ -693,7 +693,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
        return t->task == NULL;
 }
 
-static long __sched nanosleep_restart(struct restart_block *restart)
+long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
        struct hrtimer_sleeper t;
        struct timespec __user *rmtp;
@@ -702,13 +702,13 @@ static long __sched nanosleep_restart(struct restart_block *restart)
 
        restart->fn = do_no_restart_syscall;
 
-       hrtimer_init(&t.timer, restart->arg3, HRTIMER_ABS);
-       t.timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
+       hrtimer_init(&t.timer, restart->arg0, HRTIMER_ABS);
+       t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
 
        if (do_nanosleep(&t, HRTIMER_ABS))
                return 0;
 
-       rmtp = (struct timespec __user *) restart->arg2;
+       rmtp = (struct timespec __user *) restart->arg1;
        if (rmtp) {
                time = ktime_sub(t.timer.expires, t.timer.base->get_time());
                if (time.tv64 <= 0)
@@ -718,7 +718,7 @@ static long __sched nanosleep_restart(struct restart_block *restart)
                        return -EFAULT;
        }
 
-       restart->fn = nanosleep_restart;
+       restart->fn = hrtimer_nanosleep_restart;
 
        /* The other values in restart are already filled in */
        return -ERESTART_RESTARTBLOCK;
@@ -751,11 +751,11 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
        }
 
        restart = &current_thread_info()->restart_block;
-       restart->fn = nanosleep_restart;
-       restart->arg0 = t.timer.expires.tv64 & 0xFFFFFFFF;
-       restart->arg1 = t.timer.expires.tv64 >> 32;
-       restart->arg2 = (unsigned long) rmtp;
-       restart->arg3 = (unsigned long) t.timer.base->index;
+       restart->fn = hrtimer_nanosleep_restart;
+       restart->arg0 = (unsigned long) t.timer.base->index;
+       restart->arg1 = (unsigned long) rmtp;
+       restart->arg2 = t.timer.expires.tv64 & 0xFFFFFFFF;
+       restart->arg3 = t.timer.expires.tv64 >> 32;
 
        return -ERESTART_RESTARTBLOCK;
 }
index ac1f850d4937e5a020f22132a83da5a49fe9a3bf..736cb0bd498f8ff5c7a50d8b60e3130da43d9d7f 100644 (file)
@@ -40,10 +40,6 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
        spin_lock_irqsave(&desc->lock, flags);
        irq_chip_set_defaults(chip);
        desc->chip = chip;
-       /*
-        * For compatibility only:
-        */
-       desc->chip = chip;
        spin_unlock_irqrestore(&desc->lock, flags);
 
        return 0;
@@ -146,7 +142,7 @@ static void default_disable(unsigned int irq)
        struct irq_desc *desc = irq_desc + irq;
 
        if (!(desc->status & IRQ_DELAYED_DISABLE))
-               irq_desc[irq].chip->mask(irq);
+               desc->chip->mask(irq);
 }
 
 /*
index 50087ecf337ea17e5429188688187b6623a57f20..fcdd5d2bc3f4b47b57854c41a1cec882939c02ed 100644 (file)
@@ -40,7 +40,7 @@ struct resource crashk_res = {
 
 int kexec_should_crash(struct task_struct *p)
 {
-       if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
+       if (in_interrupt() || !p->pid || is_init(p) || panic_on_oops)
                return 1;
        return 0;
 }
@@ -995,7 +995,8 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
        image = xchg(dest_image, image);
 
 out:
-       xchg(&kexec_lock, 0); /* Release the mutex */
+       locked = xchg(&kexec_lock, 0); /* Release the mutex */
+       BUG_ON(!locked);
        kimage_free(image);
 
        return result;
@@ -1061,7 +1062,8 @@ void crash_kexec(struct pt_regs *regs)
                        machine_crash_shutdown(&fixed_regs);
                        machine_kexec(kexec_crash_image);
                }
-               xchg(&kexec_lock, 0);
+               locked = xchg(&kexec_lock, 0);
+               BUG_ON(!locked);
        }
 }
 
index 64ab045c3d9d3a72126971f51c0081e199a4468d..5d1d907378a299ad6c6aab16b15d55d1248f296e 100644 (file)
@@ -122,6 +122,13 @@ unsigned int __kfifo_put(struct kfifo *fifo,
 
        len = min(len, fifo->size - fifo->in + fifo->out);
 
+       /*
+        * Ensure that we sample the fifo->out index -before- we
+        * start putting bytes into the kfifo.
+        */
+
+       smp_mb();
+
        /* first put the data starting from fifo->in to buffer end */
        l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
        memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
@@ -129,6 +136,13 @@ unsigned int __kfifo_put(struct kfifo *fifo,
        /* then put the rest (if any) at the beginning of the buffer */
        memcpy(fifo->buffer, buffer + l, len - l);
 
+       /*
+        * Ensure that we add the bytes to the kfifo -before-
+        * we update the fifo->in index.
+        */
+
+       smp_wmb();
+
        fifo->in += len;
 
        return len;
@@ -154,6 +168,13 @@ unsigned int __kfifo_get(struct kfifo *fifo,
 
        len = min(len, fifo->in - fifo->out);
 
+       /*
+        * Ensure that we sample the fifo->in index -before- we
+        * start removing bytes from the kfifo.
+        */
+
+       smp_rmb();
+
        /* first get the data from fifo->out until the end of the buffer */
        l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
        memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
@@ -161,6 +182,13 @@ unsigned int __kfifo_get(struct kfifo *fifo,
        /* then get the rest (if any) from the beginning of the buffer */
        memcpy(buffer + l, fifo->buffer, len - l);
 
+       /*
+        * Ensure that we remove the bytes from the kfifo -before-
+        * we update the fifo->out index.
+        */
+
+       smp_mb();
+
        fifo->out += len;
 
        return len;
index 5c470c57fb57c0997bd5f76e24a1bb5cc24e687b..f8121b95183f3c58502e1cacf6b25c1285ebecc3 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mount.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/resource.h>
 #include <asm/uaccess.h>
 
 extern int max_threads;
@@ -122,6 +123,7 @@ struct subprocess_info {
        struct key *ring;
        int wait;
        int retval;
+       struct file *stdin;
 };
 
 /*
@@ -145,12 +147,29 @@ static int ____call_usermodehelper(void *data)
 
        key_put(old_session);
 
+       /* Install input pipe when needed */
+       if (sub_info->stdin) {
+               struct files_struct *f = current->files;
+               struct fdtable *fdt;
+               /* no races because files should be private here */
+               sys_close(0);
+               fd_install(0, sub_info->stdin);
+               spin_lock(&f->file_lock);
+               fdt = files_fdtable(f);
+               FD_SET(0, fdt->open_fds);
+               FD_CLR(0, fdt->close_on_exec);
+               spin_unlock(&f->file_lock);
+
+               /* and disallow core files too */
+               current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0};
+       }
+
        /* We can run anywhere, unlike our parent keventd(). */
        set_cpus_allowed(current, CPU_MASK_ALL);
 
        retval = -EPERM;
        if (current->fs->root)
-               retval = execve(sub_info->path, sub_info->argv,sub_info->envp);
+               retval = execve(sub_info->path, sub_info->argv, sub_info->envp);
 
        /* Exec failed? */
        sub_info->retval = retval;
@@ -176,6 +195,8 @@ static int wait_for_helper(void *data)
        if (pid < 0) {
                sub_info->retval = pid;
        } else {
+               int ret;
+
                /*
                 * Normally it is bogus to call wait4() from in-kernel because
                 * wait4() wants to write the exit code to a userspace address.
@@ -185,7 +206,15 @@ static int wait_for_helper(void *data)
                 *
                 * Thus the __user pointer cast is valid here.
                 */
-               sys_wait4(pid, (int __user *) &sub_info->retval, 0, NULL);
+               sys_wait4(pid, (int __user *)&ret, 0, NULL);
+
+               /*
+                * If ret is 0, either ____call_usermodehelper failed and the
+                * real error code is already in sub_info->retval or
+                * sub_info->retval is 0 anyway, so don't mess with it then.
+                */
+               if (ret)
+                       sub_info->retval = ret;
        }
 
        complete(sub_info->complete);
@@ -258,6 +287,44 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
 }
 EXPORT_SYMBOL(call_usermodehelper_keys);
 
+int call_usermodehelper_pipe(char *path, char **argv, char **envp,
+                            struct file **filp)
+{
+       DECLARE_COMPLETION(done);
+       struct subprocess_info sub_info = {
+               .complete       = &done,
+               .path           = path,
+               .argv           = argv,
+               .envp           = envp,
+               .retval         = 0,
+       };
+       struct file *f;
+       DECLARE_WORK(work, __call_usermodehelper, &sub_info);
+
+       if (!khelper_wq)
+               return -EBUSY;
+
+       if (path[0] == '\0')
+               return 0;
+
+       f = create_write_pipe();
+       if (!f)
+               return -ENOMEM;
+       *filp = f;
+
+       f = create_read_pipe(f);
+       if (!f) {
+               free_write_pipe(*filp);
+               return -ENOMEM;
+       }
+       sub_info.stdin = f;
+
+       queue_work(khelper_wq, &work);
+       wait_for_completion(&done);
+       return sub_info.retval;
+}
+EXPORT_SYMBOL(call_usermodehelper_pipe);
+
 void __init usermodehelper_init(void)
 {
        khelper_wq = create_singlethread_workqueue("khelper");
diff --git a/kernel/latency.c b/kernel/latency.c
new file mode 100644 (file)
index 0000000..258f255
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * latency.c: Explicit system-wide latency-expectation infrastructure
+ *
+ * The purpose of this infrastructure is to allow device drivers to set
+ * latency constraint they have and to collect and summarize these
+ * expectations globally. The cummulated result can then be used by
+ * power management and similar users to make decisions that have
+ * tradoffs with a latency component.
+ *
+ * An example user of this are the x86 C-states; each higher C state saves
+ * more power, but has a higher exit latency. For the idle loop power
+ * code to make a good decision which C-state to use, information about
+ * acceptable latencies is required.
+ *
+ * An example announcer of latency is an audio driver that knowns it
+ * will get an interrupt when the hardware has 200 usec of samples
+ * left in the DMA buffer; in that case the driver can set a latency
+ * constraint of, say, 150 usec.
+ *
+ * Multiple drivers can each announce their maximum accepted latency,
+ * to keep these appart, a string based identifier is used.
+ *
+ *
+ * (C) Copyright 2006 Intel Corporation
+ * Author: Arjan van de Ven <arjan@linux.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; version 2
+ * of the License.
+ */
+
+#include <linux/latency.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <asm/atomic.h>
+
+struct latency_info {
+       struct list_head list;
+       int usecs;
+       char *identifier;
+};
+
+/*
+ * locking rule: all modifications to current_max_latency and
+ * latency_list need to be done while holding the latency_lock.
+ * latency_lock needs to be taken _irqsave.
+ */
+static atomic_t current_max_latency;
+static DEFINE_SPINLOCK(latency_lock);
+
+static LIST_HEAD(latency_list);
+static BLOCKING_NOTIFIER_HEAD(latency_notifier);
+
+/*
+ * This function returns the maximum latency allowed, which
+ * happens to be the minimum of all maximum latencies on the
+ * list.
+ */
+static int __find_max_latency(void)
+{
+       int min = INFINITE_LATENCY;
+       struct latency_info *info;
+
+       list_for_each_entry(info, &latency_list, list) {
+               if (info->usecs < min)
+                       min = info->usecs;
+       }
+       return min;
+}
+
+/**
+ * set_acceptable_latency - sets the maximum latency acceptable
+ * @identifier: string that identifies this driver
+ * @usecs: maximum acceptable latency for this driver
+ *
+ * This function informs the kernel that this device(driver)
+ * can accept at most usecs latency. This setting is used for
+ * power management and similar tradeoffs.
+ *
+ * This function sleeps and can only be called from process
+ * context.
+ * Calling this function with an existing identifier is valid
+ * and will cause the existing latency setting to be changed.
+ */
+void set_acceptable_latency(char *identifier, int usecs)
+{
+       struct latency_info *info, *iter;
+       unsigned long flags;
+       int found_old = 0;
+
+       info = kzalloc(sizeof(struct latency_info), GFP_KERNEL);
+       if (!info)
+               return;
+       info->usecs = usecs;
+       info->identifier = kstrdup(identifier, GFP_KERNEL);
+       if (!info->identifier)
+               goto free_info;
+
+       spin_lock_irqsave(&latency_lock, flags);
+       list_for_each_entry(iter, &latency_list, list) {
+               if (strcmp(iter->identifier, identifier)==0) {
+                       found_old = 1;
+                       iter->usecs = usecs;
+                       break;
+               }
+       }
+       if (!found_old)
+               list_add(&info->list, &latency_list);
+
+       if (usecs < atomic_read(&current_max_latency))
+               atomic_set(&current_max_latency, usecs);
+
+       spin_unlock_irqrestore(&latency_lock, flags);
+
+       blocking_notifier_call_chain(&latency_notifier,
+               atomic_read(&current_max_latency), NULL);
+
+       /*
+        * if we inserted the new one, we're done; otherwise there was
+        * an existing one so we need to free the redundant data
+        */
+       if (!found_old)
+               return;
+
+       kfree(info->identifier);
+free_info:
+       kfree(info);
+}
+EXPORT_SYMBOL_GPL(set_acceptable_latency);
+
+/**
+ * modify_acceptable_latency - changes the maximum latency acceptable
+ * @identifier: string that identifies this driver
+ * @usecs: maximum acceptable latency for this driver
+ *
+ * This function informs the kernel that this device(driver)
+ * can accept at most usecs latency. This setting is used for
+ * power management and similar tradeoffs.
+ *
+ * This function does not sleep and can be called in any context.
+ * Trying to use a non-existing identifier silently gets ignored.
+ *
+ * Due to the atomic nature of this function, the modified latency
+ * value will only be used for future decisions; past decisions
+ * can still lead to longer latencies in the near future.
+ */
+void modify_acceptable_latency(char *identifier, int usecs)
+{
+       struct latency_info *iter;
+       unsigned long flags;
+
+       spin_lock_irqsave(&latency_lock, flags);
+       list_for_each_entry(iter, &latency_list, list) {
+               if (strcmp(iter->identifier, identifier) == 0) {
+                       iter->usecs = usecs;
+                       break;
+               }
+       }
+       if (usecs < atomic_read(&current_max_latency))
+               atomic_set(&current_max_latency, usecs);
+       spin_unlock_irqrestore(&latency_lock, flags);
+}
+EXPORT_SYMBOL_GPL(modify_acceptable_latency);
+
+/**
+ * remove_acceptable_latency - removes the maximum latency acceptable
+ * @identifier: string that identifies this driver
+ *
+ * This function removes a previously set maximum latency setting
+ * for the driver and frees up any resources associated with the
+ * bookkeeping needed for this.
+ *
+ * This function does not sleep and can be called in any context.
+ * Trying to use a non-existing identifier silently gets ignored.
+ */
+void remove_acceptable_latency(char *identifier)
+{
+       unsigned long flags;
+       int newmax = 0;
+       struct latency_info *iter, *temp;
+
+       spin_lock_irqsave(&latency_lock, flags);
+
+       list_for_each_entry_safe(iter,  temp, &latency_list, list) {
+               if (strcmp(iter->identifier, identifier) == 0) {
+                       list_del(&iter->list);
+                       newmax = iter->usecs;
+                       kfree(iter->identifier);
+                       kfree(iter);
+                       break;
+               }
+       }
+
+       /* If we just deleted the system wide value, we need to
+        * recalculate with a full search
+        */
+       if (newmax == atomic_read(&current_max_latency)) {
+               newmax = __find_max_latency();
+               atomic_set(&current_max_latency, newmax);
+       }
+       spin_unlock_irqrestore(&latency_lock, flags);
+}
+EXPORT_SYMBOL_GPL(remove_acceptable_latency);
+
+/**
+ * system_latency_constraint - queries the system wide latency maximum
+ *
+ * This function returns the system wide maximum latency in
+ * microseconds.
+ *
+ * This function does not sleep and can be called in any context.
+ */
+int system_latency_constraint(void)
+{
+       return atomic_read(&current_max_latency);
+}
+EXPORT_SYMBOL_GPL(system_latency_constraint);
+
+/**
+ * synchronize_acceptable_latency - recalculates all latency decisions
+ *
+ * This function will cause a callback to various kernel pieces that
+ * will make those pieces rethink their latency decisions. This implies
+ * that if there are overlong latencies in hardware state already, those
+ * latencies get taken right now. When this call completes no overlong
+ * latency decisions should be active anymore.
+ *
+ * Typical usecase of this is after a modify_acceptable_latency() call,
+ * which in itself is non-blocking and non-synchronizing.
+ *
+ * This function blocks and should not be called with locks held.
+ */
+
+void synchronize_acceptable_latency(void)
+{
+       blocking_notifier_call_chain(&latency_notifier,
+               atomic_read(&current_max_latency), NULL);
+}
+EXPORT_SYMBOL_GPL(synchronize_acceptable_latency);
+
+/*
+ * Latency notifier: this notifier gets called when a non-atomic new
+ * latency value gets set. The expectation nof the caller of the
+ * non-atomic set is that when the call returns, future latencies
+ * are within bounds, so the functions on the notifier list are
+ * expected to take the overlong latencies immediately, inside the
+ * callback, and not make a overlong latency decision anymore.
+ *
+ * The callback gets called when the new latency value is made
+ * active so system_latency_constraint() returns the new latency.
+ */
+int register_latency_notifier(struct notifier_block * nb)
+{
+       return blocking_notifier_chain_register(&latency_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(register_latency_notifier);
+
+int unregister_latency_notifier(struct notifier_block * nb)
+{
+       return blocking_notifier_chain_unregister(&latency_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_latency_notifier);
+
+static __init int latency_init(void)
+{
+       atomic_set(&current_max_latency, INFINITE_LATENCY);
+       /*
+        * we don't want by default to have longer latencies than 2 ticks,
+        * since that would cause lost ticks
+        */
+       set_acceptable_latency("kernel", 2*1000000/HZ);
+       return 0;
+}
+
+module_init(latency_init);
index c088e5542e84074d3f784108805c841c162b0ce9..e596525669ed4fa5018ee452c7bc429b945f8d00 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/stacktrace.h>
 #include <linux/debug_locks.h>
 #include <linux/irqflags.h>
+#include <linux/utsname.h>
 
 #include <asm/sections.h>
 
@@ -121,8 +122,8 @@ static struct list_head chainhash_table[CHAINHASH_SIZE];
  * unique.
  */
 #define iterate_chain_key(key1, key2) \
-       (((key1) << MAX_LOCKDEP_KEYS_BITS/2) ^ \
-       ((key1) >> (64-MAX_LOCKDEP_KEYS_BITS/2)) ^ \
+       (((key1) << MAX_LOCKDEP_KEYS_BITS) ^ \
+       ((key1) >> (64-MAX_LOCKDEP_KEYS_BITS)) ^ \
        (key2))
 
 void lockdep_off(void)
@@ -515,6 +516,13 @@ print_circular_bug_entry(struct lock_list *target, unsigned int depth)
        return 0;
 }
 
+static void print_kernel_version(void)
+{
+       printk("%s %.*s\n", system_utsname.release,
+               (int)strcspn(system_utsname.version, " "),
+               system_utsname.version);
+}
+
 /*
  * When a circular dependency is detected, print the
  * header first:
@@ -531,6 +539,7 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth)
 
        printk("\n=======================================================\n");
        printk(  "[ INFO: possible circular locking dependency detected ]\n");
+       print_kernel_version();
        printk(  "-------------------------------------------------------\n");
        printk("%s/%d is trying to acquire lock:\n",
                curr->comm, curr->pid);
@@ -712,6 +721,7 @@ print_bad_irq_dependency(struct task_struct *curr,
        printk("\n======================================================\n");
        printk(  "[ INFO: %s-safe -> %s-unsafe lock order detected ]\n",
                irqclass, irqclass);
+       print_kernel_version();
        printk(  "------------------------------------------------------\n");
        printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] is trying to acquire:\n",
                curr->comm, curr->pid,
@@ -793,6 +803,7 @@ print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
 
        printk("\n=============================================\n");
        printk(  "[ INFO: possible recursive locking detected ]\n");
+       print_kernel_version();
        printk(  "---------------------------------------------\n");
        printk("%s/%d is trying to acquire lock:\n",
                curr->comm, curr->pid);
@@ -1375,6 +1386,7 @@ print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
 
        printk("\n=========================================================\n");
        printk(  "[ INFO: possible irq lock inversion dependency detected ]\n");
+       print_kernel_version();
        printk(  "---------------------------------------------------------\n");
        printk("%s/%d just changed the state of lock:\n",
                curr->comm, curr->pid);
@@ -1469,6 +1481,7 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this,
 
        printk("\n=================================\n");
        printk(  "[ INFO: inconsistent lock state ]\n");
+       print_kernel_version();
        printk(  "---------------------------------\n");
 
        printk("inconsistent {%s} -> {%s} usage.\n",
index b7fe6e84096303865f20e1c606c6bb35c77451c8..05625d5dc7583ac5567d3deec22ebd95c57b72bc 100644 (file)
@@ -933,6 +933,15 @@ static ssize_t module_sect_show(struct module_attribute *mattr,
        return sprintf(buf, "0x%lx\n", sattr->address);
 }
 
+static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
+{
+       int section;
+
+       for (section = 0; section < sect_attrs->nsections; section++)
+               kfree(sect_attrs->attrs[section].name);
+       kfree(sect_attrs);
+}
+
 static void add_sect_attrs(struct module *mod, unsigned int nsect,
                char *secstrings, Elf_Shdr *sechdrs)
 {
@@ -949,21 +958,26 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
                        + nloaded * sizeof(sect_attrs->attrs[0]),
                        sizeof(sect_attrs->grp.attrs[0]));
        size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);
-       if (! (sect_attrs = kmalloc(size[0] + size[1], GFP_KERNEL)))
+       sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
+       if (sect_attrs == NULL)
                return;
 
        /* Setup section attributes. */
        sect_attrs->grp.name = "sections";
        sect_attrs->grp.attrs = (void *)sect_attrs + size[0];
 
+       sect_attrs->nsections = 0;
        sattr = &sect_attrs->attrs[0];
        gattr = &sect_attrs->grp.attrs[0];
        for (i = 0; i < nsect; i++) {
                if (! (sechdrs[i].sh_flags & SHF_ALLOC))
                        continue;
                sattr->address = sechdrs[i].sh_addr;
-               strlcpy(sattr->name, secstrings + sechdrs[i].sh_name,
-                       MODULE_SECT_NAME_LEN);
+               sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,
+                                       GFP_KERNEL);
+               if (sattr->name == NULL)
+                       goto out;
+               sect_attrs->nsections++;
                sattr->mattr.show = module_sect_show;
                sattr->mattr.store = NULL;
                sattr->mattr.attr.name = sattr->name;
@@ -979,7 +993,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
        mod->sect_attrs = sect_attrs;
        return;
   out:
-       kfree(sect_attrs);
+       free_sect_attrs(sect_attrs);
 }
 
 static void remove_sect_attrs(struct module *mod)
@@ -989,13 +1003,13 @@ static void remove_sect_attrs(struct module *mod)
                                   &mod->sect_attrs->grp);
                /* We are positive that no one is using any sect attrs
                 * at this point.  Deallocate immediately. */
-               kfree(mod->sect_attrs);
+               free_sect_attrs(mod->sect_attrs);
                mod->sect_attrs = NULL;
        }
 }
 
-
 #else
+
 static inline void add_sect_attrs(struct module *mod, unsigned int nsect,
                char *sectstrings, Elf_Shdr *sechdrs)
 {
index 6ceb664fb52aec50c9c2d922c5c8cf17ad5979b2..525e365f72390bb3fb4601c0be4c4bd81214eceb 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/debug_locks.h>
 
 int panic_on_oops;
-int panic_on_unrecovered_nmi;
 int tainted;
 static int pause_on_oops;
 static int pause_on_oops_flag;
index 91aea7aa532e53940fc7c63367d6a9634249be95..f406655d66536b8a373b62c082b9ef64364d2c20 100644 (file)
@@ -547,6 +547,7 @@ static void __init kernel_param_sysfs_setup(const char *name,
                                            unsigned int name_skip)
 {
        struct module_kobject *mk;
+       int ret;
 
        mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
        BUG_ON(!mk);
@@ -554,7 +555,8 @@ static void __init kernel_param_sysfs_setup(const char *name,
        mk->mod = THIS_MODULE;
        kobj_set_kset_s(mk, module_subsys);
        kobject_set_name(&mk->kobj, name);
-       kobject_register(&mk->kobj);
+       ret = kobject_register(&mk->kobj);
+       BUG_ON(ret < 0);
 
        /* no need to keep the kobject if no parameter is exported */
        if (!param_sysfs_setup(mk, kparam, num_params, name_skip)) {
@@ -684,13 +686,20 @@ decl_subsys(module, &module_ktype, NULL);
  */
 static int __init param_sysfs_init(void)
 {
-       subsystem_register(&module_subsys);
+       int ret;
+
+       ret = subsystem_register(&module_subsys);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s (%d): subsystem_register error: %d\n",
+                       __FILE__, __LINE__, ret);
+               return ret;
+       }
 
        param_sysfs_builtin();
 
        return 0;
 }
-__initcall(param_sysfs_init);
+subsys_initcall(param_sysfs_init);
 
 EXPORT_SYMBOL(param_set_byte);
 EXPORT_SYMBOL(param_get_byte);
index 93e212f20671fd3b19838327366c45e3ad54ced8..8387e8c681938a968ae005f52c58fcdf11ab17c3 100644 (file)
@@ -223,9 +223,6 @@ int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr)
        struct pid_link *link;
        struct pid *pid;
 
-       WARN_ON(!task->pid); /* to be removed soon */
-       WARN_ON(!nr); /* to be removed soon */
-
        link = &task->pids[type];
        link->pid = pid = find_pid(nr);
        hlist_add_head_rcu(&link->node, &pid->tasks[type]);
@@ -252,6 +249,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type)
        free_pid(pid);
 }
 
+/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
+void fastcall transfer_pid(struct task_struct *old, struct task_struct *new,
+                          enum pid_type type)
+{
+       new->pids[type].pid = old->pids[type].pid;
+       hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
+       old->pids[type].pid = NULL;
+}
+
 struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
 {
        struct task_struct *result = NULL;
index d38d9ec3276c3069c1259744496e9d2a05fef117..479b16b44f79f6b639683c724405f51b3ecc156f 100644 (file)
@@ -1393,24 +1393,12 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
        }
 }
 
-static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
-
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-                    struct timespec *rqtp, struct timespec __user *rmtp)
+static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
+                           struct timespec *rqtp, struct itimerspec *it)
 {
-       struct restart_block *restart_block =
-           &current_thread_info()->restart_block;
        struct k_itimer timer;
        int error;
 
-       /*
-        * Diagnose required errors first.
-        */
-       if (CPUCLOCK_PERTHREAD(which_clock) &&
-           (CPUCLOCK_PID(which_clock) == 0 ||
-            CPUCLOCK_PID(which_clock) == current->pid))
-               return -EINVAL;
-
        /*
         * Set up a temporary timer and then wait for it to go off.
         */
@@ -1422,11 +1410,12 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
        timer.it_process = current;
        if (!error) {
                static struct itimerspec zero_it;
-               struct itimerspec it = { .it_value = *rqtp,
-                                        .it_interval = {} };
+
+               memset(it, 0, sizeof *it);
+               it->it_value = *rqtp;
 
                spin_lock_irq(&timer.it_lock);
-               error = posix_cpu_timer_set(&timer, flags, &it, NULL);
+               error = posix_cpu_timer_set(&timer, flags, it, NULL);
                if (error) {
                        spin_unlock_irq(&timer.it_lock);
                        return error;
@@ -1454,49 +1443,89 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
                 * We were interrupted by a signal.
                 */
                sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
-               posix_cpu_timer_set(&timer, 0, &zero_it, &it);
+               posix_cpu_timer_set(&timer, 0, &zero_it, it);
                spin_unlock_irq(&timer.it_lock);
 
-               if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
+               if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
                        /*
                         * It actually did fire already.
                         */
                        return 0;
                }
 
+               error = -ERESTART_RESTARTBLOCK;
+       }
+
+       return error;
+}
+
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+                    struct timespec *rqtp, struct timespec __user *rmtp)
+{
+       struct restart_block *restart_block =
+           &current_thread_info()->restart_block;
+       struct itimerspec it;
+       int error;
+
+       /*
+        * Diagnose required errors first.
+        */
+       if (CPUCLOCK_PERTHREAD(which_clock) &&
+           (CPUCLOCK_PID(which_clock) == 0 ||
+            CPUCLOCK_PID(which_clock) == current->pid))
+               return -EINVAL;
+
+       error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
+
+       if (error == -ERESTART_RESTARTBLOCK) {
+
+               if (flags & TIMER_ABSTIME)
+                       return -ERESTARTNOHAND;
                /*
-                * Report back to the user the time still remaining.
-                */
-               if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
-                   copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+                * Report back to the user the time still remaining.
+                */
+               if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
                        return -EFAULT;
 
-               restart_block->fn = posix_cpu_clock_nanosleep_restart;
-               /* Caller already set restart_block->arg1 */
+               restart_block->fn = posix_cpu_nsleep_restart;
                restart_block->arg0 = which_clock;
                restart_block->arg1 = (unsigned long) rmtp;
                restart_block->arg2 = rqtp->tv_sec;
                restart_block->arg3 = rqtp->tv_nsec;
-
-               error = -ERESTART_RESTARTBLOCK;
        }
-
        return error;
 }
 
-static long
-posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
+long posix_cpu_nsleep_restart(struct restart_block *restart_block)
 {
        clockid_t which_clock = restart_block->arg0;
        struct timespec __user *rmtp;
        struct timespec t;
+       struct itimerspec it;
+       int error;
 
        rmtp = (struct timespec __user *) restart_block->arg1;
        t.tv_sec = restart_block->arg2;
        t.tv_nsec = restart_block->arg3;
 
        restart_block->fn = do_no_restart_syscall;
-       return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
+       error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
+
+       if (error == -ERESTART_RESTARTBLOCK) {
+               /*
+                * Report back to the user the time still remaining.
+                */
+               if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+                       return -EFAULT;
+
+               restart_block->fn = posix_cpu_nsleep_restart;
+               restart_block->arg0 = which_clock;
+               restart_block->arg1 = (unsigned long) rmtp;
+               restart_block->arg2 = t.tv_sec;
+               restart_block->arg3 = t.tv_nsec;
+       }
+       return error;
+
 }
 
 
@@ -1524,6 +1553,10 @@ static int process_cpu_nsleep(const clockid_t which_clock, int flags,
 {
        return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
 }
+static long process_cpu_nsleep_restart(struct restart_block *restart_block)
+{
+       return -EINVAL;
+}
 static int thread_cpu_clock_getres(const clockid_t which_clock,
                                   struct timespec *tp)
 {
@@ -1544,6 +1577,10 @@ static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
 {
        return -EINVAL;
 }
+static long thread_cpu_nsleep_restart(struct restart_block *restart_block)
+{
+       return -EINVAL;
+}
 
 static __init int init_posix_cpu_timers(void)
 {
@@ -1553,6 +1590,7 @@ static __init int init_posix_cpu_timers(void)
                .clock_set = do_posix_clock_nosettime,
                .timer_create = process_cpu_timer_create,
                .nsleep = process_cpu_nsleep,
+               .nsleep_restart = process_cpu_nsleep_restart,
        };
        struct k_clock thread = {
                .clock_getres = thread_cpu_clock_getres,
@@ -1560,6 +1598,7 @@ static __init int init_posix_cpu_timers(void)
                .clock_set = do_posix_clock_nosettime,
                .timer_create = thread_cpu_timer_create,
                .nsleep = thread_cpu_nsleep,
+               .nsleep_restart = thread_cpu_nsleep_restart,
        };
 
        register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
index ac6dc8744429f986f2f6c6b628513b2524316374..e5ebcc1ec3a0f4c612ca4f9db9ead45d07d424ce 100644 (file)
@@ -973,3 +973,24 @@ sys_clock_nanosleep(const clockid_t which_clock, int flags,
        return CLOCK_DISPATCH(which_clock, nsleep,
                              (which_clock, flags, &t, rmtp));
 }
+
+/*
+ * nanosleep_restart for monotonic and realtime clocks
+ */
+static int common_nsleep_restart(struct restart_block *restart_block)
+{
+       return hrtimer_nanosleep_restart(restart_block);
+}
+
+/*
+ * This will restart clock_nanosleep. This is required only by
+ * compat_clock_nanosleep_restart for now.
+ */
+long
+clock_nanosleep_restart(struct restart_block *restart_block)
+{
+       clockid_t which_clock = restart_block->arg0;
+
+       return CLOCK_DISPATCH(which_clock, nsleep_restart,
+                             (restart_block));
+}
index 9a111f70145c6673cddf08eeaf2e86da03dff8d8..4d50e06fd745cf28fc940252d856b51d1b372110 100644 (file)
@@ -241,60 +241,6 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
        return 0;
 }
 
-/*
- * Access another process' address space.
- * Source/target buffer must be kernel space, 
- * Do not walk the page table directly, use get_user_pages
- */
-
-int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
-{
-       struct mm_struct *mm;
-       struct vm_area_struct *vma;
-       struct page *page;
-       void *old_buf = buf;
-
-       mm = get_task_mm(tsk);
-       if (!mm)
-               return 0;
-
-       down_read(&mm->mmap_sem);
-       /* ignore errors, just check how much was sucessfully transfered */
-       while (len) {
-               int bytes, ret, offset;
-               void *maddr;
-
-               ret = get_user_pages(tsk, mm, addr, 1,
-                               write, 1, &page, &vma);
-               if (ret <= 0)
-                       break;
-
-               bytes = len;
-               offset = addr & (PAGE_SIZE-1);
-               if (bytes > PAGE_SIZE-offset)
-                       bytes = PAGE_SIZE-offset;
-
-               maddr = kmap(page);
-               if (write) {
-                       copy_to_user_page(vma, page, addr,
-                                         maddr + offset, buf, bytes);
-                       set_page_dirty_lock(page);
-               } else {
-                       copy_from_user_page(vma, page, addr,
-                                           buf, maddr + offset, bytes);
-               }
-               kunmap(page);
-               page_cache_release(page);
-               len -= bytes;
-               buf += bytes;
-               addr += bytes;
-       }
-       up_read(&mm->mmap_sem);
-       mmput(mm);
-       
-       return buf - old_buf;
-}
-
 int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
 {
        int copied = 0;
@@ -494,6 +440,7 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
        child = find_task_by_pid(pid);
        if (child)
                get_task_struct(child);
+
        read_unlock(&tasklist_lock);
        if (!child)
                return ERR_PTR(-ESRCH);
index 4d1c3d2471278ebe93e00d7291eb253e83f7d89a..4f2c4272d59c91bda58823e8f6e04e121c85458d 100644 (file)
@@ -192,13 +192,13 @@ static struct rcu_torture_ops *cur_ops = NULL;
  * Definitions for rcu torture testing.
  */
 
-static int rcu_torture_read_lock(void)
+static int rcu_torture_read_lock(void) __acquires(RCU)
 {
        rcu_read_lock();
        return 0;
 }
 
-static void rcu_torture_read_unlock(int idx)
+static void rcu_torture_read_unlock(int idx) __releases(RCU)
 {
        rcu_read_unlock();
 }
@@ -250,13 +250,13 @@ static struct rcu_torture_ops rcu_ops = {
  * Definitions for rcu_bh torture testing.
  */
 
-static int rcu_bh_torture_read_lock(void)
+static int rcu_bh_torture_read_lock(void) __acquires(RCU_BH)
 {
        rcu_read_lock_bh();
        return 0;
 }
 
-static void rcu_bh_torture_read_unlock(int idx)
+static void rcu_bh_torture_read_unlock(int idx) __releases(RCU_BH)
 {
        rcu_read_unlock_bh();
 }
index 33345e73485c6149f2db834fb749a7934f906442..1d63ecddfa7018cd4a14f8b6dc24c352a9ddc447 100644 (file)
@@ -95,7 +95,7 @@ int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
  *     @buf: the buffer struct
  *     @size: total size of the buffer
  *
- *     Returns a pointer to the resulting buffer, NULL if unsuccessful. The
+ *     Returns a pointer to the resulting buffer, %NULL if unsuccessful. The
  *     passed in size will get page aligned, if it isn't already.
  */
 static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
@@ -132,10 +132,9 @@ depopulate:
 
 /**
  *     relay_create_buf - allocate and initialize a channel buffer
- *     @alloc_size: size of the buffer to allocate
- *     @n_subbufs: number of sub-buffers in the channel
+ *     @chan: the relay channel
  *
- *     Returns channel buffer if successful, NULL otherwise
+ *     Returns channel buffer if successful, %NULL otherwise.
  */
 struct rchan_buf *relay_create_buf(struct rchan *chan)
 {
@@ -163,6 +162,7 @@ free_buf:
 
 /**
  *     relay_destroy_channel - free the channel struct
+ *     @kref: target kernel reference that contains the relay channel
  *
  *     Should only be called from kref_put().
  */
@@ -194,6 +194,7 @@ void relay_destroy_buf(struct rchan_buf *buf)
 
 /**
  *     relay_remove_buf - remove a channel buffer
+ *     @kref: target kernel reference that contains the relay buffer
  *
  *     Removes the file from the fileystem, which also frees the
  *     rchan_buf_struct and the channel buffer.  Should only be called from
@@ -374,7 +375,7 @@ void relay_reset(struct rchan *chan)
 }
 EXPORT_SYMBOL_GPL(relay_reset);
 
-/**
+/*
  *     relay_open_buf - create a new relay channel buffer
  *
  *     Internal - used by relay_open().
@@ -448,12 +449,12 @@ static inline void setup_callbacks(struct rchan *chan,
 /**
  *     relay_open - create a new relay channel
  *     @base_filename: base name of files to create
- *     @parent: dentry of parent directory, NULL for root directory
+ *     @parent: dentry of parent directory, %NULL for root directory
  *     @subbuf_size: size of sub-buffers
  *     @n_subbufs: number of sub-buffers
  *     @cb: client callback functions
  *
- *     Returns channel pointer if successful, NULL otherwise.
+ *     Returns channel pointer if successful, %NULL otherwise.
  *
  *     Creates a channel buffer for each cpu using the sizes and
  *     attributes specified.  The created channel buffer files
@@ -585,7 +586,7 @@ EXPORT_SYMBOL_GPL(relay_switch_subbuf);
  *     subbufs_consumed should be the number of sub-buffers newly consumed,
  *     not the total consumed.
  *
- *     NOTE: kernel clients don't need to call this function if the channel
+ *     NOTE: Kernel clients don't need to call this function if the channel
  *     mode is 'overwrite'.
  */
 void relay_subbufs_consumed(struct rchan *chan,
@@ -641,7 +642,7 @@ EXPORT_SYMBOL_GPL(relay_close);
  *     relay_flush - close the channel
  *     @chan: the channel
  *
- *     Flushes all channel buffers i.e. forces buffer switch.
+ *     Flushes all channel buffers, i.e. forces buffer switch.
  */
 void relay_flush(struct rchan *chan)
 {
@@ -669,7 +670,7 @@ EXPORT_SYMBOL_GPL(relay_flush);
  */
 static int relay_file_open(struct inode *inode, struct file *filp)
 {
-       struct rchan_buf *buf = inode->u.generic_ip;
+       struct rchan_buf *buf = inode->i_private;
        kref_get(&buf->kref);
        filp->private_data = buf;
 
@@ -729,7 +730,7 @@ static int relay_file_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
-/**
+/*
  *     relay_file_read_consume - update the consumed count for the buffer
  */
 static void relay_file_read_consume(struct rchan_buf *buf,
@@ -756,7 +757,7 @@ static void relay_file_read_consume(struct rchan_buf *buf,
        }
 }
 
-/**
+/*
  *     relay_file_read_avail - boolean, are there unconsumed bytes available?
  */
 static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
@@ -793,6 +794,8 @@ static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
 
 /**
  *     relay_file_read_subbuf_avail - return bytes available in sub-buffer
+ *     @read_pos: file read position
+ *     @buf: relay channel buffer
  */
 static size_t relay_file_read_subbuf_avail(size_t read_pos,
                                           struct rchan_buf *buf)
@@ -818,6 +821,8 @@ static size_t relay_file_read_subbuf_avail(size_t read_pos,
 
 /**
  *     relay_file_read_start_pos - find the first available byte to read
+ *     @read_pos: file read position
+ *     @buf: relay channel buffer
  *
  *     If the read_pos is in the middle of padding, return the
  *     position of the first actually available byte, otherwise
@@ -844,6 +849,9 @@ static size_t relay_file_read_start_pos(size_t read_pos,
 
 /**
  *     relay_file_read_end_pos - return the new read position
+ *     @read_pos: file read position
+ *     @buf: relay channel buffer
+ *     @count: number of bytes to be read
  */
 static size_t relay_file_read_end_pos(struct rchan_buf *buf,
                                      size_t read_pos,
@@ -865,7 +873,7 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf,
        return end_pos;
 }
 
-/**
+/*
  *     subbuf_read_actor - read up to one subbuf's worth of data
  */
 static int subbuf_read_actor(size_t read_start,
@@ -890,7 +898,7 @@ static int subbuf_read_actor(size_t read_start,
        return ret;
 }
 
-/**
+/*
  *     subbuf_send_actor - send up to one subbuf's worth of data
  */
 static int subbuf_send_actor(size_t read_start,
@@ -933,7 +941,7 @@ typedef int (*subbuf_actor_t) (size_t read_start,
                               read_descriptor_t *desc,
                               read_actor_t actor);
 
-/**
+/*
  *     relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
  */
 static inline ssize_t relay_file_read_subbufs(struct file *filp,
index 46286434af8066af359143df81244e0c3024de19..9db38a1a75208cb36bb8c68cd51f6ba7b293ce5f 100644 (file)
@@ -344,12 +344,11 @@ EXPORT_SYMBOL(allocate_resource);
  *
  * Returns 0 on success, -EBUSY if the resource can't be inserted.
  *
- * This function is equivalent of request_resource when no conflict
+ * This function is equivalent to request_resource when no conflict
  * happens. If a conflict happens, and the conflicting resources
  * entirely fit within the range of the new resource, then the new
- * resource is inserted and the conflicting resources become childs of
- * the new resource.  Otherwise the new resource becomes the child of
- * the conflicting resource
+ * resource is inserted and the conflicting resources become children of
+ * the new resource.
  */
 int insert_resource(struct resource *parent, struct resource *new)
 {
@@ -357,20 +356,21 @@ int insert_resource(struct resource *parent, struct resource *new)
        struct resource *first, *next;
 
        write_lock(&resource_lock);
- begin:
-       result = 0;
-       first = __request_resource(parent, new);
-       if (!first)
-               goto out;
 
-       result = -EBUSY;
-       if (first == parent)
-               goto out;
+       for (;; parent = first) {
+               result = 0;
+               first = __request_resource(parent, new);
+               if (!first)
+                       goto out;
 
-       /* Resource fully contained by the clashing resource? Recurse into it */
-       if (first->start <= new->start && first->end >= new->end) {
-               parent = first;
-               goto begin;
+               result = -EBUSY;
+               if (first == parent)
+                       goto out;
+
+               if ((first->start > new->start) || (first->end < new->end))
+                       break;
+               if ((first->start == new->start) && (first->end == new->end))
+                       break;
        }
 
        for (next = first; ; next = next->sibling) {
index 3e13a1e5856fecf8a06eab48372d12a01efb428b..4ab17da46fd80de1690744f9022691923942cb70 100644 (file)
@@ -251,6 +251,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
 
        /* Grab the next task */
        task = rt_mutex_owner(lock);
+       get_task_struct(task);
        spin_lock_irqsave(&task->pi_lock, flags);
 
        if (waiter == rt_mutex_top_waiter(lock)) {
@@ -269,7 +270,6 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
                __rt_mutex_adjust_prio(task);
        }
 
-       get_task_struct(task);
        spin_unlock_irqrestore(&task->pi_lock, flags);
 
        top_waiter = rt_mutex_top_waiter(lock);
@@ -409,7 +409,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
        struct task_struct *owner = rt_mutex_owner(lock);
        struct rt_mutex_waiter *top_waiter = waiter;
        unsigned long flags;
-       int boost = 0, res;
+       int chain_walk = 0, res;
 
        spin_lock_irqsave(&current->pi_lock, flags);
        __rt_mutex_adjust_prio(current);
@@ -433,25 +433,23 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
                plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
 
                __rt_mutex_adjust_prio(owner);
-               if (owner->pi_blocked_on) {
-                       boost = 1;
-                       /* gets dropped in rt_mutex_adjust_prio_chain()! */
-                       get_task_struct(owner);
-               }
-               spin_unlock_irqrestore(&owner->pi_lock, flags);
-       }
-       else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) {
-               spin_lock_irqsave(&owner->pi_lock, flags);
-               if (owner->pi_blocked_on) {
-                       boost = 1;
-                       /* gets dropped in rt_mutex_adjust_prio_chain()! */
-                       get_task_struct(owner);
-               }
+               if (owner->pi_blocked_on)
+                       chain_walk = 1;
                spin_unlock_irqrestore(&owner->pi_lock, flags);
        }
-       if (!boost)
+       else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock))
+               chain_walk = 1;
+
+       if (!chain_walk)
                return 0;
 
+       /*
+        * The owner can't disappear while holding a lock,
+        * so the owner struct is protected by wait_lock.
+        * Gets dropped in rt_mutex_adjust_prio_chain()!
+        */
+       get_task_struct(owner);
+
        spin_unlock(&lock->wait_lock);
 
        res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter,
@@ -532,7 +530,7 @@ static void remove_waiter(struct rt_mutex *lock,
        int first = (waiter == rt_mutex_top_waiter(lock));
        struct task_struct *owner = rt_mutex_owner(lock);
        unsigned long flags;
-       int boost = 0;
+       int chain_walk = 0;
 
        spin_lock_irqsave(&current->pi_lock, flags);
        plist_del(&waiter->list_entry, &lock->wait_list);
@@ -554,19 +552,20 @@ static void remove_waiter(struct rt_mutex *lock,
                }
                __rt_mutex_adjust_prio(owner);
 
-               if (owner->pi_blocked_on) {
-                       boost = 1;
-                       /* gets dropped in rt_mutex_adjust_prio_chain()! */
-                       get_task_struct(owner);
-               }
+               if (owner->pi_blocked_on)
+                       chain_walk = 1;
+
                spin_unlock_irqrestore(&owner->pi_lock, flags);
        }
 
        WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
 
-       if (!boost)
+       if (!chain_walk)
                return;
 
+       /* gets dropped in rt_mutex_adjust_prio_chain()! */
+       get_task_struct(owner);
+
        spin_unlock(&lock->wait_lock);
 
        rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current);
@@ -592,10 +591,10 @@ void rt_mutex_adjust_pi(struct task_struct *task)
                return;
        }
 
-       /* gets dropped in rt_mutex_adjust_prio_chain()! */
-       get_task_struct(task);
        spin_unlock_irqrestore(&task->pi_lock, flags);
 
+       /* gets dropped in rt_mutex_adjust_prio_chain()! */
+       get_task_struct(task);
        rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task);
 }
 
index 5c848fd4e461c67bded9c27b81405889a80cd656..2bbd948f0169dc3361d8b8924b0dce59eda1a825 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/seq_file.h>
 #include <linux/syscalls.h>
 #include <linux/times.h>
-#include <linux/acct.h>
+#include <linux/tsacct_kern.h>
 #include <linux/kprobes.h>
 #include <linux/delayacct.h>
 #include <asm/tlb.h>
@@ -1755,27 +1755,27 @@ static inline void finish_task_switch(struct rq *rq, struct task_struct *prev)
        __releases(rq->lock)
 {
        struct mm_struct *mm = rq->prev_mm;
-       unsigned long prev_task_flags;
+       long prev_state;
 
        rq->prev_mm = NULL;
 
        /*
         * A task struct has one reference for the use as "current".
-        * If a task dies, then it sets EXIT_ZOMBIE in tsk->exit_state and
-        * calls schedule one last time. The schedule call will never return,
-        * and the scheduled task must drop that reference.
-        * The test for EXIT_ZOMBIE must occur while the runqueue locks are
+        * If a task dies, then it sets TASK_DEAD in tsk->state and calls
+        * schedule one last time. The schedule call will never return, and
+        * the scheduled task must drop that reference.
+        * The test for TASK_DEAD must occur while the runqueue locks are
         * still held, otherwise prev could be scheduled on another cpu, die
         * there before we look at prev->state, and then the reference would
         * be dropped twice.
         *              Manfred Spraul <manfred@colorfullife.com>
         */
-       prev_task_flags = prev->flags;
+       prev_state = prev->state;
        finish_arch_switch(prev);
        finish_lock_switch(rq, prev);
        if (mm)
                mmdrop(mm);
-       if (unlikely(prev_task_flags & PF_DEAD)) {
+       if (unlikely(prev_state == TASK_DEAD)) {
                /*
                 * Remove function-return probe instances associated with this
                 * task and put them back on the free list.
@@ -3348,9 +3348,6 @@ need_resched_nonpreemptible:
 
        spin_lock_irq(&rq->lock);
 
-       if (unlikely(prev->flags & PF_DEAD))
-               prev->state = EXIT_DEAD;
-
        switch_count = &prev->nivcsw;
        if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
                switch_count = &prev->nvcsw;
@@ -4080,6 +4077,8 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
  * @p: the task in question.
  * @policy: new policy.
  * @param: structure containing the new RT priority.
+ *
+ * NOTE: the task may be already dead
  */
 int sched_setscheduler(struct task_struct *p, int policy,
                       struct sched_param *param)
@@ -4107,28 +4106,32 @@ recheck:
            (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
            (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
                return -EINVAL;
-       if ((policy == SCHED_NORMAL || policy == SCHED_BATCH)
-                                       != (param->sched_priority == 0))
+       if (is_rt_policy(policy) != (param->sched_priority != 0))
                return -EINVAL;
 
        /*
         * Allow unprivileged RT tasks to decrease priority:
         */
        if (!capable(CAP_SYS_NICE)) {
-               /*
-                * can't change policy, except between SCHED_NORMAL
-                * and SCHED_BATCH:
-                */
-               if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
-                       (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
-                               !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
-                       return -EPERM;
-               /* can't increase priority */
-               if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) &&
-                   param->sched_priority > p->rt_priority &&
-                   param->sched_priority >
-                               p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
-                       return -EPERM;
+               if (is_rt_policy(policy)) {
+                       unsigned long rlim_rtprio;
+                       unsigned long flags;
+
+                       if (!lock_task_sighand(p, &flags))
+                               return -ESRCH;
+                       rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
+                       unlock_task_sighand(p, &flags);
+
+                       /* can't set/change the rt policy */
+                       if (policy != p->policy && !rlim_rtprio)
+                               return -EPERM;
+
+                       /* can't increase priority */
+                       if (param->sched_priority > p->rt_priority &&
+                           param->sched_priority > rlim_rtprio)
+                               return -EPERM;
+               }
+
                /* can't change other user's priorities */
                if ((current->euid != p->euid) &&
                    (current->euid != p->uid))
@@ -4193,14 +4196,13 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
                return -EINVAL;
        if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
                return -EFAULT;
-       read_lock_irq(&tasklist_lock);
+
+       rcu_read_lock();
+       retval = -ESRCH;
        p = find_process_by_pid(pid);
-       if (!p) {
-               read_unlock_irq(&tasklist_lock);
-               return -ESRCH;
-       }
-       retval = sched_setscheduler(p, policy, &lparam);
-       read_unlock_irq(&tasklist_lock);
+       if (p != NULL)
+               retval = sched_setscheduler(p, policy, &lparam);
+       rcu_read_unlock();
 
        return retval;
 }
@@ -5151,7 +5153,7 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
        BUG_ON(p->exit_state != EXIT_ZOMBIE && p->exit_state != EXIT_DEAD);
 
        /* Cannot have done final schedule yet: would have vanished. */
-       BUG_ON(p->flags & PF_DEAD);
+       BUG_ON(p->state == TASK_DEAD);
 
        get_task_struct(p);
 
@@ -5272,9 +5274,11 @@ static struct notifier_block __cpuinitdata migration_notifier = {
 int __init migration_init(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
+       int err;
 
        /* Start one for the boot CPU: */
-       migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
+       err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
+       BUG_ON(err == NOTIFY_BAD);
        migration_call(&migration_notifier, CPU_ONLINE, cpu);
        register_cpu_notifier(&migration_notifier);
 
index bfdb5686fa3e4e3d23075afd2bf21bf680ba0aae..fb5da6d19f14eef721f28750307c9654f17a8bfa 100644 (file)
@@ -417,9 +417,8 @@ static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
                        siginfo_t *info)
 {
-       int sig = 0;
+       int sig = next_signal(pending, mask);
 
-       sig = next_signal(pending, mask);
        if (sig) {
                if (current->notifier) {
                        if (sigismember(current->notifier_mask, sig)) {
@@ -432,9 +431,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
 
                if (!collect_signal(sig, pending, info))
                        sig = 0;
-                               
        }
-       recalc_sigpending();
 
        return sig;
 }
@@ -451,6 +448,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
        if (!signr)
                signr = __dequeue_signal(&tsk->signal->shared_pending,
                                         mask, info);
+       recalc_sigpending_tsk(tsk);
        if (signr && unlikely(sig_kernel_stop(signr))) {
                /*
                 * Set a marker that we have dequeued a stop signal.  Our
@@ -2577,6 +2575,11 @@ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 }
 #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
 
+__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       return NULL;
+}
+
 void __init signals_init(void)
 {
        sigqueue_cachep =
index 3789ca98197c2a793b25dc6ac403e26202312133..bf25015dce162a541059c051567c3569069985b9 100644 (file)
@@ -612,7 +612,9 @@ static struct notifier_block __cpuinitdata cpu_nfb = {
 __init int spawn_ksoftirqd(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
-       cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+       int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+
+       BUG_ON(err == NOTIFY_BAD);
        cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
        register_cpu_notifier(&cpu_nfb);
        return 0;
index 03e6a2b0b787a97f426887f6ecdf709951acaced..50afeb813305d76435e8c6852a80b5b9dc5c8cd9 100644 (file)
@@ -149,8 +149,9 @@ static struct notifier_block __cpuinitdata cpu_nfb = {
 __init void spawn_softlockup_task(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
+       int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
 
-       cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
+       BUG_ON(err == NOTIFY_BAD);
        cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
        register_cpu_notifier(&cpu_nfb);
 
index 9644a41e0bef60fd40773976705c6529b49c45d1..476c3741511b31af1717f90e052880e0e6c9b585 100644 (file)
 #include <linux/debug_locks.h>
 #include <linux/module.h>
 
-/*
- * Generic declaration of the raw read_trylock() function,
- * architectures are supposed to optimize this:
- */
-int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock)
-{
-       __raw_read_lock(lock);
-       return 1;
-}
-EXPORT_SYMBOL(generic__raw_read_trylock);
-
 int __lockfunc _spin_trylock(spinlock_t *lock)
 {
        preempt_disable();
@@ -226,7 +215,7 @@ void __lockfunc _##op##_lock(locktype##_t *lock)                    \
                if (!(lock)->break_lock)                                \
                        (lock)->break_lock = 1;                         \
                while (!op##_can_lock(lock) && (lock)->break_lock)      \
-                       cpu_relax();                                    \
+                       _raw_##op##_relax(&lock->raw_lock);             \
        }                                                               \
        (lock)->break_lock = 0;                                         \
 }                                                                      \
@@ -248,7 +237,7 @@ unsigned long __lockfunc _##op##_lock_irqsave(locktype##_t *lock)   \
                if (!(lock)->break_lock)                                \
                        (lock)->break_lock = 1;                         \
                while (!op##_can_lock(lock) && (lock)->break_lock)      \
-                       cpu_relax();                                    \
+                       _raw_##op##_relax(&lock->raw_lock);             \
        }                                                               \
        (lock)->break_lock = 0;                                         \
        return flags;                                                   \
index 51cacd111dbd8412c35a1d9578cfb3d7eaf86c6a..12458040e66500aec1040b91448c458972d08d69 100644 (file)
@@ -1,3 +1,6 @@
+/* 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>
index 3f894775488dd7fb62907d149d0d1959b67de049..2460581c928cf504ee2f81363d1c609b19136515 100644 (file)
@@ -607,12 +607,10 @@ static void kernel_restart_prepare(char *cmd)
 void kernel_restart(char *cmd)
 {
        kernel_restart_prepare(cmd);
-       if (!cmd) {
+       if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
-       } else {
+       else
                printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);
-       }
-       printk(".\n");
        machine_restart(cmd);
 }
 EXPORT_SYMBOL_GPL(kernel_restart);
@@ -628,9 +626,8 @@ static void kernel_kexec(void)
 #ifdef CONFIG_KEXEC
        struct kimage *image;
        image = xchg(&kexec_image, NULL);
-       if (!image) {
+       if (!image)
                return;
-       }
        kernel_restart_prepare(NULL);
        printk(KERN_EMERG "Starting new kernel\n");
        machine_shutdown();
@@ -824,12 +821,10 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
                    (current->sgid == egid) ||
                    capable(CAP_SETGID))
                        new_egid = egid;
-               else {
+               else
                        return -EPERM;
-               }
        }
-       if (new_egid != old_egid)
-       {
+       if (new_egid != old_egid) {
                current->mm->dumpable = suid_dumpable;
                smp_wmb();
        }
@@ -858,19 +853,14 @@ asmlinkage long sys_setgid(gid_t gid)
        if (retval)
                return retval;
 
-       if (capable(CAP_SETGID))
-       {
-               if(old_egid != gid)
-               {
+       if (capable(CAP_SETGID)) {
+               if (old_egid != gid) {
                        current->mm->dumpable = suid_dumpable;
                        smp_wmb();
                }
                current->gid = current->egid = current->sgid = current->fsgid = gid;
-       }
-       else if ((gid == current->gid) || (gid == current->sgid))
-       {
-               if(old_egid != gid)
-               {
+       } else if ((gid == current->gid) || (gid == current->sgid)) {
+               if (old_egid != gid) {
                        current->mm->dumpable = suid_dumpable;
                        smp_wmb();
                }
@@ -901,8 +891,7 @@ static int set_user(uid_t new_ruid, int dumpclear)
 
        switch_uid(new_user);
 
-       if(dumpclear)
-       {
+       if (dumpclear) {
                current->mm->dumpable = suid_dumpable;
                smp_wmb();
        }
@@ -958,8 +947,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
        if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
                return -EAGAIN;
 
-       if (new_euid != old_euid)
-       {
+       if (new_euid != old_euid) {
                current->mm->dumpable = suid_dumpable;
                smp_wmb();
        }
@@ -1009,8 +997,7 @@ asmlinkage long sys_setuid(uid_t uid)
        } else if ((uid != current->uid) && (uid != new_suid))
                return -EPERM;
 
-       if (old_euid != uid)
-       {
+       if (old_euid != uid) {
                current->mm->dumpable = suid_dumpable;
                smp_wmb();
        }
@@ -1055,8 +1042,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
                        return -EAGAIN;
        }
        if (euid != (uid_t) -1) {
-               if (euid != current->euid)
-               {
+               if (euid != current->euid) {
                        current->mm->dumpable = suid_dumpable;
                        smp_wmb();
                }
@@ -1106,8 +1092,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
                        return -EPERM;
        }
        if (egid != (gid_t) -1) {
-               if (egid != current->egid)
-               {
+               if (egid != current->egid) {
                        current->mm->dumpable = suid_dumpable;
                        smp_wmb();
                }
@@ -1152,10 +1137,8 @@ asmlinkage long sys_setfsuid(uid_t uid)
 
        if (uid == current->uid || uid == current->euid ||
            uid == current->suid || uid == current->fsuid || 
-           capable(CAP_SETUID))
-       {
-               if (uid != old_fsuid)
-               {
+           capable(CAP_SETUID)) {
+               if (uid != old_fsuid) {
                        current->mm->dumpable = suid_dumpable;
                        smp_wmb();
                }
@@ -1183,10 +1166,8 @@ asmlinkage long sys_setfsgid(gid_t gid)
 
        if (gid == current->gid || gid == current->egid ||
            gid == current->sgid || gid == current->fsgid || 
-           capable(CAP_SETGID))
-       {
-               if (gid != old_fsgid)
-               {
+           capable(CAP_SETGID)) {
+               if (gid != old_fsgid) {
                        current->mm->dumpable = suid_dumpable;
                        smp_wmb();
                }
@@ -1322,9 +1303,9 @@ out:
 
 asmlinkage long sys_getpgid(pid_t pid)
 {
-       if (!pid) {
+       if (!pid)
                return process_group(current);
-       else {
+       else {
                int retval;
                struct task_struct *p;
 
@@ -1354,9 +1335,9 @@ asmlinkage long sys_getpgrp(void)
 
 asmlinkage long sys_getsid(pid_t pid)
 {
-       if (!pid) {
+       if (!pid)
                return current->signal->session;
-       else {
+       else {
                int retval;
                struct task_struct *p;
 
@@ -1364,7 +1345,7 @@ asmlinkage long sys_getsid(pid_t pid)
                p = find_task_by_pid(pid);
 
                retval = -ESRCH;
-               if(p) {
+               if (p) {
                        retval = security_task_getsid(p);
                        if (!retval)
                                retval = p->signal->session;
@@ -1432,9 +1413,9 @@ struct group_info *groups_alloc(int gidsetsize)
        group_info->nblocks = nblocks;
        atomic_set(&group_info->usage, 1);
 
-       if (gidsetsize <= NGROUPS_SMALL) {
+       if (gidsetsize <= NGROUPS_SMALL)
                group_info->blocks[0] = group_info->small_block;
-       else {
+       else {
                for (i = 0; i < nblocks; i++) {
                        gid_t *b;
                        b = (void *)__get_free_page(GFP_USER);
@@ -1490,7 +1471,7 @@ static int groups_to_user(gid_t __user *grouplist,
 /* fill a group_info from a user-space array - it must be allocated already */
 static int groups_from_user(struct group_info *group_info,
     gid_t __user *grouplist)
- {
+{
        int i;
        int count = group_info->ngroups;
 
@@ -1648,9 +1629,8 @@ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
 int in_group_p(gid_t grp)
 {
        int retval = 1;
-       if (grp != current->fsgid) {
+       if (grp != current->fsgid)
                retval = groups_search(current->group_info, grp);
-       }
        return retval;
 }
 
@@ -1659,9 +1639,8 @@ EXPORT_SYMBOL(in_group_p);
 int in_egroup_p(gid_t grp)
 {
        int retval = 1;
-       if (grp != current->egid) {
+       if (grp != current->egid)
                retval = groups_search(current->group_info, grp);
-       }
        return retval;
 }
 
@@ -1776,9 +1755,9 @@ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *r
        task_lock(current->group_leader);
        x = current->signal->rlim[resource];
        task_unlock(current->group_leader);
-       if(x.rlim_cur > 0x7FFFFFFF)
+       if (x.rlim_cur > 0x7FFFFFFF)
                x.rlim_cur = 0x7FFFFFFF;
-       if(x.rlim_max > 0x7FFFFFFF)
+       if (x.rlim_max > 0x7FFFFFFF)
                x.rlim_max = 0x7FFFFFFF;
        return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
 }
@@ -2084,12 +2063,12 @@ asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep,
                 * padding
                 */
                unsigned long t0, t1;
-               get_user(t0, &cache->t0);
-               get_user(t1, &cache->t1);
+               get_user(t0, &cache->blob[0]);
+               get_user(t1, &cache->blob[1]);
                t0++;
                t1++;
-               put_user(t0, &cache->t0);
-               put_user(t1, &cache->t1);
+               put_user(t0, &cache->blob[0]);
+               put_user(t1, &cache->blob[1]);
        }
        return err ? -EFAULT : 0;
 }
index 6991bece67e8e7609e5d18920183246e0e007143..7a3b2e75f0402122ced8b15d5488a6b9de49ee8e 100644 (file)
@@ -134,3 +134,8 @@ cond_syscall(sys_madvise);
 cond_syscall(sys_mremap);
 cond_syscall(sys_remap_file_pages);
 cond_syscall(compat_sys_move_pages);
+
+/* block-layer dependent */
+cond_syscall(sys_bdflush);
+cond_syscall(sys_ioprio_set);
+cond_syscall(sys_ioprio_get);
index bcb3a181dbb2fb3984939dffd7f27e24d449da11..ba42694f0453d774d7666b794c6422af21935d75 100644 (file)
 extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
                      void __user *buffer, size_t *lenp, loff_t *ppos);
 
+#ifdef CONFIG_X86
+#include <asm/nmi.h>
+#endif
+
 #if defined(CONFIG_SYSCTL)
 
 /* External variables not in a header file. */
@@ -74,13 +78,6 @@ extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
 extern int compat_log;
 
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
-int unknown_nmi_panic;
-int nmi_watchdog_enabled;
-extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
-                       void __user *, size_t *, loff_t *);
-#endif
-
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
 static int minolduid;
@@ -137,8 +134,11 @@ extern int no_unaligned_warning;
 extern int max_lock_depth;
 #endif
 
-static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
-                      ctl_table *, void **);
+#ifdef CONFIG_SYSCTL_SYSCALL
+static int parse_table(int __user *, int, void __user *, size_t __user *,
+               void __user *, size_t, ctl_table *, void **);
+#endif
+
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
 
@@ -165,7 +165,7 @@ int sysctl_legacy_va_layout;
 
 /* /proc declarations: */
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
 
 static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
 static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
@@ -294,7 +294,7 @@ static ctl_table kern_table[] = {
                .ctl_name       = KERN_CORE_PATTERN,
                .procname       = "core_pattern",
                .data           = core_pattern,
-               .maxlen         = 64,
+               .maxlen         = 128,
                .mode           = 0644,
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
@@ -1166,12 +1166,13 @@ static void start_unregistering(struct ctl_table_header *p)
 
 void __init sysctl_init(void)
 {
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
        register_proc_table(root_table, proc_sys_root, &root_table_header);
        init_irq_proc();
 #endif
 }
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
               void __user *newval, size_t newlen)
 {
@@ -1225,6 +1226,7 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
        unlock_kernel();
        return error;
 }
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
  * ctl_perm does NOT grant the superuser all rights automatically, because
@@ -1251,6 +1253,7 @@ static inline int ctl_perm(ctl_table *table, int op)
        return test_perm(table->mode, op);
 }
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 static int parse_table(int __user *name, int nlen,
                       void __user *oldval, size_t __user *oldlenp,
                       void __user *newval, size_t newlen,
@@ -1340,6 +1343,7 @@ int do_sysctl_strategy (ctl_table *table,
        }
        return 0;
 }
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /**
  * register_sysctl_table - register a sysctl hierarchy
@@ -1427,7 +1431,7 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
        else
                list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
        spin_unlock(&sysctl_lock);
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
        register_proc_table(table, proc_sys_root, tmp);
 #endif
        return tmp;
@@ -1445,18 +1449,31 @@ void unregister_sysctl_table(struct ctl_table_header * header)
        might_sleep();
        spin_lock(&sysctl_lock);
        start_unregistering(header);
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
        unregister_proc_table(header->ctl_table, proc_sys_root);
 #endif
        spin_unlock(&sysctl_lock);
        kfree(header);
 }
 
+#else /* !CONFIG_SYSCTL */
+struct ctl_table_header * register_sysctl_table(ctl_table * table,
+                                               int insert_at_head)
+{
+       return NULL;
+}
+
+void unregister_sysctl_table(struct ctl_table_header * table)
+{
+}
+
+#endif /* CONFIG_SYSCTL */
+
 /*
  * /proc/sys support
  */
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
 
 /* Scan the sysctl entries in table and add them all into /proc */
 static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
@@ -1895,7 +1912,7 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
                return -EPERM;
        }
 
-       op = (current->pid == 1) ? OP_SET : OP_AND;
+       op = is_init(current) ? OP_SET : OP_AND;
        return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                                do_proc_dointvec_bset_conv,&op);
 }
@@ -2318,6 +2335,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 #endif /* CONFIG_PROC_FS */
 
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 /*
  * General sysctl support routines 
  */
@@ -2460,11 +2478,19 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return 1;
 }
 
-#else /* CONFIG_SYSCTL */
+#else /* CONFIG_SYSCTL_SYSCALL */
 
 
 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 {
+       static int msg_count;
+
+       if (msg_count < 5) {
+               msg_count++;
+               printk(KERN_INFO
+                       "warning: process `%s' used the removed sysctl "
+                       "system call\n", current->comm);
+       }
        return -ENOSYS;
 }
 
@@ -2496,73 +2522,7 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return -ENOSYS;
 }
 
-int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
-                            void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
-                                     struct file *filp,
-                                     void __user *buffer,
-                                     size_t *lenp, loff_t *ppos)
-{
-    return -ENOSYS;
-}
-
-struct ctl_table_header * register_sysctl_table(ctl_table * table, 
-                                               int insert_at_head)
-{
-       return NULL;
-}
-
-void unregister_sysctl_table(struct ctl_table_header * table)
-{
-}
-
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
  * No sense putting this after each symbol definition, twice,
index 2ed4040d0dc56423fa73ec0105c226357528f18e..5d6a8c54ee85f56f9a3640480d5560ed35f2b4e5 100644 (file)
@@ -18,7 +18,9 @@
 
 #include <linux/kernel.h>
 #include <linux/taskstats_kern.h>
+#include <linux/tsacct_kern.h>
 #include <linux/delayacct.h>
+#include <linux/tsacct_kern.h>
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 #include <net/genetlink.h>
@@ -75,7 +77,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
        /*
         * If new attributes are added, please revisit this allocation
         */
-       skb = nlmsg_new(size, GFP_KERNEL);
+       skb = nlmsg_new(genlmsg_total_size(size), GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
 
@@ -198,7 +200,13 @@ static int fill_pid(pid_t pid, struct task_struct *pidtsk,
         */
 
        delayacct_add_tsk(stats, tsk);
+
+       /* fill in basic acct fields */
        stats->version = TASKSTATS_VERSION;
+       bacct_add_tsk(stats, tsk);
+
+       /* fill in extended acct fields */
+       xacct_add_tsk(stats, tsk);
 
        /* Define err: label here if needed */
        put_task_struct(tsk);
index 5bd489747643c9e9dced9316cd372bba8f81a9e1..0e017bff4c19e77daeb657669618c757399dde03 100644 (file)
@@ -202,179 +202,6 @@ asmlinkage long sys_settimeofday(struct timeval __user *tv,
        return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 }
 
-/* we call this to notify the arch when the clock is being
- * controlled.  If no such arch routine, do nothing.
- */
-void __attribute__ ((weak)) notify_arch_cmos_timer(void)
-{
-       return;
-}
-
-/* adjtimex mainly allows reading (and writing, if superuser) of
- * kernel time-keeping variables. used by xntpd.
- */
-int do_adjtimex(struct timex *txc)
-{
-        long ltemp, mtemp, save_adjust;
-       int result;
-
-       /* In order to modify anything, you gotta be super-user! */
-       if (txc->modes && !capable(CAP_SYS_TIME))
-               return -EPERM;
-               
-       /* Now we validate the data before disabling interrupts */
-
-       if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
-         /* singleshot must not be used with any other mode bits */
-               if (txc->modes != ADJ_OFFSET_SINGLESHOT)
-                       return -EINVAL;
-
-       if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
-         /* adjustment Offset limited to +- .512 seconds */
-               if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
-                       return -EINVAL; 
-
-       /* if the quartz is off by more than 10% something is VERY wrong ! */
-       if (txc->modes & ADJ_TICK)
-               if (txc->tick <  900000/USER_HZ ||
-                   txc->tick > 1100000/USER_HZ)
-                       return -EINVAL;
-
-       write_seqlock_irq(&xtime_lock);
-       result = time_state;    /* mostly `TIME_OK' */
-
-       /* Save for later - semantics of adjtime is to return old value */
-       save_adjust = time_next_adjust ? time_next_adjust : time_adjust;
-
-#if 0  /* STA_CLOCKERR is never set yet */
-       time_status &= ~STA_CLOCKERR;           /* reset STA_CLOCKERR */
-#endif
-       /* If there are input parameters, then process them */
-       if (txc->modes)
-       {
-           if (txc->modes & ADJ_STATUS)        /* only set allowed bits */
-               time_status =  (txc->status & ~STA_RONLY) |
-                             (time_status & STA_RONLY);
-
-           if (txc->modes & ADJ_FREQUENCY) {   /* p. 22 */
-               if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
-                   result = -EINVAL;
-                   goto leave;
-               }
-               time_freq = txc->freq;
-           }
-
-           if (txc->modes & ADJ_MAXERROR) {
-               if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
-                   result = -EINVAL;
-                   goto leave;
-               }
-               time_maxerror = txc->maxerror;
-           }
-
-           if (txc->modes & ADJ_ESTERROR) {
-               if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
-                   result = -EINVAL;
-                   goto leave;
-               }
-               time_esterror = txc->esterror;
-           }
-
-           if (txc->modes & ADJ_TIMECONST) {   /* p. 24 */
-               if (txc->constant < 0) {        /* NTP v4 uses values > 6 */
-                   result = -EINVAL;
-                   goto leave;
-               }
-               time_constant = txc->constant;
-           }
-
-           if (txc->modes & ADJ_OFFSET) {      /* values checked earlier */
-               if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
-                   /* adjtime() is independent from ntp_adjtime() */
-                   if ((time_next_adjust = txc->offset) == 0)
-                        time_adjust = 0;
-               }
-               else if (time_status & STA_PLL) {
-                   ltemp = txc->offset;
-
-                   /*
-                    * Scale the phase adjustment and
-                    * clamp to the operating range.
-                    */
-                   if (ltemp > MAXPHASE)
-                       time_offset = MAXPHASE << SHIFT_UPDATE;
-                   else if (ltemp < -MAXPHASE)
-                       time_offset = -(MAXPHASE << SHIFT_UPDATE);
-                   else
-                       time_offset = ltemp << SHIFT_UPDATE;
-
-                   /*
-                    * Select whether the frequency is to be controlled
-                    * and in which mode (PLL or FLL). Clamp to the operating
-                    * range. Ugly multiply/divide should be replaced someday.
-                    */
-
-                   if (time_status & STA_FREQHOLD || time_reftime == 0)
-                       time_reftime = xtime.tv_sec;
-                   mtemp = xtime.tv_sec - time_reftime;
-                   time_reftime = xtime.tv_sec;
-                   if (time_status & STA_FLL) {
-                       if (mtemp >= MINSEC) {
-                           ltemp = (time_offset / mtemp) << (SHIFT_USEC -
-                                                             SHIFT_UPDATE);
-                           time_freq += shift_right(ltemp, SHIFT_KH);
-                       } else /* calibration interval too short (p. 12) */
-                               result = TIME_ERROR;
-                   } else {    /* PLL mode */
-                       if (mtemp < MAXSEC) {
-                           ltemp *= mtemp;
-                           time_freq += shift_right(ltemp,(time_constant +
-                                                      time_constant +
-                                                      SHIFT_KF - SHIFT_USEC));
-                       } else /* calibration interval too long (p. 12) */
-                               result = TIME_ERROR;
-                   }
-                   time_freq = min(time_freq, time_tolerance);
-                   time_freq = max(time_freq, -time_tolerance);
-               } /* STA_PLL */
-           } /* txc->modes & ADJ_OFFSET */
-           if (txc->modes & ADJ_TICK) {
-               tick_usec = txc->tick;
-               tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
-           }
-       } /* txc->modes */
-leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
-               result = TIME_ERROR;
-       
-       if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
-           txc->offset    = save_adjust;
-       else {
-           txc->offset = shift_right(time_offset, SHIFT_UPDATE);
-       }
-       txc->freq          = time_freq;
-       txc->maxerror      = time_maxerror;
-       txc->esterror      = time_esterror;
-       txc->status        = time_status;
-       txc->constant      = time_constant;
-       txc->precision     = time_precision;
-       txc->tolerance     = time_tolerance;
-       txc->tick          = tick_usec;
-
-       /* PPS is not implemented, so these are zero */
-       txc->ppsfreq       = 0;
-       txc->jitter        = 0;
-       txc->shift         = 0;
-       txc->stabil        = 0;
-       txc->jitcnt        = 0;
-       txc->calcnt        = 0;
-       txc->errcnt        = 0;
-       txc->stbcnt        = 0;
-       write_sequnlock_irq(&xtime_lock);
-       do_gettimeofday(&txc->time);
-       notify_arch_cmos_timer();
-       return(result);
-}
-
 asmlinkage long sys_adjtimex(struct timex __user *txc_p)
 {
        struct timex txc;               /* Local copy of parameter */
index e1dfd8e86cce145131de4021a226df60d3acd61f..61a3907d16fb5caa0ef0391b3e52b70a08a6844e 100644 (file)
@@ -1 +1 @@
-obj-y += clocksource.o jiffies.o
+obj-y += ntp.o clocksource.o jiffies.o
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
new file mode 100644 (file)
index 0000000..47195fa
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * linux/kernel/time/ntp.c
+ *
+ * NTP state machine interfaces and logic.
+ *
+ * This code was mainly moved from kernel/timer.c and kernel/time.c
+ * Please see those files for relevant copyright info and historical
+ * changelogs.
+ */
+
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+#include <asm/div64.h>
+#include <asm/timex.h>
+
+/*
+ * Timekeeping variables
+ */
+unsigned long tick_usec = TICK_USEC;           /* USER_HZ period (usec) */
+unsigned long tick_nsec;                       /* ACTHZ period (nsec) */
+static u64 tick_length, tick_length_base;
+
+#define MAX_TICKADJ            500             /* microsecs */
+#define MAX_TICKADJ_SCALED     (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
+                                 TICK_LENGTH_SHIFT) / HZ)
+
+/*
+ * phase-lock loop variables
+ */
+/* TIME_ERROR prevents overwriting the CMOS clock */
+static int time_state = TIME_OK;       /* clock synchronization status */
+int time_status = STA_UNSYNC;          /* clock status bits            */
+static long time_offset;               /* time adjustment (ns)         */
+static long time_constant = 2;         /* pll time constant            */
+long time_maxerror = NTP_PHASE_LIMIT;  /* maximum error (us)           */
+long time_esterror = NTP_PHASE_LIMIT;  /* estimated error (us)         */
+long time_freq;                                /* frequency offset (scaled ppm)*/
+static long time_reftime;              /* time at last adjustment (s)  */
+long time_adjust;
+
+#define CLOCK_TICK_OVERFLOW    (LATCH * HZ - CLOCK_TICK_RATE)
+#define CLOCK_TICK_ADJUST      (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
+                                       (s64)CLOCK_TICK_RATE)
+
+static void ntp_update_frequency(void)
+{
+       tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
+       tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
+       tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+
+       do_div(tick_length_base, HZ);
+
+       tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
+}
+
+/**
+ * ntp_clear - Clears the NTP state variables
+ *
+ * Must be called while holding a write on the xtime_lock
+ */
+void ntp_clear(void)
+{
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+
+       ntp_update_frequency();
+
+       tick_length = tick_length_base;
+       time_offset = 0;
+}
+
+/*
+ * this routine handles the overflow of the microsecond field
+ *
+ * The tricky bits of code to handle the accurate clock support
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+ * They were originally developed for SUN and DEC kernels.
+ * All the kudos should go to Dave for this stuff.
+ */
+void second_overflow(void)
+{
+       long time_adj;
+
+       /* Bump the maxerror field */
+       time_maxerror += MAXFREQ >> SHIFT_USEC;
+       if (time_maxerror > NTP_PHASE_LIMIT) {
+               time_maxerror = NTP_PHASE_LIMIT;
+               time_status |= STA_UNSYNC;
+       }
+
+       /*
+        * Leap second processing. If in leap-insert state at the end of the
+        * day, the system clock is set back one second; if in leap-delete
+        * state, the system clock is set ahead one second. The microtime()
+        * routine or external clock driver will insure that reported time is
+        * always monotonic. The ugly divides should be replaced.
+        */
+       switch (time_state) {
+       case TIME_OK:
+               if (time_status & STA_INS)
+                       time_state = TIME_INS;
+               else if (time_status & STA_DEL)
+                       time_state = TIME_DEL;
+               break;
+       case TIME_INS:
+               if (xtime.tv_sec % 86400 == 0) {
+                       xtime.tv_sec--;
+                       wall_to_monotonic.tv_sec++;
+                       /*
+                        * The timer interpolator will make time change
+                        * gradually instead of an immediate jump by one second
+                        */
+                       time_interpolator_update(-NSEC_PER_SEC);
+                       time_state = TIME_OOP;
+                       clock_was_set();
+                       printk(KERN_NOTICE "Clock: inserting leap second "
+                                       "23:59:60 UTC\n");
+               }
+               break;
+       case TIME_DEL:
+               if ((xtime.tv_sec + 1) % 86400 == 0) {
+                       xtime.tv_sec++;
+                       wall_to_monotonic.tv_sec--;
+                       /*
+                        * Use of time interpolator for a gradual change of
+                        * time
+                        */
+                       time_interpolator_update(NSEC_PER_SEC);
+                       time_state = TIME_WAIT;
+                       clock_was_set();
+                       printk(KERN_NOTICE "Clock: deleting leap second "
+                                       "23:59:59 UTC\n");
+               }
+               break;
+       case TIME_OOP:
+               time_state = TIME_WAIT;
+               break;
+       case TIME_WAIT:
+               if (!(time_status & (STA_INS | STA_DEL)))
+               time_state = TIME_OK;
+       }
+
+       /*
+        * Compute the phase adjustment for the next second. The offset is
+        * reduced by a fixed factor times the time constant.
+        */
+       tick_length = tick_length_base;
+       time_adj = shift_right(time_offset, SHIFT_PLL + time_constant);
+       time_offset -= time_adj;
+       tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
+
+       if (unlikely(time_adjust)) {
+               if (time_adjust > MAX_TICKADJ) {
+                       time_adjust -= MAX_TICKADJ;
+                       tick_length += MAX_TICKADJ_SCALED;
+               } else if (time_adjust < -MAX_TICKADJ) {
+                       time_adjust += MAX_TICKADJ;
+                       tick_length -= MAX_TICKADJ_SCALED;
+               } else {
+                       time_adjust = 0;
+                       tick_length += (s64)(time_adjust * NSEC_PER_USEC /
+                                            HZ) << TICK_LENGTH_SHIFT;
+               }
+       }
+}
+
+/*
+ * Return how long ticks are at the moment, that is, how much time
+ * update_wall_time_one_tick will add to xtime next time we call it
+ * (assuming no calls to do_adjtimex in the meantime).
+ * The return value is in fixed-point nanoseconds shifted by the
+ * specified number of bits to the right of the binary point.
+ * This function has no side-effects.
+ */
+u64 current_tick_length(void)
+{
+       return tick_length;
+}
+
+
+void __attribute__ ((weak)) notify_arch_cmos_timer(void)
+{
+       return;
+}
+
+/* adjtimex mainly allows reading (and writing, if superuser) of
+ * kernel time-keeping variables. used by xntpd.
+ */
+int do_adjtimex(struct timex *txc)
+{
+       long ltemp, mtemp, save_adjust;
+       s64 freq_adj, temp64;
+       int result;
+
+       /* In order to modify anything, you gotta be super-user! */
+       if (txc->modes && !capable(CAP_SYS_TIME))
+               return -EPERM;
+
+       /* Now we validate the data before disabling interrupts */
+
+       if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+         /* singleshot must not be used with any other mode bits */
+               if (txc->modes != ADJ_OFFSET_SINGLESHOT)
+                       return -EINVAL;
+
+       if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
+         /* adjustment Offset limited to +- .512 seconds */
+               if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
+                       return -EINVAL;
+
+       /* if the quartz is off by more than 10% something is VERY wrong ! */
+       if (txc->modes & ADJ_TICK)
+               if (txc->tick <  900000/USER_HZ ||
+                   txc->tick > 1100000/USER_HZ)
+                       return -EINVAL;
+
+       write_seqlock_irq(&xtime_lock);
+       result = time_state;    /* mostly `TIME_OK' */
+
+       /* Save for later - semantics of adjtime is to return old value */
+       save_adjust = time_adjust;
+
+#if 0  /* STA_CLOCKERR is never set yet */
+       time_status &= ~STA_CLOCKERR;           /* reset STA_CLOCKERR */
+#endif
+       /* If there are input parameters, then process them */
+       if (txc->modes)
+       {
+           if (txc->modes & ADJ_STATUS)        /* only set allowed bits */
+               time_status =  (txc->status & ~STA_RONLY) |
+                             (time_status & STA_RONLY);
+
+           if (txc->modes & ADJ_FREQUENCY) {   /* p. 22 */
+               if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
+                   result = -EINVAL;
+                   goto leave;
+               }
+               time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC);
+           }
+
+           if (txc->modes & ADJ_MAXERROR) {
+               if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
+                   result = -EINVAL;
+                   goto leave;
+               }
+               time_maxerror = txc->maxerror;
+           }
+
+           if (txc->modes & ADJ_ESTERROR) {
+               if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
+                   result = -EINVAL;
+                   goto leave;
+               }
+               time_esterror = txc->esterror;
+           }
+
+           if (txc->modes & ADJ_TIMECONST) {   /* p. 24 */
+               if (txc->constant < 0) {        /* NTP v4 uses values > 6 */
+                   result = -EINVAL;
+                   goto leave;
+               }
+               time_constant = min(txc->constant + 4, (long)MAXTC);
+           }
+
+           if (txc->modes & ADJ_OFFSET) {      /* values checked earlier */
+               if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
+                   /* adjtime() is independent from ntp_adjtime() */
+                   time_adjust = txc->offset;
+               }
+               else if (time_status & STA_PLL) {
+                   ltemp = txc->offset * NSEC_PER_USEC;
+
+                   /*
+                    * Scale the phase adjustment and
+                    * clamp to the operating range.
+                    */
+                   time_offset = min(ltemp, MAXPHASE * NSEC_PER_USEC);
+                   time_offset = max(time_offset, -MAXPHASE * NSEC_PER_USEC);
+
+                   /*
+                    * Select whether the frequency is to be controlled
+                    * and in which mode (PLL or FLL). Clamp to the operating
+                    * range. Ugly multiply/divide should be replaced someday.
+                    */
+
+                   if (time_status & STA_FREQHOLD || time_reftime == 0)
+                       time_reftime = xtime.tv_sec;
+                   mtemp = xtime.tv_sec - time_reftime;
+                   time_reftime = xtime.tv_sec;
+
+                   freq_adj = (s64)time_offset * mtemp;
+                   freq_adj = shift_right(freq_adj, time_constant * 2 +
+                                          (SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
+                   if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
+                       temp64 = (s64)time_offset << (SHIFT_NSEC - SHIFT_FLL);
+                       if (time_offset < 0) {
+                           temp64 = -temp64;
+                           do_div(temp64, mtemp);
+                           freq_adj -= temp64;
+                       } else {
+                           do_div(temp64, mtemp);
+                           freq_adj += temp64;
+                       }
+                   }
+                   freq_adj += time_freq;
+                   freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
+                   time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
+                   time_offset = (time_offset / HZ) << SHIFT_UPDATE;
+               } /* STA_PLL */
+           } /* txc->modes & ADJ_OFFSET */
+           if (txc->modes & ADJ_TICK)
+               tick_usec = txc->tick;
+
+           if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
+                   ntp_update_frequency();
+       } /* txc->modes */
+leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
+               result = TIME_ERROR;
+
+       if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+           txc->offset    = save_adjust;
+       else
+           txc->offset    = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000;
+       txc->freq          = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC);
+       txc->maxerror      = time_maxerror;
+       txc->esterror      = time_esterror;
+       txc->status        = time_status;
+       txc->constant      = time_constant;
+       txc->precision     = 1;
+       txc->tolerance     = MAXFREQ;
+       txc->tick          = tick_usec;
+
+       /* PPS is not implemented, so these are zero */
+       txc->ppsfreq       = 0;
+       txc->jitter        = 0;
+       txc->shift         = 0;
+       txc->stabil        = 0;
+       txc->jitcnt        = 0;
+       txc->calcnt        = 0;
+       txc->errcnt        = 0;
+       txc->stbcnt        = 0;
+       write_sequnlock_irq(&xtime_lock);
+       do_gettimeofday(&txc->time);
+       notify_arch_cmos_timer();
+       return(result);
+}
index 1d7dd6267c2de52206bb2f09ca981ff81db4b1a1..c1c7fbcffec1615e84a380c2994659cde6216947 100644 (file)
 #include <asm/timex.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_TIME_INTERPOLATION
-static void time_interpolator_update(long delta_nsec);
-#else
-#define time_interpolator_update(x)
-#endif
-
 u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
 
 EXPORT_SYMBOL(jiffies_64);
@@ -136,7 +130,7 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
        list_add_tail(&timer->entry, vec);
 }
 
-/***
+/**
  * init_timer - initialize a timer.
  * @timer: the timer to be initialized
  *
@@ -175,6 +169,7 @@ static inline void detach_timer(struct timer_list *timer,
  */
 static tvec_base_t *lock_timer_base(struct timer_list *timer,
                                        unsigned long *flags)
+       __acquires(timer->base->lock)
 {
        tvec_base_t *base;
 
@@ -235,7 +230,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
 
 EXPORT_SYMBOL(__mod_timer);
 
-/***
+/**
  * add_timer_on - start a timer on a particular CPU
  * @timer: the timer to be added
  * @cpu: the CPU to start it on
@@ -255,9 +250,10 @@ void add_timer_on(struct timer_list *timer, int cpu)
 }
 
 
-/***
+/**
  * mod_timer - modify a timer's timeout
  * @timer: the timer to be modified
+ * @expires: new timeout in jiffies
  *
  * mod_timer is a more efficient way to update the expire field of an
  * active timer (if the timer is inactive it will be activated)
@@ -291,7 +287,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
 
 EXPORT_SYMBOL(mod_timer);
 
-/***
+/**
  * del_timer - deactive a timer.
  * @timer: the timer to be deactivated
  *
@@ -323,7 +319,10 @@ int del_timer(struct timer_list *timer)
 EXPORT_SYMBOL(del_timer);
 
 #ifdef CONFIG_SMP
-/*
+/**
+ * try_to_del_timer_sync - Try to deactivate a timer
+ * @timer: timer do del
+ *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
  *
@@ -351,7 +350,7 @@ out:
        return ret;
 }
 
-/***
+/**
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
  *
@@ -401,15 +400,15 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
        return index;
 }
 
-/***
+#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
+
+/**
  * __run_timers - run all expired timers (if any) on this CPU.
  * @base: the timer vector to be processed.
  *
  * This function cascades all vectors and executes all expired timer
  * vectors.
  */
-#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
-
 static inline void __run_timers(tvec_base_t *base)
 {
        struct timer_list *timer;
@@ -563,12 +562,6 @@ found:
 
 /******************************************************************/
 
-/*
- * Timekeeping variables
- */
-unsigned long tick_usec = TICK_USEC;           /* USER_HZ period (usec) */
-unsigned long tick_nsec = TICK_NSEC;           /* ACTHZ period (nsec) */
-
 /* 
  * The current time 
  * wall_to_monotonic is what we need to add to xtime (or xtime corrected 
@@ -582,209 +575,6 @@ struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
 
 EXPORT_SYMBOL(xtime);
 
-/* Don't completely fail for HZ > 500.  */
-int tickadj = 500/HZ ? : 1;            /* microsecs */
-
-
-/*
- * phase-lock loop variables
- */
-/* TIME_ERROR prevents overwriting the CMOS clock */
-int time_state = TIME_OK;              /* clock synchronization status */
-int time_status = STA_UNSYNC;          /* clock status bits            */
-long time_offset;                      /* time adjustment (us)         */
-long time_constant = 2;                        /* pll time constant            */
-long time_tolerance = MAXFREQ;         /* frequency tolerance (ppm)    */
-long time_precision = 1;               /* clock precision (us)         */
-long time_maxerror = NTP_PHASE_LIMIT;  /* maximum error (us)           */
-long time_esterror = NTP_PHASE_LIMIT;  /* estimated error (us)         */
-long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
-                                       /* frequency offset (scaled ppm)*/
-static long time_adj;                  /* tick adjust (scaled 1 / HZ)  */
-long time_reftime;                     /* time at last adjustment (s)  */
-long time_adjust;
-long time_next_adjust;
-
-/*
- * this routine handles the overflow of the microsecond field
- *
- * The tricky bits of code to handle the accurate clock support
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
- * They were originally developed for SUN and DEC kernels.
- * All the kudos should go to Dave for this stuff.
- *
- */
-static void second_overflow(void)
-{
-       long ltemp;
-
-       /* Bump the maxerror field */
-       time_maxerror += time_tolerance >> SHIFT_USEC;
-       if (time_maxerror > NTP_PHASE_LIMIT) {
-               time_maxerror = NTP_PHASE_LIMIT;
-               time_status |= STA_UNSYNC;
-       }
-
-       /*
-        * Leap second processing. If in leap-insert state at the end of the
-        * day, the system clock is set back one second; if in leap-delete
-        * state, the system clock is set ahead one second. The microtime()
-        * routine or external clock driver will insure that reported time is
-        * always monotonic. The ugly divides should be replaced.
-        */
-       switch (time_state) {
-       case TIME_OK:
-               if (time_status & STA_INS)
-                       time_state = TIME_INS;
-               else if (time_status & STA_DEL)
-                       time_state = TIME_DEL;
-               break;
-       case TIME_INS:
-               if (xtime.tv_sec % 86400 == 0) {
-                       xtime.tv_sec--;
-                       wall_to_monotonic.tv_sec++;
-                       /*
-                        * The timer interpolator will make time change
-                        * gradually instead of an immediate jump by one second
-                        */
-                       time_interpolator_update(-NSEC_PER_SEC);
-                       time_state = TIME_OOP;
-                       clock_was_set();
-                       printk(KERN_NOTICE "Clock: inserting leap second "
-                                       "23:59:60 UTC\n");
-               }
-               break;
-       case TIME_DEL:
-               if ((xtime.tv_sec + 1) % 86400 == 0) {
-                       xtime.tv_sec++;
-                       wall_to_monotonic.tv_sec--;
-                       /*
-                        * Use of time interpolator for a gradual change of
-                        * time
-                        */
-                       time_interpolator_update(NSEC_PER_SEC);
-                       time_state = TIME_WAIT;
-                       clock_was_set();
-                       printk(KERN_NOTICE "Clock: deleting leap second "
-                                       "23:59:59 UTC\n");
-               }
-               break;
-       case TIME_OOP:
-               time_state = TIME_WAIT;
-               break;
-       case TIME_WAIT:
-               if (!(time_status & (STA_INS | STA_DEL)))
-               time_state = TIME_OK;
-       }
-
-       /*
-        * Compute the phase adjustment for the next second. In PLL mode, the
-        * offset is reduced by a fixed factor times the time constant. In FLL
-        * mode the offset is used directly. In either mode, the maximum phase
-        * adjustment for each second is clamped so as to spread the adjustment
-        * over not more than the number of seconds between updates.
-        */
-       ltemp = time_offset;
-       if (!(time_status & STA_FLL))
-               ltemp = shift_right(ltemp, SHIFT_KG + time_constant);
-       ltemp = min(ltemp, (MAXPHASE / MINSEC) << SHIFT_UPDATE);
-       ltemp = max(ltemp, -(MAXPHASE / MINSEC) << SHIFT_UPDATE);
-       time_offset -= ltemp;
-       time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
-
-       /*
-        * Compute the frequency estimate and additional phase adjustment due
-        * to frequency error for the next second.
-        */
-       ltemp = time_freq;
-       time_adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
-
-#if HZ == 100
-       /*
-        * Compensate for (HZ==100) != (1 << SHIFT_HZ).  Add 25% and 3.125% to
-        * get 128.125; => only 0.125% error (p. 14)
-        */
-       time_adj += shift_right(time_adj, 2) + shift_right(time_adj, 5);
-#endif
-#if HZ == 250
-       /*
-        * Compensate for (HZ==250) != (1 << SHIFT_HZ).  Add 1.5625% and
-        * 0.78125% to get 255.85938; => only 0.05% error (p. 14)
-        */
-       time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7);
-#endif
-#if HZ == 1000
-       /*
-        * Compensate for (HZ==1000) != (1 << SHIFT_HZ).  Add 1.5625% and
-        * 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
-        */
-       time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7);
-#endif
-}
-
-/*
- * Returns how many microseconds we need to add to xtime this tick
- * in doing an adjustment requested with adjtime.
- */
-static long adjtime_adjustment(void)
-{
-       long time_adjust_step;
-
-       time_adjust_step = time_adjust;
-       if (time_adjust_step) {
-               /*
-                * We are doing an adjtime thing.  Prepare time_adjust_step to
-                * be within bounds.  Note that a positive time_adjust means we
-                * want the clock to run faster.
-                *
-                * Limit the amount of the step to be in the range
-                * -tickadj .. +tickadj
-                */
-               time_adjust_step = min(time_adjust_step, (long)tickadj);
-               time_adjust_step = max(time_adjust_step, (long)-tickadj);
-       }
-       return time_adjust_step;
-}
-
-/* in the NTP reference this is called "hardclock()" */
-static void update_ntp_one_tick(void)
-{
-       long time_adjust_step;
-
-       time_adjust_step = adjtime_adjustment();
-       if (time_adjust_step)
-               /* Reduce by this step the amount of time left  */
-               time_adjust -= time_adjust_step;
-
-       /* Changes by adjtime() do not take effect till next tick. */
-       if (time_next_adjust != 0) {
-               time_adjust = time_next_adjust;
-               time_next_adjust = 0;
-       }
-}
-
-/*
- * Return how long ticks are at the moment, that is, how much time
- * update_wall_time_one_tick will add to xtime next time we call it
- * (assuming no calls to do_adjtimex in the meantime).
- * The return value is in fixed-point nanoseconds shifted by the
- * specified number of bits to the right of the binary point.
- * This function has no side-effects.
- */
-u64 current_tick_length(void)
-{
-       long delta_nsec;
-       u64 ret;
-
-       /* calculate the finest interval NTP will allow.
-        *    ie: nanosecond value shifted by (SHIFT_SCALE - 10)
-        */
-       delta_nsec = tick_nsec + adjtime_adjustment() * 1000;
-       ret = (u64)delta_nsec << TICK_LENGTH_SHIFT;
-       ret += (s64)time_adj << (TICK_LENGTH_SHIFT - (SHIFT_SCALE - 10));
-
-       return ret;
-}
 
 /* XXX - all of this timekeeping code should be later moved to time.c */
 #include <linux/clocksource.h>
@@ -961,21 +751,24 @@ void __init timekeeping_init(void)
        unsigned long flags;
 
        write_seqlock_irqsave(&xtime_lock, flags);
+
+       ntp_clear();
+
        clock = clocksource_get_next();
        clocksource_calculate_interval(clock, tick_nsec);
        clock->cycle_last = clocksource_read(clock);
-       ntp_clear();
+
        write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
 
 static int timekeeping_suspended;
-/*
+/**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:       unused
  *
  * This is for the generic clocksource timekeeping.
- * xtime/wall_to_monotonic/jiffies/wall_jiffies/etc are
+ * xtime/wall_to_monotonic/jiffies/etc are
  * still managed by arch specific suspend/resume code.
  */
 static int timekeeping_resume(struct sys_device *dev)
@@ -1106,7 +899,7 @@ static void clocksource_adjust(struct clocksource *clock, s64 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.
@@ -1144,8 +937,6 @@ static void update_wall_time(void)
                /* interpolator bits */
                time_interpolator_update(clock->xtime_interval
                                                >> clock->shift);
-               /* increment the NTP state machine */
-               update_ntp_one_tick();
 
                /* accumulate error between NTP and clock interval */
                clock->error += current_tick_length();
@@ -1217,19 +1008,14 @@ static inline void calc_load(unsigned long ticks)
        unsigned long active_tasks; /* fixed-point */
        static int count = LOAD_FREQ;
 
-       count -= ticks;
-       if (count < 0) {
-               count += LOAD_FREQ;
-               active_tasks = count_active_tasks();
+       active_tasks = count_active_tasks();
+       for (count -= ticks; count < 0; count += LOAD_FREQ) {
                CALC_LOAD(avenrun[0], EXP_1, active_tasks);
                CALC_LOAD(avenrun[1], EXP_5, active_tasks);
                CALC_LOAD(avenrun[2], EXP_15, active_tasks);
        }
 }
 
-/* jiffies at the most recent update of wall time */
-unsigned long wall_jiffies = INITIAL_JIFFIES;
-
 /*
  * This read-write spinlock protects us from races in SMP while
  * playing with xtime and avenrun.
@@ -1265,12 +1051,8 @@ void run_local_timers(void)
  * Called by the timer interrupt. xtime_lock must already be taken
  * by the timer IRQ!
  */
-static inline void update_times(void)
+static inline void update_times(unsigned long ticks)
 {
-       unsigned long ticks;
-
-       ticks = jiffies - wall_jiffies;
-       wall_jiffies += ticks;
        update_wall_time();
        calc_load(ticks);
 }
@@ -1281,12 +1063,10 @@ static inline void update_times(void)
  * jiffies is defined in the linker script...
  */
 
-void do_timer(struct pt_regs *regs)
+void do_timer(unsigned long ticks)
 {
-       jiffies_64++;
-       /* prevent loading jiffies before storing new jiffies_64 value. */
-       barrier();
-       update_times();
+       jiffies_64 += ticks;
+       update_times(ticks);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
@@ -1470,8 +1250,9 @@ asmlinkage long sys_gettid(void)
        return current->pid;
 }
 
-/*
+/**
  * sys_sysinfo - fill in sysinfo struct
+ * @info: pointer to buffer to fill
  */ 
 asmlinkage long sys_sysinfo(struct sysinfo __user *info)
 {
@@ -1688,8 +1469,10 @@ static struct notifier_block __cpuinitdata timers_nb = {
 
 void __init init_timers(void)
 {
-       timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
+       int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
                                (void *)(long)smp_processor_id());
+
+       BUG_ON(err == NOTIFY_BAD);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
 }
@@ -1774,7 +1557,7 @@ unsigned long time_interpolator_get_offset(void)
 #define INTERPOLATOR_ADJUST 65536
 #define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
 
-static void time_interpolator_update(long delta_nsec)
+void time_interpolator_update(long delta_nsec)
 {
        u64 counter;
        unsigned long offset;
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
new file mode 100644 (file)
index 0000000..db44322
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * tsacct.c - System accounting over taskstats interface
+ *
+ * Copyright (C) Jay Lan,      <jlan@sgi.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/tsacct_kern.h>
+#include <linux/acct.h>
+#include <linux/jiffies.h>
+
+
+#define USEC_PER_TICK  (USEC_PER_SEC/HZ)
+/*
+ * fill in basic accounting fields
+ */
+void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
+{
+       struct timespec uptime, ts;
+       s64 ac_etime;
+
+       BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN);
+
+       /* calculate task elapsed time in timespec */
+       do_posix_clock_monotonic_gettime(&uptime);
+       ts = timespec_sub(uptime, current->group_leader->start_time);
+       /* rebase elapsed time to usec */
+       ac_etime = timespec_to_ns(&ts);
+       do_div(ac_etime, NSEC_PER_USEC);
+       stats->ac_etime = ac_etime;
+       stats->ac_btime = xtime.tv_sec - ts.tv_sec;
+       if (thread_group_leader(tsk)) {
+               stats->ac_exitcode = tsk->exit_code;
+               if (tsk->flags & PF_FORKNOEXEC)
+                       stats->ac_flag |= AFORK;
+       }
+       if (tsk->flags & PF_SUPERPRIV)
+               stats->ac_flag |= ASU;
+       if (tsk->flags & PF_DUMPCORE)
+               stats->ac_flag |= ACORE;
+       if (tsk->flags & PF_SIGNALED)
+               stats->ac_flag |= AXSIG;
+       stats->ac_nice   = task_nice(tsk);
+       stats->ac_sched  = tsk->policy;
+       stats->ac_uid    = tsk->uid;
+       stats->ac_gid    = tsk->gid;
+       stats->ac_pid    = tsk->pid;
+       stats->ac_ppid   = (tsk->parent) ? tsk->parent->pid : 0;
+       stats->ac_utime  = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC;
+       stats->ac_stime  = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC;
+       stats->ac_minflt = tsk->min_flt;
+       stats->ac_majflt = tsk->maj_flt;
+
+       strncpy(stats->ac_comm, tsk->comm, sizeof(stats->ac_comm));
+}
+
+
+#ifdef CONFIG_TASK_XACCT
+
+#define KB 1024
+#define MB (1024*KB)
+/*
+ * fill in extended accounting fields
+ */
+void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
+{
+       /* convert pages-jiffies to Mbyte-usec */
+       stats->coremem = jiffies_to_usecs(p->acct_rss_mem1) * PAGE_SIZE / MB;
+       stats->virtmem = jiffies_to_usecs(p->acct_vm_mem1) * PAGE_SIZE / MB;
+       if (p->mm) {
+               /* adjust to KB unit */
+               stats->hiwater_rss   = p->mm->hiwater_rss * PAGE_SIZE / KB;
+               stats->hiwater_vm    = p->mm->hiwater_vm * PAGE_SIZE / KB;
+       }
+       stats->read_char        = p->rchar;
+       stats->write_char       = p->wchar;
+       stats->read_syscalls    = p->syscr;
+       stats->write_syscalls   = p->syscw;
+}
+#undef KB
+#undef MB
+
+/**
+ * acct_update_integrals - update mm integral fields in task_struct
+ * @tsk: task_struct for accounting
+ */
+void acct_update_integrals(struct task_struct *tsk)
+{
+       if (likely(tsk->mm)) {
+               long delta = cputime_to_jiffies(
+                       cputime_sub(tsk->stime, tsk->acct_stimexpd));
+
+               if (delta == 0)
+                       return;
+               tsk->acct_stimexpd = tsk->stime;
+               tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
+               tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
+       }
+}
+
+/**
+ * acct_clear_integrals - clear the mm integral fields in task_struct
+ * @tsk: task_struct whose accounting fields are cleared
+ */
+void acct_clear_integrals(struct task_struct *tsk)
+{
+       tsk->acct_stimexpd = 0;
+       tsk->acct_rss_mem1 = 0;
+       tsk->acct_vm_mem1 = 0;
+}
+#endif
index 3430475fcd886d011c01370a558e0a5965dd950d..2e2368607aab1a8293739315d832c608463d8d5f 100644 (file)
@@ -102,7 +102,7 @@ static struct unwind_table {
        unsigned long size;
        struct unwind_table *link;
        const char *name;
-} root_table, *last_table;
+} root_table;
 
 struct unwind_item {
        enum item_location {
@@ -174,6 +174,8 @@ void __init unwind_init(void)
 
 #ifdef CONFIG_MODULES
 
+static struct unwind_table *last_table;
+
 /* Must be called with module_mutex held. */
 void *unwind_add_table(struct module *module,
                        const void *table_start,
index f1ac3184dc08c5566f7f1c812675cc57059a4e7e..f9ae75cc014566b95609983b803e0ef6282723f8 100644 (file)
@@ -284,7 +284,7 @@ config DEBUG_HIGHMEM
 config DEBUG_BUGVERBOSE
        bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
        depends on BUG
-       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV
+       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH
        default !EMBEDDED
        help
          Say Y here to make BUG() panics output the file name and line number
@@ -320,9 +320,18 @@ config DEBUG_VM
 
          If unsure, say N.
 
+config DEBUG_LIST
+       bool "Debug linked list manipulation"
+       depends on DEBUG_KERNEL
+       help
+         Enable this to turn on extended checks in the linked-list
+         walking routines.
+
+         If unsure, say N.
+
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
-       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32)
+       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH)
        default y if DEBUG_INFO && UML
        help
          If you say Y here the resulting kernel image will be slightly larger
index ef1d37afbbb66df24e3b60ccb304c063abe981f1..ddf3e676e1f47b1b18f8cc62ea31f17724e021f6 100644 (file)
@@ -7,6 +7,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
         idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
         sha1.o
 
+lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
 
 lib-y  += kobject.o kref.o kobject_uevent.o klist.o
@@ -28,6 +29,7 @@ lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_PLIST) += plist.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
+obj-$(CONFIG_DEBUG_LIST) += list_debug.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
diff --git a/lib/ioremap.c b/lib/ioremap.c
new file mode 100644 (file)
index 0000000..99fa277
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ */
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+
+static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
+               unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+       pte_t *pte;
+       unsigned long pfn;
+
+       pfn = phys_addr >> PAGE_SHIFT;
+       pte = pte_alloc_kernel(pmd, addr);
+       if (!pte)
+               return -ENOMEM;
+       do {
+               BUG_ON(!pte_none(*pte));
+               set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
+               pfn++;
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+       return 0;
+}
+
+static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
+               unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+       pmd_t *pmd;
+       unsigned long next;
+
+       phys_addr -= addr;
+       pmd = pmd_alloc(&init_mm, pud, addr);
+       if (!pmd)
+               return -ENOMEM;
+       do {
+               next = pmd_addr_end(addr, end);
+               if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
+                       return -ENOMEM;
+       } while (pmd++, addr = next, addr != end);
+       return 0;
+}
+
+static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
+               unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+       pud_t *pud;
+       unsigned long next;
+
+       phys_addr -= addr;
+       pud = pud_alloc(&init_mm, pgd, addr);
+       if (!pud)
+               return -ENOMEM;
+       do {
+               next = pud_addr_end(addr, end);
+               if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
+                       return -ENOMEM;
+       } while (pud++, addr = next, addr != end);
+       return 0;
+}
+
+int ioremap_page_range(unsigned long addr,
+                      unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+       pgd_t *pgd;
+       unsigned long start;
+       unsigned long next;
+       int err;
+
+       BUG_ON(addr >= end);
+
+       start = addr;
+       phys_addr -= addr;
+       pgd = pgd_offset_k(addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot);
+               if (err)
+                       break;
+       } while (pgd++, addr = next, addr != end);
+
+       flush_cache_vmap(start, end);
+
+       return err;
+}
diff --git a/lib/list_debug.c b/lib/list_debug.c
new file mode 100644 (file)
index 0000000..7ba9d82
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2006, Red Hat, Inc., Dave Jones
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the linked list implementations for
+ * DEBUG_LIST.
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+
+void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       if (unlikely(next->prev != prev)) {
+               printk(KERN_ERR "list_add corruption. next->prev should be %p, but was %p\n",
+                       prev, next->prev);
+               BUG();
+       }
+       if (unlikely(prev->next != next)) {
+               printk(KERN_ERR "list_add corruption. prev->next should be %p, but was %p\n",
+                       next, prev->next);
+               BUG();
+       }
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+EXPORT_SYMBOL(__list_add);
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+EXPORT_SYMBOL(list_add);
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+void list_del(struct list_head *entry)
+{
+       if (unlikely(entry->prev->next != entry)) {
+               printk(KERN_ERR "list_del corruption. prev->next should be %p, "
+                               "but was %p\n", entry, entry->prev->next);
+               BUG();
+       }
+       if (unlikely(entry->next->prev != entry)) {
+               printk(KERN_ERR "list_del corruption. next->prev should be %p, "
+                               "but was %p\n", entry, entry->next->prev);
+               BUG();
+       }
+       __list_del(entry->prev, entry->next);
+       entry->next = LIST_POISON1;
+       entry->prev = LIST_POISON2;
+}
+EXPORT_SYMBOL(list_del);
index 1e55ba1c2edfac510c41c87e47e7849f99a5f3b3..48499c2d88ccf16d65c8891e3fc5a23e8cdf283a 100644 (file)
@@ -322,6 +322,9 @@ struct rb_node *rb_next(struct rb_node *node)
 {
        struct rb_node *parent;
 
+       if (rb_parent(node) == node)
+               return NULL;
+
        /* If we have a right-hand child, go down and then left as far
           as we can. */
        if (node->rb_right) {
@@ -348,6 +351,9 @@ struct rb_node *rb_prev(struct rb_node *node)
 {
        struct rb_node *parent;
 
+       if (rb_parent(node) == node)
+               return NULL;
+
        /* If we have a left-hand child, go down and then right as far
           as we can. */
        if (node->rb_left) {
index b322421c2969f1e3046313e91dcd3a07aa3fca9a..901d0e7da89220fae47848d349633ae43c1afd7e 100644 (file)
@@ -146,7 +146,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int downgrading)
 /*
  * wait for a lock to be granted
  */
-static inline struct rw_semaphore *
+static struct rw_semaphore *
 rwsem_down_failed_common(struct rw_semaphore *sem,
                        struct rwsem_waiter *waiter, signed long adjustment)
 {
index 58c577dd82e5240e551d151b73ea31c55de8c309..dafaf1de2491aedb0a323aed4951e5084e58e18c 100644 (file)
@@ -99,11 +99,12 @@ static inline void debug_spin_unlock(spinlock_t *lock)
 
 static void __spin_lock_debug(spinlock_t *lock)
 {
-       int print_once = 1;
        u64 i;
+       u64 loops = loops_per_jiffy * HZ;
+       int print_once = 1;
 
        for (;;) {
-               for (i = 0; i < loops_per_jiffy * HZ; i++) {
+               for (i = 0; i < loops; i++) {
                        if (__raw_spin_trylock(&lock->raw_lock))
                                return;
                        __delay(1);
@@ -165,11 +166,12 @@ static void rwlock_bug(rwlock_t *lock, const char *msg)
 #if 0          /* __write_lock_debug() can lock up - maybe this can too? */
 static void __read_lock_debug(rwlock_t *lock)
 {
-       int print_once = 1;
        u64 i;
+       u64 loops = loops_per_jiffy * HZ;
+       int print_once = 1;
 
        for (;;) {
-               for (i = 0; i < loops_per_jiffy * HZ; i++) {
+               for (i = 0; i < loops; i++) {
                        if (__raw_read_trylock(&lock->raw_lock))
                                return;
                        __delay(1);
@@ -239,11 +241,12 @@ static inline void debug_write_unlock(rwlock_t *lock)
 #if 0          /* This can cause lockups */
 static void __write_lock_debug(rwlock_t *lock)
 {
-       int print_once = 1;
        u64 i;
+       u64 loops = loops_per_jiffy * HZ;
+       int print_once = 1;
 
        for (;;) {
-               for (i = 0; i < loops_per_jiffy * HZ; i++) {
+               for (i = 0; i < loops; i++) {
                        if (__raw_write_trylock(&lock->raw_lock))
                                return;
                        __delay(1);
index 87847c2ae9e28d9330c28df80dbef75ad99206b4..af575b61526b97749c31bb65221af72eb457353c 100644 (file)
  *
  *   A finite state machine consists of n states (struct ts_fsm_token)
  *   representing the pattern as a finite automation. The data is read
- *   sequentially on a octet basis. Every state token specifies the number
+ *   sequentially on an octet basis. Every state token specifies the number
  *   of recurrences and the type of value accepted which can be either a
  *   specific character or ctype based set of characters. The available
  *   type of recurrences include 1, (0|1), [0 n], and [1 n].
  *
- *   The algorithm differs between strict/non-strict mode specyfing
- *   whether the pattern has to start at the first octect. Strict mode
+ *   The algorithm differs between strict/non-strict mode specifying
+ *   whether the pattern has to start at the first octet. Strict mode
  *   is enabled by default and can be disabled by inserting
  *   TS_FSM_HEAD_IGNORE as the first token in the chain.
  *
@@ -44,7 +44,7 @@ struct ts_fsm
 #define _W             0x200 /* wildcard */
 
 /* Map to _ctype flags and some magic numbers */
-static u16 token_map[TS_FSM_TYPE_MAX+1] = {
+static const u16 token_map[TS_FSM_TYPE_MAX+1] = {
        [TS_FSM_SPECIFIC] = 0,
        [TS_FSM_WILDCARD] = _W,
        [TS_FSM_CNTRL]    = _C,
@@ -61,7 +61,7 @@ static u16 token_map[TS_FSM_TYPE_MAX+1] = {
        [TS_FSM_ASCII]    = _A,
 };
 
-static u16 token_lookup_tbl[256] = {
+static const u16 token_lookup_tbl[256] = {
 _W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,           /*   0-  3 */
 _W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,           /*   4-  7 */
 _W|_A|_C,      _W|_A|_C|_S,  _W|_A|_C|_S,  _W|_A|_C|_S,                /*   8- 11 */
index 8f5b45615f7bf1b43c35253b8f28f1ef4871818e..5d88489ef2de39e43245aa5483daa8af4a8a9452 100644 (file)
@@ -115,12 +115,17 @@ config SPARSEMEM_EXTREME
 # eventually, we can have this option just 'select SPARSEMEM'
 config MEMORY_HOTPLUG
        bool "Allow for memory hot-add"
-       depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG
+       depends on SPARSEMEM || X86_64_ACPI_NUMA
+       depends on HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG
        depends on (IA64 || X86 || PPC64)
 
 comment "Memory hotplug is currently incompatible with Software Suspend"
        depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
 
+config MEMORY_HOTPLUG_SPARSE
+       def_bool y
+       depends on SPARSEMEM && MEMORY_HOTPLUG
+
 # Heavily threaded applications may benefit from splitting the mm-wide
 # page_table_lock, so that faults on different parts of the user address
 # space can be handled with less contention: split it at this NR_CPUS.
index 60c56c0b5e1049218d38bf81df35ae897dbfdc5a..12b3a4eee88d56a3b4d4fe6c4255fa4a1ca81352 100644 (file)
@@ -12,11 +12,15 @@ obj-y                       := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
                           readahead.o swap.o truncate.o vmscan.o \
                           prio_tree.o util.o mmzone.o vmstat.o $(mmu-y)
 
+ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy)
+obj-y                  += bounce.o
+endif
 obj-$(CONFIG_SWAP)     += page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)        += hugetlb.o
 obj-$(CONFIG_NUMA)     += mempolicy.o
 obj-$(CONFIG_SPARSEMEM)        += sparse.o
 obj-$(CONFIG_SHMEM) += shmem.o
+obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_SLAB) += slab.o
diff --git a/mm/bounce.c b/mm/bounce.c
new file mode 100644 (file)
index 0000000..e4b62d2
--- /dev/null
@@ -0,0 +1,302 @@
+/* bounce buffer handling for block devices
+ *
+ * - Split from highmem.c
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/swap.h>
+#include <linux/bio.h>
+#include <linux/pagemap.h>
+#include <linux/mempool.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+#include <linux/hash.h>
+#include <linux/highmem.h>
+#include <linux/blktrace_api.h>
+#include <asm/tlbflush.h>
+
+#define POOL_SIZE      64
+#define ISA_POOL_SIZE  16
+
+static mempool_t *page_pool, *isa_page_pool;
+
+#ifdef CONFIG_HIGHMEM
+static __init int init_emergency_pool(void)
+{
+       struct sysinfo i;
+       si_meminfo(&i);
+       si_swapinfo(&i);
+
+       if (!i.totalhigh)
+               return 0;
+
+       page_pool = mempool_create_page_pool(POOL_SIZE, 0);
+       BUG_ON(!page_pool);
+       printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
+
+       return 0;
+}
+
+__initcall(init_emergency_pool);
+
+/*
+ * highmem version, map in to vec
+ */
+static void bounce_copy_vec(struct bio_vec *to, unsigned char *vfrom)
+{
+       unsigned long flags;
+       unsigned char *vto;
+
+       local_irq_save(flags);
+       vto = kmap_atomic(to->bv_page, KM_BOUNCE_READ);
+       memcpy(vto + to->bv_offset, vfrom, to->bv_len);
+       kunmap_atomic(vto, KM_BOUNCE_READ);
+       local_irq_restore(flags);
+}
+
+#else /* CONFIG_HIGHMEM */
+
+#define bounce_copy_vec(to, vfrom)     \
+       memcpy(page_address((to)->bv_page) + (to)->bv_offset, vfrom, (to)->bv_len)
+
+#endif /* CONFIG_HIGHMEM */
+
+/*
+ * allocate pages in the DMA region for the ISA pool
+ */
+static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data)
+{
+       return mempool_alloc_pages(gfp_mask | GFP_DMA, data);
+}
+
+/*
+ * gets called "every" time someone init's a queue with BLK_BOUNCE_ISA
+ * as the max address, so check if the pool has already been created.
+ */
+int init_emergency_isa_pool(void)
+{
+       if (isa_page_pool)
+               return 0;
+
+       isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa,
+                                      mempool_free_pages, (void *) 0);
+       BUG_ON(!isa_page_pool);
+
+       printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
+       return 0;
+}
+
+/*
+ * Simple bounce buffer support for highmem pages. Depending on the
+ * queue gfp mask set, *to may or may not be a highmem page. kmap it
+ * always, it will do the Right Thing
+ */
+static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
+{
+       unsigned char *vfrom;
+       struct bio_vec *tovec, *fromvec;
+       int i;
+
+       __bio_for_each_segment(tovec, to, i, 0) {
+               fromvec = from->bi_io_vec + i;
+
+               /*
+                * not bounced
+                */
+               if (tovec->bv_page == fromvec->bv_page)
+                       continue;
+
+               /*
+                * fromvec->bv_offset and fromvec->bv_len might have been
+                * modified by the block layer, so use the original copy,
+                * bounce_copy_vec already uses tovec->bv_len
+                */
+               vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
+
+               flush_dcache_page(tovec->bv_page);
+               bounce_copy_vec(tovec, vfrom);
+       }
+}
+
+static void bounce_end_io(struct bio *bio, mempool_t *pool, int err)
+{
+       struct bio *bio_orig = bio->bi_private;
+       struct bio_vec *bvec, *org_vec;
+       int i;
+
+       if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags))
+               set_bit(BIO_EOPNOTSUPP, &bio_orig->bi_flags);
+
+       /*
+        * free up bounce indirect pages used
+        */
+       __bio_for_each_segment(bvec, bio, i, 0) {
+               org_vec = bio_orig->bi_io_vec + i;
+               if (bvec->bv_page == org_vec->bv_page)
+                       continue;
+
+               dec_zone_page_state(bvec->bv_page, NR_BOUNCE);
+               mempool_free(bvec->bv_page, pool);
+       }
+
+       bio_endio(bio_orig, bio_orig->bi_size, err);
+       bio_put(bio);
+}
+
+static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
+{
+       if (bio->bi_size)
+               return 1;
+
+       bounce_end_io(bio, page_pool, err);
+       return 0;
+}
+
+static int bounce_end_io_write_isa(struct bio *bio, unsigned int bytes_done, int err)
+{
+       if (bio->bi_size)
+               return 1;
+
+       bounce_end_io(bio, isa_page_pool, err);
+       return 0;
+}
+
+static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err)
+{
+       struct bio *bio_orig = bio->bi_private;
+
+       if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+               copy_to_high_bio_irq(bio_orig, bio);
+
+       bounce_end_io(bio, pool, err);
+}
+
+static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err)
+{
+       if (bio->bi_size)
+               return 1;
+
+       __bounce_end_io_read(bio, page_pool, err);
+       return 0;
+}
+
+static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int err)
+{
+       if (bio->bi_size)
+               return 1;
+
+       __bounce_end_io_read(bio, isa_page_pool, err);
+       return 0;
+}
+
+static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig,
+                              mempool_t *pool)
+{
+       struct page *page;
+       struct bio *bio = NULL;
+       int i, rw = bio_data_dir(*bio_orig);
+       struct bio_vec *to, *from;
+
+       bio_for_each_segment(from, *bio_orig, i) {
+               page = from->bv_page;
+
+               /*
+                * is destination page below bounce pfn?
+                */
+               if (page_to_pfn(page) < q->bounce_pfn)
+                       continue;
+
+               /*
+                * irk, bounce it
+                */
+               if (!bio)
+                       bio = bio_alloc(GFP_NOIO, (*bio_orig)->bi_vcnt);
+
+               to = bio->bi_io_vec + i;
+
+               to->bv_page = mempool_alloc(pool, q->bounce_gfp);
+               to->bv_len = from->bv_len;
+               to->bv_offset = from->bv_offset;
+               inc_zone_page_state(to->bv_page, NR_BOUNCE);
+
+               if (rw == WRITE) {
+                       char *vto, *vfrom;
+
+                       flush_dcache_page(from->bv_page);
+                       vto = page_address(to->bv_page) + to->bv_offset;
+                       vfrom = kmap(from->bv_page) + from->bv_offset;
+                       memcpy(vto, vfrom, to->bv_len);
+                       kunmap(from->bv_page);
+               }
+       }
+
+       /*
+        * no pages bounced
+        */
+       if (!bio)
+               return;
+
+       /*
+        * at least one page was bounced, fill in possible non-highmem
+        * pages
+        */
+       __bio_for_each_segment(from, *bio_orig, i, 0) {
+               to = bio_iovec_idx(bio, i);
+               if (!to->bv_page) {
+                       to->bv_page = from->bv_page;
+                       to->bv_len = from->bv_len;
+                       to->bv_offset = from->bv_offset;
+               }
+       }
+
+       bio->bi_bdev = (*bio_orig)->bi_bdev;
+       bio->bi_flags |= (1 << BIO_BOUNCED);
+       bio->bi_sector = (*bio_orig)->bi_sector;
+       bio->bi_rw = (*bio_orig)->bi_rw;
+
+       bio->bi_vcnt = (*bio_orig)->bi_vcnt;
+       bio->bi_idx = (*bio_orig)->bi_idx;
+       bio->bi_size = (*bio_orig)->bi_size;
+
+       if (pool == page_pool) {
+               bio->bi_end_io = bounce_end_io_write;
+               if (rw == READ)
+                       bio->bi_end_io = bounce_end_io_read;
+       } else {
+               bio->bi_end_io = bounce_end_io_write_isa;
+               if (rw == READ)
+                       bio->bi_end_io = bounce_end_io_read_isa;
+       }
+
+       bio->bi_private = *bio_orig;
+       *bio_orig = bio;
+}
+
+void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig)
+{
+       mempool_t *pool;
+
+       /*
+        * for non-isa bounce case, just check if the bounce pfn is equal
+        * to or bigger than the highest pfn in the system -- in that case,
+        * don't waste time iterating over bio segments
+        */
+       if (!(q->bounce_gfp & GFP_DMA)) {
+               if (q->bounce_pfn >= blk_max_pfn)
+                       return;
+               pool = page_pool;
+       } else {
+               BUG_ON(!isa_page_pool);
+               pool = isa_page_pool;
+       }
+
+       blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE);
+
+       /*
+        * slow path
+        */
+       __blk_queue_bounce(q, bio_orig, pool);
+}
+
+EXPORT_SYMBOL(blk_queue_bounce);
index afcdc72b5e906658475a8ff47b5e3dcd389c0188..ec469235985d6e2cd89d39bf8bd40405f133e142 100644 (file)
@@ -1149,13 +1149,14 @@ success:
  * that can use the page cache directly.
  */
 ssize_t
-__generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
-               unsigned long nr_segs, loff_t *ppos)
+generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t pos)
 {
        struct file *filp = iocb->ki_filp;
        ssize_t retval;
        unsigned long seg;
        size_t count;
+       loff_t *ppos = &iocb->ki_pos;
 
        count = 0;
        for (seg = 0; seg < nr_segs; seg++) {
@@ -1179,7 +1180,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 
        /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
        if (filp->f_flags & O_DIRECT) {
-               loff_t pos = *ppos, size;
+               loff_t size;
                struct address_space *mapping;
                struct inode *inode;
 
@@ -1223,33 +1224,8 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 out:
        return retval;
 }
-EXPORT_SYMBOL(__generic_file_aio_read);
-
-ssize_t
-generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
-{
-       struct iovec local_iov = { .iov_base = buf, .iov_len = count };
-
-       BUG_ON(iocb->ki_pos != pos);
-       return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
-}
 EXPORT_SYMBOL(generic_file_aio_read);
 
-ssize_t
-generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
-       struct iovec local_iov = { .iov_base = buf, .iov_len = count };
-       struct kiocb kiocb;
-       ssize_t ret;
-
-       init_sync_kiocb(&kiocb, filp);
-       ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
-       return ret;
-}
-EXPORT_SYMBOL(generic_file_read);
-
 int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
 {
        ssize_t written;
@@ -1471,7 +1447,7 @@ outside_data_content:
         * accessible..
         */
        if (area->vm_mm == current->mm)
-               return NULL;
+               return NOPAGE_SIGBUS;
        /* Fall through to the non-read-ahead case */
 no_cached_page:
        /*
@@ -1496,7 +1472,7 @@ no_cached_page:
         */
        if (error == -ENOMEM)
                return NOPAGE_OOM;
-       return NULL;
+       return NOPAGE_SIGBUS;
 
 page_not_uptodate:
        if (!did_readaround) {
@@ -1565,7 +1541,7 @@ page_not_uptodate:
         */
        shrink_readahead_size_eio(file, ra);
        page_cache_release(page);
-       return NULL;
+       return NOPAGE_SIGBUS;
 }
 EXPORT_SYMBOL(filemap_nopage);
 
@@ -2020,6 +1996,7 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
                if (unlikely(*pos + *count > inode->i_sb->s_maxbytes))
                        *count = inode->i_sb->s_maxbytes - *pos;
        } else {
+#ifdef CONFIG_BLOCK
                loff_t isize;
                if (bdev_read_only(I_BDEV(inode)))
                        return -EPERM;
@@ -2031,6 +2008,9 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
 
                if (*pos + *count > isize)
                        *count = isize - *pos;
+#else
+               return -EPERM;
+#endif
        }
        return 0;
 }
@@ -2311,22 +2291,22 @@ out:
        current->backing_dev_info = NULL;
        return written ? written : err;
 }
-EXPORT_SYMBOL(generic_file_aio_write_nolock);
 
-ssize_t
-generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t *ppos)
+ssize_t generic_file_aio_write_nolock(struct kiocb *iocb,
+               const struct iovec *iov, unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        struct inode *inode = mapping->host;
        ssize_t ret;
-       loff_t pos = *ppos;
 
-       ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, ppos);
+       BUG_ON(iocb->ki_pos != pos);
+
+       ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
+                       &iocb->ki_pos);
 
        if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
-               int err;
+               ssize_t err;
 
                err = sync_page_range_nolock(inode, mapping, pos, ret);
                if (err < 0)
@@ -2334,51 +2314,21 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
        }
        return ret;
 }
+EXPORT_SYMBOL(generic_file_aio_write_nolock);
 
-static ssize_t
-__generic_file_write_nolock(struct file *file, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t *ppos)
-{
-       struct kiocb kiocb;
-       ssize_t ret;
-
-       init_sync_kiocb(&kiocb, file);
-       ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
-       if (ret == -EIOCBQUEUED)
-               ret = wait_on_sync_kiocb(&kiocb);
-       return ret;
-}
-
-ssize_t
-generic_file_write_nolock(struct file *file, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t *ppos)
-{
-       struct kiocb kiocb;
-       ssize_t ret;
-
-       init_sync_kiocb(&kiocb, file);
-       ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
-       return ret;
-}
-EXPORT_SYMBOL(generic_file_write_nolock);
-
-ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
-                              size_t count, loff_t pos)
+ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+               unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        struct inode *inode = mapping->host;
        ssize_t ret;
-       struct iovec local_iov = { .iov_base = (void __user *)buf,
-                                       .iov_len = count };
 
        BUG_ON(iocb->ki_pos != pos);
 
        mutex_lock(&inode->i_mutex);
-       ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1,
-                                               &iocb->ki_pos);
+       ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
+                       &iocb->ki_pos);
        mutex_unlock(&inode->i_mutex);
 
        if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
@@ -2392,66 +2342,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
 }
 EXPORT_SYMBOL(generic_file_aio_write);
 
-ssize_t generic_file_write(struct file *file, const char __user *buf,
-                          size_t count, loff_t *ppos)
-{
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       ssize_t ret;
-       struct iovec local_iov = { .iov_base = (void __user *)buf,
-                                       .iov_len = count };
-
-       mutex_lock(&inode->i_mutex);
-       ret = __generic_file_write_nolock(file, &local_iov, 1, ppos);
-       mutex_unlock(&inode->i_mutex);
-
-       if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
-               ssize_t err;
-
-               err = sync_page_range(inode, mapping, *ppos - ret, ret);
-               if (err < 0)
-                       ret = err;
-       }
-       return ret;
-}
-EXPORT_SYMBOL(generic_file_write);
-
-ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
-                       unsigned long nr_segs, loff_t *ppos)
-{
-       struct kiocb kiocb;
-       ssize_t ret;
-
-       init_sync_kiocb(&kiocb, filp);
-       ret = __generic_file_aio_read(&kiocb, iov, nr_segs, ppos);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&kiocb);
-       return ret;
-}
-EXPORT_SYMBOL(generic_file_readv);
-
-ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
-                       unsigned long nr_segs, loff_t *ppos)
-{
-       struct address_space *mapping = file->f_mapping;
-       struct inode *inode = mapping->host;
-       ssize_t ret;
-
-       mutex_lock(&inode->i_mutex);
-       ret = __generic_file_write_nolock(file, iov, nr_segs, ppos);
-       mutex_unlock(&inode->i_mutex);
-
-       if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
-               int err;
-
-               err = sync_page_range(inode, mapping, *ppos - ret, ret);
-               if (err < 0)
-                       ret = err;
-       }
-       return ret;
-}
-EXPORT_SYMBOL(generic_file_writev);
-
 /*
  * Called under i_mutex for writes to S_ISREG files.   Returns -EIO if something
  * went wrong during pagecache shootdown.
@@ -2491,3 +2381,33 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        }
        return retval;
 }
+
+/**
+ * try_to_release_page() - release old fs-specific metadata on a page
+ *
+ * @page: the page which the kernel is trying to free
+ * @gfp_mask: memory allocation flags (and I/O mode)
+ *
+ * The address_space is to try to release any data against the page
+ * (presumably at page->private).  If the release was successful, return `1'.
+ * Otherwise return zero.
+ *
+ * The @gfp_mask argument specifies whether I/O may be performed to release
+ * this page (__GFP_IO), and whether the call may block (__GFP_WAIT).
+ *
+ * NOTE: @gfp_mask may go away, and this function may become non-blocking.
+ */
+int try_to_release_page(struct page *page, gfp_t gfp_mask)
+{
+       struct address_space * const mapping = page->mapping;
+
+       BUG_ON(!PageLocked(page));
+       if (PageWriteback(page))
+               return 0;
+
+       if (mapping && mapping->a_ops->releasepage)
+               return mapping->a_ops->releasepage(page, gfp_mask);
+       return try_to_free_buffers(page);
+}
+
+EXPORT_SYMBOL(try_to_release_page);
index aa30618ec6b2cd356c57896a2099a3e4b2a5e39c..7a9d0f5d246da922c132738f2476a688812fc1ac 100644 (file)
@@ -39,7 +39,7 @@ static int zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
        } else {
                if (!pte_file(pte))
                        free_swap_and_cache(pte_to_swp_entry(pte));
-               pte_clear(mm, addr, ptep);
+               pte_clear_not_present_full(mm, addr, ptep, 0);
        }
        return !!page;
 }
index ee5519b176ee9a2fc704e9af51f4f26836b53df1..0206e7e5018c8998c87349706fe1fcfb5644933c 100644 (file)
 #include <linux/blktrace_api.h>
 #include <asm/tlbflush.h>
 
-static mempool_t *page_pool, *isa_page_pool;
-
-static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data)
-{
-       return mempool_alloc_pages(gfp_mask | GFP_DMA, data);
-}
-
 /*
  * Virtual_count is not a pure "count".
  *  0 means that it is not mapped, and has not been mapped
@@ -217,282 +210,8 @@ void fastcall kunmap_high(struct page *page)
 }
 
 EXPORT_SYMBOL(kunmap_high);
-
-#define POOL_SIZE      64
-
-static __init int init_emergency_pool(void)
-{
-       struct sysinfo i;
-       si_meminfo(&i);
-       si_swapinfo(&i);
-        
-       if (!i.totalhigh)
-               return 0;
-
-       page_pool = mempool_create_page_pool(POOL_SIZE, 0);
-       BUG_ON(!page_pool);
-       printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
-
-       return 0;
-}
-
-__initcall(init_emergency_pool);
-
-/*
- * highmem version, map in to vec
- */
-static void bounce_copy_vec(struct bio_vec *to, unsigned char *vfrom)
-{
-       unsigned long flags;
-       unsigned char *vto;
-
-       local_irq_save(flags);
-       vto = kmap_atomic(to->bv_page, KM_BOUNCE_READ);
-       memcpy(vto + to->bv_offset, vfrom, to->bv_len);
-       kunmap_atomic(vto, KM_BOUNCE_READ);
-       local_irq_restore(flags);
-}
-
-#else /* CONFIG_HIGHMEM */
-
-#define bounce_copy_vec(to, vfrom)     \
-       memcpy(page_address((to)->bv_page) + (to)->bv_offset, vfrom, (to)->bv_len)
-
 #endif
 
-#define ISA_POOL_SIZE  16
-
-/*
- * gets called "every" time someone init's a queue with BLK_BOUNCE_ISA
- * as the max address, so check if the pool has already been created.
- */
-int init_emergency_isa_pool(void)
-{
-       if (isa_page_pool)
-               return 0;
-
-       isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa,
-                                      mempool_free_pages, (void *) 0);
-       BUG_ON(!isa_page_pool);
-
-       printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
-       return 0;
-}
-
-/*
- * Simple bounce buffer support for highmem pages. Depending on the
- * queue gfp mask set, *to may or may not be a highmem page. kmap it
- * always, it will do the Right Thing
- */
-static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
-{
-       unsigned char *vfrom;
-       struct bio_vec *tovec, *fromvec;
-       int i;
-
-       __bio_for_each_segment(tovec, to, i, 0) {
-               fromvec = from->bi_io_vec + i;
-
-               /*
-                * not bounced
-                */
-               if (tovec->bv_page == fromvec->bv_page)
-                       continue;
-
-               /*
-                * fromvec->bv_offset and fromvec->bv_len might have been
-                * modified by the block layer, so use the original copy,
-                * bounce_copy_vec already uses tovec->bv_len
-                */
-               vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
-
-               flush_dcache_page(tovec->bv_page);
-               bounce_copy_vec(tovec, vfrom);
-       }
-}
-
-static void bounce_end_io(struct bio *bio, mempool_t *pool, int err)
-{
-       struct bio *bio_orig = bio->bi_private;
-       struct bio_vec *bvec, *org_vec;
-       int i;
-
-       if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags))
-               set_bit(BIO_EOPNOTSUPP, &bio_orig->bi_flags);
-
-       /*
-        * free up bounce indirect pages used
-        */
-       __bio_for_each_segment(bvec, bio, i, 0) {
-               org_vec = bio_orig->bi_io_vec + i;
-               if (bvec->bv_page == org_vec->bv_page)
-                       continue;
-
-               dec_zone_page_state(bvec->bv_page, NR_BOUNCE);
-               mempool_free(bvec->bv_page, pool);
-       }
-
-       bio_endio(bio_orig, bio_orig->bi_size, err);
-       bio_put(bio);
-}
-
-static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
-{
-       if (bio->bi_size)
-               return 1;
-
-       bounce_end_io(bio, page_pool, err);
-       return 0;
-}
-
-static int bounce_end_io_write_isa(struct bio *bio, unsigned int bytes_done, int err)
-{
-       if (bio->bi_size)
-               return 1;
-
-       bounce_end_io(bio, isa_page_pool, err);
-       return 0;
-}
-
-static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err)
-{
-       struct bio *bio_orig = bio->bi_private;
-
-       if (test_bit(BIO_UPTODATE, &bio->bi_flags))
-               copy_to_high_bio_irq(bio_orig, bio);
-
-       bounce_end_io(bio, pool, err);
-}
-
-static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err)
-{
-       if (bio->bi_size)
-               return 1;
-
-       __bounce_end_io_read(bio, page_pool, err);
-       return 0;
-}
-
-static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int err)
-{
-       if (bio->bi_size)
-               return 1;
-
-       __bounce_end_io_read(bio, isa_page_pool, err);
-       return 0;
-}
-
-static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig,
-                              mempool_t *pool)
-{
-       struct page *page;
-       struct bio *bio = NULL;
-       int i, rw = bio_data_dir(*bio_orig);
-       struct bio_vec *to, *from;
-
-       bio_for_each_segment(from, *bio_orig, i) {
-               page = from->bv_page;
-
-               /*
-                * is destination page below bounce pfn?
-                */
-               if (page_to_pfn(page) < q->bounce_pfn)
-                       continue;
-
-               /*
-                * irk, bounce it
-                */
-               if (!bio)
-                       bio = bio_alloc(GFP_NOIO, (*bio_orig)->bi_vcnt);
-
-               to = bio->bi_io_vec + i;
-
-               to->bv_page = mempool_alloc(pool, q->bounce_gfp);
-               to->bv_len = from->bv_len;
-               to->bv_offset = from->bv_offset;
-               inc_zone_page_state(to->bv_page, NR_BOUNCE);
-
-               if (rw == WRITE) {
-                       char *vto, *vfrom;
-
-                       flush_dcache_page(from->bv_page);
-                       vto = page_address(to->bv_page) + to->bv_offset;
-                       vfrom = kmap(from->bv_page) + from->bv_offset;
-                       memcpy(vto, vfrom, to->bv_len);
-                       kunmap(from->bv_page);
-               }
-       }
-
-       /*
-        * no pages bounced
-        */
-       if (!bio)
-               return;
-
-       /*
-        * at least one page was bounced, fill in possible non-highmem
-        * pages
-        */
-       __bio_for_each_segment(from, *bio_orig, i, 0) {
-               to = bio_iovec_idx(bio, i);
-               if (!to->bv_page) {
-                       to->bv_page = from->bv_page;
-                       to->bv_len = from->bv_len;
-                       to->bv_offset = from->bv_offset;
-               }
-       }
-
-       bio->bi_bdev = (*bio_orig)->bi_bdev;
-       bio->bi_flags |= (1 << BIO_BOUNCED);
-       bio->bi_sector = (*bio_orig)->bi_sector;
-       bio->bi_rw = (*bio_orig)->bi_rw;
-
-       bio->bi_vcnt = (*bio_orig)->bi_vcnt;
-       bio->bi_idx = (*bio_orig)->bi_idx;
-       bio->bi_size = (*bio_orig)->bi_size;
-
-       if (pool == page_pool) {
-               bio->bi_end_io = bounce_end_io_write;
-               if (rw == READ)
-                       bio->bi_end_io = bounce_end_io_read;
-       } else {
-               bio->bi_end_io = bounce_end_io_write_isa;
-               if (rw == READ)
-                       bio->bi_end_io = bounce_end_io_read_isa;
-       }
-
-       bio->bi_private = *bio_orig;
-       *bio_orig = bio;
-}
-
-void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig)
-{
-       mempool_t *pool;
-
-       /*
-        * for non-isa bounce case, just check if the bounce pfn is equal
-        * to or bigger than the highest pfn in the system -- in that case,
-        * don't waste time iterating over bio segments
-        */
-       if (!(q->bounce_gfp & GFP_DMA)) {
-               if (q->bounce_pfn >= blk_max_pfn)
-                       return;
-               pool = page_pool;
-       } else {
-               BUG_ON(!isa_page_pool);
-               pool = isa_page_pool;
-       }
-
-       blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE);
-
-       /*
-        * slow path
-        */
-       __blk_queue_bounce(q, bio_orig, pool);
-}
-
-EXPORT_SYMBOL(blk_queue_bounce);
-
 #if defined(HASHED_PAGE_VIRTUAL)
 
 #define PA_HASH_ORDER  7
index 92a3ebd8d7951daff767f409836c8490cf283028..9cf3f341a28a6cf4c53af58f01959a9cf7c23eb1 100644 (file)
@@ -467,7 +467,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
         */
        if (is_cow_mapping(vm_flags)) {
                ptep_set_wrprotect(src_mm, addr, src_pte);
-               pte = *src_pte;
+               pte = pte_wrprotect(pte);
        }
 
        /*
@@ -506,6 +506,7 @@ again:
        src_pte = pte_offset_map_nested(src_pmd, addr);
        src_ptl = pte_lockptr(src_mm, src_pmd);
        spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
+       arch_enter_lazy_mmu_mode();
 
        do {
                /*
@@ -527,6 +528,7 @@ again:
                progress += 8;
        } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
 
+       arch_leave_lazy_mmu_mode();
        spin_unlock(src_ptl);
        pte_unmap_nested(src_pte - 1);
        add_mm_rss(dst_mm, rss[0], rss[1]);
@@ -628,6 +630,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
        int anon_rss = 0;
 
        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       arch_enter_lazy_mmu_mode();
        do {
                pte_t ptent = *pte;
                if (pte_none(ptent)) {
@@ -690,10 +693,11 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
                        continue;
                if (!pte_file(ptent))
                        free_swap_and_cache(pte_to_swp_entry(ptent));
-               pte_clear_full(mm, addr, pte, tlb->fullmm);
+               pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
        } while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0));
 
        add_mm_rss(mm, file_rss, anon_rss);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
 
        return addr;
@@ -1109,6 +1113,7 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
        pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
        if (!pte)
                return -ENOMEM;
+       arch_enter_lazy_mmu_mode();
        do {
                struct page *page = ZERO_PAGE(addr);
                pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
@@ -1118,6 +1123,7 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
                BUG_ON(!pte_none(*pte));
                set_pte_at(mm, addr, pte, zero_pte);
        } while (pte++, addr += PAGE_SIZE, addr != end);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
        return 0;
 }
@@ -1275,11 +1281,13 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd,
        pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
        if (!pte)
                return -ENOMEM;
+       arch_enter_lazy_mmu_mode();
        do {
                BUG_ON(!pte_none(*pte));
                set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
                pfn++;
        } while (pte++, addr += PAGE_SIZE, addr != end);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
        return 0;
 }
@@ -1577,7 +1585,14 @@ gotten:
                entry = mk_pte(new_page, vma->vm_page_prot);
                entry = maybe_mkwrite(pte_mkdirty(entry), vma);
                lazy_mmu_prot_update(entry);
-               ptep_establish(vma, address, page_table, entry);
+               /*
+                * Clear the pte entry and flush it first, before updating the
+                * pte with the new entry. This will avoid a race condition
+                * seen in the presence of one thread doing SMC and another
+                * thread doing COW.
+                */
+               ptep_clear_flush(vma, address, page_table);
+               set_pte_at(mm, address, page_table, entry);
                update_mmu_cache(vma, address, entry);
                lru_cache_add_active(new_page);
                page_add_new_anon_rmap(new_page, vma, address);
@@ -2255,6 +2270,54 @@ oom:
        return VM_FAULT_OOM;
 }
 
+/*
+ * do_no_pfn() tries to create a new page mapping for a page without
+ * a struct_page backing it
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
+ *
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
+ *
+ * It is expected that the ->nopfn handler always returns the same pfn
+ * for a given virtual mapping.
+ *
+ * Mark this `noinline' to prevent it from bloating the main pagefault code.
+ */
+static noinline int do_no_pfn(struct mm_struct *mm, struct vm_area_struct *vma,
+                    unsigned long address, pte_t *page_table, pmd_t *pmd,
+                    int write_access)
+{
+       spinlock_t *ptl;
+       pte_t entry;
+       unsigned long pfn;
+       int ret = VM_FAULT_MINOR;
+
+       pte_unmap(page_table);
+       BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+       BUG_ON(is_cow_mapping(vma->vm_flags));
+
+       pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
+       if (pfn == NOPFN_OOM)
+               return VM_FAULT_OOM;
+       if (pfn == NOPFN_SIGBUS)
+               return VM_FAULT_SIGBUS;
+
+       page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+
+       /* Only go through if we didn't race with anybody else... */
+       if (pte_none(*page_table)) {
+               entry = pfn_pte(pfn, vma->vm_page_prot);
+               if (write_access)
+                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+               set_pte_at(mm, address, page_table, entry);
+       }
+       pte_unmap_unlock(page_table, ptl);
+       return ret;
+}
+
 /*
  * Fault of a previously existing named mapping. Repopulate the pte
  * from the encoded file_pte if possible. This enables swappable
@@ -2317,11 +2380,17 @@ static inline int handle_pte_fault(struct mm_struct *mm,
        old_entry = entry = *pte;
        if (!pte_present(entry)) {
                if (pte_none(entry)) {
-                       if (!vma->vm_ops || !vma->vm_ops->nopage)
-                               return do_anonymous_page(mm, vma, address,
-                                       pte, pmd, write_access);
-                       return do_no_page(mm, vma, address,
-                                       pte, pmd, write_access);
+                       if (vma->vm_ops) {
+                               if (vma->vm_ops->nopage)
+                                       return do_no_page(mm, vma, address,
+                                                         pte, pmd,
+                                                         write_access);
+                               if (unlikely(vma->vm_ops->nopfn))
+                                       return do_no_pfn(mm, vma, address, pte,
+                                                        pmd, write_access);
+                       }
+                       return do_anonymous_page(mm, vma, address,
+                                                pte, pmd, write_access);
                }
                if (pte_file(entry))
                        return do_file_page(mm, vma, address,
@@ -2550,3 +2619,56 @@ int in_gate_area_no_task(unsigned long addr)
 }
 
 #endif /* __HAVE_ARCH_GATE_AREA */
+
+/*
+ * Access another process' address space.
+ * Source/target buffer must be kernel space,
+ * Do not walk the page table directly, use get_user_pages
+ */
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       struct mm_struct *mm;
+       struct vm_area_struct *vma;
+       struct page *page;
+       void *old_buf = buf;
+
+       mm = get_task_mm(tsk);
+       if (!mm)
+               return 0;
+
+       down_read(&mm->mmap_sem);
+       /* ignore errors, just check how much was sucessfully transfered */
+       while (len) {
+               int bytes, ret, offset;
+               void *maddr;
+
+               ret = get_user_pages(tsk, mm, addr, 1,
+                               write, 1, &page, &vma);
+               if (ret <= 0)
+                       break;
+
+               bytes = len;
+               offset = addr & (PAGE_SIZE-1);
+               if (bytes > PAGE_SIZE-offset)
+                       bytes = PAGE_SIZE-offset;
+
+               maddr = kmap(page);
+               if (write) {
+                       copy_to_user_page(vma, page, addr,
+                                         maddr + offset, buf, bytes);
+                       set_page_dirty_lock(page);
+               } else {
+                       copy_from_user_page(vma, page, addr,
+                                           buf, maddr + offset, bytes);
+               }
+               kunmap(page);
+               page_cache_release(page);
+               len -= bytes;
+               buf += bytes;
+               addr += bytes;
+       }
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+
+       return buf - old_buf;
+}
index c37319542b700a92339fdfc4427a5fc4d6fa2ee4..fd678a662eae1a015ef6393c2b6f23e586592105 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/pagevec.h>
+#include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
 #include <linux/highmem.h>
 #include <linux/vmalloc.h>
 #include <linux/ioport.h>
+#include <linux/cpuset.h>
 
 #include <asm/tlbflush.h>
 
-extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
-                         unsigned long size);
+/* add this memory to iomem resource */
+static struct resource *register_memory_resource(u64 start, u64 size)
+{
+       struct resource *res;
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       BUG_ON(!res);
+
+       res->name = "System RAM";
+       res->start = start;
+       res->end = start + size - 1;
+       res->flags = IORESOURCE_MEM;
+       if (request_resource(&iomem_resource, res) < 0) {
+               printk("System RAM resource %llx - %llx cannot be added\n",
+               (unsigned long long)res->start, (unsigned long long)res->end);
+               kfree(res);
+               res = NULL;
+       }
+       return res;
+}
+
+static void release_memory_resource(struct resource *res)
+{
+       if (!res)
+               return;
+       release_resource(res);
+       kfree(res);
+       return;
+}
+
+
+#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
 {
        struct pglist_data *pgdat = zone->zone_pgdat;
@@ -45,8 +76,6 @@ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
        return 0;
 }
 
-extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
-                                 int nr_pages);
 static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
 {
        int nr_pages = PAGES_PER_SECTION;
@@ -191,8 +220,10 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
        if (need_zonelists_rebuild)
                build_all_zonelists();
        vm_total_pages = nr_free_pagecache_pages();
+       writeback_set_ratelimit();
        return 0;
 }
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
 static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
 {
@@ -222,36 +253,6 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
        return;
 }
 
-/* add this memory to iomem resource */
-static struct resource *register_memory_resource(u64 start, u64 size)
-{
-       struct resource *res;
-       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
-       BUG_ON(!res);
-
-       res->name = "System RAM";
-       res->start = start;
-       res->end = start + size - 1;
-       res->flags = IORESOURCE_MEM;
-       if (request_resource(&iomem_resource, res) < 0) {
-               printk("System RAM resource %llx - %llx cannot be added\n",
-               (unsigned long long)res->start, (unsigned long long)res->end);
-               kfree(res);
-               res = NULL;
-       }
-       return res;
-}
-
-static void release_memory_resource(struct resource *res)
-{
-       if (!res)
-               return;
-       release_resource(res);
-       kfree(res);
-       return;
-}
-
-
 
 int add_memory(int nid, u64 start, u64 size)
 {
@@ -283,6 +284,8 @@ int add_memory(int nid, u64 start, u64 size)
        /* we online node here. we can't roll back from here. */
        node_set_online(nid);
 
+       cpuset_track_online_nodes();
+
        if (new_pgdat) {
                ret = register_one_node(nid);
                /*
index 38f89650bc84962d9209b5035297b173c3b16c44..25788b1b7fcff4b6d116dffab3abe6e1ecc17d08 100644 (file)
@@ -1136,7 +1136,9 @@ static unsigned interleave_nodes(struct mempolicy *policy)
  */
 unsigned slab_node(struct mempolicy *policy)
 {
-       switch (policy->policy) {
+       int pol = policy ? policy->policy : MPOL_DEFAULT;
+
+       switch (pol) {
        case MPOL_INTERLEAVE:
                return interleave_nodes(policy);
 
@@ -1322,12 +1324,11 @@ struct mempolicy *__mpol_copy(struct mempolicy *old)
        atomic_set(&new->refcnt, 1);
        if (new->policy == MPOL_BIND) {
                int sz = ksize(old->v.zonelist);
-               new->v.zonelist = kmalloc(sz, SLAB_KERNEL);
+               new->v.zonelist = kmemdup(old->v.zonelist, sz, SLAB_KERNEL);
                if (!new->v.zonelist) {
                        kmem_cache_free(policy_cache, new);
                        return ERR_PTR(-ENOMEM);
                }
-               memcpy(new->v.zonelist, old->v.zonelist, sz);
        }
        return new;
 }
index 20a8c2687b1efea5b7bb1ab23d6b9195a2e97453..ba2453f9483dfe4b03b3df1c089607da36ebb60c 100644 (file)
@@ -409,6 +409,7 @@ int migrate_page(struct address_space *mapping,
 }
 EXPORT_SYMBOL(migrate_page);
 
+#ifdef CONFIG_BLOCK
 /*
  * Migration function for pages with buffers. This function can only be used
  * if the underlying filesystem guarantees that no other references to "page"
@@ -466,6 +467,7 @@ int buffer_migrate_page(struct address_space *mapping,
        return 0;
 }
 EXPORT_SYMBOL(buffer_migrate_page);
+#endif
 
 /*
  * Writeback a page to clean the dirty state
@@ -525,7 +527,7 @@ static int fallback_migrate_page(struct address_space *mapping,
         * Buffers may be managed in a filesystem specific way.
         * We must have no buffers or drop them.
         */
-       if (page_has_buffers(page) &&
+       if (PagePrivate(page) &&
            !try_to_release_page(page, GFP_KERNEL))
                return -EAGAIN;
 
index 955f9d0e38aa3f5f35d09eb2473ce3f565196292..3b8f3c0c63f3b948cda9edca535d7aaa65b4a38b 100644 (file)
@@ -34,6 +34,7 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
        spinlock_t *ptl;
 
        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       arch_enter_lazy_mmu_mode();
        do {
                oldpte = *pte;
                if (pte_present(oldpte)) {
@@ -70,6 +71,7 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
                }
 
        } while (pte++, addr += PAGE_SIZE, addr != end);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
 }
 
index 7c15cf3373ad0d0e94ba6f5b74145339da0052d3..9c769fa29f32aff451ef6ff86ce836c1fc0bf856 100644 (file)
@@ -98,6 +98,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
        new_ptl = pte_lockptr(mm, new_pmd);
        if (new_ptl != old_ptl)
                spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
+       arch_enter_lazy_mmu_mode();
 
        for (; old_addr < old_end; old_pte++, old_addr += PAGE_SIZE,
                                   new_pte++, new_addr += PAGE_SIZE) {
@@ -109,6 +110,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
                set_pte_at(mm, new_addr, new_pte, pte);
        }
 
+       arch_leave_lazy_mmu_mode();
        if (new_ptl != old_ptl)
                spin_unlock(new_ptl);
        pte_unmap_nested(new_pte - 1);
index d99dea31e443f2505ce97b967c69681f2ae1e359..365019599df8556c23d493f007a07dbf201add00 100644 (file)
@@ -122,26 +122,50 @@ unsigned int kobjsize(const void *objp)
 }
 
 /*
- * The nommu dodgy version :-)
+ * get a list of pages in an address range belonging to the specified process
+ * and indicate the VMA that covers each page
+ * - this is potentially dodgy as we may end incrementing the page count of a
+ *   slab page or a secondary page from a compound page
+ * - don't permit access to VMAs that don't support it, such as I/O mappings
  */
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        unsigned long start, int len, int write, int force,
        struct page **pages, struct vm_area_struct **vmas)
 {
+       struct vm_area_struct *vma;
+       unsigned long vm_flags;
        int i;
-       static struct vm_area_struct dummy_vma;
+
+       /* calculate required read or write permissions.
+        * - if 'force' is set, we only require the "MAY" flags.
+        */
+       vm_flags  = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+       vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 
        for (i = 0; i < len; i++) {
+               vma = find_vma(mm, start);
+               if (!vma)
+                       goto finish_or_fault;
+
+               /* protect what we can, including chardevs */
+               if (vma->vm_flags & (VM_IO | VM_PFNMAP) ||
+                   !(vm_flags & vma->vm_flags))
+                       goto finish_or_fault;
+
                if (pages) {
                        pages[i] = virt_to_page(start);
                        if (pages[i])
                                page_cache_get(pages[i]);
                }
                if (vmas)
-                       vmas[i] = &dummy_vma;
+                       vmas[i] = vma;
                start += PAGE_SIZE;
        }
-       return(i);
+
+       return i;
+
+finish_or_fault:
+       return i ? : -EFAULT;
 }
 
 EXPORT_SYMBOL(get_user_pages);
@@ -286,6 +310,77 @@ static void show_process_blocks(void)
 }
 #endif /* DEBUG */
 
+/*
+ * add a VMA into a process's mm_struct in the appropriate place in the list
+ * - should be called with mm->mmap_sem held writelocked
+ */
+static void add_vma_to_mm(struct mm_struct *mm, struct vm_list_struct *vml)
+{
+       struct vm_list_struct **ppv;
+
+       for (ppv = &current->mm->context.vmlist; *ppv; ppv = &(*ppv)->next)
+               if ((*ppv)->vma->vm_start > vml->vma->vm_start)
+                       break;
+
+       vml->next = *ppv;
+       *ppv = vml;
+}
+
+/*
+ * look up the first VMA in which addr resides, NULL if none
+ * - should be called with mm->mmap_sem at least held readlocked
+ */
+struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+{
+       struct vm_list_struct *loop, *vml;
+
+       /* search the vm_start ordered list */
+       vml = NULL;
+       for (loop = mm->context.vmlist; loop; loop = loop->next) {
+               if (loop->vma->vm_start > addr)
+                       break;
+               vml = loop;
+       }
+
+       if (vml && vml->vma->vm_end > addr)
+               return vml->vma;
+
+       return NULL;
+}
+EXPORT_SYMBOL(find_vma);
+
+/*
+ * find a VMA
+ * - we don't extend stack VMAs under NOMMU conditions
+ */
+struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
+{
+       return find_vma(mm, addr);
+}
+
+/*
+ * look up the first VMA exactly that exactly matches addr
+ * - should be called with mm->mmap_sem at least held readlocked
+ */
+static inline struct vm_area_struct *find_vma_exact(struct mm_struct *mm,
+                                                   unsigned long addr)
+{
+       struct vm_list_struct *vml;
+
+       /* search the vm_start ordered list */
+       for (vml = mm->context.vmlist; vml; vml = vml->next) {
+               if (vml->vma->vm_start == addr)
+                       return vml->vma;
+               if (vml->vma->vm_start > addr)
+                       break;
+       }
+
+       return NULL;
+}
+
+/*
+ * find a VMA in the global tree
+ */
 static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
 {
        struct vm_area_struct *vma;
@@ -305,6 +400,9 @@ static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
        return NULL;
 }
 
+/*
+ * add a VMA in the global tree
+ */
 static void add_nommu_vma(struct vm_area_struct *vma)
 {
        struct vm_area_struct *pvma;
@@ -351,6 +449,9 @@ static void add_nommu_vma(struct vm_area_struct *vma)
        rb_insert_color(&vma->vm_rb, &nommu_vma_tree);
 }
 
+/*
+ * delete a VMA from the global list
+ */
 static void delete_nommu_vma(struct vm_area_struct *vma)
 {
        struct address_space *mapping;
@@ -828,8 +929,7 @@ unsigned long do_mmap_pgoff(struct file *file,
        realalloc += kobjsize(vml);
        askedalloc += sizeof(*vml);
 
-       vml->next = current->mm->context.vmlist;
-       current->mm->context.vmlist = vml;
+       add_vma_to_mm(current->mm, vml);
 
        up_write(&nommu_vma_sem);
 
@@ -848,7 +948,8 @@ unsigned long do_mmap_pgoff(struct file *file,
        up_write(&nommu_vma_sem);
        kfree(vml);
        if (vma) {
-               fput(vma->vm_file);
+               if (vma->vm_file)
+                       fput(vma->vm_file);
                kfree(vma);
        }
        return ret;
@@ -908,6 +1009,11 @@ static void put_vma(struct vm_area_struct *vma)
        }
 }
 
+/*
+ * release a mapping
+ * - under NOMMU conditions the parameters must match exactly to the mapping to
+ *   be removed
+ */
 int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 {
        struct vm_list_struct *vml, **parent;
@@ -917,10 +1023,13 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
        printk("do_munmap:\n");
 #endif
 
-       for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next)
+       for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next) {
+               if ((*parent)->vma->vm_start > addr)
+                       break;
                if ((*parent)->vma->vm_start == addr &&
                    ((len == 0) || ((*parent)->vma->vm_end == end)))
                        goto found;
+       }
 
        printk("munmap of non-mmaped memory by process %d (%s): %p\n",
               current->pid, current->comm, (void *) addr);
@@ -946,7 +1055,20 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
        return 0;
 }
 
-/* Release all mmaps. */
+asmlinkage long sys_munmap(unsigned long addr, size_t len)
+{
+       int ret;
+       struct mm_struct *mm = current->mm;
+
+       down_write(&mm->mmap_sem);
+       ret = do_munmap(mm, addr, len);
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+
+/*
+ * Release all mappings
+ */
 void exit_mmap(struct mm_struct * mm)
 {
        struct vm_list_struct *tmp;
@@ -973,37 +1095,26 @@ void exit_mmap(struct mm_struct * mm)
        }
 }
 
-asmlinkage long sys_munmap(unsigned long addr, size_t len)
-{
-       int ret;
-       struct mm_struct *mm = current->mm;
-
-       down_write(&mm->mmap_sem);
-       ret = do_munmap(mm, addr, len);
-       up_write(&mm->mmap_sem);
-       return ret;
-}
-
 unsigned long do_brk(unsigned long addr, unsigned long len)
 {
        return -ENOMEM;
 }
 
 /*
- * Expand (or shrink) an existing mapping, potentially moving it at the
- * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
+ * expand (or shrink) an existing mapping, potentially moving it at the same
+ * time (controlled by the MREMAP_MAYMOVE flag and available VM space)
  *
- * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise
- * This option implies MREMAP_MAYMOVE.
+ * under NOMMU conditions, we only permit changing a mapping's size, and only
+ * as long as it stays within the hole allocated by the kmalloc() call in
+ * do_mmap_pgoff() and the block is not shareable
  *
- * on uClinux, we only permit changing a mapping's size, and only as long as it stays within the
- * hole allocated by the kmalloc() call in do_mmap_pgoff() and the block is not shareable
+ * MREMAP_FIXED is not supported under NOMMU conditions
  */
 unsigned long do_mremap(unsigned long addr,
                        unsigned long old_len, unsigned long new_len,
                        unsigned long flags, unsigned long new_addr)
 {
-       struct vm_list_struct *vml = NULL;
+       struct vm_area_struct *vma;
 
        /* insanity checks first */
        if (new_len == 0)
@@ -1012,58 +1123,46 @@ unsigned long do_mremap(unsigned long addr,
        if (flags & MREMAP_FIXED && new_addr != addr)
                return (unsigned long) -EINVAL;
 
-       for (vml = current->mm->context.vmlist; vml; vml = vml->next)
-               if (vml->vma->vm_start == addr)
-                       goto found;
-
-       return (unsigned long) -EINVAL;
+       vma = find_vma_exact(current->mm, addr);
+       if (!vma)
+               return (unsigned long) -EINVAL;
 
- found:
-       if (vml->vma->vm_end != vml->vma->vm_start + old_len)
+       if (vma->vm_end != vma->vm_start + old_len)
                return (unsigned long) -EFAULT;
 
-       if (vml->vma->vm_flags & VM_MAYSHARE)
+       if (vma->vm_flags & VM_MAYSHARE)
                return (unsigned long) -EPERM;
 
        if (new_len > kobjsize((void *) addr))
                return (unsigned long) -ENOMEM;
 
        /* all checks complete - do it */
-       vml->vma->vm_end = vml->vma->vm_start + new_len;
+       vma->vm_end = vma->vm_start + new_len;
 
        askedalloc -= old_len;
        askedalloc += new_len;
 
-       return vml->vma->vm_start;
+       return vma->vm_start;
 }
 
-/*
- * Look up the first VMA which satisfies  addr < vm_end,  NULL if none
- */
-struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+asmlinkage unsigned long sys_mremap(unsigned long addr,
+       unsigned long old_len, unsigned long new_len,
+       unsigned long flags, unsigned long new_addr)
 {
-       struct vm_list_struct *vml;
-
-       for (vml = mm->context.vmlist; vml; vml = vml->next)
-               if (addr >= vml->vma->vm_start && addr < vml->vma->vm_end)
-                       return vml->vma;
+       unsigned long ret;
 
-       return NULL;
+       down_write(&current->mm->mmap_sem);
+       ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+       up_write(&current->mm->mmap_sem);
+       return ret;
 }
 
-EXPORT_SYMBOL(find_vma);
-
 struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                        unsigned int foll_flags)
 {
        return NULL;
 }
 
-struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
-{
-       return NULL;
-}
-
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
                unsigned long to, unsigned long size, pgprot_t prot)
 {
@@ -1206,3 +1305,44 @@ struct page *filemap_nopage(struct vm_area_struct *area,
        BUG();
        return NULL;
 }
+
+/*
+ * Access another process' address space.
+ * - source/target buffer must be kernel space
+ */
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       struct vm_area_struct *vma;
+       struct mm_struct *mm;
+
+       if (addr + len < addr)
+               return 0;
+
+       mm = get_task_mm(tsk);
+       if (!mm)
+               return 0;
+
+       down_read(&mm->mmap_sem);
+
+       /* the access must start within one of the target process's mappings */
+       vma = find_vma(mm, addr);
+       if (vma) {
+               /* don't overrun this mapping */
+               if (addr + len >= vma->vm_end)
+                       len = vma->vm_end - addr;
+
+               /* only read or write mappings where it is permitted */
+               if (write && vma->vm_flags & VM_MAYWRITE)
+                       len -= copy_to_user((void *) addr, buf, len);
+               else if (!write && vma->vm_flags & VM_MAYREAD)
+                       len -= copy_from_user(buf, (void *) addr, len);
+               else
+                       len = 0;
+       } else {
+               len = 0;
+       }
+
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+       return len;
+}
index bada3d03119ff01381d6d47c1b828b59c3867106..20f41b082e16484a8c52aa04272bf4f30359593c 100644 (file)
@@ -204,15 +204,29 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
        do_posix_clock_monotonic_gettime(&uptime);
        do_each_thread(g, p) {
                unsigned long points;
-               int releasing;
 
-               /* skip kernel threads */
+               /*
+                * skip kernel threads and tasks which have already released
+                * their mm.
+                */
                if (!p->mm)
                        continue;
-               /* skip the init task with pid == 1 */
-               if (p->pid == 1)
+               /* skip the init task */
+               if (is_init(p))
                        continue;
 
+               /*
+                * This task already has access to memory reserves and is
+                * being killed. Don't allow any other task access to the
+                * memory reserve.
+                *
+                * Note: this may have a chance of deadlock if it gets
+                * blocked waiting for another task which itself is waiting
+                * for memory. Is there a better alternative?
+                */
+               if (test_tsk_thread_flag(p, TIF_MEMDIE))
+                       return ERR_PTR(-1UL);
+
                /*
                 * This is in the process of releasing memory so wait for it
                 * to finish before killing some other task by mistake.
@@ -221,21 +235,16 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
                 * go ahead if it is exiting: this will simply set TIF_MEMDIE,
                 * which will allow it to gain access to memory reserves in
                 * the process of exiting and releasing its resources.
-                * Otherwise we could get an OOM deadlock.
+                * Otherwise we could get an easy OOM deadlock.
                 */
-               releasing = test_tsk_thread_flag(p, TIF_MEMDIE) ||
-                                               p->flags & PF_EXITING;
-               if (releasing) {
-                       /* PF_DEAD tasks have already released their mm */
-                       if (p->flags & PF_DEAD)
-                               continue;
-                       if (p->flags & PF_EXITING && p == current) {
-                               chosen = p;
-                               *ppoints = ULONG_MAX;
-                               break;
-                       }
-                       return ERR_PTR(-1UL);
+               if (p->flags & PF_EXITING) {
+                       if (p != current)
+                               return ERR_PTR(-1UL);
+
+                       chosen = p;
+                       *ppoints = ULONG_MAX;
                }
+
                if (p->oomkilladj == OOM_DISABLE)
                        continue;
 
@@ -245,6 +254,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
                        *ppoints = points;
                }
        } while_each_thread(g, p);
+
        return chosen;
 }
 
@@ -255,20 +265,17 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
  */
 static void __oom_kill_task(struct task_struct *p, const char *message)
 {
-       if (p->pid == 1) {
+       if (is_init(p)) {
                WARN_ON(1);
                printk(KERN_WARNING "tried to kill init!\n");
                return;
        }
 
-       task_lock(p);
-       if (!p->mm || p->mm == &init_mm) {
+       if (!p->mm) {
                WARN_ON(1);
                printk(KERN_WARNING "tried to kill an mm-less task!\n");
-               task_unlock(p);
                return;
        }
-       task_unlock(p);
 
        if (message) {
                printk(KERN_ERR "%s: Killed process %d (%s).\n",
@@ -302,7 +309,7 @@ static int oom_kill_task(struct task_struct *p, const char *message)
         * However, this is of no concern to us.
         */
 
-       if (mm == NULL || mm == &init_mm)
+       if (mm == NULL)
                return 1;
 
        __oom_kill_task(p, message);
index 555752907dc3111b8fea4f042f5b1440f041f28d..c0d4ce144dec41130e552723c5b3ecd4dca1876a 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
+#include <linux/buffer_head.h>
+#include <linux/pagevec.h>
 
 /*
  * The maximum number of pages to writeout in a single bdflush/kupdate
@@ -46,7 +48,6 @@
  */
 static long ratelimit_pages = 32;
 
-static long total_pages;       /* The total number of pages in the machine. */
 static int dirty_exceeded __cacheline_aligned_in_smp;  /* Dirty mem may be over limit */
 
 /*
@@ -126,7 +127,7 @@ get_dirty_limits(long *pbackground, long *pdirty,
        int unmapped_ratio;
        long background;
        long dirty;
-       unsigned long available_memory = total_pages;
+       unsigned long available_memory = vm_total_pages;
        struct task_struct *tsk;
 
 #ifdef CONFIG_HIGHMEM
@@ -141,7 +142,7 @@ get_dirty_limits(long *pbackground, long *pdirty,
 
        unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) +
                                global_page_state(NR_ANON_PAGES)) * 100) /
-                                       total_pages;
+                                       vm_total_pages;
 
        dirty_ratio = vm_dirty_ratio;
        if (dirty_ratio > unmapped_ratio / 2)
@@ -502,9 +503,9 @@ void laptop_sync_completion(void)
  * will write six megabyte chunks, max.
  */
 
-static void set_ratelimit(void)
+void writeback_set_ratelimit(void)
 {
-       ratelimit_pages = total_pages / (num_online_cpus() * 32);
+       ratelimit_pages = vm_total_pages / (num_online_cpus() * 32);
        if (ratelimit_pages < 16)
                ratelimit_pages = 16;
        if (ratelimit_pages * PAGE_CACHE_SIZE > 4096 * 1024)
@@ -514,7 +515,7 @@ static void set_ratelimit(void)
 static int __cpuinit
 ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
 {
-       set_ratelimit();
+       writeback_set_ratelimit();
        return 0;
 }
 
@@ -533,9 +534,7 @@ void __init page_writeback_init(void)
        long buffer_pages = nr_free_buffer_pages();
        long correction;
 
-       total_pages = nr_free_pagecache_pages();
-
-       correction = (100 * 4 * buffer_pages) / total_pages;
+       correction = (100 * 4 * buffer_pages) / vm_total_pages;
 
        if (correction < 100) {
                dirty_background_ratio *= correction;
@@ -549,10 +548,143 @@ void __init page_writeback_init(void)
                        vm_dirty_ratio = 1;
        }
        mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
-       set_ratelimit();
+       writeback_set_ratelimit();
        register_cpu_notifier(&ratelimit_nb);
 }
 
+/**
+ * generic_writepages - walk the list of dirty pages of the given
+ *                      address space and writepage() all of them.
+ *
+ * @mapping: address space structure to write
+ * @wbc: subtract the number of written pages from *@wbc->nr_to_write
+ *
+ * This is a library function, which implements the writepages()
+ * address_space_operation.
+ *
+ * If a page is already under I/O, generic_writepages() skips it, even
+ * if it's dirty.  This is desirable behaviour for memory-cleaning writeback,
+ * but it is INCORRECT for data-integrity system calls such as fsync().  fsync()
+ * and msync() need to guarantee that all the data which was dirty at the time
+ * the call was made get new I/O started against them.  If wbc->sync_mode is
+ * WB_SYNC_ALL then we were called for data integrity and we must wait for
+ * existing IO to complete.
+ *
+ * Derived from mpage_writepages() - if you fix this you should check that
+ * also!
+ */
+int generic_writepages(struct address_space *mapping,
+                      struct writeback_control *wbc)
+{
+       struct backing_dev_info *bdi = mapping->backing_dev_info;
+       int ret = 0;
+       int done = 0;
+       int (*writepage)(struct page *page, struct writeback_control *wbc);
+       struct pagevec pvec;
+       int nr_pages;
+       pgoff_t index;
+       pgoff_t end;            /* Inclusive */
+       int scanned = 0;
+       int range_whole = 0;
+
+       if (wbc->nonblocking && bdi_write_congested(bdi)) {
+               wbc->encountered_congestion = 1;
+               return 0;
+       }
+
+       writepage = mapping->a_ops->writepage;
+
+       /* deal with chardevs and other special file */
+       if (!writepage)
+               return 0;
+
+       pagevec_init(&pvec, 0);
+       if (wbc->range_cyclic) {
+               index = mapping->writeback_index; /* Start from prev offset */
+               end = -1;
+       } else {
+               index = wbc->range_start >> PAGE_CACHE_SHIFT;
+               end = wbc->range_end >> PAGE_CACHE_SHIFT;
+               if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+                       range_whole = 1;
+               scanned = 1;
+       }
+retry:
+       while (!done && (index <= end) &&
+              (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+                                             PAGECACHE_TAG_DIRTY,
+                                             min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
+               unsigned i;
+
+               scanned = 1;
+               for (i = 0; i < nr_pages; i++) {
+                       struct page *page = pvec.pages[i];
+
+                       /*
+                        * 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 (unlikely(page->mapping != mapping)) {
+                               unlock_page(page);
+                               continue;
+                       }
+
+                       if (!wbc->range_cyclic && page->index > end) {
+                               done = 1;
+                               unlock_page(page);
+                               continue;
+                       }
+
+                       if (wbc->sync_mode != WB_SYNC_NONE)
+                               wait_on_page_writeback(page);
+
+                       if (PageWriteback(page) ||
+                           !clear_page_dirty_for_io(page)) {
+                               unlock_page(page);
+                               continue;
+                       }
+
+                       ret = (*writepage)(page, wbc);
+                       if (ret) {
+                               if (ret == -ENOSPC)
+                                       set_bit(AS_ENOSPC, &mapping->flags);
+                               else
+                                       set_bit(AS_EIO, &mapping->flags);
+                       }
+
+                       if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
+                               unlock_page(page);
+                       if (ret || (--(wbc->nr_to_write) <= 0))
+                               done = 1;
+                       if (wbc->nonblocking && bdi_write_congested(bdi)) {
+                               wbc->encountered_congestion = 1;
+                               done = 1;
+                       }
+               }
+               pagevec_release(&pvec);
+               cond_resched();
+       }
+       if (!scanned && !done) {
+               /*
+                * We hit the last page and there is more work to be done: wrap
+                * back to the start of the file
+                */
+               scanned = 1;
+               index = 0;
+               goto retry;
+       }
+       if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+               mapping->writeback_index = index;
+       return ret;
+}
+
+EXPORT_SYMBOL(generic_writepages);
+
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
        int ret;
@@ -675,9 +807,11 @@ int fastcall set_page_dirty(struct page *page)
 
        if (likely(mapping)) {
                int (*spd)(struct page *) = mapping->a_ops->set_page_dirty;
-               if (spd)
-                       return (*spd)(page);
-               return __set_page_dirty_buffers(page);
+#ifdef CONFIG_BLOCK
+               if (!spd)
+                       spd = __set_page_dirty_buffers;
+#endif
+               return (*spd)(page);
        }
        if (!PageDirty(page)) {
                if (!TestSetPageDirty(page))
index 9810f0a60db7720da211386298422e138341e16e..4f59d90b81e65a314e0433dc61371b785b3df61f 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/vmalloc.h>
 #include <linux/mempolicy.h>
 #include <linux/stop_machine.h>
+#include <linux/sort.h>
+#include <linux/pfn.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -102,6 +104,38 @@ int min_free_kbytes = 1024;
 
 unsigned long __meminitdata nr_kernel_pages;
 unsigned long __meminitdata nr_all_pages;
+static unsigned long __initdata dma_reserve;
+
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+  /*
+   * MAX_ACTIVE_REGIONS determines the maxmimum number of distinct
+   * ranges of memory (RAM) that may be registered with add_active_range().
+   * Ranges passed to add_active_range() will be merged if possible
+   * so the number of times add_active_range() can be called is
+   * related to the number of nodes and the number of holes
+   */
+  #ifdef CONFIG_MAX_ACTIVE_REGIONS
+    /* Allow an architecture to set MAX_ACTIVE_REGIONS to save memory */
+    #define MAX_ACTIVE_REGIONS CONFIG_MAX_ACTIVE_REGIONS
+  #else
+    #if MAX_NUMNODES >= 32
+      /* If there can be many nodes, allow up to 50 holes per node */
+      #define MAX_ACTIVE_REGIONS (MAX_NUMNODES*50)
+    #else
+      /* By default, allow up to 256 distinct regions */
+      #define MAX_ACTIVE_REGIONS 256
+    #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];
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+  unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
+  unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
+#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
@@ -908,7 +942,7 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
         */
        do {
                zone = *z;
-               if (unlikely((gfp_mask & __GFP_THISNODE) &&
+               if (unlikely(NUMA_BUILD && (gfp_mask & __GFP_THISNODE) &&
                        zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
                                break;
                if ((alloc_flags & ALLOC_CPUSET) &&
@@ -1222,14 +1256,12 @@ unsigned int nr_free_pagecache_pages(void)
 {
        return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
 }
-#ifdef CONFIG_NUMA
-static void show_node(struct zone *zone)
+
+static inline void show_node(struct zone *zone)
 {
-       printk("Node %ld ", zone_to_nid(zone));
+       if (NUMA_BUILD)
+               printk("Node %ld ", zone_to_nid(zone));
 }
-#else
-#define show_node(zone)        do { } while (0)
-#endif
 
 void si_meminfo(struct sysinfo *val)
 {
@@ -1271,34 +1303,30 @@ void si_meminfo_node(struct sysinfo *val, int nid)
  */
 void show_free_areas(void)
 {
-       int cpu, temperature;
+       int cpu;
        unsigned long active;
        unsigned long inactive;
        unsigned long free;
        struct zone *zone;
 
        for_each_zone(zone) {
-               show_node(zone);
-               printk("%s per-cpu:", zone->name);
-
-               if (!populated_zone(zone)) {
-                       printk(" empty\n");
+               if (!populated_zone(zone))
                        continue;
-               } else
-                       printk("\n");
+
+               show_node(zone);
+               printk("%s per-cpu:\n", zone->name);
 
                for_each_online_cpu(cpu) {
                        struct per_cpu_pageset *pageset;
 
                        pageset = zone_pcp(zone, cpu);
 
-                       for (temperature = 0; temperature < 2; temperature++)
-                               printk("cpu %d %s: high %d, batch %d used:%d\n",
-                                       cpu,
-                                       temperature ? "cold" : "hot",
-                                       pageset->pcp[temperature].high,
-                                       pageset->pcp[temperature].batch,
-                                       pageset->pcp[temperature].count);
+                       printk("CPU %4d: Hot: hi:%5d, btch:%4d usd:%4d   "
+                              "Cold: hi:%5d, btch:%4d usd:%4d\n",
+                              cpu, pageset->pcp[0].high,
+                              pageset->pcp[0].batch, pageset->pcp[0].count,
+                              pageset->pcp[1].high, pageset->pcp[1].batch,
+                              pageset->pcp[1].count);
                }
        }
 
@@ -1320,6 +1348,9 @@ void show_free_areas(void)
        for_each_zone(zone) {
                int i;
 
+               if (!populated_zone(zone))
+                       continue;
+
                show_node(zone);
                printk("%s"
                        " free:%lukB"
@@ -1352,12 +1383,11 @@ void show_free_areas(void)
        for_each_zone(zone) {
                unsigned long nr[MAX_ORDER], flags, order, total = 0;
 
+               if (!populated_zone(zone))
+                       continue;
+
                show_node(zone);
                printk("%s: ", zone->name);
-               if (!populated_zone(zone)) {
-                       printk("empty\n");
-                       continue;
-               }
 
                spin_lock_irqsave(&zone->lock, flags);
                for (order = 0; order < MAX_ORDER; order++) {
@@ -1561,7 +1591,7 @@ static int __meminit __build_all_zonelists(void *dummy)
 void __meminit build_all_zonelists(void)
 {
        if (system_state == SYSTEM_BOOTING) {
-               __build_all_zonelists(0);
+               __build_all_zonelists(NULL);
                cpuset_init_current_mems_allowed();
        } else {
                /* we have to stop all cpus to guaranntee there is no user
@@ -1642,25 +1672,6 @@ static inline unsigned long wait_table_bits(unsigned long size)
 
 #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
 
-static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
-               unsigned long *zones_size, unsigned long *zholes_size)
-{
-       unsigned long realtotalpages, totalpages = 0;
-       enum zone_type i;
-
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               totalpages += zones_size[i];
-       pgdat->node_spanned_pages = totalpages;
-
-       realtotalpages = totalpages;
-       if (zholes_size)
-               for (i = 0; i < MAX_NR_ZONES; i++)
-                       realtotalpages -= zholes_size[i];
-       pgdat->node_present_pages = realtotalpages;
-       printk(KERN_DEBUG "On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages);
-}
-
-
 /*
  * Initially all pages are reserved - free ones are freed
  * up by free_all_bootmem() once the early boot process is
@@ -1818,6 +1829,9 @@ static int __cpuinit process_zones(int cpu)
 
        for_each_zone(zone) {
 
+               if (!populated_zone(zone))
+                       continue;
+
                zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset),
                                         GFP_KERNEL, cpu_to_node(cpu));
                if (!zone_pcp(zone, cpu))
@@ -1977,6 +1991,366 @@ __meminit int init_currently_empty_zone(struct zone *zone,
        return 0;
 }
 
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+/*
+ * 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)
+{
+       int i;
+
+       for (i = 0; i < nr_nodemap_entries; i++)
+               if (nid == MAX_NUMNODES || early_node_map[i].nid == nid)
+                       return i;
+
+       return -1;
+}
+
+/*
+ * 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)
+{
+       for (index = index + 1; index < nr_nodemap_entries; index++)
+               if (nid == MAX_NUMNODES || early_node_map[index].nid == nid)
+                       return index;
+
+       return -1;
+}
+
+#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+/*
+ * Required by SPARSEMEM. Given a PFN, return what node the PFN is on.
+ * Architectures may implement their own version but if add_active_range()
+ * was used and there are no special requirements, this is a convenient
+ * alternative
+ */
+int __init early_pfn_to_nid(unsigned long pfn)
+{
+       int i;
+
+       for (i = 0; i < nr_nodemap_entries; i++) {
+               unsigned long start_pfn = early_node_map[i].start_pfn;
+               unsigned long end_pfn = early_node_map[i].end_pfn;
+
+               if (start_pfn <= pfn && pfn < end_pfn)
+                       return early_node_map[i].nid;
+       }
+
+       return 0;
+}
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+/* Basic iterator support to walk early_node_map[] */
+#define for_each_active_range_index_in_nid(i, nid) \
+       for (i = first_active_region_index_in_nid(nid); i != -1; \
+                               i = next_active_region_index_in_nid(i, nid))
+
+/**
+ * free_bootmem_with_active_regions - Call free_bootmem_node for each active range
+ * @nid: The node to free memory on. If MAX_NUMNODES, all nodes are freed
+ * @max_low_pfn: The highest PFN that till be passed to free_bootmem_node
+ *
+ * If an architecture guarantees that all ranges registered with
+ * add_active_ranges() contain no holes and may be freed, this
+ * this function may be used instead of calling free_bootmem() manually.
+ */
+void __init free_bootmem_with_active_regions(int nid,
+                                               unsigned long max_low_pfn)
+{
+       int i;
+
+       for_each_active_range_index_in_nid(i, nid) {
+               unsigned long size_pages = 0;
+               unsigned long end_pfn = early_node_map[i].end_pfn;
+
+               if (early_node_map[i].start_pfn >= max_low_pfn)
+                       continue;
+
+               if (end_pfn > max_low_pfn)
+                       end_pfn = max_low_pfn;
+
+               size_pages = end_pfn - early_node_map[i].start_pfn;
+               free_bootmem_node(NODE_DATA(early_node_map[i].nid),
+                               PFN_PHYS(early_node_map[i].start_pfn),
+                               size_pages << PAGE_SHIFT);
+       }
+}
+
+/**
+ * sparse_memory_present_with_active_regions - Call memory_present for each active range
+ * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used
+ *
+ * If an architecture guarantees that all ranges registered with
+ * add_active_ranges() contain no holes and may be freed, this
+ * this function may be used instead of calling memory_present() manually.
+ */
+void __init sparse_memory_present_with_active_regions(int nid)
+{
+       int i;
+
+       for_each_active_range_index_in_nid(i, nid)
+               memory_present(early_node_map[i].nid,
+                               early_node_map[i].start_pfn,
+                               early_node_map[i].end_pfn);
+}
+
+/**
+ * push_node_boundaries - Push node boundaries to at least the requested boundary
+ * @nid: The nid of the node to push the boundary for
+ * @start_pfn: The start pfn of the node
+ * @end_pfn: The end pfn of the node
+ *
+ * In reserve-based hot-add, mem_map is allocated that is unused until hotadd
+ * time. Specifically, on x86_64, SRAT will report ranges that can potentially
+ * be hotplugged even though no physical memory exists. This function allows
+ * an arch to push out the node boundaries so mem_map is allocated that can
+ * be used later.
+ */
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+void __init push_node_boundaries(unsigned int nid,
+               unsigned long start_pfn, unsigned long end_pfn)
+{
+       printk(KERN_DEBUG "Entering push_node_boundaries(%u, %lu, %lu)\n",
+                       nid, start_pfn, end_pfn);
+
+       /* Initialise the boundary for this node if necessary */
+       if (node_boundary_end_pfn[nid] == 0)
+               node_boundary_start_pfn[nid] = -1UL;
+
+       /* Update the boundaries */
+       if (node_boundary_start_pfn[nid] > start_pfn)
+               node_boundary_start_pfn[nid] = start_pfn;
+       if (node_boundary_end_pfn[nid] < end_pfn)
+               node_boundary_end_pfn[nid] = end_pfn;
+}
+
+/* If necessary, push the node boundary out for reserve hotadd */
+static void __init account_node_boundary(unsigned int nid,
+               unsigned long *start_pfn, unsigned long *end_pfn)
+{
+       printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
+                       nid, *start_pfn, *end_pfn);
+
+       /* Return if boundary information has not been provided */
+       if (node_boundary_end_pfn[nid] == 0)
+               return;
+
+       /* Check the boundaries and update if necessary */
+       if (node_boundary_start_pfn[nid] < *start_pfn)
+               *start_pfn = node_boundary_start_pfn[nid];
+       if (node_boundary_end_pfn[nid] > *end_pfn)
+               *end_pfn = node_boundary_end_pfn[nid];
+}
+#else
+void __init push_node_boundaries(unsigned int nid,
+               unsigned long start_pfn, unsigned long end_pfn) {}
+
+static void __init account_node_boundary(unsigned int nid,
+               unsigned long *start_pfn, unsigned long *end_pfn) {}
+#endif
+
+
+/**
+ * get_pfn_range_for_nid - Return the start and end page frames for a node
+ * @nid: The nid to return the range for. If MAX_NUMNODES, the min and max PFN are returned
+ * @start_pfn: Passed by reference. On return, it will have the node start_pfn
+ * @end_pfn: Passed by reference. On return, it will have the node end_pfn
+ *
+ * It returns the start and end page frame of a node based on information
+ * provided by an arch calling add_active_range(). If called for a node
+ * 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,
+                       unsigned long *start_pfn, unsigned long *end_pfn)
+{
+       int i;
+       *start_pfn = -1UL;
+       *end_pfn = 0;
+
+       for_each_active_range_index_in_nid(i, nid) {
+               *start_pfn = min(*start_pfn, early_node_map[i].start_pfn);
+               *end_pfn = max(*end_pfn, early_node_map[i].end_pfn);
+       }
+
+       if (*start_pfn == -1UL) {
+               printk(KERN_WARNING "Node %u active with no memory\n", nid);
+               *start_pfn = 0;
+       }
+
+       /* Push the node boundaries out if requested */
+       account_node_boundary(nid, start_pfn, end_pfn);
+}
+
+/*
+ * 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 zone_type,
+                                       unsigned long *ignored)
+{
+       unsigned long node_start_pfn, node_end_pfn;
+       unsigned long zone_start_pfn, zone_end_pfn;
+
+       /* Get the start and end of the node and zone */
+       get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
+       zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
+       zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+
+       /* Check that this node has pages within the zone's required range */
+       if (zone_end_pfn < node_start_pfn || zone_start_pfn > node_end_pfn)
+               return 0;
+
+       /* Move the zone boundaries inside the node if necessary */
+       zone_end_pfn = min(zone_end_pfn, node_end_pfn);
+       zone_start_pfn = max(zone_start_pfn, node_start_pfn);
+
+       /* Return the spanned pages */
+       return zone_end_pfn - zone_start_pfn;
+}
+
+/*
+ * 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 range_start_pfn,
+                               unsigned long range_end_pfn)
+{
+       int i = 0;
+       unsigned long prev_end_pfn = 0, hole_pages = 0;
+       unsigned long start_pfn;
+
+       /* Find the end_pfn of the first active range of pfns in the node */
+       i = first_active_region_index_in_nid(nid);
+       if (i == -1)
+               return 0;
+
+       /* Account for ranges before physical memory on this node */
+       if (early_node_map[i].start_pfn > range_start_pfn)
+               hole_pages = early_node_map[i].start_pfn - range_start_pfn;
+
+       prev_end_pfn = early_node_map[i].start_pfn;
+
+       /* Find all holes for the zone within the node */
+       for (; i != -1; i = next_active_region_index_in_nid(i, nid)) {
+
+               /* No need to continue if prev_end_pfn is outside the zone */
+               if (prev_end_pfn >= range_end_pfn)
+                       break;
+
+               /* Make sure the end of the zone is not within the hole */
+               start_pfn = min(early_node_map[i].start_pfn, range_end_pfn);
+               prev_end_pfn = max(prev_end_pfn, range_start_pfn);
+
+               /* Update the hole size cound and move on */
+               if (start_pfn > range_start_pfn) {
+                       BUG_ON(prev_end_pfn > start_pfn);
+                       hole_pages += start_pfn - prev_end_pfn;
+               }
+               prev_end_pfn = early_node_map[i].end_pfn;
+       }
+
+       /* Account for ranges past physical memory on this node */
+       if (range_end_pfn > prev_end_pfn)
+               hole_pages = range_end_pfn -
+                               max(range_start_pfn, prev_end_pfn);
+
+       return hole_pages;
+}
+
+/**
+ * absent_pages_in_range - Return number of page frames in holes within a range
+ * @start_pfn: The start PFN to start searching for holes
+ * @end_pfn: The end PFN to stop searching for holes
+ *
+ * It returns the number of pages frames in memory holes within a range
+ */
+unsigned long __init absent_pages_in_range(unsigned long start_pfn,
+                                                       unsigned long end_pfn)
+{
+       return __absent_pages_in_range(MAX_NUMNODES, start_pfn, end_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 zone_type,
+                                       unsigned long *ignored)
+{
+       unsigned long node_start_pfn, node_end_pfn;
+       unsigned long zone_start_pfn, zone_end_pfn;
+
+       get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
+       zone_start_pfn = max(arch_zone_lowest_possible_pfn[zone_type],
+                                                       node_start_pfn);
+       zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type],
+                                                       node_end_pfn);
+
+       return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
+}
+
+/* Return the zone index a PFN is in */
+int memmap_zone_idx(struct page *lmem_map)
+{
+       int i;
+       unsigned long phys_addr = virt_to_phys(lmem_map);
+       unsigned long pfn = phys_addr >> PAGE_SHIFT;
+
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               if (pfn < arch_zone_highest_possible_pfn[i])
+                       break;
+
+       return i;
+}
+#else
+static inline unsigned long zone_spanned_pages_in_node(int nid,
+                                       unsigned long zone_type,
+                                       unsigned long *zones_size)
+{
+       return zones_size[zone_type];
+}
+
+static inline unsigned long zone_absent_pages_in_node(int nid,
+                                               unsigned long zone_type,
+                                               unsigned long *zholes_size)
+{
+       if (!zholes_size)
+               return 0;
+
+       return zholes_size[zone_type];
+}
+
+static inline int memmap_zone_idx(struct page *lmem_map)
+{
+       return MAX_NR_ZONES;
+}
+#endif
+
+static void __init calculate_node_totalpages(struct pglist_data *pgdat,
+               unsigned long *zones_size, unsigned long *zholes_size)
+{
+       unsigned long realtotalpages, totalpages = 0;
+       enum zone_type i;
+
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               totalpages += zone_spanned_pages_in_node(pgdat->node_id, i,
+                                                               zones_size);
+       pgdat->node_spanned_pages = totalpages;
+
+       realtotalpages = totalpages;
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               realtotalpages -=
+                       zone_absent_pages_in_node(pgdat->node_id, i,
+                                                               zholes_size);
+       pgdat->node_present_pages = realtotalpages;
+       printk(KERN_DEBUG "On node %d totalpages: %lu\n", pgdat->node_id,
+                                                       realtotalpages);
+}
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -1998,11 +2372,34 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
        
        for (j = 0; j < MAX_NR_ZONES; j++) {
                struct zone *zone = pgdat->node_zones + j;
-               unsigned long size, realsize;
+               unsigned long size, realsize, memmap_pages;
 
-               realsize = size = zones_size[j];
-               if (zholes_size)
-                       realsize -= zholes_size[j];
+               size = zone_spanned_pages_in_node(nid, j, zones_size);
+               realsize = size - zone_absent_pages_in_node(nid, j,
+                                                               zholes_size);
+
+               /*
+                * Adjust realsize so that it accounts for how much memory
+                * is used by this zone for memmap. This affects the watermark
+                * and per-cpu initialisations
+                */
+               memmap_pages = (size * sizeof(struct page)) >> PAGE_SHIFT;
+               if (realsize >= memmap_pages) {
+                       realsize -= memmap_pages;
+                       printk(KERN_DEBUG
+                               "  %s zone: %lu pages used for memmap\n",
+                               zone_names[j], memmap_pages);
+               } else
+                       printk(KERN_WARNING
+                               "  %s zone: %lu pages exceeds realsize %lu\n",
+                               zone_names[j], memmap_pages, realsize);
+
+               /* Account for reserved DMA pages */
+               if (j == ZONE_DMA && realsize > dma_reserve) {
+                       realsize -= dma_reserve;
+                       printk(KERN_DEBUG "  DMA zone: %lu pages reserved\n",
+                                                               dma_reserve);
+               }
 
                if (!is_highmem_idx(j))
                        nr_kernel_pages += realsize;
@@ -2011,6 +2408,7 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
                zone->spanned_pages = size;
                zone->present_pages = realsize;
 #ifdef CONFIG_NUMA
+               zone->node = nid;
                zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio)
                                                / 100;
                zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100;
@@ -2073,8 +2471,13 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat)
        /*
         * With no DISCONTIG, the global mem_map is just set as node 0's
         */
-       if (pgdat == NODE_DATA(0))
+       if (pgdat == NODE_DATA(0)) {
                mem_map = NODE_DATA(0)->node_mem_map;
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+               if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
+                       mem_map -= pgdat->node_start_pfn;
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+       }
 #endif
 #endif /* CONFIG_FLAT_NODE_MEM_MAP */
 }
@@ -2085,13 +2488,255 @@ void __meminit free_area_init_node(int nid, struct pglist_data *pgdat,
 {
        pgdat->node_id = nid;
        pgdat->node_start_pfn = node_start_pfn;
-       calculate_zone_totalpages(pgdat, zones_size, zholes_size);
+       calculate_node_totalpages(pgdat, zones_size, zholes_size);
 
        alloc_node_mem_map(pgdat);
 
        free_area_init_core(pgdat, zones_size, zholes_size);
 }
 
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+/**
+ * add_active_range - Register a range of PFNs backed by physical memory
+ * @nid: The node ID the range resides on
+ * @start_pfn: The start PFN of the available physical memory
+ * @end_pfn: The end PFN of the available physical memory
+ *
+ * These ranges are stored in an early_node_map[] and later used by
+ * free_area_init_nodes() to calculate zone sizes and holes. If the
+ * range spans a memory hole, it is up to the architecture to ensure
+ * the memory is not freed by the bootmem allocator. If possible
+ * the range being registered will be merged with existing ranges.
+ */
+void __init add_active_range(unsigned int nid, unsigned long start_pfn,
+                                               unsigned long end_pfn)
+{
+       int i;
+
+       printk(KERN_DEBUG "Entering add_active_range(%d, %lu, %lu) "
+                         "%d entries of %d used\n",
+                         nid, start_pfn, end_pfn,
+                         nr_nodemap_entries, MAX_ACTIVE_REGIONS);
+
+       /* Merge with existing active regions if possible */
+       for (i = 0; i < nr_nodemap_entries; i++) {
+               if (early_node_map[i].nid != nid)
+                       continue;
+
+               /* Skip if an existing region covers this new one */
+               if (start_pfn >= early_node_map[i].start_pfn &&
+                               end_pfn <= early_node_map[i].end_pfn)
+                       return;
+
+               /* Merge forward if suitable */
+               if (start_pfn <= early_node_map[i].end_pfn &&
+                               end_pfn > early_node_map[i].end_pfn) {
+                       early_node_map[i].end_pfn = end_pfn;
+                       return;
+               }
+
+               /* Merge backward if suitable */
+               if (start_pfn < early_node_map[i].end_pfn &&
+                               end_pfn >= early_node_map[i].start_pfn) {
+                       early_node_map[i].start_pfn = start_pfn;
+                       return;
+               }
+       }
+
+       /* Check that early_node_map is large enough */
+       if (i >= MAX_ACTIVE_REGIONS) {
+               printk(KERN_CRIT "More than %d memory regions, truncating\n",
+                                                       MAX_ACTIVE_REGIONS);
+               return;
+       }
+
+       early_node_map[i].nid = nid;
+       early_node_map[i].start_pfn = start_pfn;
+       early_node_map[i].end_pfn = end_pfn;
+       nr_nodemap_entries = i + 1;
+}
+
+/**
+ * shrink_active_range - Shrink an existing registered range of PFNs
+ * @nid: The node id the range is on that should be shrunk
+ * @old_end_pfn: The old end PFN of the range
+ * @new_end_pfn: The new PFN of the range
+ *
+ * i386 with NUMA use alloc_remap() to store a node_mem_map on a local node.
+ * The map is kept at the end physical page range that has already been
+ * registered with add_active_range(). This function allows an arch to shrink
+ * an existing registered range.
+ */
+void __init shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
+                                               unsigned long new_end_pfn)
+{
+       int i;
+
+       /* Find the old active region end and shrink */
+       for_each_active_range_index_in_nid(i, nid)
+               if (early_node_map[i].end_pfn == old_end_pfn) {
+                       early_node_map[i].end_pfn = new_end_pfn;
+                       break;
+               }
+}
+
+/**
+ * remove_all_active_ranges - Remove all currently registered regions
+ * During discovery, it may be found that a table like SRAT is invalid
+ * and an alternative discovery method must be used. This function removes
+ * all currently registered regions.
+ */
+void __init remove_all_active_ranges()
+{
+       memset(early_node_map, 0, sizeof(early_node_map));
+       nr_nodemap_entries = 0;
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+       memset(node_boundary_start_pfn, 0, sizeof(node_boundary_start_pfn));
+       memset(node_boundary_end_pfn, 0, sizeof(node_boundary_end_pfn));
+#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+}
+
+/* Compare two active node_active_regions */
+static int __init cmp_node_active_region(const void *a, const void *b)
+{
+       struct node_active_region *arange = (struct node_active_region *)a;
+       struct node_active_region *brange = (struct node_active_region *)b;
+
+       /* Done this way to avoid overflows */
+       if (arange->start_pfn > brange->start_pfn)
+               return 1;
+       if (arange->start_pfn < brange->start_pfn)
+               return -1;
+
+       return 0;
+}
+
+/* sort the node_map by start_pfn */
+static void __init sort_node_map(void)
+{
+       sort(early_node_map, (size_t)nr_nodemap_entries,
+                       sizeof(struct node_active_region),
+                       cmp_node_active_region, NULL);
+}
+
+/* Find the lowest pfn for a node. This depends on a sorted early_node_map */
+unsigned long __init find_min_pfn_for_node(unsigned long nid)
+{
+       int i;
+
+       /* Assuming a sorted map, the first range found has the starting pfn */
+       for_each_active_range_index_in_nid(i, nid)
+               return early_node_map[i].start_pfn;
+
+       printk(KERN_WARNING "Could not find start_pfn for node %lu\n", nid);
+       return 0;
+}
+
+/**
+ * find_min_pfn_with_active_regions - Find the minimum PFN registered
+ *
+ * It returns the minimum PFN based on information provided via
+ * add_active_range()
+ */
+unsigned long __init find_min_pfn_with_active_regions(void)
+{
+       return find_min_pfn_for_node(MAX_NUMNODES);
+}
+
+/**
+ * find_max_pfn_with_active_regions - Find the maximum PFN registered
+ *
+ * It returns the maximum PFN based on information provided via
+ * add_active_range()
+ */
+unsigned long __init find_max_pfn_with_active_regions(void)
+{
+       int i;
+       unsigned long max_pfn = 0;
+
+       for (i = 0; i < nr_nodemap_entries; i++)
+               max_pfn = max(max_pfn, early_node_map[i].end_pfn);
+
+       return max_pfn;
+}
+
+/**
+ * free_area_init_nodes - Initialise all pg_data_t and zone data
+ * @arch_max_dma_pfn: The maximum PFN usable for ZONE_DMA
+ * @arch_max_dma32_pfn: The maximum PFN usable for ZONE_DMA32
+ * @arch_max_low_pfn: The maximum PFN usable for ZONE_NORMAL
+ * @arch_max_high_pfn: The maximum PFN usable for ZONE_HIGHMEM
+ *
+ * This will call free_area_init_node() for each active node in the system.
+ * Using the page ranges provided by add_active_range(), the size of each
+ * zone in each node and their holes is calculated. If the maximum PFN
+ * between two adjacent zones match, it is assumed that the zone is empty.
+ * For example, if arch_max_dma_pfn == arch_max_dma32_pfn, it is assumed
+ * that arch_max_dma32_pfn has no pages. It is also assumed that a zone
+ * starts where the previous one ended. For example, ZONE_DMA32 starts
+ * at arch_max_dma_pfn.
+ */
+void __init free_area_init_nodes(unsigned long *max_zone_pfn)
+{
+       unsigned long nid;
+       enum zone_type i;
+
+       /* Record where the zone boundaries are */
+       memset(arch_zone_lowest_possible_pfn, 0,
+                               sizeof(arch_zone_lowest_possible_pfn));
+       memset(arch_zone_highest_possible_pfn, 0,
+                               sizeof(arch_zone_highest_possible_pfn));
+       arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
+       arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
+       for (i = 1; i < MAX_NR_ZONES; i++) {
+               arch_zone_lowest_possible_pfn[i] =
+                       arch_zone_highest_possible_pfn[i-1];
+               arch_zone_highest_possible_pfn[i] =
+                       max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
+       }
+
+       /* Regions in the early_node_map can be in any order */
+       sort_node_map();
+
+       /* Print out the zone ranges */
+       printk("Zone PFN ranges:\n");
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               printk("  %-8s %8lu -> %8lu\n",
+                               zone_names[i],
+                               arch_zone_lowest_possible_pfn[i],
+                               arch_zone_highest_possible_pfn[i]);
+
+       /* Print out the early_node_map[] */
+       printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
+       for (i = 0; i < nr_nodemap_entries; i++)
+               printk("  %3d: %8lu -> %8lu\n", early_node_map[i].nid,
+                                               early_node_map[i].start_pfn,
+                                               early_node_map[i].end_pfn);
+
+       /* Initialise every node */
+       for_each_online_node(nid) {
+               pg_data_t *pgdat = NODE_DATA(nid);
+               free_area_init_node(nid, pgdat, NULL,
+                               find_min_pfn_for_node(nid), NULL);
+       }
+}
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+
+/**
+ * set_dma_reserve - Account the specified number of pages reserved in ZONE_DMA
+ * @new_dma_reserve - The number of pages to mark reserved
+ *
+ * The per-cpu batchsize and zone watermarks are determined by present_pages.
+ * In the DMA zone, a significant percentage may be consumed by kernel image
+ * and other unfreeable allocations which can skew the watermarks badly. This
+ * function may optionally be used to account for unfreeable pages in
+ * ZONE_DMA. The effect will be lower watermarks and smaller per-cpu batchsize
+ */
+void __init set_dma_reserve(unsigned long new_dma_reserve)
+{
+       dma_reserve = new_dma_reserve;
+}
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 static bootmem_data_t contig_bootmem_data;
 struct pglist_data contig_page_data = { .bdata = &contig_bootmem_data };
index 8631be45b40d46304d0dcbc1f398acaf1325beaf..bb8ca7ef70940de154adfcbb7f30debd3f3c3737 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/xattr.h>
+#include <linux/generic_acl.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/file.h>
@@ -177,6 +179,7 @@ static const struct address_space_operations shmem_aops;
 static struct file_operations shmem_file_operations;
 static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
+static struct inode_operations shmem_special_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
@@ -637,7 +640,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
        struct page *page = NULL;
        int error;
 
-       if (attr->ia_valid & ATTR_SIZE) {
+       if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
                if (attr->ia_size < inode->i_size) {
                        /*
                         * If truncating down to a partial page, then
@@ -670,6 +673,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
        error = inode_change_ok(inode, attr);
        if (!error)
                error = inode_setattr(inode, attr);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+       if (!error && (attr->ia_valid & ATTR_MODE))
+               error = generic_acl_chmod(inode, &shmem_acl_ops);
+#endif
        if (page)
                page_cache_release(page);
        return error;
@@ -1351,7 +1358,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &shmem_aops;
                inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
@@ -1363,6 +1369,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 
                switch (mode & S_IFMT) {
                default:
+                       inode->i_op = &shmem_special_inode_operations;
                        init_special_inode(inode, mode, dev);
                        break;
                case S_IFREG:
@@ -1372,7 +1379,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                                                        &sbinfo->policy_nodes);
                        break;
                case S_IFDIR:
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        /* Some things misbehave if size == 0 on a directory */
                        inode->i_size = 2 * BOGO_DIRENT_SIZE;
                        inode->i_op = &shmem_dir_inode_operations;
@@ -1683,7 +1690,11 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
                                iput(inode);
                                return error;
                        }
-                       error = 0;
+               }
+               error = shmem_acl_init(inode, dir);
+               if (error) {
+                       iput(inode);
+                       return error;
                }
                if (dir->i_mode & S_ISGID) {
                        inode->i_gid = dir->i_gid;
@@ -1704,7 +1715,7 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
                return error;
-       dir->i_nlink++;
+       inc_nlink(dir);
        return 0;
 }
 
@@ -1739,7 +1750,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
 
        dir->i_size += BOGO_DIRENT_SIZE;
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       inode->i_nlink++;
+       inc_nlink(inode);
        atomic_inc(&inode->i_count);    /* New dentry reference */
        dget(dentry);           /* Extra pinning count for the created dentry */
        d_instantiate(dentry, inode);
@@ -1761,7 +1772,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 
        dir->i_size -= BOGO_DIRENT_SIZE;
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       inode->i_nlink--;
+       drop_nlink(inode);
        dput(dentry);   /* Undo the count from "create" - this does all the work */
        return 0;
 }
@@ -1771,8 +1782,8 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
        if (!simple_empty(dentry))
                return -ENOTEMPTY;
 
-       dentry->d_inode->i_nlink--;
-       dir->i_nlink--;
+       drop_nlink(dentry->d_inode);
+       drop_nlink(dir);
        return shmem_unlink(dir, dentry);
 }
 
@@ -1793,10 +1804,10 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
        if (new_dentry->d_inode) {
                (void) shmem_unlink(new_dir, new_dentry);
                if (they_are_dirs)
-                       old_dir->i_nlink--;
+                       drop_nlink(old_dir);
        } else if (they_are_dirs) {
-               old_dir->i_nlink--;
-               new_dir->i_nlink++;
+               drop_nlink(old_dir);
+               inc_nlink(new_dir);
        }
 
        old_dir->i_size -= BOGO_DIRENT_SIZE;
@@ -1898,6 +1909,53 @@ static struct inode_operations shmem_symlink_inode_operations = {
        .put_link       = shmem_put_link,
 };
 
+#ifdef CONFIG_TMPFS_POSIX_ACL
+/**
+ * Superblocks without xattr inode operations will get security.* xattr
+ * support from the VFS "for free". As soon as we have any other xattrs
+ * like ACLs, we also need to implement the security.* handlers at
+ * filesystem level, though.
+ */
+
+static size_t shmem_xattr_security_list(struct inode *inode, char *list,
+                                       size_t list_len, const char *name,
+                                       size_t name_len)
+{
+       return security_inode_listsecurity(inode, list, list_len);
+}
+
+static int shmem_xattr_security_get(struct inode *inode, const char *name,
+                                   void *buffer, size_t size)
+{
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return security_inode_getsecurity(inode, name, buffer, size,
+                                         -EOPNOTSUPP);
+}
+
+static int shmem_xattr_security_set(struct inode *inode, const char *name,
+                                   const void *value, size_t size, int flags)
+{
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return security_inode_setsecurity(inode, name, value, size, flags);
+}
+
+struct xattr_handler shmem_xattr_security_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .list   = shmem_xattr_security_list,
+       .get    = shmem_xattr_security_get,
+       .set    = shmem_xattr_security_set,
+};
+
+static struct xattr_handler *shmem_xattr_handlers[] = {
+       &shmem_xattr_acl_access_handler,
+       &shmem_xattr_acl_default_handler,
+       &shmem_xattr_security_handler,
+       NULL
+};
+#endif
+
 static int shmem_parse_options(char *options, int *mode, uid_t *uid,
        gid_t *gid, unsigned long *blocks, unsigned long *inodes,
        int *policy, nodemask_t *policy_nodes)
@@ -2095,6 +2153,10 @@ static int shmem_fill_super(struct super_block *sb,
        sb->s_magic = TMPFS_MAGIC;
        sb->s_op = &shmem_ops;
        sb->s_time_gran = 1;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+       sb->s_xattr = shmem_xattr_handlers;
+       sb->s_flags |= MS_POSIXACL;
+#endif
 
        inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
        if (!inode)
@@ -2131,6 +2193,7 @@ static void shmem_destroy_inode(struct inode *inode)
                /* only struct inode is valid if it's an inline symlink */
                mpol_free_shared_policy(&SHMEM_I(inode)->policy);
        }
+       shmem_acl_destroy_inode(inode);
        kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 }
 
@@ -2142,6 +2205,10 @@ static void init_once(void *foo, struct kmem_cache *cachep,
        if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
            SLAB_CTOR_CONSTRUCTOR) {
                inode_init_once(&p->vfs_inode);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+               p->i_acl = NULL;
+               p->i_default_acl = NULL;
+#endif
        }
 }
 
@@ -2157,8 +2224,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(shmem_inode_cachep))
-               printk(KERN_INFO "shmem_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(shmem_inode_cachep);
 }
 
 static const struct address_space_operations shmem_aops = {
@@ -2186,6 +2252,14 @@ static struct inode_operations shmem_inode_operations = {
        .truncate       = shmem_truncate,
        .setattr        = shmem_notify_change,
        .truncate_range = shmem_truncate_range,
+#ifdef CONFIG_TMPFS_POSIX_ACL
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = generic_listxattr,
+       .removexattr    = generic_removexattr,
+       .permission     = shmem_permission,
+#endif
+
 };
 
 static struct inode_operations shmem_dir_inode_operations = {
@@ -2200,6 +2274,25 @@ static struct inode_operations shmem_dir_inode_operations = {
        .mknod          = shmem_mknod,
        .rename         = shmem_rename,
 #endif
+#ifdef CONFIG_TMPFS_POSIX_ACL
+       .setattr        = shmem_notify_change,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = generic_listxattr,
+       .removexattr    = generic_removexattr,
+       .permission     = shmem_permission,
+#endif
+};
+
+static struct inode_operations shmem_special_inode_operations = {
+#ifdef CONFIG_TMPFS_POSIX_ACL
+       .setattr        = shmem_notify_change,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = generic_listxattr,
+       .removexattr    = generic_removexattr,
+       .permission     = shmem_permission,
+#endif
 };
 
 static struct super_operations shmem_ops = {
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
new file mode 100644 (file)
index 0000000..c946bf4
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * mm/shmem_acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/fs.h>
+#include <linux/shmem_fs.h>
+#include <linux/xattr.h>
+#include <linux/generic_acl.h>
+
+/**
+ * shmem_get_acl  -   generic_acl_operations->getacl() operation
+ */
+static struct posix_acl *
+shmem_get_acl(struct inode *inode, int type)
+{
+       struct posix_acl *acl = NULL;
+
+       spin_lock(&inode->i_lock);
+       switch(type) {
+               case ACL_TYPE_ACCESS:
+                       acl = posix_acl_dup(SHMEM_I(inode)->i_acl);
+                       break;
+
+               case ACL_TYPE_DEFAULT:
+                       acl = posix_acl_dup(SHMEM_I(inode)->i_default_acl);
+                       break;
+       }
+       spin_unlock(&inode->i_lock);
+
+       return acl;
+}
+
+/**
+ * shmem_get_acl  -   generic_acl_operations->setacl() operation
+ */
+static void
+shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+       struct posix_acl *free = NULL;
+
+       spin_lock(&inode->i_lock);
+       switch(type) {
+               case ACL_TYPE_ACCESS:
+                       free = SHMEM_I(inode)->i_acl;
+                       SHMEM_I(inode)->i_acl = posix_acl_dup(acl);
+                       break;
+
+               case ACL_TYPE_DEFAULT:
+                       free = SHMEM_I(inode)->i_default_acl;
+                       SHMEM_I(inode)->i_default_acl = posix_acl_dup(acl);
+                       break;
+       }
+       spin_unlock(&inode->i_lock);
+       posix_acl_release(free);
+}
+
+struct generic_acl_operations shmem_acl_ops = {
+       .getacl = shmem_get_acl,
+       .setacl = shmem_set_acl,
+};
+
+/**
+ * shmem_list_acl_access, shmem_get_acl_access, shmem_set_acl_access,
+ * shmem_xattr_acl_access_handler  -  plumbing code to implement the
+ * system.posix_acl_access xattr using the generic acl functions.
+ */
+
+static size_t
+shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
+                     const char *name, size_t name_len)
+{
+       return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
+                               list, list_size);
+}
+
+static int
+shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
+                    size_t size)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, buffer,
+                              size);
+}
+
+static int
+shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
+                    size_t size, int flags)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, value,
+                              size);
+}
+
+struct xattr_handler shmem_xattr_acl_access_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .list   = shmem_list_acl_access,
+       .get    = shmem_get_acl_access,
+       .set    = shmem_set_acl_access,
+};
+
+/**
+ * shmem_list_acl_default, shmem_get_acl_default, shmem_set_acl_default,
+ * shmem_xattr_acl_default_handler  -  plumbing code to implement the
+ * system.posix_acl_default xattr using the generic acl functions.
+ */
+
+static size_t
+shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
+                      const char *name, size_t name_len)
+{
+       return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
+                               list, list_size);
+}
+
+static int
+shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
+                     size_t size)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, buffer,
+                              size);
+}
+
+static int
+shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
+                     size_t size, int flags)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, value,
+                              size);
+}
+
+struct xattr_handler shmem_xattr_acl_default_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .list   = shmem_list_acl_default,
+       .get    = shmem_get_acl_default,
+       .set    = shmem_set_acl_default,
+};
+
+/**
+ * shmem_acl_init  -  Inizialize the acl(s) of a new inode
+ */
+int
+shmem_acl_init(struct inode *inode, struct inode *dir)
+{
+       return generic_acl_init(inode, dir, &shmem_acl_ops);
+}
+
+/**
+ * shmem_acl_destroy_inode  -  destroy acls hanging off the in-memory inode
+ *
+ * This is done before destroying the actual inode.
+ */
+
+void
+shmem_acl_destroy_inode(struct inode *inode)
+{
+       if (SHMEM_I(inode)->i_acl)
+               posix_acl_release(SHMEM_I(inode)->i_acl);
+       SHMEM_I(inode)->i_acl = NULL;
+       if (SHMEM_I(inode)->i_default_acl)
+               posix_acl_release(SHMEM_I(inode)->i_default_acl);
+       SHMEM_I(inode)->i_default_acl = NULL;
+}
+
+/**
+ * shmem_check_acl  -  check_acl() callback for generic_permission()
+ */
+static int
+shmem_check_acl(struct inode *inode, int mask)
+{
+       struct posix_acl *acl = shmem_get_acl(inode, ACL_TYPE_ACCESS);
+
+       if (acl) {
+               int error = posix_acl_permission(inode, acl, mask);
+               posix_acl_release(acl);
+               return error;
+       }
+       return -EAGAIN;
+}
+
+/**
+ * shmem_permission  -  permission() inode operation
+ */
+int
+shmem_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+       return generic_permission(inode, mask, shmem_check_acl);
+}
index 7a48eb1a60c834bf3a3b9698f43a82d8ebcae1e8..3dbd6f4e74774be9fd1db7e19d581ae31b1f4cce 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -972,7 +972,39 @@ static int transfer_objects(struct array_cache *to,
        return nr;
 }
 
-#ifdef CONFIG_NUMA
+#ifndef CONFIG_NUMA
+
+#define drain_alien_cache(cachep, alien) do { } while (0)
+#define reap_alien(cachep, l3) do { } while (0)
+
+static inline struct array_cache **alloc_alien_cache(int node, int limit)
+{
+       return (struct array_cache **)BAD_ALIEN_MAGIC;
+}
+
+static inline void free_alien_cache(struct array_cache **ac_ptr)
+{
+}
+
+static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
+{
+       return 0;
+}
+
+static inline void *alternate_node_alloc(struct kmem_cache *cachep,
+               gfp_t flags)
+{
+       return NULL;
+}
+
+static inline void *__cache_alloc_node(struct kmem_cache *cachep,
+                gfp_t flags, int nodeid)
+{
+       return NULL;
+}
+
+#else  /* CONFIG_NUMA */
+
 static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int);
 static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
 
@@ -1101,26 +1133,6 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
        }
        return 1;
 }
-
-#else
-
-#define drain_alien_cache(cachep, alien) do { } while (0)
-#define reap_alien(cachep, l3) do { } while (0)
-
-static inline struct array_cache **alloc_alien_cache(int node, int limit)
-{
-       return (struct array_cache **)BAD_ALIEN_MAGIC;
-}
-
-static inline void free_alien_cache(struct array_cache **ac_ptr)
-{
-}
-
-static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
-{
-       return 0;
-}
-
 #endif
 
 static int __cpuinit cpuup_callback(struct notifier_block *nfb,
@@ -1564,7 +1576,13 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
         */
        flags |= __GFP_COMP;
 #endif
-       flags |= cachep->gfpflags;
+
+       /*
+        * Under NUMA we want memory on the indicated node. We will handle
+        * the needed fallback ourselves since we want to serve from our
+        * per node object lists first for other nodes.
+        */
+       flags |= cachep->gfpflags | GFP_THISNODE;
 
        page = alloc_pages_node(nodeid, flags, cachep->gfporder);
        if (!page)
@@ -1665,10 +1683,32 @@ static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
 static void dump_line(char *data, int offset, int limit)
 {
        int i;
+       unsigned char error = 0;
+       int bad_count = 0;
+
        printk(KERN_ERR "%03x:", offset);
-       for (i = 0; i < limit; i++)
+       for (i = 0; i < limit; i++) {
+               if (data[offset + i] != POISON_FREE) {
+                       error = data[offset + i];
+                       bad_count++;
+               }
                printk(" %02x", (unsigned char)data[offset + i]);
+       }
        printk("\n");
+
+       if (bad_count == 1) {
+               error ^= POISON_FREE;
+               if (!(error & (error - 1))) {
+                       printk(KERN_ERR "Single bit error detected. Probably "
+                                       "bad RAM.\n");
+#ifdef CONFIG_X86
+                       printk(KERN_ERR "Run memtest86+ or a similar memory "
+                                       "test tool.\n");
+#else
+                       printk(KERN_ERR "Run a memory test tool.\n");
+#endif
+               }
+       }
 }
 #endif
 
@@ -2442,7 +2482,6 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  * @cachep: the cache to destroy
  *
  * Remove a struct kmem_cache object from the slab cache.
- * Returns 0 on success.
  *
  * It is expected this function will be called by a module when it is
  * unloaded.  This will remove the cache completely, and avoid a duplicate
@@ -2454,7 +2493,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  * The caller must guarantee that noone will allocate memory from the cache
  * during the kmem_cache_destroy().
  */
-int kmem_cache_destroy(struct kmem_cache *cachep)
+void kmem_cache_destroy(struct kmem_cache *cachep)
 {
        BUG_ON(!cachep || in_interrupt());
 
@@ -2475,7 +2514,7 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
                list_add(&cachep->next, &cache_chain);
                mutex_unlock(&cache_chain_mutex);
                unlock_cpu_hotplug();
-               return 1;
+               return;
        }
 
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
@@ -2483,7 +2522,6 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
 
        __kmem_cache_destroy(cachep);
        unlock_cpu_hotplug();
-       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
@@ -3030,14 +3068,6 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
        void *objp;
        struct array_cache *ac;
 
-#ifdef CONFIG_NUMA
-       if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY))) {
-               objp = alternate_node_alloc(cachep, flags);
-               if (objp != NULL)
-                       return objp;
-       }
-#endif
-
        check_irq_off();
        ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
@@ -3055,12 +3085,24 @@ static __always_inline void *__cache_alloc(struct kmem_cache *cachep,
                                                gfp_t flags, void *caller)
 {
        unsigned long save_flags;
-       void *objp;
+       void *objp = NULL;
 
        cache_alloc_debugcheck_before(cachep, flags);
 
        local_irq_save(save_flags);
-       objp = ____cache_alloc(cachep, flags);
+
+       if (unlikely(NUMA_BUILD &&
+                       current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY)))
+               objp = alternate_node_alloc(cachep, flags);
+
+       if (!objp)
+               objp = ____cache_alloc(cachep, flags);
+       /*
+        * We may just have run out of memory on the local node.
+        * __cache_alloc_node() knows how to locate memory on other nodes
+        */
+       if (NUMA_BUILD && !objp)
+               objp = __cache_alloc_node(cachep, flags, numa_node_id());
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp,
                                            caller);
@@ -3079,7 +3121,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        int nid_alloc, nid_here;
 
-       if (in_interrupt())
+       if (in_interrupt() || (flags & __GFP_THISNODE))
                return NULL;
        nid_alloc = nid_here = numa_node_id();
        if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD))
@@ -3091,6 +3133,28 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
        return NULL;
 }
 
+/*
+ * Fallback function if there was no memory available and no objects on a
+ * certain node and we are allowed to fall back. We mimick the behavior of
+ * the page allocator. We fall back according to a zonelist determined by
+ * the policy layer while obeying cpuset constraints.
+ */
+void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+       struct zonelist *zonelist = &NODE_DATA(slab_node(current->mempolicy))
+                                       ->node_zonelists[gfp_zone(flags)];
+       struct zone **z;
+       void *obj = NULL;
+
+       for (z = zonelist->zones; *z && !obj; z++)
+               if (zone_idx(*z) <= ZONE_NORMAL &&
+                               cpuset_zone_allowed(*z, flags))
+                       obj = __cache_alloc_node(cache,
+                                       flags | __GFP_THISNODE,
+                                       zone_to_nid(*z));
+       return obj;
+}
+
 /*
  * A interface to enable slab creation on nodeid
  */
@@ -3144,11 +3208,15 @@ retry:
 must_grow:
        spin_unlock(&l3->list_lock);
        x = cache_grow(cachep, flags, nodeid);
+       if (x)
+               goto retry;
 
-       if (!x)
-               return NULL;
+       if (!(flags & __GFP_THISNODE))
+               /* Unable to grow the cache. Fall back to other nodes. */
+               return fallback_alloc(cachep, flags);
+
+       return NULL;
 
-       goto retry;
 done:
        return obj;
 }
index 20188627347c5dae1ae2575e1f036b6d9b03906f..542394184a58e6c825a3b24cc7dfe1ad0e6e4fba 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -270,10 +270,9 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
-int kmem_cache_destroy(struct kmem_cache *c)
+void kmem_cache_destroy(struct kmem_cache *c)
 {
        slob_free(c, sizeof(struct kmem_cache));
-       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
index f1f5ec783781cfebcbd4f3c5efe79336eaedcfa1..a15def63f28f19e8e9d0e9f550177b80b033526e 100644 (file)
@@ -1723,13 +1723,14 @@ get_swap_info_struct(unsigned type)
  */
 int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
 {
-       int ret = 0, i = 1 << page_cluster;
+       int our_page_cluster = page_cluster;
+       int ret = 0, i = 1 << our_page_cluster;
        unsigned long toff;
        struct swap_info_struct *swapdev = swp_type(entry) + swap_info;
 
-       if (!page_cluster)      /* no readahead */
+       if (!our_page_cluster)  /* no readahead */
                return 0;
-       toff = (swp_offset(entry) >> page_cluster) << page_cluster;
+       toff = (swp_offset(entry) >> our_page_cluster) << our_page_cluster;
        if (!toff)              /* first page is swap header */
                toff++, i--;
        *offset = toff;
index c6ab55ec6883378cb46367e54c7568f1f2b3983d..f4edbc179d14423e1f3acf9555b96bc9795b37bc 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
                                   do_invalidatepage */
 
 
+/**
+ * do_invalidatepage - invalidate part of all of a page
+ * @page: the page which is affected
+ * @offset: the index of the truncation point
+ *
+ * do_invalidatepage() is called when all or part of the page has become
+ * invalidated by a truncate operation.
+ *
+ * do_invalidatepage() does not have to release all buffers, but it must
+ * ensure that no dirty buffer is left outside @offset and that no I/O
+ * is underway against any of the blocks which are outside the truncation
+ * point.  Because the caller is about to free (and possibly reuse) those
+ * blocks on-disk.
+ */
+void do_invalidatepage(struct page *page, unsigned long offset)
+{
+       void (*invalidatepage)(struct page *, unsigned long);
+       invalidatepage = page->mapping->a_ops->invalidatepage;
+#ifdef CONFIG_BLOCK
+       if (!invalidatepage)
+               invalidatepage = block_invalidatepage;
+#endif
+       if (invalidatepage)
+               (*invalidatepage)(page, offset);
+}
+
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
        memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
@@ -52,36 +79,26 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
 /*
  * This is for invalidate_inode_pages().  That function can be called at
  * any time, and is not supposed to throw away dirty pages.  But pages can
- * be marked dirty at any time too.  So we re-check the dirtiness inside
- * ->tree_lock.  That provides exclusion against the __set_page_dirty
- * functions.
+ * be marked dirty at any time too, so use remove_mapping which safely
+ * discards clean, unused pages.
  *
  * Returns non-zero if the page was successfully invalidated.
  */
 static int
 invalidate_complete_page(struct address_space *mapping, struct page *page)
 {
+       int ret;
+
        if (page->mapping != mapping)
                return 0;
 
        if (PagePrivate(page) && !try_to_release_page(page, 0))
                return 0;
 
-       write_lock_irq(&mapping->tree_lock);
-       if (PageDirty(page))
-               goto failed;
-       if (page_count(page) != 2)      /* caller's ref + pagecache ref */
-               goto failed;
-
-       BUG_ON(PagePrivate(page));
-       __remove_from_page_cache(page);
-       write_unlock_irq(&mapping->tree_lock);
+       ret = remove_mapping(mapping, page);
        ClearPageUptodate(page);
-       page_cache_release(page);       /* pagecache ref */
-       return 1;
-failed:
-       write_unlock_irq(&mapping->tree_lock);
-       return 0;
+
+       return ret;
 }
 
 /**
@@ -270,9 +287,39 @@ unsigned long invalidate_inode_pages(struct address_space *mapping)
 {
        return invalidate_mapping_pages(mapping, 0, ~0UL);
 }
-
 EXPORT_SYMBOL(invalidate_inode_pages);
 
+/*
+ * This is like invalidate_complete_page(), except it ignores the page's
+ * refcount.  We do this because invalidate_inode_pages2() needs stronger
+ * invalidation guarantees, and cannot afford to leave pages behind because
+ * shrink_list() has a temp ref on them, or because they're transiently sitting
+ * in the lru_cache_add() pagevecs.
+ */
+static int
+invalidate_complete_page2(struct address_space *mapping, struct page *page)
+{
+       if (page->mapping != mapping)
+               return 0;
+
+       if (PagePrivate(page) && !try_to_release_page(page, 0))
+               return 0;
+
+       write_lock_irq(&mapping->tree_lock);
+       if (PageDirty(page))
+               goto failed;
+
+       BUG_ON(PagePrivate(page));
+       __remove_from_page_cache(page);
+       write_unlock_irq(&mapping->tree_lock);
+       ClearPageUptodate(page);
+       page_cache_release(page);       /* pagecache ref */
+       return 1;
+failed:
+       write_unlock_irq(&mapping->tree_lock);
+       return 0;
+}
+
 /**
  * invalidate_inode_pages2_range - remove range of pages from an address_space
  * @mapping: the address_space
@@ -339,7 +386,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
                                }
                        }
                        was_dirty = test_clear_page_dirty(page);
-                       if (!invalidate_complete_page(mapping, page)) {
+                       if (!invalidate_complete_page2(mapping, page)) {
                                if (was_dirty)
                                        set_page_dirty(page);
                                ret = -EIO;
index 7368479220b3b4c3d8c12a9306bb18221d9a99b9..e14fa84ef39a2df08b2087259c110851bfcf1bcc 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -40,6 +40,24 @@ char *kstrdup(const char *s, gfp_t gfp)
 }
 EXPORT_SYMBOL(kstrdup);
 
+/**
+ * kmemdup - duplicate region of memory
+ *
+ * @src: memory region to duplicate
+ * @len: memory region length
+ * @gfp: GFP mask to use
+ */
+void *kmemdup(const void *src, size_t len, gfp_t gfp)
+{
+       void *p;
+
+       p = ____kmalloc(len, gfp);
+       if (p)
+               memcpy(p, src, len);
+       return p;
+}
+EXPORT_SYMBOL(kmemdup);
+
 /*
  * strndup_user - duplicate an existing string from user space
  *
index 9aad8b0cc6ee71f5da612d0c4bd79aa8a3fb4476..1ac191ce564142b46cf46ec7655231d76aad093e 100644 (file)
@@ -241,7 +241,6 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 
 /**
  *     get_vm_area  -  reserve a contingous kernel virtual area
- *
  *     @size:          size of the area
  *     @flags:         %VM_IOREMAP for I/O mappings or VM_ALLOC
  *
@@ -273,7 +272,7 @@ static struct vm_struct *__find_vm_area(void *addr)
 }
 
 /* Caller must hold vmlist_lock */
-struct vm_struct *__remove_vm_area(void *addr)
+static struct vm_struct *__remove_vm_area(void *addr)
 {
        struct vm_struct **p, *tmp;
 
@@ -296,7 +295,6 @@ found:
 
 /**
  *     remove_vm_area  -  find and remove a contingous kernel virtual area
- *
  *     @addr:          base address
  *
  *     Search for the kernel VM area starting at @addr, and remove it.
@@ -355,7 +353,6 @@ void __vunmap(void *addr, int deallocate_pages)
 
 /**
  *     vfree  -  release memory allocated by vmalloc()
- *
  *     @addr:          memory base address
  *
  *     Free the virtually contiguous memory area starting at @addr, as
@@ -373,7 +370,6 @@ EXPORT_SYMBOL(vfree);
 
 /**
  *     vunmap  -  release virtual mapping obtained by vmap()
- *
  *     @addr:          memory base address
  *
  *     Free the virtually contiguous memory area starting at @addr,
@@ -390,7 +386,6 @@ EXPORT_SYMBOL(vunmap);
 
 /**
  *     vmap  -  map an array of pages into virtually contiguous space
- *
  *     @pages:         array of page pointers
  *     @count:         number of pages to map
  *     @flags:         vm_area->flags
@@ -471,7 +466,6 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
 
 /**
  *     __vmalloc_node  -  allocate virtually contiguous memory
- *
  *     @size:          allocation size
  *     @gfp_mask:      flags for the page level allocator
  *     @prot:          protection mask for the allocated pages
@@ -505,9 +499,7 @@ EXPORT_SYMBOL(__vmalloc);
 
 /**
  *     vmalloc  -  allocate virtually contiguous memory
- *
  *     @size:          allocation size
- *
  *     Allocate enough pages to cover @size from the page level
  *     allocator and map them into contiguous kernel virtual space.
  *
@@ -521,11 +513,11 @@ void *vmalloc(unsigned long size)
 EXPORT_SYMBOL(vmalloc);
 
 /**
- *     vmalloc_user  -  allocate virtually contiguous memory which has
- *                        been zeroed so it can be mapped to userspace without
- *                        leaking data.
+ * vmalloc_user - allocate zeroed virtually contiguous memory for userspace
+ * @size: allocation size
  *
- *     @size:          allocation size
+ * The resulting memory area is zeroed so it can be mapped to userspace
+ * without leaking data.
  */
 void *vmalloc_user(unsigned long size)
 {
@@ -544,7 +536,6 @@ EXPORT_SYMBOL(vmalloc_user);
 
 /**
  *     vmalloc_node  -  allocate memory on a specific node
- *
  *     @size:          allocation size
  *     @node:          numa node
  *
@@ -566,7 +557,6 @@ EXPORT_SYMBOL(vmalloc_node);
 
 /**
  *     vmalloc_exec  -  allocate virtually contiguous, executable memory
- *
  *     @size:          allocation size
  *
  *     Kernel-internal function to allocate enough pages to cover @size
@@ -584,7 +574,6 @@ void *vmalloc_exec(unsigned long size)
 
 /**
  *     vmalloc_32  -  allocate virtually contiguous memory (32bit addressable)
- *
  *     @size:          allocation size
  *
  *     Allocate enough 32bit PA addressable pages to cover @size from the
@@ -597,11 +586,11 @@ void *vmalloc_32(unsigned long size)
 EXPORT_SYMBOL(vmalloc_32);
 
 /**
- *     vmalloc_32_user  -  allocate virtually contiguous memory (32bit
- *                           addressable) which is zeroed so it can be
- *                           mapped to userspace without leaking data.
- *
+ * vmalloc_32_user - allocate zeroed virtually contiguous 32bit memory
  *     @size:          allocation size
+ *
+ * The resulting memory area is 32bit addressable and zeroed so it can be
+ * mapped to userspace without leaking data.
  */
 void *vmalloc_32_user(unsigned long size)
 {
@@ -695,7 +684,6 @@ finished:
 
 /**
  *     remap_vmalloc_range  -  map vmalloc pages to userspace
- *
  *     @vma:           vma to cover (map full range of vma)
  *     @addr:          vmalloc memory
  *     @pgoff:         number of pages into addr before first page to map
index 87779dda4ec6d7af4afe8427c6cf0476138d3245..eca70310adb26239e94c5435eaf2abf0271c89fa 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/vmstat.h>
 #include <linux/file.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
@@ -370,7 +371,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
                        /* synchronous write or broken a_ops? */
                        ClearPageReclaim(page);
                }
-
+               inc_zone_page_state(page, NR_VMSCAN_WRITE);
                return PAGE_SUCCESS;
        }
 
@@ -383,11 +384,30 @@ int remove_mapping(struct address_space *mapping, struct page *page)
        BUG_ON(mapping != page_mapping(page));
 
        write_lock_irq(&mapping->tree_lock);
-
        /*
-        * The non-racy check for busy page.  It is critical to check
-        * PageDirty _after_ making sure that the page is freeable and
-        * not in use by anybody.       (pagecache + us == 2)
+        * The non racy check for a busy page.
+        *
+        * Must be careful with the order of the tests. When someone has
+        * a ref to the page, it may be possible that they dirty it then
+        * drop the reference. So if PageDirty is tested before page_count
+        * here, then the following race may occur:
+        *
+        * get_user_pages(&page);
+        * [user mapping goes away]
+        * write_to(page);
+        *                              !PageDirty(page)    [good]
+        * SetPageDirty(page);
+        * put_page(page);
+        *                              !page_count(page)   [good, discard it]
+        *
+        * [oops, our write_to data is lost]
+        *
+        * Reversing the order of the tests ensures such a situation cannot
+        * escape unnoticed. The smp_rmb is needed to ensure the page->flags
+        * load is not satisfied before that of page->_count.
+        *
+        * Note that if SetPageDirty is always performed via set_page_dirty,
+        * and thus under tree_lock, then this ordering is not required.
         */
        if (unlikely(page_count(page) != 2))
                goto cannot_free;
index 490d8c1a0ded5efe731e6729136e3460341b3e5e..a2b6a9f96e5c6390625ec031763a74de9fa5f5b2 100644 (file)
@@ -371,7 +371,7 @@ void zone_statistics(struct zonelist *zonelist, struct zone *z)
                __inc_zone_state(z, NUMA_MISS);
                __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN);
        }
-       if (z->zone_pgdat == NODE_DATA(numa_node_id()))
+       if (z->node == numa_node_id())
                __inc_zone_state(z, NUMA_LOCAL);
        else
                __inc_zone_state(z, NUMA_OTHER);
@@ -465,6 +465,7 @@ static char *vmstat_text[] = {
        "nr_writeback",
        "nr_unstable",
        "nr_bounce",
+       "nr_vmscan_write",
 
 #ifdef CONFIG_NUMA
        "numa_hit",
index d7d8f40c4fed0d17d0113eceb92de3d821e723fc..829deb41ce81d436aad10567d03d35ca86532b58 100644 (file)
@@ -164,7 +164,7 @@ static int tr_rebuild_header(struct sk_buff *skb)
         */
         
        if(trllc->ethertype != htons(ETH_P_IP)) {
-               printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(trllc->ethertype));
+               printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(trllc->ethertype));
                return 0;
        }
 
@@ -186,7 +186,7 @@ static int tr_rebuild_header(struct sk_buff *skb)
  *     it via SNAP.
  */
  
-unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) 
+__be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 
        struct trh_hdr *trh=(struct trh_hdr *)skb->data;
@@ -229,15 +229,15 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev)
         */
 
        if (trllc->dsap == EXTENDED_SAP &&
-           (trllc->ethertype == ntohs(ETH_P_IP) ||
-            trllc->ethertype == ntohs(ETH_P_IPV6) ||
-            trllc->ethertype == ntohs(ETH_P_ARP)))
+           (trllc->ethertype == htons(ETH_P_IP) ||
+            trllc->ethertype == htons(ETH_P_IPV6) ||
+            trllc->ethertype == htons(ETH_P_ARP)))
        {
                skb_pull(skb, sizeof(struct trllc));
                return trllc->ethertype;
        }
 
-       return ntohs(ETH_P_TR_802_2);
+       return htons(ETH_P_TR_802_2);
 }
 
 /*
index 6528a935622cc61ca2269a250ada0181932c61ff..a81aca43932f975ed912e1f00482e24b5a6d7102 100644 (file)
@@ -231,7 +231,7 @@ config NET_TCPPROBE
        TCP congestion avoidance modules. If you don't understand
        what was just said, you don't need it: say N.
 
-       Documentation on how to use the packet generator can be found
+       Documentation on how to use TCP connection probing can be found
        at http://linux-net.osdl.org/index.php/TcpProbe
 
        To compile this code as a module, choose M here: the
index 96dc6bb52d14aecd00cff0e8f37bed950d6b557f..708e2e0371aff2ae8be46529c112be0078e58686 100644 (file)
@@ -1002,7 +1002,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
        return sum;
 }
 
-static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
+static __be16 atalk_checksum(const struct sk_buff *skb, int len)
 {
        unsigned long sum;
 
@@ -1010,7 +1010,7 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
        sum = atalk_sum_skb(skb, 4, len-4, 0);
 
        /* Use 0xFFFF for 0. 0 itself means none */
-       return sum ? htons((unsigned short)sum) : 0xFFFF;
+       return sum ? htons((unsigned short)sum) : htons(0xFFFF);
 }
 
 static struct proto ddp_proto = {
@@ -1289,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
 #endif
 
 static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
-                              struct ddpehdr *ddp, struct ddpebits *ddphv,
+                              struct ddpehdr *ddp, __u16 len_hops,
                               int origlen)
 {
        struct atalk_route *rt;
@@ -1317,10 +1317,12 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
 
        /* Route the packet */
        rt = atrtr_find(&ta);
-       if (!rt || ddphv->deh_hops == DDP_MAXHOPS)
+       /* increment hops count */
+       len_hops += 1 << 10;
+       if (!rt || !(len_hops & (15 << 10)))
                goto free_it;
+
        /* FIXME: use skb->cb to be able to use shared skbs */
-       ddphv->deh_hops++;
 
        /*
         * Route goes through another gateway, so set the target to the
@@ -1335,11 +1337,10 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
         /* Fix up skb->len field */
         skb_trim(skb, min_t(unsigned int, origlen,
                            (rt->dev->hard_header_len +
-                            ddp_dl->header_length + ddphv->deh_len)));
+                            ddp_dl->header_length + (len_hops & 1023))));
 
-       /* Mend the byte order */
        /* FIXME: use skb->cb to be able to use shared skbs */
-       *((__u16 *)ddp) = ntohs(*((__u16 *)ddphv));
+       ddp->deh_len_hops = htons(len_hops);
 
        /*
         * Send the buffer onwards
@@ -1394,7 +1395,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
        struct atalk_iface *atif;
        struct sockaddr_at tosat;
         int origlen;
-        struct ddpebits ddphv;
+       __u16 len_hops;
 
        /* Don't mangle buffer if shared */
        if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 
@@ -1406,16 +1407,11 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
 
        ddp = ddp_hdr(skb);
 
-       /*
-        *      Fix up the length field [Ok this is horrible but otherwise
-        *      I end up with unions of bit fields and messy bit field order
-        *      compiler/endian dependencies..]
-        */
-       *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+       len_hops = ntohs(ddp->deh_len_hops);
 
        /* Trim buffer in case of stray trailing data */
        origlen = skb->len;
-       skb_trim(skb, min_t(unsigned int, skb->len, ddphv.deh_len));
+       skb_trim(skb, min_t(unsigned int, skb->len, len_hops & 1023));
 
        /*
         * Size check to see if ddp->deh_len was crap
@@ -1430,7 +1426,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
         * valid for net byte orders all over the networking code...
         */
        if (ddp->deh_sum &&
-           atalk_checksum(skb, ddphv.deh_len) != ddp->deh_sum)
+           atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
                /* Not a valid AppleTalk frame - dustbin time */
                goto freeit;
 
@@ -1444,7 +1440,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Not ours, so we route the packet via the correct
                 * AppleTalk iface
                 */
-               atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
+               atalk_route_packet(skb, dev, ddp, len_hops, origlen);
                goto out;
        }
 
@@ -1489,7 +1485,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Find our address */
                struct atalk_addr *ap = atalk_find_dev_addr(dev);
 
-               if (!ap || skb->len < sizeof(struct ddpshdr))
+               if (!ap || skb->len < sizeof(__be16) || skb->len > 1023)
                        goto freeit;
 
                /* Don't mangle buffer if shared */
@@ -1519,11 +1515,8 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /*
                 * Not sure about this bit...
                 */
-               ddp->deh_len   = skb->len;
-               ddp->deh_hops  = DDP_MAXHOPS;   /* Non routable, so force a drop
-                                                  if we slip up later */
-               /* Mend the byte order */
-               *((__u16 *)ddp) = htons(*((__u16 *)ddp));
+               /* Non routable, so force a drop if we slip up later */
+               ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
        }
        skb->h.raw = skb->data;
 
@@ -1622,16 +1615,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
 
        ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
-       ddp->deh_pad  = 0;
-       ddp->deh_hops = 0;
-       ddp->deh_len  = len + sizeof(*ddp);
-       /*
-        * Fix up the length field [Ok this is horrible but otherwise
-        * I end up with unions of bit fields and messy bit field order
-        * compiler/endian dependencies..
-        */
-       *((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
-
+       ddp->deh_len_hops  = htons(len + sizeof(*ddp));
        ddp->deh_dnet  = usat->sat_addr.s_net;
        ddp->deh_snet  = at->src_net;
        ddp->deh_dnode = usat->sat_addr.s_node;
@@ -1712,8 +1696,8 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
        struct ddpehdr *ddp;
        int copied = 0;
+       int offset = 0;
        int err = 0;
-        struct ddpebits ddphv;
        struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                                flags & MSG_DONTWAIT, &err);
        if (!skb)
@@ -1721,25 +1705,18 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 
        /* FIXME: use skb->cb to be able to use shared skbs */
        ddp = ddp_hdr(skb);
-       *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+       copied = ntohs(ddp->deh_len_hops) & 1023;
 
-       if (sk->sk_type == SOCK_RAW) {
-               copied = ddphv.deh_len;
-               if (copied > size) {
-                       copied = size;
-                       msg->msg_flags |= MSG_TRUNC;
-               }
+       if (sk->sk_type != SOCK_RAW) {
+               offset = sizeof(*ddp);
+               copied -= offset;
+       }
 
-               err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-       } else {
-               copied = ddphv.deh_len - sizeof(*ddp);
-               if (copied > size) {
-                       copied = size;
-                       msg->msg_flags |= MSG_TRUNC;
-               }
-               err = skb_copy_datagram_iovec(skb, sizeof(*ddp),
-                                             msg->msg_iov, copied);
+       if (copied > size) {
+               copied = size;
+               msg->msg_flags |= MSG_TRUNC;
        }
+       err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
 
        if (!err) {
                if (sat) {
index b4aa489849dfefc0185395415de8e88c31b303ab..66c57c1091a8e3ff2020bd75135f7ac65e971544 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lec.c: Lan Emulation driver 
- * Marko Kiiskila mkiiskila@yahoo.com
  *
+ * Marko Kiiskila <mkiiskila@yahoo.com>
  */
 
 #include <linux/kernel.h>
@@ -38,7 +38,7 @@
 #include <linux/if_bridge.h>
 #include "../bridge/br_private.h"
 
-static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
+static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
 #endif
 
 /* Modular too */
@@ -55,38 +55,41 @@ static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
 #define DPRINTK(format,args...)
 #endif
 
-#define DUMP_PACKETS 0 /* 0 = None,
-                        * 1 = 30 first bytes
-                        * 2 = Whole packet
-                        */
+#define DUMP_PACKETS 0         /*
+                                * 0 = None,
+                                * 1 = 30 first bytes
+                                * 2 = Whole packet
+                                */
 
-#define LEC_UNRES_QUE_LEN 8 /* number of tx packets to queue for a
-                               single destination while waiting for SVC */
+#define LEC_UNRES_QUE_LEN 8    /*
+                                * number of tx packets to queue for a
+                                * single destination while waiting for SVC
+                                */
 
 static int lec_open(struct net_device *dev);
 static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lec_close(struct net_device *dev);
 static struct net_device_stats *lec_get_stats(struct net_device *dev);
 static void lec_init(struct net_device *dev);
-static struct lec_arp_tablelec_arp_find(struct lec_priv *priv,
-                                                     unsigned char *mac_addr);
+static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
+                                         unsigned char *mac_addr);
 static int lec_arp_remove(struct lec_priv *priv,
-                                    struct lec_arp_table *to_remove);
+                         struct lec_arp_table *to_remove);
 /* LANE2 functions */
-static void lane2_associate_ind (struct net_device *dev, u8 *mac_address,
-                          u8 *tlvs, u32 sizeoftlvs);
+static void lane2_associate_ind(struct net_device *dev, u8 *mac_address,
+                               u8 *tlvs, u32 sizeoftlvs);
 static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
-                  u8 **tlvs, u32 *sizeoftlvs);
-static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
-                         u8 *tlvs, u32 sizeoftlvs);
+                        u8 **tlvs, u32 *sizeoftlvs);
+static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
+                              u8 *tlvs, u32 sizeoftlvs);
 
-static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, 
+static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
                           unsigned long permanent);
 static void lec_arp_check_empties(struct lec_priv *priv,
                                  struct atm_vcc *vcc, struct sk_buff *skb);
 static void lec_arp_destroy(struct lec_priv *priv);
 static void lec_arp_init(struct lec_priv *priv);
-static struct atm_vcclec_arp_resolve(struct lec_priv *priv,
+static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
                                       unsigned char *mac_to_find,
                                       int is_rdesc,
                                       struct lec_arp_table **ret_entry);
@@ -100,16 +103,30 @@ static void lec_set_flush_tran_id(struct lec_priv *priv,
                                  unsigned long tran_id);
 static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
                          struct atm_vcc *vcc,
-                         void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb));
+                         void (*old_push) (struct atm_vcc *vcc,
+                                           struct sk_buff *skb));
 static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
 
+/* must be done under lec_arp_lock */
+static inline void lec_arp_hold(struct lec_arp_table *entry)
+{
+       atomic_inc(&entry->usage);
+}
+
+static inline void lec_arp_put(struct lec_arp_table *entry)
+{
+       if (atomic_dec_and_test(&entry->usage))
+               kfree(entry);
+}
+
+
 static struct lane2_ops lane2_ops = {
-       lane2_resolve,         /* resolve,             spec 3.1.3 */
-       lane2_associate_req,   /* associate_req,       spec 3.1.4 */
-       NULL                  /* associate indicator, spec 3.1.5 */
+       lane2_resolve,          /* resolve,             spec 3.1.3 */
+       lane2_associate_req,    /* associate_req,       spec 3.1.4 */
+       NULL                    /* associate indicator, spec 3.1.5 */
 };
 
-static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 /* Device structures */
 static struct net_device *dev_lec[MAX_LEC_ITF];
@@ -117,36 +134,39 @@ static struct net_device *dev_lec[MAX_LEC_ITF];
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
 {
-        struct ethhdr *eth;
-        char *buff;
-        struct lec_priv *priv;
-
-        /* Check if this is a BPDU. If so, ask zeppelin to send
-         * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
-         * as the Config BPDU has */
-        eth = (struct ethhdr *)skb->data;
-        buff = skb->data + skb->dev->hard_header_len;
-        if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
+       struct ethhdr *eth;
+       char *buff;
+       struct lec_priv *priv;
+
+       /*
+        * Check if this is a BPDU. If so, ask zeppelin to send
+        * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit
+        * as the Config BPDU has
+        */
+       eth = (struct ethhdr *)skb->data;
+       buff = skb->data + skb->dev->hard_header_len;
+       if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
                struct sock *sk;
-                struct sk_buff *skb2;
-                struct atmlec_msg *mesg;
-
-                skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
-                if (skb2 == NULL) return;
-                skb2->len = sizeof(struct atmlec_msg);
-                mesg = (struct atmlec_msg *)skb2->data;
-                mesg->type = l_topology_change;
-                buff += 4;
-                mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */
-
-                priv = (struct lec_priv *)dev->priv;
-                atm_force_charge(priv->lecd, skb2->truesize);
+               struct sk_buff *skb2;
+               struct atmlec_msg *mesg;
+
+               skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
+               if (skb2 == NULL)
+                       return;
+               skb2->len = sizeof(struct atmlec_msg);
+               mesg = (struct atmlec_msg *)skb2->data;
+               mesg->type = l_topology_change;
+               buff += 4;
+               mesg->content.normal.flag = *buff & 0x01;       /* 0x01 is topology change */
+
+               priv = (struct lec_priv *)dev->priv;
+               atm_force_charge(priv->lecd, skb2->truesize);
                sk = sk_atm(priv->lecd);
-                skb_queue_tail(&sk->sk_receive_queue, skb2);
-                sk->sk_data_ready(sk, skb2->len);
-        }
+               skb_queue_tail(&sk->sk_receive_queue, skb2);
+               sk->sk_data_ready(sk, skb2->len);
+       }
 
-        return;
+       return;
 }
 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
 
@@ -162,36 +182,35 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
 #ifdef CONFIG_TR
 static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
 {
-        struct trh_hdr *trh;
-        int riflen, num_rdsc;
-        
-        trh = (struct trh_hdr *)packet;
-        if (trh->daddr[0] & (uint8_t)0x80)
-                return bus_mac; /* multicast */
-
-        if (trh->saddr[0] & TR_RII) {
-                riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
-                if ((ntohs(trh->rcf) >> 13) != 0)
-                        return bus_mac; /* ARE or STE */
-        }
-        else
-                return trh->daddr; /* not source routed */
-
-        if (riflen < 6)
-                return trh->daddr; /* last hop, source routed */
-                
-        /* riflen is 6 or more, packet has more than one route descriptor */
-        num_rdsc = (riflen/2) - 1;
-        memset(rdesc, 0, ETH_ALEN);
-        /* offset 4 comes from LAN destination field in LE control frames */
-        if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT))
-                memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t));
-        else {
-                memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
-                rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
-        }
-
-        return NULL;
+       struct trh_hdr *trh;
+       int riflen, num_rdsc;
+
+       trh = (struct trh_hdr *)packet;
+       if (trh->daddr[0] & (uint8_t) 0x80)
+               return bus_mac; /* multicast */
+
+       if (trh->saddr[0] & TR_RII) {
+               riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8;
+               if ((ntohs(trh->rcf) >> 13) != 0)
+                       return bus_mac; /* ARE or STE */
+       } else
+               return trh->daddr;      /* not source routed */
+
+       if (riflen < 6)
+               return trh->daddr;      /* last hop, source routed */
+
+       /* riflen is 6 or more, packet has more than one route descriptor */
+       num_rdsc = (riflen / 2) - 1;
+       memset(rdesc, 0, ETH_ALEN);
+       /* offset 4 comes from LAN destination field in LE control frames */
+       if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT))
+               memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(uint16_t));
+       else {
+               memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t));
+               rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0));
+       }
+
+       return NULL;
 }
 #endif /* CONFIG_TR */
 
@@ -204,15 +223,14 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
  * there is non-reboot way to recover if something goes wrong.
  */
 
-static int 
-lec_open(struct net_device *dev)
+static int lec_open(struct net_device *dev)
 {
-        struct lec_priv *priv = (struct lec_priv *)dev->priv;
-        
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
+
        netif_start_queue(dev);
-        memset(&priv->stats,0,sizeof(struct net_device_stats));
-        
-        return 0;
+       memset(&priv->stats, 0, sizeof(struct net_device_stats));
+
+       return 0;
 }
 
 static __inline__ void
@@ -231,160 +249,166 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
        priv->stats.tx_bytes += skb->len;
 }
 
-static void
-lec_tx_timeout(struct net_device *dev)
+static void lec_tx_timeout(struct net_device *dev)
 {
        printk(KERN_INFO "%s: tx timeout\n", dev->name);
        dev->trans_start = jiffies;
        netif_wake_queue(dev);
 }
 
-static int 
-lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-        struct sk_buff *skb2;
-        struct lec_priv *priv = (struct lec_priv *)dev->priv;
-        struct lecdatahdr_8023 *lec_h;
-        struct atm_vcc *vcc;
+       struct sk_buff *skb2;
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
+       struct lecdatahdr_8023 *lec_h;
+       struct atm_vcc *vcc;
        struct lec_arp_table *entry;
-        unsigned char *dst;
+       unsigned char *dst;
        int min_frame_size;
 #ifdef CONFIG_TR
-        unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */
+       unsigned char rdesc[ETH_ALEN];  /* Token Ring route descriptor */
 #endif
-        int is_rdesc;
+       int is_rdesc;
 #if DUMP_PACKETS > 0
-        char buf[300];
-        int i=0;
+       char buf[300];
+       int i = 0;
 #endif /* DUMP_PACKETS >0 */
-        
-        DPRINTK("lec_start_xmit called\n");  
-        if (!priv->lecd) {
-                printk("%s:No lecd attached\n",dev->name);
-                priv->stats.tx_errors++;
-                netif_stop_queue(dev);
-                return -EUNATCH;
-        } 
-
-        DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
-                (long)skb->head, (long)skb->data, (long)skb->tail,
-                (long)skb->end);
+
+       DPRINTK("lec_start_xmit called\n");
+       if (!priv->lecd) {
+               printk("%s:No lecd attached\n", dev->name);
+               priv->stats.tx_errors++;
+               netif_stop_queue(dev);
+               return -EUNATCH;
+       }
+
+       DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n",
+               (long)skb->head, (long)skb->data, (long)skb->tail,
+               (long)skb->end);
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-        if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
-                lec_handle_bridge(skb, dev);
+       if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0)
+               lec_handle_bridge(skb, dev);
 #endif
 
-        /* Make sure we have room for lec_id */
-        if (skb_headroom(skb) < 2) {
+       /* Make sure we have room for lec_id */
+       if (skb_headroom(skb) < 2) {
 
-                DPRINTK("lec_start_xmit: reallocating skb\n");
-                skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
-                kfree_skb(skb);
-                if (skb2 == NULL) return 0;
-                skb = skb2;
-        }
-        skb_push(skb, 2);
+               DPRINTK("lec_start_xmit: reallocating skb\n");
+               skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
+               kfree_skb(skb);
+               if (skb2 == NULL)
+                       return 0;
+               skb = skb2;
+       }
+       skb_push(skb, 2);
 
-        /* Put le header to place, works for TokenRing too */
-        lec_h = (struct lecdatahdr_8023*)skb->data;
-        lec_h->le_header = htons(priv->lecid); 
+       /* Put le header to place, works for TokenRing too */
+       lec_h = (struct lecdatahdr_8023 *)skb->data;
+       lec_h->le_header = htons(priv->lecid);
 
 #ifdef CONFIG_TR
-        /* Ugly. Use this to realign Token Ring packets for
-         * e.g. PCA-200E driver. */
-        if (priv->is_trdev) {
-                skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
-                kfree_skb(skb);
-                if (skb2 == NULL) return 0;
-                skb = skb2;
-        }
+       /*
+        * Ugly. Use this to realign Token Ring packets for
+        * e.g. PCA-200E driver.
+        */
+       if (priv->is_trdev) {
+               skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
+               kfree_skb(skb);
+               if (skb2 == NULL)
+                       return 0;
+               skb = skb2;
+       }
 #endif
 
 #if DUMP_PACKETS > 0
-        printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
-               skb->len, priv->lecid);
+       printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
+              skb->len, priv->lecid);
 #if DUMP_PACKETS >= 2
-        for(i=0;i<skb->len && i <99;i++) {
-                sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]);
-        }
+       for (i = 0; i < skb->len && i < 99; i++) {
+               sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
+       }
 #elif DUMP_PACKETS >= 1
-        for(i=0;i<skb->len && i < 30;i++) {
-                sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]);
-        }
+       for (i = 0; i < skb->len && i < 30; i++) {
+               sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
+       }
 #endif /* DUMP_PACKETS >= 1 */
-        if (i==skb->len)
-                printk("%s\n",buf);
-        else
-                printk("%s...\n",buf);
+       if (i == skb->len)
+               printk("%s\n", buf);
+       else
+               printk("%s...\n", buf);
 #endif /* DUMP_PACKETS > 0 */
 
-        /* Minimum ethernet-frame size */
+       /* Minimum ethernet-frame size */
 #ifdef CONFIG_TR
-        if (priv->is_trdev)
-                min_frame_size = LEC_MINIMUM_8025_SIZE;
+       if (priv->is_trdev)
+               min_frame_size = LEC_MINIMUM_8025_SIZE;
        else
 #endif
-        min_frame_size = LEC_MINIMUM_8023_SIZE;
-        if (skb->len < min_frame_size) {
-                if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
-                        skb2 = skb_copy_expand(skb, 0,
-                            min_frame_size - skb->truesize, GFP_ATOMIC);
-                                dev_kfree_skb(skb);
-                        if (skb2 == NULL) {
-                                priv->stats.tx_dropped++;
-                                return 0;
-                        }
-                        skb = skb2;
-                }
+               min_frame_size = LEC_MINIMUM_8023_SIZE;
+       if (skb->len < min_frame_size) {
+               if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
+                       skb2 = skb_copy_expand(skb, 0,
+                                              min_frame_size - skb->truesize,
+                                              GFP_ATOMIC);
+                       dev_kfree_skb(skb);
+                       if (skb2 == NULL) {
+                               priv->stats.tx_dropped++;
+                               return 0;
+                       }
+                       skb = skb2;
+               }
                skb_put(skb, min_frame_size - skb->len);
-        }
-        
-        /* Send to right vcc */
-        is_rdesc = 0;
-        dst = lec_h->h_dest;
+       }
+
+       /* Send to right vcc */
+       is_rdesc = 0;
+       dst = lec_h->h_dest;
 #ifdef CONFIG_TR
-        if (priv->is_trdev) {
-                dst = get_tr_dst(skb->data+2, rdesc);
-                if (dst == NULL) {
-                        dst = rdesc;
-                        is_rdesc = 1;
-                }
-        }
+       if (priv->is_trdev) {
+               dst = get_tr_dst(skb->data + 2, rdesc);
+               if (dst == NULL) {
+                       dst = rdesc;
+                       is_rdesc = 1;
+               }
+       }
 #endif
-        entry = NULL;
-        vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
-        DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
-                vcc, vcc?vcc->flags:0, entry);
-        if (!vcc || !test_bit(ATM_VF_READY,&vcc->flags)) {    
-                if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
-                        DPRINTK("%s:lec_start_xmit: queuing packet, ", dev->name);
-                        DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
-                                lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
-                                lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
-                        skb_queue_tail(&entry->tx_wait, skb);
-                } else {
-                        DPRINTK("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name);
-                        DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
-                                lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
-                                lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
-                        priv->stats.tx_dropped++;
-                        dev_kfree_skb(skb);
-                }
-                return 0;
-        }
-                
-#if DUMP_PACKETS > 0                    
-        printk("%s:sending to vpi:%d vci:%d\n", dev->name,
-               vcc->vpi, vcc->vci);       
+       entry = NULL;
+       vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry);
+       DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name,
+               vcc, vcc ? vcc->flags : 0, entry);
+       if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) {
+               if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) {
+                       DPRINTK("%s:lec_start_xmit: queuing packet, ",
+                               dev->name);
+                       DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
+                               lec_h->h_dest[0], lec_h->h_dest[1],
+                               lec_h->h_dest[2], lec_h->h_dest[3],
+                               lec_h->h_dest[4], lec_h->h_dest[5]);
+                       skb_queue_tail(&entry->tx_wait, skb);
+               } else {
+                       DPRINTK
+                           ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ",
+                            dev->name);
+                       DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
+                               lec_h->h_dest[0], lec_h->h_dest[1],
+                               lec_h->h_dest[2], lec_h->h_dest[3],
+                               lec_h->h_dest[4], lec_h->h_dest[5]);
+                       priv->stats.tx_dropped++;
+                       dev_kfree_skb(skb);
+               }
+               goto out;
+       }
+#if DUMP_PACKETS > 0
+       printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci);
 #endif /* DUMP_PACKETS > 0 */
-                
-        while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
-                DPRINTK("lec.c: emptying tx queue, ");
-                DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
-                        lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
-                        lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
+
+       while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) {
+               DPRINTK("lec.c: emptying tx queue, ");
+               DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
+                       lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
                lec_send(vcc, skb2, priv);
-        }
+       }
 
        lec_send(vcc, skb, priv);
 
@@ -404,210 +428,219 @@ lec_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        netif_wake_queue(dev);
        }
 
+out:
+       if (entry)
+               lec_arp_put(entry);
        dev->trans_start = jiffies;
-        return 0;
+       return 0;
 }
 
 /* The inverse routine to net_open(). */
-static int 
-lec_close(struct net_device *dev) 
+static int lec_close(struct net_device *dev)
 {
-        netif_stop_queue(dev);
-        return 0;
+       netif_stop_queue(dev);
+       return 0;
 }
 
 /*
  * Get the current statistics.
  * This may be called with the card open or closed.
  */
-static struct net_device_stats *
-lec_get_stats(struct net_device *dev)
+static struct net_device_stats *lec_get_stats(struct net_device *dev)
 {
-        return &((struct lec_priv *)dev->priv)->stats;
+       return &((struct lec_priv *)dev->priv)->stats;
 }
 
-static int 
-lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
+static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 {
        unsigned long flags;
-        struct net_device *dev = (struct net_device*)vcc->proto_data;
-        struct lec_priv *priv = (struct lec_priv*)dev->priv;
-        struct atmlec_msg *mesg;
-        struct lec_arp_table *entry;
-        int i;
-        char *tmp; /* FIXME */
+       struct net_device *dev = (struct net_device *)vcc->proto_data;
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
+       struct atmlec_msg *mesg;
+       struct lec_arp_table *entry;
+       int i;
+       char *tmp;              /* FIXME */
 
        atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
-        mesg = (struct atmlec_msg *)skb->data;
-        tmp = skb->data;
-        tmp += sizeof(struct atmlec_msg);
-        DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
-        switch(mesg->type) {
-        case l_set_mac_addr:
-                for (i=0;i<6;i++) {
-                        dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
-                }    
-                break;
-        case l_del_mac_addr:
-                for(i=0;i<6;i++) {
-                        dev->dev_addr[i] = 0;
-                }
-                break;
-        case l_addr_delete:
-                lec_addr_delete(priv, mesg->content.normal.atm_addr, 
-                                mesg->content.normal.flag);
-                break;
-        case l_topology_change:
-                priv->topology_change = mesg->content.normal.flag;  
-                break;
-        case l_flush_complete:
-                lec_flush_complete(priv, mesg->content.normal.flag);
-                break;
-        case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
+       mesg = (struct atmlec_msg *)skb->data;
+       tmp = skb->data;
+       tmp += sizeof(struct atmlec_msg);
+       DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type);
+       switch (mesg->type) {
+       case l_set_mac_addr:
+               for (i = 0; i < 6; i++) {
+                       dev->dev_addr[i] = mesg->content.normal.mac_addr[i];
+               }
+               break;
+       case l_del_mac_addr:
+               for (i = 0; i < 6; i++) {
+                       dev->dev_addr[i] = 0;
+               }
+               break;
+       case l_addr_delete:
+               lec_addr_delete(priv, mesg->content.normal.atm_addr,
+                               mesg->content.normal.flag);
+               break;
+       case l_topology_change:
+               priv->topology_change = mesg->content.normal.flag;
+               break;
+       case l_flush_complete:
+               lec_flush_complete(priv, mesg->content.normal.flag);
+               break;
+       case l_narp_req:        /* LANE2: see 7.1.35 in the lane2 spec */
                spin_lock_irqsave(&priv->lec_arp_lock, flags);
-                entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
-                lec_arp_remove(priv, entry);
+               entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
+               lec_arp_remove(priv, entry);
                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
-                if (mesg->content.normal.no_source_le_narp)
-                        break;
-                /* FALL THROUGH */
-        case l_arp_update:
-                lec_arp_update(priv, mesg->content.normal.mac_addr,
-                               mesg->content.normal.atm_addr,
-                               mesg->content.normal.flag,
-                               mesg->content.normal.targetless_le_arp);
-                DPRINTK("lec: in l_arp_update\n");
-                if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */
-                        DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n", mesg->sizeoftlvs);
-                        lane2_associate_ind(dev,
-                                            mesg->content.normal.mac_addr,
-                                            tmp, mesg->sizeoftlvs);
-                }
-                break;
-        case l_config:
-                priv->maximum_unknown_frame_count = 
-                        mesg->content.config.maximum_unknown_frame_count;
-                priv->max_unknown_frame_time = 
-                        (mesg->content.config.max_unknown_frame_time*HZ);
-                priv->max_retry_count = 
-                        mesg->content.config.max_retry_count;
-                priv->aging_time = (mesg->content.config.aging_time*HZ);
-                priv->forward_delay_time = 
-                        (mesg->content.config.forward_delay_time*HZ);
-                priv->arp_response_time = 
-                        (mesg->content.config.arp_response_time*HZ);
-                priv->flush_timeout = (mesg->content.config.flush_timeout*HZ);
-                priv->path_switching_delay = 
-                        (mesg->content.config.path_switching_delay*HZ);
-                priv->lane_version = mesg->content.config.lane_version; /* LANE2 */
+               if (mesg->content.normal.no_source_le_narp)
+                       break;
+               /* FALL THROUGH */
+       case l_arp_update:
+               lec_arp_update(priv, mesg->content.normal.mac_addr,
+                              mesg->content.normal.atm_addr,
+                              mesg->content.normal.flag,
+                              mesg->content.normal.targetless_le_arp);
+               DPRINTK("lec: in l_arp_update\n");
+               if (mesg->sizeoftlvs != 0) {    /* LANE2 3.1.5 */
+                       DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n",
+                               mesg->sizeoftlvs);
+                       lane2_associate_ind(dev, mesg->content.normal.mac_addr,
+                                           tmp, mesg->sizeoftlvs);
+               }
+               break;
+       case l_config:
+               priv->maximum_unknown_frame_count =
+                   mesg->content.config.maximum_unknown_frame_count;
+               priv->max_unknown_frame_time =
+                   (mesg->content.config.max_unknown_frame_time * HZ);
+               priv->max_retry_count = mesg->content.config.max_retry_count;
+               priv->aging_time = (mesg->content.config.aging_time * HZ);
+               priv->forward_delay_time =
+                   (mesg->content.config.forward_delay_time * HZ);
+               priv->arp_response_time =
+                   (mesg->content.config.arp_response_time * HZ);
+               priv->flush_timeout = (mesg->content.config.flush_timeout * HZ);
+               priv->path_switching_delay =
+                   (mesg->content.config.path_switching_delay * HZ);
+               priv->lane_version = mesg->content.config.lane_version; /* LANE2 */
                priv->lane2_ops = NULL;
                if (priv->lane_version > 1)
                        priv->lane2_ops = &lane2_ops;
                if (dev->change_mtu(dev, mesg->content.config.mtu))
                        printk("%s: change_mtu to %d failed\n", dev->name,
-                           mesg->content.config.mtu);
+                              mesg->content.config.mtu);
                priv->is_proxy = mesg->content.config.is_proxy;
-                break;
-        case l_flush_tran_id:
-                lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
-                                      mesg->content.normal.flag);
-                break;
-        case l_set_lecid:
-                priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag);
-                break;
-        case l_should_bridge: {
+               break;
+       case l_flush_tran_id:
+               lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
+                                     mesg->content.normal.flag);
+               break;
+       case l_set_lecid:
+               priv->lecid =
+                   (unsigned short)(0xffff & mesg->content.normal.flag);
+               break;
+       case l_should_bridge:
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-                struct net_bridge_fdb_entry *f;
-
-                DPRINTK("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
-                        dev->name,
-                        mesg->content.proxy.mac_addr[0], mesg->content.proxy.mac_addr[1],
-                        mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3],
-                        mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]);
-
-                if (br_fdb_get_hook == NULL || dev->br_port == NULL)
-                        break;
-
-                f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr);
-                if (f != NULL &&
-                    f->dst->dev != dev &&
-                    f->dst->state == BR_STATE_FORWARDING) {
-                                /* hit from bridge table, send LE_ARP_RESPONSE */
-                        struct sk_buff *skb2;
-                       struct sock *sk;
-
-                        DPRINTK("%s: entry found, responding to zeppelin\n", dev->name);
-                        skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
-                        if (skb2 == NULL) {
-                                br_fdb_put_hook(f);
-                                break;
-                        }
-                        skb2->len = sizeof(struct atmlec_msg);
-                        memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
-                        atm_force_charge(priv->lecd, skb2->truesize);
-                       sk = sk_atm(priv->lecd);
-                        skb_queue_tail(&sk->sk_receive_queue, skb2);
-                        sk->sk_data_ready(sk, skb2->len);
-                }
-                if (f != NULL) br_fdb_put_hook(f);
+               {
+                       struct net_bridge_fdb_entry *f;
+
+                       DPRINTK
+                           ("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
+                            dev->name, mesg->content.proxy.mac_addr[0],
+                            mesg->content.proxy.mac_addr[1],
+                            mesg->content.proxy.mac_addr[2],
+                            mesg->content.proxy.mac_addr[3],
+                            mesg->content.proxy.mac_addr[4],
+                            mesg->content.proxy.mac_addr[5]);
+
+                       if (br_fdb_get_hook == NULL || dev->br_port == NULL)
+                               break;
+
+                       f = br_fdb_get_hook(dev->br_port->br,
+                                           mesg->content.proxy.mac_addr);
+                       if (f != NULL && f->dst->dev != dev
+                           && f->dst->state == BR_STATE_FORWARDING) {
+                               /* hit from bridge table, send LE_ARP_RESPONSE */
+                               struct sk_buff *skb2;
+                               struct sock *sk;
+
+                               DPRINTK
+                                   ("%s: entry found, responding to zeppelin\n",
+                                    dev->name);
+                               skb2 =
+                                   alloc_skb(sizeof(struct atmlec_msg),
+                                             GFP_ATOMIC);
+                               if (skb2 == NULL) {
+                                       br_fdb_put_hook(f);
+                                       break;
+                               }
+                               skb2->len = sizeof(struct atmlec_msg);
+                               memcpy(skb2->data, mesg,
+                                      sizeof(struct atmlec_msg));
+                               atm_force_charge(priv->lecd, skb2->truesize);
+                               sk = sk_atm(priv->lecd);
+                               skb_queue_tail(&sk->sk_receive_queue, skb2);
+                               sk->sk_data_ready(sk, skb2->len);
+                       }
+                       if (f != NULL)
+                               br_fdb_put_hook(f);
+               }
 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
-                }
-                break;
-        default:
-                printk("%s: Unknown message type %d\n", dev->name, mesg->type);
-                dev_kfree_skb(skb);
-                return -EINVAL;
-        }
-        dev_kfree_skb(skb);
-        return 0;
+               break;
+       default:
+               printk("%s: Unknown message type %d\n", dev->name, mesg->type);
+               dev_kfree_skb(skb);
+               return -EINVAL;
+       }
+       dev_kfree_skb(skb);
+       return 0;
 }
 
-static void 
-lec_atm_close(struct atm_vcc *vcc)
+static void lec_atm_close(struct atm_vcc *vcc)
 {
-        struct sk_buff *skb;
-        struct net_device *dev = (struct net_device *)vcc->proto_data;
-        struct lec_priv *priv = (struct lec_priv *)dev->priv;
+       struct sk_buff *skb;
+       struct net_device *dev = (struct net_device *)vcc->proto_data;
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
 
-        priv->lecd = NULL;
-        /* Do something needful? */
+       priv->lecd = NULL;
+       /* Do something needful? */
 
-        netif_stop_queue(dev);
-        lec_arp_destroy(priv);
+       netif_stop_queue(dev);
+       lec_arp_destroy(priv);
 
-        if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
+       if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
                printk("%s lec_atm_close: closing with messages pending\n",
-                       dev->name);
-        while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
-                atm_return(vcc, skb->truesize);
+                      dev->name);
+       while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
+               atm_return(vcc, skb->truesize);
                dev_kfree_skb(skb);
-        }
-  
+       }
+
        printk("%s: Shut down!\n", dev->name);
-        module_put(THIS_MODULE);
+       module_put(THIS_MODULE);
 }
 
 static struct atmdev_ops lecdev_ops = {
-        .close = lec_atm_close,
-        .send  = lec_atm_send
+       .close = lec_atm_close,
+       .send = lec_atm_send
 };
 
 static struct atm_dev lecatm_dev = {
-       .ops    = &lecdev_ops,
-       .type   = "lec",
-       .number = 999,  /* dummy device number */
-       .lock   = SPIN_LOCK_UNLOCKED
+       .ops = &lecdev_ops,
+       .type = "lec",
+       .number = 999,          /* dummy device number */
+       .lock = SPIN_LOCK_UNLOCKED
 };
 
 /*
  * LANE2: new argument struct sk_buff *data contains
  * the LE_ARP based TLVs introduced in the LANE2 spec
  */
-static int 
-send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, 
-             unsigned char *mac_addr, unsigned char *atm_addr,
-             struct sk_buff *data)
+static int
+send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
+            unsigned char *mac_addr, unsigned char *atm_addr,
+            struct sk_buff *data)
 {
        struct sock *sk;
        struct sk_buff *skb;
@@ -621,187 +654,193 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
                return -1;
        skb->len = sizeof(struct atmlec_msg);
        mesg = (struct atmlec_msg *)skb->data;
-        memset(mesg, 0, sizeof(struct atmlec_msg));
+       memset(mesg, 0, sizeof(struct atmlec_msg));
        mesg->type = type;
-        if (data != NULL)
-                mesg->sizeoftlvs = data->len;
+       if (data != NULL)
+               mesg->sizeoftlvs = data->len;
        if (mac_addr)
                memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN);
-        else
-                mesg->content.normal.targetless_le_arp = 1;
+       else
+               mesg->content.normal.targetless_le_arp = 1;
        if (atm_addr)
                memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
 
-        atm_force_charge(priv->lecd, skb->truesize);
+       atm_force_charge(priv->lecd, skb->truesize);
        sk = sk_atm(priv->lecd);
        skb_queue_tail(&sk->sk_receive_queue, skb);
-        sk->sk_data_ready(sk, skb->len);
+       sk->sk_data_ready(sk, skb->len);
 
-        if (data != NULL) {
-                DPRINTK("lec: about to send %d bytes of data\n", data->len);
-                atm_force_charge(priv->lecd, data->truesize);
-                skb_queue_tail(&sk->sk_receive_queue, data);
-                sk->sk_data_ready(sk, skb->len);
-        }
+       if (data != NULL) {
+               DPRINTK("lec: about to send %d bytes of data\n", data->len);
+               atm_force_charge(priv->lecd, data->truesize);
+               skb_queue_tail(&sk->sk_receive_queue, data);
+               sk->sk_data_ready(sk, skb->len);
+       }
 
-        return 0;
+       return 0;
 }
 
 /* shamelessly stolen from drivers/net/net_init.c */
 static int lec_change_mtu(struct net_device *dev, int new_mtu)
 {
-        if ((new_mtu < 68) || (new_mtu > 18190))
-                return -EINVAL;
-        dev->mtu = new_mtu;
-        return 0;
+       if ((new_mtu < 68) || (new_mtu > 18190))
+               return -EINVAL;
+       dev->mtu = new_mtu;
+       return 0;
 }
 
 static void lec_set_multicast_list(struct net_device *dev)
 {
-       /* by default, all multicast frames arrive over the bus.
-         * eventually support selective multicast service
-         */
-        return;
+       /*
+        * by default, all multicast frames arrive over the bus.
+        * eventually support selective multicast service
+        */
+       return;
 }
 
-static void 
-lec_init(struct net_device *dev)
+static void lec_init(struct net_device *dev)
 {
-        dev->change_mtu = lec_change_mtu;
-        dev->open = lec_open;
-        dev->stop = lec_close;
-        dev->hard_start_xmit = lec_start_xmit;
+       dev->change_mtu = lec_change_mtu;
+       dev->open = lec_open;
+       dev->stop = lec_close;
+       dev->hard_start_xmit = lec_start_xmit;
        dev->tx_timeout = lec_tx_timeout;
 
-        dev->get_stats = lec_get_stats;
-        dev->set_multicast_list = lec_set_multicast_list;
-        dev->do_ioctl  = NULL;
-        printk("%s: Initialized!\n",dev->name);
-        return;
+       dev->get_stats = lec_get_stats;
+       dev->set_multicast_list = lec_set_multicast_list;
+       dev->do_ioctl = NULL;
+       printk("%s: Initialized!\n", dev->name);
+       return;
 }
 
 static unsigned char lec_ctrl_magic[] = {
-        0xff,
-        0x00,
-        0x01,
-        0x01 };
+       0xff,
+       0x00,
+       0x01,
+       0x01
+};
 
 #define LEC_DATA_DIRECT_8023  2
 #define LEC_DATA_DIRECT_8025  3
 
 static int lec_is_data_direct(struct atm_vcc *vcc)
-{ 
+{
        return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
                (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
-} 
+}
 
-static void 
-lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
+static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
 {
        unsigned long flags;
-        struct net_device *dev = (struct net_device *)vcc->proto_data;
-        struct lec_priv *priv = (struct lec_priv *)dev->priv; 
+       struct net_device *dev = (struct net_device *)vcc->proto_data;
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
 
 #if DUMP_PACKETS >0
-        int i=0;
-        char buf[300];
+       int i = 0;
+       char buf[300];
 
-        printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
-               vcc->vpi, vcc->vci);
+       printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name,
+              vcc->vpi, vcc->vci);
 #endif
-        if (!skb) {
-                DPRINTK("%s: null skb\n",dev->name);
-                lec_vcc_close(priv, vcc);
-                return;
-        }
+       if (!skb) {
+               DPRINTK("%s: null skb\n", dev->name);
+               lec_vcc_close(priv, vcc);
+               return;
+       }
 #if DUMP_PACKETS > 0
-        printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
-               skb->len, priv->lecid);
+       printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name,
+              skb->len, priv->lecid);
 #if DUMP_PACKETS >= 2
-        for(i=0;i<skb->len && i <99;i++) {
-                sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]);
-        }
+       for (i = 0; i < skb->len && i < 99; i++) {
+               sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
+       }
 #elif DUMP_PACKETS >= 1
-        for(i=0;i<skb->len && i < 30;i++) {
-                sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]);
-        }
+       for (i = 0; i < skb->len && i < 30; i++) {
+               sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
+       }
 #endif /* DUMP_PACKETS >= 1 */
-        if (i==skb->len)
-                printk("%s\n",buf);
-        else
-                printk("%s...\n",buf);
+       if (i == skb->len)
+               printk("%s\n", buf);
+       else
+               printk("%s...\n", buf);
 #endif /* DUMP_PACKETS > 0 */
-        if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
+       if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) {        /* Control frame, to daemon */
                struct sock *sk = sk_atm(vcc);
 
-                DPRINTK("%s: To daemon\n",dev->name);
-                skb_queue_tail(&sk->sk_receive_queue, skb);
-                sk->sk_data_ready(sk, skb->len);
-        } else { /* Data frame, queue to protocol handlers */
+               DPRINTK("%s: To daemon\n", dev->name);
+               skb_queue_tail(&sk->sk_receive_queue, skb);
+               sk->sk_data_ready(sk, skb->len);
+       } else {                /* Data frame, queue to protocol handlers */
                struct lec_arp_table *entry;
-                unsigned char *src, *dst;
-
-                atm_return(vcc,skb->truesize);
-                if (*(uint16_t *)skb->data == htons(priv->lecid) ||
-                    !priv->lecd ||
-                    !(dev->flags & IFF_UP)) { 
-                        /* Probably looping back, or if lecd is missing,
-                           lecd has gone down */
-                        DPRINTK("Ignoring frame...\n");
-                        dev_kfree_skb(skb);
-                        return;
-                }
+               unsigned char *src, *dst;
+
+               atm_return(vcc, skb->truesize);
+               if (*(uint16_t *) skb->data == htons(priv->lecid) ||
+                   !priv->lecd || !(dev->flags & IFF_UP)) {
+                       /*
+                        * Probably looping back, or if lecd is missing,
+                        * lecd has gone down
+                        */
+                       DPRINTK("Ignoring frame...\n");
+                       dev_kfree_skb(skb);
+                       return;
+               }
 #ifdef CONFIG_TR
-                if (priv->is_trdev)
-                       dst = ((struct lecdatahdr_8025 *) skb->data)->h_dest;
-                else
+               if (priv->is_trdev)
+                       dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
+               else
 #endif
-               dst = ((struct lecdatahdr_8023 *) skb->data)->h_dest;
+                       dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
 
-               /* If this is a Data Direct VCC, and the VCC does not match
+               /*
+                * If this is a Data Direct VCC, and the VCC does not match
                 * the LE_ARP cache entry, delete the LE_ARP cache entry.
                 */
                spin_lock_irqsave(&priv->lec_arp_lock, flags);
                if (lec_is_data_direct(vcc)) {
 #ifdef CONFIG_TR
                        if (priv->is_trdev)
-                               src = ((struct lecdatahdr_8025 *) skb->data)->h_source;
+                               src =
+                                   ((struct lecdatahdr_8025 *)skb->data)->
+                                   h_source;
                        else
 #endif
-                       src = ((struct lecdatahdr_8023 *) skb->data)->h_source;
+                               src =
+                                   ((struct lecdatahdr_8023 *)skb->data)->
+                                   h_source;
                        entry = lec_arp_find(priv, src);
                        if (entry && entry->vcc != vcc) {
                                lec_arp_remove(priv, entry);
-                               kfree(entry);
+                               lec_arp_put(entry);
                        }
                }
                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
-                if (!(dst[0]&0x01) &&   /* Never filter Multi/Broadcast */
-                    !priv->is_proxy &&  /* Proxy wants all the packets */
+               if (!(dst[0] & 0x01) && /* Never filter Multi/Broadcast */
+                   !priv->is_proxy &&  /* Proxy wants all the packets */
                    memcmp(dst, dev->dev_addr, dev->addr_len)) {
-                        dev_kfree_skb(skb);
-                        return;
-                }
-                if (priv->lec_arp_empty_ones) {
-                        lec_arp_check_empties(priv, vcc, skb);
-                }
-                skb->dev = dev;
-                skb_pull(skb, 2); /* skip lec_id */
+                       dev_kfree_skb(skb);
+                       return;
+               }
+               if (!hlist_empty(&priv->lec_arp_empty_ones)) {
+                       lec_arp_check_empties(priv, vcc, skb);
+               }
+               skb->dev = dev;
+               skb_pull(skb, 2);       /* skip lec_id */
 #ifdef CONFIG_TR
-                if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
-                else
+               if (priv->is_trdev)
+                       skb->protocol = tr_type_trans(skb, dev);
+               else
 #endif
-                skb->protocol = eth_type_trans(skb, dev);
-                priv->stats.rx_packets++;
-                priv->stats.rx_bytes += skb->len;
-                memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
-                netif_rx(skb);
-        }
+                       skb->protocol = eth_type_trans(skb, dev);
+               priv->stats.rx_packets++;
+               priv->stats.rx_bytes += skb->len;
+               memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
+               netif_rx(skb);
+       }
 }
 
-static void
-lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
+static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
        struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
        struct net_device *dev = skb->dev;
@@ -820,123 +859,121 @@ lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
        }
 }
 
-static int 
-lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
+static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
 {
        struct lec_vcc_priv *vpriv;
-        int bytes_left;
-        struct atmlec_ioc ioc_data;
-
-        /* Lecd must be up in this case */
-        bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
-        if (bytes_left != 0) {
-                printk("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
-                       bytes_left);
-        }
-        if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || 
-            !dev_lec[ioc_data.dev_num])
-                return -EINVAL;
+       int bytes_left;
+       struct atmlec_ioc ioc_data;
+
+       /* Lecd must be up in this case */
+       bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
+       if (bytes_left != 0) {
+               printk
+                   ("lec: lec_vcc_attach, copy from user failed for %d bytes\n",
+                    bytes_left);
+       }
+       if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
+           !dev_lec[ioc_data.dev_num])
+               return -EINVAL;
        if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
                return -ENOMEM;
        vpriv->xoff = 0;
        vpriv->old_pop = vcc->pop;
        vcc->user_back = vpriv;
        vcc->pop = lec_pop;
-        lec_vcc_added(dev_lec[ioc_data.dev_num]->priv, 
-                      &ioc_data, vcc, vcc->push);
-        vcc->proto_data = dev_lec[ioc_data.dev_num];
-        vcc->push = lec_push;
-        return 0;
+       lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
+                     &ioc_data, vcc, vcc->push);
+       vcc->proto_data = dev_lec[ioc_data.dev_num];
+       vcc->push = lec_push;
+       return 0;
 }
 
-static int 
-lec_mcast_attach(struct atm_vcc *vcc, int arg)
+static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
 {
-        if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
-                return -EINVAL;
-        vcc->proto_data = dev_lec[arg];
-        return (lec_mcast_make((struct lec_priv*)dev_lec[arg]->priv, vcc));
+       if (arg < 0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
+               return -EINVAL;
+       vcc->proto_data = dev_lec[arg];
+       return (lec_mcast_make((struct lec_priv *)dev_lec[arg]->priv, vcc));
 }
 
 /* Initialize device. */
-static int 
-lecd_attach(struct atm_vcc *vcc, int arg)
-{  
-        int i;
-        struct lec_priv *priv;
-
-        if (arg<0)
-                i = 0;
-        else
-                i = arg;
+static int lecd_attach(struct atm_vcc *vcc, int arg)
+{
+       int i;
+       struct lec_priv *priv;
+
+       if (arg < 0)
+               i = 0;
+       else
+               i = arg;
 #ifdef CONFIG_TR
-        if (arg >= MAX_LEC_ITF)
-                return -EINVAL;
-#else /* Reserve the top NUM_TR_DEVS for TR */
-        if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS))
-                return -EINVAL;
+       if (arg >= MAX_LEC_ITF)
+               return -EINVAL;
+#else                          /* Reserve the top NUM_TR_DEVS for TR */
+       if (arg >= (MAX_LEC_ITF - NUM_TR_DEVS))
+               return -EINVAL;
 #endif
-        if (!dev_lec[i]) {
-                int is_trdev, size;
+       if (!dev_lec[i]) {
+               int is_trdev, size;
 
-                is_trdev = 0;
-                if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
-                        is_trdev = 1;
+               is_trdev = 0;
+               if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
+                       is_trdev = 1;
 
-                size = sizeof(struct lec_priv);
+               size = sizeof(struct lec_priv);
 #ifdef CONFIG_TR
-                if (is_trdev)
-                        dev_lec[i] = alloc_trdev(size);
-                else
+               if (is_trdev)
+                       dev_lec[i] = alloc_trdev(size);
+               else
 #endif
-                dev_lec[i] = alloc_etherdev(size);
-                if (!dev_lec[i])
-                        return -ENOMEM;
-                snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
-                if (register_netdev(dev_lec[i])) {
-                        free_netdev(dev_lec[i]);
-                        return -EINVAL;
-                }
-
-                priv = dev_lec[i]->priv;
-                priv->is_trdev = is_trdev;
-                lec_init(dev_lec[i]);
-        } else {
-                priv = dev_lec[i]->priv;
-                if (priv->lecd)
-                        return -EADDRINUSE;
-        }
-        lec_arp_init(priv);
-       priv->itfnum = i;  /* LANE2 addition */
-        priv->lecd = vcc;
-        vcc->dev = &lecatm_dev;
-        vcc_insert_socket(sk_atm(vcc));
-        
-        vcc->proto_data = dev_lec[i];
-       set_bit(ATM_VF_META,&vcc->flags);
-       set_bit(ATM_VF_READY,&vcc->flags);
-
-        /* Set default values to these variables */
-        priv->maximum_unknown_frame_count = 1;
-        priv->max_unknown_frame_time = (1*HZ);
-        priv->vcc_timeout_period = (1200*HZ);
-        priv->max_retry_count = 1;
-        priv->aging_time = (300*HZ);
-        priv->forward_delay_time = (15*HZ);
-        priv->topology_change = 0;
-        priv->arp_response_time = (1*HZ);
-        priv->flush_timeout = (4*HZ);
-        priv->path_switching_delay = (6*HZ);
-
-        if (dev_lec[i]->flags & IFF_UP) {
-                netif_start_queue(dev_lec[i]);
-        }
-        __module_get(THIS_MODULE);
-        return i;
+                       dev_lec[i] = alloc_etherdev(size);
+               if (!dev_lec[i])
+                       return -ENOMEM;
+               snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
+               if (register_netdev(dev_lec[i])) {
+                       free_netdev(dev_lec[i]);
+                       return -EINVAL;
+               }
+
+               priv = dev_lec[i]->priv;
+               priv->is_trdev = is_trdev;
+               lec_init(dev_lec[i]);
+       } else {
+               priv = dev_lec[i]->priv;
+               if (priv->lecd)
+                       return -EADDRINUSE;
+       }
+       lec_arp_init(priv);
+       priv->itfnum = i;       /* LANE2 addition */
+       priv->lecd = vcc;
+       vcc->dev = &lecatm_dev;
+       vcc_insert_socket(sk_atm(vcc));
+
+       vcc->proto_data = dev_lec[i];
+       set_bit(ATM_VF_META, &vcc->flags);
+       set_bit(ATM_VF_READY, &vcc->flags);
+
+       /* Set default values to these variables */
+       priv->maximum_unknown_frame_count = 1;
+       priv->max_unknown_frame_time = (1 * HZ);
+       priv->vcc_timeout_period = (1200 * HZ);
+       priv->max_retry_count = 1;
+       priv->aging_time = (300 * HZ);
+       priv->forward_delay_time = (15 * HZ);
+       priv->topology_change = 0;
+       priv->arp_response_time = (1 * HZ);
+       priv->flush_timeout = (4 * HZ);
+       priv->path_switching_delay = (6 * HZ);
+
+       if (dev_lec[i]->flags & IFF_UP) {
+               netif_start_queue(dev_lec[i]);
+       }
+       __module_get(THIS_MODULE);
+       return i;
 }
 
 #ifdef CONFIG_PROC_FS
-static charlec_arp_get_status_string(unsigned char status)
+static char *lec_arp_get_status_string(unsigned char status)
 {
        static char *lec_arp_status_string[] = {
                "ESI_UNKNOWN       ",
@@ -966,52 +1003,54 @@ static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
        if (entry->vcc)
                seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci);
        else
-               seq_printf(seq, "        ");
+               seq_printf(seq, "        ");
        if (entry->recv_vcc) {
                seq_printf(seq, "     %3d %3d", entry->recv_vcc->vpi,
                           entry->recv_vcc->vci);
-        }
-        seq_putc(seq, '\n');
+       }
+       seq_putc(seq, '\n');
 }
 
-
 struct lec_state {
        unsigned long flags;
        struct lec_priv *locked;
-       struct lec_arp_table *entry;
+       struct hlist_node *node;
        struct net_device *dev;
        int itf;
        int arp_table;
        int misc_table;
 };
 
-static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl,
+static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
                          loff_t *l)
 {
-       struct lec_arp_table *e = state->entry;
+       struct hlist_node *e = state->node;
+       struct lec_arp_table *tmp;
 
        if (!e)
-               e = tbl;
+               e = tbl->first;
        if (e == (void *)1) {
-               e = tbl;
+               e = tbl->first;
                --*l;
        }
-       for (; e; e = e->next) {
+
+       hlist_for_each_entry_from(tmp, e, next) {
                if (--*l < 0)
                        break;
        }
-       state->entry = e;
+       state->node = e;
+
        return (*l < 0) ? state : NULL;
 }
 
 static void *lec_arp_walk(struct lec_state *state, loff_t *l,
-                             struct lec_priv *priv)
+                         struct lec_priv *priv)
 {
        void *v = NULL;
        int p;
 
        for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
-               v = lec_tbl_walk(state, priv->lec_arp_tables[p], l);
+               v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
                if (v)
                        break;
        }
@@ -1022,10 +1061,10 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l,
 static void *lec_misc_walk(struct lec_state *state, loff_t *l,
                           struct lec_priv *priv)
 {
-       struct lec_arp_table *lec_misc_tables[] = {
-               priv->lec_arp_empty_ones,
-               priv->lec_no_forward,
-               priv->mcast_fwds
+       struct hlist_head *lec_misc_tables[] = {
+               &priv->lec_arp_empty_ones,
+               &priv->lec_no_forward,
+               &priv->mcast_fwds
        };
        void *v = NULL;
        int q;
@@ -1046,8 +1085,7 @@ static void *lec_priv_walk(struct lec_state *state, loff_t *l,
                state->locked = priv;
                spin_lock_irqsave(&priv->lec_arp_lock, state->flags);
        }
-       if (!lec_arp_walk(state, l, priv) &&
-           !lec_misc_walk(state, l, priv)) {
+       if (!lec_arp_walk(state, l, priv) && !lec_misc_walk(state, l, priv)) {
                spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags);
                state->locked = NULL;
                /* Partial state reset for the next time we get called */
@@ -1081,7 +1119,7 @@ static void *lec_get_idx(struct lec_state *state, loff_t l)
                if (v)
                        break;
        }
-       return v; 
+       return v;
 }
 
 static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
@@ -1093,9 +1131,9 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
        state->locked = NULL;
        state->arp_table = 0;
        state->misc_table = 0;
-       state->entry = (void *)1;
+       state->node = (void *)1;
 
-       return *pos ? lec_get_idx(state, *pos) : (void*)1;
+       return *pos ? lec_get_idx(state, *pos) : (void *)1;
 }
 
 static void lec_seq_stop(struct seq_file *seq, void *v)
@@ -1120,27 +1158,28 @@ static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 static int lec_seq_show(struct seq_file *seq, void *v)
 {
-       static char lec_banner[] = "Itf  MAC          ATM destination" 
-               "                          Status            Flags "
-               "VPI/VCI Recv VPI/VCI\n";
+       static char lec_banner[] = "Itf  MAC          ATM destination"
+           "                          Status            Flags "
+           "VPI/VCI Recv VPI/VCI\n";
 
        if (v == (void *)1)
                seq_puts(seq, lec_banner);
        else {
                struct lec_state *state = seq->private;
-               struct net_device *dev = state->dev; 
+               struct net_device *dev = state->dev;
+               struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next);
 
                seq_printf(seq, "%s ", dev->name);
-               lec_info(seq, state->entry);
+               lec_info(seq, entry);
        }
        return 0;
 }
 
 static struct seq_operations lec_seq_ops = {
-       .start  = lec_seq_start,
-       .next   = lec_seq_next,
-       .stop   = lec_seq_stop,
-       .show   = lec_seq_show,
+       .start = lec_seq_start,
+       .next = lec_seq_next,
+       .stop = lec_seq_stop,
+       .show = lec_seq_show,
 };
 
 static int lec_seq_open(struct inode *inode, struct file *file)
@@ -1174,11 +1213,11 @@ static int lec_seq_release(struct inode *inode, struct file *file)
 }
 
 static struct file_operations lec_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = lec_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = lec_seq_release,
+       .owner = THIS_MODULE,
+       .open = lec_seq_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = lec_seq_release,
 };
 #endif
 
@@ -1186,38 +1225,38 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        struct atm_vcc *vcc = ATM_SD(sock);
        int err = 0;
-       
+
        switch (cmd) {
-               case ATMLEC_CTRL: 
-               case ATMLEC_MCAST:
-               case ATMLEC_DATA:
-                       if (!capable(CAP_NET_ADMIN))
-                               return -EPERM;
-                       break;
-               default:
-                       return -ENOIOCTLCMD;
+       case ATMLEC_CTRL:
+       case ATMLEC_MCAST:
+       case ATMLEC_DATA:
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               break;
+       default:
+               return -ENOIOCTLCMD;
        }
 
        switch (cmd) {
-               case ATMLEC_CTRL:
-                       err = lecd_attach(vcc, (int) arg);
-                       if (err >= 0)
-                               sock->state = SS_CONNECTED;
-                       break;
-               case ATMLEC_MCAST:
-                       err = lec_mcast_attach(vcc, (int) arg);
-                       break;
-               case ATMLEC_DATA:
-                       err = lec_vcc_attach(vcc, (void __user *) arg);
-                       break;
+       case ATMLEC_CTRL:
+               err = lecd_attach(vcc, (int)arg);
+               if (err >= 0)
+                       sock->state = SS_CONNECTED;
+               break;
+       case ATMLEC_MCAST:
+               err = lec_mcast_attach(vcc, (int)arg);
+               break;
+       case ATMLEC_DATA:
+               err = lec_vcc_attach(vcc, (void __user *)arg);
+               break;
        }
 
        return err;
 }
 
 static struct atm_ioctl lane_ioctl_ops = {
-       .owner  = THIS_MODULE,
-       .ioctl  = lane_ioctl,
+       .owner = THIS_MODULE,
+       .ioctl = lane_ioctl,
 };
 
 static int __init lane_module_init(void)
@@ -1231,29 +1270,29 @@ static int __init lane_module_init(void)
 #endif
 
        register_atm_ioctl(&lane_ioctl_ops);
-        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
-        return 0;
+       printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
+       return 0;
 }
 
 static void __exit lane_module_cleanup(void)
 {
-        int i;
-        struct lec_priv *priv;
+       int i;
+       struct lec_priv *priv;
 
        remove_proc_entry("lec", atm_proc_root);
 
        deregister_atm_ioctl(&lane_ioctl_ops);
 
-        for (i = 0; i < MAX_LEC_ITF; i++) {
-                if (dev_lec[i] != NULL) {
-                        priv = (struct lec_priv *)dev_lec[i]->priv;
+       for (i = 0; i < MAX_LEC_ITF; i++) {
+               if (dev_lec[i] != NULL) {
+                       priv = (struct lec_priv *)dev_lec[i]->priv;
                        unregister_netdev(dev_lec[i]);
-                        free_netdev(dev_lec[i]);
-                        dev_lec[i] = NULL;
-                }
-        }
+                       free_netdev(dev_lec[i]);
+                       dev_lec[i] = NULL;
+               }
+       }
 
-        return;                                    
+       return;
 }
 
 module_init(lane_module_init);
@@ -1267,34 +1306,34 @@ module_exit(lane_module_cleanup);
  * If dst_mac == NULL, targetless LE_ARP will be sent
  */
 static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
-    u8 **tlvs, u32 *sizeoftlvs)
+                        u8 **tlvs, u32 *sizeoftlvs)
 {
        unsigned long flags;
-        struct lec_priv *priv = (struct lec_priv *)dev->priv;
-        struct lec_arp_table *table;
-        struct sk_buff *skb;
-        int retval;
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
+       struct lec_arp_table *table;
+       struct sk_buff *skb;
+       int retval;
 
-        if (force == 0) {
+       if (force == 0) {
                spin_lock_irqsave(&priv->lec_arp_lock, flags);
-                table = lec_arp_find(priv, dst_mac);
+               table = lec_arp_find(priv, dst_mac);
                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-                if(table == NULL)
-                        return -1;
-                
-                *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC);
-                if (*tlvs == NULL)
-                        return -1;
-                
-                memcpy(*tlvs, table->tlvs, table->sizeoftlvs);
-                *sizeoftlvs = table->sizeoftlvs;
-                
-                return 0;
-        }
+               if (table == NULL)
+                       return -1;
+
+               *tlvs = kmalloc(table->sizeoftlvs, GFP_ATOMIC);
+               if (*tlvs == NULL)
+                       return -1;
+
+               memcpy(*tlvs, table->tlvs, table->sizeoftlvs);
+               *sizeoftlvs = table->sizeoftlvs;
+
+               return 0;
+       }
 
        if (sizeoftlvs == NULL)
                retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
-               
+
        else {
                skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
                if (skb == NULL)
@@ -1303,9 +1342,8 @@ static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
                memcpy(skb->data, *tlvs, *sizeoftlvs);
                retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, skb);
        }
-        return retval;
-}        
-
+       return retval;
+}
 
 /*
  * LANE2: 3.1.4, LE_ASSOCIATE.request
@@ -1314,80 +1352,85 @@ static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
  * Returns 1 for success, 0 for failure (out of memory)
  *
  */
-static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
-                         u8 *tlvs, u32 sizeoftlvs)
+static int lane2_associate_req(struct net_device *dev, u8 *lan_dst,
+                              u8 *tlvs, u32 sizeoftlvs)
 {
-        int retval;
-        struct sk_buff *skb;
-        struct lec_priv *priv = (struct lec_priv*)dev->priv;
-
-        if (compare_ether_addr(lan_dst, dev->dev_addr))
-                return (0);       /* not our mac address */
-
-        kfree(priv->tlvs); /* NULL if there was no previous association */
-
-        priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
-        if (priv->tlvs == NULL)
-                return (0);
-        priv->sizeoftlvs = sizeoftlvs;
-        memcpy(priv->tlvs, tlvs, sizeoftlvs);
-
-        skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
-        if (skb == NULL)
-                return 0;
-        skb->len = sizeoftlvs;
-        memcpy(skb->data, tlvs, sizeoftlvs);
-        retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
-        if (retval != 0)
-                printk("lec.c: lane2_associate_req() failed\n");
-        /* If the previous association has changed we must
-         * somehow notify other LANE entities about the change
-         */
-        return (1);
+       int retval;
+       struct sk_buff *skb;
+       struct lec_priv *priv = (struct lec_priv *)dev->priv;
+
+       if (compare_ether_addr(lan_dst, dev->dev_addr))
+               return (0);     /* not our mac address */
+
+       kfree(priv->tlvs);      /* NULL if there was no previous association */
+
+       priv->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
+       if (priv->tlvs == NULL)
+               return (0);
+       priv->sizeoftlvs = sizeoftlvs;
+       memcpy(priv->tlvs, tlvs, sizeoftlvs);
+
+       skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
+       if (skb == NULL)
+               return 0;
+       skb->len = sizeoftlvs;
+       memcpy(skb->data, tlvs, sizeoftlvs);
+       retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb);
+       if (retval != 0)
+               printk("lec.c: lane2_associate_req() failed\n");
+       /*
+        * If the previous association has changed we must
+        * somehow notify other LANE entities about the change
+        */
+       return (1);
 }
 
 /*
  * LANE2: 3.1.5, LE_ASSOCIATE.indication
  *
  */
-static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
-    u8 *tlvs, u32 sizeoftlvs)
+static void lane2_associate_ind(struct net_device *dev, u8 *mac_addr,
+                               u8 *tlvs, u32 sizeoftlvs)
 {
 #if 0
-        int i = 0;
+       int i = 0;
 #endif
        struct lec_priv *priv = (struct lec_priv *)dev->priv;
-#if 0 /* Why have the TLVs in LE_ARP entries since we do not use them? When you
-         uncomment this code, make sure the TLVs get freed when entry is killed */
-        struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
+#if 0                          /*
+                                * Why have the TLVs in LE_ARP entries
+                                * since we do not use them? When you
+                                * uncomment this code, make sure the
+                                * TLVs get freed when entry is killed
+                                */
+       struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
 
-        if (entry == NULL)
-                return;     /* should not happen */
+       if (entry == NULL)
+               return;         /* should not happen */
 
-        kfree(entry->tlvs);
+       kfree(entry->tlvs);
 
-        entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
-        if (entry->tlvs == NULL)
-                return;
+       entry->tlvs = kmalloc(sizeoftlvs, GFP_KERNEL);
+       if (entry->tlvs == NULL)
+               return;
 
-        entry->sizeoftlvs = sizeoftlvs;
-        memcpy(entry->tlvs, tlvs, sizeoftlvs);
+       entry->sizeoftlvs = sizeoftlvs;
+       memcpy(entry->tlvs, tlvs, sizeoftlvs);
 #endif
 #if 0
-        printk("lec.c: lane2_associate_ind()\n");
-        printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
-        while (i < sizeoftlvs)
-                printk("%02x ", tlvs[i++]);
-        
-        printk("\n");
+       printk("lec.c: lane2_associate_ind()\n");
+       printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs);
+       while (i < sizeoftlvs)
+               printk("%02x ", tlvs[i++]);
+
+       printk("\n");
 #endif
 
-        /* tell MPOA about the TLVs we saw */
-        if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
-                priv->lane2_ops->associate_indicator(dev, mac_addr,
-                                                     tlvs, sizeoftlvs);
-        }
-        return;
+       /* tell MPOA about the TLVs we saw */
+       if (priv->lane2_ops && priv->lane2_ops->associate_indicator) {
+               priv->lane2_ops->associate_indicator(dev, mac_addr,
+                                                    tlvs, sizeoftlvs);
+       }
+       return;
 }
 
 /*
@@ -1395,7 +1438,6 @@ static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
  *
  * lec_arpc.c was added here when making
  * lane client modular. October 1997
- *
  */
 
 #include <linux/types.h>
@@ -1406,7 +1448,6 @@ static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
 #include <linux/inetdevice.h>
 #include <net/route.h>
 
-
 #if 0
 #define DPRINTK(format,args...)
 /*
@@ -1417,7 +1458,7 @@ static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
 
 #define LEC_ARP_REFRESH_INTERVAL (3*HZ)
 
-static void lec_arp_check_expire(unsigned long data);
+static void lec_arp_check_expire(void *data);
 static void lec_arp_expire_arp(unsigned long data);
 
 /* 
@@ -1429,474 +1470,397 @@ static void lec_arp_expire_arp(unsigned long data);
 /*
  * Initialization of arp-cache
  */
-static void 
-lec_arp_init(struct lec_priv *priv)
+static void lec_arp_init(struct lec_priv *priv)
 {
-        unsigned short i;
+       unsigned short i;
 
-        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-                priv->lec_arp_tables[i] = NULL;
-        }        
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
+       }
+        INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
+        INIT_HLIST_HEAD(&priv->lec_no_forward);
+        INIT_HLIST_HEAD(&priv->mcast_fwds);
        spin_lock_init(&priv->lec_arp_lock);
-        init_timer(&priv->lec_arp_timer);
-        priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
-        priv->lec_arp_timer.data = (unsigned long)priv;
-        priv->lec_arp_timer.function = lec_arp_check_expire;
-        add_timer(&priv->lec_arp_timer);
+       INIT_WORK(&priv->lec_arp_work, lec_arp_check_expire, priv);
+       schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
 }
 
-static void
-lec_arp_clear_vccs(struct lec_arp_table *entry)
+static void lec_arp_clear_vccs(struct lec_arp_table *entry)
 {
-        if (entry->vcc) {
+       if (entry->vcc) {
                struct atm_vcc *vcc = entry->vcc;
                struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
-               struct net_device *dev = (struct net_device*) vcc->proto_data;
+               struct net_device *dev = (struct net_device *)vcc->proto_data;
 
-                vcc->pop = vpriv->old_pop;
+               vcc->pop = vpriv->old_pop;
                if (vpriv->xoff)
                        netif_wake_queue(dev);
                kfree(vpriv);
                vcc->user_back = NULL;
-                vcc->push = entry->old_push;
+               vcc->push = entry->old_push;
                vcc_release_async(vcc, -EPIPE);
-                vcc = NULL;
-        }
-        if (entry->recv_vcc) {
-                entry->recv_vcc->push = entry->old_recv_push;
+               entry->vcc = NULL;
+       }
+       if (entry->recv_vcc) {
+               entry->recv_vcc->push = entry->old_recv_push;
                vcc_release_async(entry->recv_vcc, -EPIPE);
-                entry->recv_vcc = NULL;
-        }        
+               entry->recv_vcc = NULL;
+       }
 }
 
 /*
  * Insert entry to lec_arp_table
  * LANE2: Add to the end of the list to satisfy 8.1.13
  */
-static inline void 
-lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
+static inline void
+lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
 {
-        unsigned short place;
-        struct lec_arp_table *tmp;
-
-        place = HASH(to_add->mac_addr[ETH_ALEN-1]);
-        tmp = priv->lec_arp_tables[place];
-        to_add->next = NULL;
-        if (tmp == NULL)
-                priv->lec_arp_tables[place] = to_add;
-  
-        else {  /* add to the end */
-                while (tmp->next)
-                        tmp = tmp->next;
-                tmp->next = to_add;
-        }
-
-        DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-                0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1],
-                0xff&to_add->mac_addr[2], 0xff&to_add->mac_addr[3],
-                0xff&to_add->mac_addr[4], 0xff&to_add->mac_addr[5]);
+       struct hlist_head *tmp;
+
+       tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
+       hlist_add_head(&entry->next, tmp);
+
+       DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+               0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1],
+               0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3],
+               0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]);
 }
 
 /*
  * Remove entry from lec_arp_table
  */
-static int 
-lec_arp_remove(struct lec_priv *priv,
-               struct lec_arp_table *to_remove)
+static int
+lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
 {
-        unsigned short place;
-        struct lec_arp_table *tmp;
-        int remove_vcc=1;
-
-        if (!to_remove) {
-                return -1;
-        }
-        place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
-        tmp = priv->lec_arp_tables[place];
-        if (tmp == to_remove) {
-                priv->lec_arp_tables[place] = tmp->next;
-        } else {
-                while(tmp && tmp->next != to_remove) {
-                        tmp = tmp->next;
-                }
-                if (!tmp) {/* Entry was not found */
-                        return -1;
-                }
-        }
-        tmp->next = to_remove->next;
-        del_timer(&to_remove->timer);
-  
-        /* If this is the only MAC connected to this VCC, also tear down
-           the VCC */
-        if (to_remove->status >= ESI_FLUSH_PENDING) {
-                /*
-                 * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
-                 */
-                for(place = 0; place < LEC_ARP_TABLE_SIZE; place++) {
-                        for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) {
-                                if (memcmp(tmp->atm_addr, to_remove->atm_addr,
-                                           ATM_ESA_LEN)==0) {
-                                        remove_vcc=0;
-                                        break;
-                                }
-                        }
-                }
-                if (remove_vcc)
-                        lec_arp_clear_vccs(to_remove);
-        }
-        skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
-
-        DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-                0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
-                0xff&to_remove->mac_addr[2], 0xff&to_remove->mac_addr[3],
-                0xff&to_remove->mac_addr[4], 0xff&to_remove->mac_addr[5]);
-        return 0;
+       struct hlist_node *node;
+       struct lec_arp_table *entry;
+       int i, remove_vcc = 1;
+
+       if (!to_remove) {
+               return -1;
+       }
+
+       hlist_del(&to_remove->next);
+       del_timer(&to_remove->timer);
+
+       /* If this is the only MAC connected to this VCC, also tear down the VCC */
+       if (to_remove->status >= ESI_FLUSH_PENDING) {
+               /*
+                * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
+                */
+               for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+                       hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
+                               if (memcmp(to_remove->atm_addr,
+                                          entry->atm_addr, ATM_ESA_LEN) == 0) {
+                                       remove_vcc = 0;
+                                       break;
+                               }
+                       }
+               }
+               if (remove_vcc)
+                       lec_arp_clear_vccs(to_remove);
+       }
+       skb_queue_purge(&to_remove->tx_wait);   /* FIXME: good place for this? */
+
+       DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+               0xff & to_remove->mac_addr[0], 0xff & to_remove->mac_addr[1],
+               0xff & to_remove->mac_addr[2], 0xff & to_remove->mac_addr[3],
+               0xff & to_remove->mac_addr[4], 0xff & to_remove->mac_addr[5]);
+       return 0;
 }
 
 #if DEBUG_ARP_TABLE
-static char*
-get_status_string(unsigned char st)
+static char *get_status_string(unsigned char st)
 {
-        switch(st) {
-        case ESI_UNKNOWN:
-                return "ESI_UNKNOWN";
-        case ESI_ARP_PENDING:
-                return "ESI_ARP_PENDING";
-        case ESI_VC_PENDING:
-                return "ESI_VC_PENDING";
-        case ESI_FLUSH_PENDING:
-                return "ESI_FLUSH_PENDING";
-        case ESI_FORWARD_DIRECT:
-                return "ESI_FORWARD_DIRECT";
-        default:
-                return "<UNKNOWN>";
-        }
+       switch (st) {
+       case ESI_UNKNOWN:
+               return "ESI_UNKNOWN";
+       case ESI_ARP_PENDING:
+               return "ESI_ARP_PENDING";
+       case ESI_VC_PENDING:
+               return "ESI_VC_PENDING";
+       case ESI_FLUSH_PENDING:
+               return "ESI_FLUSH_PENDING";
+       case ESI_FORWARD_DIRECT:
+               return "ESI_FORWARD_DIRECT";
+       default:
+               return "<UNKNOWN>";
+       }
 }
-#endif
 
-static void
-dump_arp_table(struct lec_priv *priv)
+static void dump_arp_table(struct lec_priv *priv)
 {
-#if DEBUG_ARP_TABLE
-        int i,j, offset;
-        struct lec_arp_table *rulla;
-        char buf[1024];
-        struct lec_arp_table **lec_arp_tables =
-                (struct lec_arp_table **)priv->lec_arp_tables;
-        struct lec_arp_table *lec_arp_empty_ones =
-                (struct lec_arp_table *)priv->lec_arp_empty_ones;
-        struct lec_arp_table *lec_no_forward =
-                (struct lec_arp_table *)priv->lec_no_forward;
-        struct lec_arp_table *mcast_fwds = priv->mcast_fwds;
-
-
-        printk("Dump %p:\n",priv);
-        for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-                rulla = lec_arp_tables[i];
-                offset = 0;
-                offset += sprintf(buf,"%d: %p\n",i, rulla);
-                while (rulla) {
-                        offset += sprintf(buf+offset,"Mac:");
-                        for(j=0;j<ETH_ALEN;j++) {
-                                offset+=sprintf(buf+offset,
-                                                "%2.2x ",
-                                                rulla->mac_addr[j]&0xff);
-                        }
-                        offset +=sprintf(buf+offset,"Atm:");
-                        for(j=0;j<ATM_ESA_LEN;j++) {
-                                offset+=sprintf(buf+offset,
-                                                "%2.2x ",
-                                                rulla->atm_addr[j]&0xff);
-                        }      
-                        offset+=sprintf(buf+offset,
-                                        "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
-                                        rulla->vcc?rulla->vcc->vpi:0, 
-                                        rulla->vcc?rulla->vcc->vci:0,
-                                        rulla->recv_vcc?rulla->recv_vcc->vpi:0,
-                                        rulla->recv_vcc?rulla->recv_vcc->vci:0,
-                                        rulla->last_used,
-                                        rulla->timestamp, rulla->no_tries);
-                        offset+=sprintf(buf+offset,
-                                        "Flags:%x, Packets_flooded:%x, Status: %s ",
-                                        rulla->flags, rulla->packets_flooded, 
-                                        get_status_string(rulla->status));
-                        offset+=sprintf(buf+offset,"->%p\n",rulla->next);
-                        rulla = rulla->next;
-                }
-                printk("%s",buf);
-        }
-        rulla = lec_no_forward;
-        if (rulla)
-                printk("No forward\n");  
-        while(rulla) {
-                offset=0;
-                offset += sprintf(buf+offset,"Mac:");
-                for(j=0;j<ETH_ALEN;j++) {
-                        offset+=sprintf(buf+offset,"%2.2x ",
-                                        rulla->mac_addr[j]&0xff);
-                }
-                offset +=sprintf(buf+offset,"Atm:");
-                for(j=0;j<ATM_ESA_LEN;j++) {
-                        offset+=sprintf(buf+offset,"%2.2x ",
-                                        rulla->atm_addr[j]&0xff);
-                }      
-                offset+=sprintf(buf+offset,
-                                "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
-                                rulla->vcc?rulla->vcc->vpi:0, 
-                                rulla->vcc?rulla->vcc->vci:0, 
-                                rulla->recv_vcc?rulla->recv_vcc->vpi:0,
-                                rulla->recv_vcc?rulla->recv_vcc->vci:0,
-                                rulla->last_used, 
-                                rulla->timestamp, rulla->no_tries);
-                offset+=sprintf(buf+offset,
-                                "Flags:%x, Packets_flooded:%x, Status: %s ",
-                                rulla->flags, rulla->packets_flooded, 
-                                get_status_string(rulla->status));
-                offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
-                rulla = rulla->next;
-                printk("%s",buf);
-        }
-        rulla = lec_arp_empty_ones;
-        if (rulla)
-                printk("Empty ones\n");  
-        while(rulla) {
-                offset=0;
-                offset += sprintf(buf+offset,"Mac:");
-                for(j=0;j<ETH_ALEN;j++) {
-                        offset+=sprintf(buf+offset,"%2.2x ",
-                                        rulla->mac_addr[j]&0xff);
-                }
-                offset +=sprintf(buf+offset,"Atm:");
-                for(j=0;j<ATM_ESA_LEN;j++) {
-                        offset+=sprintf(buf+offset,"%2.2x ",
-                                        rulla->atm_addr[j]&0xff);
-                }      
-                offset+=sprintf(buf+offset,
-                                "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
-                                rulla->vcc?rulla->vcc->vpi:0, 
-                                rulla->vcc?rulla->vcc->vci:0, 
-                                rulla->recv_vcc?rulla->recv_vcc->vpi:0,
-                                rulla->recv_vcc?rulla->recv_vcc->vci:0,
-                                rulla->last_used, 
-                                rulla->timestamp, rulla->no_tries);
-                offset+=sprintf(buf+offset,
-                                "Flags:%x, Packets_flooded:%x, Status: %s ",
-                                rulla->flags, rulla->packets_flooded, 
-                                get_status_string(rulla->status));
-                offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
-                rulla = rulla->next;
-                printk("%s",buf);
-        }
-
-        rulla = mcast_fwds;
-        if (rulla)
-                printk("Multicast Forward VCCs\n");  
-        while(rulla) {
-                offset=0;
-                offset += sprintf(buf+offset,"Mac:");
-                for(j=0;j<ETH_ALEN;j++) {
-                        offset+=sprintf(buf+offset,"%2.2x ",
-                                        rulla->mac_addr[j]&0xff);
-                }
-                offset +=sprintf(buf+offset,"Atm:");
-                for(j=0;j<ATM_ESA_LEN;j++) {
-                        offset+=sprintf(buf+offset,"%2.2x ",
-                                        rulla->atm_addr[j]&0xff);
-                }      
-                offset+=sprintf(buf+offset,
-                                "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
-                                rulla->vcc?rulla->vcc->vpi:0, 
-                                rulla->vcc?rulla->vcc->vci:0, 
-                                rulla->recv_vcc?rulla->recv_vcc->vpi:0,
-                                rulla->recv_vcc?rulla->recv_vcc->vci:0,
-                                rulla->last_used, 
-                                rulla->timestamp, rulla->no_tries);
-                offset+=sprintf(buf+offset,
-                                "Flags:%x, Packets_flooded:%x, Status: %s ",
-                                rulla->flags, rulla->packets_flooded, 
-                                get_status_string(rulla->status));
-                offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next);
-                rulla = rulla->next;
-                printk("%s",buf);
-        }
+       struct hlist_node *node;
+       struct lec_arp_table *rulla;
+       char buf[256];
+       int i, j, offset;
+
+       printk("Dump %p:\n", priv);
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) {
+                       offset = 0;
+                       offset += sprintf(buf, "%d: %p\n", i, rulla);
+                       offset += sprintf(buf + offset, "Mac:");
+                       for (j = 0; j < ETH_ALEN; j++) {
+                               offset += sprintf(buf + offset,
+                                                 "%2.2x ",
+                                                 rulla->mac_addr[j] & 0xff);
+                       }
+                       offset += sprintf(buf + offset, "Atm:");
+                       for (j = 0; j < ATM_ESA_LEN; j++) {
+                               offset += sprintf(buf + offset,
+                                                 "%2.2x ",
+                                                 rulla->atm_addr[j] & 0xff);
+                       }
+                       offset += sprintf(buf + offset,
+                                         "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
+                                         rulla->vcc ? rulla->vcc->vpi : 0,
+                                         rulla->vcc ? rulla->vcc->vci : 0,
+                                         rulla->recv_vcc ? rulla->recv_vcc->
+                                         vpi : 0,
+                                         rulla->recv_vcc ? rulla->recv_vcc->
+                                         vci : 0, rulla->last_used,
+                                         rulla->timestamp, rulla->no_tries);
+                       offset +=
+                           sprintf(buf + offset,
+                                   "Flags:%x, Packets_flooded:%x, Status: %s ",
+                                   rulla->flags, rulla->packets_flooded,
+                                   get_status_string(rulla->status));
+                       printk("%s\n", buf);
+               }
+       }
+
+       if (!hlist_empty(&priv->lec_no_forward))
+               printk("No forward\n");
+       hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
+               offset = 0;
+               offset += sprintf(buf + offset, "Mac:");
+               for (j = 0; j < ETH_ALEN; j++) {
+                       offset += sprintf(buf + offset, "%2.2x ",
+                                         rulla->mac_addr[j] & 0xff);
+               }
+               offset += sprintf(buf + offset, "Atm:");
+               for (j = 0; j < ATM_ESA_LEN; j++) {
+                       offset += sprintf(buf + offset, "%2.2x ",
+                                         rulla->atm_addr[j] & 0xff);
+               }
+               offset += sprintf(buf + offset,
+                                 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
+                                 rulla->vcc ? rulla->vcc->vpi : 0,
+                                 rulla->vcc ? rulla->vcc->vci : 0,
+                                 rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
+                                 rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
+                                 rulla->last_used,
+                                 rulla->timestamp, rulla->no_tries);
+               offset += sprintf(buf + offset,
+                                 "Flags:%x, Packets_flooded:%x, Status: %s ",
+                                 rulla->flags, rulla->packets_flooded,
+                                 get_status_string(rulla->status));
+               printk("%s\n", buf);
+       }
+
+       if (!hlist_empty(&priv->lec_arp_empty_ones))
+               printk("Empty ones\n");
+       hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
+               offset = 0;
+               offset += sprintf(buf + offset, "Mac:");
+               for (j = 0; j < ETH_ALEN; j++) {
+                       offset += sprintf(buf + offset, "%2.2x ",
+                                         rulla->mac_addr[j] & 0xff);
+               }
+               offset += sprintf(buf + offset, "Atm:");
+               for (j = 0; j < ATM_ESA_LEN; j++) {
+                       offset += sprintf(buf + offset, "%2.2x ",
+                                         rulla->atm_addr[j] & 0xff);
+               }
+               offset += sprintf(buf + offset,
+                                 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
+                                 rulla->vcc ? rulla->vcc->vpi : 0,
+                                 rulla->vcc ? rulla->vcc->vci : 0,
+                                 rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
+                                 rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
+                                 rulla->last_used,
+                                 rulla->timestamp, rulla->no_tries);
+               offset += sprintf(buf + offset,
+                                 "Flags:%x, Packets_flooded:%x, Status: %s ",
+                                 rulla->flags, rulla->packets_flooded,
+                                 get_status_string(rulla->status));
+               printk("%s", buf);
+       }
+
+       if (!hlist_empty(&priv->mcast_fwds))
+               printk("Multicast Forward VCCs\n");
+       hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
+               offset = 0;
+               offset += sprintf(buf + offset, "Mac:");
+               for (j = 0; j < ETH_ALEN; j++) {
+                       offset += sprintf(buf + offset, "%2.2x ",
+                                         rulla->mac_addr[j] & 0xff);
+               }
+               offset += sprintf(buf + offset, "Atm:");
+               for (j = 0; j < ATM_ESA_LEN; j++) {
+                       offset += sprintf(buf + offset, "%2.2x ",
+                                         rulla->atm_addr[j] & 0xff);
+               }
+               offset += sprintf(buf + offset,
+                                 "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ",
+                                 rulla->vcc ? rulla->vcc->vpi : 0,
+                                 rulla->vcc ? rulla->vcc->vci : 0,
+                                 rulla->recv_vcc ? rulla->recv_vcc->vpi : 0,
+                                 rulla->recv_vcc ? rulla->recv_vcc->vci : 0,
+                                 rulla->last_used,
+                                 rulla->timestamp, rulla->no_tries);
+               offset += sprintf(buf + offset,
+                                 "Flags:%x, Packets_flooded:%x, Status: %s ",
+                                 rulla->flags, rulla->packets_flooded,
+                                 get_status_string(rulla->status));
+               printk("%s\n", buf);
+       }
 
-#endif
 }
+#else
+#define dump_arp_table(priv) do { } while (0)
+#endif
 
 /*
  * Destruction of arp-cache
  */
-static void
-lec_arp_destroy(struct lec_priv *priv)
+static void lec_arp_destroy(struct lec_priv *priv)
 {
        unsigned long flags;
-        struct lec_arp_table *entry, *next;
-        int i;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
+       int i;
+
+       cancel_rearming_delayed_work(&priv->lec_arp_work);
 
-        del_timer_sync(&priv->lec_arp_timer);
-        
-        /*
-         * Remove all entries
-         */
+       /*
+        * Remove all entries
+        */
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-                for(entry = priv->lec_arp_tables[i]; entry != NULL; entry=next) {
-                        next = entry->next;
-                        lec_arp_remove(priv, entry);
-                        kfree(entry);
-                }
-        }
-        entry = priv->lec_arp_empty_ones;
-        while(entry) {
-                next = entry->next;
-                del_timer_sync(&entry->timer);
-                lec_arp_clear_vccs(entry);
-                kfree(entry);
-                entry = next;
-        }
-        priv->lec_arp_empty_ones = NULL;
-        entry = priv->lec_no_forward;
-        while(entry) {
-                next = entry->next;
-                del_timer_sync(&entry->timer);
-                lec_arp_clear_vccs(entry);
-                kfree(entry);
-                entry = next;
-        }
-        priv->lec_no_forward = NULL;
-        entry = priv->mcast_fwds;
-        while(entry) {
-                next = entry->next;
-                /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
-                lec_arp_clear_vccs(entry);
-                kfree(entry);
-                entry = next;
-        }
-        priv->mcast_fwds = NULL;
-        priv->mcast_vcc = NULL;
-        memset(priv->lec_arp_tables, 0, 
-               sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE);
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
+                       lec_arp_remove(priv, entry);
+                       lec_arp_put(entry);
+               }
+               INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
+       }
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+               del_timer_sync(&entry->timer);
+               lec_arp_clear_vccs(entry);
+               hlist_del(&entry->next);
+               lec_arp_put(entry);
+       }
+       INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
+               del_timer_sync(&entry->timer);
+               lec_arp_clear_vccs(entry);
+               hlist_del(&entry->next);
+               lec_arp_put(entry);
+       }
+       INIT_HLIST_HEAD(&priv->lec_no_forward);
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
+               /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
+               lec_arp_clear_vccs(entry);
+               hlist_del(&entry->next);
+               lec_arp_put(entry);
+       }
+       INIT_HLIST_HEAD(&priv->mcast_fwds);
+       priv->mcast_vcc = NULL;
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
 
-
 /* 
  * Find entry by mac_address
  */
-static struct lec_arp_table*
-lec_arp_find(struct lec_priv *priv,
-             unsigned char *mac_addr)
+static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
+                                         unsigned char *mac_addr)
 {
-        unsigned short place;
-        struct lec_arp_table *to_return;
-
-        DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
-                mac_addr[0]&0xff, mac_addr[1]&0xff, mac_addr[2]&0xff, 
-                mac_addr[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff);
-        place = HASH(mac_addr[ETH_ALEN-1]);
-  
-        to_return = priv->lec_arp_tables[place];
-        while(to_return) {
-                if (!compare_ether_addr(mac_addr, to_return->mac_addr)) {
-                        return to_return;
-                }
-                to_return = to_return->next;
-        }
-        return NULL;
+       struct hlist_node *node;
+       struct hlist_head *head;
+       struct lec_arp_table *entry;
+
+       DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+               mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff,
+               mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff);
+
+       head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
+       hlist_for_each_entry(entry, node, head, next) {
+               if (!compare_ether_addr(mac_addr, entry->mac_addr)) {
+                       return entry;
+               }
+       }
+       return NULL;
 }
 
-static struct lec_arp_table*
-make_entry(struct lec_priv *priv, unsigned char *mac_addr)
+static struct lec_arp_table *make_entry(struct lec_priv *priv,
+                                       unsigned char *mac_addr)
 {
-        struct lec_arp_table *to_return;
-
-        to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
-        if (!to_return) {
-                printk("LEC: Arp entry kmalloc failed\n");
-                return NULL;
-        }
-        memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
-        init_timer(&to_return->timer);
-        to_return->timer.function = lec_arp_expire_arp;
-        to_return->timer.data = (unsigned long) to_return;
-        to_return->last_used = jiffies;
-        to_return->priv = priv;
-        skb_queue_head_init(&to_return->tx_wait);
-        return to_return;
+       struct lec_arp_table *to_return;
+
+       to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
+       if (!to_return) {
+               printk("LEC: Arp entry kmalloc failed\n");
+               return NULL;
+       }
+       memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
+       INIT_HLIST_NODE(&to_return->next);
+       init_timer(&to_return->timer);
+       to_return->timer.function = lec_arp_expire_arp;
+       to_return->timer.data = (unsigned long)to_return;
+       to_return->last_used = jiffies;
+       to_return->priv = priv;
+       skb_queue_head_init(&to_return->tx_wait);
+       atomic_set(&to_return->usage, 1);
+       return to_return;
 }
 
-/*
- *
- * Arp sent timer expired
- *
- */
-static void
-lec_arp_expire_arp(unsigned long data)
+/* Arp sent timer expired */
+static void lec_arp_expire_arp(unsigned long data)
 {
-        struct lec_arp_table *entry;
-
-        entry = (struct lec_arp_table *)data;
-
-        DPRINTK("lec_arp_expire_arp\n");
-        if (entry->status == ESI_ARP_PENDING) {
-                if (entry->no_tries <= entry->priv->max_retry_count) {
-                        if (entry->is_rdesc)
-                                send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL);
-                        else
-                                send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
-                        entry->no_tries++;
-                }
-                mod_timer(&entry->timer, jiffies + (1*HZ));
-        }
+       struct lec_arp_table *entry;
+
+       entry = (struct lec_arp_table *)data;
+
+       DPRINTK("lec_arp_expire_arp\n");
+       if (entry->status == ESI_ARP_PENDING) {
+               if (entry->no_tries <= entry->priv->max_retry_count) {
+                       if (entry->is_rdesc)
+                               send_to_lecd(entry->priv, l_rdesc_arp_xmt,
+                                            entry->mac_addr, NULL, NULL);
+                       else
+                               send_to_lecd(entry->priv, l_arp_xmt,
+                                            entry->mac_addr, NULL, NULL);
+                       entry->no_tries++;
+               }
+               mod_timer(&entry->timer, jiffies + (1 * HZ));
+       }
 }
 
-/*
- *
- * Unknown/unused vcc expire, remove associated entry
- *
- */
-static void
-lec_arp_expire_vcc(unsigned long data)
+/* Unknown/unused vcc expire, remove associated entry */
+static void lec_arp_expire_vcc(unsigned long data)
 {
        unsigned long flags;
-        struct lec_arp_table *to_remove = (struct lec_arp_table*)data;
-        struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
-        struct lec_arp_table *entry = NULL;
+       struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
+       struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
 
-        del_timer(&to_remove->timer);
+       del_timer(&to_remove->timer);
 
-        DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
-                to_remove, priv, 
-                to_remove->vcc?to_remove->recv_vcc->vpi:0,
-                to_remove->vcc?to_remove->recv_vcc->vci:0);
-        DPRINTK("eo:%p nf:%p\n",priv->lec_arp_empty_ones,priv->lec_no_forward);
+       DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n",
+               to_remove, priv,
+               to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
+               to_remove->vcc ? to_remove->recv_vcc->vci : 0);
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        if (to_remove == priv->lec_arp_empty_ones)
-                priv->lec_arp_empty_ones = to_remove->next;
-        else {
-                entry = priv->lec_arp_empty_ones;
-                while (entry && entry->next != to_remove)
-                        entry = entry->next;
-                if (entry)
-                        entry->next = to_remove->next;
-        }
-        if (!entry) {
-                if (to_remove == priv->lec_no_forward) {
-                        priv->lec_no_forward = to_remove->next;
-                } else {
-                        entry = priv->lec_no_forward;
-                        while (entry && entry->next != to_remove)
-                                entry = entry->next;
-                        if (entry)
-                                entry->next = to_remove->next;
-                }
-       }
+       hlist_del(&to_remove->next);
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
-        lec_arp_clear_vccs(to_remove);
-        kfree(to_remove);
+       lec_arp_clear_vccs(to_remove);
+       lec_arp_put(to_remove);
 }
 
 /*
@@ -1915,158 +1879,171 @@ lec_arp_expire_vcc(unsigned long data)
  *       to ESI_FORWARD_DIRECT. This causes the flush period to end
  *       regardless of the progress of the flush protocol.
  */
-static void
-lec_arp_check_expire(unsigned long data)
+static void lec_arp_check_expire(void *data)
 {
        unsigned long flags;
-        struct lec_priv *priv = (struct lec_priv *)data;
-        struct lec_arp_table *entry, *next;
-        unsigned long now;
-        unsigned long time_to_check;
-        int i;
-
-        DPRINTK("lec_arp_check_expire %p\n",priv);
-        DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
-                priv->lec_no_forward);
+       struct lec_priv *priv = data;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
+       unsigned long now;
+       unsigned long time_to_check;
+       int i;
+
+       DPRINTK("lec_arp_check_expire %p\n", priv);
        now = jiffies;
+restart:
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-       for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-               for(entry = priv->lec_arp_tables[i]; entry != NULL; ) {
-                       if ((entry->flags) & LEC_REMOTE_FLAG && 
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
+                       if ((entry->flags) & LEC_REMOTE_FLAG &&
                            priv->topology_change)
                                time_to_check = priv->forward_delay_time;
                        else
                                time_to_check = priv->aging_time;
 
                        DPRINTK("About to expire: %lx - %lx > %lx\n",
-                               now,entry->last_used, time_to_check);
-                       if( time_after(now, entry->last_used+
-                          time_to_check) && 
-                           !(entry->flags & LEC_PERMANENT_FLAG) &&
-                           !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */
+                               now, entry->last_used, time_to_check);
+                       if (time_after(now, entry->last_used + time_to_check)
+                           && !(entry->flags & LEC_PERMANENT_FLAG)
+                           && !(entry->mac_addr[0] & 0x01)) {  /* LANE2: 7.1.20 */
                                /* Remove entry */
                                DPRINTK("LEC:Entry timed out\n");
-                               next = entry->next;      
                                lec_arp_remove(priv, entry);
-                               kfree(entry);
-                               entry = next;
+                               lec_arp_put(entry);
                        } else {
                                /* Something else */
                                if ((entry->status == ESI_VC_PENDING ||
-                                    entry->status == ESI_ARP_PENDING) 
+                                    entry->status == ESI_ARP_PENDING)
                                    && time_after_eq(now,
-                                   entry->timestamp +
-                                   priv->max_unknown_frame_time)) {
+                                                    entry->timestamp +
+                                                    priv->
+                                                    max_unknown_frame_time)) {
                                        entry->timestamp = jiffies;
                                        entry->packets_flooded = 0;
                                        if (entry->status == ESI_VC_PENDING)
-                                               send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL);
+                                               send_to_lecd(priv, l_svc_setup,
+                                                            entry->mac_addr,
+                                                            entry->atm_addr,
+                                                            NULL);
                                }
-                               if (entry->status == ESI_FLUSH_PENDING 
-                                  &&
-                                  time_after_eq(now, entry->timestamp+
-                                  priv->path_switching_delay)) {
+                               if (entry->status == ESI_FLUSH_PENDING
+                                   &&
+                                   time_after_eq(now, entry->timestamp +
+                                                 priv->path_switching_delay)) {
                                        struct sk_buff *skb;
+                                       struct atm_vcc *vcc = entry->vcc;
 
+                                       lec_arp_hold(entry);
+                                       spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                                        while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
-                                               lec_send(entry->vcc, skb, entry->priv);
+                                               lec_send(vcc, skb, entry->priv);
                                        entry->last_used = jiffies;
-                                       entry->status = 
-                                               ESI_FORWARD_DIRECT;
+                                       entry->status = ESI_FORWARD_DIRECT;
+                                       lec_arp_put(entry);
+                                       goto restart;
                                }
-                               entry = entry->next;
                        }
                }
        }
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
-        mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
+       schedule_delayed_work(&priv->lec_arp_work, LEC_ARP_REFRESH_INTERVAL);
 }
+
 /*
  * Try to find vcc where mac_address is attached.
  * 
  */
-static struct atm_vcc*
-lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
-               int is_rdesc, struct lec_arp_table **ret_entry)
+static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
+                                      unsigned char *mac_to_find, int is_rdesc,
+                                      struct lec_arp_table **ret_entry)
 {
        unsigned long flags;
-        struct lec_arp_table *entry;
+       struct lec_arp_table *entry;
        struct atm_vcc *found;
 
-        if (mac_to_find[0] & 0x01) {
-                switch (priv->lane_version) {
-                case 1:
-                        return priv->mcast_vcc;
-                        break;
-                case 2:  /* LANE2 wants arp for multicast addresses */
-                        if (!compare_ether_addr(mac_to_find, bus_mac))
-                                return priv->mcast_vcc;
-                        break;
-                default:
-                        break;
-                }
-        }
+       if (mac_to_find[0] & 0x01) {
+               switch (priv->lane_version) {
+               case 1:
+                       return priv->mcast_vcc;
+                       break;
+               case 2: /* LANE2 wants arp for multicast addresses */
+                       if (!compare_ether_addr(mac_to_find, bus_mac))
+                               return priv->mcast_vcc;
+                       break;
+               default:
+                       break;
+               }
+       }
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        entry = lec_arp_find(priv, mac_to_find);
-  
-        if (entry) {
-                if (entry->status == ESI_FORWARD_DIRECT) {
-                        /* Connection Ok */
-                        entry->last_used = jiffies;
-                        *ret_entry = entry;
-                        found = entry->vcc;
+       entry = lec_arp_find(priv, mac_to_find);
+
+       if (entry) {
+               if (entry->status == ESI_FORWARD_DIRECT) {
+                       /* Connection Ok */
+                       entry->last_used = jiffies;
+                       lec_arp_hold(entry);
+                       *ret_entry = entry;
+                       found = entry->vcc;
                        goto out;
-                }
-               /* If the LE_ARP cache entry is still pending, reset count to 0
+               }
+               /*
+                * If the LE_ARP cache entry is still pending, reset count to 0
                 * so another LE_ARP request can be made for this frame.
                 */
                if (entry->status == ESI_ARP_PENDING) {
                        entry->no_tries = 0;
                }
-                /* Data direct VC not yet set up, check to see if the unknown
-                   frame count is greater than the limit. If the limit has
-                   not been reached, allow the caller to send packet to
-                   BUS. */
-                if (entry->status != ESI_FLUSH_PENDING &&
-                    entry->packets_flooded<priv->maximum_unknown_frame_count) {
-                        entry->packets_flooded++;
-                        DPRINTK("LEC_ARP: Flooding..\n");
-                        found = priv->mcast_vcc;
+               /*
+                * Data direct VC not yet set up, check to see if the unknown
+                * frame count is greater than the limit. If the limit has
+                * not been reached, allow the caller to send packet to
+                * BUS.
+                */
+               if (entry->status != ESI_FLUSH_PENDING &&
+                   entry->packets_flooded <
+                   priv->maximum_unknown_frame_count) {
+                       entry->packets_flooded++;
+                       DPRINTK("LEC_ARP: Flooding..\n");
+                       found = priv->mcast_vcc;
                        goto out;
-                }
-               /* We got here because entry->status == ESI_FLUSH_PENDING
+               }
+               /*
+                * We got here because entry->status == ESI_FLUSH_PENDING
                 * or BUS flood limit was reached for an entry which is
                 * in ESI_ARP_PENDING or ESI_VC_PENDING state.
                 */
-                *ret_entry = entry;
-                DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc);
-                found = NULL;
-        } else {
-                /* No matching entry was found */
-                entry = make_entry(priv, mac_to_find);
-                DPRINTK("LEC_ARP: Making entry\n");
-                if (!entry) {
-                        found = priv->mcast_vcc;
+               lec_arp_hold(entry);
+               *ret_entry = entry;
+               DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status,
+                       entry->vcc);
+               found = NULL;
+       } else {
+               /* No matching entry was found */
+               entry = make_entry(priv, mac_to_find);
+               DPRINTK("LEC_ARP: Making entry\n");
+               if (!entry) {
+                       found = priv->mcast_vcc;
                        goto out;
-                }
-                lec_arp_add(priv, entry);
-                /* We want arp-request(s) to be sent */
-                entry->packets_flooded =1;
-                entry->status = ESI_ARP_PENDING;
-                entry->no_tries = 1;
-                entry->last_used = entry->timestamp = jiffies;
-                entry->is_rdesc = is_rdesc;
-                if (entry->is_rdesc)
-                        send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL);
-                else
-                        send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
-                entry->timer.expires = jiffies + (1*HZ);
-                entry->timer.function = lec_arp_expire_arp;
-                add_timer(&entry->timer);
-                found = priv->mcast_vcc;
-        }
+               }
+               lec_arp_add(priv, entry);
+               /* We want arp-request(s) to be sent */
+               entry->packets_flooded = 1;
+               entry->status = ESI_ARP_PENDING;
+               entry->no_tries = 1;
+               entry->last_used = entry->timestamp = jiffies;
+               entry->is_rdesc = is_rdesc;
+               if (entry->is_rdesc)
+                       send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL,
+                                    NULL);
+               else
+                       send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL);
+               entry->timer.expires = jiffies + (1 * HZ);
+               entry->timer.function = lec_arp_expire_arp;
+               add_timer(&entry->timer);
+               found = priv->mcast_vcc;
+       }
 
 out:
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
@@ -2074,30 +2051,30 @@ out:
 }
 
 static int
-lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, 
-                unsigned long permanent)
+lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
+               unsigned long permanent)
 {
        unsigned long flags;
-        struct lec_arp_table *entry, *next;
-        int i;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
+       int i;
 
-        DPRINTK("lec_addr_delete\n");
+       DPRINTK("lec_addr_delete\n");
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-                for(entry = priv->lec_arp_tables[i]; entry != NULL; entry = next) {
-                        next = entry->next;
-                        if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
-                            && (permanent || 
-                                !(entry->flags & LEC_PERMANENT_FLAG))) {
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
+                       if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
+                           && (permanent ||
+                               !(entry->flags & LEC_PERMANENT_FLAG))) {
                                lec_arp_remove(priv, entry);
-                                kfree(entry);
-                        }
+                               lec_arp_put(entry);
+                       }
                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-                        return 0;
-                }
-        }
+                       return 0;
+               }
+       }
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-        return -1;
+       return -1;
 }
 
 /*
@@ -2105,109 +2082,98 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
  */
 static void
 lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
-               unsigned char *atm_addr, unsigned long remoteflag,
-               unsigned int targetless_le_arp)
+              unsigned char *atm_addr, unsigned long remoteflag,
+              unsigned int targetless_le_arp)
 {
        unsigned long flags;
-        struct lec_arp_table *entry, *tmp;
-        int i;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry, *tmp;
+       int i;
 
-        DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " ");
-        DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
-                mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],
-                mac_addr[4],mac_addr[5]);
+       DPRINTK("lec:%s", (targetless_le_arp) ? "targetless " : " ");
+       DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+               mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+               mac_addr[4], mac_addr[5]);
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        entry = lec_arp_find(priv, mac_addr);
-        if (entry == NULL && targetless_le_arp)
-                goto out;   /* LANE2: ignore targetless LE_ARPs for which
-                             * we have no entry in the cache. 7.1.30
-                             */
-        if (priv->lec_arp_empty_ones) {
-                entry = priv->lec_arp_empty_ones;
-                if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
-                        priv->lec_arp_empty_ones = entry->next;
-                } else {
-                        while(entry->next && memcmp(entry->next->atm_addr, 
-                                                    atm_addr, ATM_ESA_LEN))
-                                entry = entry->next;
-                        if (entry->next) {
-                                tmp = entry;
-                                entry = entry->next;
-                                tmp->next = entry->next;
-                        } else
-                                entry = NULL;
-                        
-                }
-                if (entry) {
-                        del_timer(&entry->timer);
-                        tmp = lec_arp_find(priv, mac_addr);
-                        if (tmp) {
-                                del_timer(&tmp->timer);
-                                tmp->status = ESI_FORWARD_DIRECT;
-                                memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
-                                tmp->vcc = entry->vcc;
-                                tmp->old_push = entry->old_push;
-                                tmp->last_used = jiffies;
-                                del_timer(&entry->timer);
-                                kfree(entry);
-                                entry=tmp;
-                        } else {
-                                entry->status = ESI_FORWARD_DIRECT;
-                                memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
-                                entry->last_used = jiffies;
-                                lec_arp_add(priv, entry);
-                        }
-                        if (remoteflag)
-                                entry->flags|=LEC_REMOTE_FLAG;
-                        else
-                                entry->flags&=~LEC_REMOTE_FLAG;
-                        DPRINTK("After update\n");
-                        dump_arp_table(priv);
-                        goto out;
-                }
-        }
-        entry = lec_arp_find(priv, mac_addr);
-        if (!entry) {
-                entry = make_entry(priv, mac_addr);
-                if (!entry)
+       entry = lec_arp_find(priv, mac_addr);
+       if (entry == NULL && targetless_le_arp)
+               goto out;       /*
+                                * LANE2: ignore targetless LE_ARPs for which
+                                * we have no entry in the cache. 7.1.30
+                                */
+       if (!hlist_empty(&priv->lec_arp_empty_ones)) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+                       if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
+                               hlist_del(&entry->next);
+                               del_timer(&entry->timer);
+                               tmp = lec_arp_find(priv, mac_addr);
+                               if (tmp) {
+                                       del_timer(&tmp->timer);
+                                       tmp->status = ESI_FORWARD_DIRECT;
+                                       memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
+                                       tmp->vcc = entry->vcc;
+                                       tmp->old_push = entry->old_push;
+                                       tmp->last_used = jiffies;
+                                       del_timer(&entry->timer);
+                                       lec_arp_put(entry);
+                                       entry = tmp;
+                               } else {
+                                       entry->status = ESI_FORWARD_DIRECT;
+                                       memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
+                                       entry->last_used = jiffies;
+                                       lec_arp_add(priv, entry);
+                               }
+                               if (remoteflag)
+                                       entry->flags |= LEC_REMOTE_FLAG;
+                               else
+                                       entry->flags &= ~LEC_REMOTE_FLAG;
+                               DPRINTK("After update\n");
+                               dump_arp_table(priv);
+                               goto out;
+                       }
+               }
+       }
+
+       entry = lec_arp_find(priv, mac_addr);
+       if (!entry) {
+               entry = make_entry(priv, mac_addr);
+               if (!entry)
                        goto out;
-                entry->status = ESI_UNKNOWN;
-                lec_arp_add(priv, entry);
-                /* Temporary, changes before end of function */
-        }
-        memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
-        del_timer(&entry->timer);
-        for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-                for(tmp = priv->lec_arp_tables[i]; tmp; tmp=tmp->next) {
-                        if (entry != tmp &&
-                            !memcmp(tmp->atm_addr, atm_addr,
-                                    ATM_ESA_LEN)) { 
-                                /* Vcc to this host exists */
-                                if (tmp->status > ESI_VC_PENDING) {
-                                        /*
-                                         * ESI_FLUSH_PENDING,
-                                         * ESI_FORWARD_DIRECT
-                                         */
-                                        entry->vcc = tmp->vcc;
-                                        entry->old_push=tmp->old_push;
-                                }
-                                entry->status=tmp->status;
-                                break;
-                        }
-                }
-        }
-        if (remoteflag)
-                entry->flags|=LEC_REMOTE_FLAG;
-        else
-                entry->flags&=~LEC_REMOTE_FLAG;
-        if (entry->status == ESI_ARP_PENDING ||
-            entry->status == ESI_UNKNOWN) {
-                entry->status = ESI_VC_PENDING;
-                send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
-        }
-        DPRINTK("After update2\n");
-        dump_arp_table(priv);
+               entry->status = ESI_UNKNOWN;
+               lec_arp_add(priv, entry);
+               /* Temporary, changes before end of function */
+       }
+       memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
+       del_timer(&entry->timer);
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) {
+                       if (entry != tmp &&
+                           !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
+                               /* Vcc to this host exists */
+                               if (tmp->status > ESI_VC_PENDING) {
+                                       /*
+                                        * ESI_FLUSH_PENDING,
+                                        * ESI_FORWARD_DIRECT
+                                        */
+                                       entry->vcc = tmp->vcc;
+                                       entry->old_push = tmp->old_push;
+                               }
+                               entry->status = tmp->status;
+                               break;
+                       }
+               }
+       }
+       if (remoteflag)
+               entry->flags |= LEC_REMOTE_FLAG;
+       else
+               entry->flags &= ~LEC_REMOTE_FLAG;
+       if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
+               entry->status = ESI_VC_PENDING;
+               send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
+       }
+       DPRINTK("After update2\n");
+       dump_arp_table(priv);
 out:
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
@@ -2217,299 +2183,299 @@ out:
  */
 static void
 lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
-              struct atm_vcc *vcc,
-              void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb))
+             struct atm_vcc *vcc,
+             void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
 {
        unsigned long flags;
-        struct lec_arp_table *entry;
-        int i, found_entry=0;
+       struct hlist_node *node;
+       struct lec_arp_table *entry;
+       int i, found_entry = 0;
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        if (ioc_data->receive == 2) {
-                /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
+       if (ioc_data->receive == 2) {
+               /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */
 
-                DPRINTK("LEC_ARP: Attaching mcast forward\n");
+               DPRINTK("LEC_ARP: Attaching mcast forward\n");
 #if 0
-                entry = lec_arp_find(priv, bus_mac);
-                if (!entry) {
-                        printk("LEC_ARP: Multicast entry not found!\n");
+               entry = lec_arp_find(priv, bus_mac);
+               if (!entry) {
+                       printk("LEC_ARP: Multicast entry not found!\n");
                        goto out;
-                }
-                memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
-                entry->recv_vcc = vcc;
-                entry->old_recv_push = old_push;
+               }
+               memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
+               entry->recv_vcc = vcc;
+               entry->old_recv_push = old_push;
 #endif
-                entry = make_entry(priv, bus_mac);
-                if (entry == NULL)
+               entry = make_entry(priv, bus_mac);
+               if (entry == NULL)
                        goto out;
-                del_timer(&entry->timer);
-                memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
-                entry->recv_vcc = vcc;
-                entry->old_recv_push = old_push;
-                entry->next = priv->mcast_fwds;
-                priv->mcast_fwds = entry;
-                goto out;
-        } else if (ioc_data->receive == 1) {
-                /* Vcc which we don't want to make default vcc, attach it
-                   anyway. */
-                DPRINTK("LEC_ARP:Attaching data direct, not default :%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
-                        ioc_data->atm_addr[0],ioc_data->atm_addr[1],
-                        ioc_data->atm_addr[2],ioc_data->atm_addr[3],
-                        ioc_data->atm_addr[4],ioc_data->atm_addr[5],
-                        ioc_data->atm_addr[6],ioc_data->atm_addr[7],
-                        ioc_data->atm_addr[8],ioc_data->atm_addr[9],
-                        ioc_data->atm_addr[10],ioc_data->atm_addr[11],
-                        ioc_data->atm_addr[12],ioc_data->atm_addr[13],
-                        ioc_data->atm_addr[14],ioc_data->atm_addr[15],
-                        ioc_data->atm_addr[16],ioc_data->atm_addr[17],
-                        ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
-                entry = make_entry(priv, bus_mac);
-                if (entry == NULL)
+               del_timer(&entry->timer);
+               memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
+               entry->recv_vcc = vcc;
+               entry->old_recv_push = old_push;
+               hlist_add_head(&entry->next, &priv->mcast_fwds);
+               goto out;
+       } else if (ioc_data->receive == 1) {
+               /*
+                * Vcc which we don't want to make default vcc,
+                * attach it anyway.
+                */
+               DPRINTK
+                   ("LEC_ARP:Attaching data direct, not default: "
+                    "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+                    ioc_data->atm_addr[0], ioc_data->atm_addr[1],
+                    ioc_data->atm_addr[2], ioc_data->atm_addr[3],
+                    ioc_data->atm_addr[4], ioc_data->atm_addr[5],
+                    ioc_data->atm_addr[6], ioc_data->atm_addr[7],
+                    ioc_data->atm_addr[8], ioc_data->atm_addr[9],
+                    ioc_data->atm_addr[10], ioc_data->atm_addr[11],
+                    ioc_data->atm_addr[12], ioc_data->atm_addr[13],
+                    ioc_data->atm_addr[14], ioc_data->atm_addr[15],
+                    ioc_data->atm_addr[16], ioc_data->atm_addr[17],
+                    ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
+               entry = make_entry(priv, bus_mac);
+               if (entry == NULL)
                        goto out;
-                memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
-                memset(entry->mac_addr, 0, ETH_ALEN);
-                entry->recv_vcc = vcc;
-                entry->old_recv_push = old_push;
-                entry->status = ESI_UNKNOWN;
-                entry->timer.expires = jiffies + priv->vcc_timeout_period;
-                entry->timer.function = lec_arp_expire_vcc;
-                add_timer(&entry->timer);
-                entry->next = priv->lec_no_forward;
-                priv->lec_no_forward = entry;
+               memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
+               memset(entry->mac_addr, 0, ETH_ALEN);
+               entry->recv_vcc = vcc;
+               entry->old_recv_push = old_push;
+               entry->status = ESI_UNKNOWN;
+               entry->timer.expires = jiffies + priv->vcc_timeout_period;
+               entry->timer.function = lec_arp_expire_vcc;
+               hlist_add_head(&entry->next, &priv->lec_no_forward);
+               add_timer(&entry->timer);
                dump_arp_table(priv);
                goto out;
-        }
-        DPRINTK("LEC_ARP:Attaching data direct, default:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
-                ioc_data->atm_addr[0],ioc_data->atm_addr[1],
-                ioc_data->atm_addr[2],ioc_data->atm_addr[3],
-                ioc_data->atm_addr[4],ioc_data->atm_addr[5],
-                ioc_data->atm_addr[6],ioc_data->atm_addr[7],
-                ioc_data->atm_addr[8],ioc_data->atm_addr[9],
-                ioc_data->atm_addr[10],ioc_data->atm_addr[11],
-                ioc_data->atm_addr[12],ioc_data->atm_addr[13],
-                ioc_data->atm_addr[14],ioc_data->atm_addr[15],
-                ioc_data->atm_addr[16],ioc_data->atm_addr[17],
-                ioc_data->atm_addr[18],ioc_data->atm_addr[19]);
-        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-                for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
-                        if (memcmp(ioc_data->atm_addr, entry->atm_addr, 
-                                   ATM_ESA_LEN)==0) {
-                                DPRINTK("LEC_ARP: Attaching data direct\n");
-                                DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n",
-                                        entry->vcc?entry->vcc->vci:0,
-                                        entry->recv_vcc?entry->recv_vcc->vci:0);
-                                found_entry=1;
-                                del_timer(&entry->timer);
-                                entry->vcc = vcc;
-                                entry->old_push = old_push;
-                                if (entry->status == ESI_VC_PENDING) {
-                                        if(priv->maximum_unknown_frame_count
-                                           ==0)
-                                                entry->status = 
-                                                        ESI_FORWARD_DIRECT;
-                                        else {
-                                                entry->timestamp = jiffies;
-                                                entry->status = 
-                                                        ESI_FLUSH_PENDING;
+       }
+       DPRINTK
+           ("LEC_ARP:Attaching data direct, default: "
+            "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
+            ioc_data->atm_addr[0], ioc_data->atm_addr[1],
+            ioc_data->atm_addr[2], ioc_data->atm_addr[3],
+            ioc_data->atm_addr[4], ioc_data->atm_addr[5],
+            ioc_data->atm_addr[6], ioc_data->atm_addr[7],
+            ioc_data->atm_addr[8], ioc_data->atm_addr[9],
+            ioc_data->atm_addr[10], ioc_data->atm_addr[11],
+            ioc_data->atm_addr[12], ioc_data->atm_addr[13],
+            ioc_data->atm_addr[14], ioc_data->atm_addr[15],
+            ioc_data->atm_addr[16], ioc_data->atm_addr[17],
+            ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
+                       if (memcmp
+                           (ioc_data->atm_addr, entry->atm_addr,
+                            ATM_ESA_LEN) == 0) {
+                               DPRINTK("LEC_ARP: Attaching data direct\n");
+                               DPRINTK("Currently -> Vcc: %d, Rvcc:%d\n",
+                                       entry->vcc ? entry->vcc->vci : 0,
+                                       entry->recv_vcc ? entry->recv_vcc->
+                                       vci : 0);
+                               found_entry = 1;
+                               del_timer(&entry->timer);
+                               entry->vcc = vcc;
+                               entry->old_push = old_push;
+                               if (entry->status == ESI_VC_PENDING) {
+                                       if (priv->maximum_unknown_frame_count
+                                           == 0)
+                                               entry->status =
+                                                   ESI_FORWARD_DIRECT;
+                                       else {
+                                               entry->timestamp = jiffies;
+                                               entry->status =
+                                                   ESI_FLUSH_PENDING;
 #if 0
-                                                send_to_lecd(priv,l_flush_xmt,
-                                                             NULL,
-                                                             entry->atm_addr,
-                                                             NULL);
+                                               send_to_lecd(priv, l_flush_xmt,
+                                                            NULL,
+                                                            entry->atm_addr,
+                                                            NULL);
 #endif
-                                        }
-                                } else {
-                                        /* They were forming a connection
-                                           to us, and we to them. Our
-                                           ATM address is numerically lower
-                                           than theirs, so we make connection
-                                           we formed into default VCC (8.1.11).
-                                           Connection they made gets torn
-                                           down. This might confuse some
-                                           clients. Can be changed if
-                                           someone reports trouble... */
-                                        ;
-                                }
-                        }
-                }
-        }
-        if (found_entry) {
-                DPRINTK("After vcc was added\n");
-                dump_arp_table(priv);
+                                       }
+                               } else {
+                                       /*
+                                        * They were forming a connection
+                                        * to us, and we to them. Our
+                                        * ATM address is numerically lower
+                                        * than theirs, so we make connection
+                                        * we formed into default VCC (8.1.11).
+                                        * Connection they made gets torn
+                                        * down. This might confuse some
+                                        * clients. Can be changed if
+                                        * someone reports trouble...
+                                        */
+                                       ;
+                               }
+                       }
+               }
+       }
+       if (found_entry) {
+               DPRINTK("After vcc was added\n");
+               dump_arp_table(priv);
                goto out;
-        }
-        /* Not found, snatch address from first data packet that arrives from
-           this vcc */
-        entry = make_entry(priv, bus_mac);
-        if (!entry)
+       }
+       /*
+        * Not found, snatch address from first data packet that arrives
+        * from this vcc
+        */
+       entry = make_entry(priv, bus_mac);
+       if (!entry)
                goto out;
-        entry->vcc = vcc;
-        entry->old_push = old_push;
-        memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
-        memset(entry->mac_addr, 0, ETH_ALEN);
-        entry->status = ESI_UNKNOWN;
-        entry->next = priv->lec_arp_empty_ones;
-        priv->lec_arp_empty_ones = entry;
-        entry->timer.expires = jiffies + priv->vcc_timeout_period;
-        entry->timer.function = lec_arp_expire_vcc;
-        add_timer(&entry->timer);
-        DPRINTK("After vcc was added\n");
+       entry->vcc = vcc;
+       entry->old_push = old_push;
+       memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
+       memset(entry->mac_addr, 0, ETH_ALEN);
+       entry->status = ESI_UNKNOWN;
+       hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
+       entry->timer.expires = jiffies + priv->vcc_timeout_period;
+       entry->timer.function = lec_arp_expire_vcc;
+       add_timer(&entry->timer);
+       DPRINTK("After vcc was added\n");
        dump_arp_table(priv);
 out:
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
 
-static void
-lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
+static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
 {
        unsigned long flags;
-        struct lec_arp_table *entry;
-        int i;
-  
-        DPRINTK("LEC:lec_flush_complete %lx\n",tran_id);
+       struct hlist_node *node;
+       struct lec_arp_table *entry;
+       int i;
+
+       DPRINTK("LEC:lec_flush_complete %lx\n", tran_id);
+restart:
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
-                for (entry = priv->lec_arp_tables[i]; entry; entry=entry->next) {
-                        if (entry->flush_tran_id == tran_id &&
-                            entry->status == ESI_FLUSH_PENDING) {
-                               struct sk_buff *skb;
-
-                               while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
-                                       lec_send(entry->vcc, skb, entry->priv);
-                                entry->status = ESI_FORWARD_DIRECT;
-                                DPRINTK("LEC_ARP: Flushed\n");
-                        }
-                }
-        }
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
+                       if (entry->flush_tran_id == tran_id
+                           && entry->status == ESI_FLUSH_PENDING) {
+                               struct sk_buff *skb;
+                               struct atm_vcc *vcc = entry->vcc;
+
+                               lec_arp_hold(entry);
+                               spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
+                               while ((skb = skb_dequeue(&entry->tx_wait)) != NULL)
+                                       lec_send(vcc, skb, entry->priv);
+                               entry->last_used = jiffies;
+                               entry->status = ESI_FORWARD_DIRECT;
+                               lec_arp_put(entry);
+                               DPRINTK("LEC_ARP: Flushed\n");
+                               goto restart;
+                       }
+               }
+       }
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-        dump_arp_table(priv);
+       dump_arp_table(priv);
 }
 
 static void
 lec_set_flush_tran_id(struct lec_priv *priv,
-                      unsigned char *atm_addr, unsigned long tran_id)
+                     unsigned char *atm_addr, unsigned long tran_id)
 {
        unsigned long flags;
-        struct lec_arp_table *entry;
-        int i;
+       struct hlist_node *node;
+       struct lec_arp_table *entry;
+       int i;
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
-                for(entry = priv->lec_arp_tables[i]; entry; entry=entry->next)
-                        if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
-                                entry->flush_tran_id = tran_id;
-                                DPRINTK("Set flush transaction id to %lx for %p\n",tran_id,entry);
-                        }
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
+               hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
+                       if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
+                               entry->flush_tran_id = tran_id;
+                               DPRINTK("Set flush transaction id to %lx for %p\n",
+                                       tran_id, entry);
+                       }
+               }
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
 
-static int 
-lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
+static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
 {
        unsigned long flags;
-        unsigned char mac_addr[] = {
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-        struct lec_arp_table *to_add;
+       unsigned char mac_addr[] = {
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+       };
+       struct lec_arp_table *to_add;
        struct lec_vcc_priv *vpriv;
        int err = 0;
-  
+
        if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL)))
                return -ENOMEM;
        vpriv->xoff = 0;
        vpriv->old_pop = vcc->pop;
        vcc->user_back = vpriv;
-        vcc->pop = lec_pop;
+       vcc->pop = lec_pop;
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        to_add = make_entry(priv, mac_addr);
-        if (!to_add) {
+       to_add = make_entry(priv, mac_addr);
+       if (!to_add) {
                vcc->pop = vpriv->old_pop;
                kfree(vpriv);
-                err = -ENOMEM;
+               err = -ENOMEM;
                goto out;
-        }
-        memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
-        to_add->status = ESI_FORWARD_DIRECT;
-        to_add->flags |= LEC_PERMANENT_FLAG;
-        to_add->vcc = vcc;
-        to_add->old_push = vcc->push;
-        vcc->push = lec_push;
-        priv->mcast_vcc = vcc;
-        lec_arp_add(priv, to_add);
+       }
+       memcpy(to_add->atm_addr, vcc->remote.sas_addr.prv, ATM_ESA_LEN);
+       to_add->status = ESI_FORWARD_DIRECT;
+       to_add->flags |= LEC_PERMANENT_FLAG;
+       to_add->vcc = vcc;
+       to_add->old_push = vcc->push;
+       vcc->push = lec_push;
+       priv->mcast_vcc = vcc;
+       lec_arp_add(priv, to_add);
 out:
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-        return err;
+       return err;
 }
 
-static void
-lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
+static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
 {
        unsigned long flags;
-        struct lec_arp_table *entry, *next;
-        int i;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry;
+       int i;
+
+       DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
+       dump_arp_table(priv);
 
-        DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n",vcc->vpi,vcc->vci);
-        dump_arp_table(priv);
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-                for(entry = priv->lec_arp_tables[i];entry; entry=next) {
-                        next = entry->next;
-                        if (vcc == entry->vcc) {
-                                lec_arp_remove(priv, entry);
-                                kfree(entry);
-                                if (priv->mcast_vcc == vcc) {
-                                        priv->mcast_vcc = NULL;
-                                }
-                        }
-                }
-        }
-
-        entry = priv->lec_arp_empty_ones;
-        priv->lec_arp_empty_ones = NULL;
-        while (entry != NULL) {
-                next = entry->next;
-                if (entry->vcc == vcc) { /* leave it out from the list */
-                        lec_arp_clear_vccs(entry);
-                        del_timer(&entry->timer);
-                        kfree(entry);
-                }
-                else {              /* put it back to the list */
-                        entry->next = priv->lec_arp_empty_ones;
-                        priv->lec_arp_empty_ones = entry;
-                }
-                entry = next;
-        }
-        
-        entry = priv->lec_no_forward;
-        priv->lec_no_forward = NULL;
-        while (entry != NULL) {
-                next = entry->next;
-                if (entry->recv_vcc == vcc) {
-                        lec_arp_clear_vccs(entry);
-                        del_timer(&entry->timer);
-                        kfree(entry);
-                }
-                else {
-                        entry->next = priv->lec_no_forward;
-                        priv->lec_no_forward = entry;
-                }
-                entry = next;
-        }
-
-        entry = priv->mcast_fwds;
-        priv->mcast_fwds = NULL;
-        while (entry != NULL) {
-                next = entry->next;
-                if (entry->recv_vcc == vcc) {
-                        lec_arp_clear_vccs(entry);
-                        /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
-                        kfree(entry);
-                }
-                else {
-                        entry->next = priv->mcast_fwds;
-                        priv->mcast_fwds = entry;
-                }
-                entry = next;
-        }
+
+       for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+               hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
+                       if (vcc == entry->vcc) {
+                               lec_arp_remove(priv, entry);
+                               lec_arp_put(entry);
+                               if (priv->mcast_vcc == vcc) {
+                                       priv->mcast_vcc = NULL;
+                               }
+                       }
+               }
+       }
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+               if (entry->vcc == vcc) {
+                       lec_arp_clear_vccs(entry);
+                       del_timer(&entry->timer);
+                       hlist_del(&entry->next);
+                       lec_arp_put(entry);
+               }
+       }
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
+               if (entry->recv_vcc == vcc) {
+                       lec_arp_clear_vccs(entry);
+                       del_timer(&entry->timer);
+                       hlist_del(&entry->next);
+                       lec_arp_put(entry);
+               }
+       }
+
+       hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
+               if (entry->recv_vcc == vcc) {
+                       lec_arp_clear_vccs(entry);
+                       /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
+                       hlist_del(&entry->next);
+                       lec_arp_put(entry);
+               }
+       }
 
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
        dump_arp_table(priv);
@@ -2517,57 +2483,42 @@ lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
 
 static void
 lec_arp_check_empties(struct lec_priv *priv,
-                      struct atm_vcc *vcc, struct sk_buff *skb)
+                     struct atm_vcc *vcc, struct sk_buff *skb)
 {
-        unsigned long flags;
-        struct lec_arp_table *entry, *prev;
-        struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
-        unsigned char *src;
+       unsigned long flags;
+       struct hlist_node *node, *next;
+       struct lec_arp_table *entry, *tmp;
+       struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
+       unsigned char *src;
 #ifdef CONFIG_TR
-        struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
+       struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data;
 
-        if (priv->is_trdev) src = tr_hdr->h_source;
-        else
+       if (priv->is_trdev)
+               src = tr_hdr->h_source;
+       else
 #endif
-        src = hdr->h_source;
+               src = hdr->h_source;
 
        spin_lock_irqsave(&priv->lec_arp_lock, flags);
-        entry = priv->lec_arp_empty_ones;
-        if (vcc == entry->vcc) {
-                del_timer(&entry->timer);
-                memcpy(entry->mac_addr, src, ETH_ALEN);
-                entry->status = ESI_FORWARD_DIRECT;
-                entry->last_used = jiffies;
-                priv->lec_arp_empty_ones = entry->next;
-                /* We might have got an entry */
-                if ((prev = lec_arp_find(priv,src))) {
-                        lec_arp_remove(priv, prev);
-                        kfree(prev);
-                }
-                lec_arp_add(priv, entry);
-               goto out;
-        }
-        prev = entry;
-        entry = entry->next;
-        while (entry && entry->vcc != vcc) {
-                prev= entry;
-                entry = entry->next;
-        }
-        if (!entry) {
-                DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
-               goto out;
-        }
-        del_timer(&entry->timer);
-        memcpy(entry->mac_addr, src, ETH_ALEN);
-        entry->status = ESI_FORWARD_DIRECT;
-        entry->last_used = jiffies;
-        prev->next = entry->next;
-        if ((prev = lec_arp_find(priv, src))) {
-                lec_arp_remove(priv, prev);
-                kfree(prev);
-        }
-        lec_arp_add(priv, entry);
+       hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
+               if (vcc == entry->vcc) {
+                       del_timer(&entry->timer);
+                       memcpy(entry->mac_addr, src, ETH_ALEN);
+                       entry->status = ESI_FORWARD_DIRECT;
+                       entry->last_used = jiffies;
+                       /* We might have got an entry */
+                       if ((tmp = lec_arp_find(priv, src))) {
+                               lec_arp_remove(priv, tmp);
+                               lec_arp_put(tmp);
+                       }
+                       hlist_del(&entry->next);
+                       lec_arp_add(priv, entry);
+                       goto out;
+               }
+       }
+       DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
 out:
        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 }
+
 MODULE_LICENSE("GPL");
index c22a8bfa1f813bb0a61b9af087eb496a5daa91ae..8ac6b73216357aac3816c8e1165ed74ba19cee22 100644 (file)
@@ -1,14 +1,13 @@
 /*
- *
  * Lan Emulation client header file
  *
- * Marko Kiiskila mkiiskila@yahoo.com
- *
+ * Marko Kiiskila <mkiiskila@yahoo.com>
  */
 
 #ifndef _LEC_H_
 #define _LEC_H_
 
+#include <linux/config.h>
 #include <linux/atmdev.h>
 #include <linux/netdevice.h>
 #include <linux/atmlec.h>
 #define LEC_HEADER_LEN 16
 
 struct lecdatahdr_8023 {
-  unsigned short le_header;
-  unsigned char h_dest[ETH_ALEN];
-  unsigned char h_source[ETH_ALEN];
-  unsigned short h_type;
+       unsigned short le_header;
+       unsigned char h_dest[ETH_ALEN];
+       unsigned char h_source[ETH_ALEN];
+       unsigned short h_type;
 };
 
 struct lecdatahdr_8025 {
-  unsigned short le_header;
-  unsigned char ac_pad;
-  unsigned char fc;
-  unsigned char h_dest[ETH_ALEN];
-  unsigned char h_source[ETH_ALEN];
+       unsigned short le_header;
+       unsigned char ac_pad;
+       unsigned char fc;
+       unsigned char h_dest[ETH_ALEN];
+       unsigned char h_source[ETH_ALEN];
 };
 
 #define LEC_MINIMUM_8023_SIZE   62
@@ -44,17 +43,18 @@ struct lecdatahdr_8025 {
  *
  */
 struct lane2_ops {
-       int  (*resolve)(struct net_device *dev, u8 *dst_mac, int force,
-                        u8 **tlvs, u32 *sizeoftlvs);
-        int  (*associate_req)(struct net_device *dev, u8 *lan_dst,
-                              u8 *tlvs, u32 sizeoftlvs);
-       void (*associate_indicator)(struct net_device *dev, u8 *mac_addr,
-                                    u8 *tlvs, u32 sizeoftlvs);
+       int (*resolve) (struct net_device *dev, u8 *dst_mac, int force,
+                       u8 **tlvs, u32 *sizeoftlvs);
+       int (*associate_req) (struct net_device *dev, u8 *lan_dst,
+                             u8 *tlvs, u32 sizeoftlvs);
+       void (*associate_indicator) (struct net_device *dev, u8 *mac_addr,
+                                    u8 *tlvs, u32 sizeoftlvs);
 };
 
 /*
  * ATM LAN Emulation supports both LLC & Dix Ethernet EtherType
  * frames. 
+ *
  * 1. Dix Ethernet EtherType frames encoded by placing EtherType
  *    field in h_type field. Data follows immediatelly after header.
  * 2. LLC Data frames whose total length, including LLC field and data,
@@ -70,72 +70,88 @@ struct lane2_ops {
 #define LEC_ARP_TABLE_SIZE 16
 
 struct lec_priv {
-        struct net_device_stats stats;
-        unsigned short lecid;      /* Lecid of this client */
-        struct lec_arp_table *lec_arp_empty_ones;
-        /* Used for storing VCC's that don't have a MAC address attached yet */
-        struct lec_arp_table *lec_arp_tables[LEC_ARP_TABLE_SIZE];
-        /* Actual LE ARP table */
-        struct lec_arp_table *lec_no_forward;
-        /* Used for storing VCC's (and forward packets from) which are to
-           age out by not using them to forward packets. 
-           This is because to some LE clients there will be 2 VCCs. Only
-           one of them gets used. */
-        struct lec_arp_table *mcast_fwds;
-        /* With LANEv2 it is possible that BUS (or a special multicast server)
-           establishes multiple Multicast Forward VCCs to us. This list
-           collects all those VCCs. LANEv1 client has only one item in this
-           list. These entries are not aged out. */
-        spinlock_t lec_arp_lock;
-        struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
-        struct atm_vcc *lecd;
-        struct timer_list lec_arp_timer;
-        /* C10 */
-        unsigned int maximum_unknown_frame_count;
-/* Within the period of time defined by this variable, the client will send 
-   no more than C10 frames to BUS for a given unicast destination. (C11) */
-        unsigned long max_unknown_frame_time;
-/* If no traffic has been sent in this vcc for this period of time,
-   vcc will be torn down (C12)*/
-        unsigned long vcc_timeout_period;
-/* An LE Client MUST not retry an LE_ARP_REQUEST for a 
-   given frame's LAN Destination more than maximum retry count times,
-   after the first LEC_ARP_REQUEST (C13)*/
-        unsigned short max_retry_count;
-/* Max time the client will maintain an entry in its arp cache in
-   absence of a verification of that relationship (C17)*/
-        unsigned long aging_time;
-/* Max time the client will maintain an entry in cache when
-   topology change flag is true (C18) */
-        unsigned long forward_delay_time;
-/* Topology change flag  (C19)*/
-        int topology_change;
-/* Max time the client expects an LE_ARP_REQUEST/LE_ARP_RESPONSE
-   cycle to take (C20)*/
-        unsigned long arp_response_time;
-/* Time limit ot wait to receive an LE_FLUSH_RESPONSE after the
-   LE_FLUSH_REQUEST has been sent before taking recover action. (C21)*/
-        unsigned long flush_timeout;
-/* The time since sending a frame to the bus after which the
-   LE Client may assume that the frame has been either discarded or
-   delivered to the recipient (C22) */
-        unsigned long path_switching_delay;
+       struct net_device_stats stats;
+       unsigned short lecid;                   /* Lecid of this client */
+       struct hlist_head lec_arp_empty_ones;
+                                               /* Used for storing VCC's that don't have a MAC address attached yet */
+       struct hlist_head lec_arp_tables[LEC_ARP_TABLE_SIZE];
+                                               /* Actual LE ARP table */
+       struct hlist_head lec_no_forward;
+                                               /*
+                                                * Used for storing VCC's (and forward packets from) which are to
+                                                * age out by not using them to forward packets.
+                                                * This is because to some LE clients there will be 2 VCCs. Only
+                                                * one of them gets used.
+                                                */
+       struct hlist_head mcast_fwds;
+                                               /*
+                                                * With LANEv2 it is possible that BUS (or a special multicast server)
+                                                * establishes multiple Multicast Forward VCCs to us. This list
+                                                * collects all those VCCs. LANEv1 client has only one item in this
+                                                * list. These entries are not aged out.
+                                                */
+       spinlock_t lec_arp_lock;
+       struct atm_vcc *mcast_vcc;              /* Default Multicast Send VCC */
+       struct atm_vcc *lecd;
+       struct work_struct lec_arp_work;        /* C10 */
+       unsigned int maximum_unknown_frame_count;
+                                               /*
+                                                * Within the period of time defined by this variable, the client will send
+                                                * no more than C10 frames to BUS for a given unicast destination. (C11)
+                                                */
+       unsigned long max_unknown_frame_time;
+                                               /*
+                                                * If no traffic has been sent in this vcc for this period of time,
+                                                * vcc will be torn down (C12)
+                                                */
+       unsigned long vcc_timeout_period;
+                                               /*
+                                                * An LE Client MUST not retry an LE_ARP_REQUEST for a
+                                                * given frame's LAN Destination more than maximum retry count times,
+                                                * after the first LEC_ARP_REQUEST (C13)
+                                                */
+       unsigned short max_retry_count;
+                                               /*
+                                                * Max time the client will maintain an entry in its arp cache in
+                                                * absence of a verification of that relationship (C17)
+                                                */
+       unsigned long aging_time;
+                                               /*
+                                                * Max time the client will maintain an entry in cache when
+                                                * topology change flag is true (C18)
+                                                */
+       unsigned long forward_delay_time;       /* Topology change flag (C19) */
+       int topology_change;
+                                               /*
+                                                * Max time the client expects an LE_ARP_REQUEST/LE_ARP_RESPONSE
+                                                * cycle to take (C20)
+                                                */
+       unsigned long arp_response_time;
+                                               /*
+                                                * Time limit ot wait to receive an LE_FLUSH_RESPONSE after the
+                                                * LE_FLUSH_REQUEST has been sent before taking recover action. (C21)
+                                                */
+       unsigned long flush_timeout;
+                                               /* The time since sending a frame to the bus after which the
+                                                * LE Client may assume that the frame has been either discarded or
+                                                * delivered to the recipient (C22)
+                                                */
+       unsigned long path_switching_delay;
 
-        u8 *tlvs;          /* LANE2: TLVs are new                */
-        u32 sizeoftlvs;    /* The size of the tlv array in bytes */
-        int lane_version;  /* LANE2                              */
-       int itfnum;        /* e.g. 2 for lec2, 5 for lec5        */
-        struct lane2_ops *lane2_ops; /* can be NULL for LANE v1  */
-        int is_proxy;      /* bridge between ATM and Ethernet    */
-        int is_trdev;      /* Device type, 0 = Ethernet, 1 = TokenRing */
+       u8 *tlvs;                               /* LANE2: TLVs are new */
+       u32 sizeoftlvs;                         /* The size of the tlv array in bytes */
+       int lane_version;                       /* LANE2 */
+       int itfnum;                             /* e.g. 2 for lec2, 5 for lec5 */
+       struct lane2_ops *lane2_ops;            /* can be NULL for LANE v1 */
+       int is_proxy;                           /* bridge between ATM and Ethernet */
+       int is_trdev;                           /* Device type, 0 = Ethernet, 1 = TokenRing */
 };
 
 struct lec_vcc_priv {
-       void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+       void (*old_pop) (struct atm_vcc *vcc, struct sk_buff *skb);
        int xoff;
 };
 
 #define LEC_VCC_PRIV(vcc)      ((struct lec_vcc_priv *)((vcc)->user_back))
 
-#endif /* _LEC_H_ */
-
+#endif                         /* _LEC_H_ */
index 397448094648e938ba9c869dfb6c4a796229f1bc..ec67435a40a6ffe172aa6d71c01396c5c652d832 100644 (file)
@@ -1,92 +1,96 @@
 /*
  * Lec arp cache
- * Marko Kiiskila mkiiskila@yahoo.com
  *
+ * Marko Kiiskila <mkiiskila@yahoo.com>
  */
-#ifndef _LEC_ARP_H
-#define _LEC_ARP_H
+#ifndef _LEC_ARP_H_
+#define _LEC_ARP_H_
 #include <linux/atm.h>
 #include <linux/atmdev.h>
 #include <linux/if_ether.h>
 #include <linux/atmlec.h>
 
 struct lec_arp_table {
-        struct lec_arp_table *next;          /* Linked entry list */
-        unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */
-        unsigned char mac_addr[ETH_ALEN];    /* Mac address */
-        int is_rdesc;                        /* Mac address is a route descriptor */
-        struct atm_vcc *vcc;                 /* Vcc this entry is attached */
-        struct atm_vcc *recv_vcc;            /* Vcc we receive data from */
-        void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); 
-                                             /* Push that leads to daemon */
-        void (*old_recv_push)(struct atm_vcc *vcc, struct sk_buff *skb);
-                                             /* Push that leads to daemon */
-        void (*old_close)(struct atm_vcc *vcc);
-                                             /* We want to see when this
-                                              * vcc gets closed */
-        unsigned long last_used;             /* For expiry */
-        unsigned long timestamp;             /* Used for various timestamping
-                                              * things:
-                                              * 1. FLUSH started 
-                                              *    (status=ESI_FLUSH_PENDING)
-                                              * 2. Counting to 
-                                              *    max_unknown_frame_time
-                                              *    (status=ESI_ARP_PENDING||
-                                              *     status=ESI_VC_PENDING)
-                                              */
-        unsigned char no_tries;              /* No of times arp retry has been 
-                                                tried */
-        unsigned char status;                /* Status of this entry */
-        unsigned short flags;                /* Flags for this entry */
-        unsigned short packets_flooded;      /* Data packets flooded */
-        unsigned long flush_tran_id;         /* Transaction id in flush protocol */
-        struct timer_list timer;             /* Arping timer */
-        struct lec_priv *priv;               /* Pointer back */
+       struct hlist_node next;         /* Linked entry list */
+       unsigned char atm_addr[ATM_ESA_LEN];    /* Atm address */
+       unsigned char mac_addr[ETH_ALEN];       /* Mac address */
+       int is_rdesc;                   /* Mac address is a route descriptor */
+       struct atm_vcc *vcc;            /* Vcc this entry is attached */
+       struct atm_vcc *recv_vcc;       /* Vcc we receive data from */
 
-        u8  *tlvs;             /* LANE2: Each MAC address can have TLVs    */
-        u32 sizeoftlvs;        /* associated with it. sizeoftlvs tells the */
-                               /* the length of the tlvs array             */
-        struct sk_buff_head tx_wait; /* wait queue for outgoing packets    */
+       void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb);
+                                       /* Push that leads to daemon */
+
+       void (*old_recv_push) (struct atm_vcc *vcc, struct sk_buff *skb);
+                                       /* Push that leads to daemon */
+
+       unsigned long last_used;        /* For expiry */
+       unsigned long timestamp;        /* Used for various timestamping things:
+                                        * 1. FLUSH started
+                                        *    (status=ESI_FLUSH_PENDING)
+                                        * 2. Counting to
+                                        *    max_unknown_frame_time
+                                        *    (status=ESI_ARP_PENDING||
+                                        *     status=ESI_VC_PENDING)
+                                        */
+       unsigned char no_tries;         /* No of times arp retry has been tried */
+       unsigned char status;           /* Status of this entry */
+       unsigned short flags;           /* Flags for this entry */
+       unsigned short packets_flooded; /* Data packets flooded */
+       unsigned long flush_tran_id;    /* Transaction id in flush protocol */
+       struct timer_list timer;        /* Arping timer */
+       struct lec_priv *priv;          /* Pointer back */
+       u8 *tlvs;
+       u32 sizeoftlvs;                 /*
+                                        * LANE2: Each MAC address can have TLVs
+                                        * associated with it.  sizeoftlvs tells the
+                                        * the length of the tlvs array
+                                        */
+       struct sk_buff_head tx_wait;    /* wait queue for outgoing packets */
+       atomic_t usage;                 /* usage count */
 };
 
-struct tlv {                   /* LANE2: Template tlv struct for accessing */
-                               /* the tlvs in the lec_arp_table->tlvs array*/
-        u32 type;
-        u8  length;
-        u8  value[255];
+/*
+ * LANE2: Template tlv struct for accessing
+ * the tlvs in the lec_arp_table->tlvs array
+ */
+struct tlv {
+       u32 type;
+       u8 length;
+       u8 value[255];
 };
 
 /* Status fields */
-#define ESI_UNKNOWN 0       /*
-                             * Next packet sent to this mac address
-                             * causes ARP-request to be sent 
-                             */
-#define ESI_ARP_PENDING 1   /*
-                             * There is no ATM address associated with this
-                             * 48-bit address.  The LE-ARP protocol is in
-                             * progress.
-                             */
-#define ESI_VC_PENDING 2    /*
-                             * There is a valid ATM address associated with 
-                             * this 48-bit address but there is no VC set 
-                             * up to that ATM address.  The signaling 
-                             * protocol is in process.
-                             */
-#define ESI_FLUSH_PENDING 4 /*
-                             * The LEC has been notified of the FLUSH_START
-                             * status and it is assumed that the flush 
-                             * protocol is in process.
-                             */
-#define ESI_FORWARD_DIRECT 5 /*
-                              * Either the Path Switching Delay (C22) has 
-                              * elapsed or the LEC has notified the Mapping 
-                              * that the flush protocol has completed.  In 
-                              * either case, it is safe to forward packets 
-                              * to this address via the data direct VC.
-                              */
+#define ESI_UNKNOWN 0          /*
+                                * Next packet sent to this mac address
+                                * causes ARP-request to be sent
+                                */
+#define ESI_ARP_PENDING 1      /*
+                                * There is no ATM address associated with this
+                                * 48-bit address.  The LE-ARP protocol is in
+                                * progress.
+                                */
+#define ESI_VC_PENDING 2       /*
+                                * There is a valid ATM address associated with
+                                * this 48-bit address but there is no VC set
+                                * up to that ATM address.  The signaling
+                                * protocol is in process.
+                                */
+#define ESI_FLUSH_PENDING 4    /*
+                                * The LEC has been notified of the FLUSH_START
+                                * status and it is assumed that the flush
+                                * protocol is in process.
+                                */
+#define ESI_FORWARD_DIRECT 5   /*
+                                * Either the Path Switching Delay (C22) has
+                                * elapsed or the LEC has notified the Mapping
+                                * that the flush protocol has completed.  In
+                                * either case, it is safe to forward packets
+                                * to this address via the data direct VC.
+                                */
 
 /* Flag values */
 #define LEC_REMOTE_FLAG      0x0001
 #define LEC_PERMANENT_FLAG   0x0002
 
-#endif
+#endif /* _LEC_ARP_H_ */
index b87c2a88bdce40c63fdc136cac99e4ec7463eabb..0d2b994af5115931e419d3696b8e36e70fdaf493 100644 (file)
@@ -560,7 +560,6 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
        struct atmmpc_ioc ioc_data;
        in_cache_entry *in_entry;
        uint32_t  ipaddr;
-       unsigned char *ip;
 
        bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc));
        if (bytes_left != 0) {
@@ -583,9 +582,8 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
                        if (in_entry != NULL) mpc->in_ops->put(in_entry);
                        return -EINVAL;
                }
-               ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip;
                printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
-                      mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+                      mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
                in_entry->shortcut = vcc;
                mpc->in_ops->put(in_entry);
        } else {
@@ -616,10 +614,8 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
        dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
        in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
        if (in_entry) {
-               unsigned char *ip __attribute__ ((unused)) =
-                   (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
                dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
-                      mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+                      mpc->dev->name, NIPQUAD(in_entry->ctrl_info.in_dst_ip));
                in_entry->shortcut = NULL;
                mpc->in_ops->put(in_entry);
        }
@@ -1154,18 +1150,17 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
        uint32_t dst_ip = msg->content.in_info.in_dst_ip;
        uint32_t mask = msg->ip_mask;
-       unsigned char *ip = (unsigned char *)&dst_ip;
        in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
 
        if(entry == NULL){
                printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
-               printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+               printk("ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
                return;
        }
 
        do {
                dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
-                       mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+                       mpc->dev->name, NIPQUAD(dst_ip));
                write_lock_bh(&mpc->ingress_lock);
                mpc->in_ops->remove_entry(entry, mpc);
                write_unlock_bh(&mpc->ingress_lock);
index 781ed1b9329d32f4308b734081f2ccd1ebd2466b..fbf13cdcf46ed2af4edfa2f1bf085af201e0ed6f 100644 (file)
@@ -87,7 +87,6 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
 static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
                                          struct mpoa_client *client)
 {
-       unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
        in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
 
        if (entry == NULL) {
@@ -95,7 +94,7 @@ static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
                return NULL;
        }
 
-       dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+       dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
        memset(entry,0,sizeof(in_cache_entry));
 
        atomic_set(&entry->use, 1);
@@ -152,10 +151,7 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
 
        if( entry->count > mpc->parameters.mpc_p1 &&
            entry->entry_state == INGRESS_INVALID){
-               unsigned char *ip __attribute__ ((unused)) =
-                   (unsigned char *)&entry->ctrl_info.in_dst_ip;
-
-               dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+               dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, NIPQUAD(entry->ctrl_info.in_dst_ip));
                entry->entry_state = INGRESS_RESOLVING;
                msg.type =  SND_MPOA_RES_RQST;
                memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
@@ -187,11 +183,9 @@ static void in_cache_remove_entry(in_cache_entry *entry,
 {
        struct atm_vcc *vcc;
        struct k_message msg;
-       unsigned char *ip;
 
        vcc = entry->shortcut;
-       ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
-       dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
+       dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",NIPQUAD(entry->ctrl_info.in_dst_ip));
 
        if (entry->prev != NULL)
                entry->prev->next = entry->next;
index 788ea7a2b74498c10534501e62c3e91fd17c117e..305a099b7477eb8fd0e4a7a7b487b7bd435e6677 100644 (file)
@@ -276,7 +276,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
                set_current_state(TASK_INTERRUPTIBLE);
 
                if (!timeo) {
-                       err = -EAGAIN;
+                       err = -EINPROGRESS;
                        break;
                }
 
index e620061fb50fd83cd530167d863b1745f3f7a3fd..2312d050eeedfb66ed382108f0703f6d2dfc5b9d 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "bnep.h"
@@ -515,6 +516,26 @@ static int bnep_session(void *arg)
        return 0;
 }
 
+static struct device *bnep_get_device(struct bnep_session *session)
+{
+       bdaddr_t *src = &bt_sk(session->sock->sk)->src;
+       bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(dst, src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+       if (!conn)
+               return NULL;
+
+       hci_dev_put(hdev);
+
+       return &conn->dev;
+}
+
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 {
        struct net_device *dev;
@@ -534,7 +555,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        if (!dev)
                return -ENOMEM;
 
-
        down_write(&bnep_session_sem);
 
        ss = __bnep_get_session(dst);
@@ -551,7 +571,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        memcpy(s->eh.h_source, &dst, ETH_ALEN);
        memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
-       s->dev = dev;
+       s->dev   = dev;
        s->sock  = sock;
        s->role  = req->role;
        s->state = BT_CONNECTED;
@@ -568,6 +588,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        bnep_set_default_proto_filter(s);
 #endif
 
+       SET_NETDEV_DEV(dev, bnep_get_device(s));
+
        err = register_netdev(dev);
        if (err) {
                goto failed;
index 420ed4d7e57e98e44615196248e7afb94d36498e..90e3a285a17eaf9a4bde198879748d8a4da680a7 100644 (file)
@@ -84,6 +84,20 @@ static void hci_acl_connect(struct hci_conn *conn)
        hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
 }
 
+static void hci_acl_connect_cancel(struct hci_conn *conn)
+{
+       struct hci_cp_create_conn_cancel cp;
+
+       BT_DBG("%p", conn);
+
+       if (conn->hdev->hci_ver < 2)
+               return;
+
+       bacpy(&cp.bdaddr, &conn->dst);
+       hci_send_cmd(conn->hdev, OGF_LINK_CTL,
+                               OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
+}
+
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
 {
        struct hci_cp_disconnect cp;
@@ -94,7 +108,8 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
 
        cp.handle = __cpu_to_le16(conn->handle);
        cp.reason = reason;
-       hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, sizeof(cp), &cp);
+       hci_send_cmd(conn->hdev, OGF_LINK_CTL,
+                               OCF_DISCONNECT, sizeof(cp), &cp);
 }
 
 void hci_add_sco(struct hci_conn *conn, __u16 handle)
@@ -124,12 +139,20 @@ static void hci_conn_timeout(unsigned long arg)
                return;
 
        hci_dev_lock(hdev);
-       if (conn->state == BT_CONNECTED)
+
+       switch (conn->state) {
+       case BT_CONNECT:
+               hci_acl_connect_cancel(conn);
+               break;
+       case BT_CONNECTED:
                hci_acl_disconn(conn, 0x13);
-       else
+               break;
+       default:
                conn->state = BT_CLOSED;
+               break;
+       }
+
        hci_dev_unlock(hdev);
-       return;
 }
 
 static void hci_conn_idle(unsigned long arg)
@@ -179,6 +202,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
        if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
 
+       hci_conn_add_sysfs(conn);
+
        tasklet_enable(&hdev->tx_task);
 
        return conn;
@@ -211,6 +236,8 @@ int hci_conn_del(struct hci_conn *conn)
 
        tasklet_disable(&hdev->tx_task);
 
+       hci_conn_del_sysfs(conn);
+
        hci_conn_hash_del(hdev, conn);
        if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -221,7 +248,9 @@ int hci_conn_del(struct hci_conn *conn)
 
        hci_dev_put(hdev);
 
-       kfree(conn);
+       /* will free via device release */
+       put_device(&conn->dev);
+
        return 0;
 }
 
index 5ed47427790385fc335168857d02082deb2ab498..338ae977a31b2209fb39e1a97d644db185d4597a 100644 (file)
@@ -206,6 +206,9 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
        /* Read Local Supported Features */
        hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
 
+       /* Read Local Version */
+       hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL);
+
        /* Read Buffer Size (ACL mtu, max pkt, etc.) */
        hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL);
 
index 3896dabab11da70898640581f9c3e5b2195f7678..d43d0c8909752564796b540a61cb58389cc8cb0d 100644 (file)
@@ -62,6 +62,7 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
 
        switch (ocf) {
        case OCF_INQUIRY_CANCEL:
+       case OCF_EXIT_PERIODIC_INQ:
                status = *((__u8 *) skb->data);
 
                if (status) {
@@ -297,6 +298,7 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
 /* Command Complete OGF INFO_PARAM  */
 static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
 {
+       struct hci_rp_read_loc_version *lv;
        struct hci_rp_read_local_features *lf;
        struct hci_rp_read_buffer_size *bs;
        struct hci_rp_read_bd_addr *ba;
@@ -304,6 +306,23 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
        BT_DBG("%s ocf 0x%x", hdev->name, ocf);
 
        switch (ocf) {
+       case OCF_READ_LOCAL_VERSION:
+               lv = (struct hci_rp_read_loc_version *) skb->data;
+
+               if (lv->status) {
+                       BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
+                       break;
+               }
+
+               hdev->hci_ver = lv->hci_ver;
+               hdev->hci_rev = btohs(lv->hci_rev);
+               hdev->manufacturer = btohs(lv->manufacturer);
+
+               BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name,
+                               hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
+
+               break;
+
        case OCF_READ_LOCAL_FEATURES:
                lf = (struct hci_rp_read_local_features *) skb->data;
 
@@ -328,7 +347,8 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
                if (hdev->features[1] & LMP_HV3)
                        hdev->pkt_type |= (HCI_HV3);
 
-               BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, lf->features[0], lf->features[1], lf->features[2]);
+               BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
+                               lf->features[0], lf->features[1], lf->features[2]);
 
                break;
 
@@ -757,6 +777,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 
                        hci_send_cmd(hdev, OGF_LINK_CTL,
                                OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
+               } else {
+                       /* Update disconnect timer */
+                       hci_conn_hold(conn);
+                       hci_conn_put(conn);
                }
        } else
                conn->state = BT_CLOSED;
index 3987d167f04e73225ea98556bd1f583c899e9223..989b22d9042e92f929435d9f0290d2d429e7fd75 100644 (file)
 #define BT_DBG(D...)
 #endif
 
-static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+static inline char *typetostr(int type)
 {
-       struct hci_dev *hdev = dev_get_drvdata(dev);
-       return sprintf(buf, "%s\n", hdev->name);
+       switch (type) {
+       case HCI_VIRTUAL:
+               return "VIRTUAL";
+       case HCI_USB:
+               return "USB";
+       case HCI_PCCARD:
+               return "PCCARD";
+       case HCI_UART:
+               return "UART";
+       case HCI_RS232:
+               return "RS232";
+       case HCI_PCI:
+               return "PCI";
+       case HCI_SDIO:
+               return "SDIO";
+       default:
+               return "UNKNOWN";
+       }
 }
 
 static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct hci_dev *hdev = dev_get_drvdata(dev);
-       return sprintf(buf, "%d\n", hdev->type);
+       return sprintf(buf, "%s\n", typetostr(hdev->type));
 }
 
 static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
@@ -33,10 +49,22 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, c
        return sprintf(buf, "%s\n", batostr(&bdaddr));
 }
 
-static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_manufacturer(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct hci_dev *hdev = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", hdev->manufacturer);
+}
+
+static ssize_t show_hci_version(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct hci_dev *hdev = dev_get_drvdata(dev);
-       return sprintf(buf, "0x%lx\n", hdev->flags);
+       return sprintf(buf, "%d\n", hdev->hci_ver);
+}
+
+static ssize_t show_hci_revision(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct hci_dev *hdev = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", hdev->hci_rev);
 }
 
 static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
@@ -141,10 +169,11 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
        return count;
 }
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
-static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
+static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
+static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
+static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
 static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
 
 static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
@@ -155,10 +184,11 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
                                show_sniff_min_interval, store_sniff_min_interval);
 
 static struct device_attribute *bt_attrs[] = {
-       &dev_attr_name,
        &dev_attr_type,
        &dev_attr_address,
-       &dev_attr_flags,
+       &dev_attr_manufacturer,
+       &dev_attr_hci_version,
+       &dev_attr_hci_revision,
        &dev_attr_inquiry_cache,
        &dev_attr_idle_timeout,
        &dev_attr_sniff_max_interval,
@@ -166,6 +196,32 @@ static struct device_attribute *bt_attrs[] = {
        NULL
 };
 
+static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct hci_conn *conn = dev_get_drvdata(dev);
+       return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO");
+}
+
+static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct hci_conn *conn = dev_get_drvdata(dev);
+       bdaddr_t bdaddr;
+       baswap(&bdaddr, &conn->dst);
+       return sprintf(buf, "%s\n", batostr(&bdaddr));
+}
+
+#define CONN_ATTR(_name,_mode,_show,_store) \
+struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
+
+static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL);
+static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL);
+
+static struct device_attribute *conn_attrs[] = {
+       &conn_attr_type,
+       &conn_attr_address,
+       NULL
+};
+
 struct class *bt_class = NULL;
 EXPORT_SYMBOL_GPL(bt_class);
 
@@ -177,8 +233,57 @@ static struct platform_device *bt_platform;
 
 static void bt_release(struct device *dev)
 {
-       struct hci_dev *hdev = dev_get_drvdata(dev);
-       kfree(hdev);
+       void *data = dev_get_drvdata(dev);
+       kfree(data);
+}
+
+static void add_conn(void *data)
+{
+       struct hci_conn *conn = data;
+       int i;
+
+       device_register(&conn->dev);
+
+       for (i = 0; conn_attrs[i]; i++)
+               device_create_file(&conn->dev, conn_attrs[i]);
+}
+
+void hci_conn_add_sysfs(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+       bdaddr_t *ba = &conn->dst;
+
+       BT_DBG("conn %p", conn);
+
+       conn->dev.parent  = &hdev->dev;
+       conn->dev.release = bt_release;
+
+       snprintf(conn->dev.bus_id, BUS_ID_SIZE,
+                       "%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+                       conn->type == ACL_LINK ? "acl" : "sco",
+                       ba->b[5], ba->b[4], ba->b[3],
+                       ba->b[2], ba->b[1], ba->b[0]);
+
+       dev_set_drvdata(&conn->dev, conn);
+
+       INIT_WORK(&conn->work, add_conn, (void *) conn);
+
+       schedule_work(&conn->work);
+}
+
+static void del_conn(void *data)
+{
+       struct hci_conn *conn = data;
+       device_del(&conn->dev);
+}
+
+void hci_conn_del_sysfs(struct hci_conn *conn)
+{
+       BT_DBG("conn %p", conn);
+
+       INIT_WORK(&conn->work, del_conn, (void *) conn);
+
+       schedule_work(&conn->work);
 }
 
 int hci_register_sysfs(struct hci_dev *hdev)
@@ -214,11 +319,9 @@ int hci_register_sysfs(struct hci_dev *hdev)
 
 void hci_unregister_sysfs(struct hci_dev *hdev)
 {
-       struct device *dev = &hdev->dev;
-
        BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-       device_del(dev);
+       device_del(&hdev->dev);
 }
 
 int __init bt_sysfs_init(void)
@@ -245,7 +348,7 @@ int __init bt_sysfs_init(void)
        return 0;
 }
 
-void __exit bt_sysfs_cleanup(void)
+void bt_sysfs_cleanup(void)
 {
        class_destroy(bt_class);
 
index c6e3a2c27c6ecc864dfa85153b1b42f557957f69..03b5dadb49511f90b0c57ee6d9d677d580c5ef18 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/input.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "hidp.h"
@@ -528,6 +529,26 @@ static int hidp_session(void *arg)
        return 0;
 }
 
+static struct device *hidp_get_device(struct hidp_session *session)
+{
+       bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
+       bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(dst, src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+       if (!conn)
+               return NULL;
+
+       hci_dev_put(hdev);
+
+       return &conn->dev;
+}
+
 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
 {
        struct input_dev *input = session->input;
@@ -566,6 +587,8 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
                input->relbit[0] |= BIT(REL_WHEEL);
        }
 
+       input->cdev.dev = hidp_get_device(session);
+
        input->event = hidp_input_event;
 
        input_register_device(input);
index 332dd8f436ea0a2957df07db7d7b4aedcffa888f..468df3b953f6d3c615169a0939e50ec924eb1af8 100644 (file)
@@ -644,7 +644,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = htobs(RFCOMM_PSM);
        *err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
-       if (*err == 0 || *err == -EAGAIN)
+       if (*err == 0 || *err == -EINPROGRESS)
                return s;
 
        rfcomm_session_del(s);
index bd8d671a0ba6f1622ee54e463c2d393b0a6a8943..26f322737db0c83702267b25190dca8fa925c324 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/skbuff.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/rfcomm.h>
 
 #ifndef CONFIG_BT_RFCOMM_DEBUG
@@ -161,6 +162,24 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
        return dev;
 }
 
+static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
+{
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(&dev->dst, &dev->src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
+       if (!conn)
+               return NULL;
+
+       hci_dev_put(hdev);
+
+       return &conn->dev;
+}
+
 static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 {
        struct rfcomm_dev *dev;
@@ -244,7 +263,7 @@ out:
                return err;
        }
 
-       tty_register_device(rfcomm_tty_driver, dev->id, NULL);
+       tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev));
 
        return dev->id;
 }
index d19fc4b328dcfa481f9d982a830172c1e3cd1582..0aa7b9910a86159a66043ba819298a02f6b917f1 100644 (file)
@@ -20,7 +20,7 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
    const void *data, unsigned int datalen)
 {
        struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
-       u32 _sip, *siptr, _dip, *diptr;
+       __be32 _sip, *siptr, _dip, *diptr;
        struct arphdr _ah, *ap;
        unsigned char _sha[ETH_ALEN], *shp;
        struct sk_buff *skb = *pskb;
index 14de297d024d1e8771180dde2e07aec624b90e1c..4d891beab13899cd96c74b8a6a88b5ef5d6aba43 100644 (file)
@@ -1480,14 +1480,16 @@ gso:
        if (q->enqueue) {
                /* Grab device queue */
                spin_lock(&dev->queue_lock);
+               q = dev->qdisc;
+               if (q->enqueue) {
+                       rc = q->enqueue(skb, q);
+                       qdisc_run(dev);
+                       spin_unlock(&dev->queue_lock);
 
-               rc = q->enqueue(skb, q);
-
-               qdisc_run(dev);
-
+                       rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
+                       goto out;
+               }
                spin_unlock(&dev->queue_lock);
-               rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
-               goto out;
        }
 
        /* The device has no queue. Common case for software devices:
index e0ca04f38cef3d7058e4ffe548e9b2aa85f92f47..87dc556fd9d6c694f65e33c6868aebdeef8325cc 100644 (file)
@@ -806,13 +806,6 @@ int dev_ethtool(struct ifreq *ifr)
        int rc;
        unsigned long old_features;
 
-       /*
-        * XXX: This can be pushed down into the ethtool_* handlers that
-        * need it.  Keep existing behaviour for the moment.
-        */
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-
        if (!dev || !netif_device_present(dev))
                return -ENODEV;
 
@@ -822,6 +815,27 @@ int dev_ethtool(struct ifreq *ifr)
        if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
                return -EFAULT;
 
+       /* Allow some commands to be done by anyone */
+       switch(ethcmd) {
+       case ETHTOOL_GDRVINFO:
+       case ETHTOOL_GMSGLVL:
+       case ETHTOOL_GCOALESCE:
+       case ETHTOOL_GRINGPARAM:
+       case ETHTOOL_GPAUSEPARAM:
+       case ETHTOOL_GRXCSUM:
+       case ETHTOOL_GTXCSUM:
+       case ETHTOOL_GSG:
+       case ETHTOOL_GSTRINGS:
+       case ETHTOOL_GTSO:
+       case ETHTOOL_GPERMADDR:
+       case ETHTOOL_GUFO:
+       case ETHTOOL_GGSO:
+               break;
+       default:
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+       }
+
        if(dev->ethtool_ops->begin)
                if ((rc = dev->ethtool_ops->begin(dev)) < 0)
                        return rc;
@@ -947,6 +961,10 @@ int dev_ethtool(struct ifreq *ifr)
        return rc;
 
  ioctl:
+       /* Keep existing behaviour for the moment.       */
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (dev->do_ioctl)
                return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
        return -EOPNOTSUPP;
index b6c69e1463e87f0dc756022ade88e52e4062dea0..8ce8c471d8687427ad2b88acf5d33a17a874bbbc 100644 (file)
@@ -1079,7 +1079,7 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 }
 
 static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
-                         u16 protocol)
+                         __be16 protocol)
 {
        struct hh_cache *hh;
        struct net_device *dev = dst->dev;
index 13472762b18b4c89f57c7bb27916bd8b67b47339..f47f319bb7dc2ae78b02e5f97f2d84519e686710 100644 (file)
@@ -344,8 +344,6 @@ static ssize_t wireless_show(struct class_device *cd, char *buf,
                if(dev->wireless_handlers &&
                   dev->wireless_handlers->get_wireless_stats)
                        iw = dev->wireless_handlers->get_wireless_stats(dev);
-               else if (dev->get_wireless_stats)
-                       iw = dev->get_wireless_stats(dev);
                if (iw != NULL)
                        ret = (*format)(iw, buf);
        }
@@ -465,8 +463,7 @@ int netdev_register_sysfs(struct net_device *net)
                *groups++ = &netstat_group;
 
 #ifdef WIRELESS_EXT
-       if (net->get_wireless_stats
-           || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
+       if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
                *groups++ = &wireless_group;
 #endif
 
index 72145d4a260082fc6e798522e95052a36f1643c6..dd023fd2830409475f42b8cd8ccb7fb16cd03aa2 100644 (file)
  *
  * MPLS support by Steven Whitehouse <steve@chygwyn.com>
  *
+ * 802.1Q/Q-in-Q support by Francesco Fondelli (FF) <francesco.fondelli@gmail.com>
+ *
  */
 #include <linux/sys.h>
 #include <linux/types.h>
 #include <linux/inetdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_arp.h>
+#include <linux/if_vlan.h>
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <asm/div64.h>         /* do_div */
 #include <asm/timex.h>
 
-#define VERSION  "pktgen v2.67: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.68: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a)
 #define F_TXSIZE_RND  (1<<6)   /* Transmit size is random */
 #define F_IPV6        (1<<7)   /* Interface in IPV6 Mode */
 #define F_MPLS_RND    (1<<8)   /* Random MPLS labels */
+#define F_VID_RND     (1<<9)   /* Random VLAN ID */
+#define F_SVID_RND    (1<<10)  /* Random SVLAN ID */
 
 /* Thread control flag bits */
 #define T_TERMINATE   (1<<0)
@@ -198,6 +203,9 @@ static struct proc_dir_entry *pg_proc_dir = NULL;
 
 #define MAX_CFLOWS  65536
 
+#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
+#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
+
 struct flow_state {
        __u32 cur_daddr;
        int count;
@@ -284,10 +292,23 @@ struct pktgen_dev {
        __u16 udp_dst_min;      /* inclusive, dest UDP port */
        __u16 udp_dst_max;      /* exclusive, dest UDP port */
 
+       /* DSCP + ECN */
+       __u8 tos;            /* six most significant bits of (former) IPv4 TOS are for dscp codepoint */
+       __u8 traffic_class;  /* ditto for the (former) Traffic Class in IPv6 (see RFC 3260, sec. 4) */
+
        /* MPLS */
        unsigned nr_labels;     /* Depth of stack, 0 = no MPLS */
        __be32 labels[MAX_MPLS_LABELS];
 
+       /* VLAN/SVLAN (802.1Q/Q-in-Q) */
+       __u8  vlan_p;
+       __u8  vlan_cfi;
+       __u16 vlan_id;  /* 0xffff means no vlan tag */
+
+       __u8  svlan_p;
+       __u8  svlan_cfi;
+       __u16 svlan_id; /* 0xffff means no svlan tag */
+
        __u32 src_mac_count;    /* How many MACs to iterate through */
        __u32 dst_mac_count;    /* How many MACs to iterate through */
 
@@ -644,6 +665,24 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
                                   i == pkt_dev->nr_labels-1 ? "\n" : ", ");
        }
 
+       if (pkt_dev->vlan_id != 0xffff) {
+               seq_printf(seq, "     vlan_id: %u  vlan_p: %u  vlan_cfi: %u\n",
+                          pkt_dev->vlan_id, pkt_dev->vlan_p, pkt_dev->vlan_cfi);
+       }
+
+       if (pkt_dev->svlan_id != 0xffff) {
+               seq_printf(seq, "     svlan_id: %u  vlan_p: %u  vlan_cfi: %u\n",
+                          pkt_dev->svlan_id, pkt_dev->svlan_p, pkt_dev->svlan_cfi);
+       }
+
+       if (pkt_dev->tos) {
+               seq_printf(seq, "     tos: 0x%02x\n", pkt_dev->tos);
+       }
+
+       if (pkt_dev->traffic_class) {
+               seq_printf(seq, "     traffic_class: 0x%02x\n", pkt_dev->traffic_class);
+       }
+
        seq_printf(seq, "     Flags: ");
 
        if (pkt_dev->flags & F_IPV6)
@@ -673,6 +712,12 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
        if (pkt_dev->flags & F_MACDST_RND)
                seq_printf(seq, "MACDST_RND  ");
 
+       if (pkt_dev->flags & F_VID_RND)
+               seq_printf(seq, "VID_RND  ");
+
+       if (pkt_dev->flags & F_SVID_RND)
+               seq_printf(seq, "SVID_RND  ");
+
        seq_puts(seq, "\n");
 
        sa = pkt_dev->started_at;
@@ -715,12 +760,12 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
 }
 
 
-static int hex32_arg(const char __user *user_buffer, __u32 *num)
+static int hex32_arg(const char __user *user_buffer, unsigned long maxlen, __u32 *num)
 {
        int i = 0;
        *num = 0;
 
-       for(; i < 8; i++) {
+       for(; i < maxlen; i++) {
                char c;
                *num <<= 4;
                if (get_user(c, &user_buffer[i]))
@@ -815,7 +860,7 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
        pkt_dev->nr_labels = 0;
        do {
                __u32 tmp;
-               len = hex32_arg(&buffer[i], &tmp);
+               len = hex32_arg(&buffer[i], 8, &tmp);
                if (len <= 0)
                        return len;
                pkt_dev->labels[n] = htonl(tmp);
@@ -1140,11 +1185,27 @@ static ssize_t pktgen_if_write(struct file *file,
                else if (strcmp(f, "!MPLS_RND") == 0)
                        pkt_dev->flags &= ~F_MPLS_RND;
 
+               else if (strcmp(f, "VID_RND") == 0)
+                       pkt_dev->flags |= F_VID_RND;
+
+               else if (strcmp(f, "!VID_RND") == 0)
+                       pkt_dev->flags &= ~F_VID_RND;
+
+               else if (strcmp(f, "SVID_RND") == 0)
+                       pkt_dev->flags |= F_SVID_RND;
+
+               else if (strcmp(f, "!SVID_RND") == 0)
+                       pkt_dev->flags &= ~F_SVID_RND;
+
+               else if (strcmp(f, "!IPV6") == 0)
+                       pkt_dev->flags &= ~F_IPV6;
+
                else {
                        sprintf(pg_result,
                                "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
                                f,
-                               "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
+                               "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, "
+                               "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n");
                        return count;
                }
                sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
@@ -1445,6 +1506,160 @@ static ssize_t pktgen_if_write(struct file *file,
                        offset += sprintf(pg_result + offset,
                                          "%08x%s", ntohl(pkt_dev->labels[n]),
                                          n == pkt_dev->nr_labels-1 ? "" : ",");
+
+               if (pkt_dev->nr_labels && pkt_dev->vlan_id != 0xffff) {
+                       pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
+                       pkt_dev->svlan_id = 0xffff;
+
+                       if (debug)
+                               printk("pktgen: VLAN/SVLAN auto turned off\n");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "vlan_id")) {
+               len = num_arg(&user_buffer[i], 4, &value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if (value <= 4095) {
+                       pkt_dev->vlan_id = value;  /* turn on VLAN */
+
+                       if (debug)
+                               printk("pktgen: VLAN turned on\n");
+
+                       if (debug && pkt_dev->nr_labels)
+                               printk("pktgen: MPLS auto turned off\n");
+
+                       pkt_dev->nr_labels = 0;    /* turn off MPLS */
+                       sprintf(pg_result, "OK: vlan_id=%u", pkt_dev->vlan_id);
+               } else {
+                       pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
+                       pkt_dev->svlan_id = 0xffff;
+
+                       if (debug)
+                               printk("pktgen: VLAN/SVLAN turned off\n");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "vlan_p")) {
+               len = num_arg(&user_buffer[i], 1, &value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if ((value <= 7) && (pkt_dev->vlan_id != 0xffff)) {
+                       pkt_dev->vlan_p = value;
+                       sprintf(pg_result, "OK: vlan_p=%u", pkt_dev->vlan_p);
+               } else {
+                       sprintf(pg_result, "ERROR: vlan_p must be 0-7");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "vlan_cfi")) {
+               len = num_arg(&user_buffer[i], 1, &value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if ((value <= 1) && (pkt_dev->vlan_id != 0xffff)) {
+                       pkt_dev->vlan_cfi = value;
+                       sprintf(pg_result, "OK: vlan_cfi=%u", pkt_dev->vlan_cfi);
+               } else {
+                       sprintf(pg_result, "ERROR: vlan_cfi must be 0-1");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "svlan_id")) {
+               len = num_arg(&user_buffer[i], 4, &value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if ((value <= 4095) && ((pkt_dev->vlan_id != 0xffff))) {
+                       pkt_dev->svlan_id = value;  /* turn on SVLAN */
+
+                       if (debug)
+                               printk("pktgen: SVLAN turned on\n");
+
+                       if (debug && pkt_dev->nr_labels)
+                               printk("pktgen: MPLS auto turned off\n");
+
+                       pkt_dev->nr_labels = 0;    /* turn off MPLS */
+                       sprintf(pg_result, "OK: svlan_id=%u", pkt_dev->svlan_id);
+               } else {
+                       pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
+                       pkt_dev->svlan_id = 0xffff;
+
+                       if (debug)
+                               printk("pktgen: VLAN/SVLAN turned off\n");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "svlan_p")) {
+               len = num_arg(&user_buffer[i], 1, &value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if ((value <= 7) && (pkt_dev->svlan_id != 0xffff)) {
+                       pkt_dev->svlan_p = value;
+                       sprintf(pg_result, "OK: svlan_p=%u", pkt_dev->svlan_p);
+               } else {
+                       sprintf(pg_result, "ERROR: svlan_p must be 0-7");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "svlan_cfi")) {
+               len = num_arg(&user_buffer[i], 1, &value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if ((value <= 1) && (pkt_dev->svlan_id != 0xffff)) {
+                       pkt_dev->svlan_cfi = value;
+                       sprintf(pg_result, "OK: svlan_cfi=%u", pkt_dev->svlan_cfi);
+               } else {
+                       sprintf(pg_result, "ERROR: svlan_cfi must be 0-1");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "tos")) {
+               __u32 tmp_value = 0;
+               len = hex32_arg(&user_buffer[i], 2, &tmp_value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if (len == 2) {
+                       pkt_dev->tos = tmp_value;
+                       sprintf(pg_result, "OK: tos=0x%02x", pkt_dev->tos);
+               } else {
+                       sprintf(pg_result, "ERROR: tos must be 00-ff");
+               }
+               return count;
+       }
+
+       if (!strcmp(name, "traffic_class")) {
+               __u32 tmp_value = 0;
+               len = hex32_arg(&user_buffer[i], 2, &tmp_value);
+               if (len < 0) {
+                       return len;
+               }
+               i += len;
+               if (len == 2) {
+                       pkt_dev->traffic_class = tmp_value;
+                       sprintf(pg_result, "OK: traffic_class=0x%02x", pkt_dev->traffic_class);
+               } else {
+                       sprintf(pg_result, "ERROR: traffic_class must be 00-ff");
+               }
                return count;
        }
 
@@ -1949,6 +2164,14 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                                                      htonl(0x000fffff));
        }
 
+       if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) {
+               pkt_dev->vlan_id = pktgen_random() % 4096;
+       }
+
+       if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) {
+               pkt_dev->svlan_id = pktgen_random() % 4096;
+       }
+
        if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
                if (pkt_dev->flags & F_UDPSRC_RND)
                        pkt_dev->cur_udp_src =
@@ -2092,10 +2315,18 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        struct pktgen_hdr *pgh = NULL;
        __be16 protocol = __constant_htons(ETH_P_IP);
        __be32 *mpls;
+       __be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
+       __be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
+       __be16 *svlan_tci = NULL;                /* Encapsulates priority and SVLAN ID */
+       __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
+
 
        if (pkt_dev->nr_labels)
                protocol = __constant_htons(ETH_P_MPLS_UC);
 
+       if (pkt_dev->vlan_id != 0xffff)
+               protocol = __constant_htons(ETH_P_8021Q);
+
        /* Update any of the values, used when we're incrementing various
         * fields.
         */
@@ -2103,7 +2334,9 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 
        datalen = (odev->hard_header_len + 16) & ~0xf;
        skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
-                       pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
+                       pkt_dev->nr_labels*sizeof(u32) +
+                       VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
+                       GFP_ATOMIC);
        if (!skb) {
                sprintf(pkt_dev->result, "No memory");
                return NULL;
@@ -2116,6 +2349,24 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
        if (pkt_dev->nr_labels)
                mpls_push(mpls, pkt_dev);
+
+       if (pkt_dev->vlan_id != 0xffff) {
+               if(pkt_dev->svlan_id != 0xffff) {
+                       svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+                       *svlan_tci = htons(pkt_dev->svlan_id);
+                       *svlan_tci |= pkt_dev->svlan_p << 5;
+                       *svlan_tci |= pkt_dev->svlan_cfi << 4;
+                       svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+                       *svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
+               }
+               vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+               *vlan_tci = htons(pkt_dev->vlan_id);
+               *vlan_tci |= pkt_dev->vlan_p << 5;
+               *vlan_tci |= pkt_dev->vlan_cfi << 4;
+               vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+               *vlan_encapsulated_proto = __constant_htons(ETH_P_IP);
+       }
+
        iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
        udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
@@ -2124,7 +2375,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 
        /* Eth + IPh + UDPh + mpls */
        datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
-                 pkt_dev->nr_labels*sizeof(u32);
+                 pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
        if (datalen < sizeof(struct pktgen_hdr))
                datalen = sizeof(struct pktgen_hdr);
 
@@ -2136,7 +2387,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        iph->ihl = 5;
        iph->version = 4;
        iph->ttl = 32;
-       iph->tos = 0;
+       iph->tos = pkt_dev->tos;
        iph->protocol = IPPROTO_UDP;    /* UDP */
        iph->saddr = pkt_dev->cur_saddr;
        iph->daddr = pkt_dev->cur_daddr;
@@ -2146,7 +2397,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        iph->check = 0;
        iph->check = ip_fast_csum((void *)iph, iph->ihl);
        skb->protocol = protocol;
-       skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
+       skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32) -
+               VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
        skb->nh.iph = iph;
@@ -2218,7 +2470,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
                pgh->tv_sec = htonl(timestamp.tv_sec);
                pgh->tv_usec = htonl(timestamp.tv_usec);
        }
-       pkt_dev->seq_num++;
 
        return skb;
 }
@@ -2402,17 +2653,26 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        struct pktgen_hdr *pgh = NULL;
        __be16 protocol = __constant_htons(ETH_P_IPV6);
        __be32 *mpls;
+       __be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
+       __be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
+       __be16 *svlan_tci = NULL;                /* Encapsulates priority and SVLAN ID */
+       __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
 
        if (pkt_dev->nr_labels)
                protocol = __constant_htons(ETH_P_MPLS_UC);
 
+       if (pkt_dev->vlan_id != 0xffff)
+               protocol = __constant_htons(ETH_P_8021Q);
+
        /* Update any of the values, used when we're incrementing various
         * fields.
         */
        mod_cur_headers(pkt_dev);
 
        skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
-                       pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
+                       pkt_dev->nr_labels*sizeof(u32) +
+                       VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
+                       GFP_ATOMIC);
        if (!skb) {
                sprintf(pkt_dev->result, "No memory");
                return NULL;
@@ -2425,16 +2685,34 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
        if (pkt_dev->nr_labels)
                mpls_push(mpls, pkt_dev);
+
+       if (pkt_dev->vlan_id != 0xffff) {
+               if(pkt_dev->svlan_id != 0xffff) {
+                       svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+                       *svlan_tci = htons(pkt_dev->svlan_id);
+                       *svlan_tci |= pkt_dev->svlan_p << 5;
+                       *svlan_tci |= pkt_dev->svlan_cfi << 4;
+                       svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+                       *svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
+               }
+               vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
+               *vlan_tci = htons(pkt_dev->vlan_id);
+               *vlan_tci |= pkt_dev->vlan_p << 5;
+               *vlan_tci |= pkt_dev->vlan_cfi << 4;
+               vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
+               *vlan_encapsulated_proto = __constant_htons(ETH_P_IPV6);
+       }
+
        iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
        udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
        memcpy(eth, pkt_dev->hh, 12);
-       *(u16 *) & eth[12] = __constant_htons(ETH_P_IPV6);
+       *(u16 *) & eth[12] = protocol;
 
        /* Eth + IPh + UDPh + mpls */
        datalen = pkt_dev->cur_pkt_size - 14 -
                  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
-                 pkt_dev->nr_labels*sizeof(u32);
+                 pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
 
        if (datalen < sizeof(struct pktgen_hdr)) {
                datalen = sizeof(struct pktgen_hdr);
@@ -2450,6 +2728,11 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 
        *(u32 *) iph = __constant_htonl(0x60000000);    /* Version + flow */
 
+       if (pkt_dev->traffic_class) {
+               /* Version + traffic class + flow (0) */
+               *(u32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20));
+       }
+
        iph->hop_limit = 32;
 
        iph->payload_len = htons(sizeof(struct udphdr) + datalen);
@@ -2458,7 +2741,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
        ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
 
-       skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
+       skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32) -
+               VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
        skb->protocol = protocol;
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
@@ -2531,7 +2815,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                pgh->tv_sec = htonl(timestamp.tv_sec);
                pgh->tv_usec = htonl(timestamp.tv_usec);
        }
-       pkt_dev->seq_num++;
+       /* pkt_dev->seq_num++; FF: you really mean this? */
 
        return skb;
 }
@@ -3177,6 +3461,13 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
        pkt_dev->udp_dst_min = 9;
        pkt_dev->udp_dst_max = 9;
 
+       pkt_dev->vlan_p = 0;
+       pkt_dev->vlan_cfi = 0;
+       pkt_dev->vlan_id = 0xffff;
+       pkt_dev->svlan_p = 0;
+       pkt_dev->svlan_cfi = 0;
+       pkt_dev->svlan_id = 0xffff;
+
        strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
 
        if (!pktgen_setup_dev(pkt_dev)) {
index d8e25e08cb7e7b725b3cc5cfb6e34cdf67a11532..221e4038216b8da1e61a67b32087eb146b02af3c 100644 (file)
@@ -562,7 +562,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
        if (err < 0)
-               goto errout;
+               return err;
 
        ifm = nlmsg_data(nlh);
        if (ifm->ifi_index >= 0) {
index 2682490777dec6ceea515596d11f6c7117910147..94c5d761c830e3a156501b9e0320ec16929d5564 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Authors:
  *     net_random Alan Cox
- *     net_ratelimit Andy Kleen
+ *     net_ratelimit Andi Kleen
  *     in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project
  *
  *     Created by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
index 3168fca312f7c4d188dd9162f8b3dd43942692b3..ffff0da46c6ee2a3703a9f3116eab0162b4727e6 100644 (file)
  *
  * v8 - 17.02.06 - Jean II
  *     o RtNetlink requests support (SET/GET)
+ *
+ * v8b - 03.08.06 - Herbert Xu
+ *     o Fix Wireless Event locking issues.
+ *
+ * v9 - 14.3.06 - Jean II
+ *     o Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *     o Make standard_ioctl_num and standard_event_num unsigned
+ *     o Remove (struct net_device *)->get_wireless_stats()
  */
 
 /***************************** INCLUDES *****************************/
@@ -234,24 +242,24 @@ static const struct iw_ioctl_description standard_ioctl[] = {
        [SIOCSIWESSID   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
                .flags          = IW_DESCR_FLAG_EVENT,
        },
        [SIOCGIWESSID   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
                .flags          = IW_DESCR_FLAG_DUMP,
        },
        [SIOCSIWNICKN   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
        },
        [SIOCGIWNICKN   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
        },
        [SIOCSIWRATE    - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_PARAM,
@@ -338,8 +346,8 @@ static const struct iw_ioctl_description standard_ioctl[] = {
                .max_tokens     = sizeof(struct iw_pmksa),
        },
 };
-static const int standard_ioctl_num = (sizeof(standard_ioctl) /
-                                      sizeof(struct iw_ioctl_description));
+static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) /
+                                           sizeof(struct iw_ioctl_description));
 
 /*
  * Meta-data about all the additional standard Wireless Extension events
@@ -389,8 +397,8 @@ static const struct iw_ioctl_description standard_event[] = {
                .max_tokens     = sizeof(struct iw_pmkid_cand),
        },
 };
-static const int standard_event_num = (sizeof(standard_event) /
-                                      sizeof(struct iw_ioctl_description));
+static const unsigned standard_event_num = (sizeof(standard_event) /
+                                           sizeof(struct iw_ioctl_description));
 
 /* Size (in bytes) of the various private data types */
 static const char iw_priv_type_size[] = {
@@ -465,17 +473,6 @@ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
           (dev->wireless_handlers->get_wireless_stats != NULL))
                return dev->wireless_handlers->get_wireless_stats(dev);
 
-       /* Old location, field to be removed in next WE */
-       if(dev->get_wireless_stats) {
-               static int printed_message;
-
-               if (!printed_message++)
-                       printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
-                               dev->name);
-
-               return dev->get_wireless_stats(dev);
-       }
-
        /* Not found */
        return (struct iw_statistics *) NULL;
 }
@@ -1843,8 +1840,33 @@ int wireless_rtnetlink_set(struct net_device *   dev,
  */
 
 #ifdef WE_EVENT_RTNETLINK
+/* ---------------------------------------------------------------- */
+/*
+ * Locking...
+ * ----------
+ *
+ * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
+ * the locking issue in here and implementing this code !
+ *
+ * The issue : wireless_send_event() is often called in interrupt context,
+ * while the Netlink layer can never be called in interrupt context.
+ * The fully formed RtNetlink events are queued, and then a tasklet is run
+ * to feed those to Netlink.
+ * The skb_queue is interrupt safe, and its lock is not held while calling
+ * Netlink, so there is no possibility of dealock.
+ * Jean II
+ */
+
 static struct sk_buff_head wireless_nlevent_queue;
 
+static int __init wireless_nlevent_init(void)
+{
+       skb_queue_head_init(&wireless_nlevent_queue);
+       return 0;
+}
+
+subsys_initcall(wireless_nlevent_init);
+
 static void wireless_nlevent_process(unsigned long data)
 {
        struct sk_buff *skb;
@@ -1921,13 +1943,6 @@ static inline void rtmsg_iwinfo(struct net_device *      dev,
        tasklet_schedule(&wireless_nlevent_tasklet);
 }
 
-static int __init wireless_nlevent_init(void)
-{
-       skb_queue_head_init(&wireless_nlevent_queue);
-       return 0;
-}
-
-subsys_initcall(wireless_nlevent_init);
 #endif /* WE_EVENT_RTNETLINK */
 
 /* ---------------------------------------------------------------- */
index 66be29b6f508484b180fecf63356d09667bc90c1..bf692c1c116f69a1384d7124c03212ee2d504ebb 100644 (file)
@@ -50,7 +50,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct dccp_sock *dp = dccp_sk(sk);
        const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
        struct rtable *rt;
-       u32 daddr, nexthop;
+       __be32 daddr, nexthop;
        int tmp;
        int err;
 
index 43863933f27f92dc0c6f09556dfee953fab08704..4bd78c8cfb26fe9f229813613a14b0548de3a4d1 100644 (file)
@@ -223,7 +223,7 @@ static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
  */
 int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
 {
-       unsigned short type = hh->hh_type;
+       __be16 type = hh->hh_type;
        struct ethhdr *eth;
        struct net_device *dev = neigh->dev;
 
index 75320b6842ab59e0bbd7d4d160249585ff649e39..2aa779d18f3861a2f6f2119f99c89c6c2c56b583 100644 (file)
@@ -80,10 +80,10 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
         * If it's our network, ignore the change, we're already doing it!
         */
        if((sm->associnfo.associating || sm->associated) &&
-          (data->essid.flags && data->essid.length && extra)) {
+          (data->essid.flags && data->essid.length)) {
                /* Get the associating network */
                n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
-               if(n && n->essid.len == (data->essid.length - 1) &&
+               if(n && n->essid.len == data->essid.length &&
                   !memcmp(n->essid.data, extra, n->essid.len)) {
                        dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
                                MAC_ARG(sm->associnfo.bssid));
@@ -109,8 +109,8 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
        sm->associnfo.static_essid = 0;
        sm->associnfo.assoc_wait = 0;
 
-       if (data->essid.flags && data->essid.length && extra /*required?*/) {
-               length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
+       if (data->essid.flags && data->essid.length) {
+               length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
                if (length) {
                        memcpy(sm->associnfo.req_essid.data, extra, length);
                        sm->associnfo.static_essid = 1;
index fdd89e37b9aaccfd17532352822b3140a6b61578..edcf0932ac6de06a96c0dc9699d662cf5539a140 100644 (file)
@@ -996,7 +996,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
        struct rtable *rt;
        __u32 old_saddr = inet->saddr;
        __u32 new_saddr;
-       __u32 daddr = inet->daddr;
+       __be32 daddr = inet->daddr;
 
        if (inet->opt && inet->opt->srr)
                daddr = inet->opt->faddr;
@@ -1043,7 +1043,7 @@ int inet_sk_rebuild_header(struct sock *sk)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
-       u32 daddr;
+       __be32 daddr;
        int err;
 
        /* Route is OK, nothing to do. */
@@ -1342,10 +1342,10 @@ static int __init inet_init(void)
        rc = 0;
 out:
        return rc;
-out_unregister_tcp_proto:
-       proto_unregister(&tcp_prot);
 out_unregister_udp_proto:
        proto_unregister(&udp_prot);
+out_unregister_tcp_proto:
+       proto_unregister(&tcp_prot);
        goto out;
 }
 
index c8a3723bc001b0a744d382a4a353c2c902a28ddd..cfe5c84742865c56c0e6b40702bdf54b14f4f752 100644 (file)
@@ -234,7 +234,7 @@ static u32 arp_hash(const void *pkey, const struct net_device *dev)
 
 static int arp_constructor(struct neighbour *neigh)
 {
-       u32 addr = *(u32*)neigh->primary_key;
+       __be32 addr = *(__be32*)neigh->primary_key;
        struct net_device *dev = neigh->dev;
        struct in_device *in_dev;
        struct neigh_parms *parms;
@@ -330,10 +330,10 @@ static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb)
 
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-       u32 saddr = 0;
+       __be32 saddr = 0;
        u8  *dst_ha = NULL;
        struct net_device *dev = neigh->dev;
-       u32 target = *(u32*)neigh->primary_key;
+       __be32 target = *(__be32*)neigh->primary_key;
        int probes = atomic_read(&neigh->probes);
        struct in_device *in_dev = in_dev_get(dev);
 
@@ -385,7 +385,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 }
 
 static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
-                     u32 sip, u32 tip)
+                     __be32 sip, __be32 tip)
 {
        int scope;
 
@@ -420,7 +420,7 @@ static int arp_ignore(struct in_device *in_dev, struct net_device *dev,
        return !inet_confirm_addr(dev, sip, tip, scope);
 }
 
-static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
+static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
 {
        struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip,
                                                 .saddr = tip } } };
@@ -449,7 +449,7 @@ static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
  *     is allowed to use this function, it is scheduled to be removed. --ANK
  */
 
-static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct net_device * dev)
+static int arp_set_predefined(int addr_hint, unsigned char * haddr, __be32 paddr, struct net_device * dev)
 {
        switch (addr_hint) {
        case RTN_LOCAL:
@@ -470,7 +470,7 @@ static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, s
 int arp_find(unsigned char *haddr, struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
-       u32 paddr;
+       __be32 paddr;
        struct neighbour *n;
 
        if (!skb->dst) {
@@ -511,7 +511,7 @@ int arp_bind_neighbour(struct dst_entry *dst)
        if (dev == NULL)
                return -EINVAL;
        if (n == NULL) {
-               u32 nexthop = ((struct rtable*)dst)->rt_gateway;
+               __be32 nexthop = ((struct rtable*)dst)->rt_gateway;
                if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
                        nexthop = 0;
                n = __neigh_lookup_errno(
@@ -560,8 +560,8 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt)
  *     Create an arp packet. If (dest_hw == NULL), we create a broadcast
  *     message.
  */
-struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
-                          struct net_device *dev, u32 src_ip,
+struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+                          struct net_device *dev, __be32 src_ip,
                           unsigned char *dest_hw, unsigned char *src_hw,
                           unsigned char *target_hw)
 {
@@ -675,8 +675,8 @@ void arp_xmit(struct sk_buff *skb)
 /*
  *     Create and send an arp packet.
  */
-void arp_send(int type, int ptype, u32 dest_ip, 
-             struct net_device *dev, u32 src_ip, 
+void arp_send(int type, int ptype, __be32 dest_ip,
+             struct net_device *dev, __be32 src_ip,
              unsigned char *dest_hw, unsigned char *src_hw,
              unsigned char *target_hw)
 {
@@ -710,7 +710,7 @@ static int arp_process(struct sk_buff *skb)
        unsigned char *arp_ptr;
        struct rtable *rt;
        unsigned char *sha, *tha;
-       u32 sip, tip;
+       __be32 sip, tip;
        u16 dev_type = dev->type;
        int addr_type;
        struct neighbour *n;
@@ -969,13 +969,13 @@ out_of_mem:
 
 static int arp_req_set(struct arpreq *r, struct net_device * dev)
 {
-       u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+       __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
        struct neighbour *neigh;
        int err;
 
        if (r->arp_flags&ATF_PUBL) {
-               u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
-               if (mask && mask != 0xFFFFFFFF)
+               __be32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
+               if (mask && mask != htonl(0xFFFFFFFF))
                        return -EINVAL;
                if (!dev && (r->arp_flags & ATF_COM)) {
                        dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data);
@@ -1063,7 +1063,7 @@ static unsigned arp_state_to_flags(struct neighbour *neigh)
 
 static int arp_req_get(struct arpreq *r, struct net_device *dev)
 {
-       u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+       __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
        struct neighbour *neigh;
        int err = -ENXIO;
 
@@ -1084,13 +1084,13 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
 static int arp_req_delete(struct arpreq *r, struct net_device * dev)
 {
        int err;
-       u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
+       __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
        struct neighbour *neigh;
 
        if (r->arp_flags & ATF_PUBL) {
-               u32 mask =
+               __be32 mask =
                       ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;
-               if (mask == 0xFFFFFFFF)
+               if (mask == htonl(0xFFFFFFFF))
                        return pneigh_delete(&arp_tbl, &ip, dev);
                if (mask == 0) {
                        if (dev == NULL) {
index e6ce0b3ba62a49ed8aef7ae0c6f4541a67a3d53d..a8e2e879a64764c31bbcc2626cb6779a5aba04fb 100644 (file)
@@ -474,6 +474,7 @@ doi_add_failure_rlock:
 /**
  * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
  * @doi: the DOI value
+ * @audit_secid: the LSM secid to use in the audit message
  * @callback: the DOI cleanup/free callback
  *
  * Description:
@@ -483,7 +484,9 @@ doi_add_failure_rlock:
  * success and negative values on failure.
  *
  */
-int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head))
+int cipso_v4_doi_remove(u32 doi,
+                       struct netlbl_audit *audit_info,
+                       void (*callback) (struct rcu_head * head))
 {
        struct cipso_v4_doi *doi_def;
        struct cipso_v4_domhsh_entry *dom_iter;
@@ -502,7 +505,8 @@ int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head))
                spin_unlock(&cipso_v4_doi_list_lock);
                list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
                        if (dom_iter->valid)
-                               netlbl_domhsh_remove(dom_iter->domain);
+                               netlbl_domhsh_remove(dom_iter->domain,
+                                                    audit_info);
                cipso_v4_cache_invalidate();
                rcu_read_unlock();
 
index ec5da4fbd9f43d84fd961de6e855455591e49311..7b068a891953aae4d9e377438319815c3439259b 100644 (file)
@@ -25,7 +25,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct inet_sock *inet = inet_sk(sk);
        struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
        struct rtable *rt;
-       u32 saddr;
+       __be32 saddr;
        int oif;
        int err;
 
index 8e8d1f17d77a7c29009fbcbc760a290259d5afc2..7602c79a389bece923dc5dfd8b00b524690d8d85 100644 (file)
@@ -224,7 +224,7 @@ static void inetdev_destroy(struct in_device *in_dev)
        call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
 }
 
-int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
+int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
 {
        rcu_read_lock();
        for_primary_ifa(in_dev) {
@@ -429,8 +429,8 @@ struct in_device *inetdev_by_index(int ifindex)
 
 /* Called only from RTNL semaphored context. No locks. */
 
-struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix,
-                                   u32 mask)
+struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
+                                   __be32 mask)
 {
        ASSERT_RTNL();
 
@@ -467,7 +467,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
             ifap = &ifa->ifa_next) {
                if (tb[IFA_LOCAL] &&
-                   ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL]))
+                   ifa->ifa_local != nla_get_be32(tb[IFA_LOCAL]))
                        continue;
 
                if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
@@ -475,7 +475,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
 
                if (tb[IFA_ADDRESS] &&
                    (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
-                   !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa)))
+                   !inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa)))
                        continue;
 
                __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid);
@@ -540,14 +540,14 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
        ifa->ifa_scope = ifm->ifa_scope;
        ifa->ifa_dev = in_dev;
 
-       ifa->ifa_local = nla_get_u32(tb[IFA_LOCAL]);
-       ifa->ifa_address = nla_get_u32(tb[IFA_ADDRESS]);
+       ifa->ifa_local = nla_get_be32(tb[IFA_LOCAL]);
+       ifa->ifa_address = nla_get_be32(tb[IFA_ADDRESS]);
 
        if (tb[IFA_BROADCAST])
-               ifa->ifa_broadcast = nla_get_u32(tb[IFA_BROADCAST]);
+               ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]);
 
        if (tb[IFA_ANYCAST])
-               ifa->ifa_anycast = nla_get_u32(tb[IFA_ANYCAST]);
+               ifa->ifa_anycast = nla_get_be32(tb[IFA_ANYCAST]);
 
        if (tb[IFA_LABEL])
                nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
@@ -805,7 +805,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
                        break;
                ret = 0;
                if (ifa->ifa_mask != sin->sin_addr.s_addr) {
-                       u32 old_mask = ifa->ifa_mask;
+                       __be32 old_mask = ifa->ifa_mask;
                        inet_del_ifa(in_dev, ifap, 0);
                        ifa->ifa_mask = sin->sin_addr.s_addr;
                        ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
@@ -876,9 +876,9 @@ out:
        return done;
 }
 
-u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
+__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
 {
-       u32 addr = 0;
+       __be32 addr = 0;
        struct in_device *in_dev;
 
        rcu_read_lock();
@@ -927,11 +927,11 @@ out:
        return addr;
 }
 
-static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
-                             u32 local, int scope)
+static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
+                             __be32 local, int scope)
 {
        int same = 0;
-       u32 addr = 0;
+       __be32 addr = 0;
 
        for_ifa(in_dev) {
                if (!addr &&
@@ -971,9 +971,9 @@ static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
  * - local: address, 0=autoselect the local address
  * - scope: maximum allowed scope value for the local address
  */
-u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope)
+__be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope)
 {
-       u32 addr = 0;
+       __be32 addr = 0;
        struct in_device *in_dev;
 
        if (dev) {
@@ -1138,16 +1138,16 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
        ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
 
        if (ifa->ifa_address)
-               NLA_PUT_U32(skb, IFA_ADDRESS, ifa->ifa_address);
+               NLA_PUT_BE32(skb, IFA_ADDRESS, ifa->ifa_address);
 
        if (ifa->ifa_local)
-               NLA_PUT_U32(skb, IFA_LOCAL, ifa->ifa_local);
+               NLA_PUT_BE32(skb, IFA_LOCAL, ifa->ifa_local);
 
        if (ifa->ifa_broadcast)
-               NLA_PUT_U32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
+               NLA_PUT_BE32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
 
        if (ifa->ifa_anycast)
-               NLA_PUT_U32(skb, IFA_ANYCAST, ifa->ifa_anycast);
+               NLA_PUT_BE32(skb, IFA_ANYCAST, ifa->ifa_anycast);
 
        if (ifa->ifa_label[0])
                NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
index cfb527c060e48e4235063591a349ae91e7bb263a..9c399a70dd5d5962f3e47ad9e82cae0ae8b46c7b 100644 (file)
@@ -122,7 +122,7 @@ static void fib_flush(void)
  *     Find the first device with a given source address.
  */
 
-struct net_device * ip_dev_find(u32 addr)
+struct net_device * ip_dev_find(__be32 addr)
 {
        struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
        struct fib_result res;
@@ -146,7 +146,7 @@ out:
        return dev;
 }
 
-unsigned inet_addr_type(u32 addr)
+unsigned inet_addr_type(__be32 addr)
 {
        struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
        struct fib_result       res;
@@ -180,8 +180,8 @@ unsigned inet_addr_type(u32 addr)
    - check, that packet arrived from expected physical interface.
  */
 
-int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-                       struct net_device *dev, u32 *spec_dst, u32 *itag)
+int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
+                       struct net_device *dev, __be32 *spec_dst, u32 *itag)
 {
        struct in_device *in_dev;
        struct flowi fl = { .nl_u = { .ip4_u =
@@ -253,7 +253,7 @@ e_inval:
 
 #ifndef CONFIG_IP_NOSIOCRT
 
-static inline u32 sk_extract_addr(struct sockaddr *addr)
+static inline __be32 sk_extract_addr(struct sockaddr *addr)
 {
        return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
 }
@@ -273,7 +273,7 @@ static int put_rtax(struct nlattr *mx, int len, int type, u32 value)
 static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
                                 struct fib_config *cfg)
 {
-       u32 addr;
+       __be32 addr;
        int plen;
 
        memset(cfg, 0, sizeof(*cfg));
@@ -292,7 +292,7 @@ static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
        plen = 32;
        addr = sk_extract_addr(&rt->rt_dst);
        if (!(rt->rt_flags & RTF_HOST)) {
-               u32 mask = sk_extract_addr(&rt->rt_genmask);
+               __be32 mask = sk_extract_addr(&rt->rt_genmask);
 
                if (rt->rt_genmask.sa_family != AF_INET) {
                        if (mask || rt->rt_genmask.sa_family)
@@ -499,22 +499,22 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
                switch (attr->nla_type) {
                case RTA_DST:
-                       cfg->fc_dst = nla_get_u32(attr);
+                       cfg->fc_dst = nla_get_be32(attr);
                        break;
                case RTA_SRC:
-                       cfg->fc_src = nla_get_u32(attr);
+                       cfg->fc_src = nla_get_be32(attr);
                        break;
                case RTA_OIF:
                        cfg->fc_oif = nla_get_u32(attr);
                        break;
                case RTA_GATEWAY:
-                       cfg->fc_gw = nla_get_u32(attr);
+                       cfg->fc_gw = nla_get_be32(attr);
                        break;
                case RTA_PRIORITY:
                        cfg->fc_priority = nla_get_u32(attr);
                        break;
                case RTA_PREFSRC:
-                       cfg->fc_prefsrc = nla_get_u32(attr);
+                       cfg->fc_prefsrc = nla_get_be32(attr);
                        break;
                case RTA_METRICS:
                        cfg->fc_mx = nla_data(attr);
@@ -627,8 +627,7 @@ out:
    only when netlink is already locked.
  */
 
-static void fib_magic(int cmd, int type, u32 dst, int dst_len,
-                     struct in_ifaddr *ifa)
+static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
 {
        struct fib_table *tb;
        struct fib_config cfg = {
@@ -667,9 +666,9 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
        struct in_device *in_dev = ifa->ifa_dev;
        struct net_device *dev = in_dev->dev;
        struct in_ifaddr *prim = ifa;
-       u32 mask = ifa->ifa_mask;
-       u32 addr = ifa->ifa_local;
-       u32 prefix = ifa->ifa_address&mask;
+       __be32 mask = ifa->ifa_mask;
+       __be32 addr = ifa->ifa_local;
+       __be32 prefix = ifa->ifa_address&mask;
 
        if (ifa->ifa_flags&IFA_F_SECONDARY) {
                prim = inet_ifa_byprefix(in_dev, prefix, mask);
@@ -685,7 +684,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
                return;
 
        /* Add broadcast address, if it is explicitly assigned. */
-       if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
+       if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
                fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
 
        if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
@@ -707,8 +706,8 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
        struct net_device *dev = in_dev->dev;
        struct in_ifaddr *ifa1;
        struct in_ifaddr *prim = ifa;
-       u32 brd = ifa->ifa_address|~ifa->ifa_mask;
-       u32 any = ifa->ifa_address&ifa->ifa_mask;
+       __be32 brd = ifa->ifa_address|~ifa->ifa_mask;
+       __be32 any = ifa->ifa_address&ifa->ifa_mask;
 #define LOCAL_OK       1
 #define BRD_OK         2
 #define BRD0_OK                4
index 88133b383dc586cc95ee0c482cc019f8db4730b4..107bb6cbb0b370be0f8e10b0d434a432fbc3ebdd 100644 (file)
@@ -51,7 +51,7 @@ static kmem_cache_t *fn_alias_kmem __read_mostly;
 struct fib_node {
        struct hlist_node       fn_hash;
        struct list_head        fn_alias;
-       u32                     fn_key;
+       __be32                  fn_key;
 };
 
 struct fn_zone {
@@ -64,7 +64,7 @@ struct fn_zone {
 #define FZ_HASHMASK(fz)                ((fz)->fz_hashmask)
 
        int                     fz_order;       /* Zone order           */
-       u32                     fz_mask;
+       __be32                  fz_mask;
 #define FZ_MASK(fz)            ((fz)->fz_mask)
 };
 
@@ -77,7 +77,7 @@ struct fn_hash {
        struct fn_zone  *fn_zone_list;
 };
 
-static inline u32 fn_hash(u32 key, struct fn_zone *fz)
+static inline u32 fn_hash(__be32 key, struct fn_zone *fz)
 {
        u32 h = ntohl(key)>>(32 - fz->fz_order);
        h ^= (h>>20);
@@ -87,7 +87,7 @@ static inline u32 fn_hash(u32 key, struct fn_zone *fz)
        return h;
 }
 
-static inline u32 fz_key(u32 dst, struct fn_zone *fz)
+static inline __be32 fz_key(__be32 dst, struct fn_zone *fz)
 {
        return dst & FZ_MASK(fz);
 }
@@ -254,7 +254,7 @@ fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
                struct hlist_head *head;
                struct hlist_node *node;
                struct fib_node *f;
-               u32 k = fz_key(flp->fl4_dst, fz);
+               __be32 k = fz_key(flp->fl4_dst, fz);
 
                head = &fz->fz_hash[fn_hash(k, fz)];
                hlist_for_each_entry(f, node, head, fn_hash) {
@@ -365,7 +365,7 @@ static inline void fib_insert_node(struct fn_zone *fz, struct fib_node *f)
 }
 
 /* Return the node in FZ matching KEY. */
-static struct fib_node *fib_find_node(struct fn_zone *fz, u32 key)
+static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key)
 {
        struct hlist_head *head = &fz->fz_hash[fn_hash(key, fz)];
        struct hlist_node *node;
@@ -387,7 +387,7 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg)
        struct fn_zone *fz;
        struct fib_info *fi;
        u8 tos = cfg->fc_tos;
-       u32 key;
+       __be32 key;
        int err;
 
        if (cfg->fc_dst_len > 32)
@@ -541,7 +541,7 @@ static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg)
        struct fib_node *f;
        struct fib_alias *fa, *fa_to_delete;
        struct fn_zone *fz;
-       u32 key;
+       __be32 key;
 
        if (cfg->fc_dst_len > 32)
                return -EINVAL;
@@ -966,7 +966,7 @@ static void fib_seq_stop(struct seq_file *seq, void *v)
        read_unlock(&fib_hash_lock);
 }
 
-static unsigned fib_flag_trans(int type, u32 mask, struct fib_info *fi)
+static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
 {
        static const unsigned type2flags[RTN_MAX + 1] = {
                [7] = RTF_REJECT, [8] = RTF_REJECT,
@@ -975,7 +975,7 @@ static unsigned fib_flag_trans(int type, u32 mask, struct fib_info *fi)
 
        if (fi && fi->fib_nh->nh_gw)
                flags |= RTF_GATEWAY;
-       if (mask == 0xFFFFFFFF)
+       if (mask == htonl(0xFFFFFFFF))
                flags |= RTF_HOST;
        flags |= RTF_UP;
        return flags;
@@ -991,7 +991,7 @@ static int fib_seq_show(struct seq_file *seq, void *v)
 {
        struct fib_iter_state *iter;
        char bf[128];
-       u32 prefix, mask;
+       __be32 prefix, mask;
        unsigned flags;
        struct fib_node *f;
        struct fib_alias *fa;
index fd6f7769f8ab7fd0278fe1f65b02a677db44b688..0e8b70bad4e194b6f4a3968acb127b2387b6c2fe 100644 (file)
@@ -20,16 +20,16 @@ struct fib_alias {
 /* Exported by fib_semantics.c */
 extern int fib_semantic_match(struct list_head *head,
                              const struct flowi *flp,
-                             struct fib_result *res, __u32 zone, __u32 mask,
+                             struct fib_result *res, __be32 zone, __be32 mask,
                                int prefixlen);
 extern void fib_release_info(struct fib_info *);
 extern struct fib_info *fib_create_info(struct fib_config *cfg);
 extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-                        u32 tb_id, u8 type, u8 scope, u32 dst,
+                        u32 tb_id, u8 type, u8 scope, __be32 dst,
                         int dst_len, u8 tos, struct fib_info *fi,
                         unsigned int);
-extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
+extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
                      int dst_len, u32 tb_id, struct nl_info *info);
 extern struct fib_alias *fib_find_alias(struct list_head *fah,
                                        u8 tos, u32 prio);
index 52b2adae4f2230ae2af02f7a51efab6ab9516615..0852b9cd065a27bad02c3759c2262fcebf08405e 100644 (file)
@@ -40,10 +40,10 @@ struct fib4_rule
        u8                      dst_len;
        u8                      src_len;
        u8                      tos;
-       u32                     src;
-       u32                     srcmask;
-       u32                     dst;
-       u32                     dstmask;
+       __be32                  src;
+       __be32                  srcmask;
+       __be32                  dst;
+       __be32                  dstmask;
 #ifdef CONFIG_IP_ROUTE_FWMARK
        u32                     fwmark;
        u32                     fwmask;
@@ -150,8 +150,8 @@ void fib_select_default(const struct flowi *flp, struct fib_result *res)
 static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
        struct fib4_rule *r = (struct fib4_rule *) rule;
-       u32 daddr = fl->fl4_dst;
-       u32 saddr = fl->fl4_src;
+       __be32 daddr = fl->fl4_dst;
+       __be32 saddr = fl->fl4_src;
 
        if (((saddr ^ r->src) & r->srcmask) ||
            ((daddr ^ r->dst) & r->dstmask))
@@ -215,10 +215,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        }
 
        if (tb[FRA_SRC])
-               rule4->src = nla_get_u32(tb[FRA_SRC]);
+               rule4->src = nla_get_be32(tb[FRA_SRC]);
 
        if (tb[FRA_DST])
-               rule4->dst = nla_get_u32(tb[FRA_DST]);
+               rule4->dst = nla_get_be32(tb[FRA_DST]);
 
 #ifdef CONFIG_IP_ROUTE_FWMARK
        if (tb[FRA_FWMARK]) {
@@ -277,10 +277,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
                return 0;
 #endif
 
-       if (tb[FRA_SRC] && (rule4->src != nla_get_u32(tb[FRA_SRC])))
+       if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC])))
                return 0;
 
-       if (tb[FRA_DST] && (rule4->dst != nla_get_u32(tb[FRA_DST])))
+       if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST])))
                return 0;
 
        return 1;
@@ -305,10 +305,10 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
 #endif
 
        if (rule4->dst_len)
-               NLA_PUT_U32(skb, FRA_DST, rule4->dst);
+               NLA_PUT_BE32(skb, FRA_DST, rule4->dst);
 
        if (rule4->src_len)
-               NLA_PUT_U32(skb, FRA_SRC, rule4->src);
+               NLA_PUT_BE32(skb, FRA_SRC, rule4->src);
 
 #ifdef CONFIG_NET_CLS_ROUTE
        if (rule4->tclassid)
index 2ead09543f68899bef4ef584fd2c029d9e8b7df9..884d176e0082f3a230b9fa360ba4dc37518f2cb9 100644 (file)
@@ -203,7 +203,7 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
        unsigned int val = fi->fib_nhs;
 
        val ^= fi->fib_protocol;
-       val ^= fi->fib_prefsrc;
+       val ^= (__force u32)fi->fib_prefsrc;
        val ^= fi->fib_priority;
 
        return (val ^ (val >> 7) ^ (val >> 12)) & mask;
@@ -248,7 +248,7 @@ static inline unsigned int fib_devindex_hashfn(unsigned int val)
    Used only by redirect accept routine.
  */
 
-int ip_fib_check_default(u32 gw, struct net_device *dev)
+int ip_fib_check_default(__be32 gw, struct net_device *dev)
 {
        struct hlist_head *head;
        struct hlist_node *node;
@@ -273,7 +273,7 @@ int ip_fib_check_default(u32 gw, struct net_device *dev)
        return -1;
 }
 
-void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
+void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
               int dst_len, u32 tb_id, struct nl_info *info)
 {
        struct sk_buff *skb;
@@ -374,7 +374,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
                        struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
 
                        nla = nla_find(attrs, attrlen, RTA_GATEWAY);
-                       nh->nh_gw = nla ? nla_get_u32(nla) : 0;
+                       nh->nh_gw = nla ? nla_get_be32(nla) : 0;
 #ifdef CONFIG_NET_CLS_ROUTE
                        nla = nla_find(attrs, attrlen, RTA_FLOW);
                        nh->nh_tclassid = nla ? nla_get_u32(nla) : 0;
@@ -427,7 +427,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
                        struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
 
                        nla = nla_find(attrs, attrlen, RTA_GATEWAY);
-                       if (nla && nla_get_u32(nla) != nh->nh_gw)
+                       if (nla && nla_get_be32(nla) != nh->nh_gw)
                                return 1;
 #ifdef CONFIG_NET_CLS_ROUTE
                        nla = nla_find(attrs, attrlen, RTA_FLOW);
@@ -568,11 +568,11 @@ out:
        return 0;
 }
 
-static inline unsigned int fib_laddr_hashfn(u32 val)
+static inline unsigned int fib_laddr_hashfn(__be32 val)
 {
        unsigned int mask = (fib_hash_size - 1);
 
-       return (val ^ (val >> 7) ^ (val >> 14)) & mask;
+       return ((__force u32)val ^ ((__force u32)val >> 7) ^ ((__force u32)val >> 14)) & mask;
 }
 
 static struct hlist_head *fib_hash_alloc(int bytes)
@@ -847,7 +847,7 @@ failure:
 
 /* Note! fib_semantic_match intentionally uses  RCU list functions. */
 int fib_semantic_match(struct list_head *head, const struct flowi *flp,
-                      struct fib_result *res, __u32 zone, __u32 mask, 
+                      struct fib_result *res, __be32 zone, __be32 mask,
                        int prefixlen)
 {
        struct fib_alias *fa;
@@ -914,8 +914,7 @@ out_fill_res:
        res->fi = fa->fa_info;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
        res->netmask = mask;
-       res->network = zone &
-               (0xFFFFFFFF >> (32 - prefixlen));
+       res->network = zone & inet_make_mask(prefixlen);
 #endif
        atomic_inc(&res->fi->fib_clntref);
        return 0;
@@ -923,13 +922,13 @@ out_fill_res:
 
 /* Find appropriate source address to this destination */
 
-u32 __fib_res_prefsrc(struct fib_result *res)
+__be32 __fib_res_prefsrc(struct fib_result *res)
 {
        return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
 }
 
 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-                 u32 tb_id, u8 type, u8 scope, u32 dst, int dst_len, u8 tos,
+                 u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
                  struct fib_info *fi, unsigned int flags)
 {
        struct nlmsghdr *nlh;
@@ -952,7 +951,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
        rtm->rtm_protocol = fi->fib_protocol;
 
        if (rtm->rtm_dst_len)
-               NLA_PUT_U32(skb, RTA_DST, dst);
+               NLA_PUT_BE32(skb, RTA_DST, dst);
 
        if (fi->fib_priority)
                NLA_PUT_U32(skb, RTA_PRIORITY, fi->fib_priority);
@@ -961,11 +960,11 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                goto nla_put_failure;
 
        if (fi->fib_prefsrc)
-               NLA_PUT_U32(skb, RTA_PREFSRC, fi->fib_prefsrc);
+               NLA_PUT_BE32(skb, RTA_PREFSRC, fi->fib_prefsrc);
 
        if (fi->fib_nhs == 1) {
                if (fi->fib_nh->nh_gw)
-                       NLA_PUT_U32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw);
+                       NLA_PUT_BE32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw);
 
                if (fi->fib_nh->nh_oif)
                        NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif);
@@ -993,7 +992,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                        rtnh->rtnh_ifindex = nh->nh_oif;
 
                        if (nh->nh_gw)
-                               NLA_PUT_U32(skb, RTA_GATEWAY, nh->nh_gw);
+                               NLA_PUT_BE32(skb, RTA_GATEWAY, nh->nh_gw);
 #ifdef CONFIG_NET_CLS_ROUTE
                        if (nh->nh_tclassid)
                                NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid);
@@ -1018,7 +1017,7 @@ nla_put_failure:
    - device went down -> we must shutdown all nexthops going via it.
  */
 
-int fib_sync_down(u32 local, struct net_device *dev, int force)
+int fib_sync_down(__be32 local, struct net_device *dev, int force)
 {
        int ret = 0;
        int scope = RT_SCOPE_NOWHERE;
index 9c3ff6ba6e218e45c351c22f1eb8ff188442a509..d17990ec724f68d30fa6987e8c61fd7dc21fdd5d 100644 (file)
@@ -1834,7 +1834,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
        int i, s_i;
        struct fib_alias *fa;
 
-       u32 xkey = htonl(key);
+       __be32 xkey = htonl(key);
 
        s_i = cb->args[4];
        i = 0;
@@ -2281,7 +2281,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
 
        if (IS_TNODE(n)) {
                struct tnode *tn = (struct tnode *) n;
-               t_key prf = ntohl(MASK_PFX(tn->key, tn->pos));
+               __be32 prf = htonl(MASK_PFX(tn->key, tn->pos));
 
                if (!NODE_PARENT(n)) {
                        if (iter->trie == trie_local)
@@ -2297,7 +2297,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
        } else {
                struct leaf *l = (struct leaf *) n;
                int i;
-               u32 val = ntohl(l->key);
+               __be32 val = htonl(l->key);
 
                seq_indent(seq, iter->depth);
                seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
@@ -2360,7 +2360,7 @@ static struct file_operations fib_trie_fops = {
        .release = seq_release_private,
 };
 
-static unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi)
+static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
 {
        static unsigned type2flags[RTN_MAX + 1] = {
                [7] = RTF_REJECT, [8] = RTF_REJECT,
@@ -2369,7 +2369,7 @@ static unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi)
 
        if (fi && fi->fib_nh->nh_gw)
                flags |= RTF_GATEWAY;
-       if (mask == 0xFFFFFFFF)
+       if (mask == htonl(0xFFFFFFFF))
                flags |= RTF_HOST;
        flags |= RTF_UP;
        return flags;
@@ -2403,7 +2403,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
        for (i=32; i>=0; i--) {
                struct leaf_info *li = find_leaf_info(l, i);
                struct fib_alias *fa;
-               u32 mask, prefix;
+               __be32 mask, prefix;
 
                if (!li)
                        continue;
index c2ad07e48ab4f97ad77af0a99fbd7202b7f048e4..b39a37a4754506c436b17a0be5bf3c2a6165f26e 100644 (file)
@@ -104,7 +104,7 @@ struct icmp_bxm {
 
        struct {
                struct icmphdr icmph;
-               __u32          times[3];
+               __be32         times[3];
        } data;
        int head_len;
        struct ip_options replyopts;
@@ -381,7 +381,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
        struct inet_sock *inet = inet_sk(sk);
        struct ipcm_cookie ipc;
        struct rtable *rt = (struct rtable *)skb->dst;
-       u32 daddr;
+       __be32 daddr;
 
        if (ip_options_echo(&icmp_param->replyopts, skb))
                return;
@@ -430,14 +430,14 @@ out_unlock:
  *                     MUST reply to only the first fragment.
  */
 
-void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
+void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 {
        struct iphdr *iph;
        int room;
        struct icmp_bxm icmp_param;
        struct rtable *rt = (struct rtable *)skb_in->dst;
        struct ipcm_cookie ipc;
-       u32 saddr;
+       __be32 saddr;
        u8  tos;
 
        if (!rt)
@@ -895,7 +895,7 @@ static void icmp_address_reply(struct sk_buff *skb)
        if (in_dev->ifa_list &&
            IN_DEV_LOG_MARTIANS(in_dev) &&
            IN_DEV_FORWARD(in_dev)) {
-               u32 _mask, *mp;
+               __be32 _mask, *mp;
 
                mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask);
                BUG_ON(mp == NULL);
index 58be8227b0cb95975ef5eae527b4de88e352dd08..6eee71647b7c92f5fdcb69f43c68ce37c3b59cee 100644 (file)
                time_before(jiffies, (in_dev)->mr_v2_seen)))
 
 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
-static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr);
+static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
 static void igmpv3_clear_delrec(struct in_device *in_dev);
 static int sf_setstate(struct ip_mc_list *pmc);
 static void sf_markstate(struct ip_mc_list *pmc);
 #endif
 static void ip_mc_clear_src(struct ip_mc_list *pmc);
-static int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
-                        int sfcount, __u32 *psfsrc, int delta);
+static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+                        int sfcount, __be32 *psfsrc, int delta);
 
 static void ip_ma_put(struct ip_mc_list *im)
 {
@@ -426,7 +426,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
        first = 1;
        psf_prev = NULL;
        for (psf=*psf_list; psf; psf=psf_next) {
-               u32 *psrc;
+               __be32 *psrc;
 
                psf_next = psf->sf_next;
 
@@ -439,7 +439,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
                if (isquery)
                        psf->sf_gsresp = 0;
 
-               if (AVAILABLE(skb) < sizeof(u32) +
+               if (AVAILABLE(skb) < sizeof(__be32) +
                    first*sizeof(struct igmpv3_grec)) {
                        if (truncate && !first)
                                break;   /* truncate these */
@@ -455,7 +455,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
                        skb = add_grhead(skb, pmc, type, &pgr);
                        first = 0;
                }
-               psrc = (u32 *)skb_put(skb, sizeof(u32));
+               psrc = (__be32 *)skb_put(skb, sizeof(__be32));
                *psrc = psf->sf_inaddr;
                scount++; stotal++;
                if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
@@ -630,8 +630,8 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        struct igmphdr *ih;
        struct rtable *rt;
        struct net_device *dev = in_dev->dev;
-       u32     group = pmc ? pmc->multiaddr : 0;
-       u32     dst;
+       __be32  group = pmc ? pmc->multiaddr : 0;
+       __be32  dst;
 
        if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
                return igmpv3_send_report(in_dev, pmc);
@@ -748,7 +748,7 @@ static void igmp_timer_expire(unsigned long data)
 }
 
 /* mark EXCLUDE-mode sources */
-static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
 {
        struct ip_sf_list *psf;
        int i, scount;
@@ -775,7 +775,7 @@ static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
        return 1;
 }
 
-static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
 {
        struct ip_sf_list *psf;
        int i, scount;
@@ -803,7 +803,7 @@ static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
        return 1;
 }
 
-static void igmp_heard_report(struct in_device *in_dev, u32 group)
+static void igmp_heard_report(struct in_device *in_dev, __be32 group)
 {
        struct ip_mc_list *im;
 
@@ -828,7 +828,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
        struct igmphdr          *ih = skb->h.igmph;
        struct igmpv3_query *ih3 = (struct igmpv3_query *)ih;
        struct ip_mc_list       *im;
-       u32                     group = ih->group;
+       __be32                  group = ih->group;
        int                     max_delay;
        int                     mark = 0;
 
@@ -862,7 +862,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
                ih3 = (struct igmpv3_query *) skb->h.raw;
                if (ih3->nsrcs) {
                        if (!pskb_may_pull(skb, sizeof(struct igmpv3_query) 
-                                          + ntohs(ih3->nsrcs)*sizeof(__u32)))
+                                          + ntohs(ih3->nsrcs)*sizeof(__be32)))
                                return;
                        ih3 = (struct igmpv3_query *) skb->h.raw;
                }
@@ -985,7 +985,7 @@ drop:
  *     Add a filter to a device
  */
 
-static void ip_mc_filter_add(struct in_device *in_dev, u32 addr)
+static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
 {
        char buf[MAX_ADDR_LEN];
        struct net_device *dev = in_dev->dev;
@@ -1005,7 +1005,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, u32 addr)
  *     Remove a filter from a device
  */
 
-static void ip_mc_filter_del(struct in_device *in_dev, u32 addr)
+static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
 {
        char buf[MAX_ADDR_LEN];
        struct net_device *dev = in_dev->dev;
@@ -1055,7 +1055,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
        spin_unlock_bh(&in_dev->mc_tomb_lock);
 }
 
-static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
+static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
 {
        struct ip_mc_list *pmc, *pmc_prev;
        struct ip_sf_list *psf, *psf_next;
@@ -1193,7 +1193,7 @@ static void igmp_group_added(struct ip_mc_list *im)
  *     A socket has joined a multicast group on device dev.
  */
 
-void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
+void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
 {
        struct ip_mc_list *im;
 
@@ -1252,7 +1252,7 @@ out:
  *     A socket has left a multicast group on device dev
  */
 
-void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
+void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
 {
        struct ip_mc_list *i, **ip;
        
@@ -1402,7 +1402,7 @@ int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF;
 
 
 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
-       __u32 *psfsrc)
+       __be32 *psfsrc)
 {
        struct ip_sf_list *psf, *psf_prev;
        int rv = 0;
@@ -1450,8 +1450,8 @@ static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
 #define igmp_ifc_event(x)      do { } while (0)
 #endif
 
-static int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
-                        int sfcount, __u32 *psfsrc, int delta)
+static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+                        int sfcount, __be32 *psfsrc, int delta)
 {
        struct ip_mc_list *pmc;
        int     changerec = 0;
@@ -1517,7 +1517,7 @@ out_unlock:
  * Add multicast single-source filter to the interface list
  */
 static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
-       __u32 *psfsrc, int delta)
+       __be32 *psfsrc, int delta)
 {
        struct ip_sf_list *psf, *psf_prev;
 
@@ -1623,8 +1623,8 @@ static int sf_setstate(struct ip_mc_list *pmc)
 /*
  * Add multicast source filter list to the interface list
  */
-static int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
-                        int sfcount, __u32 *psfsrc, int delta)
+static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+                        int sfcount, __be32 *psfsrc, int delta)
 {
        struct ip_mc_list *pmc;
        int     isexclude;
@@ -1717,7 +1717,7 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc)
 int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
 {
        int err;
-       u32 addr = imr->imr_multiaddr.s_addr;
+       __be32 addr = imr->imr_multiaddr.s_addr;
        struct ip_mc_socklist *iml=NULL, *i;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
@@ -1791,7 +1791,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
        struct inet_sock *inet = inet_sk(sk);
        struct ip_mc_socklist *iml, **imlp;
        struct in_device *in_dev;
-       u32 group = imr->imr_multiaddr.s_addr;
+       __be32 group = imr->imr_multiaddr.s_addr;
        u32 ifindex;
        int ret = -EADDRNOTAVAIL;
 
@@ -1829,7 +1829,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
 {
        int err;
        struct ip_mreqn imr;
-       u32 addr = mreqs->imr_multiaddr;
+       __be32 addr = mreqs->imr_multiaddr;
        struct ip_mc_socklist *pmc;
        struct in_device *in_dev = NULL;
        struct inet_sock *inet = inet_sk(sk);
@@ -1883,7 +1883,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
-                               sizeof(__u32));
+                               sizeof(__be32));
                        if (rv == 0)
                                break;
                }
@@ -1935,7 +1935,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
                rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
-                       sizeof(__u32));
+                       sizeof(__be32));
                if (rv == 0)
                        break;
        }
@@ -1960,7 +1960,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
 {
        int err = 0;
        struct ip_mreqn imr;
-       u32 addr = msf->imsf_multiaddr;
+       __be32 addr = msf->imsf_multiaddr;
        struct ip_mc_socklist *pmc;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
@@ -2044,7 +2044,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
 {
        int err, len, count, copycount;
        struct ip_mreqn imr;
-       u32 addr = msf->imsf_multiaddr;
+       __be32 addr = msf->imsf_multiaddr;
        struct ip_mc_socklist *pmc;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
@@ -2103,7 +2103,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
 {
        int err, i, count, copycount;
        struct sockaddr_in *psin;
-       u32 addr;
+       __be32 addr;
        struct ip_mc_socklist *pmc;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *psl;
@@ -2156,7 +2156,7 @@ done:
 /*
  * check if a multicast source filter allows delivery for a given <src,dst,intf>
  */
-int ip_mc_sf_allow(struct sock *sk, u32 loc_addr, u32 rmt_addr, int dif)
+int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct ip_mc_socklist *pmc;
@@ -2216,7 +2216,7 @@ void ip_mc_drop_socket(struct sock *sk)
        rtnl_unlock();
 }
 
-int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
+int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
 {
        struct ip_mc_list *im;
        struct ip_sf_list *psf;
index 07204391d083bb11fb12d6f09576a8102e9cfbbd..96bbe2a0aa1b05e41fcd144e3b11a61b17d854ba 100644 (file)
@@ -39,7 +39,7 @@ int sysctl_local_port_range[2] = { 1024, 4999 };
 int inet_csk_bind_conflict(const struct sock *sk,
                           const struct inet_bind_bucket *tb)
 {
-       const u32 sk_rcv_saddr = inet_rcv_saddr(sk);
+       const __be32 sk_rcv_saddr = inet_rcv_saddr(sk);
        struct sock *sk2;
        struct hlist_node *node;
        int reuse = sk->sk_reuse;
@@ -52,7 +52,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
                        if (!reuse || !sk2->sk_reuse ||
                            sk2->sk_state == TCP_LISTEN) {
-                               const u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
+                               const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
                                if (!sk2_rcv_saddr || !sk_rcv_saddr ||
                                    sk2_rcv_saddr == sk_rcv_saddr)
                                        break;
@@ -342,10 +342,10 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
 
 EXPORT_SYMBOL_GPL(inet_csk_route_req);
 
-static inline u32 inet_synq_hash(const u32 raddr, const u16 rport,
+static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport,
                                 const u32 rnd, const u16 synq_hsize)
 {
-       return jhash_2words(raddr, (u32)rport, rnd) & (synq_hsize - 1);
+       return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1);
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -356,8 +356,8 @@ static inline u32 inet_synq_hash(const u32 raddr, const u16 rport,
 
 struct request_sock *inet_csk_search_req(const struct sock *sk,
                                         struct request_sock ***prevp,
-                                        const __u16 rport, const __u32 raddr,
-                                        const __u32 laddr)
+                                        const __be16 rport, const __be32 raddr,
+                                        const __be32 laddr)
 {
        const struct inet_connection_sock *icsk = inet_csk(sk);
        struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
index 492858e6faf0140fee625d8f966093c57c141773..77761ac4f7bb0589bc22d89127e3d64abb14c65a 100644 (file)
@@ -36,8 +36,8 @@
 static const struct inet_diag_handler **inet_diag_table;
 
 struct inet_diag_entry {
-       u32 *saddr;
-       u32 *daddr;
+       __be32 *saddr;
+       __be32 *daddr;
        u16 sport;
        u16 dport;
        u16 family;
@@ -294,7 +294,7 @@ out:
        return err;
 }
 
-static int bitstring_match(const u32 *a1, const u32 *a2, int bits)
+static int bitstring_match(const __be32 *a1, const __be32 *a2, int bits)
 {
        int words = bits >> 5;
 
@@ -305,8 +305,8 @@ static int bitstring_match(const u32 *a1, const u32 *a2, int bits)
                        return 0;
        }
        if (bits) {
-               __u32 w1, w2;
-               __u32 mask;
+               __be32 w1, w2;
+               __be32 mask;
 
                w1 = a1[words];
                w2 = a2[words];
@@ -352,7 +352,7 @@ static int inet_diag_bc_run(const void *bc, int len,
                case INET_DIAG_BC_S_COND:
                case INET_DIAG_BC_D_COND: {
                        struct inet_diag_hostcond *cond;
-                       u32 *addr;
+                       __be32 *addr;
 
                        cond = (struct inet_diag_hostcond *)(op + 1);
                        if (cond->port != -1 &&
index fb296c9a7f3fe385aeebbf5d5cc521360335fa8d..244c4f445c7d55779a99fe301152c2241bbcacd7 100644 (file)
@@ -125,7 +125,7 @@ EXPORT_SYMBOL(inet_listen_wlock);
  * wildcarded during the search since they can never be otherwise.
  */
 static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
-                                             const u32 daddr,
+                                             const __be32 daddr,
                                              const unsigned short hnum,
                                              const int dif)
 {
@@ -137,7 +137,7 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
                const struct inet_sock *inet = inet_sk(sk);
 
                if (inet->num == hnum && !ipv6_only_sock(sk)) {
-                       const __u32 rcv_saddr = inet->rcv_saddr;
+                       const __be32 rcv_saddr = inet->rcv_saddr;
                        int score = sk->sk_family == PF_INET ? 1 : 0;
 
                        if (rcv_saddr) {
@@ -163,7 +163,7 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
 
 /* Optimize the common listener case. */
 struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
-                                   const u32 daddr, const unsigned short hnum,
+                                   const __be32 daddr, const unsigned short hnum,
                                    const int dif)
 {
        struct sock *sk = NULL;
@@ -197,11 +197,11 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
 {
        struct inet_hashinfo *hinfo = death_row->hashinfo;
        struct inet_sock *inet = inet_sk(sk);
-       u32 daddr = inet->rcv_saddr;
-       u32 saddr = inet->daddr;
+       __be32 daddr = inet->rcv_saddr;
+       __be32 saddr = inet->daddr;
        int dif = sk->sk_bound_dev_if;
        INET_ADDR_COOKIE(acookie, saddr, daddr)
-       const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+       const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
        unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
        struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
        struct sock *sk2;
index a675602ef2953acf12d33096657c8bb09689a4af..2b1a54b59c48c4f2a65d6f8838bbcfd567a71183 100644 (file)
@@ -163,7 +163,7 @@ static void unlink_from_unused(struct inet_peer *p)
        for (u = peer_root; u != peer_avl_empty; ) {            \
                if (daddr == u->v4daddr)                        \
                        break;                                  \
-               if (daddr < u->v4daddr)                         \
+               if ((__force __u32)daddr < (__force __u32)u->v4daddr)   \
                        v = &u->avl_left;                       \
                else                                            \
                        v = &u->avl_right;                      \
@@ -368,7 +368,7 @@ static int cleanup_once(unsigned long ttl)
 }
 
 /* Called with or without local BH being disabled. */
-struct inet_peer *inet_getpeer(__u32 daddr, int create)
+struct inet_peer *inet_getpeer(__be32 daddr, int create)
 {
        struct inet_peer *p, *n;
        struct inet_peer **stack[PEER_MAXDEPTH], ***stackptr;
index 165d72859ddf4cbe7d49bb49ecafb739b0001806..74046efdf875804ee4bd60f20636b2aa1d09e7bf 100644 (file)
@@ -77,9 +77,9 @@ struct ipq {
        struct hlist_node list;
        struct list_head lru_list;      /* lru list member                      */
        u32             user;
-       u32             saddr;
-       u32             daddr;
-       u16             id;
+       __be32          saddr;
+       __be32          daddr;
+       __be16          id;
        u8              protocol;
        u8              last_in;
 #define COMPLETE               4
@@ -123,9 +123,10 @@ static __inline__ void ipq_unlink(struct ipq *ipq)
        write_unlock(&ipfrag_lock);
 }
 
-static unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
+static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
 {
-       return jhash_3words((u32)id << 16 | prot, saddr, daddr,
+       return jhash_3words((__force u32)id << 16 | prot,
+                           (__force u32)saddr, (__force u32)daddr,
                            ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
 }
 
@@ -387,8 +388,8 @@ out_nomem:
 static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
 {
        __be16 id = iph->id;
-       __u32 saddr = iph->saddr;
-       __u32 daddr = iph->daddr;
+       __be32 saddr = iph->saddr;
+       __be32 daddr = iph->daddr;
        __u8 protocol = iph->protocol;
        unsigned int hash;
        struct ipq *qp;
index e7437c0913266cf5431e83bce781ebd22e2bb044..8dabbfc312674bd574df7f69f2a5646146723c18 100644 (file)
@@ -38,7 +38,7 @@
  */
 
 void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
-                           u32 daddr, struct rtable *rt, int is_frag) 
+                           __be32 daddr, struct rtable *rt, int is_frag)
 {
        unsigned char * iph = skb->nh.raw;
 
@@ -57,7 +57,7 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
                        ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
                if (opt->ts_needtime) {
                        struct timeval tv;
-                       __u32 midtime;
+                       __be32 midtime;
                        do_gettimeofday(&tv);
                        midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
                        memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
@@ -91,7 +91,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
        unsigned char *sptr, *dptr;
        int soffset, doffset;
        int     optlen;
-       u32     daddr;
+       __be32  daddr;
 
        memset(dopt, 0, sizeof(struct ip_options));
 
@@ -148,7 +148,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
                                        dopt->ts_needtime = 0;
 
                                        if (soffset + 8 <= optlen) {
-                                               __u32 addr;
+                                               __be32 addr;
 
                                                memcpy(&addr, sptr+soffset-1, 4);
                                                if (inet_addr_type(addr) != RTN_LOCAL) {
@@ -165,7 +165,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
        }
        if (sopt->srr) {
                unsigned char * start = sptr+sopt->srr;
-               u32 faddr;
+               __be32 faddr;
 
                optlen  = start[1];
                soffset = start[2];
@@ -362,7 +362,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
                                goto error;
                        }
                        if (optptr[2] <= optlen) {
-                               __u32 * timeptr = NULL;
+                               __be32 *timeptr = NULL;
                                if (optptr[2]+3 > optptr[1]) {
                                        pp_ptr = optptr + 2;
                                        goto error;
@@ -371,7 +371,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
                                      case IPOPT_TS_TSONLY:
                                        opt->ts = optptr - iph;
                                        if (skb) 
-                                               timeptr = (__u32*)&optptr[optptr[2]-1];
+                                               timeptr = (__be32*)&optptr[optptr[2]-1];
                                        opt->ts_needtime = 1;
                                        optptr[2] += 4;
                                        break;
@@ -383,7 +383,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
                                        opt->ts = optptr - iph;
                                        if (skb) {
                                                memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
-                                               timeptr = (__u32*)&optptr[optptr[2]+3];
+                                               timeptr = (__be32*)&optptr[optptr[2]+3];
                                        }
                                        opt->ts_needaddr = 1;
                                        opt->ts_needtime = 1;
@@ -396,12 +396,12 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
                                        }
                                        opt->ts = optptr - iph;
                                        {
-                                               u32 addr;
+                                               __be32 addr;
                                                memcpy(&addr, &optptr[optptr[2]-1], 4);
                                                if (inet_addr_type(addr) == RTN_UNICAST)
                                                        break;
                                                if (skb)
-                                                       timeptr = (__u32*)&optptr[optptr[2]+3];
+                                                       timeptr = (__be32*)&optptr[optptr[2]+3];
                                        }
                                        opt->ts_needtime = 1;
                                        optptr[2] += 8;
@@ -415,10 +415,10 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
                                }
                                if (timeptr) {
                                        struct timeval tv;
-                                       __u32  midtime;
+                                       __be32  midtime;
                                        do_gettimeofday(&tv);
                                        midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
-                                       memcpy(timeptr, &midtime, sizeof(__u32));
+                                       memcpy(timeptr, &midtime, sizeof(__be32));
                                        opt->is_changed = 1;
                                }
                        } else {
@@ -607,7 +607,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
 {
        struct ip_options *opt = &(IPCB(skb)->opt);
        int srrspace, srrptr;
-       u32 nexthop;
+       __be32 nexthop;
        struct iphdr *iph = skb->nh.iph;
        unsigned char * optptr = skb->nh.raw + opt->srr;
        struct rtable *rt = (struct rtable*)skb->dst;
index 97aee76fb7463d41bdaac364907b37cf4f6b25dd..fc195a44fc2e1800d0ba5e32fedc9019d29562f2 100644 (file)
@@ -118,7 +118,7 @@ static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
  *
  */
 int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
-                         u32 saddr, u32 daddr, struct ip_options *opt)
+                         __be32 saddr, __be32 daddr, struct ip_options *opt)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct rtable *rt = (struct rtable *)skb->dst;
@@ -306,7 +306,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
        /* Make sure we can route this packet. */
        rt = (struct rtable *)__sk_dst_check(sk, 0);
        if (rt == NULL) {
-               u32 daddr;
+               __be32 daddr;
 
                /* Use correct destination address if we have options. */
                daddr = inet->daddr;
@@ -1340,7 +1340,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
                char                    data[40];
        } replyopts;
        struct ipcm_cookie ipc;
-       u32 daddr;
+       __be32 daddr;
        struct rtable *rt = (struct rtable*)skb->dst;
 
        if (ip_options_echo(&replyopts.opt, skb))
index 2d05c4133d3e350b7940c737ecf4055b4f197a24..4b132953bcc2a7ceb3a00d6232f9069d2baf98b5 100644 (file)
@@ -254,7 +254,7 @@ int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct s
 }
 
 void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
-                  u16 port, u32 info, u8 *payload)
+                  __be16 port, u32 info, u8 *payload)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct sock_exterr_skb *serr;
@@ -283,7 +283,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
                kfree_skb(skb);
 }
 
-void ip_local_error(struct sock *sk, int err, u32 daddr, u16 port, u32 info)
+void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct sock_exterr_skb *serr;
index 17342430a843bc20781590c79f210564221905b4..2017d36024d48d61816bd52e82bf67f4c196479d 100644 (file)
@@ -183,7 +183,7 @@ out_ok:
 
 static void ipcomp4_err(struct sk_buff *skb, u32 info)
 {
-       u32 spi;
+       __be32 spi;
        struct iphdr *iph = (struct iphdr *)skb->data;
        struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
        struct xfrm_state *x;
index ba49588da2424f70e4d6fa483839db279b30890e..97cfa97c8abbfe8fba81b8bbcbc2ff3960ce3db4 100644 (file)
@@ -462,7 +462,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
        return 0;
 }
 
-static struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
+static struct mfc_cache *ipmr_cache_find(__be32 origin, __be32 mcastgrp)
 {
        int line=MFC_HASH(mcastgrp,origin);
        struct mfc_cache *c;
@@ -1097,7 +1097,7 @@ static struct notifier_block ip_mr_notifier={
  *     important for multicast video.
  */
  
-static void ip_encap(struct sk_buff *skb, u32 saddr, u32 daddr)
+static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
 {
        struct iphdr *iph = (struct iphdr *)skb_push(skb,sizeof(struct iphdr));
 
index 87b83813cf2c2f12f4a43fba75385c7e979c16d5..8832eb517d5200355356eb0281b4f4cc6be8cb61 100644 (file)
@@ -115,9 +115,9 @@ static inline void ct_write_unlock_bh(unsigned key)
 /*
  *     Returns hash value for IPVS connection entry
  */
-static unsigned int ip_vs_conn_hashkey(unsigned proto, __u32 addr, __u16 port)
+static unsigned int ip_vs_conn_hashkey(unsigned proto, __be32 addr, __be16 port)
 {
-       return jhash_3words(addr, port, proto, ip_vs_conn_rnd)
+       return jhash_3words((__force u32)addr, (__force u32)port, proto, ip_vs_conn_rnd)
                & IP_VS_CONN_TAB_MASK;
 }
 
@@ -188,7 +188,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
  *     d_addr, d_port: pkt dest address (load balancer)
  */
 static inline struct ip_vs_conn *__ip_vs_conn_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
        unsigned hash;
        struct ip_vs_conn *cp;
@@ -215,7 +215,7 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
 }
 
 struct ip_vs_conn *ip_vs_conn_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
        struct ip_vs_conn *cp;
 
@@ -234,7 +234,7 @@ struct ip_vs_conn *ip_vs_conn_in_get
 
 /* Get reference to connection template */
 struct ip_vs_conn *ip_vs_ct_in_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
        unsigned hash;
        struct ip_vs_conn *cp;
@@ -274,7 +274,7 @@ struct ip_vs_conn *ip_vs_ct_in_get
  *     d_addr, d_port: pkt dest address (foreign host)
  */
 struct ip_vs_conn *ip_vs_conn_out_get
-(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
 {
        unsigned hash;
        struct ip_vs_conn *cp, *ret=NULL;
@@ -324,7 +324,7 @@ void ip_vs_conn_put(struct ip_vs_conn *cp)
 /*
  *     Fill a no_client_port connection with a client port number
  */
-void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __u16 cport)
+void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport)
 {
        if (ip_vs_conn_unhash(cp)) {
                spin_lock(&cp->lock);
@@ -508,10 +508,10 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
                /*
                 * Invalidate the connection template
                 */
-               if (ct->vport != 65535) {
+               if (ct->vport != htons(0xffff)) {
                        if (ip_vs_conn_unhash(ct)) {
-                               ct->dport = 65535;
-                               ct->vport = 65535;
+                               ct->dport = htons(0xffff);
+                               ct->vport = htons(0xffff);
                                ct->cport = 0;
                                ip_vs_conn_hash(ct);
                        }
@@ -596,8 +596,8 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
  *     Create a new connection entry and hash it into the ip_vs_conn_tab
  */
 struct ip_vs_conn *
-ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport,
-              __u32 daddr, __u16 dport, unsigned flags,
+ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport,
+              __be32 daddr, __be16 dport, unsigned flags,
               struct ip_vs_dest *dest)
 {
        struct ip_vs_conn *cp;
index 3f47ad8e1cad1c7f8165b6e5c003a3f919711e4a..6dee03935f786076448f7f1573abc2c806ff12f0 100644 (file)
@@ -209,14 +209,14 @@ int ip_vs_make_skb_writable(struct sk_buff **pskb, int writable_len)
 static struct ip_vs_conn *
 ip_vs_sched_persist(struct ip_vs_service *svc,
                    const struct sk_buff *skb,
-                   __u16 ports[2])
+                   __be16 ports[2])
 {
        struct ip_vs_conn *cp = NULL;
        struct iphdr *iph = skb->nh.iph;
        struct ip_vs_dest *dest;
        struct ip_vs_conn *ct;
-       __u16  dport;    /* destination port to forward */
-       __u32  snet;     /* source network of the client, after masking */
+       __be16  dport;   /* destination port to forward */
+       __be32  snet;    /* source network of the client, after masking */
 
        /* Mask saddr with the netmask to adjust template granularity */
        snet = iph->saddr & svc->netmask;
@@ -383,7 +383,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
        struct ip_vs_conn *cp = NULL;
        struct iphdr *iph = skb->nh.iph;
        struct ip_vs_dest *dest;
-       __u16 _ports[2], *pptr;
+       __be16 _ports[2], *pptr;
 
        pptr = skb_header_pointer(skb, iph->ihl*4,
                                  sizeof(_ports), _ports);
@@ -446,7 +446,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                struct ip_vs_protocol *pp)
 {
-       __u16 _ports[2], *pptr;
+       __be16 _ports[2], *pptr;
        struct iphdr *iph = skb->nh.iph;
 
        pptr = skb_header_pointer(skb, iph->ihl*4,
@@ -576,7 +576,7 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
 
        /* the TCP/UDP port */
        if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol) {
-               __u16 *ports = (void *)ciph + ciph->ihl*4;
+               __be16 *ports = (void *)ciph + ciph->ihl*4;
 
                if (inout)
                        ports[1] = cp->vport;
@@ -775,7 +775,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
                if (sysctl_ip_vs_nat_icmp_send &&
                    (pp->protocol == IPPROTO_TCP ||
                     pp->protocol == IPPROTO_UDP)) {
-                       __u16 _ports[2], *pptr;
+                       __be16 _ports[2], *pptr;
 
                        pptr = skb_header_pointer(skb, ihl,
                                                  sizeof(_ports), _ports);
index 6a28fafe910c2a6ef858a900e688c682d9c470d5..f261616e460218b5379340ba77ba6f4b6ce48506 100644 (file)
@@ -283,7 +283,7 @@ static atomic_t ip_vs_nullsvc_counter = ATOMIC_INIT(0);
  *     Returns hash value for virtual service
  */
 static __inline__ unsigned
-ip_vs_svc_hashkey(unsigned proto, __u32 addr, __u16 port)
+ip_vs_svc_hashkey(unsigned proto, __be32 addr, __be16 port)
 {
        register unsigned porth = ntohs(port);
 
@@ -365,7 +365,7 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
  *     Get service by {proto,addr,port} in the service table.
  */
 static __inline__ struct ip_vs_service *
-__ip_vs_service_get(__u16 protocol, __u32 vaddr, __u16 vport)
+__ip_vs_service_get(__u16 protocol, __be32 vaddr, __be16 vport)
 {
        unsigned hash;
        struct ip_vs_service *svc;
@@ -410,7 +410,7 @@ static __inline__ struct ip_vs_service *__ip_vs_svc_fwm_get(__u32 fwmark)
 }
 
 struct ip_vs_service *
-ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport)
+ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
 {
        struct ip_vs_service *svc;
 
@@ -480,7 +480,7 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest)
 /*
  *     Returns hash value for real service
  */
-static __inline__ unsigned ip_vs_rs_hashkey(__u32 addr, __u16 port)
+static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port)
 {
        register unsigned porth = ntohs(port);
 
@@ -531,7 +531,7 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest)
  *     Lookup real service by <proto,addr,port> in the real service table.
  */
 struct ip_vs_dest *
-ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport)
+ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport)
 {
        unsigned hash;
        struct ip_vs_dest *dest;
@@ -562,7 +562,7 @@ ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport)
  *     Lookup destination by {addr,port} in the given service
  */
 static struct ip_vs_dest *
-ip_vs_lookup_dest(struct ip_vs_service *svc, __u32 daddr, __u16 dport)
+ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
 {
        struct ip_vs_dest *dest;
 
@@ -591,7 +591,7 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __u32 daddr, __u16 dport)
  *  scheduling.
  */
 static struct ip_vs_dest *
-ip_vs_trash_get_dest(struct ip_vs_service *svc, __u32 daddr, __u16 dport)
+ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
 {
        struct ip_vs_dest *dest, *nxt;
 
@@ -773,8 +773,8 @@ static int
 ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
 {
        struct ip_vs_dest *dest;
-       __u32 daddr = udest->addr;
-       __u16 dport = udest->port;
+       __be32 daddr = udest->addr;
+       __be16 dport = udest->port;
        int ret;
 
        EnterFunction(2);
@@ -879,8 +879,8 @@ static int
 ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
 {
        struct ip_vs_dest *dest;
-       __u32 daddr = udest->addr;
-       __u16 dport = udest->port;
+       __be32 daddr = udest->addr;
+       __be16 dport = udest->port;
 
        EnterFunction(2);
 
@@ -991,8 +991,8 @@ static int
 ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest)
 {
        struct ip_vs_dest *dest;
-       __u32 daddr = udest->addr;
-       __u16 dport = udest->port;
+       __be32 daddr = udest->addr;
+       __be16 dport = udest->port;
 
        EnterFunction(2);
 
index 9fee19c4c6179958f5ea5eb39c4a550e67b314ee..502111fba87284ae6fe11ab944d3720a0b6b8a02 100644 (file)
@@ -66,7 +66,7 @@ struct ip_vs_dh_bucket {
 /*
  *     Returns hash value for IPVS DH entry
  */
-static inline unsigned ip_vs_dh_hashkey(__u32 addr)
+static inline unsigned ip_vs_dh_hashkey(__be32 addr)
 {
        return (ntohl(addr)*2654435761UL) & IP_VS_DH_TAB_MASK;
 }
@@ -76,7 +76,7 @@ static inline unsigned ip_vs_dh_hashkey(__u32 addr)
  *      Get ip_vs_dest associated with supplied parameters.
  */
 static inline struct ip_vs_dest *
-ip_vs_dh_get(struct ip_vs_dh_bucket *tbl, __u32 addr)
+ip_vs_dh_get(struct ip_vs_dh_bucket *tbl, __be32 addr)
 {
        return (tbl[ip_vs_dh_hashkey(addr)]).dest;
 }
index 37fafb1fbcff378b09c0b67449bada0bb5fddc0c..e433cb0ff894b19899f30788ea824b14fa237873 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/ip.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
+#include <asm/unaligned.h>
 
 #include <net/ip_vs.h>
 
@@ -44,8 +45,8 @@
  * List of ports (up to IP_VS_APP_MAX_PORTS) to be handled by helper
  * First port is set to the default port.
  */
-static int ports[IP_VS_APP_MAX_PORTS] = {21, 0};
-module_param_array(ports, int, NULL, 0);
+static unsigned short ports[IP_VS_APP_MAX_PORTS] = {21, 0};
+module_param_array(ports, ushort, NULL, 0);
 MODULE_PARM_DESC(ports, "Ports to monitor for FTP control commands");
 
 
@@ -74,7 +75,7 @@ ip_vs_ftp_done_conn(struct ip_vs_app *app, struct ip_vs_conn *cp)
  */
 static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
                                  const char *pattern, size_t plen, char term,
-                                 __u32 *addr, __u16 *port,
+                                 __be32 *addr, __be16 *port,
                                  char **start, char **end)
 {
        unsigned char p[6];
@@ -114,8 +115,8 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
        if (i != 5)
                return -1;
 
-       *addr = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
-       *port = (p[5]<<8) | p[4];
+       *addr = get_unaligned((__be32 *)p);
+       *port = get_unaligned((__be16 *)(p + 4));
        return 1;
 }
 
@@ -140,8 +141,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
        struct tcphdr *th;
        char *data, *data_limit;
        char *start, *end;
-       __u32 from;
-       __u16 port;
+       __be32 from;
+       __be16 port;
        struct ip_vs_conn *n_cp;
        char buf[24];           /* xxx.xxx.xxx.xxx,ppp,ppp\000 */
        unsigned buf_len;
@@ -199,7 +200,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
                from = n_cp->vaddr;
                port = n_cp->vport;
                sprintf(buf,"%d,%d,%d,%d,%d,%d", NIPQUAD(from),
-                       port&255, (port>>8)&255);
+                       ntohs(port)&255, (ntohs(port)>>8)&255);
                buf_len = strlen(buf);
 
                /*
@@ -243,8 +244,8 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
        struct tcphdr *th;
        char *data, *data_start, *data_limit;
        char *start, *end;
-       __u32 to;
-       __u16 port;
+       __be32 to;
+       __be16 port;
        struct ip_vs_conn *n_cp;
 
        /* no diff required for incoming packets */
@@ -365,12 +366,6 @@ static int __init ip_vs_ftp_init(void)
        for (i=0; i<IP_VS_APP_MAX_PORTS; i++) {
                if (!ports[i])
                        continue;
-               if (ports[i] < 0 || ports[i] > 0xffff) {
-                       IP_VS_WARNING("ip_vs_ftp: Ignoring invalid "
-                                     "configuration port[%d] = %d\n",
-                                     i, ports[i]);
-                       continue;
-               }
                ret = register_ip_vs_app_inc(app, app->protocol, ports[i]);
                if (ret)
                        break;
index 6e5cb92a5c83b114d4751093f13e6691c323a15f..524751e031de5203c12735d0aaa3c588dce675cd 100644 (file)
@@ -87,7 +87,7 @@ static int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ;
  */
 struct ip_vs_lblc_entry {
        struct list_head        list;
-       __u32                   addr;           /* destination IP address */
+       __be32                  addr;           /* destination IP address */
        struct ip_vs_dest       *dest;          /* real server (cache) */
        unsigned long           lastuse;        /* last used time */
 };
@@ -160,7 +160,7 @@ static struct ctl_table_header * sysctl_header;
  *      IP address to a server.
  */
 static inline struct ip_vs_lblc_entry *
-ip_vs_lblc_new(__u32 daddr, struct ip_vs_dest *dest)
+ip_vs_lblc_new(__be32 daddr, struct ip_vs_dest *dest)
 {
        struct ip_vs_lblc_entry *en;
 
@@ -195,7 +195,7 @@ static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en)
 /*
  *     Returns hash value for IPVS LBLC entry
  */
-static inline unsigned ip_vs_lblc_hashkey(__u32 addr)
+static inline unsigned ip_vs_lblc_hashkey(__be32 addr)
 {
        return (ntohl(addr)*2654435761UL) & IP_VS_LBLC_TAB_MASK;
 }
@@ -234,7 +234,7 @@ ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en)
  *  Get ip_vs_lblc_entry associated with supplied parameters.
  */
 static inline struct ip_vs_lblc_entry *
-ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __u32 addr)
+ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr)
 {
        unsigned hash;
        struct ip_vs_lblc_entry *en;
index 32ba37ba72d855cadbd92979df7edf1734f388ca..08990192b6eccbd5ec9e0abc06ac161b1491432c 100644 (file)
@@ -276,7 +276,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
  */
 struct ip_vs_lblcr_entry {
        struct list_head        list;
-       __u32                   addr;           /* destination IP address */
+       __be32                   addr;           /* destination IP address */
        struct ip_vs_dest_set   set;            /* destination server set */
        unsigned long           lastuse;        /* last used time */
 };
@@ -348,7 +348,7 @@ static struct ctl_table_header * sysctl_header;
  *      new/free a ip_vs_lblcr_entry, which is a mapping of a destination
  *      IP address to a server.
  */
-static inline struct ip_vs_lblcr_entry *ip_vs_lblcr_new(__u32 daddr)
+static inline struct ip_vs_lblcr_entry *ip_vs_lblcr_new(__be32 daddr)
 {
        struct ip_vs_lblcr_entry *en;
 
@@ -381,7 +381,7 @@ static inline void ip_vs_lblcr_free(struct ip_vs_lblcr_entry *en)
 /*
  *     Returns hash value for IPVS LBLCR entry
  */
-static inline unsigned ip_vs_lblcr_hashkey(__u32 addr)
+static inline unsigned ip_vs_lblcr_hashkey(__be32 addr)
 {
        return (ntohl(addr)*2654435761UL) & IP_VS_LBLCR_TAB_MASK;
 }
@@ -420,7 +420,7 @@ ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en)
  *  Get ip_vs_lblcr_entry associated with supplied parameters.
  */
 static inline struct ip_vs_lblcr_entry *
-ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __u32 addr)
+ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __be32 addr)
 {
        unsigned hash;
        struct ip_vs_lblcr_entry *en;
index 867d4e9c6594c3a62eb70475d6b2c26cfe74c2ca..c4528b5c800d04a257f2d806ed6414378b98ea31 100644 (file)
@@ -176,7 +176,7 @@ ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp,
                        pp->name, NIPQUAD(ih->saddr),
                        NIPQUAD(ih->daddr));
        else {
-               __u16 _ports[2], *pptr
+               __be16 _ports[2], *pptr
 ;
                pptr = skb_header_pointer(skb, offset + ih->ihl*4,
                                          sizeof(_ports), _ports);
index 820e8318d10df06be7412054814838b41e6ad17d..bfe779e74590e14be21af29fa35c6a54551ec231 100644 (file)
@@ -29,7 +29,7 @@ static struct ip_vs_conn *
 tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-       __u16 _ports[2], *pptr;
+       __be16 _ports[2], *pptr;
 
        pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
        if (pptr == NULL)
@@ -50,7 +50,7 @@ static struct ip_vs_conn *
 tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-       __u16 _ports[2], *pptr;
+       __be16 _ports[2], *pptr;
 
        pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
        if (pptr == NULL)
@@ -112,12 +112,12 @@ tcp_conn_schedule(struct sk_buff *skb,
 
 
 static inline void
-tcp_fast_csum_update(struct tcphdr *tcph, u32 oldip, u32 newip,
-                    u16 oldport, u16 newport)
+tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
+                    __be16 oldport, __be16 newport)
 {
        tcph->check =
                ip_vs_check_diff(~oldip, newip,
-                                ip_vs_check_diff(oldport ^ 0xFFFF,
+                                ip_vs_check_diff(oldport ^ htonl(0xFFFF),
                                                  newport, tcph->check));
 }
 
index 90c8166c0ec129a5c84aa449876ef4139bab9e48..54aa7603591f5c3e9091cb341d6ae4aab4bcd96f 100644 (file)
@@ -29,7 +29,7 @@ udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
        struct ip_vs_conn *cp;
-       __u16 _ports[2], *pptr;
+       __be16 _ports[2], *pptr;
 
        pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
        if (pptr == NULL)
@@ -54,7 +54,7 @@ udp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
                 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
        struct ip_vs_conn *cp;
-       __u16 _ports[2], *pptr;
+       __be16 _ports[2], *pptr;
 
        pptr = skb_header_pointer(skb, skb->nh.iph->ihl*4,
                                  sizeof(_ports), _ports);
@@ -117,15 +117,15 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
 
 
 static inline void
-udp_fast_csum_update(struct udphdr *uhdr, u32 oldip, u32 newip,
-                    u16 oldport, u16 newport)
+udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
+                    __be16 oldport, __be16 newport)
 {
        uhdr->check =
                ip_vs_check_diff(~oldip, newip,
-                                ip_vs_check_diff(oldport ^ 0xFFFF,
+                                ip_vs_check_diff(oldport ^ htonl(0xFFFF),
                                                  newport, uhdr->check));
        if (!uhdr->check)
-               uhdr->check = 0xFFFF;
+               uhdr->check = htonl(0xFFFF);
 }
 
 static int
@@ -173,7 +173,7 @@ udp_snat_handler(struct sk_buff **pskb,
                                                cp->protocol,
                                                (*pskb)->csum);
                if (udph->check == 0)
-                       udph->check = 0xFFFF;
+                       udph->check = htonl(0xFFFF);
                IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
                          pp->name, udph->check,
                          (char*)&(udph->check) - (char*)udph);
index 7775e6cc68be3a4597dc94b4d5ab0fc5e928a614..338668f88fe286a9b9c3cfaa05e32c7c334b01ea 100644 (file)
@@ -63,7 +63,7 @@ struct ip_vs_sh_bucket {
 /*
  *     Returns hash value for IPVS SH entry
  */
-static inline unsigned ip_vs_sh_hashkey(__u32 addr)
+static inline unsigned ip_vs_sh_hashkey(__be32 addr)
 {
        return (ntohl(addr)*2654435761UL) & IP_VS_SH_TAB_MASK;
 }
@@ -73,7 +73,7 @@ static inline unsigned ip_vs_sh_hashkey(__u32 addr)
  *      Get ip_vs_dest associated with supplied parameters.
  */
 static inline struct ip_vs_dest *
-ip_vs_sh_get(struct ip_vs_sh_bucket *tbl, __u32 addr)
+ip_vs_sh_get(struct ip_vs_sh_bucket *tbl, __be32 addr)
 {
        return (tbl[ip_vs_sh_hashkey(addr)]).dest;
 }
index 1bca714bda3d63c244afea44b39a9d26bb0814a9..91a075edd68e379fc8fcad685ac1ecd53c4801b7 100644 (file)
@@ -48,16 +48,16 @@ struct ip_vs_sync_conn {
 
        /* Protocol, addresses and port numbers */
        __u8                    protocol;       /* Which protocol (TCP/UDP) */
-       __u16                   cport;
-       __u16                   vport;
-       __u16                   dport;
-       __u32                   caddr;          /* client address */
-       __u32                   vaddr;          /* virtual address */
-       __u32                   daddr;          /* destination address */
+       __be16                  cport;
+       __be16                  vport;
+       __be16                  dport;
+       __be32                  caddr;          /* client address */
+       __be32                  vaddr;          /* virtual address */
+       __be32                  daddr;          /* destination address */
 
        /* Flags and state transition */
-       __u16                   flags;          /* status flags */
-       __u16                   state;          /* state info */
+       __be16                  flags;          /* status flags */
+       __be16                  state;          /* state info */
 
        /* The sequence options start here */
 };
@@ -464,7 +464,7 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
 static int bind_mcastif_addr(struct socket *sock, char *ifname)
 {
        struct net_device *dev;
-       u32 addr;
+       __be32 addr;
        struct sockaddr_in sin;
 
        if ((dev = __dev_get_by_name(ifname)) == NULL)
@@ -836,7 +836,7 @@ static int fork_sync_thread(void *startup)
 
 int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
 {
-       DECLARE_COMPLETION(startup);
+       DECLARE_COMPLETION_ONSTACK(startup);
        pid_t pid;
 
        if ((state == IP_VS_STATE_MASTER && sync_master_pid) ||
index 52c12e9edbbc48a2d6d5bb47f76585a976709ef9..e1f77bd7c9a52a940036c4b8a633c29a74d3e8e2 100644 (file)
@@ -232,7 +232,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
        /* check if it is a connection of no-client-port */
        if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
-               __u16 _pt, *p;
+               __be16 _pt, *p;
                p = skb_header_pointer(skb, iph->ihl*4, sizeof(_pt), &_pt);
                if (p == NULL)
                        goto tx_error;
index d25ec4ae09e55ca2d9e0eb6d8dbc38de10b7849c..92b04823e034292328be4cf92c2891ce8e05b9fd 100644 (file)
@@ -60,8 +60,8 @@ struct multipath_dest {
        struct list_head        list;
 
        const struct fib_nh     *nh_info;
-       __u32                   netmask;
-       __u32                   network;
+       __be32                  netmask;
+       __be32                  network;
        unsigned char           prefixlen;
 
        struct rcu_head         rcu;
@@ -76,7 +76,7 @@ struct multipath_route {
        struct list_head        list;
 
        int                     oif;
-       __u32                   gw;
+       __be32                  gw;
        struct list_head        dests;
 
        struct rcu_head         rcu;
@@ -128,8 +128,8 @@ static unsigned char __multipath_lookup_weight(const struct flowi *fl,
 
        /* find state entry for destination */
        list_for_each_entry_rcu(d, &target_route->dests, list) {
-               __u32 targetnetwork = fl->fl4_dst & 
-                       (0xFFFFFFFF >> (32 - d->prefixlen));
+               __be32 targetnetwork = fl->fl4_dst &
+                       inet_make_mask(d->prefixlen);
 
                if ((targetnetwork & d->netmask) == d->network) {
                        weight = d->nh_info->nh_weight;
@@ -217,8 +217,8 @@ static void wrandom_select_route(const struct flowi *flp,
        *rp = decision;
 }
 
-static void wrandom_set_nhinfo(__u32 network,
-                              __u32 netmask,
+static void wrandom_set_nhinfo(__be32 network,
+                              __be32 netmask,
                               unsigned char prefixlen,
                               const struct fib_nh *nh)
 {
index f88347de21a9927a2877b11b0cf31d39979b6763..5ac15379a0cfd15d76c0f7c06145d8da58ba6049 100644 (file)
@@ -128,8 +128,8 @@ EXPORT_SYMBOL(ip_nat_decode_session);
  */
 
 struct ip_rt_info {
-       u_int32_t daddr;
-       u_int32_t saddr;
+       __be32 daddr;
+       __be32 saddr;
        u_int8_t tos;
 };
 
index 85f0d73ebfb4cd19fccfea105819b95dcf7e42f0..17e1a687ab4553e76f53a40029c4f87599d49df9 100644 (file)
@@ -80,7 +80,7 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
 {
        char *arpptr = (char *)(arphdr + 1);
        char *src_devaddr, *tgt_devaddr;
-       u32 src_ipaddr, tgt_ipaddr;
+       __be32 src_ipaddr, tgt_ipaddr;
        int i, ret;
 
 #define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg))
index 0a7bd7f04061f89b55f1e2b7a596f5b0b17ca15f..6c7383a8e42b940c355005091876de8b6396c6c7 100644 (file)
@@ -155,11 +155,11 @@ static int help(struct sk_buff **pskb,
                exp->tuple.dst.protonum = IPPROTO_TCP;
                exp->tuple.dst.u.tcp.port = htons(port);
 
-               exp->mask.src.ip = 0xFFFFFFFF;
+               exp->mask.src.ip = htonl(0xFFFFFFFF);
                exp->mask.src.u.tcp.port = 0;
-               exp->mask.dst.ip = 0xFFFFFFFF;
+               exp->mask.dst.ip = htonl(0xFFFFFFFF);
                exp->mask.dst.protonum = 0xFF;
-               exp->mask.dst.u.tcp.port = 0xFFFF;
+               exp->mask.dst.u.tcp.port = htons(0xFFFF);
 
                if (ip_nat_amanda_hook)
                        ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
index c432b31636091133650ebfea5a04241443e3b59c..143c4668538b40203063e2c6c741b395a0bf3fef 100644 (file)
@@ -149,8 +149,8 @@ static unsigned int ip_conntrack_hash_rnd;
 static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
                            unsigned int size, unsigned int rnd)
 {
-       return (jhash_3words(tuple->src.ip,
-                            (tuple->dst.ip ^ tuple->dst.protonum),
+       return (jhash_3words((__force u32)tuple->src.ip,
+                            ((__force u32)tuple->dst.ip ^ tuple->dst.protonum),
                             (tuple->src.u.all | (tuple->dst.u.all << 16)),
                             rnd) % size);
 }
@@ -1169,9 +1169,9 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
 int ip_ct_port_tuple_to_nfattr(struct sk_buff *skb,
                               const struct ip_conntrack_tuple *tuple)
 {
-       NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
+       NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(__be16),
                &tuple->src.u.tcp.port);
-       NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
+       NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(__be16),
                &tuple->dst.u.tcp.port);
        return 0;
 
@@ -1186,9 +1186,9 @@ int ip_ct_port_nfattr_to_tuple(struct nfattr *tb[],
                return -EINVAL;
 
        t->src.u.tcp.port =
-               *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
+               *(__be16 *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
        t->dst.u.tcp.port =
-               *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
+               *(__be16 *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
 
        return 0;
 }
index 1d18c863f064d67fbba87db04c01020327c2025c..93dcf960662f66232fbbce45f7131f76fe1a5e34 100644 (file)
@@ -425,8 +425,8 @@ static int help(struct sk_buff **pskb,
        exp->tuple.src.u.tcp.port = 0; /* Don't care. */
        exp->tuple.dst.protonum = IPPROTO_TCP;
        exp->mask = ((struct ip_conntrack_tuple)
-               { { 0xFFFFFFFF, { 0 } },
-                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+               { { htonl(0xFFFFFFFF), { 0 } },
+                 { htonl(0xFFFFFFFF), { .tcp = { htons(0xFFFF) } }, 0xFF }});
 
        exp->expectfn = NULL;
        exp->flags = 0;
@@ -488,7 +488,7 @@ static int __init ip_conntrack_ftp_init(void)
        for (i = 0; i < ports_c; i++) {
                ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
                ftp[i].tuple.dst.protonum = IPPROTO_TCP;
-               ftp[i].mask.src.u.tcp.port = 0xFFFF;
+               ftp[i].mask.src.u.tcp.port = htons(0xFFFF);
                ftp[i].mask.dst.protonum = 0xFF;
                ftp[i].max_expected = 1;
                ftp[i].timeout = 5 * 60; /* 5 minutes */
index 9a39e2969712701d0ab45b9bb0dcd1d3c6ccf0e6..7b7441202bfd6e14505142a6b0d270c77f73042f 100644 (file)
@@ -49,11 +49,11 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
 int (*set_h245_addr_hook) (struct sk_buff ** pskb,
                           unsigned char **data, int dataoff,
                           H245_TransportAddress * addr,
-                          u_int32_t ip, u_int16_t port);
+                          __be32 ip, u_int16_t port);
 int (*set_h225_addr_hook) (struct sk_buff ** pskb,
                           unsigned char **data, int dataoff,
                           TransportAddress * addr,
-                          u_int32_t ip, u_int16_t port);
+                          __be32 ip, u_int16_t port);
 int (*set_sig_addr_hook) (struct sk_buff ** pskb,
                          struct ip_conntrack * ct,
                          enum ip_conntrack_info ctinfo,
@@ -209,7 +209,7 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
 
 /****************************************************************************/
 static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
-                        u_int32_t * ip, u_int16_t * port)
+                        __be32 * ip, u_int16_t * port)
 {
        unsigned char *p;
 
@@ -232,7 +232,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        u_int16_t rtp_port;
        struct ip_conntrack_expect *rtp_exp;
@@ -254,10 +254,10 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
        rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
        rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);
        rtp_exp->tuple.dst.protonum = IPPROTO_UDP;
-       rtp_exp->mask.src.ip = 0xFFFFFFFF;
+       rtp_exp->mask.src.ip = htonl(0xFFFFFFFF);
        rtp_exp->mask.src.u.udp.port = 0;
-       rtp_exp->mask.dst.ip = 0xFFFFFFFF;
-       rtp_exp->mask.dst.u.udp.port = 0xFFFF;
+       rtp_exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       rtp_exp->mask.dst.u.udp.port = htons(0xFFFF);
        rtp_exp->mask.dst.protonum = 0xFF;
        rtp_exp->flags = 0;
 
@@ -271,10 +271,10 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
        rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
        rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);
        rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;
-       rtcp_exp->mask.src.ip = 0xFFFFFFFF;
+       rtcp_exp->mask.src.ip = htonl(0xFFFFFFFF);
        rtcp_exp->mask.src.u.udp.port = 0;
-       rtcp_exp->mask.dst.ip = 0xFFFFFFFF;
-       rtcp_exp->mask.dst.u.udp.port = 0xFFFF;
+       rtcp_exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       rtcp_exp->mask.dst.u.udp.port = htons(0xFFFF);
        rtcp_exp->mask.dst.protonum = 0xFF;
        rtcp_exp->flags = 0;
 
@@ -325,7 +325,7 @@ static int expect_t120(struct sk_buff **pskb,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
 
@@ -342,10 +342,10 @@ static int expect_t120(struct sk_buff **pskb,
        exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_TCP;
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = IP_CT_EXPECT_PERMANENT;    /* Accept multiple channels */
 
@@ -626,7 +626,7 @@ void ip_conntrack_h245_expect(struct ip_conntrack *new,
 
 /****************************************************************************/
 int get_h225_addr(unsigned char *data, TransportAddress * addr,
-                 u_int32_t * ip, u_int16_t * port)
+                 __be32 * ip, u_int16_t * port)
 {
        unsigned char *p;
 
@@ -648,7 +648,7 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
 
@@ -665,10 +665,10 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
        exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_TCP;
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = 0;
 
@@ -709,7 +709,7 @@ static int expect_callforwarding(struct sk_buff **pskb,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
 
@@ -751,10 +751,10 @@ static int expect_callforwarding(struct sk_buff **pskb,
        exp->tuple.dst.ip = ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_TCP;
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = 0;
 
@@ -791,7 +791,7 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret;
        int i;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
 
        DEBUGP("ip_ct_q931: Setup\n");
@@ -1188,7 +1188,7 @@ static unsigned char *get_udp_data(struct sk_buff **pskb, int *datalen)
 
 /****************************************************************************/
 static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct,
-                                              u_int32_t ip, u_int16_t port)
+                                              __be32 ip, u_int16_t port)
 {
        struct ip_conntrack_expect *exp;
        struct ip_conntrack_tuple tuple;
@@ -1228,7 +1228,7 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
        int i;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp;
 
@@ -1251,10 +1251,10 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
        exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_TCP;
-       exp->mask.src.ip = gkrouted_only ? 0xFFFFFFFF : 0;
+       exp->mask.src.ip = gkrouted_only ? htonl(0xFFFFFFFF) : 0;
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = IP_CT_EXPECT_PERMANENT;    /* Accept multiple calls */
 
@@ -1307,7 +1307,7 @@ static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp;
 
@@ -1333,10 +1333,10 @@ static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct,
        exp->tuple.dst.ip = ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_UDP;
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = 0;
        exp->expectfn = ip_conntrack_ras_expect;
@@ -1477,7 +1477,7 @@ static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
        int dir = CTINFO2DIR(ctinfo);
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
 
        DEBUGP("ip_ct_ras: ARQ\n");
@@ -1513,7 +1513,7 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp;
 
@@ -1538,10 +1538,10 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
        exp->tuple.dst.ip = ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_TCP;
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = IP_CT_EXPECT_PERMANENT;
        exp->expectfn = ip_conntrack_q931_expect;
@@ -1581,7 +1581,7 @@ static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        int dir = CTINFO2DIR(ctinfo);
        int ret = 0;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
        struct ip_conntrack_expect *exp = NULL;
 
@@ -1598,10 +1598,10 @@ static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct,
        exp->tuple.dst.ip = ip;
        exp->tuple.dst.u.tcp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_TCP;
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.tcp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.tcp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
        exp->flags = IP_CT_EXPECT_PERMANENT;
        exp->expectfn = ip_conntrack_q931_expect;
index fb0aee691721444ddb8551ca0460d8fcd8cbec1e..a2af5e0c7f9938b25f91618478fd8081220909a6 100644 (file)
@@ -242,10 +242,10 @@ exp_gre(struct ip_conntrack *ct,
        exp_orig->tuple.dst.u.gre.key = callid;
        exp_orig->tuple.dst.protonum = IPPROTO_GRE;
 
-       exp_orig->mask.src.ip = 0xffffffff;
+       exp_orig->mask.src.ip = htonl(0xffffffff);
        exp_orig->mask.src.u.all = 0;
        exp_orig->mask.dst.u.gre.key = htons(0xffff);
-       exp_orig->mask.dst.ip = 0xffffffff;
+       exp_orig->mask.dst.ip = htonl(0xffffffff);
        exp_orig->mask.dst.protonum = 0xff;
 
        exp_orig->master = ct;
index 44889075f3b2df3ed85807fb87cd5bc536e679aa..75f7c3db16196d3fbdd585defabca1771067fe9b 100644 (file)
@@ -218,7 +218,8 @@ static int help(struct sk_buff **pskb,
                                    IPPROTO_TCP }});
                        exp->mask = ((struct ip_conntrack_tuple)
                                { { 0, { 0 } },
-                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
+                                 { htonl(0xFFFFFFFF),
+                                       { .tcp = { htons(0xFFFF) } }, 0xFF }});
                        exp->expectfn = NULL;
                        exp->flags = 0;
                        if (ip_nat_irc_hook)
@@ -266,7 +267,7 @@ static int __init ip_conntrack_irc_init(void)
                hlpr = &irc_helpers[i];
                hlpr->tuple.src.u.tcp.port = htons(ports[i]);
                hlpr->tuple.dst.protonum = IPPROTO_TCP;
-               hlpr->mask.src.u.tcp.port = 0xFFFF;
+               hlpr->mask.src.u.tcp.port = htons(0xFFFF);
                hlpr->mask.dst.protonum = 0xFF;
                hlpr->max_expected = max_dcc_channels;
                hlpr->timeout = dcc_timeout;
index 3d0b438783db0a71787a87a6815d182025e9f535..a1d6a89f64aa44b140eaa46473562f89508ec7c9 100644 (file)
@@ -48,7 +48,7 @@ static int help(struct sk_buff **pskb,
        struct iphdr *iph = (*pskb)->nh.iph;
        struct rtable *rt = (struct rtable *)(*pskb)->dst;
        struct in_device *in_dev;
-       u_int32_t mask = 0;
+       __be32 mask = 0;
 
        /* we're only interested in locally generated packets */
        if ((*pskb)->sk == NULL)
@@ -78,12 +78,12 @@ static int help(struct sk_buff **pskb,
                goto out;
 
        exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-       exp->tuple.src.u.udp.port = ntohs(NMBD_PORT);
+       exp->tuple.src.u.udp.port = htons(NMBD_PORT);
 
        exp->mask.src.ip          = mask;
-       exp->mask.src.u.udp.port  = 0xFFFF;
-       exp->mask.dst.ip          = 0xFFFFFFFF;
-       exp->mask.dst.u.udp.port  = 0xFFFF;
+       exp->mask.src.u.udp.port  = htons(0xFFFF);
+       exp->mask.dst.ip          = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.udp.port  = htons(0xFFFF);
        exp->mask.dst.protonum    = 0xFF;
 
        exp->expectfn             = NULL;
@@ -115,7 +115,7 @@ static struct ip_conntrack_helper helper = {
                .src = {
                        .u = {
                                .udp = {
-                                       .port   = 0xFFFF,
+                                       .port   = __constant_htons(0xFFFF),
                                }
                        }
                },
index 52eddea27e93706b2cca87c1923fd901b6146276..53b6dffea6c2174fcf49f30e7844010c015a3772 100644 (file)
@@ -78,8 +78,8 @@ ctnetlink_dump_tuples_ip(struct sk_buff *skb,
 {
        struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
        
-       NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
-       NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
+       NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(__be32), &tuple->src.ip);
+       NFA_PUT(skb, CTA_IP_V4_DST, sizeof(__be32), &tuple->dst.ip);
 
        NFA_NEST_END(skb, nest_parms);
 
@@ -110,7 +110,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
 static inline int
 ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-       u_int32_t status = htonl((u_int32_t) ct->status);
+       __be32 status = htonl((u_int32_t) ct->status);
        NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
        return 0;
 
@@ -122,7 +122,7 @@ static inline int
 ctnetlink_dump_timeout(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
        long timeout_l = ct->timeout.expires - jiffies;
-       u_int32_t timeout;
+       __be32 timeout;
 
        if (timeout_l < 0)
                timeout = 0;
@@ -192,13 +192,13 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct,
 {
        enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
        struct nfattr *nest_count = NFA_NEST(skb, type);
-       u_int32_t tmp;
+       __be32 tmp;
 
        tmp = htonl(ct->counters[dir].packets);
-       NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
+       NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(__be32), &tmp);
 
        tmp = htonl(ct->counters[dir].bytes);
-       NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
+       NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(__be32), &tmp);
 
        NFA_NEST_END(skb, nest_count);
 
@@ -215,9 +215,9 @@ nfattr_failure:
 static inline int
 ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-       u_int32_t mark = htonl(ct->mark);
+       __be32 mark = htonl(ct->mark);
 
-       NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
+       NFA_PUT(skb, CTA_MARK, sizeof(__be32), &mark);
        return 0;
 
 nfattr_failure:
@@ -230,8 +230,8 @@ nfattr_failure:
 static inline int
 ctnetlink_dump_id(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-       u_int32_t id = htonl(ct->id);
-       NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
+       __be32 id = htonl(ct->id);
+       NFA_PUT(skb, CTA_ID, sizeof(__be32), &id);
        return 0;
 
 nfattr_failure:
@@ -241,9 +241,9 @@ nfattr_failure:
 static inline int
 ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-       u_int32_t use = htonl(atomic_read(&ct->ct_general.use));
+       __be32 use = htonl(atomic_read(&ct->ct_general.use));
        
-       NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
+       NFA_PUT(skb, CTA_USE, sizeof(__be32), &use);
        return 0;
 
 nfattr_failure:
@@ -457,8 +457,8 @@ out:
 }
 
 static const size_t cta_min_ip[CTA_IP_MAX] = {
-       [CTA_IP_V4_SRC-1]       = sizeof(u_int32_t),
-       [CTA_IP_V4_DST-1]       = sizeof(u_int32_t),
+       [CTA_IP_V4_SRC-1]       = sizeof(__be32),
+       [CTA_IP_V4_DST-1]       = sizeof(__be32),
 };
 
 static inline int
@@ -475,11 +475,11 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
 
        if (!tb[CTA_IP_V4_SRC-1])
                return -EINVAL;
-       tuple->src.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
+       tuple->src.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
 
        if (!tb[CTA_IP_V4_DST-1])
                return -EINVAL;
-       tuple->dst.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
+       tuple->dst.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
 
        DEBUGP("leaving\n");
 
@@ -602,8 +602,8 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
 }
 
 static const size_t cta_min_nat[CTA_NAT_MAX] = {
-       [CTA_NAT_MINIP-1]       = sizeof(u_int32_t),
-       [CTA_NAT_MAXIP-1]       = sizeof(u_int32_t),
+       [CTA_NAT_MINIP-1]       = sizeof(__be32),
+       [CTA_NAT_MAXIP-1]       = sizeof(__be32),
 };
 
 static inline int
@@ -623,12 +623,12 @@ ctnetlink_parse_nat(struct nfattr *nat,
                return -EINVAL;
 
        if (tb[CTA_NAT_MINIP-1])
-               range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
+               range->min_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
 
        if (!tb[CTA_NAT_MAXIP-1])
                range->max_ip = range->min_ip;
        else
-               range->max_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
+               range->max_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
 
        if (range->min_ip)
                range->flags |= IP_NAT_RANGE_MAP_IPS;
@@ -663,11 +663,11 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
 }
 
 static const size_t cta_min[CTA_MAX] = {
-       [CTA_STATUS-1]          = sizeof(u_int32_t),
-       [CTA_TIMEOUT-1]         = sizeof(u_int32_t),
-       [CTA_MARK-1]            = sizeof(u_int32_t),
-       [CTA_USE-1]             = sizeof(u_int32_t),
-       [CTA_ID-1]              = sizeof(u_int32_t)
+       [CTA_STATUS-1]          = sizeof(__be32),
+       [CTA_TIMEOUT-1]         = sizeof(__be32),
+       [CTA_MARK-1]            = sizeof(__be32),
+       [CTA_USE-1]             = sizeof(__be32),
+       [CTA_ID-1]              = sizeof(__be32)
 };
 
 static int
@@ -706,7 +706,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
        ct = tuplehash_to_ctrack(h);
        
        if (cda[CTA_ID-1]) {
-               u_int32_t id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+               u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
                if (ct->id != id) {
                        ip_conntrack_put(ct);
                        return -ENOENT;
@@ -808,7 +808,7 @@ static inline int
 ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
 {
        unsigned long d;
-       unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
+       unsigned status = ntohl(*(__be32 *)NFA_DATA(cda[CTA_STATUS-1]));
        d = ct->status ^ status;
 
        if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -903,7 +903,7 @@ ctnetlink_change_helper(struct ip_conntrack *ct, struct nfattr *cda[])
 static inline int
 ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
 {
-       u_int32_t timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+       u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
        
        if (!del_timer(&ct->timeout))
                return -ETIME;
@@ -966,7 +966,7 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
 
 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
        if (cda[CTA_MARK-1])
-               ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+               ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
        DEBUGP("all done\n");
@@ -989,7 +989,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
 
        if (!cda[CTA_TIMEOUT-1])
                goto err;
-       ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+       ct->timeout.expires = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
 
        ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
        ct->status |= IPS_CONFIRMED;
@@ -1006,7 +1006,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
 
 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
        if (cda[CTA_MARK-1])
-               ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+               ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
        ct->helper = ip_conntrack_helper_find_get(rtuple);
@@ -1138,8 +1138,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
                           const struct ip_conntrack_expect *exp)
 {
        struct ip_conntrack *master = exp->master;
-       u_int32_t timeout = htonl((exp->timeout.expires - jiffies) / HZ);
-       u_int32_t id = htonl(exp->id);
+       __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
+       __be32 id = htonl(exp->id);
 
        if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
                goto nfattr_failure;
@@ -1150,8 +1150,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
                                 CTA_EXPECT_MASTER) < 0)
                goto nfattr_failure;
        
-       NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
-       NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
+       NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(__be32), &timeout);
+       NFA_PUT(skb, CTA_EXPECT_ID, sizeof(__be32), &id);
 
        return 0;
        
@@ -1272,8 +1272,8 @@ out:
 }
 
 static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
-       [CTA_EXPECT_TIMEOUT-1]          = sizeof(u_int32_t),
-       [CTA_EXPECT_ID-1]               = sizeof(u_int32_t)
+       [CTA_EXPECT_TIMEOUT-1]          = sizeof(__be32),
+       [CTA_EXPECT_ID-1]               = sizeof(__be32)
 };
 
 static int
@@ -1321,7 +1321,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
                return -ENOENT;
 
        if (cda[CTA_EXPECT_ID-1]) {
-               u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+               __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
                if (exp->id != ntohl(id)) {
                        ip_conntrack_expect_put(exp);
                        return -ENOENT;
@@ -1375,8 +1375,8 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
                        return -ENOENT;
 
                if (cda[CTA_EXPECT_ID-1]) {
-                       u_int32_t id = 
-                               *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
+                       __be32 id =
+                               *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
                        if (exp->id != ntohl(id)) {
                                ip_conntrack_expect_put(exp);
                                return -ENOENT;
index 09c40ebe3345f0221d0c32934004a9dc6316706a..295b6fa340dbc021e440c77cd92de51c03291164 100644 (file)
@@ -261,7 +261,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
 static int icmp_tuple_to_nfattr(struct sk_buff *skb,
                                const struct ip_conntrack_tuple *t)
 {
-       NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t),
+       NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(__be16),
                &t->src.u.icmp.id);
        NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
                &t->dst.u.icmp.type);
@@ -287,7 +287,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
        tuple->dst.u.icmp.code =
                        *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
        tuple->src.u.icmp.id =
-                       *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+                       *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
 
        if (tuple->dst.u.icmp.type >= sizeof(invmap)
            || !invmap[tuple->dst.u.icmp.type])
index b908a4842e186d3cf192dd500bc49e9a509db602..2443322e4128ac3f054fabd442cc80713b71dbc5 100644 (file)
@@ -210,7 +210,7 @@ static int sctp_print_conntrack(struct seq_file *s,
 for (offset = skb->nh.iph->ihl * 4 + sizeof(sctp_sctphdr_t), count = 0;        \
        offset < skb->len &&                                            \
        (sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch));   \
-       offset += (htons(sch->length) + 3) & ~3, count++)
+       offset += (ntohs(sch->length) + 3) & ~3, count++)
 
 /* Some validity checks to make sure the chunks are fine */
 static int do_basic_checks(struct ip_conntrack *conntrack,
index 03ae9a04cb37c39351735394222f5de4b5b967a8..06e4e8a6dd9f88db85452c556d51058025db3dde 100644 (file)
@@ -519,8 +519,8 @@ static void tcp_sack(const struct sk_buff *skb,
 
        /* Fast path for timestamp-only option */
        if (length == TCPOLEN_TSTAMP_ALIGNED*4
-           && *(__u32 *)ptr ==
-               __constant_ntohl((TCPOPT_NOP << 24) 
+           && *(__be32 *)ptr ==
+               __constant_htonl((TCPOPT_NOP << 24)
                                 | (TCPOPT_NOP << 16)
                                 | (TCPOPT_TIMESTAMP << 8)
                                 | TCPOLEN_TIMESTAMP))
@@ -551,7 +551,7 @@ static void tcp_sack(const struct sk_buff *skb,
                                for (i = 0;
                                     i < (opsize - TCPOLEN_SACK_BASE);
                                     i += TCPOLEN_SACK_PERBLOCK) {
-                                       tmp = ntohl(*((u_int32_t *)(ptr+i)+1));
+                                       tmp = ntohl(*((__be32 *)(ptr+i)+1));
                                        
                                        if (after(tmp, *sack))
                                                *sack = tmp;
index 2893e9c748506627f9abce8cec1a32fb576bdd1a..f4f75995a9e4cb9c4941d5ff06b0bed6a017a4da 100644 (file)
@@ -193,7 +193,7 @@ static int skp_digits_len(const char *dptr, const char *limit, int *shift)
 
 /* Simple ipaddr parser.. */
 static int parse_ipaddr(const char *cp,        const char **endp,
-                       u_int32_t *ipaddr, const char *limit)
+                       __be32 *ipaddr, const char *limit)
 {
        unsigned long int val;
        int i, digit = 0;
@@ -227,7 +227,7 @@ static int parse_ipaddr(const char *cp,     const char **endp,
 static int epaddr_len(const char *dptr, const char *limit, int *shift)
 {
        const char *aux = dptr;
-       u_int32_t ip;
+       __be32 ip;
 
        if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
                DEBUGP("ip: %s parse failed.!\n", dptr);
@@ -302,7 +302,7 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
 static int set_expected_rtp(struct sk_buff **pskb,
                            struct ip_conntrack *ct,
                            enum ip_conntrack_info ctinfo,
-                           u_int32_t ipaddr, u_int16_t port,
+                           __be32 ipaddr, u_int16_t port,
                            const char *dptr)
 {
        struct ip_conntrack_expect *exp;
@@ -319,10 +319,10 @@ static int set_expected_rtp(struct sk_buff **pskb,
        exp->tuple.dst.u.udp.port = htons(port);
        exp->tuple.dst.protonum = IPPROTO_UDP;
 
-       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.ip = htonl(0xFFFFFFFF);
        exp->mask.src.u.udp.port = 0;
-       exp->mask.dst.ip = 0xFFFFFFFF;
-       exp->mask.dst.u.udp.port = 0xFFFF;
+       exp->mask.dst.ip = htonl(0xFFFFFFFF);
+       exp->mask.dst.u.udp.port = htons(0xFFFF);
        exp->mask.dst.protonum = 0xFF;
 
        exp->expectfn = NULL;
@@ -349,7 +349,7 @@ static int sip_help(struct sk_buff **pskb,
        const char *dptr;
        int ret = NF_ACCEPT;
        int matchoff, matchlen;
-       u_int32_t ipaddr;
+       __be32 ipaddr;
        u_int16_t port;
 
        /* No Data ? */
@@ -439,7 +439,7 @@ static int __init init(void)
 
                sip[i].tuple.dst.protonum = IPPROTO_UDP;
                sip[i].tuple.src.u.udp.port = htons(ports[i]);
-               sip[i].mask.src.u.udp.port = 0xFFFF;
+               sip[i].mask.src.u.udp.port = htons(0xFFFF);
                sip[i].mask.dst.protonum = 0xFF;
                sip[i].max_expected = 2;
                sip[i].timeout = 3 * 60; /* 3 minutes */
index 7e33d3bed5e3831e8b0a57ed06de304e3144b707..fe0b634dd37761fd15d341698cf45c0158485631 100644 (file)
@@ -70,10 +70,10 @@ static int tftp_help(struct sk_buff **pskb,
                        return NF_DROP;
 
                exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-               exp->mask.src.ip = 0xffffffff;
+               exp->mask.src.ip = htonl(0xffffffff);
                exp->mask.src.u.udp.port = 0;
-               exp->mask.dst.ip = 0xffffffff;
-               exp->mask.dst.u.udp.port = 0xffff;
+               exp->mask.dst.ip = htonl(0xffffffff);
+               exp->mask.dst.u.udp.port = htons(0xffff);
                exp->mask.dst.protonum = 0xff;
                exp->expectfn = NULL;
                exp->flags = 0;
@@ -129,7 +129,7 @@ static int __init ip_conntrack_tftp_init(void)
                tftp[i].tuple.dst.protonum = IPPROTO_UDP;
                tftp[i].tuple.src.u.udp.port = htons(ports[i]);
                tftp[i].mask.dst.protonum = 0xFF;
-               tftp[i].mask.src.u.udp.port = 0xFFFF;
+               tftp[i].mask.src.u.udp.port = htons(0xFFFF);
                tftp[i].max_expected = 1;
                tftp[i].timeout = 5 * 60; /* 5 minutes */
                tftp[i].me = THIS_MODULE;
index 71f3e09cbc84b456f5488d9f7a49b1ba7a7fa819..4b6260a974085f754278d3a727f76f821ac92b7a 100644 (file)
@@ -82,7 +82,7 @@ static inline unsigned int
 hash_by_src(const struct ip_conntrack_tuple *tuple)
 {
        /* Original src, to ensure we map it consistently if poss. */
-       return jhash_3words(tuple->src.ip, tuple->src.u.all,
+       return jhash_3words((__force u32)tuple->src.ip, tuple->src.u.all,
                            tuple->dst.protonum, 0) % ip_nat_htable_size;
 }
 
@@ -190,7 +190,7 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple,
                    const struct ip_conntrack *conntrack,
                    enum ip_nat_manip_type maniptype)
 {
-       u_int32_t *var_ipp;
+       __be32 *var_ipp;
        /* Host order */
        u_int32_t minip, maxip, j;
 
@@ -217,7 +217,7 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple,
         * like this), even across reboots. */
        minip = ntohl(range->min_ip);
        maxip = ntohl(range->max_ip);
-       j = jhash_2words(tuple->src.ip, tuple->dst.ip, 0);
+       j = jhash_2words((__force u32)tuple->src.ip, (__force u32)tuple->dst.ip, 0);
        *var_ipp = htonl(minip + j % (maxip - minip + 1));
 }
 
@@ -534,9 +534,9 @@ int
 ip_nat_port_range_to_nfattr(struct sk_buff *skb, 
                            const struct ip_nat_range *range)
 {
-       NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(u_int16_t),
+       NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16),
                &range->min.tcp.port);
-       NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(u_int16_t),
+       NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(__be16),
                &range->max.tcp.port);
 
        return 0;
@@ -555,7 +555,7 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
        if (tb[CTA_PROTONAT_PORT_MIN-1]) {
                ret = 1;
                range->min.tcp.port = 
-                       *(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
+                       *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
        }
        
        if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
@@ -564,7 +564,7 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
        } else {
                ret = 1;
                range->max.tcp.port = 
-                       *(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
+                       *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
        }
 
        return ret;
index 3328fc5c5f500e381daa205f111e9319b686b71f..a71c233d8112b9cb9888ab3e3cff4d71ed9061a3 100644 (file)
@@ -34,7 +34,7 @@ MODULE_DESCRIPTION("ftp NAT helper");
 
 static int
 mangle_rfc959_packet(struct sk_buff **pskb,
-                    u_int32_t newip,
+                    __be32 newip,
                     u_int16_t port,
                     unsigned int matchoff,
                     unsigned int matchlen,
@@ -57,7 +57,7 @@ mangle_rfc959_packet(struct sk_buff **pskb,
 /* |1|132.235.1.2|6275| */
 static int
 mangle_eprt_packet(struct sk_buff **pskb,
-                  u_int32_t newip,
+                  __be32 newip,
                   u_int16_t port,
                   unsigned int matchoff,
                   unsigned int matchlen,
@@ -79,7 +79,7 @@ mangle_eprt_packet(struct sk_buff **pskb,
 /* |1|132.235.1.2|6275| */
 static int
 mangle_epsv_packet(struct sk_buff **pskb,
-                  u_int32_t newip,
+                  __be32 newip,
                   u_int16_t port,
                   unsigned int matchoff,
                   unsigned int matchlen,
@@ -98,7 +98,7 @@ mangle_epsv_packet(struct sk_buff **pskb,
                                        matchlen, buffer, strlen(buffer));
 }
 
-static int (*mangle[])(struct sk_buff **, u_int32_t, u_int16_t,
+static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
                     unsigned int,
                     unsigned int,
                     struct ip_conntrack *,
@@ -120,7 +120,7 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb,
                               struct ip_conntrack_expect *exp,
                               u32 *seq)
 {
-       u_int32_t newip;
+       __be32 newip;
        u_int16_t port;
        int dir = CTINFO2DIR(ctinfo);
        struct ip_conntrack *ct = exp->master;
index 7f6a75984f6c7830ea7a4382869a65a1607d035c..3bf858480558fe26b4c93ef515ebcd9721340e65 100644 (file)
@@ -189,7 +189,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
                                                        datalen, 0));
        } else
                tcph->check = nf_proto_csum_update(*pskb,
-                                                  htons(oldlen) ^ 0xFFFF,
+                                                  htons(oldlen) ^ htons(0xFFFF),
                                                   htons(datalen),
                                                   tcph->check, 1);
 
@@ -267,7 +267,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
                        udph->check = -1;
        } else
                udph->check = nf_proto_csum_update(*pskb,
-                                                  htons(oldlen) ^ 0xFFFF,
+                                                  htons(oldlen) ^ htons(0xFFFF),
                                                   htons(datalen),
                                                   udph->check, 1);
        return 1;
@@ -283,27 +283,25 @@ sack_adjust(struct sk_buff *skb,
            struct ip_nat_seq *natseq)
 {
        while (sackoff < sackend) {
-               struct tcp_sack_block *sack;
-               u_int32_t new_start_seq, new_end_seq;
+               struct tcp_sack_block_wire *sack;
+               __be32 new_start_seq, new_end_seq;
 
                sack = (void *)skb->data + sackoff;
                if (after(ntohl(sack->start_seq) - natseq->offset_before,
                          natseq->correction_pos))
-                       new_start_seq = ntohl(sack->start_seq) 
-                                       - natseq->offset_after;
+                       new_start_seq = htonl(ntohl(sack->start_seq)
+                                       - natseq->offset_after);
                else
-                       new_start_seq = ntohl(sack->start_seq) 
-                                       - natseq->offset_before;
-               new_start_seq = htonl(new_start_seq);
+                       new_start_seq = htonl(ntohl(sack->start_seq)
+                                       - natseq->offset_before);
 
                if (after(ntohl(sack->end_seq) - natseq->offset_before,
                          natseq->correction_pos))
-                       new_end_seq = ntohl(sack->end_seq)
-                                     - natseq->offset_after;
+                       new_end_seq = htonl(ntohl(sack->end_seq)
+                                     - natseq->offset_after);
                else
-                       new_end_seq = ntohl(sack->end_seq)
-                                     - natseq->offset_before;
-               new_end_seq = htonl(new_end_seq);
+                       new_end_seq = htonl(ntohl(sack->end_seq)
+                                     - natseq->offset_before);
 
                DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
                        ntohl(sack->start_seq), new_start_seq,
@@ -375,7 +373,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
                  enum ip_conntrack_info ctinfo)
 {
        struct tcphdr *tcph;
-       int dir, newseq, newack;
+       int dir;
+       __be32 newseq, newack;
        struct ip_nat_seq *this_way, *other_way;        
 
        dir = CTINFO2DIR(ctinfo);
@@ -388,17 +387,15 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
 
        tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
        if (after(ntohl(tcph->seq), this_way->correction_pos))
-               newseq = ntohl(tcph->seq) + this_way->offset_after;
+               newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
        else
-               newseq = ntohl(tcph->seq) + this_way->offset_before;
-       newseq = htonl(newseq);
+               newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);
 
        if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
                  other_way->correction_pos))
-               newack = ntohl(tcph->ack_seq) - other_way->offset_after;
+               newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
        else
-               newack = ntohl(tcph->ack_seq) - other_way->offset_before;
-       newack = htonl(newack);
+               newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
 
        tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq,
                                           tcph->check, 0);
index 419b878fb467276ac3f885fdae6f1228118591a3..4a7d34466ee2a9485a6ad3082af4b5eb5a6ad618 100644 (file)
 /****************************************************************************/
 static int set_addr(struct sk_buff **pskb,
                    unsigned char **data, int dataoff,
-                   unsigned int addroff, u_int32_t ip, u_int16_t port)
+                   unsigned int addroff, __be32 ip, u_int16_t port)
 {
        enum ip_conntrack_info ctinfo;
        struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
        struct {
-               u_int32_t ip;
-               u_int16_t port;
+               __be32 ip;
+               __be16 port;
        } __attribute__ ((__packed__)) buf;
        struct tcphdr _tcph, *th;
 
@@ -86,7 +86,7 @@ static int set_addr(struct sk_buff **pskb,
 static int set_h225_addr(struct sk_buff **pskb,
                         unsigned char **data, int dataoff,
                         TransportAddress * addr,
-                        u_int32_t ip, u_int16_t port)
+                        __be32 ip, u_int16_t port)
 {
        return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
 }
@@ -95,7 +95,7 @@ static int set_h225_addr(struct sk_buff **pskb,
 static int set_h245_addr(struct sk_buff **pskb,
                         unsigned char **data, int dataoff,
                         H245_TransportAddress * addr,
-                        u_int32_t ip, u_int16_t port)
+                        __be32 ip, u_int16_t port)
 {
        return set_addr(pskb, data, dataoff,
                        addr->unicastAddress.iPAddress.network, ip, port);
@@ -110,7 +110,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
        struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
        int dir = CTINFO2DIR(ctinfo);
        int i;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
 
        for (i = 0; i < count; i++) {
@@ -164,7 +164,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
 {
        int dir = CTINFO2DIR(ctinfo);
        int i;
-       u_int32_t ip;
+       __be32 ip;
        u_int16_t port;
 
        for (i = 0; i < count; i++) {
@@ -433,7 +433,7 @@ static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
        struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
        int dir = CTINFO2DIR(ctinfo);
        u_int16_t nated_port = port;
-       u_int32_t ip;
+       __be32 ip;
 
        /* Set expectations for NAT */
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
index 2ff5788071237fa968a74dd1d45c7da512472d1e..329fdcd7d7029aa9724930e94416b2431ff1e669 100644 (file)
@@ -51,7 +51,7 @@
 
 #define IP_NAT_PPTP_VERSION "3.0"
 
-#define REQ_CID(req, off)              (*(u_int16_t *)((char *)(req) + (off)))
+#define REQ_CID(req, off)              (*(__be16 *)((char *)(req) + (off)))
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
index ec50cc295317feac7527e22ba21c5d1972492265..3f6efc13ac74e7a20f9a9ecd9bbd9a1d99e5a2c7 100644 (file)
@@ -67,7 +67,7 @@ icmp_manip_pkt(struct sk_buff **pskb,
 
        hdr = (struct icmphdr *)((*pskb)->data + hdroff);
        hdr->checksum = nf_proto_csum_update(*pskb,
-                                            hdr->un.echo.id ^ 0xFFFF,
+                                            hdr->un.echo.id ^ htons(0xFFFF),
                                             tuple->src.u.icmp.id,
                                             hdr->checksum, 0);
        hdr->un.echo.id = tuple->src.u.icmp.id;
index 72a6307bd2db90dde126cabb647cf738b1b1bf0b..12deb13b93b12aee127377cf316c729cd100f8d8 100644 (file)
@@ -24,7 +24,7 @@ tcp_in_range(const struct ip_conntrack_tuple *tuple,
             const union ip_conntrack_manip_proto *min,
             const union ip_conntrack_manip_proto *max)
 {
-       u_int16_t port;
+       __be16 port;
 
        if (maniptype == IP_NAT_MANIP_SRC)
                port = tuple->src.u.tcp.port;
@@ -42,7 +42,7 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple,
                 const struct ip_conntrack *conntrack)
 {
        static u_int16_t port;
-       u_int16_t *portptr;
+       __be16 *portptr;
        unsigned int range_size, min, i;
 
        if (maniptype == IP_NAT_MANIP_SRC)
@@ -93,8 +93,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
        struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
        struct tcphdr *hdr;
        unsigned int hdroff = iphdroff + iph->ihl*4;
-       u32 oldip, newip;
-       u16 *portptr, newport, oldport;
+       __be32 oldip, newip;
+       __be16 *portptr, newport, oldport;
        int hdrsize = 8; /* TCP connection tracking guarantees this much */
 
        /* this could be a inner header returned in icmp packet; in such
@@ -130,7 +130,7 @@ tcp_manip_pkt(struct sk_buff **pskb,
                return 1;
 
        hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1);
-       hdr->check = nf_proto_csum_update(*pskb, oldport ^ 0xFFFF, newport,
+       hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport,
                                          hdr->check, 0);
        return 1;
 }
index 5da196ae758cf07e6cb09b8ef2629789ec0c8bb0..4bbec7730d18b3fbbec444aee353bf0b07dc41dd 100644 (file)
@@ -24,7 +24,7 @@ udp_in_range(const struct ip_conntrack_tuple *tuple,
             const union ip_conntrack_manip_proto *min,
             const union ip_conntrack_manip_proto *max)
 {
-       u_int16_t port;
+       __be16 port;
 
        if (maniptype == IP_NAT_MANIP_SRC)
                port = tuple->src.u.udp.port;
@@ -42,7 +42,7 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
                 const struct ip_conntrack *conntrack)
 {
        static u_int16_t port;
-       u_int16_t *portptr;
+       __be16 *portptr;
        unsigned int range_size, min, i;
 
        if (maniptype == IP_NAT_MANIP_SRC)
@@ -91,8 +91,8 @@ udp_manip_pkt(struct sk_buff **pskb,
        struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
        struct udphdr *hdr;
        unsigned int hdroff = iphdroff + iph->ihl*4;
-       u32 oldip, newip;
-       u16 *portptr, newport;
+       __be32 oldip, newip;
+       __be16 *portptr, newport;
 
        if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
                return 0;
@@ -118,7 +118,7 @@ udp_manip_pkt(struct sk_buff **pskb,
                hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip,
                                                  hdr->check, 1);
                hdr->check = nf_proto_csum_update(*pskb,
-                                                 *portptr ^ 0xFFFF, newport,
+                                                 *portptr ^ htons(0xFFFF), newport,
                                                  hdr->check, 0);
                if (!hdr->check)
                        hdr->check = -1;
index 7b703839aa58ca78d4b2a73d40f2516198d714b1..a176aa3031e0f37557d100975e6e9ba92f0df4f0 100644 (file)
@@ -119,7 +119,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
 }
 
 /* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
-static void warn_if_extra_mangle(u32 dstip, u32 srcip)
+static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
 {
        static int warned = 0;
        struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
@@ -205,7 +205,7 @@ alloc_null_binding(struct ip_conntrack *conntrack,
           per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
           Use reply in case it's already been mangled (eg local packet).
        */
-       u_int32_t ip
+       __be32 ip
                = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
                   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
                   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
@@ -222,7 +222,7 @@ alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
                              struct ip_nat_info *info,
                              unsigned int hooknum)
 {
-       u_int32_t ip
+       __be32 ip
                = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
                   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
                   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
index 6ffba63adca230e17ed1345838e49240879a857a..71fc2730a007d5ccdd9f4069c763d4b8bb8f748c 100644 (file)
@@ -60,8 +60,8 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb,
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
        char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
        unsigned int bufflen, dataoff;
-       u_int32_t ip;
-       u_int16_t port;
+       __be32 ip;
+       __be16 port;
 
        dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
 
@@ -159,7 +159,7 @@ static int mangle_content_len(struct sk_buff **pskb,
 static unsigned int mangle_sdp(struct sk_buff **pskb,
                               enum ip_conntrack_info ctinfo,
                               struct ip_conntrack *ct,
-                              u_int32_t newip, u_int16_t port,
+                              __be32 newip, u_int16_t port,
                               const char *dptr)
 {
        char buffer[sizeof("nnn.nnn.nnn.nnn")];
@@ -195,7 +195,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
 {
        struct ip_conntrack *ct = exp->master;
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
-       u_int32_t newip;
+       __be32 newip;
        u_int16_t port;
 
        DEBUGP("ip_nat_sdp():\n");
index 18b7fbdccb6126684f67478fa6a7ba1580445b23..168f45fa1898d2ce1094ed2782916e2b67d88c50 100644 (file)
@@ -1211,7 +1211,7 @@ static int snmp_translate(struct ip_conntrack *ct,
                           struct sk_buff **pskb)
 {
        struct iphdr *iph = (*pskb)->nh.iph;
-       struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+       struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
        u_int16_t udplen = ntohs(udph->len);
        u_int16_t paylen = udplen - sizeof(struct udphdr);
        int dir = CTINFO2DIR(ctinfo);
index 9c577db62047a7255c4ebed0c317050319290865..021395b674639b19f65975732239321a2fd34750 100644 (file)
@@ -191,7 +191,7 @@ ip_nat_in(unsigned int hooknum,
           int (*okfn)(struct sk_buff *))
 {
        unsigned int ret;
-       u_int32_t daddr = (*pskb)->nh.iph->daddr;
+       __be32 daddr = (*pskb)->nh.iph->daddr;
 
        ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
        if (ret != NF_DROP && ret != NF_STOLEN
index 41589665fc5ddabc128690199ac266bc98494537..7a29d6e7baa7db35c4d71da25889e0e0b83f3a66 100644 (file)
@@ -52,7 +52,7 @@ struct clusterip_config {
        atomic_t entries;                       /* number of entries/rules
                                                 * referencing us */
 
-       u_int32_t clusterip;                    /* the IP address */
+       __be32 clusterip;                       /* the IP address */
        u_int8_t clustermac[ETH_ALEN];          /* the MAC address */
        struct net_device *dev;                 /* device */
        u_int16_t num_total_nodes;              /* total number of nodes */
@@ -119,7 +119,7 @@ clusterip_config_entry_put(struct clusterip_config *c)
 }
 
 static struct clusterip_config *
-__clusterip_config_find(u_int32_t clusterip)
+__clusterip_config_find(__be32 clusterip)
 {
        struct list_head *pos;
 
@@ -136,7 +136,7 @@ __clusterip_config_find(u_int32_t clusterip)
 }
 
 static inline struct clusterip_config *
-clusterip_config_find_get(u_int32_t clusterip, int entry)
+clusterip_config_find_get(__be32 clusterip, int entry)
 {
        struct clusterip_config *c;
 
@@ -166,7 +166,7 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
 }
 
 static struct clusterip_config *
-clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
+clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
                        struct net_device *dev)
 {
        struct clusterip_config *c;
@@ -387,7 +387,7 @@ checkentry(const char *tablename,
                return 0;
 
        }
-       if (e->ip.dmsk.s_addr != 0xffffffff
+       if (e->ip.dmsk.s_addr != htonl(0xffffffff)
            || e->ip.dst.s_addr == 0) {
                printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
                return 0;
@@ -476,9 +476,9 @@ static struct ipt_target clusterip_tgt = {
 /* hardcoded for 48bit ethernet and 32bit ipv4 addresses */
 struct arp_payload {
        u_int8_t src_hw[ETH_ALEN];
-       u_int32_t src_ip;
+       __be32 src_ip;
        u_int8_t dst_hw[ETH_ALEN];
-       u_int32_t dst_ip;
+       __be32 dst_ip;
 } __attribute__ ((packed));
 
 #ifdef CLUSTERIP_DEBUG
index 23f9c7ebe7ebb5992e57dbc9877b36c068ad9262..12a818a2462f2a8caf9f8fea514d401fd1d7311b 100644 (file)
@@ -28,7 +28,7 @@ static inline int
 set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
        struct iphdr *iph = (*pskb)->nh.iph;
-       u_int16_t oldtos;
+       __be16 oldtos;
 
        if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
                if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -37,7 +37,7 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
                oldtos = iph->tos;
                iph->tos &= ~IPT_ECN_IP_MASK;
                iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
-               iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos,
+               iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
                                            iph->check);
        } 
        return 1;
@@ -48,7 +48,7 @@ static inline int
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
        struct tcphdr _tcph, *tcph;
-       u_int16_t oldval;
+       __be16 oldval;
 
        /* Not enought header? */
        tcph = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
@@ -66,15 +66,15 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
                return 0;
        tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4;
 
-       oldval = ((u_int16_t *)tcph)[6];
+       oldval = ((__be16 *)tcph)[6];
        if (einfo->operation & IPT_ECN_OP_SET_ECE)
                tcph->ece = einfo->proto.tcp.ece;
        if (einfo->operation & IPT_ECN_OP_SET_CWR)
                tcph->cwr = einfo->proto.tcp.cwr;
 
        tcph->check = nf_proto_csum_update((*pskb),
-                                          oldval ^ 0xFFFF,
-                                          ((u_int16_t *)tcph)[6],
+                                          oldval ^ htons(0xFFFF),
+                                          ((__be16 *)tcph)[6],
                                           tcph->check, 0);
        return 1;
 }
index bc65168a3437d7793cf4cfed31daa02e8a5dee9f..3dbfcfac8a84db1b46543ebec8ba58865d12edf0 100644 (file)
@@ -70,7 +70,7 @@ masquerade_target(struct sk_buff **pskb,
        const struct ip_nat_multi_range_compat *mr;
        struct ip_nat_range newrange;
        struct rtable *rt;
-       u_int32_t newsrc;
+       __be32 newsrc;
 
        IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
 
index beb2914225ff6e4db3c64a800678a7f6ed4b35a8..58a88f2271081383c81b25c6c2dca4ff3d7ac010 100644 (file)
@@ -58,7 +58,7 @@ target(struct sk_buff **pskb,
 {
        struct ip_conntrack *ct;
        enum ip_conntrack_info ctinfo;
-       u_int32_t new_ip, netmask;
+       __be32 new_ip, netmask;
        const struct ip_nat_multi_range_compat *mr = targinfo;
        struct ip_nat_range newrange;
 
index f03d43671c6d1e5278bcd263971aac630abef9bf..c0dcfe9d610cd35baa4df884de2b3a0aed8398a7 100644 (file)
@@ -61,7 +61,7 @@ redirect_target(struct sk_buff **pskb,
 {
        struct ip_conntrack *ct;
        enum ip_conntrack_info ctinfo;
-       u_int32_t newdst;
+       __be32 newdst;
        const struct ip_nat_multi_range_compat *mr = targinfo;
        struct ip_nat_range newrange;
 
index b81821edd893382a20ca9d996a47209fc90f97ec..fd0c05efed8a088ead0dc29ca1e08a05147a9e22 100644 (file)
@@ -104,8 +104,8 @@ static void send_reset(struct sk_buff *oldskb, int hook)
        struct iphdr *iph = oldskb->nh.iph;
        struct tcphdr _otcph, *oth, *tcph;
        struct rtable *rt;
-       u_int16_t tmp_port;
-       u_int32_t tmp_addr;
+       __be16 tmp_port;
+       __be32 tmp_addr;
        int needs_ack;
        int hh_len;
 
index efbcb119883244bc3273d9a5f31f263ad232a400..b38b13328d739fce3b3fc3a54d312f772501cffc 100644 (file)
@@ -135,7 +135,8 @@ same_target(struct sk_buff **pskb,
 {
        struct ip_conntrack *ct;
        enum ip_conntrack_info ctinfo;
-       u_int32_t tmpip, aindex, new_ip;
+       u_int32_t tmpip, aindex;
+       __be32 new_ip;
        const struct ipt_same_info *same = targinfo;
        struct ip_nat_range newrange;
        const struct ip_conntrack_tuple *t;
index 4246c4321e5bb74333bc9a1ed1a3fde6929b6510..108b6b76311fea42b48312a217bdf07e42137191 100644 (file)
@@ -42,7 +42,8 @@ ipt_tcpmss_target(struct sk_buff **pskb,
        const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
        struct tcphdr *tcph;
        struct iphdr *iph;
-       u_int16_t tcplen, newtotlen, oldval, newmss;
+       u_int16_t tcplen, newmss;
+       __be16 newtotlen, oldval;
        unsigned int i;
        u_int8_t *opt;
 
@@ -97,7 +98,7 @@ ipt_tcpmss_target(struct sk_buff **pskb,
                        opt[i+3] = (newmss & 0x00ff);
 
                        tcph->check = nf_proto_csum_update(*pskb,
-                                                          htons(oldmss)^0xFFFF,
+                                                          htons(oldmss)^htons(0xFFFF),
                                                           htons(newmss),
                                                           tcph->check, 0);
                        return IPT_CONTINUE;
@@ -126,7 +127,7 @@ ipt_tcpmss_target(struct sk_buff **pskb,
        memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
 
        tcph->check = nf_proto_csum_update(*pskb,
-                                          htons(tcplen) ^ 0xFFFF,
+                                          htons(tcplen) ^ htons(0xFFFF),
                                           htons(tcplen + TCPOLEN_MSS),
                                           tcph->check, 1);
        opt[0] = TCPOPT_MSS;
@@ -134,18 +135,18 @@ ipt_tcpmss_target(struct sk_buff **pskb,
        opt[2] = (newmss & 0xff00) >> 8;
        opt[3] = (newmss & 0x00ff);
 
-       tcph->check = nf_proto_csum_update(*pskb, ~0, *((u_int32_t *)opt),
+       tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt),
                                           tcph->check, 0);
 
-       oldval = ((u_int16_t *)tcph)[6];
+       oldval = ((__be16 *)tcph)[6];
        tcph->doff += TCPOLEN_MSS/4;
        tcph->check = nf_proto_csum_update(*pskb,
-                                          oldval ^ 0xFFFF,
-                                          ((u_int16_t *)tcph)[6],
+                                          oldval ^ htons(0xFFFF),
+                                          ((__be16 *)tcph)[6],
                                           tcph->check, 0);
 
        newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
-       iph->check = nf_csum_update(iph->tot_len ^ 0xFFFF,
+       iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF),
                                    newtotlen, iph->check);
        iph->tot_len = newtotlen;
        return IPT_CONTINUE;
index 471a4c438b0af123ec174e8e51bcae9b27be7695..6b8b14ccc3d3ff9a0fa0610a0e08df6d274cf2ef 100644 (file)
@@ -30,7 +30,7 @@ target(struct sk_buff **pskb,
 {
        const struct ipt_tos_target_info *tosinfo = targinfo;
        struct iphdr *iph = (*pskb)->nh.iph;
-       u_int16_t oldtos;
+       __be16 oldtos;
 
        if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
                if (!skb_make_writable(pskb, sizeof(struct iphdr)))
@@ -38,7 +38,7 @@ target(struct sk_buff **pskb,
                iph = (*pskb)->nh.iph;
                oldtos = iph->tos;
                iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
-               iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos,
+               iph->check = nf_csum_update(oldtos ^ htons(0xFFFF), iph->tos,
                                            iph->check);
        }
        return IPT_CONTINUE;
index 96e79cc6d0f233dd20cb95b4ffc76336a72d2a7d..ac9517d62af0e1d79a3e81da2142e26578d7e269 100644 (file)
@@ -54,8 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb,
        }
 
        if (new_ttl != iph->ttl) {
-               iph->check = nf_csum_update(ntohs((iph->ttl << 8)) ^ 0xFFFF,
-                                           ntohs(new_ttl << 8),
+               iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF),
+                                           htons(new_ttl << 8),
                                            iph->check);
                iph->ttl = new_ttl;
        }
index 893dae210b0482b324329fffc834974c6e61ec32..7b60eb74788b6671617425cd2c2602ffe79fe956 100644 (file)
@@ -22,7 +22,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_DESCRIPTION("iptables addrtype match");
 
-static inline int match_type(u_int32_t addr, u_int16_t mask)
+static inline int match_type(__be32 addr, u_int16_t mask)
 {
        return !!(mask & (1 << inet_addr_type(addr)));
 }
index 4f73a61aa3dd48e6b2bedb2bd9f851819837842d..33ccdbf8e7940b0f37d6d0fe0557b7e633530554 100644 (file)
@@ -50,11 +50,11 @@ static struct file_operations dl_file_ops;
 /* hash table crap */
 
 struct dsthash_dst {
-       u_int32_t src_ip;
-       u_int32_t dst_ip;
+       __be32 src_ip;
+       __be32 dst_ip;
        /* ports have to be consecutive !!! */
-       u_int16_t src_port;
-       u_int16_t dst_port;
+       __be16 src_port;
+       __be16 dst_port;
 };
 
 struct dsthash_ent {
@@ -106,8 +106,10 @@ static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
 static inline u_int32_t
 hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
 {
-       return (jhash_3words(dst->dst_ip, (dst->dst_port<<16 | dst->src_port), 
-                            dst->src_ip, ht->rnd) % ht->cfg.size);
+       return (jhash_3words((__force u32)dst->dst_ip,
+                           ((__force u32)dst->dst_port<<16 |
+                            (__force u32)dst->src_port),
+                            (__force u32)dst->src_ip, ht->rnd) % ht->cfg.size);
 }
 
 static inline struct dsthash_ent *
@@ -406,7 +408,7 @@ hashlimit_match(const struct sk_buff *skb,
                dst.src_ip = skb->nh.iph->saddr;
        if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
            ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
-               u_int16_t _ports[2], *ports;
+               __be16 _ports[2], *ports;
 
                switch (skb->nh.iph->protocol) {
                case IPPROTO_TCP:
index 32ae8d7ac50654c41ff3288d4be4a996e3ce4a79..126db44e71a8eaa3fd91fa5ba36f8bbd27db46fe 100644 (file)
@@ -50,11 +50,10 @@ MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files");
 MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files");
 MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files");
 
-
 struct recent_entry {
        struct list_head        list;
        struct list_head        lru_list;
-       u_int32_t               addr;
+       __be32                  addr;
        u_int8_t                ttl;
        u_int8_t                index;
        u_int16_t               nstamps;
@@ -85,17 +84,17 @@ static struct file_operations       recent_fops;
 static u_int32_t hash_rnd;
 static int hash_rnd_initted;
 
-static unsigned int recent_entry_hash(u_int32_t addr)
+static unsigned int recent_entry_hash(__be32 addr)
 {
        if (!hash_rnd_initted) {
                get_random_bytes(&hash_rnd, 4);
                hash_rnd_initted = 1;
        }
-       return jhash_1word(addr, hash_rnd) & (ip_list_hash_size - 1);
+       return jhash_1word((__force u32)addr, hash_rnd) & (ip_list_hash_size - 1);
 }
 
 static struct recent_entry *
-recent_entry_lookup(const struct recent_table *table, u_int32_t addr, u_int8_t ttl)
+recent_entry_lookup(const struct recent_table *table, __be32 addr, u_int8_t ttl)
 {
        struct recent_entry *e;
        unsigned int h;
@@ -116,7 +115,7 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
 }
 
 static struct recent_entry *
-recent_entry_init(struct recent_table *t, u_int32_t addr, u_int8_t ttl)
+recent_entry_init(struct recent_table *t, __be32 addr, u_int8_t ttl)
 {
        struct recent_entry *e;
 
@@ -178,7 +177,7 @@ ipt_recent_match(const struct sk_buff *skb,
        const struct ipt_recent_info *info = matchinfo;
        struct recent_table *t;
        struct recent_entry *e;
-       u_int32_t addr;
+       __be32 addr;
        u_int8_t ttl;
        int ret = info->invert;
 
@@ -406,7 +405,7 @@ static ssize_t recent_proc_write(struct file *file, const char __user *input,
        struct recent_table *t = pde->data;
        struct recent_entry *e;
        char buf[sizeof("+255.255.255.255")], *c = buf;
-       u_int32_t addr;
+       __be32 addr;
        int add;
 
        if (size > sizeof(buf))
index 79336cb42527387d9708fcdb9c4bd4105ea66767..e62ea2bb9c0ac422f7c77e39aa7f99eba5fa6e3b 100644 (file)
@@ -131,7 +131,7 @@ ipt_local_hook(unsigned int hook,
 {
        unsigned int ret;
        u_int8_t tos;
-       u_int32_t saddr, daddr;
+       __be32 saddr, daddr;
        unsigned long nfmark;
 
        /* root is playing with raw sockets. */
index 0e935b4c87411ab9e697a5255fe0d8b58f9e8eb3..b430cf2a4f6609db27f6ea137e3f18b0281bd442 100644 (file)
@@ -381,8 +381,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct ipcm_cookie ipc;
        struct rtable *rt = NULL;
        int free = 0;
-       u32 daddr;
-       u32 saddr;
+       __be32 daddr;
+       __be32 saddr;
        u8  tos;
        int err;
 
index 20ffe8e88c0f0809d28418743fb81fd5cc43bc02..c41ddba02e9d3553dac0f4aca6d7c5c8b9975584 100644 (file)
@@ -261,6 +261,10 @@ static unsigned int rt_hash_code(u32 daddr, u32 saddr)
                & rt_hash_mask);
 }
 
+#define rt_hash(daddr, saddr, idx) \
+       rt_hash_code((__force u32)(__be32)(daddr),\
+                    (__force u32)(__be32)(saddr) ^ ((idx) << 5))
+
 #ifdef CONFIG_PROC_FS
 struct rt_cache_iter_state {
        int bucket;
@@ -1074,7 +1078,7 @@ static void ip_select_fb_ident(struct iphdr *iph)
        u32 salt;
 
        spin_lock_bh(&ip_fb_id_lock);
-       salt = secure_ip_id(ip_fallback_id ^ iph->daddr);
+       salt = secure_ip_id((__force __be32)ip_fallback_id ^ iph->daddr);
        iph->id = htons(salt & 0xFFFF);
        ip_fallback_id = salt;
        spin_unlock_bh(&ip_fb_id_lock);
@@ -1118,13 +1122,13 @@ static void rt_del(unsigned hash, struct rtable *rt)
        spin_unlock_bh(rt_hash_lock_addr(hash));
 }
 
-void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
-                   u32 saddr, struct net_device *dev)
+void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+                   __be32 saddr, struct net_device *dev)
 {
        int i, k;
        struct in_device *in_dev = in_dev_get(dev);
        struct rtable *rth, **rthp;
-       u32  skeys[2] = { saddr, 0 };
+       __be32  skeys[2] = { saddr, 0 };
        int  ikeys[2] = { dev->ifindex, 0 };
        struct netevent_redirect netevent;
 
@@ -1147,8 +1151,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
 
        for (i = 0; i < 2; i++) {
                for (k = 0; k < 2; k++) {
-                       unsigned hash = rt_hash_code(daddr,
-                                                    skeys[i] ^ (ikeys[k] << 5));
+                       unsigned hash = rt_hash(daddr, skeys[i], ikeys[k]);
 
                        rthp=&rt_hash_table[hash].chain;
 
@@ -1260,9 +1263,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
                        ret = NULL;
                } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
                           rt->u.dst.expires) {
-                       unsigned hash = rt_hash_code(rt->fl.fl4_dst,
-                                                    rt->fl.fl4_src ^
-                                                       (rt->fl.oif << 5));
+                       unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
+                                               rt->fl.oif);
 #if RT_CACHE_DEBUG >= 1
                        printk(KERN_DEBUG "ip_rt_advice: redirect to "
                                          "%u.%u.%u.%u/%02x dropped\n",
@@ -1397,15 +1399,15 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
        int i;
        unsigned short old_mtu = ntohs(iph->tot_len);
        struct rtable *rth;
-       u32  skeys[2] = { iph->saddr, 0, };
-       u32  daddr = iph->daddr;
+       __be32  skeys[2] = { iph->saddr, 0, };
+       __be32  daddr = iph->daddr;
        unsigned short est_mtu = 0;
 
        if (ipv4_config.no_pmtu_disc)
                return 0;
 
        for (i = 0; i < 2; i++) {
-               unsigned hash = rt_hash_code(daddr, skeys[i]);
+               unsigned hash = rt_hash(daddr, skeys[i], 0);
 
                rcu_read_lock();
                for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -1530,7 +1532,7 @@ static int ip_rt_bug(struct sk_buff *skb)
 
 void ip_rt_get_source(u8 *addr, struct rtable *rt)
 {
-       u32 src;
+       __be32 src;
        struct fib_result res;
 
        if (rt->fl.iif == 0)
@@ -1596,12 +1598,12 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
         rt->rt_type = res->type;
 }
 
-static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
+static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                                u8 tos, struct net_device *dev, int our)
 {
        unsigned hash;
        struct rtable *rth;
-       u32 spec_dst;
+       __be32 spec_dst;
        struct in_device *in_dev = in_dev_get(dev);
        u32 itag = 0;
 
@@ -1665,7 +1667,7 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
        RT_CACHE_STAT_INC(in_slow_mc);
 
        in_dev_put(in_dev);
-       hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5));
+       hash = rt_hash(daddr, saddr, dev->ifindex);
        return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
 
 e_nobufs:
@@ -1681,8 +1683,8 @@ e_inval:
 static void ip_handle_martian_source(struct net_device *dev,
                                     struct in_device *in_dev,
                                     struct sk_buff *skb,
-                                    u32 daddr,
-                                    u32 saddr) 
+                                    __be32 daddr,
+                                    __be32 saddr)
 {
        RT_CACHE_STAT_INC(in_martian_src);
 #ifdef CONFIG_IP_ROUTE_VERBOSE
@@ -1712,7 +1714,7 @@ static void ip_handle_martian_source(struct net_device *dev,
 static inline int __mkroute_input(struct sk_buff *skb, 
                                  struct fib_result* res, 
                                  struct in_device *in_dev, 
-                                 u32 daddr, u32 saddr, u32 tos, 
+                                 __be32 daddr, __be32 saddr, u32 tos,
                                  struct rtable **result) 
 {
 
@@ -1720,7 +1722,8 @@ static inline int __mkroute_input(struct sk_buff *skb,
        int err;
        struct in_device *out_dev;
        unsigned flags = 0;
-       u32 spec_dst, itag;
+       __be32 spec_dst;
+       u32 itag;
 
        /* get a working reference to the output device */
        out_dev = in_dev_get(FIB_RES_DEV(*res));
@@ -1813,7 +1816,7 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
                                       struct fib_result* res, 
                                       const struct flowi *fl,
                                       struct in_device *in_dev,
-                                      u32 daddr, u32 saddr, u32 tos)
+                                      __be32 daddr, __be32 saddr, u32 tos)
 {
        struct rtable* rth = NULL;
        int err;
@@ -1830,7 +1833,7 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
                return err;
 
        /* put it into the cache */
-       hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5));
+       hash = rt_hash(daddr, saddr, fl->iif);
        return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);   
 }
 
@@ -1838,7 +1841,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
                                   struct fib_result* res, 
                                   const struct flowi *fl,
                                   struct in_device *in_dev,
-                                  u32 daddr, u32 saddr, u32 tos)
+                                  __be32 daddr, __be32 saddr, u32 tos)
 {
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
        struct rtable* rth = NULL, *rtres;
@@ -1871,7 +1874,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
                        return err;
 
                /* put it into the cache */
-               hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5));
+               hash = rt_hash(daddr, saddr, fl->iif);
                err = rt_intern_hash(hash, rth, &rtres);
                if (err)
                        return err;
@@ -1901,7 +1904,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
  *     2. IP spoofing attempts are filtered with 100% of guarantee.
  */
 
-static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
+static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                               u8 tos, struct net_device *dev)
 {
        struct fib_result res;
@@ -1920,7 +1923,7 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
        u32             itag = 0;
        struct rtable * rth;
        unsigned        hash;
-       u32             spec_dst;
+       __be32          spec_dst;
        int             err = -EINVAL;
        int             free_res = 0;
 
@@ -1936,7 +1939,7 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
        if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr))
                goto martian_source;
 
-       if (daddr == 0xFFFFFFFF || (saddr == 0 && daddr == 0))
+       if (daddr == htonl(0xFFFFFFFF) || (saddr == 0 && daddr == 0))
                goto brd_input;
 
        /* Accept zero addresses only to limited broadcast;
@@ -2048,7 +2051,7 @@ local_input:
                rth->rt_flags   &= ~RTCF_LOCAL;
        }
        rth->rt_type    = res.type;
-       hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5));
+       hash = rt_hash(daddr, saddr, fl.iif);
        err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
        goto done;
 
@@ -2087,7 +2090,7 @@ martian_source:
        goto e_inval;
 }
 
-int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
+int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                   u8 tos, struct net_device *dev)
 {
        struct rtable * rth;
@@ -2095,7 +2098,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
        int iif = dev->ifindex;
 
        tos &= IPTOS_RT_MASK;
-       hash = rt_hash_code(daddr, saddr ^ (iif << 5));
+       hash = rt_hash(daddr, saddr, iif);
 
        rcu_read_lock();
        for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -2169,7 +2172,7 @@ static inline int __mkroute_output(struct rtable **result,
        if (LOOPBACK(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
                return -EINVAL;
 
-       if (fl->fl4_dst == 0xFFFFFFFF)
+       if (fl->fl4_dst == htonl(0xFFFFFFFF))
                res->type = RTN_BROADCAST;
        else if (MULTICAST(fl->fl4_dst))
                res->type = RTN_MULTICAST;
@@ -2293,8 +2296,7 @@ static inline int ip_mkroute_output_def(struct rtable **rp,
        int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
        unsigned hash;
        if (err == 0) {
-               hash = rt_hash_code(oldflp->fl4_dst, 
-                                   oldflp->fl4_src ^ (oldflp->oif << 5));
+               hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif);
                err = rt_intern_hash(hash, rth, rp);
        }
        
@@ -2336,9 +2338,8 @@ static inline int ip_mkroute_output(struct rtable** rp,
                        if (err != 0)
                                goto cleanup;
 
-                       hash = rt_hash_code(oldflp->fl4_dst, 
-                                           oldflp->fl4_src ^
-                                           (oldflp->oif << 5));
+                       hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
+                                       oldflp->oif);
                        err = rt_intern_hash(hash, rth, rp);
 
                        /* forward hop information to multipath impl. */
@@ -2417,7 +2418,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
                 */
 
                if (oldflp->oif == 0
-                   && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF)) {
+                   && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
                        /* Special hack: user can direct multicasts
                           and limited broadcast via necessary interface
                           without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
@@ -2454,7 +2455,7 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
                        goto out;       /* Wrong error code */
                }
 
-               if (LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF) {
+               if (LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF)) {
                        if (!fl.fl4_src)
                                fl.fl4_src = inet_select_addr(dev_out, 0,
                                                              RT_SCOPE_LINK);
@@ -2567,7 +2568,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
        unsigned hash;
        struct rtable *rth;
 
-       hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5));
+       hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->oif);
 
        rcu_read_lock_bh();
        for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -2660,11 +2661,11 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
        if (rt->rt_flags & RTCF_NOTIFY)
                r->rtm_flags |= RTM_F_NOTIFY;
 
-       NLA_PUT_U32(skb, RTA_DST, rt->rt_dst);
+       NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst);
 
        if (rt->fl.fl4_src) {
                r->rtm_src_len = 32;
-               NLA_PUT_U32(skb, RTA_SRC, rt->fl.fl4_src);
+               NLA_PUT_BE32(skb, RTA_SRC, rt->fl.fl4_src);
        }
        if (rt->u.dst.dev)
                NLA_PUT_U32(skb, RTA_OIF, rt->u.dst.dev->ifindex);
@@ -2677,12 +2678,12 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
 #endif
        if (rt->fl.iif)
-               NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_spec_dst);
+               NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
        else if (rt->rt_src != rt->fl.fl4_src)
-               NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_src);
+               NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src);
 
        if (rt->rt_dst != rt->rt_gateway)
-               NLA_PUT_U32(skb, RTA_GATEWAY, rt->rt_gateway);
+               NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway);
 
        if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
                goto nla_put_failure;
@@ -2706,7 +2707,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 
        if (rt->fl.iif) {
 #ifdef CONFIG_IP_MROUTE
-               u32 dst = rt->rt_dst;
+               __be32 dst = rt->rt_dst;
 
                if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
                    ipv4_devconf.mc_forwarding) {
@@ -2740,7 +2741,9 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
        struct rtmsg *rtm;
        struct nlattr *tb[RTA_MAX+1];
        struct rtable *rt = NULL;
-       u32 dst, src, iif;
+       __be32 dst = 0;
+       __be32 src = 0;
+       u32 iif;
        int err;
        struct sk_buff *skb;
 
@@ -2765,8 +2768,8 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
        skb->nh.iph->protocol = IPPROTO_ICMP;
        skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
-       src = tb[RTA_SRC] ? nla_get_u32(tb[RTA_SRC]) : 0;
-       dst = tb[RTA_DST] ? nla_get_u32(tb[RTA_DST]) : 0;
+       src = tb[RTA_SRC] ? nla_get_be32(tb[RTA_SRC]) : 0;
+       dst = tb[RTA_DST] ? nla_get_be32(tb[RTA_DST]) : 0;
        iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
 
        if (iif) {
index b3def0df14fb81df0057ca9b5c61839f5e432601..3f884cea14ff439651b876ffce4f351289640681 100644 (file)
@@ -935,7 +935,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
        const struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
-       struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
+       struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2);
        int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
        int reord = tp->packets_out;
        int prior_fackets;
@@ -2239,13 +2239,12 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
        return acked;
 }
 
-static u32 tcp_usrtt(const struct sk_buff *skb)
+static u32 tcp_usrtt(struct timeval *tv)
 {
-       struct timeval tv, now;
+       struct timeval now;
 
        do_gettimeofday(&now);
-       skb_get_timestamp(skb, &tv);
-       return (now.tv_sec - tv.tv_sec) * 1000000 + (now.tv_usec - tv.tv_usec);
+       return (now.tv_sec - tv->tv_sec) * 1000000 + (now.tv_usec - tv->tv_usec);
 }
 
 /* Remove acknowledged frames from the retransmission queue. */
@@ -2260,6 +2259,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
        u32 pkts_acked = 0;
        void (*rtt_sample)(struct sock *sk, u32 usrtt)
                = icsk->icsk_ca_ops->rtt_sample;
+       struct timeval tv;
 
        while ((skb = skb_peek(&sk->sk_write_queue)) &&
               skb != sk->sk_send_head) {
@@ -2308,8 +2308,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
                                seq_rtt = -1;
                        } else if (seq_rtt < 0) {
                                seq_rtt = now - scb->when;
-                               if (rtt_sample)
-                                       (*rtt_sample)(sk, tcp_usrtt(skb));
+                               skb_get_timestamp(skb, &tv);
                        }
                        if (sacked & TCPCB_SACKED_ACKED)
                                tp->sacked_out -= tcp_skb_pcount(skb);
@@ -2322,8 +2321,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
                        }
                } else if (seq_rtt < 0) {
                        seq_rtt = now - scb->when;
-                       if (rtt_sample)
-                               (*rtt_sample)(sk, tcp_usrtt(skb));
+                       skb_get_timestamp(skb, &tv);
                }
                tcp_dec_pcount_approx(&tp->fackets_out, skb);
                tcp_packets_out_dec(tp, skb);
@@ -2335,6 +2333,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
        if (acked&FLAG_ACKED) {
                tcp_ack_update_rtt(sk, acked, seq_rtt);
                tcp_ack_packets_out(sk, tp);
+               if (rtt_sample && !(acked & FLAG_RETRANS_DATA_ACKED))
+                       (*rtt_sample)(sk, tcp_usrtt(&tv));
 
                if (icsk->icsk_ca_ops->pkts_acked)
                        icsk->icsk_ca_ops->pkts_acked(sk, pkts_acked);
@@ -2629,7 +2629,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
                                switch(opcode) {
                                case TCPOPT_MSS:
                                        if(opsize==TCPOLEN_MSS && th->syn && !estab) {
-                                               u16 in_mss = ntohs(get_unaligned((__u16 *)ptr));
+                                               u16 in_mss = ntohs(get_unaligned((__be16 *)ptr));
                                                if (in_mss) {
                                                        if (opt_rx->user_mss && opt_rx->user_mss < in_mss)
                                                                in_mss = opt_rx->user_mss;
@@ -2657,8 +2657,8 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
                                                if ((estab && opt_rx->tstamp_ok) ||
                                                    (!estab && sysctl_tcp_timestamps)) {
                                                        opt_rx->saw_tstamp = 1;
-                                                       opt_rx->rcv_tsval = ntohl(get_unaligned((__u32 *)ptr));
-                                                       opt_rx->rcv_tsecr = ntohl(get_unaligned((__u32 *)(ptr+4)));
+                                                       opt_rx->rcv_tsval = ntohl(get_unaligned((__be32 *)ptr));
+                                                       opt_rx->rcv_tsecr = ntohl(get_unaligned((__be32 *)(ptr+4)));
                                                }
                                        }
                                        break;
@@ -2695,8 +2695,8 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
                return 0;
        } else if (tp->rx_opt.tstamp_ok &&
                   th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
-               __u32 *ptr = (__u32 *)(th + 1);
-               if (*ptr == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+               __be32 *ptr = (__be32 *)(th + 1);
+               if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
                                  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
                        tp->rx_opt.saw_tstamp = 1;
                        ++ptr;
@@ -3911,10 +3911,10 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 
                /* Check timestamp */
                if (tcp_header_len == sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) {
-                       __u32 *ptr = (__u32 *)(th + 1);
+                       __be32 *ptr = (__be32 *)(th + 1);
 
                        /* No? Slow path! */
-                       if (*ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+                       if (*ptr != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
                                          | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
                                goto slow_path;
 
index 39b1798560824e3ba85dfae375a0a22ca37f135b..c83938b8fcb1201ddf403c6423cd83790397595b 100644 (file)
@@ -159,7 +159,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct tcp_sock *tp = tcp_sk(sk);
        struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
        struct rtable *rt;
-       u32 daddr, nexthop;
+       __be32 daddr, nexthop;
        int tmp;
        int err;
 
@@ -734,8 +734,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        struct inet_request_sock *ireq;
        struct tcp_options_received tmp_opt;
        struct request_sock *req;
-       __u32 saddr = skb->nh.iph->saddr;
-       __u32 daddr = skb->nh.iph->daddr;
+       __be32 saddr = skb->nh.iph->saddr;
+       __be32 daddr = skb->nh.iph->daddr;
        __u32 isn = TCP_SKB_CB(skb)->when;
        struct dst_entry *dst = NULL;
 #ifdef CONFIG_SYN_COOKIES
@@ -1763,7 +1763,7 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
 
 static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i)
 {
-       unsigned int dest, src;
+       __be32 dest, src;
        __u16 destp, srcp;
        int ttd = tw->tw_ttd - jiffies;
 
index 308fb7e071c56faaebbf742e6fc07cc0ecbabdc8..f0ebaf0e21cbf7276119f8c3886e0d2c1971e139 100644 (file)
@@ -31,8 +31,6 @@
  *   Hung Hing Lun, Mike <hlhung3i@gmail.com>
  * SourceForge project page:
  *   http://tcp-lp-mod.sourceforge.net/
- *
- * Version: $Id: tcp_lp.c,v 1.24 2006/09/05 20:22:53 hswong3i Exp $
  */
 
 #include <linux/module.h>
@@ -164,7 +162,7 @@ static u32 tcp_lp_remote_hz_estimator(struct sock *sk)
 
  out:
        /* record time for successful remote HZ calc */
-       if (rhz > 0)
+       if ((rhz >> 6) > 0)
                lp->flag |= LP_VALID_RHZ;
        else
                lp->flag &= ~LP_VALID_RHZ;
index 061edfae0c29df44ada4e1aec6d055a21eaf7f38..9a253faefc81c9c2f95d82e9cbb7878d677b25a1 100644 (file)
@@ -269,7 +269,7 @@ static u16 tcp_select_window(struct sock *sk)
        return new_win;
 }
 
-static void tcp_build_and_update_options(__u32 *ptr, struct tcp_sock *tp,
+static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
                                         __u32 tstamp)
 {
        if (tp->rx_opt.tstamp_ok) {
@@ -305,7 +305,7 @@ static void tcp_build_and_update_options(__u32 *ptr, struct tcp_sock *tp,
  * MAX_SYN_SIZE to match the new maximum number of options that you
  * can generate.
  */
-static void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
+static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
                                  int offer_wscale, int wscale, __u32 tstamp,
                                  __u32 ts_recent)
 {
@@ -424,7 +424,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
        th->dest                = inet->dport;
        th->seq                 = htonl(tcb->seq);
        th->ack_seq             = htonl(tp->rcv_nxt);
-       *(((__u16 *)th) + 6)    = htons(((tcp_header_size >> 2) << 12) |
+       *(((__be16 *)th) + 6)   = htons(((tcp_header_size >> 2) << 12) |
                                        tcb->flags);
 
        if (unlikely(tcb->flags & TCPCB_FLAG_SYN)) {
@@ -445,7 +445,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
        }
 
        if (unlikely(tcb->flags & TCPCB_FLAG_SYN)) {
-               tcp_syn_build_options((__u32 *)(th + 1),
+               tcp_syn_build_options((__be32 *)(th + 1),
                                      tcp_advertise_mss(sk),
                                      (sysctl_flags & SYSCTL_FLAG_TSTAMPS),
                                      (sysctl_flags & SYSCTL_FLAG_SACK),
@@ -454,7 +454,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
                                      tcb->when,
                                      tp->rx_opt.ts_recent);
        } else {
-               tcp_build_and_update_options((__u32 *)(th + 1),
+               tcp_build_and_update_options((__be32 *)(th + 1),
                                             tp, tcb->when);
                TCP_ECN_send(sk, tp, skb, tcp_header_size);
        }
@@ -2070,7 +2070,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        th->window = htons(req->rcv_wnd);
 
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
-       tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
+       tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
                              ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
                              TCP_SKB_CB(skb)->when,
                              req->ts_recent);
index 77e265d7bb8f8a7a795e552aef4214570a40a7da..6d6142f9c478baa8c85dcf1d174a5a88f66d783a 100644 (file)
@@ -243,8 +243,8 @@ static void udp_v4_unhash(struct sock *sk)
 /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
  * harder than this. -DaveM
  */
-static struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport,
-                                         u32 daddr, u16 dport, int dif)
+static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
+                                         __be32 daddr, __be16 dport, int dif)
 {
        struct sock *sk, *result = NULL;
        struct hlist_node *node;
@@ -288,8 +288,8 @@ static struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport,
        return result;
 }
 
-static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
-                                            u32 daddr, u16 dport, int dif)
+static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport,
+                                            __be32 daddr, __be16 dport, int dif)
 {
        struct sock *sk;
 
@@ -302,8 +302,8 @@ static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
 }
 
 static inline struct sock *udp_v4_mcast_next(struct sock *sk,
-                                            u16 loc_port, u32 loc_addr,
-                                            u16 rmt_port, u32 rmt_addr,
+                                            __be16 loc_port, __be32 loc_addr,
+                                            __be16 rmt_port, __be32 rmt_addr,
                                             int dif)
 {
        struct hlist_node *node;
@@ -498,7 +498,7 @@ out:
 }
 
 
-static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
+static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base)
 {
        return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
 }
@@ -513,8 +513,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct rtable *rt = NULL;
        int free = 0;
        int connected = 0;
-       u32 daddr, faddr, saddr;
-       u16 dport;
+       __be32 daddr, faddr, saddr;
+       __be16 dport;
        u8  tos;
        int err;
        int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
@@ -931,7 +931,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
        int iphlen, len;
   
        __u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr);
-       __u32 *udpdata32 = (__u32 *)udpdata;
+       __be32 *udpdata32 = (__be32 *)udpdata;
        __u16 encap_type = up->encap_type;
 
        /* if we're overly short, let UDP handle it */
@@ -1080,7 +1080,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
  *     so we don't need to lock the hashes.
  */
 static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
-                                u32 saddr, u32 daddr)
+                                __be32 saddr, __be32 daddr)
 {
        struct sock *sk;
        int dif;
@@ -1121,7 +1121,7 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
  * including udp header and folding it to skb->csum.
  */
 static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-                            unsigned short ulen, u32 saddr, u32 daddr)
+                            unsigned short ulen, __be32 saddr, __be32 daddr)
 {
        if (uh->check == 0) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1146,8 +1146,8 @@ int udp_rcv(struct sk_buff *skb)
        struct udphdr *uh;
        unsigned short ulen;
        struct rtable *rt = (struct rtable*)skb->dst;
-       u32 saddr = skb->nh.iph->saddr;
-       u32 daddr = skb->nh.iph->daddr;
+       __be32 saddr = skb->nh.iph->saddr;
+       __be32 daddr = skb->nh.iph->daddr;
        int len = skb->len;
 
        /*
@@ -1563,8 +1563,8 @@ void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
 static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
 {
        struct inet_sock *inet = inet_sk(sp);
-       unsigned int dest = inet->daddr;
-       unsigned int src  = inet->rcv_saddr;
+       __be32 dest = inet->daddr;
+       __be32 src  = inet->rcv_saddr;
        __u16 destp       = ntohs(inet->dport);
        __u16 srcp        = ntohs(inet->sport);
 
index 040e8475f295c1cefcb3350099f57feb08308d56..8655d038364cba364880f8cb9595e94708fe14db 100644 (file)
@@ -23,7 +23,7 @@ int xfrm4_rcv(struct sk_buff *skb)
 
 EXPORT_SYMBOL(xfrm4_rcv);
 
-static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
        switch (nexthdr) {
        case IPPROTO_IPIP:
@@ -55,7 +55,7 @@ drop:
 int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
        int err;
-       u32 spi, seq;
+       __be32 spi, seq;
        struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
        struct xfrm_state *x;
        int xfrm_nr = 0;
index eabcd27b176730d83e42ce599e28c7a7e3407e0f..7a7a00147e55c7d63758d2d3bad84884d3b1a4c6 100644 (file)
@@ -221,7 +221,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
 
                case IPPROTO_ESP:
                        if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
-                               u32 *ehdr = (u32 *)xprth;
+                               __be32 *ehdr = (__be32 *)xprth;
 
                                fl->fl_ipsec_spi = ehdr[0];
                        }
@@ -229,7 +229,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
 
                case IPPROTO_AH:
                        if (pskb_may_pull(skb, xprth + 8 - skb->data)) {
-                               u32 *ah_hdr = (u32*)xprth;
+                               __be32 *ah_hdr = (__be32*)xprth;
 
                                fl->fl_ipsec_spi = ah_hdr[1];
                        }
@@ -237,7 +237,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
 
                case IPPROTO_COMP:
                        if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
-                               u16 *ipcomp_hdr = (u16 *)xprth;
+                               __be16 *ipcomp_hdr = (__be16 *)xprth;
 
                                fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
                        }
index fe2034494d0854e7f22d9e40147c4dc16b76bdc4..3cc3df0c6ece97420f79c2a84efca31e1b8cbcd1 100644 (file)
@@ -29,9 +29,9 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
        x->sel.daddr.a4 = fl->fl4_dst;
        x->sel.saddr.a4 = fl->fl4_src;
        x->sel.dport = xfrm_flowi_dport(fl);
-       x->sel.dport_mask = ~0;
+       x->sel.dport_mask = htons(0xffff);
        x->sel.sport = xfrm_flowi_sport(fl);
-       x->sel.sport_mask = ~0;
+       x->sel.sport_mask = htons(0xffff);
        x->sel.prefixlen_d = 32;
        x->sel.prefixlen_s = 32;
        x->sel.proto = fl->proto;
index c18676352397cc11a7adc0961262117681b79ab8..e03c33b2465bc72415c8e27dce382db233959a69 100644 (file)
@@ -1258,8 +1258,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
 {
        const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
        const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
-       u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
-       u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
+       __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
+       __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
        int sk_ipv6only = ipv6_only_sock(sk);
        int sk2_ipv6only = inet_v6_ipv6only(sk2);
        int addr_type = ipv6_addr_type(sk_rcv_saddr6);
index bf6e8aff19d4f2fa62a5e18641548bd0a4e2a60b..e94eccb99707991c80409ebce8a157e1beaba3e7 100644 (file)
@@ -246,7 +246,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sock *sk = sock->sk;
        struct inet_sock *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
-       __u32 v4addr = 0;
+       __be32 v4addr = 0;
        unsigned short snum;
        int addr_type = 0;
        int err = 0;
index d2f3fc990bfaa2a535bf4cbf2f6a4590b66abb71..8accd1fbeeda96d9201d7cbd1f71cd85344c8b51 100644 (file)
@@ -64,7 +64,7 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
 {
        struct sock *sk;
        const struct hlist_node *node;
-       const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+       const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
@@ -82,7 +82,7 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
        sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
                const struct inet_timewait_sock *tw = inet_twsk(sk);
 
-               if(*((__u32 *)&(tw->tw_dport))  == ports        &&
+               if(*((__portpair *)&(tw->tw_dport))     == ports        &&
                   sk->sk_family                == PF_INET6) {
                        const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
 
@@ -171,7 +171,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
        const struct in6_addr *daddr = &np->rcv_saddr;
        const struct in6_addr *saddr = &np->daddr;
        const int dif = sk->sk_bound_dev_if;
-       const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+       const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
        const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
                                                inet->dport);
        struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
@@ -188,7 +188,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
 
                tw = inet_twsk(sk2);
 
-               if(*((__u32 *)&(tw->tw_dport)) == ports          &&
+               if(*((__portpair *)&(tw->tw_dport)) == ports             &&
                   sk2->sk_family              == PF_INET6       &&
                   ipv6_addr_equal(&tw6->tw_v6_daddr, saddr)     &&
                   ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
index ad9c6e824e629e02c8c37a4e17c94ea5dab50b35..a2860e35efd7d68ee67d3839e4b064aa6f3a574e 100644 (file)
@@ -178,7 +178,7 @@ out_ok:
 static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                                int type, int code, int offset, __u32 info)
 {
-       u32 spi;
+       __be32 spi;
        struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
        struct ipv6_comp_hdr *ipcomph = (struct ipv6_comp_hdr*)(skb->data+offset);
        struct xfrm_state *x;
@@ -234,7 +234,7 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x)
 {
        int err = 0;
        struct xfrm_state *t = NULL;
-       u32 spi;
+       __be32 spi;
 
        spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr);
        if (spi)
index 4f3bb7fcc8b509ac71615e7a8c0f543d95349854..de6b91981b30611b0cd63ea8d14a304b34387c27 100644 (file)
@@ -123,6 +123,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
        struct ipv6hdr *ipv6h;
        struct inet6_protocol *ops;
 
+       if (!(features & NETIF_F_HW_CSUM))
+               features &= ~NETIF_F_SG;
+
        if (unlikely(skb_shinfo(skb)->gso_type &
                     ~(SKB_GSO_UDP |
                       SKB_GSO_DODGY |
index 2546fc9f0a78b14559fc380b365665ad02afaed6..3b6575478fcc381aae64ee2c0d7b2b791d5f1846 100644 (file)
@@ -1237,7 +1237,7 @@ process:
 
        skb->dev = NULL;
 
-       bh_lock_sock(sk);
+       bh_lock_sock_nested(sk);
        ret = 0;
        if (!sock_owned_by_user(sk)) {
 #ifdef CONFIG_NET_DMA
index a40a057890133b13fec3d16fa66d80021f174c96..5c8b7a5688003dcf7c21ca0923be689b42d7cd40 100644 (file)
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
 {
        int err;
-       u32 seq;
+       __be32 seq;
        struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
        struct xfrm_state *x;
        int xfrm_nr = 0;
index 711bfafb2472dfd5fda8dc04c19a7f536355e64c..9ddaa9d41539fe23ec7df3d5cc9059749348e4ec 100644 (file)
@@ -29,9 +29,9 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
        ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
        ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
        x->sel.dport = xfrm_flowi_dport(fl);
-       x->sel.dport_mask = ~0;
+       x->sel.dport_mask = htons(0xffff);
        x->sel.sport = xfrm_flowi_sport(fl);
-       x->sel.sport_mask = ~0;
+       x->sel.sport_mask = htons(0xffff);
        x->sel.prefixlen_d = 128;
        x->sel.prefixlen_s = 128;
        x->sel.proto = fl->proto;
index 59685ee8f700d9690180560180320064912ceda8..7af227bb1551477730b13097e3490241bebc154b 100644 (file)
@@ -258,7 +258,7 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 static int xfrm6_tunnel_rcv(struct sk_buff *skb)
 {
        struct ipv6hdr *iph = skb->nh.ipv6h;
-       u32 spi;
+       __be32 spi;
 
        spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
        return xfrm6_rcv_spi(skb, spi);
index 17699eeb64d78274481bca74888dfc41313fb548..7e1aea89ef05b60709fcb37e1f5ec531303f0359 100644 (file)
@@ -132,13 +132,14 @@ static void irda_disconnect_indication(void *instance, void *sap,
 
        /* Prevent race conditions with irda_release() and irda_shutdown() */
        if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) {
+               lock_sock(sk);
                sk->sk_state     = TCP_CLOSE;
                sk->sk_err       = ECONNRESET;
                sk->sk_shutdown |= SEND_SHUTDOWN;
 
                sk->sk_state_change(sk);
-               /* Uh-oh... Should use sock_orphan ? */
-                sock_set_flag(sk, SOCK_DEAD);
+                sock_orphan(sk);
+               release_sock(sk);
 
                /* Close our TSAP.
                 * If we leave it open, IrLMP put it back into the list of
@@ -308,7 +309,8 @@ static void irda_connect_response(struct irda_sock *self)
 
        IRDA_ASSERT(self != NULL, return;);
 
-       skb = alloc_skb(64, GFP_ATOMIC);
+       skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+                       GFP_ATOMIC);
        if (skb == NULL) {
                IRDA_DEBUG(0, "%s() Unable to allocate sk_buff!\n",
                           __FUNCTION__);
@@ -1212,6 +1214,7 @@ static int irda_release(struct socket *sock)
         if (sk == NULL)
                return 0;
 
+       lock_sock(sk);
        sk->sk_state       = TCP_CLOSE;
        sk->sk_shutdown   |= SEND_SHUTDOWN;
        sk->sk_state_change(sk);
@@ -1221,6 +1224,7 @@ static int irda_release(struct socket *sock)
 
        sock_orphan(sk);
        sock->sk   = NULL;
+       release_sock(sk);
 
        /* Purge queues (see sock_init_data()) */
        skb_queue_purge(&sk->sk_receive_queue);
@@ -1353,6 +1357,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
        IRDA_ASSERT(self != NULL, return -1;);
+       IRDA_ASSERT(!sock_error(sk), return -1;);
 
        skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                flags & MSG_DONTWAIT, &err);
@@ -1405,6 +1410,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
        IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
        IRDA_ASSERT(self != NULL, return -1;);
+       IRDA_ASSERT(!sock_error(sk), return -1;);
 
        if (sock->flags & __SO_ACCEPTCON)
                return(-EINVAL);
index 959874b6451f00cf9edf4ad23343a1cd07e73b5b..c8e0d89ee11fd3e9443767fd875d05372453bcc5 100644 (file)
@@ -81,7 +81,7 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self,
        
        /* Any userdata supplied? */
        if (userdata == NULL) {
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
                if (!tx_skb)
                        return -ENOMEM;
 
@@ -115,7 +115,7 @@ static int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 
         if (!userdata) {
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
                if (!tx_skb)
                        return -ENOMEM;
                
index 61128aa05b4015c9fb85027bd1cc870b34a9beec..415cf4eec23b8e86ac69597dd0ffae6e3f953f44 100644 (file)
@@ -345,10 +345,11 @@ static void iriap_disconnect_request(struct iriap_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 
-       tx_skb = alloc_skb(64, GFP_ATOMIC);
+       tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
        if (tx_skb == NULL) {
-               IRDA_DEBUG(0, "%s(), Could not allocate an sk_buff of length %d\n", 
-                       __FUNCTION__, 64);
+               IRDA_DEBUG(0,
+                          "%s(), Could not allocate an sk_buff of length %d\n",
+                          __FUNCTION__, LMP_MAX_HEADER);
                return;
        }
 
@@ -701,7 +702,7 @@ void iriap_send_ack(struct iriap_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 
-       tx_skb = alloc_skb(64, GFP_ATOMIC);
+       tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC);
        if (!tx_skb)
                return;
 
index da17395df05adab0dab896b9e64f59ff1d4f62ab..99b18dc7a0b7e3b26f8fcd52d7c30bebee14d69d 100644 (file)
@@ -365,7 +365,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
 
        switch (event) {
        case IAP_LM_CONNECT_INDICATION:
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
                if (tx_skb == NULL) {
                        IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
                        return;
index 7dd0a2fe1d20dfac9a51b60fc4724c64e8c38b84..9b962f247714f5ec71c02f4b1e9822cd1531955e 100644 (file)
@@ -636,7 +636,8 @@ void irlan_get_provider_info(struct irlan_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-       skb = alloc_skb(64, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER,
+                       GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -668,7 +669,10 @@ void irlan_open_data_channel(struct irlan_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb = alloc_skb(64, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3") +
+                       IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "DIRECT"),
+                       GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -704,7 +708,9 @@ void irlan_close_data_channel(struct irlan_cb *self)
        if (self->client.tsap_ctrl == NULL)
                return;
 
-       skb = alloc_skb(64, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN"),
+                       GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -715,7 +721,7 @@ void irlan_close_data_channel(struct irlan_cb *self)
        
        /* Build frame */
        frame[0] = CMD_CLOSE_DATA_CHAN;
-       frame[1] = 0x01; /* Two parameters */
+       frame[1] = 0x01; /* One parameter */
 
        irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
 
@@ -739,7 +745,11 @@ static void irlan_open_unicast_addr(struct irlan_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);       
        
-       skb = alloc_skb(128, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
+                       GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -777,7 +787,12 @@ void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb = alloc_skb(128, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") +
+                       /* We may waste one byte here...*/
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
+                       GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -816,7 +831,12 @@ void irlan_set_multicast_filter(struct irlan_cb *self, int status)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-       skb = alloc_skb(128, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") +
+                       /* We may waste one byte here...*/
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "NONE"),
+                       GFP_ATOMIC);
        if (!skb)
                return;
        
@@ -856,7 +876,12 @@ static void irlan_get_unicast_addr(struct irlan_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb = alloc_skb(128, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_OPERATION",
+                                                  "DYNAMIC"),
+                       GFP_ATOMIC);
        if (!skb)
                return;
 
@@ -891,7 +916,10 @@ void irlan_get_media_char(struct irlan_cb *self)
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb = alloc_skb(64, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3"),
+                       GFP_ATOMIC);
+
        if (!skb)
                return;
 
index 9c0df86044d7d4aaeabe71c0be10667dda723a10..58efde919667fb1a18c7ee0436aa53c6c1185f09 100644 (file)
@@ -296,7 +296,14 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-       skb = alloc_skb(128, GFP_ATOMIC);
+       skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
+                       /* Bigger param length comes from CMD_GET_MEDIA_CHAR */
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BORADCAST") +
+                       IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") +
+                       IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "HOSTED"),
+                       GFP_ATOMIC);
+
        if (!skb)
                return;
 
@@ -354,8 +361,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
                } else
                        skb->data[1] = 0x02; /* 2 parameters */
                irlan_insert_byte_param(skb, "DATA_CHAN", self->stsap_sel_data);
-               irlan_insert_array_param(skb, "RECONNECT_KEY", "LINUX RULES!",
-                                        12);
+               irlan_insert_string_param(skb, "RECONNECT_KEY", "LINUX RULES!");
                break;
        case CMD_FILTER_OPERATION:
                irlan_filter_request(self, skb);
index ccb983bf0f4a222a8f848a0a8162b327c5d01d8e..dba349c832d02454b8451bbd02aa1935e23d9e15 100644 (file)
@@ -117,7 +117,9 @@ void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
        IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
        /* Allocate frame */
-       tx_skb = alloc_skb(64, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct snrm_frame) +
+                          IRLAP_NEGOCIATION_PARAMS_LEN,
+                          GFP_ATOMIC);
        if (!tx_skb)
                return;
 
@@ -136,7 +138,7 @@ void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
         *  If we are establishing a connection then insert QoS paramerters
         */
        if (qos) {
-               skb_put(tx_skb, 9); /* 21 left */
+               skb_put(tx_skb, 9); /* 25 left */
                frame->saddr = cpu_to_le32(self->saddr);
                frame->daddr = cpu_to_le32(self->daddr);
 
@@ -210,7 +212,9 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
        IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
        /* Allocate frame */
-       tx_skb = alloc_skb(64, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct ua_frame) +
+                          IRLAP_NEGOCIATION_PARAMS_LEN,
+                          GFP_ATOMIC);
        if (!tx_skb)
                return;
 
@@ -245,23 +249,23 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
 void irlap_send_dm_frame( struct irlap_cb *self)
 {
        struct sk_buff *tx_skb = NULL;
-       __u8 *frame;
+       struct dm_frame *frame;
 
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
-       tx_skb = alloc_skb(32, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct dm_frame), GFP_ATOMIC);
        if (!tx_skb)
                return;
 
-       frame = skb_put(tx_skb, 2);
+       frame = (struct dm_frame *)skb_put(tx_skb, 2);
 
        if (self->state == LAP_NDM)
-               frame[0] = CBROADCAST;
+               frame->caddr = CBROADCAST;
        else
-               frame[0] = self->caddr;
+               frame->caddr = self->caddr;
 
-       frame[1] = DM_RSP | PF_BIT;
+       frame->control = DM_RSP | PF_BIT;
 
        irlap_queue_xmit(self, tx_skb);
 }
@@ -275,21 +279,21 @@ void irlap_send_dm_frame( struct irlap_cb *self)
 void irlap_send_disc_frame(struct irlap_cb *self)
 {
        struct sk_buff *tx_skb = NULL;
-       __u8 *frame;
+       struct disc_frame *frame;
 
        IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
-       tx_skb = alloc_skb(16, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct disc_frame), GFP_ATOMIC);
        if (!tx_skb)
                return;
 
-       frame = skb_put(tx_skb, 2);
+       frame = (struct disc_frame *)skb_put(tx_skb, 2);
 
-       frame[0] = self->caddr | CMD_FRAME;
-       frame[1] = DISC_CMD | PF_BIT;
+       frame->caddr = self->caddr | CMD_FRAME;
+       frame->control = DISC_CMD | PF_BIT;
 
        irlap_queue_xmit(self, tx_skb);
 }
@@ -315,7 +319,8 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
        IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
        IRDA_ASSERT(discovery != NULL, return;);
 
-       tx_skb = alloc_skb(64, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct xid_frame) + IRLAP_DISCOVERY_INFO_LEN,
+                          GFP_ATOMIC);
        if (!tx_skb)
                return;
 
@@ -573,18 +578,18 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
 void irlap_send_rr_frame(struct irlap_cb *self, int command)
 {
        struct sk_buff *tx_skb;
-       __u8 *frame;
+       struct rr_frame *frame;
 
-       tx_skb = alloc_skb(16, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct rr_frame), GFP_ATOMIC);
        if (!tx_skb)
                return;
 
-       frame = skb_put(tx_skb, 2);
+       frame = (struct rr_frame *)skb_put(tx_skb, 2);
 
-       frame[0] = self->caddr;
-       frame[0] |= (command) ? CMD_FRAME : 0;
+       frame->caddr = self->caddr;
+       frame->caddr |= (command) ? CMD_FRAME : 0;
 
-       frame[1] = RR | PF_BIT | (self->vr << 5);
+       frame->control = RR | PF_BIT | (self->vr << 5);
 
        irlap_queue_xmit(self, tx_skb);
 }
@@ -598,16 +603,16 @@ void irlap_send_rr_frame(struct irlap_cb *self, int command)
 void irlap_send_rd_frame(struct irlap_cb *self)
 {
        struct sk_buff *tx_skb;
-       __u8 *frame;
+       struct rd_frame *frame;
 
-       tx_skb = alloc_skb(16, GFP_ATOMIC);
+       tx_skb = alloc_skb(sizeof(struct rd_frame), GFP_ATOMIC);
        if (!tx_skb)
                return;
 
-       frame = skb_put(tx_skb, 2);
+       frame = (struct rd_frame *)skb_put(tx_skb, 2);
 
-       frame[0] = self->caddr;
-       frame[1] = RD_RSP | PF_BIT;
+       frame->caddr = self->caddr;
+       frame->caddr = RD_RSP | PF_BIT;
 
        irlap_queue_xmit(self, tx_skb);
 }
@@ -1214,7 +1219,7 @@ void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
        struct test_frame *frame;
        __u8 *info;
 
-       tx_skb = alloc_skb(cmd->len+sizeof(struct test_frame), GFP_ATOMIC);
+       tx_skb = alloc_skb(cmd->len + sizeof(struct test_frame), GFP_ATOMIC);
        if (!tx_skb)
                return;
 
index c440913dee1468358e76cdef1fef6eeaad3d22a5..5073261b9d0c875d7884cf280866f6b324bb36ba 100644 (file)
@@ -392,7 +392,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
 
        /* Any userdata? */
        if (tx_skb == NULL) {
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
                if (!tx_skb)
                        return -ENOMEM;
 
index 42acf1cde737d4e0b992df9a6d469311385db410..3c2e70b77df16375952f1c0bc889f298a588e8a9 100644 (file)
@@ -804,12 +804,12 @@ static inline void irttp_give_credit(struct tsap_cb *self)
                   self->send_credit, self->avail_credit, self->remote_credit);
 
        /* Give credit to peer */
-       tx_skb = alloc_skb(64, GFP_ATOMIC);
+       tx_skb = alloc_skb(TTP_MAX_HEADER, GFP_ATOMIC);
        if (!tx_skb)
                return;
 
        /* Reserve space for LMP, and LAP header */
-       skb_reserve(tx_skb, self->max_header_size);
+       skb_reserve(tx_skb, LMP_MAX_HEADER);
 
        /*
         *  Since we can transmit and receive frames concurrently,
@@ -1093,7 +1093,8 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
 
        /* Any userdata supplied? */
        if (userdata == NULL) {
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+                                  GFP_ATOMIC);
                if (!tx_skb)
                        return -ENOMEM;
 
@@ -1341,7 +1342,8 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
 
        /* Any userdata supplied? */
        if (userdata == NULL) {
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+                                  GFP_ATOMIC);
                if (!tx_skb)
                        return -ENOMEM;
 
@@ -1540,14 +1542,14 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
 
        if (!userdata) {
                struct sk_buff *tx_skb;
-               tx_skb = alloc_skb(64, GFP_ATOMIC);
+               tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
                if (!tx_skb)
                        return -ENOMEM;
 
                /*
                 *  Reserve space for MUX and LAP header
                 */
-               skb_reserve(tx_skb, TTP_MAX_HEADER);
+               skb_reserve(tx_skb, LMP_MAX_HEADER);
 
                userdata = tx_skb;
        }
index 83b443ddc72f57c044e7f00f961f7e41d83fc148..ff98e70b0931f8e74cfc14c3d9b9337b50c12e41 100644 (file)
@@ -2140,7 +2140,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
        xp->selector.sport = ((struct sockaddr_in *)(sa+1))->sin_port;
        if (xp->selector.sport)
-               xp->selector.sport_mask = ~0;
+               xp->selector.sport_mask = htons(0xffff);
 
        sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
        pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);
@@ -2153,7 +2153,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
 
        xp->selector.dport = ((struct sockaddr_in *)(sa+1))->sin_port;
        if (xp->selector.dport)
-               xp->selector.dport_mask = ~0;
+               xp->selector.dport_mask = htons(0xffff);
 
        sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
        if (sec_ctx != NULL) {
@@ -2243,7 +2243,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
        sel.sport = ((struct sockaddr_in *)(sa+1))->sin_port;
        if (sel.sport)
-               sel.sport_mask = ~0;
+               sel.sport_mask = htons(0xffff);
 
        sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], 
        pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
@@ -2251,7 +2251,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
        sel.dport = ((struct sockaddr_in *)(sa+1))->sin_port;
        if (sel.dport)
-               sel.dport_mask = ~0;
+               sel.dport_mask = htons(0xffff);
 
        sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
        memset(&tmp, 0, sizeof(struct xfrm_policy));
index 4125a55f469f197051963a3f0c3e1f8057084c95..a6ce1d6d5c59a00fced6f8ff82b290c0d3615719 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/socket.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
+#include <linux/audit.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
@@ -162,8 +163,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
        int nla_a_rem;
        int nla_b_rem;
 
-       if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
-           !info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
+       if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
            !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
                return -EINVAL;
 
@@ -344,8 +344,7 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info)
        int ret_val;
        struct cipso_v4_doi *doi_def = NULL;
 
-       if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
-           !info->attrs[NLBL_CIPSOV4_A_TAGLST])
+       if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
                return -EINVAL;
 
        doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
@@ -381,21 +380,40 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
 
 {
        int ret_val = -EINVAL;
-       u32 map_type;
+       u32 type;
+       u32 doi;
+       const char *type_str = "(unknown)";
+       struct audit_buffer *audit_buf;
+       struct netlbl_audit audit_info;
 
-       if (!info->attrs[NLBL_CIPSOV4_A_MTYPE])
+       if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
+           !info->attrs[NLBL_CIPSOV4_A_MTYPE])
                return -EINVAL;
 
-       map_type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
-       switch (map_type) {
+       doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
+       type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
+       switch (type) {
        case CIPSO_V4_MAP_STD:
+               type_str = "std";
                ret_val = netlbl_cipsov4_add_std(info);
                break;
        case CIPSO_V4_MAP_PASS:
+               type_str = "pass";
                ret_val = netlbl_cipsov4_add_pass(info);
                break;
        }
 
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
+                                             &audit_info);
+       audit_log_format(audit_buf,
+                        " cipso_doi=%u cipso_type=%s res=%u",
+                        doi,
+                        type_str,
+                        ret_val == 0 ? 1 : 0);
+       audit_log_end(audit_buf);
+
        return ret_val;
 }
 
@@ -653,12 +671,27 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb,
 static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
 {
        int ret_val = -EINVAL;
-       u32 doi;
+       u32 doi = 0;
+       struct audit_buffer *audit_buf;
+       struct netlbl_audit audit_info;
 
-       if (info->attrs[NLBL_CIPSOV4_A_DOI]) {
-               doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
-               ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
-       }
+       if (!info->attrs[NLBL_CIPSOV4_A_DOI])
+               return -EINVAL;
+
+       doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
+       ret_val = cipso_v4_doi_remove(doi,
+                                     &audit_info,
+                                     netlbl_cipsov4_doi_free);
+
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
+                                             &audit_info);
+       audit_log_format(audit_buf,
+                        " cipso_doi=%u res=%u",
+                        doi,
+                        ret_val == 0 ? 1 : 0);
+       audit_log_end(audit_buf);
 
        return ret_val;
 }
index f56d7a8ac7b758dacd86f83442569263b2df9253..af4371d3b459d63bcd756dd5b4f250229198494d 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
+#include <linux/audit.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <asm/bug.h>
 
 #include "netlabel_mgmt.h"
 #include "netlabel_domainhash.h"
+#include "netlabel_user.h"
 
 struct netlbl_domhsh_tbl {
        struct list_head *tbl;
@@ -186,6 +188,7 @@ int netlbl_domhsh_init(u32 size)
 /**
  * netlbl_domhsh_add - Adds a entry to the domain hash table
  * @entry: the entry to add
+ * @audit_info: NetLabel audit information
  *
  * Description:
  * Adds a new entry to the domain hash table and handles any updates to the
@@ -193,10 +196,13 @@ int netlbl_domhsh_init(u32 size)
  * negative on failure.
  *
  */
-int netlbl_domhsh_add(struct netlbl_dom_map *entry)
+int netlbl_domhsh_add(struct netlbl_dom_map *entry,
+                     struct netlbl_audit *audit_info)
 {
        int ret_val;
        u32 bkt;
+       struct audit_buffer *audit_buf;
+       char *audit_domain;
 
        switch (entry->type) {
        case NETLBL_NLTYPE_UNLABELED:
@@ -236,6 +242,26 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry)
                spin_unlock(&netlbl_domhsh_def_lock);
        } else
                ret_val = -EINVAL;
+
+       if (entry->domain != NULL)
+               audit_domain = entry->domain;
+       else
+               audit_domain = "(default)";
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
+       audit_log_format(audit_buf, " nlbl_domain=%s", audit_domain);
+       switch (entry->type) {
+       case NETLBL_NLTYPE_UNLABELED:
+               audit_log_format(audit_buf, " nlbl_protocol=unlbl");
+               break;
+       case NETLBL_NLTYPE_CIPSOV4:
+               audit_log_format(audit_buf,
+                                " nlbl_protocol=cipsov4 cipso_doi=%u",
+                                entry->type_def.cipsov4->doi);
+               break;
+       }
+       audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
+       audit_log_end(audit_buf);
+
        rcu_read_unlock();
 
        if (ret_val != 0) {
@@ -254,6 +280,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry)
 /**
  * netlbl_domhsh_add_default - Adds the default entry to the domain hash table
  * @entry: the entry to add
+ * @audit_info: NetLabel audit information
  *
  * Description:
  * Adds a new default entry to the domain hash table and handles any updates
@@ -261,14 +288,16 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry)
  * negative on failure.
  *
  */
-int netlbl_domhsh_add_default(struct netlbl_dom_map *entry)
+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
+                             struct netlbl_audit *audit_info)
 {
-       return netlbl_domhsh_add(entry);
+       return netlbl_domhsh_add(entry, audit_info);
 }
 
 /**
  * netlbl_domhsh_remove - Removes an entry from the domain hash table
  * @domain: the domain to remove
+ * @audit_info: NetLabel audit information
  *
  * Description:
  * Removes an entry from the domain hash table and handles any updates to the
@@ -276,10 +305,12 @@ int netlbl_domhsh_add_default(struct netlbl_dom_map *entry)
  * negative on failure.
  *
  */
-int netlbl_domhsh_remove(const char *domain)
+int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
 {
        int ret_val = -ENOENT;
        struct netlbl_dom_map *entry;
+       struct audit_buffer *audit_buf;
+       char *audit_domain;
 
        rcu_read_lock();
        if (domain != NULL)
@@ -316,6 +347,18 @@ int netlbl_domhsh_remove(const char *domain)
                        ret_val = -ENOENT;
                spin_unlock(&netlbl_domhsh_def_lock);
        }
+
+       if (entry->domain != NULL)
+               audit_domain = entry->domain;
+       else
+               audit_domain = "(default)";
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info);
+       audit_log_format(audit_buf,
+                        " nlbl_domain=%s res=%u",
+                        audit_domain,
+                        ret_val == 0 ? 1 : 0);
+       audit_log_end(audit_buf);
+
        if (ret_val == 0)
                call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
 
@@ -326,6 +369,7 @@ remove_return:
 
 /**
  * netlbl_domhsh_remove_default - Removes the default entry from the table
+ * @audit_info: NetLabel audit information
  *
  * Description:
  * Removes/resets the default entry for the domain hash table and handles any
@@ -333,9 +377,9 @@ remove_return:
  * success, non-zero on failure.
  *
  */
-int netlbl_domhsh_remove_default(void)
+int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info)
 {
-       return netlbl_domhsh_remove(NULL);
+       return netlbl_domhsh_remove(NULL, audit_info);
 }
 
 /**
index 02af72a7877cb94d553a39998356d6a69d12d156..3689956c34363242007d300b0865c53a0da867d5 100644 (file)
@@ -57,9 +57,11 @@ struct netlbl_dom_map {
 int netlbl_domhsh_init(u32 size);
 
 /* Manipulate the domain hash table */
-int netlbl_domhsh_add(struct netlbl_dom_map *entry);
-int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
-int netlbl_domhsh_remove_default(void);
+int netlbl_domhsh_add(struct netlbl_dom_map *entry,
+                     struct netlbl_audit *audit_info);
+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
+                             struct netlbl_audit *audit_info);
+int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info);
 struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
 int netlbl_domhsh_walk(u32 *skip_bkt,
                     u32 *skip_chain,
index 8626c9f678ebbb3434bed1c3e2977e5c28d18824..53c9079ad2c3932404df4fae1cdc5d47fb413dc4 100644 (file)
@@ -87,11 +87,14 @@ static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
        struct netlbl_dom_map *entry = NULL;
        size_t tmp_size;
        u32 tmp_val;
+       struct netlbl_audit audit_info;
 
        if (!info->attrs[NLBL_MGMT_A_DOMAIN] ||
            !info->attrs[NLBL_MGMT_A_PROTOCOL])
                goto add_failure;
 
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (entry == NULL) {
                ret_val = -ENOMEM;
@@ -108,7 +111,7 @@ static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
 
        switch (entry->type) {
        case NETLBL_NLTYPE_UNLABELED:
-               ret_val = netlbl_domhsh_add(entry);
+               ret_val = netlbl_domhsh_add(entry, &audit_info);
                break;
        case NETLBL_NLTYPE_CIPSOV4:
                if (!info->attrs[NLBL_MGMT_A_CV4DOI])
@@ -125,7 +128,7 @@ static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
                        rcu_read_unlock();
                        goto add_failure;
                }
-               ret_val = netlbl_domhsh_add(entry);
+               ret_val = netlbl_domhsh_add(entry, &audit_info);
                rcu_read_unlock();
                break;
        default:
@@ -156,12 +159,15 @@ add_failure:
 static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
 {
        char *domain;
+       struct netlbl_audit audit_info;
 
        if (!info->attrs[NLBL_MGMT_A_DOMAIN])
                return -EINVAL;
 
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
        domain = nla_data(info->attrs[NLBL_MGMT_A_DOMAIN]);
-       return netlbl_domhsh_remove(domain);
+       return netlbl_domhsh_remove(domain, &audit_info);
 }
 
 /**
@@ -264,10 +270,13 @@ static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
        int ret_val = -EINVAL;
        struct netlbl_dom_map *entry = NULL;
        u32 tmp_val;
+       struct netlbl_audit audit_info;
 
        if (!info->attrs[NLBL_MGMT_A_PROTOCOL])
                goto adddef_failure;
 
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (entry == NULL) {
                ret_val = -ENOMEM;
@@ -277,7 +286,7 @@ static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
 
        switch (entry->type) {
        case NETLBL_NLTYPE_UNLABELED:
-               ret_val = netlbl_domhsh_add_default(entry);
+               ret_val = netlbl_domhsh_add_default(entry, &audit_info);
                break;
        case NETLBL_NLTYPE_CIPSOV4:
                if (!info->attrs[NLBL_MGMT_A_CV4DOI])
@@ -294,7 +303,7 @@ static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
                        rcu_read_unlock();
                        goto adddef_failure;
                }
-               ret_val = netlbl_domhsh_add_default(entry);
+               ret_val = netlbl_domhsh_add_default(entry, &audit_info);
                rcu_read_unlock();
                break;
        default:
@@ -322,7 +331,11 @@ adddef_failure:
  */
 static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
 {
-       return netlbl_domhsh_remove_default();
+       struct netlbl_audit audit_info;
+
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
+       return netlbl_domhsh_remove_default(&audit_info);
 }
 
 /**
index 440f5c4e1e2d1c636a1ca125da78467b6db6583d..1833ad233b39f33a7a0d062d24901cade27f8400 100644 (file)
@@ -63,6 +63,34 @@ static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
        [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
 };
 
+/*
+ * Helper Functions
+ */
+
+/**
+ * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
+ * @value: desired value
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Set the value of the unlabeled accept flag to @value.
+ *
+ */
+static void netlbl_unlabel_acceptflg_set(u8 value,
+                                        struct netlbl_audit *audit_info)
+{
+       struct audit_buffer *audit_buf;
+       u8 old_val;
+
+       old_val = atomic_read(&netlabel_unlabel_accept_flg);
+       atomic_set(&netlabel_unlabel_accept_flg, value);
+
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
+                                             audit_info);
+       audit_log_format(audit_buf, " unlbl_accept=%u old=%u", value, old_val);
+       audit_log_end(audit_buf);
+}
+
 /*
  * NetLabel Command Handlers
  */
@@ -79,18 +107,19 @@ static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
  */
 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
 {
-       int ret_val = -EINVAL;
        u8 value;
+       struct netlbl_audit audit_info;
 
        if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
                value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
                if (value == 1 || value == 0) {
-                       atomic_set(&netlabel_unlabel_accept_flg, value);
-                       ret_val = 0;
+                       netlbl_netlink_auditinfo(skb, &audit_info);
+                       netlbl_unlabel_acceptflg_set(value, &audit_info);
+                       return 0;
                }
        }
 
-       return ret_val;
+       return -EINVAL;
 }
 
 /**
@@ -229,16 +258,23 @@ int netlbl_unlabel_defconf(void)
 {
        int ret_val;
        struct netlbl_dom_map *entry;
+       struct netlbl_audit audit_info;
+
+       /* Only the kernel is allowed to call this function and the only time
+        * it is called is at bootup before the audit subsystem is reporting
+        * messages so don't worry to much about these values. */
+       security_task_getsecid(current, &audit_info.secid);
+       audit_info.loginuid = 0;
 
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (entry == NULL)
                return -ENOMEM;
        entry->type = NETLBL_NLTYPE_UNLABELED;
-       ret_val = netlbl_domhsh_add_default(entry);
+       ret_val = netlbl_domhsh_add_default(entry, &audit_info);
        if (ret_val != 0)
                return ret_val;
 
-       atomic_set(&netlabel_unlabel_accept_flg, 1);
+       netlbl_unlabel_acceptflg_set(1, &audit_info);
 
        return 0;
 }
index eeb7d768d2bb558c7c963f372ec4b7b585d6b675..98a416381e61251e1986eb176d69492ca2d7a7da 100644 (file)
@@ -32,6 +32,9 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/socket.h>
+#include <linux/audit.h>
+#include <linux/tty.h>
+#include <linux/security.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
@@ -74,3 +77,41 @@ int netlbl_netlink_init(void)
 
        return 0;
 }
+
+/*
+ * NetLabel Audit Functions
+ */
+
+/**
+ * netlbl_audit_start_common - Start an audit message
+ * @type: audit message type
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Start an audit message using the type specified in @type and fill the audit
+ * message with some fields common to all NetLabel audit messages.  Returns
+ * a pointer to the audit buffer on success, NULL on failure.
+ *
+ */
+struct audit_buffer *netlbl_audit_start_common(int type,
+                                              struct netlbl_audit *audit_info)
+{
+       struct audit_context *audit_ctx = current->audit_context;
+       struct audit_buffer *audit_buf;
+       char *secctx;
+       u32 secctx_len;
+
+       audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type);
+       if (audit_buf == NULL)
+               return NULL;
+
+       audit_log_format(audit_buf, "netlabel: auid=%u", audit_info->loginuid);
+
+       if (audit_info->secid != 0 &&
+           security_secid_to_secctx(audit_info->secid,
+                                    &secctx,
+                                    &secctx_len) == 0)
+               audit_log_format(audit_buf, " subj=%s", secctx);
+
+       return audit_buf;
+}
index 3f9386b917df4bfdf6bb354ac681588dab728b0b..47967ef329640dc700f46ec018f61e0c95c22263 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/capability.h>
+#include <linux/audit.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/netlabel.h>
@@ -71,8 +72,25 @@ static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb,
                           NETLBL_PROTO_VERSION);
 }
 
+/**
+ * netlbl_netlink_auditinfo - Fetch the audit information from a NETLINK msg
+ * @skb: the packet
+ * @audit_info: NetLabel audit information
+ */
+static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
+                                           struct netlbl_audit *audit_info)
+{
+       audit_info->secid = NETLINK_CB(skb).sid;
+       audit_info->loginuid = NETLINK_CB(skb).loginuid;
+}
+
 /* NetLabel NETLINK I/O functions */
 
 int netlbl_netlink_init(void);
 
+/* NetLabel Audit Functions */
+
+struct audit_buffer *netlbl_audit_start_common(int type,
+                                             struct netlbl_audit *audit_info);
+
 #endif
index 465efc86fccf1f253cf93a4e5705017e6e1dd83d..94b2e2fe6fdb97ec548956f1d247d5da8ad4c70b 100644 (file)
@@ -381,11 +381,10 @@ static int rxrpc_incoming_msg(struct rxrpc_transport *trans,
 
                /* allocate a new message record */
                ret = -ENOMEM;
-               msg = kmalloc(sizeof(struct rxrpc_message), GFP_KERNEL);
+               msg = kmemdup(jumbomsg, sizeof(struct rxrpc_message), GFP_KERNEL);
                if (!msg)
                        goto error;
 
-               memcpy(msg, jumbomsg, sizeof(*msg));
                list_add_tail(&msg->link, msgq);
 
                /* adjust the jumbo packet */
index 7e14f14058e991393ca1a75aacc669a516e1906c..37a1840216474d77c2ad534903059bbeb1a840ea 100644 (file)
@@ -401,7 +401,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
        if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL)
                return skb->len;
 
-       read_lock_bh(&qdisc_tree_lock);
+       read_lock(&qdisc_tree_lock);
        if (!tcm->tcm_parent)
                q = dev->qdisc_sleeping;
        else
@@ -458,7 +458,7 @@ errout:
        if (cl)
                cops->put(q, cl);
 out:
-       read_unlock_bh(&qdisc_tree_lock);
+       read_unlock(&qdisc_tree_lock);
        dev_put(dev);
        return skb->len;
 }
index 86cac49a0531476d716c31c9a195571063bb9117..09fda68c8b39f494f6b5802a99efc34a39cdc030 100644 (file)
@@ -194,7 +194,7 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        if (handle)
                f->handle = handle;
        else {
-               int i = 0x80000000;
+               unsigned int i = 0x80000000;
                do {
                        if (++head->hgenerator == 0x7FFFFFFF)
                                head->hgenerator = 1;
index a19eff12cf78b9013d66f070153c869f8242b151..0b6489291140f0324c73e8a8ddb0aad716c03593 100644 (file)
@@ -195,14 +195,14 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
 {
        struct Qdisc *q;
 
-       read_lock_bh(&qdisc_tree_lock);
+       read_lock(&qdisc_tree_lock);
        list_for_each_entry(q, &dev->qdisc_list, list) {
                if (q->handle == handle) {
-                       read_unlock_bh(&qdisc_tree_lock);
+                       read_unlock(&qdisc_tree_lock);
                        return q;
                }
        }
-       read_unlock_bh(&qdisc_tree_lock);
+       read_unlock(&qdisc_tree_lock);
        return NULL;
 }
 
@@ -837,7 +837,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
                if (idx > s_idx)
                        s_q_idx = 0;
-               read_lock_bh(&qdisc_tree_lock);
+               read_lock(&qdisc_tree_lock);
                q_idx = 0;
                list_for_each_entry(q, &dev->qdisc_list, list) {
                        if (q_idx < s_q_idx) {
@@ -846,12 +846,12 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
                        }
                        if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
                                          cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
-                               read_unlock_bh(&qdisc_tree_lock);
+                               read_unlock(&qdisc_tree_lock);
                                goto done;
                        }
                        q_idx++;
                }
-               read_unlock_bh(&qdisc_tree_lock);
+               read_unlock(&qdisc_tree_lock);
        }
 
 done:
@@ -1074,7 +1074,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
        s_t = cb->args[0];
        t = 0;
 
-       read_lock_bh(&qdisc_tree_lock);
+       read_lock(&qdisc_tree_lock);
        list_for_each_entry(q, &dev->qdisc_list, list) {
                if (t < s_t || !q->ops->cl_ops ||
                    (tcm->tcm_parent &&
@@ -1096,7 +1096,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
                        break;
                t++;
        }
-       read_unlock_bh(&qdisc_tree_lock);
+       read_unlock(&qdisc_tree_lock);
 
        cb->args[0] = t;
 
index 6f91518997951cbd13056373f36a98c0f87136b2..88c6a99ce53cfb675c9fb1198ca7f5328be3577e 100644 (file)
    The idea is the following:
    - enqueue, dequeue are serialized via top level device
      spinlock dev->queue_lock.
-   - tree walking is protected by read_lock_bh(qdisc_tree_lock)
+   - tree walking is protected by read_lock(qdisc_tree_lock)
      and this lock is used only in process context.
-   - updates to tree are made under rtnl semaphore or
-     from softirq context (__qdisc_destroy rcu-callback)
-     hence this lock needs local bh disabling.
+   - updates to tree are made only under rtnl semaphore,
+     hence this lock may be made without local bh disabling.
 
    qdisc_tree_lock must be grabbed BEFORE dev->queue_lock!
  */
@@ -57,14 +56,14 @@ DEFINE_RWLOCK(qdisc_tree_lock);
 
 void qdisc_lock_tree(struct net_device *dev)
 {
-       write_lock_bh(&qdisc_tree_lock);
+       write_lock(&qdisc_tree_lock);
        spin_lock_bh(&dev->queue_lock);
 }
 
 void qdisc_unlock_tree(struct net_device *dev)
 {
        spin_unlock_bh(&dev->queue_lock);
-       write_unlock_bh(&qdisc_tree_lock);
+       write_unlock(&qdisc_tree_lock);
 }
 
 /* 
@@ -483,20 +482,6 @@ void qdisc_reset(struct Qdisc *qdisc)
 static void __qdisc_destroy(struct rcu_head *head)
 {
        struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
-       struct Qdisc_ops  *ops = qdisc->ops;
-
-#ifdef CONFIG_NET_ESTIMATOR
-       gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
-#endif
-       write_lock(&qdisc_tree_lock);
-       if (ops->reset)
-               ops->reset(qdisc);
-       if (ops->destroy)
-               ops->destroy(qdisc);
-       write_unlock(&qdisc_tree_lock);
-       module_put(ops->owner);
-
-       dev_put(qdisc->dev);
        kfree((char *) qdisc - qdisc->padded);
 }
 
@@ -504,32 +489,23 @@ static void __qdisc_destroy(struct rcu_head *head)
 
 void qdisc_destroy(struct Qdisc *qdisc)
 {
-       struct list_head cql = LIST_HEAD_INIT(cql);
-       struct Qdisc *cq, *q, *n;
+       struct Qdisc_ops  *ops = qdisc->ops;
 
        if (qdisc->flags & TCQ_F_BUILTIN ||
-               !atomic_dec_and_test(&qdisc->refcnt))
+           !atomic_dec_and_test(&qdisc->refcnt))
                return;
 
-       if (!list_empty(&qdisc->list)) {
-               if (qdisc->ops->cl_ops == NULL)
-                       list_del(&qdisc->list);
-               else
-                       list_move(&qdisc->list, &cql);
-       }
-
-       /* unlink inner qdiscs from dev->qdisc_list immediately */
-       list_for_each_entry(cq, &cql, list)
-               list_for_each_entry_safe(q, n, &qdisc->dev->qdisc_list, list)
-                       if (TC_H_MAJ(q->parent) == TC_H_MAJ(cq->handle)) {
-                               if (q->ops->cl_ops == NULL)
-                                       list_del_init(&q->list);
-                               else
-                                       list_move_tail(&q->list, &cql);
-                       }
-       list_for_each_entry_safe(cq, n, &cql, list)
-               list_del_init(&cq->list);
+       list_del(&qdisc->list);
+#ifdef CONFIG_NET_ESTIMATOR
+       gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
+#endif
+       if (ops->reset)
+               ops->reset(qdisc);
+       if (ops->destroy)
+               ops->destroy(qdisc);
 
+       module_put(ops->owner);
+       dev_put(qdisc->dev);
        call_rcu(&qdisc->q_rcu, __qdisc_destroy);
 }
 
@@ -549,15 +525,15 @@ void dev_activate(struct net_device *dev)
                                printk(KERN_INFO "%s: activation failed\n", dev->name);
                                return;
                        }
-                       write_lock_bh(&qdisc_tree_lock);
+                       write_lock(&qdisc_tree_lock);
                        list_add_tail(&qdisc->list, &dev->qdisc_list);
-                       write_unlock_bh(&qdisc_tree_lock);
+                       write_unlock(&qdisc_tree_lock);
                } else {
                        qdisc =  &noqueue_qdisc;
                }
-               write_lock_bh(&qdisc_tree_lock);
+               write_lock(&qdisc_tree_lock);
                dev->qdisc_sleeping = qdisc;
-               write_unlock_bh(&qdisc_tree_lock);
+               write_unlock(&qdisc_tree_lock);
        }
 
        if (!netif_carrier_ok(dev))
index bb3ddd4784b1cebfd4668dc15df844b484b36267..6c058e3660c0c28ec9e6d85cd79f92c94c391539 100644 (file)
@@ -391,7 +391,7 @@ static inline void htb_add_class_to_row(struct htb_sched *q,
 /* If this triggers, it is a bug in this code, but it need not be fatal */
 static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
 {
-       if (RB_EMPTY_NODE(rb)) {
+       if (!RB_EMPTY_NODE(rb)) {
                WARN_ON(1);
        } else {
                rb_erase(rb, root);
index 03f65de75d88280c0096f4aac8efbbe4330e9383..64f630102532c9e3e95379458bd934902bcf2870 100644 (file)
@@ -218,12 +218,6 @@ int sctp_rcv(struct sk_buff *skb)
                }
        }
 
-       /* SCTP seems to always need a timestamp right now (FIXME) */
-       if (skb->tstamp.off_sec == 0) {
-               __net_timestamp(skb);
-               sock_enable_timestamp(sk); 
-       }
-
        if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
                goto discard_release;
        nf_reset(skb);
@@ -388,7 +382,7 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
                         * pmtu discovery on this transport.
                         */
                        t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
-                       t->param_flags = (t->param_flags & ~SPP_HB) |
+                       t->param_flags = (t->param_flags & ~SPP_PMTUD) |
                                SPP_PMTUD_DISABLE;
                } else {
                        t->pathmtu = pmtu;
index cdc5a393676657691a2421b573235fde8318b0f8..3ef4351dd956ad95649afd568b3a91381a86e730 100644 (file)
@@ -633,7 +633,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
                 * data will fit or delay in hopes of bundling a full
                 * sized packet.
                 */
-               if (len < asoc->pathmtu - packet->overhead) {
+               if (len < asoc->frag_point) {
                        retval = SCTP_XMIT_NAGLE_DELAY;
                        goto finish;
                }
@@ -645,7 +645,13 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
        /* Keep track of how many bytes are in flight to the receiver. */
        asoc->outqueue.outstanding_bytes += datasize;
 
-       /* Update our view of the receiver's rwnd. */
+       /* Update our view of the receiver's rwnd. Include sk_buff overhead
+        * while updating peer.rwnd so that it reduces the chances of a
+        * receiver running out of receive buffer space even when receive
+        * window is still open. This can happen when a sender is sending
+        * sending small messages.
+        */
+       datasize += sizeof(struct sk_buff);
        if (datasize < rwnd)
                rwnd -= datasize;
        else
index 37074a39ecbbfb68939c9cc6b0679e21eba71bb1..739582415bf6d84b98d61235ac6a220b9a01cd34 100644 (file)
@@ -416,7 +416,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                         * (Section 7.2.4)), add the data size of those
                         * chunks to the rwnd.
                         */
-                       q->asoc->peer.rwnd += sctp_data_size(chunk);
+                       q->asoc->peer.rwnd += (sctp_data_size(chunk) +
+                                               sizeof(struct sk_buff));
                        q->outstanding_bytes -= sctp_data_size(chunk);
                        transport->flight_size -= sctp_data_size(chunk);
 
index 7745bdea7817acab1709df3e454785822ac2933a..507dff72c5853508279847672c84dcab460436cf 100644 (file)
@@ -1447,8 +1447,16 @@ no_hmac:
        /* Check to see if the cookie is stale.  If there is already
         * an association, there is no need to check cookie's expiration
         * for init collision case of lost COOKIE ACK.
+        * If skb has been timestamped, then use the stamp, otherwise
+        * use current time.  This introduces a small possibility that
+        * that a cookie may be considered expired, but his would only slow
+        * down the new association establishment instead of every packet.
         */
-       skb_get_timestamp(skb, &tv);
+       if (sock_flag(ep->base.sk, SOCK_TIMESTAMP))
+               skb_get_timestamp(skb, &tv);
+       else
+               do_gettimeofday(&tv);
+
        if (!asoc && tv_lt(bear_cookie->expiration, tv)) {
                __u16 len;
                /*
index 79c3e072cf282027f3988c17d90bbc2c6c2143b8..3fe906d6506982f9e1c7a0bdcf6e67b6d2772d58 100644 (file)
@@ -3084,8 +3084,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
         */
        sp->disable_fragments = 0;
 
-       /* Turn on/off any Nagle-like algorithm.  */
-       sp->nodelay           = 1;
+       /* Enable Nagle algorithm by default.  */
+       sp->nodelay           = 0;
 
        /* Enable by default. */
        sp->v4mapped          = 1;
index 1bc4167e0da8da20c2364c14ea48b73a0cca28df..01918f7a301aaa11f8b2375e6173dc52dee84645 100644 (file)
 #include <linux/netfilter.h>
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
-static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
-                            size_t size, loff_t pos);
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *buf,
-                             size_t size, loff_t pos);
+static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                        unsigned long nr_segs, loff_t pos);
+static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                         unsigned long nr_segs, loff_t pos);
 static int sock_mmap(struct file *file, struct vm_area_struct *vma);
 
 static int sock_close(struct inode *inode, struct file *file);
@@ -110,10 +110,6 @@ static long compat_sock_ioctl(struct file *file,
                              unsigned int cmd, unsigned long arg);
 #endif
 static int sock_fasync(int fd, struct file *filp, int on);
-static ssize_t sock_readv(struct file *file, const struct iovec *vector,
-                         unsigned long count, loff_t *ppos);
-static ssize_t sock_writev(struct file *file, const struct iovec *vector,
-                          unsigned long count, loff_t *ppos);
 static ssize_t sock_sendpage(struct file *file, struct page *page,
                             int offset, size_t size, loff_t *ppos, int more);
 
@@ -136,8 +132,6 @@ static struct file_operations socket_file_ops = {
        .open =         sock_no_open,   /* special open code to disallow open via /proc */
        .release =      sock_close,
        .fasync =       sock_fasync,
-       .readv =        sock_readv,
-       .writev =       sock_writev,
        .sendpage =     sock_sendpage,
        .splice_write = generic_splice_sendpage,
 };
@@ -664,7 +658,6 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
 }
 
 static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
-                                        char __user *ubuf, size_t size,
                                         struct sock_iocb *siocb)
 {
        if (!is_sync_kiocb(iocb)) {
@@ -675,16 +668,13 @@ static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
        }
 
        siocb->kiocb = iocb;
-       siocb->async_iov.iov_base = ubuf;
-       siocb->async_iov.iov_len = size;
-
        iocb->private = siocb;
        return siocb;
 }
 
 static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
-                           struct file *file, struct iovec *iov,
-                           unsigned long nr_segs)
+               struct file *file, const struct iovec *iov,
+               unsigned long nr_segs)
 {
        struct socket *sock = file->private_data;
        size_t size = 0;
@@ -704,43 +694,27 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
        return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
 }
 
-static ssize_t sock_readv(struct file *file, const struct iovec *iov,
-                         unsigned long nr_segs, loff_t *ppos)
-{
-       struct kiocb iocb;
-       struct sock_iocb siocb;
-       struct msghdr msg;
-       int ret;
-
-       init_sync_kiocb(&iocb, NULL);
-       iocb.private = &siocb;
-
-       ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&iocb);
-       return ret;
-}
-
-static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
-                            size_t count, loff_t pos)
+static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos)
 {
        struct sock_iocb siocb, *x;
 
        if (pos != 0)
                return -ESPIPE;
-       if (count == 0)         /* Match SYS5 behaviour */
+
+       if (iocb->ki_left == 0) /* Match SYS5 behaviour */
                return 0;
 
-       x = alloc_sock_iocb(iocb, ubuf, count, &siocb);
+
+       x = alloc_sock_iocb(iocb, &siocb);
        if (!x)
                return -ENOMEM;
-       return do_sock_read(&x->async_msg, iocb, iocb->ki_filp,
-                           &x->async_iov, 1);
+       return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
 }
 
 static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
-                            struct file *file, struct iovec *iov,
-                            unsigned long nr_segs)
+                       struct file *file, const struct iovec *iov,
+                       unsigned long nr_segs)
 {
        struct socket *sock = file->private_data;
        size_t size = 0;
@@ -762,39 +736,22 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
        return __sock_sendmsg(iocb, sock, msg, size);
 }
 
-static ssize_t sock_writev(struct file *file, const struct iovec *iov,
-                          unsigned long nr_segs, loff_t *ppos)
-{
-       struct msghdr msg;
-       struct kiocb iocb;
-       struct sock_iocb siocb;
-       int ret;
-
-       init_sync_kiocb(&iocb, NULL);
-       iocb.private = &siocb;
-
-       ret = do_sock_write(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
-       if (-EIOCBQUEUED == ret)
-               ret = wait_on_sync_kiocb(&iocb);
-       return ret;
-}
-
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
-                             size_t count, loff_t pos)
+static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                         unsigned long nr_segs, loff_t pos)
 {
        struct sock_iocb siocb, *x;
 
        if (pos != 0)
                return -ESPIPE;
-       if (count == 0)         /* Match SYS5 behaviour */
+
+       if (iocb->ki_left == 0) /* Match SYS5 behaviour */
                return 0;
 
-       x = alloc_sock_iocb(iocb, (void __user *)ubuf, count, &siocb);
+       x = alloc_sock_iocb(iocb, &siocb);
        if (!x)
                return -ENOMEM;
 
-       return do_sock_write(&x->async_msg, iocb, iocb->ki_filp,
-                            &x->async_iov, 1);
+       return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
 }
 
 /*
index 55163af3dcaf2cdb4f195fccb39c94442373c624..993ff1a5d945687883c51ffc4a8662c87aa7704a 100644 (file)
@@ -331,8 +331,8 @@ rpcauth_unbindcred(struct rpc_task *task)
        task->tk_msg.rpc_cred = NULL;
 }
 
-u32 *
-rpcauth_marshcred(struct rpc_task *task, u32 *p)
+__be32 *
+rpcauth_marshcred(struct rpc_task *task, __be32 *p)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
@@ -342,8 +342,8 @@ rpcauth_marshcred(struct rpc_task *task, u32 *p)
        return cred->cr_ops->crmarshal(task, p);
 }
 
-u32 *
-rpcauth_checkverf(struct rpc_task *task, u32 *p)
+__be32 *
+rpcauth_checkverf(struct rpc_task *task, __be32 *p)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
@@ -355,7 +355,7 @@ rpcauth_checkverf(struct rpc_task *task, u32 *p)
 
 int
 rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
-               u32 *data, void *obj)
+               __be32 *data, void *obj)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
@@ -369,7 +369,7 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
 
 int
 rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
-               u32 *data, void *obj)
+               __be32 *data, void *obj)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
index 6eed3e166ba33ab083c6d831a6b5c33d63b2fede..a6ed2d22a6e6e8017bcd6e1f9816ee2d2fcbbf64 100644 (file)
@@ -826,14 +826,14 @@ out:
 * Marshal credentials.
 * Maybe we should keep a cached credential for performance reasons.
 */
-static u32 *
-gss_marshal(struct rpc_task *task, u32 *p)
+static __be32 *
+gss_marshal(struct rpc_task *task, __be32 *p)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
                                                 gc_base);
        struct gss_cl_ctx       *ctx = gss_cred_get_ctx(cred);
-       u32             *cred_len;
+       __be32          *cred_len;
        struct rpc_rqst *req = task->tk_rqstp;
        u32             maj_stat = 0;
        struct xdr_netobj mic;
@@ -894,12 +894,12 @@ gss_refresh(struct rpc_task *task)
        return 0;
 }
 
-static u32 *
-gss_validate(struct rpc_task *task, u32 *p)
+static __be32 *
+gss_validate(struct rpc_task *task, __be32 *p)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
        struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-       u32             seq;
+       __be32          seq;
        struct kvec     iov;
        struct xdr_buf  verf_buf;
        struct xdr_netobj mic;
@@ -940,13 +940,14 @@ out_bad:
 
 static inline int
 gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-               kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+               kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj)
 {
        struct xdr_buf  *snd_buf = &rqstp->rq_snd_buf;
        struct xdr_buf  integ_buf;
-       u32             *integ_len = NULL;
+       __be32          *integ_len = NULL;
        struct xdr_netobj mic;
-       u32             offset, *q;
+       u32             offset;
+       __be32          *q;
        struct kvec     *iov;
        u32             maj_stat = 0;
        int             status = -EIO;
@@ -1032,13 +1033,13 @@ out:
 
 static inline int
 gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-               kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+               kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj)
 {
        struct xdr_buf  *snd_buf = &rqstp->rq_snd_buf;
        u32             offset;
        u32             maj_stat;
        int             status;
-       u32             *opaque_len;
+       __be32          *opaque_len;
        struct page     **inpages;
        int             first;
        int             pad;
@@ -1095,7 +1096,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 
 static int
 gss_wrap_req(struct rpc_task *task,
-            kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
+            kxdrproc_t encode, void *rqstp, __be32 *p, void *obj)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
@@ -1132,7 +1133,7 @@ out:
 
 static inline int
 gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-               struct rpc_rqst *rqstp, u32 **p)
+               struct rpc_rqst *rqstp, __be32 **p)
 {
        struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
        struct xdr_buf integ_buf;
@@ -1169,7 +1170,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 
 static inline int
 gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
-               struct rpc_rqst *rqstp, u32 **p)
+               struct rpc_rqst *rqstp, __be32 **p)
 {
        struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
        u32 offset;
@@ -1198,13 +1199,13 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
 
 static int
 gss_unwrap_resp(struct rpc_task *task,
-               kxdrproc_t decode, void *rqstp, u32 *p, void *obj)
+               kxdrproc_t decode, void *rqstp, __be32 *p, void *obj)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
                        gc_base);
        struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-       u32             *savedp = p;
+       __be32          *savedp = p;
        struct kvec     *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
        int             savedlen = head->iov_len;
        int             status = -EIO;
index 2f312164d6d5611559aabab099e37ef8e55f7459..08601ee4cd7311d45c4a1146386ce22a0d96be76 100644 (file)
@@ -115,7 +115,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
        krb5_hdr = ptr - 2;
        msg_start = krb5_hdr + 24;
 
-       *(u16 *)(krb5_hdr + 2) = htons(ctx->signalg);
+       *(__be16 *)(krb5_hdr + 2) = htons(ctx->signalg);
        memset(krb5_hdr + 4, 0xff, 4);
 
        if (make_checksum(checksum_type, krb5_hdr, 8, text, 0, &md5cksum))
index f179415d0c38e2bf4efe0e0cf345b51d009522d7..cc45c1605f80eb7bbc6f2382bb2c3952f0446ec9 100644 (file)
@@ -177,9 +177,9 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
        msg_start = krb5_hdr + 24;
        /* XXXJBF: */ BUG_ON(buf->head[0].iov_base + offset + headlen != msg_start + blocksize);
 
-       *(u16 *)(krb5_hdr + 2) = htons(kctx->signalg);
+       *(__be16 *)(krb5_hdr + 2) = htons(kctx->signalg);
        memset(krb5_hdr + 4, 0xff, 4);
-       *(u16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
+       *(__be16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
 
        make_confounder(msg_start, blocksize);
 
index 94217ec9e2dd5427a1b12cc559a46e114172e192..638c0b576203bab4fac5c0037cf1881e2c1c32e3 100644 (file)
@@ -607,7 +607,7 @@ svc_safe_getnetobj(struct kvec *argv, struct xdr_netobj *o)
 
        if (argv->iov_len < 4)
                return -1;
-       o->len = ntohl(svc_getu32(argv));
+       o->len = svc_getnl(argv);
        l = round_up_to_quad(o->len);
        if (argv->iov_len < l)
                return -1;
@@ -620,17 +620,17 @@ svc_safe_getnetobj(struct kvec *argv, struct xdr_netobj *o)
 static inline int
 svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
 {
-       u32 *p;
+       u8 *p;
 
        if (resv->iov_len + 4 > PAGE_SIZE)
                return -1;
-       svc_putu32(resv, htonl(o->len));
+       svc_putnl(resv, o->len);
        p = resv->iov_base + resv->iov_len;
        resv->iov_len += round_up_to_quad(o->len);
        if (resv->iov_len > PAGE_SIZE)
                return -1;
        memcpy(p, o->data, o->len);
-       memset((u8 *)p + o->len, 0, round_up_to_quad(o->len) - o->len);
+       memset(p + o->len, 0, round_up_to_quad(o->len) - o->len);
        return 0;
 }
 
@@ -640,7 +640,7 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
  */
 static int
 gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
-                 u32 *rpcstart, struct rpc_gss_wire_cred *gc, u32 *authp)
+                 __be32 *rpcstart, struct rpc_gss_wire_cred *gc, __be32 *authp)
 {
        struct gss_ctx          *ctx_id = rsci->mechctx;
        struct xdr_buf          rpchdr;
@@ -657,7 +657,7 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
        *authp = rpc_autherr_badverf;
        if (argv->iov_len < 4)
                return SVC_DENIED;
-       flavor = ntohl(svc_getu32(argv));
+       flavor = svc_getnl(argv);
        if (flavor != RPC_AUTH_GSS)
                return SVC_DENIED;
        if (svc_safe_getnetobj(argv, &checksum))
@@ -687,9 +687,9 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
 static int
 gss_write_null_verf(struct svc_rqst *rqstp)
 {
-       u32     *p;
+       __be32     *p;
 
-       svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL));
+       svc_putnl(rqstp->rq_res.head, RPC_AUTH_NULL);
        p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
        /* don't really need to check if head->iov_len > PAGE_SIZE ... */
        *p++ = 0;
@@ -701,14 +701,14 @@ gss_write_null_verf(struct svc_rqst *rqstp)
 static int
 gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 {
-       u32                     xdr_seq;
+       __be32                  xdr_seq;
        u32                     maj_stat;
        struct xdr_buf          verf_data;
        struct xdr_netobj       mic;
-       u32                     *p;
+       __be32                  *p;
        struct kvec             iov;
 
-       svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_GSS));
+       svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
        xdr_seq = htonl(seq);
 
        iov.iov_base = &xdr_seq;
@@ -782,7 +782,7 @@ EXPORT_SYMBOL(svcauth_gss_register_pseudoflavor);
 static inline int
 read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
 {
-       u32     raw;
+       __be32  raw;
        int     status;
 
        status = read_bytes_from_xdr_buf(buf, base, &raw, sizeof(*obj));
@@ -805,7 +805,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
        struct xdr_netobj mic;
        struct xdr_buf integ_buf;
 
-       integ_len = ntohl(svc_getu32(&buf->head[0]));
+       integ_len = svc_getnl(&buf->head[0]);
        if (integ_len & 3)
                goto out;
        if (integ_len > buf->len)
@@ -825,7 +825,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
        maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                goto out;
-       if (ntohl(svc_getu32(&buf->head[0])) != seq)
+       if (svc_getnl(&buf->head[0]) != seq)
                goto out;
        stat = 0;
 out:
@@ -857,7 +857,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
 
        rqstp->rq_sendfile_ok = 0;
 
-       priv_len = ntohl(svc_getu32(&buf->head[0]));
+       priv_len = svc_getnl(&buf->head[0]);
        if (rqstp->rq_deferred) {
                /* Already decrypted last time through! The sequence number
                 * check at out_seq is unnecessary but harmless: */
@@ -895,7 +895,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
        if (maj_stat != GSS_S_COMPLETE)
                return -EINVAL;
 out_seq:
-       if (ntohl(svc_getu32(&buf->head[0])) != seq)
+       if (svc_getnl(&buf->head[0]) != seq)
                return -EINVAL;
        return 0;
 }
@@ -905,7 +905,7 @@ struct gss_svc_data {
        struct rpc_gss_wire_cred        clcred;
        /* pointer to the beginning of the procedure-specific results,
         * which may be encrypted/checksummed in svcauth_gss_release: */
-       u32                             *body_start;
+       __be32                          *body_start;
        struct rsc                      *rsci;
 };
 
@@ -946,7 +946,7 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
  * response here and return SVC_COMPLETE.
  */
 static int
-svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
        struct kvec     *argv = &rqstp->rq_arg.head[0];
        struct kvec     *resv = &rqstp->rq_res.head[0];
@@ -956,8 +956,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
        struct rpc_gss_wire_cred *gc;
        struct rsc      *rsci = NULL;
        struct rsi      *rsip, rsikey;
-       u32             *rpcstart;
-       u32             *reject_stat = resv->iov_base + resv->iov_len;
+       __be32          *rpcstart;
+       __be32          *reject_stat = resv->iov_base + resv->iov_len;
        int             ret;
 
        dprintk("RPC:      svcauth_gss: argv->iov_len = %zd\n",argv->iov_len);
@@ -985,12 +985,12 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
 
        if (argv->iov_len < 5 * 4)
                goto auth_err;
-       crlen = ntohl(svc_getu32(argv));
-       if (ntohl(svc_getu32(argv)) != RPC_GSS_VERSION)
+       crlen = svc_getnl(argv);
+       if (svc_getnl(argv) != RPC_GSS_VERSION)
                goto auth_err;
-       gc->gc_proc = ntohl(svc_getu32(argv));
-       gc->gc_seq = ntohl(svc_getu32(argv));
-       gc->gc_svc = ntohl(svc_getu32(argv));
+       gc->gc_proc = svc_getnl(argv);
+       gc->gc_seq = svc_getnl(argv);
+       gc->gc_svc = svc_getnl(argv);
        if (svc_safe_getnetobj(argv, &gc->gc_ctx))
                goto auth_err;
        if (crlen != round_up_to_quad(gc->gc_ctx.len) + 5 * 4)
@@ -1016,9 +1016,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
        case RPC_GSS_PROC_CONTINUE_INIT:
                if (argv->iov_len < 2 * 4)
                        goto auth_err;
-               if (ntohl(svc_getu32(argv)) != RPC_AUTH_NULL)
+               if (svc_getnl(argv) != RPC_AUTH_NULL)
                        goto auth_err;
-               if (ntohl(svc_getu32(argv)) != 0)
+               if (svc_getnl(argv) != 0)
                        goto auth_err;
                break;
        case RPC_GSS_PROC_DATA:
@@ -1076,14 +1076,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                                goto drop;
                        if (resv->iov_len + 4 > PAGE_SIZE)
                                goto drop;
-                       svc_putu32(resv, rpc_success);
+                       svc_putnl(resv, RPC_SUCCESS);
                        if (svc_safe_putnetobj(resv, &rsip->out_handle))
                                goto drop;
                        if (resv->iov_len + 3 * 4 > PAGE_SIZE)
                                goto drop;
-                       svc_putu32(resv, htonl(rsip->major_status));
-                       svc_putu32(resv, htonl(rsip->minor_status));
-                       svc_putu32(resv, htonl(GSS_SEQ_WIN));
+                       svc_putnl(resv, rsip->major_status);
+                       svc_putnl(resv, rsip->minor_status);
+                       svc_putnl(resv, GSS_SEQ_WIN);
                        if (svc_safe_putnetobj(resv, &rsip->out_token))
                                goto drop;
                        rqstp->rq_client = NULL;
@@ -1093,7 +1093,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                set_bit(CACHE_NEGATIVE, &rsci->h.flags);
                if (resv->iov_len + 4 > PAGE_SIZE)
                        goto drop;
-               svc_putu32(resv, rpc_success);
+               svc_putnl(resv, RPC_SUCCESS);
                goto complete;
        case RPC_GSS_PROC_DATA:
                *authp = rpcsec_gsserr_ctxproblem;
@@ -1111,8 +1111,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                                goto auth_err;
                        /* placeholders for length and seq. number: */
                        svcdata->body_start = resv->iov_base + resv->iov_len;
-                       svc_putu32(resv, 0);
-                       svc_putu32(resv, 0);
+                       svc_putnl(resv, 0);
+                       svc_putnl(resv, 0);
                        break;
                case RPC_GSS_SVC_PRIVACY:
                        if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
@@ -1120,8 +1120,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                                goto auth_err;
                        /* placeholders for length and seq. number: */
                        svcdata->body_start = resv->iov_base + resv->iov_len;
-                       svc_putu32(resv, 0);
-                       svc_putu32(resv, 0);
+                       svc_putnl(resv, 0);
+                       svc_putnl(resv, 0);
                        break;
                default:
                        goto auth_err;
@@ -1156,7 +1156,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
        struct xdr_buf integ_buf;
        struct xdr_netobj mic;
        struct kvec *resv;
-       u32 *p;
+       __be32 *p;
        int integ_offset, integ_len;
        int stat = -EINVAL;
 
@@ -1199,7 +1199,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
        mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
        if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
                goto out_err;
-       svc_putu32(resv, htonl(mic.len));
+       svc_putnl(resv, mic.len);
        memset(mic.data + mic.len, 0,
                        round_up_to_quad(mic.len) - mic.len);
        resv->iov_len += XDR_QUADLEN(mic.len) << 2;
@@ -1219,8 +1219,8 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
        struct rpc_gss_wire_cred *gc = &gsd->clcred;
        struct xdr_buf *resbuf = &rqstp->rq_res;
        struct page **inpages = NULL;
-       u32 *p;
-       int offset, *len;
+       __be32 *p, *len;
+       int offset;
        int pad;
 
        p = gsd->body_start;
@@ -1264,7 +1264,7 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
                return -ENOMEM;
        *len = htonl(resbuf->len - offset);
        pad = 3 - ((resbuf->len - offset - 1)&3);
-       p = (u32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
+       p = (__be32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
        memset(p, 0, pad);
        resbuf->tail[0].iov_len += pad;
        resbuf->len += pad;
index 2eccffa96ba1a016208c73de79cebc77a482f94e..3be257dc32b2af4e26a5f1028ac8dc30586b7e28 100644 (file)
@@ -60,8 +60,8 @@ nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
 /*
  * Marshal credential.
  */
-static u32 *
-nul_marshal(struct rpc_task *task, u32 *p)
+static __be32 *
+nul_marshal(struct rpc_task *task, __be32 *p)
 {
        *p++ = htonl(RPC_AUTH_NULL);
        *p++ = 0;
@@ -81,8 +81,8 @@ nul_refresh(struct rpc_task *task)
        return 0;
 }
 
-static u32 *
-nul_validate(struct rpc_task *task, u32 *p)
+static __be32 *
+nul_validate(struct rpc_task *task, __be32 *p)
 {
        rpc_authflavor_t        flavor;
        u32                     size;
index 74c7406a10549d4a747e376f5b30ae41b0764290..f7f990c9afe2ef805b2ea75e1d9b23dbb7f2d2fc 100644 (file)
@@ -137,12 +137,12 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
  * Marshal credentials.
  * Maybe we should keep a cached credential for performance reasons.
  */
-static u32 *
-unx_marshal(struct rpc_task *task, u32 *p)
+static __be32 *
+unx_marshal(struct rpc_task *task, __be32 *p)
 {
        struct rpc_clnt *clnt = task->tk_client;
        struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
-       u32             *base, *hold;
+       __be32          *base, *hold;
        int             i;
 
        *p++ = htonl(RPC_AUTH_UNIX);
@@ -178,8 +178,8 @@ unx_refresh(struct rpc_task *task)
        return 0;
 }
 
-static u32 *
-unx_validate(struct rpc_task *task, u32 *p)
+static __be32 *
+unx_validate(struct rpc_task *task, __be32 *p)
 {
        rpc_authflavor_t        flavor;
        u32                     size;
index 084a0ad5c64ea0752893f7ddefb95be18384a467..124ff0ceb55b2ee20ce47d6f3358a966de37ddb5 100644 (file)
@@ -60,8 +60,8 @@ static void   call_refreshresult(struct rpc_task *task);
 static void    call_timeout(struct rpc_task *task);
 static void    call_connect(struct rpc_task *task);
 static void    call_connect_status(struct rpc_task *task);
-static u32 *   call_header(struct rpc_task *task);
-static u32 *   call_verify(struct rpc_task *task);
+static __be32 *        call_header(struct rpc_task *task);
+static __be32 *        call_verify(struct rpc_task *task);
 
 
 static int
@@ -782,7 +782,7 @@ call_encode(struct rpc_task *task)
        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
        unsigned int    bufsiz;
        kxdrproc_t      encode;
-       u32             *p;
+       __be32          *p;
 
        dprintk("RPC: %4d call_encode (status %d)\n", 
                                task->tk_pid, task->tk_status);
@@ -1100,7 +1100,7 @@ call_decode(struct rpc_task *task)
        struct rpc_clnt *clnt = task->tk_client;
        struct rpc_rqst *req = task->tk_rqstp;
        kxdrproc_t      decode = task->tk_msg.rpc_proc->p_decode;
-       u32             *p;
+       __be32          *p;
 
        dprintk("RPC: %4d call_decode (status %d)\n", 
                                task->tk_pid, task->tk_status);
@@ -1197,12 +1197,12 @@ call_refreshresult(struct rpc_task *task)
 /*
  * Call header serialization
  */
-static u32 *
+static __be32 *
 call_header(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
        struct rpc_rqst *req = task->tk_rqstp;
-       u32             *p = req->rq_svec[0].iov_base;
+       __be32          *p = req->rq_svec[0].iov_base;
 
        /* FIXME: check buffer size? */
 
@@ -1221,12 +1221,13 @@ call_header(struct rpc_task *task)
 /*
  * Reply header verification
  */
-static u32 *
+static __be32 *
 call_verify(struct rpc_task *task)
 {
        struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
        int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
-       u32     *p = iov->iov_base, n;
+       __be32  *p = iov->iov_base;
+       u32 n;
        int error = -EACCES;
 
        if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) {
@@ -1303,7 +1304,7 @@ call_verify(struct rpc_task *task)
                printk(KERN_WARNING "call_verify: auth check failed\n");
                goto out_garbage;               /* bad verifier, retry */
        }
-       len = p - (u32 *)iov->iov_base - 1;
+       len = p - (__be32 *)iov->iov_base - 1;
        if (len < 0)
                goto out_overflow;
        switch ((n = ntohl(*p++))) {
@@ -1358,12 +1359,12 @@ out_overflow:
        goto out_garbage;
 }
 
-static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj)
+static int rpcproc_encode_null(void *rqstp, __be32 *data, void *obj)
 {
        return 0;
 }
 
-static int rpcproc_decode_null(void *rqstp, u32 *data, void *obj)
+static int rpcproc_decode_null(void *rqstp, __be32 *data, void *obj)
 {
        return 0;
 }
index c04609d3476a986e630097998a6eeecb76551870..919d5ba7ca0a206cb40aff51e67ac90bbc4f67b3 100644 (file)
@@ -300,7 +300,7 @@ static struct rpc_clnt *pmap_create(char *hostname, struct sockaddr_in *srvaddr,
 /*
  * XDR encode/decode functions for PMAP
  */
-static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct portmap_args *map)
+static int xdr_encode_mapping(struct rpc_rqst *req, __be32 *p, struct portmap_args *map)
 {
        dprintk("RPC: xdr_encode_mapping(%u, %u, %u, %u)\n",
                map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
@@ -313,13 +313,13 @@ static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct portmap_args
        return 0;
 }
 
-static int xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
+static int xdr_decode_port(struct rpc_rqst *req, __be32 *p, unsigned short *portp)
 {
        *portp = (unsigned short) ntohl(*p++);
        return 0;
 }
 
-static int xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
+static int xdr_decode_bool(struct rpc_rqst *req, __be32 *p, unsigned int *boolp)
 {
        *boolp = (unsigned int) ntohl(*p++);
        return 0;
index dfa504fe383f0b56d69aecc8ce5031609e16d91f..9a0b41a97f90764f84636811137a76cdfff5ac3b 100644 (file)
@@ -488,14 +488,13 @@ rpc_get_inode(struct super_block *sb, int mode)
                return NULL;
        inode->i_mode = mode;
        inode->i_uid = inode->i_gid = 0;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        switch(mode & S_IFMT) {
                case S_IFDIR:
                        inode->i_fop = &simple_dir_operations;
                        inode->i_op = &simple_dir_inode_operations;
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                default:
                        break;
        }
@@ -572,7 +571,7 @@ rpc_populate(struct dentry *parent,
                if (private)
                        rpc_inode_setowner(inode, private);
                if (S_ISDIR(mode))
-                       dir->i_nlink++;
+                       inc_nlink(dir);
                d_add(dentry, inode);
        }
        mutex_unlock(&dir->i_mutex);
@@ -594,7 +593,7 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
                goto out_err;
        inode->i_ino = iunique(dir->i_sb, 100);
        d_instantiate(dentry, inode);
-       dir->i_nlink++;
+       inc_nlink(dir);
        inode_dir_notify(dir, DN_CREATE);
        return 0;
 out_err:
@@ -858,7 +857,6 @@ int register_rpc_pipefs(void)
 
 void unregister_rpc_pipefs(void)
 {
-       if (kmem_cache_destroy(rpc_inode_cachep))
-               printk(KERN_WARNING "RPC: unable to free inode cache\n");
+       kmem_cache_destroy(rpc_inode_cachep);
        unregister_filesystem(&rpc_pipe_fs_type);
 }
index 6390461a97563852ce72558a77d3090c0e4750e0..a1ab4eed41f4b5a495f18573aef04b3457403ba3 100644 (file)
@@ -1059,10 +1059,10 @@ rpc_destroy_mempool(void)
                mempool_destroy(rpc_buffer_mempool);
        if (rpc_task_mempool)
                mempool_destroy(rpc_task_mempool);
-       if (rpc_task_slabp && kmem_cache_destroy(rpc_task_slabp))
-               printk(KERN_INFO "rpc_task: not all structures were freed\n");
-       if (rpc_buffer_slabp && kmem_cache_destroy(rpc_buffer_slabp))
-               printk(KERN_INFO "rpc_buffers: not all structures were freed\n");
+       if (rpc_task_slabp)
+               kmem_cache_destroy(rpc_task_slabp);
+       if (rpc_buffer_slabp)
+               kmem_cache_destroy(rpc_buffer_slabp);
 }
 
 int
index b76a227dd3ad9aac842f988874bc66cbb27e4a7b..44b8d9d4c18a7d09e5929688e45eab41cdc60ef8 100644 (file)
@@ -256,11 +256,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        struct kvec *           argv = &rqstp->rq_arg.head[0];
        struct kvec *           resv = &rqstp->rq_res.head[0];
        kxdrproc_t              xdr;
-       u32                     *statp;
-       u32                     dir, prog, vers, proc,
-                               auth_stat, rpc_stat;
+       __be32                  *statp;
+       u32                     dir, prog, vers, proc;
+       __be32                  auth_stat, rpc_stat;
        int                     auth_res;
-       u32                     *accept_statp;
+       __be32                  *accept_statp;
 
        rpc_stat = rpc_success;
 
@@ -284,16 +284,16 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        rqstp->rq_sendfile_ok = 1;
        /* tcp needs a space for the record length... */
        if (rqstp->rq_prot == IPPROTO_TCP)
-               svc_putu32(resv, 0);
+               svc_putnl(resv, 0);
 
        rqstp->rq_xid = svc_getu32(argv);
        svc_putu32(resv, rqstp->rq_xid);
 
-       dir  = ntohl(svc_getu32(argv));
-       vers = ntohl(svc_getu32(argv));
+       dir  = svc_getnl(argv);
+       vers = svc_getnl(argv);
 
        /* First words of reply: */
-       svc_putu32(resv, xdr_one);              /* REPLY */
+       svc_putnl(resv, 1);             /* REPLY */
 
        if (dir != 0)           /* direction != CALL */
                goto err_bad_dir;
@@ -303,11 +303,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
        /* Save position in case we later decide to reject: */
        accept_statp = resv->iov_base + resv->iov_len;
 
-       svc_putu32(resv, xdr_zero);             /* ACCEPT */
+       svc_putnl(resv, 0);             /* ACCEPT */
 
-       rqstp->rq_prog = prog = ntohl(svc_getu32(argv));        /* program number */
-       rqstp->rq_vers = vers = ntohl(svc_getu32(argv));        /* version number */
-       rqstp->rq_proc = proc = ntohl(svc_getu32(argv));        /* procedure number */
+       rqstp->rq_prog = prog = svc_getnl(argv);        /* program number */
+       rqstp->rq_vers = vers = svc_getnl(argv);        /* version number */
+       rqstp->rq_proc = proc = svc_getnl(argv);        /* procedure number */
 
        progp = serv->sv_program;
 
@@ -361,7 +361,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
 
        /* Build the reply header. */
        statp = resv->iov_base +resv->iov_len;
-       svc_putu32(resv, rpc_success);          /* RPC_SUCCESS */
+       svc_putnl(resv, RPC_SUCCESS);
 
        /* Bump per-procedure stats counter */
        procp->pc_count++;
@@ -439,10 +439,10 @@ err_bad_dir:
 
 err_bad_rpc:
        serv->sv_stats->rpcbadfmt++;
-       svc_putu32(resv, xdr_one);      /* REJECT */
-       svc_putu32(resv, xdr_zero);     /* RPC_MISMATCH */
-       svc_putu32(resv, xdr_two);      /* Only RPCv2 supported */
-       svc_putu32(resv, xdr_two);
+       svc_putnl(resv, 1);     /* REJECT */
+       svc_putnl(resv, 0);     /* RPC_MISMATCH */
+       svc_putnl(resv, 2);     /* Only RPCv2 supported */
+       svc_putnl(resv, 2);
        goto sendit;
 
 err_bad_auth:
@@ -450,15 +450,15 @@ err_bad_auth:
        serv->sv_stats->rpcbadauth++;
        /* Restore write pointer to location of accept status: */
        xdr_ressize_check(rqstp, accept_statp);
-       svc_putu32(resv, xdr_one);      /* REJECT */
-       svc_putu32(resv, xdr_one);      /* AUTH_ERROR */
-       svc_putu32(resv, auth_stat);    /* status */
+       svc_putnl(resv, 1);     /* REJECT */
+       svc_putnl(resv, 1);     /* AUTH_ERROR */
+       svc_putnl(resv, ntohl(auth_stat));      /* status */
        goto sendit;
 
 err_bad_prog:
        dprintk("svc: unknown program %d\n", prog);
        serv->sv_stats->rpcbadfmt++;
-       svc_putu32(resv, rpc_prog_unavail);
+       svc_putnl(resv, RPC_PROG_UNAVAIL);
        goto sendit;
 
 err_bad_vers:
@@ -466,9 +466,9 @@ err_bad_vers:
        printk("svc: unknown version (%d)\n", vers);
 #endif
        serv->sv_stats->rpcbadfmt++;
-       svc_putu32(resv, rpc_prog_mismatch);
-       svc_putu32(resv, htonl(progp->pg_lovers));
-       svc_putu32(resv, htonl(progp->pg_hivers));
+       svc_putnl(resv, RPC_PROG_MISMATCH);
+       svc_putnl(resv, progp->pg_lovers);
+       svc_putnl(resv, progp->pg_hivers);
        goto sendit;
 
 err_bad_proc:
@@ -476,7 +476,7 @@ err_bad_proc:
        printk("svc: unknown procedure (%d)\n", proc);
 #endif
        serv->sv_stats->rpcbadfmt++;
-       svc_putu32(resv, rpc_proc_unavail);
+       svc_putnl(resv, RPC_PROC_UNAVAIL);
        goto sendit;
 
 err_garbage:
@@ -486,6 +486,6 @@ err_garbage:
        rpc_stat = rpc_garbage_args;
 err_bad:
        serv->sv_stats->rpcbadfmt++;
-       svc_putu32(resv, rpc_stat);
+       svc_putnl(resv, ntohl(rpc_stat));
        goto sendit;
 }
index 5b28c6176806321af56ff3edfe464c7fea297e7d..8f2320aded5c42f645b406cf51539d10228ef055 100644 (file)
@@ -35,14 +35,14 @@ static struct auth_ops      *authtab[RPC_AUTH_MAXFLAVOR] = {
 };
 
 int
-svc_authenticate(struct svc_rqst *rqstp, u32 *authp)
+svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
 {
        rpc_authflavor_t        flavor;
        struct auth_ops         *aops;
 
        *authp = rpc_auth_ok;
 
-       flavor = ntohl(svc_getu32(&rqstp->rq_arg.head[0]));
+       flavor = svc_getnl(&rqstp->rq_arg.head[0]);
 
        dprintk("svc: svc_authenticate (%d)\n", flavor);
 
index 7e5707e2d6b678fcd00cdb439cceb3b71fee0220..1020d54b01d074a7fd8c1d25976a7d9fe800935c 100644 (file)
@@ -145,7 +145,7 @@ static void ip_map_request(struct cache_detail *cd,
 {
        char text_addr[20];
        struct ip_map *im = container_of(h, struct ip_map, h);
-       __u32 addr = im->m_addr.s_addr;
+       __be32 addr = im->m_addr.s_addr;
        
        snprintf(text_addr, 20, "%u.%u.%u.%u",
                 ntohl(addr) >> 24 & 0xff,
@@ -249,10 +249,10 @@ static int ip_map_show(struct seq_file *m,
 
        seq_printf(m, "%s %d.%d.%d.%d %s\n",
                   im->m_class,
-                  htonl(addr.s_addr) >> 24 & 0xff,
-                  htonl(addr.s_addr) >> 16 & 0xff,
-                  htonl(addr.s_addr) >>  8 & 0xff,
-                  htonl(addr.s_addr) >>  0 & 0xff,
+                  ntohl(addr.s_addr) >> 24 & 0xff,
+                  ntohl(addr.s_addr) >> 16 & 0xff,
+                  ntohl(addr.s_addr) >>  8 & 0xff,
+                  ntohl(addr.s_addr) >>  0 & 0xff,
                   dom
                   );
        return 0;
@@ -410,7 +410,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
 }
 
 static int
-svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
        struct kvec     *argv = &rqstp->rq_arg.head[0];
        struct kvec     *resv = &rqstp->rq_res.head[0];
@@ -427,7 +427,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
                *authp = rpc_autherr_badcred;
                return SVC_DENIED;
        }
-       if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+       if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
                dprintk("svc: bad null verf\n");
                *authp = rpc_autherr_badverf;
                return SVC_DENIED;
@@ -441,8 +441,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
                return SVC_DROP; /* kmalloc failure - client must retry */
 
        /* Put NULL verifier */
-       svc_putu32(resv, RPC_AUTH_NULL);
-       svc_putu32(resv, 0);
+       svc_putnl(resv, RPC_AUTH_NULL);
+       svc_putnl(resv, 0);
 
        return SVC_OK;
 }
@@ -472,7 +472,7 @@ struct auth_ops svcauth_null = {
 
 
 static int
-svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
        struct kvec     *argv = &rqstp->rq_arg.head[0];
        struct kvec     *resv = &rqstp->rq_res.head[0];
@@ -488,31 +488,31 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
 
        svc_getu32(argv);                       /* length */
        svc_getu32(argv);                       /* time stamp */
-       slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));    /* machname length */
+       slen = XDR_QUADLEN(svc_getnl(argv));    /* machname length */
        if (slen > 64 || (len -= (slen + 3)*4) < 0)
                goto badcred;
-       argv->iov_base = (void*)((u32*)argv->iov_base + slen);  /* skip machname */
+       argv->iov_base = (void*)((__be32*)argv->iov_base + slen);       /* skip machname */
        argv->iov_len -= slen*4;
 
-       cred->cr_uid = ntohl(svc_getu32(argv));         /* uid */
-       cred->cr_gid = ntohl(svc_getu32(argv));         /* gid */
-       slen = ntohl(svc_getu32(argv));                 /* gids length */
+       cred->cr_uid = svc_getnl(argv);         /* uid */
+       cred->cr_gid = svc_getnl(argv);         /* gid */
+       slen = svc_getnl(argv);                 /* gids length */
        if (slen > 16 || (len -= (slen + 2)*4) < 0)
                goto badcred;
        cred->cr_group_info = groups_alloc(slen);
        if (cred->cr_group_info == NULL)
                return SVC_DROP;
        for (i = 0; i < slen; i++)
-               GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
+               GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
 
-       if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+       if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
                *authp = rpc_autherr_badverf;
                return SVC_DENIED;
        }
 
        /* Put NULL verifier */
-       svc_putu32(resv, RPC_AUTH_NULL);
-       svc_putu32(resv, 0);
+       svc_putnl(resv, RPC_AUTH_NULL);
+       svc_putnl(resv, 0);
 
        return SVC_OK;
 
index 953aff89bcac1cf3399e28cd7b9e6f401070123d..5b0fe1b66a23d5fbed578179268bedc15eae52c2 100644 (file)
@@ -1030,7 +1030,7 @@ svc_tcp_sendto(struct svc_rqst *rqstp)
 {
        struct xdr_buf  *xbufp = &rqstp->rq_res;
        int sent;
-       u32 reclen;
+       __be32 reclen;
 
        /* Set up the first element of the reply kvec.
         * Any other kvecs that may be in use have been taken
@@ -1393,14 +1393,12 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
        if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
                return error;
 
-       if (sin != NULL) {
-               if (type == SOCK_STREAM)
-                       sock->sk->sk_reuse = 1; /* allow address reuse */
-               error = kernel_bind(sock, (struct sockaddr *) sin,
-                                               sizeof(*sin));
-               if (error < 0)
-                       goto bummer;
-       }
+       if (type == SOCK_STREAM)
+               sock->sk->sk_reuse = 1; /* allow address reuse */
+       error = kernel_bind(sock, (struct sockaddr *) sin,
+                                       sizeof(*sin));
+       if (error < 0)
+               goto bummer;
 
        if (protocol == IPPROTO_TCP) {
                if ((error = kernel_listen(sock, 64)) < 0)
index 6ac45103a272343a885a234cdda576dc6b655088..9022eb8b37ed9d05ea2e1bd983747b49b4c0ff7b 100644 (file)
@@ -18,8 +18,8 @@
 /*
  * XDR functions for basic NFS types
  */
-u32 *
-xdr_encode_netobj(u32 *p, const struct xdr_netobj *obj)
+__be32 *
+xdr_encode_netobj(__be32 *p, const struct xdr_netobj *obj)
 {
        unsigned int    quadlen = XDR_QUADLEN(obj->len);
 
@@ -29,8 +29,8 @@ xdr_encode_netobj(u32 *p, const struct xdr_netobj *obj)
        return p + XDR_QUADLEN(obj->len);
 }
 
-u32 *
-xdr_decode_netobj(u32 *p, struct xdr_netobj *obj)
+__be32 *
+xdr_decode_netobj(__be32 *p, struct xdr_netobj *obj)
 {
        unsigned int    len;
 
@@ -55,7 +55,7 @@ xdr_decode_netobj(u32 *p, struct xdr_netobj *obj)
  * Returns the updated current XDR buffer position
  *
  */
-u32 *xdr_encode_opaque_fixed(u32 *p, const void *ptr, unsigned int nbytes)
+__be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int nbytes)
 {
        if (likely(nbytes != 0)) {
                unsigned int quadlen = XDR_QUADLEN(nbytes);
@@ -79,21 +79,21 @@ EXPORT_SYMBOL(xdr_encode_opaque_fixed);
  *
  * Returns the updated current XDR buffer position
  */
-u32 *xdr_encode_opaque(u32 *p, const void *ptr, unsigned int nbytes)
+__be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int nbytes)
 {
        *p++ = htonl(nbytes);
        return xdr_encode_opaque_fixed(p, ptr, nbytes);
 }
 EXPORT_SYMBOL(xdr_encode_opaque);
 
-u32 *
-xdr_encode_string(u32 *p, const char *string)
+__be32 *
+xdr_encode_string(__be32 *p, const char *string)
 {
        return xdr_encode_array(p, string, strlen(string));
 }
 
-u32 *
-xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen)
+__be32 *
+xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen)
 {
        unsigned int    len;
 
@@ -432,7 +432,7 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len)
  *      of the buffer length, and takes care of adjusting the kvec
  *      length for us.
  */
-void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
+void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 {
        struct kvec *iov = buf->head;
        int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len;
@@ -440,8 +440,8 @@ void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
        BUG_ON(scratch_len < 0);
        xdr->buf = buf;
        xdr->iov = iov;
-       xdr->p = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
-       xdr->end = (uint32_t *)((char *)iov->iov_base + scratch_len);
+       xdr->p = (__be32 *)((char *)iov->iov_base + iov->iov_len);
+       xdr->end = (__be32 *)((char *)iov->iov_base + scratch_len);
        BUG_ON(iov->iov_len > scratch_len);
 
        if (p != xdr->p && p != NULL) {
@@ -465,10 +465,10 @@ EXPORT_SYMBOL(xdr_init_encode);
  * bytes of data. If so, update the total xdr_buf length, and
  * adjust the length of the current kvec.
  */
-uint32_t * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
+__be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes)
 {
-       uint32_t *p = xdr->p;
-       uint32_t *q;
+       __be32 *p = xdr->p;
+       __be32 *q;
 
        /* align nbytes on the next 32-bit boundary */
        nbytes += 3;
@@ -524,7 +524,7 @@ EXPORT_SYMBOL(xdr_write_pages);
  * @buf: pointer to XDR buffer from which to decode data
  * @p: current pointer inside XDR buffer
  */
-void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
+void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 {
        struct kvec *iov = buf->head;
        unsigned int len = iov->iov_len;
@@ -534,7 +534,7 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
        xdr->buf = buf;
        xdr->iov = iov;
        xdr->p = p;
-       xdr->end = (uint32_t *)((char *)iov->iov_base + len);
+       xdr->end = (__be32 *)((char *)iov->iov_base + len);
 }
 EXPORT_SYMBOL(xdr_init_decode);
 
@@ -548,10 +548,10 @@ EXPORT_SYMBOL(xdr_init_decode);
  * If so return the current pointer, then update the current
  * pointer position.
  */
-uint32_t * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
+__be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
 {
-       uint32_t *p = xdr->p;
-       uint32_t *q = p + XDR_QUADLEN(nbytes);
+       __be32 *p = xdr->p;
+       __be32 *q = p + XDR_QUADLEN(nbytes);
 
        if (unlikely(q > xdr->end || q < p))
                return NULL;
@@ -599,8 +599,8 @@ void xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
         * Position current pointer at beginning of tail, and
         * set remaining message length.
         */
-       xdr->p = (uint32_t *)((char *)iov->iov_base + padding);
-       xdr->end = (uint32_t *)((char *)iov->iov_base + end);
+       xdr->p = (__be32 *)((char *)iov->iov_base + padding);
+       xdr->end = (__be32 *)((char *)iov->iov_base + end);
 }
 EXPORT_SYMBOL(xdr_read_pages);
 
@@ -624,8 +624,8 @@ void xdr_enter_page(struct xdr_stream *xdr, unsigned int len)
         */
        if (len > PAGE_CACHE_SIZE - xdr->buf->page_base)
                len = PAGE_CACHE_SIZE - xdr->buf->page_base;
-       xdr->p = (uint32_t *)(kaddr + xdr->buf->page_base);
-       xdr->end = (uint32_t *)((char *)xdr->p + len);
+       xdr->p = (__be32 *)(kaddr + xdr->buf->page_base);
+       xdr->end = (__be32 *)((char *)xdr->p + len);
 }
 EXPORT_SYMBOL(xdr_enter_page);
 
@@ -743,7 +743,7 @@ out:
 int
 xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
 {
-       u32     raw;
+       __be32  raw;
        int     status;
 
        status = read_bytes_from_xdr_buf(buf, base, &raw, sizeof(*obj));
@@ -756,7 +756,7 @@ xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
 int
 xdr_encode_word(struct xdr_buf *buf, int base, u32 obj)
 {
-       u32     raw = htonl(obj);
+       __be32  raw = htonl(obj);
 
        return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj));
 }
index 1f786f68729d465c8bc7f3fb51b45465a4c89aa2..80857470dc112f15fe18bbd91510e6147243e5e3 100644 (file)
@@ -594,7 +594,7 @@ static void xprt_connect_status(struct rpc_task *task)
  * @xid: RPC XID of incoming reply
  *
  */
-struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
 {
        struct list_head *pos;
 
@@ -801,7 +801,7 @@ void xprt_reserve(struct rpc_task *task)
        spin_unlock(&xprt->reserve_lock);
 }
 
-static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
+static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
        return xprt->xid++;
 }
index 9b62923a9c0689fd75569fb494e66604f06ce4e7..28100e01922516045b9530f46df41fadb8738729 100644 (file)
@@ -548,7 +548,8 @@ static void xs_udp_data_ready(struct sock *sk, int len)
        struct rpc_rqst *rovr;
        struct sk_buff *skb;
        int err, repsize, copied;
-       u32 _xid, *xp;
+       u32 _xid;
+       __be32 *xp;
 
        read_lock(&sk->sk_callback_lock);
        dprintk("RPC:      xs_udp_data_ready...\n");
index d3abb0b7dc62190259c941fb28cdfc068d32c1df..6ac4e4f033aca67e1d7178efb4347c98a672aa1b 100644 (file)
@@ -58,10 +58,10 @@ static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr,
 }
 
 static inline unsigned int
-__xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family,
+__xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family,
                unsigned int hmask)
 {
-       unsigned int h = spi ^ proto;
+       unsigned int h = (__force u32)spi ^ proto;
        switch (family) {
        case AF_INET:
                h ^= __xfrm4_addr_hash(daddr);
index dfc90bb1cf1f53d054c2fc7f15e0b72ed3013f2a..e8198a2c785df7416143c0781bd042f8aba995d2 100644 (file)
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(secpath_dup);
 
 /* Fetch spi and seq from ipsec header */
 
-int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
        int offset, offset_seq;
 
@@ -62,7 +62,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
        case IPPROTO_COMP:
                if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr)))
                        return -EINVAL;
-               *spi = htonl(ntohs(*(u16*)(skb->h.raw + 2)));
+               *spi = htonl(ntohs(*(__be16*)(skb->h.raw + 2)));
                *seq = 0;
                return 0;
        default:
@@ -72,8 +72,8 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
        if (!pskb_may_pull(skb, 16))
                return -EINVAL;
 
-       *spi = *(u32*)(skb->h.raw + offset);
-       *seq = *(u32*)(skb->h.raw + offset_seq);
+       *spi = *(__be32*)(skb->h.raw + offset);
+       *seq = *(__be32*)(skb->h.raw + offset_seq);
        return 0;
 }
 EXPORT_SYMBOL(xfrm_parse_spi);
index 9f63edd39346538252f07a40b5925850e61f1511..f927b7330f025cca4c05ed0dd7157edd2723924e 100644 (file)
@@ -70,7 +70,7 @@ static inline unsigned int xfrm_src_hash(xfrm_address_t *addr,
 }
 
 static inline unsigned int
-xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
+xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
 {
        return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
 }
@@ -96,9 +96,12 @@ static void xfrm_hash_transfer(struct hlist_head *list,
                                    nhashmask);
                hlist_add_head(&x->bysrc, nsrctable+h);
 
-               h = __xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
-                                   x->props.family, nhashmask);
-               hlist_add_head(&x->byspi, nspitable+h);
+               if (x->id.spi) {
+                       h = __xfrm_spi_hash(&x->id.daddr, x->id.spi,
+                                           x->id.proto, x->props.family,
+                                           nhashmask);
+                       hlist_add_head(&x->byspi, nspitable+h);
+               }
        }
 }
 
@@ -421,7 +424,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
        return 0;
 }
 
-static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
+static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
 {
        unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
        struct xfrm_state *x;
@@ -622,7 +625,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
        h = xfrm_src_hash(&x->props.saddr, x->props.family);
        hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
 
-       if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) {
+       if (x->id.spi) {
                h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
                                  x->props.family);
 
@@ -916,7 +919,7 @@ err:
 EXPORT_SYMBOL(xfrm_state_check);
 
 struct xfrm_state *
-xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
+xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto,
                  unsigned short family)
 {
        struct xfrm_state *x;
@@ -1040,7 +1043,7 @@ u32 xfrm_get_acqseq(void)
 EXPORT_SYMBOL(xfrm_get_acqseq);
 
 void
-xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
+xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi)
 {
        unsigned int h;
        struct xfrm_state *x0;
@@ -1057,10 +1060,10 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
                x->id.spi = minspi;
        } else {
                u32 spi = 0;
-               minspi = ntohl(minspi);
-               maxspi = ntohl(maxspi);
-               for (h=0; h<maxspi-minspi+1; h++) {
-                       spi = minspi + net_random()%(maxspi-minspi+1);
+               u32 low = ntohl(minspi);
+               u32 high = ntohl(maxspi);
+               for (h=0; h<high-low+1; h++) {
+                       spi = low + net_random()%(high-low+1);
                        x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
                        if (x0 == NULL) {
                                x->id.spi = htonl(spi);
@@ -1180,11 +1183,10 @@ static void xfrm_replay_timer_handler(unsigned long data)
        spin_unlock(&x->lock);
 }
 
-int xfrm_replay_check(struct xfrm_state *x, u32 seq)
+int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
 {
        u32 diff;
-
-       seq = ntohl(seq);
+       u32 seq = ntohl(net_seq);
 
        if (unlikely(seq == 0))
                return -EINVAL;
@@ -1206,11 +1208,10 @@ int xfrm_replay_check(struct xfrm_state *x, u32 seq)
 }
 EXPORT_SYMBOL(xfrm_replay_check);
 
-void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
+void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
 {
        u32 diff;
-
-       seq = ntohl(seq);
+       u32 seq = ntohl(net_seq);
 
        if (seq > x->replay.seq) {
                diff = seq - x->replay.seq;
index ea41de8fb7f57c09d6ff2297a5ee985077fd695f..1c73c5aea66b06bcecff315356abcecc2a79522f 100644 (file)
@@ -13,7 +13,7 @@ hostprogs-$(CONFIG_VT)           += conmakehash
 hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash
 hostprogs-$(CONFIG_IKCONFIG)     += bin2c
 
-always         := $(hostprogs-y)
+always         := $(hostprogs-y) $(hostprogs-m)
 
 # The following hostprogs-y programs are only build on demand
 hostprogs-y += unifdef
index cb02baa63256ba691501ac65ddea70cadb1112c4..4ab6cbf092256bad17214ae86529de37c93efd95 100644 (file)
@@ -177,6 +177,7 @@ void find_export_symbols(char * filename)
                {
                        fprintf(stderr, "docproc: ");
                        perror(real_filename);
+                       exit(1);
                }
                while(fgets(line, MAXLINESZ, fp)) {
                        char *p;
index de76da80443f757a8ed90ce4f27dd53e2ff2a8db..f61c9ccef6aa562889a2a8c867730c7d05de0f91 100644 (file)
@@ -444,6 +444,14 @@ static int do_input_entry(const char *filename, struct input_device_id *id,
        return 1;
 }
 
+static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
+               char *alias)
+{
+       if (eisa->sig[0])
+               sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", eisa->sig);
+       return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -547,6 +555,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct input_device_id), "input",
                         do_input_entry, mod);
+       else if (sym_is(symname, "__mod_eisa_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct eisa_device_id), "eisa",
+                        do_eisa_entry, mod);
 }
 
 /* Now add out buffered information to the generated C source */
index 67785df264e511c83550455240f633dc99cc3483..460e5c9cf496c725b830d8f34bc8dcf0bd8bff56 100644 (file)
@@ -93,18 +93,6 @@ config SECURITY_ROOTPLUG
          
          If you are unsure how to answer this question, answer N.
 
-config SECURITY_SECLVL
-       tristate "BSD Secure Levels"
-       depends on SECURITY
-       select CRYPTO
-       select CRYPTO_SHA1
-       help
-         Implements BSD Secure Levels as an LSM.  See
-         <file:Documentation/seclvl.txt> for instructions on how to use this
-         module.
-
-         If you are unsure how to answer this question, answer N.
-
 source security/selinux/Kconfig
 
 endmenu
index 8cbbf2f3670987d47e823b11b27be3b487735698..ef87df2f50a454ac0f9c5aedeb235b347a2706b4 100644 (file)
@@ -16,4 +16,3 @@ obj-$(CONFIG_SECURITY)                        += security.o dummy.o inode.o
 obj-$(CONFIG_SECURITY_SELINUX)         += selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)    += commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)                += commoncap.o root_plug.o
-obj-$(CONFIG_SECURITY_SECLVL)          += seclvl.o
index f50fc298cf801991879bee1de094dd56671562c3..5a5ef5ca7ea97eb9a2ef3901e3faff71fcaefcc6 100644 (file)
@@ -169,7 +169,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
        /* For init, we want to retain the capabilities set
         * in the init_task struct. Thus we skip the usual
         * capability rules */
-       if (current->pid != 1) {
+       if (!is_init(current)) {
                current->cap_permitted = new_permitted;
                current->cap_effective =
                    cap_intersect (new_permitted, bprm->cap_effective);
index 47eb63480dac94ab2bd90c39a6894e38ebe71d71..9b16e14f3a80e8faa6ad2bc5efe53d100e3d29a0 100644 (file)
@@ -44,8 +44,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
 
 static int default_open(struct inode *inode, struct file *file)
 {
-       if (inode->u.generic_ip)
-               file->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               file->private_data = inode->i_private;
 
        return 0;
 }
@@ -64,7 +64,6 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
@@ -79,7 +78,7 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
                        inode->i_fop = &simple_dir_operations;
 
                        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-                       inode->i_nlink++;
+                       inc_nlink(inode);
                        break;
                }
        }
@@ -112,7 +111,7 @@ static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
        res = mknod(dir, dentry, mode, 0);
        if (!res)
-               dir->i_nlink++;
+               inc_nlink(dir);
        return res;
 }
 
@@ -194,7 +193,7 @@ static int create_by_name(const char *name, mode_t mode,
  *          directory dentry if set.  If this paramater is NULL, then the
  *          file will be created in the root of the securityfs filesystem.
  * @data: a pointer to something that the caller will want to get to later
- *        on.  The inode.u.generic_ip pointer will point to this value on
+ *        on.  The inode.i_private pointer will point to this value on
  *        the open() call.
  * @fops: a pointer to a struct file_operations that should be used for
  *        this file.
@@ -240,7 +239,7 @@ struct dentry *securityfs_create_file(const char *name, mode_t mode,
                if (fops)
                        dentry->d_inode->i_fop = fops;
                if (data)
-                       dentry->d_inode->u.generic_ip = data;
+                       dentry->d_inode->i_private = data;
        }
 exit:
        return dentry;
diff --git a/security/seclvl.c b/security/seclvl.c
deleted file mode 100644 (file)
index 8f62919..0000000
+++ /dev/null
@@ -1,671 +0,0 @@
-/**
- * BSD Secure Levels LSM
- *
- * Maintainers:
- *     Michael A. Halcrow <mike@halcrow.us>
- *     Serge Hallyn <hallyn@cs.wm.edu>
- *
- * Copyright (c) 2001 WireX Communications, Inc <chris@wirex.com>
- * Copyright (c) 2001 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2002 International Business Machines <robb@austin.ibm.com>
- * Copyright (c) 2006 Davi E. M. Arnaut <davi.arnaut@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.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/security.h>
-#include <linux/netlink.h>
-#include <linux/fs.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/capability.h>
-#include <linux/time.h>
-#include <linux/proc_fs.h>
-#include <linux/kobject.h>
-#include <linux/crypto.h>
-#include <asm/scatterlist.h>
-#include <linux/scatterlist.h>
-#include <linux/gfp.h>
-#include <linux/sysfs.h>
-
-#define SHA1_DIGEST_SIZE 20
-
-/**
- * Module parameter that defines the initial secure level.
- *
- * When built as a module, it defaults to seclvl 1, which is the
- * behavior of BSD secure levels.  Note that this default behavior
- * wrecks havoc on a machine when the seclvl module is compiled into
- * the kernel. In that case, we default to seclvl 0.
- */
-#ifdef CONFIG_SECURITY_SECLVL_MODULE
-static int initlvl = 1;
-#else
-static int initlvl;
-#endif
-module_param(initlvl, int, 0);
-MODULE_PARM_DESC(initlvl, "Initial secure level (defaults to 1)");
-
-/* Module parameter that defines the verbosity level */
-static int verbosity;
-module_param(verbosity, int, 0);
-MODULE_PARM_DESC(verbosity, "Initial verbosity level (0 or 1; defaults to "
-                "0, which is Quiet)");
-
-/**
- * Optional password which can be passed in to bring seclvl to 0
- * (i.e., for halt/reboot).  Defaults to NULL (the passwd attribute
- * file will not be registered in sysfs).
- *
- * This gets converted to its SHA1 hash when stored.  It's probably
- * not a good idea to use this parameter when loading seclvl from a
- * script; use sha1_passwd instead.
- */
-
-#define MAX_PASSWD_SIZE        32
-static char passwd[MAX_PASSWD_SIZE];
-module_param_string(passwd, passwd, sizeof(passwd), 0);
-MODULE_PARM_DESC(passwd,
-                "Plaintext of password that sets seclvl=0 when written to "
-                "(sysfs mount point)/seclvl/passwd\n");
-
-/**
- * SHA1 hashed version of the optional password which can be passed in
- * to bring seclvl to 0 (i.e., for halt/reboot).  Must be in
- * hexadecimal format (40 characters). Defaults to NULL (the passwd
- * attribute file will not be registered in sysfs).
- *
- * Use the sha1sum utility to generate the SHA1 hash of a password:
- *
- * echo -n "secret" | sha1sum
- */
-#define MAX_SHA1_PASSWD        41
-static char sha1_passwd[MAX_SHA1_PASSWD];
-module_param_string(sha1_passwd, sha1_passwd, sizeof(sha1_passwd), 0);
-MODULE_PARM_DESC(sha1_passwd,
-                "SHA1 hash (40 hexadecimal characters) of password that "
-                "sets seclvl=0 when plaintext password is written to "
-                "(sysfs mount point)/seclvl/passwd\n");
-
-static int hideHash = 1;
-module_param(hideHash, int, 0);
-MODULE_PARM_DESC(hideHash, "When set to 0, reading seclvl/passwd from sysfs "
-                "will return the SHA1-hashed value of the password that "
-                "lowers the secure level to 0.\n");
-
-#define MY_NAME "seclvl"
-
-/**
- * This time-limits log writes to one per second.
- */
-#define seclvl_printk(verb, type, fmt, arg...)                 \
-       do {                                                    \
-               if (verbosity >= verb) {                        \
-                       static unsigned long _prior;            \
-                       unsigned long _now = jiffies;           \
-                       if ((_now - _prior) > HZ) {             \
-                               printk(type "%s: %s: " fmt,     \
-                                       MY_NAME, __FUNCTION__ , \
-                                       ## arg);                \
-                               _prior = _now;                  \
-                       }                                       \
-               }                                               \
-       } while (0)
-
-/**
- * The actual security level.  Ranges between -1 and 2 inclusive.
- */
-static int seclvl;
-
-/**
- * flag to keep track of how we were registered
- */
-static int secondary;
-
-/**
- * Verifies that the requested secure level is valid, given the current
- * secure level.
- */
-static int seclvl_sanity(int reqlvl)
-{
-       if ((reqlvl < -1) || (reqlvl > 2)) {
-               seclvl_printk(1, KERN_WARNING, "Attempt to set seclvl out of "
-                             "range: [%d]\n", reqlvl);
-               return -EINVAL;
-       }
-       if ((seclvl == 0) && (reqlvl == -1))
-               return 0;
-       if (reqlvl < seclvl) {
-               seclvl_printk(1, KERN_WARNING, "Attempt to lower seclvl to "
-                             "[%d]\n", reqlvl);
-               return -EPERM;
-       }
-       return 0;
-}
-
-/**
- * security level advancement rules:
- *   Valid levels are -1 through 2, inclusive.
- *   From -1, stuck.  [ in case compiled into kernel ]
- *   From 0 or above, can only increment.
- */
-static void do_seclvl_advance(void *data, u64 val)
-{
-       int ret;
-       int newlvl = (int)val;
-
-       ret = seclvl_sanity(newlvl);
-       if (ret)
-               return;
-
-       if (newlvl > 2) {
-               seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
-                             "[%d]\n", newlvl);
-               return;
-       }
-       if (seclvl == -1) {
-               seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "
-                             "seclvl [%d]\n", seclvl);
-               return;
-       }
-       seclvl = newlvl;  /* would it be more "correct" to set *data? */
-       return;
-}
-
-static u64 seclvl_int_get(void *data)
-{
-       return *(int *)data;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n");
-
-static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
-
-/**
- * Converts a block of plaintext of into its SHA1 hashed value.
- *
- * It would be nice if crypto had a wrapper to do this for us linear
- * people...
- */
-static int
-plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len)
-{
-       struct hash_desc desc;
-       struct scatterlist sg;
-       int err;
-
-       if (len > PAGE_SIZE) {
-               seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d "
-                             "characters).  Largest possible is %lu "
-                             "bytes.\n", len, PAGE_SIZE);
-               return -EINVAL;
-       }
-       desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(desc.tfm)) {
-               seclvl_printk(0, KERN_ERR,
-                             "Failed to load transform for SHA1\n");
-               return -EINVAL;
-       }
-       sg_init_one(&sg, (u8 *)plaintext, len);
-       desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-       err = crypto_hash_digest(&desc, &sg, len, hash);
-       crypto_free_hash(desc.tfm);
-       return err;
-}
-
-/**
- * Called whenever the user writes to the sysfs passwd handle to this kernel
- * object.  It hashes the password and compares the hashed results.
- */
-static ssize_t
-passwd_write_file(struct file * file, const char __user * buf,
-                               size_t count, loff_t *ppos)
-{
-       char *p;
-       int len;
-       unsigned char tmp[SHA1_DIGEST_SIZE];
-
-       if (!*passwd && !*sha1_passwd) {
-               seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
-                             "seclvl module, but neither a plain text "
-                             "password nor a SHA1 hashed password was "
-                             "passed in as a module parameter!  This is a "
-                             "bug, since it should not be possible to be in "
-                             "this part of the module; please tell a "
-                             "maintainer about this event.\n");
-               return -EINVAL;
-       }
-
-       if (count >= PAGE_SIZE)
-               return -EINVAL;
-       if (*ppos != 0)
-               return -EINVAL;
-       p = kmalloc(count, GFP_KERNEL);
-       if (!p)
-               return -ENOMEM;
-       len = -EFAULT;
-       if (copy_from_user(p, buf, count))
-               goto out;
-       
-       len = count;
-       /* ``echo "secret" > seclvl/passwd'' includes a newline */
-       if (p[len - 1] == '\n')
-               len--;
-       /* Hash the password, then compare the hashed values */
-       if ((len = plaintext_to_sha1(tmp, p, len))) {
-               seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
-                             "[%d]\n", len);
-               goto out;
-       }
-
-       len = -EPERM;
-       if (memcmp(hashedPassword, tmp, SHA1_DIGEST_SIZE))
-               goto out;
-
-       seclvl_printk(0, KERN_INFO,
-                     "Password accepted; seclvl reduced to 0.\n");
-       seclvl = 0;
-       len = count;
-
-out:
-       kfree (p);
-       return len;
-}
-
-static struct file_operations passwd_file_ops = {
-       .write = passwd_write_file,
-};
-
-/**
- * Explicitely disallow ptrace'ing the init process.
- */
-static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child)
-{
-       if (seclvl >= 0 && child->pid == 1) {
-               seclvl_printk(1, KERN_WARNING, "Attempt to ptrace "
-                             "the init process dissallowed in "
-                             "secure level %d\n", seclvl);
-               return -EPERM;
-       }
-       return 0;
-}
-
-/**
- * Capability checks for seclvl.  The majority of the policy
- * enforcement for seclvl takes place here.
- */
-static int seclvl_capable(struct task_struct *tsk, int cap)
-{
-       int rc = 0;
-
-       /* init can do anything it wants */
-       if (tsk->pid == 1)
-               return 0;
-
-       if (seclvl > 0) {
-               rc = -EPERM;
-
-               if (cap == CAP_LINUX_IMMUTABLE)
-                       seclvl_printk(1, KERN_WARNING, "Attempt to modify "
-                                     "the IMMUTABLE and/or APPEND extended "
-                                     "attribute on a file with the IMMUTABLE "
-                                     "and/or APPEND extended attribute set "
-                                     "denied in seclvl [%d]\n", seclvl);
-               else if (cap == CAP_SYS_RAWIO)
-                       seclvl_printk(1, KERN_WARNING, "Attempt to perform "
-                                     "raw I/O while in secure level [%d] "
-                                     "denied\n", seclvl);
-               else if (cap == CAP_NET_ADMIN)
-                       seclvl_printk(1, KERN_WARNING, "Attempt to perform "
-                                     "network administrative task while "
-                                     "in secure level [%d] denied\n", seclvl);
-               else if (cap == CAP_SETUID)
-                       seclvl_printk(1, KERN_WARNING, "Attempt to setuid "
-                                     "while in secure level [%d] denied\n",
-                                     seclvl);
-               else if (cap == CAP_SETGID)
-                       seclvl_printk(1, KERN_WARNING, "Attempt to setgid "
-                                     "while in secure level [%d] denied\n",
-                                     seclvl);
-               else if (cap == CAP_SYS_MODULE)
-                       seclvl_printk(1, KERN_WARNING, "Attempt to perform "
-                                     "a module operation while in secure "
-                                     "level [%d] denied\n", seclvl);
-               else
-                       rc = 0;
-       }
-
-       if (!rc) {
-               if (!(cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0))
-                       rc = -EPERM;
-       }
-
-       if (rc)
-               seclvl_printk(1, KERN_WARNING, "Capability denied\n");
-
-       return rc;
-}
-
-/**
- * Disallow reversing the clock in seclvl > 1
- */
-static int seclvl_settime(struct timespec *tv, struct timezone *tz)
-{
-       if (tv && seclvl > 1) {
-               struct timespec now;
-               now = current_kernel_time();
-               if (tv->tv_sec < now.tv_sec ||
-                   (tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) {
-                       seclvl_printk(1, KERN_WARNING, "Attempt to decrement "
-                                     "time in secure level %d denied: "
-                                     "current->pid = [%d], "
-                                     "current->group_leader->pid = [%d]\n",
-                                     seclvl, current->pid,
-                                     current->group_leader->pid);
-                       return -EPERM;
-               }               /* if attempt to decrement time */
-       }                       /* if seclvl > 1 */
-       return 0;
-}
-
-/* claim the blockdev to exclude mounters, release on file close */
-static int seclvl_bd_claim(struct inode *inode)
-{
-       int holder;
-       struct block_device *bdev = NULL;
-       dev_t dev = inode->i_rdev;
-       bdev = open_by_devnum(dev, FMODE_WRITE);
-       if (bdev) {
-               if (bd_claim(bdev, &holder)) {
-                       blkdev_put(bdev);
-                       return -EPERM;
-               }
-               /* claimed, mark it to release on close */
-               inode->i_security = current;
-       }
-       return 0;
-}
-
-/* release the blockdev if you claimed it */
-static void seclvl_bd_release(struct inode *inode)
-{
-       if (inode && S_ISBLK(inode->i_mode) && inode->i_security == current) {
-               struct block_device *bdev = inode->i_bdev;
-               if (bdev) {
-                       bd_release(bdev);
-                       blkdev_put(bdev);
-                       inode->i_security = NULL;
-               }
-       }
-}
-
-/**
- * Security for writes to block devices is regulated by this seclvl
- * function.  Deny all writes to block devices in seclvl 2.  In
- * seclvl 1, we only deny writes to *mounted* block devices.
- */
-static int
-seclvl_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
-       if (current->pid != 1 && S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) {
-               switch (seclvl) {
-               case 2:
-                       seclvl_printk(1, KERN_WARNING, "Write to block device "
-                                     "denied in secure level [%d]\n", seclvl);
-                       return -EPERM;
-               case 1:
-                       if (seclvl_bd_claim(inode)) {
-                               seclvl_printk(1, KERN_WARNING,
-                                             "Write to mounted block device "
-                                             "denied in secure level [%d]\n",
-                                             seclvl);
-                               return -EPERM;
-                       }
-               }
-       }
-       return 0;
-}
-
-/**
- * The SUID and SGID bits cannot be set in seclvl >= 1
- */
-static int seclvl_inode_setattr(struct dentry *dentry, struct iattr *iattr)
-{
-       if (seclvl > 0) {
-               if (iattr->ia_valid & ATTR_MODE)
-                       if (iattr->ia_mode & S_ISUID ||
-                           iattr->ia_mode & S_ISGID) {
-                               seclvl_printk(1, KERN_WARNING, "Attempt to "
-                                             "modify SUID or SGID bit "
-                                             "denied in seclvl [%d]\n",
-                                             seclvl);
-                               return -EPERM;
-                       }
-       }
-       return 0;
-}
-
-/* release busied block devices */
-static void seclvl_file_free_security(struct file *filp)
-{
-       struct dentry *dentry = filp->f_dentry;
-
-       if (dentry)
-               seclvl_bd_release(dentry->d_inode);
-}
-
-/**
- * Cannot unmount in secure level 2
- */
-static int seclvl_umount(struct vfsmount *mnt, int flags)
-{
-       if (current->pid != 1 && seclvl == 2) {
-               seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure "
-                             "level %d\n", seclvl);
-               return -EPERM;
-       }
-       return 0;
-}
-
-static struct security_operations seclvl_ops = {
-       .ptrace = seclvl_ptrace,
-       .capable = seclvl_capable,
-       .inode_permission = seclvl_inode_permission,
-       .inode_setattr = seclvl_inode_setattr,
-       .file_free_security = seclvl_file_free_security,
-       .settime = seclvl_settime,
-       .sb_umount = seclvl_umount,
-};
-
-/**
- * Process the password-related module parameters
- */
-static int processPassword(void)
-{
-       int rc = 0;
-       if (*passwd) {
-               char *p;
-
-               if (*sha1_passwd) {
-                       seclvl_printk(0, KERN_ERR, "Error: Both "
-                                     "passwd and sha1_passwd "
-                                     "were set, but they are mutually "
-                                     "exclusive.\n");
-                       return -EINVAL;
-               }
-
-               p = kstrdup(passwd, GFP_KERNEL);
-               if (p == NULL)
-                       return -ENOMEM;
-
-               if ((rc = plaintext_to_sha1(hashedPassword, p, strlen(p))))
-                       seclvl_printk(0, KERN_ERR, "Error: SHA1 support not "
-                                     "in kernel\n");
-
-               kfree (p);
-               /* All static data goes to the BSS, which zero's the
-                * plaintext password out for us. */
-       } else if (*sha1_passwd) {      // Base 16
-               int i;
-               i = strlen(sha1_passwd);
-               if (i != (SHA1_DIGEST_SIZE * 2)) {
-                       seclvl_printk(0, KERN_ERR, "Received [%d] bytes; "
-                                     "expected [%d] for the hexadecimal "
-                                     "representation of the SHA1 hash of "
-                                     "the password.\n",
-                                     i, (SHA1_DIGEST_SIZE * 2));
-                       return -EINVAL;
-               }
-               while ((i -= 2) + 2) {
-                       unsigned char tmp;
-                       tmp = sha1_passwd[i + 2];
-                       sha1_passwd[i + 2] = '\0';
-                       hashedPassword[i / 2] = (unsigned char)
-                           simple_strtol(&sha1_passwd[i], NULL, 16);
-                       sha1_passwd[i + 2] = tmp;
-               }
-       }
-       return rc;
-}
-
-/**
- * securityfs registrations
- */
-struct dentry *dir_ino, *seclvl_ino, *passwd_ino;
-
-static int seclvlfs_register(void)
-{
-       int rc = 0;
-
-       dir_ino = securityfs_create_dir("seclvl", NULL);
-
-       if (IS_ERR(dir_ino))
-               return PTR_ERR(dir_ino);
-
-       seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,
-                               dir_ino, &seclvl, &seclvl_file_ops);
-       if (IS_ERR(seclvl_ino)) {
-               rc = PTR_ERR(seclvl_ino);
-               goto out_deldir;
-       }
-       if (*passwd || *sha1_passwd) {
-               passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,
-                               dir_ino, NULL, &passwd_file_ops);
-               if (IS_ERR(passwd_ino)) {
-                       rc = PTR_ERR(passwd_ino);
-                       goto out_delf;
-               }
-       }
-       return rc;
-
-out_delf:
-       securityfs_remove(seclvl_ino);
-
-out_deldir:
-       securityfs_remove(dir_ino);
-
-       return rc;
-}
-
-static void seclvlfs_unregister(void)
-{
-       securityfs_remove(seclvl_ino);
-
-       if (*passwd || *sha1_passwd)
-               securityfs_remove(passwd_ino);
-
-       securityfs_remove(dir_ino);
-}
-
-/**
- * Initialize the seclvl module.
- */
-static int __init seclvl_init(void)
-{
-       int rc = 0;
-       static char once;
-
-       if (verbosity < 0 || verbosity > 1) {
-               printk(KERN_ERR "Error: bad verbosity [%d]; only 0 or 1 "
-                      "are valid values\n", verbosity);
-               rc = -EINVAL;
-               goto exit;
-       }
-       if (initlvl < -1 || initlvl > 2) {
-               seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "
-                             "[%d].\n", initlvl);
-               rc = -EINVAL;
-               goto exit;
-       }
-       seclvl = initlvl;
-       if ((rc = processPassword())) {
-               seclvl_printk(0, KERN_ERR, "Error processing the password "
-                             "module parameter(s): rc = [%d]\n", rc);
-               goto exit;
-       }
-
-       if ((rc = seclvlfs_register())) {
-               seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
-               goto exit;
-       }
-       /* register ourselves with the security framework */
-       if (register_security(&seclvl_ops)) {
-               seclvl_printk(0, KERN_ERR,
-                             "seclvl: Failure registering with the "
-                             "kernel.\n");
-               /* try registering with primary module */
-               rc = mod_reg_security(MY_NAME, &seclvl_ops);
-               if (rc) {
-                       seclvl_printk(0, KERN_ERR, "seclvl: Failure "
-                                     "registering with primary security "
-                                     "module.\n");
-                       seclvlfs_unregister();
-                       goto exit;
-               }               /* if primary module registered */
-               secondary = 1;
-       }                       /* if we registered ourselves with the security framework */
-
-       seclvl_printk(0, KERN_INFO, "seclvl: Successfully initialized.\n");
-
-       if (once) {
-               once = 1;
-               seclvl_printk(0, KERN_INFO, "seclvl is going away. It has been "
-                               "buggy for ages. Also, be warned that "
-                               "Securelevels are useless.");
-       }
- exit:
-       if (rc)
-               printk(KERN_ERR "seclvl: Error during initialization: rc = "
-                      "[%d]\n", rc);
-       return rc;
-}
-
-/**
- * Remove the seclvl module.
- */
-static void __exit seclvl_exit(void)
-{
-       seclvlfs_unregister();
-
-       if (secondary)
-               mod_unreg_security(MY_NAME, &seclvl_ops);
-       else if (unregister_security(&seclvl_ops))
-               seclvl_printk(0, KERN_INFO,
-                             "seclvl: Failure unregistering with the "
-                             "kernel\n");
-}
-
-module_init(seclvl_init);
-module_exit(seclvl_exit);
-
-MODULE_AUTHOR("Michael A. Halcrow <mike@halcrow.us>");
-MODULE_DESCRIPTION("LSM implementation of the BSD Secure Levels");
-MODULE_LICENSE("GPL");
index e4d81a42fca4205f9faa8962caca88af01d9245d..e9969a2fc8462116a5b8cb256e1e8cbc97a7fd3c 100644 (file)
@@ -398,7 +398,7 @@ static int try_context_mount(struct super_block *sb, void *data)
                /* Standard string-based options. */
                char *p, *options = data;
 
-               while ((p = strsep(&options, ",")) != NULL) {
+               while ((p = strsep(&options, "|")) != NULL) {
                        int token;
                        substring_t args[MAX_OPT_ARGS];
 
@@ -1923,18 +1923,40 @@ static inline void take_option(char **to, char *from, int *first, int len)
        if (!*first) {
                **to = ',';
                *to += 1;
-       }
-       else
+       } else
                *first = 0;
        memcpy(*to, from, len);
        *to += len;
 }
 
+static inline void take_selinux_option(char **to, char *from, int *first, 
+                                      int len)
+{
+       int current_size = 0;
+
+       if (!*first) {
+               **to = '|';
+               *to += 1;
+       }
+       else
+               *first = 0;
+
+       while (current_size < len) {
+               if (*from != '"') {
+                       **to = *from;
+                       *to += 1;
+               }
+               from += 1;
+               current_size += 1;
+       }
+}
+
 static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
 {
        int fnosec, fsec, rc = 0;
        char *in_save, *in_curr, *in_end;
        char *sec_curr, *nosec_save, *nosec;
+       int open_quote = 0;
 
        in_curr = orig;
        sec_curr = copy;
@@ -1956,11 +1978,14 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void
        in_save = in_end = orig;
 
        do {
-               if (*in_end == ',' || *in_end == '\0') {
+               if (*in_end == '"')
+                       open_quote = !open_quote;
+               if ((*in_end == ',' && open_quote == 0) ||
+                               *in_end == '\0') {
                        int len = in_end - in_curr;
 
                        if (selinux_option(in_curr, len))
-                               take_option(&sec_curr, in_curr, &fsec, len);
+                               take_selinux_option(&sec_curr, in_curr, &fsec, len);
                        else
                                take_option(&nosec, in_curr, &fnosec, len);
 
@@ -3594,7 +3619,9 @@ static void selinux_sock_graft(struct sock* sk, struct socket *parent)
        struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
        struct sk_security_struct *sksec = sk->sk_security;
 
-       isec->sid = sksec->sid;
+       if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
+           sk->sk_family == PF_UNIX)
+               isec->sid = sksec->sid;
 
        selinux_netlbl_sock_graft(sk, parent);
 }
index 00534c302ba2b11939807dd5668f3530cd73fd96..cd244419c980b2ef7cfd2df7ce4e4bdae252ccb2 100644 (file)
@@ -771,7 +771,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode)
        if (ret) {
                ret->i_mode = mode;
                ret->i_uid = ret->i_gid = 0;
-               ret->i_blksize = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
@@ -1254,10 +1253,10 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
-       inode->i_nlink++;
+       inc_nlink(inode);
        d_add(dentry, inode);
        /* bump link count on parent directory, too */
-       dir->i_nlink++;
+       inc_nlink(dir);
 out:
        return ret;
 }
index 1f60797afa8a42afa0a52ffdd8506d0a796cf75c..5f6bef57e825023dea13901a119d38bcd1a88c95 100644 (file)
@@ -2,6 +2,7 @@
 #
 
 obj-$(CONFIG_SOUND) += soundcore.o
+obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
@@ -11,4 +12,4 @@ ifeq ($(CONFIG_SND),y)
   obj-y += last.o
 endif
 
-soundcore-objs  := sound_core.o sound_firmware.o
+soundcore-objs  := sound_core.o
index bf8f412988b8ead58fe147d102c006fda12b78fb..fbbbcd20c4cc7d6001163631dbfa15b55900e56d 100644 (file)
@@ -629,6 +629,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
                substream->number = idx;
                substream->stream = stream;
                sprintf(substream->name, "subdevice #%i", idx);
+               snprintf(substream->latency_id, sizeof(substream->latency_id),
+                        "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
+                        (stream ? 'c' : 'p'), idx);
                substream->buffer_bytes_max = UINT_MAX;
                if (prev == NULL)
                        pstr->substream = substream;
index 0224c70414f516a9666966f38c4b83aa0d5e44e4..37b4b10850ae0358cdbbf654fffd6754aa5a11d4 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <linux/latency.h>
 #include <linux/uio.h>
 #include <sound/core.h>
 #include <sound/control.h>
@@ -347,11 +348,26 @@ out:
        return err;
 }
 
+static int period_to_usecs(struct snd_pcm_runtime *runtime)
+{
+       int usecs;
+
+       if (! runtime->rate)
+               return -1; /* invalid */
+
+       /* take 75% of period time as the deadline */
+       usecs = (750000 / runtime->rate) * runtime->period_size;
+       usecs += ((750000 % runtime->rate) * runtime->period_size) /
+               runtime->rate;
+
+       return usecs;
+}
+
 static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
        struct snd_pcm_runtime *runtime;
-       int err;
+       int err, usecs;
        unsigned int bits;
        snd_pcm_uframes_t frames;
 
@@ -431,6 +447,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
 
        snd_pcm_timer_resolution_change(substream);
        runtime->status->state = SNDRV_PCM_STATE_SETUP;
+
+       remove_acceptable_latency(substream->latency_id);
+       if ((usecs = period_to_usecs(runtime)) >= 0)
+               set_acceptable_latency(substream->latency_id, usecs);
        return 0;
  _error:
        /* hardware might be unuseable from this time,
@@ -490,6 +510,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
        if (substream->ops->hw_free)
                result = substream->ops->hw_free(substream);
        runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       remove_acceptable_latency(substream->latency_id);
        return result;
 }
 
@@ -2831,8 +2852,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
        return result;
 }
 
-static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
-                            unsigned long count, loff_t * offset)
+static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                            unsigned long nr_segs, loff_t pos)
 
 {
        struct snd_pcm_file *pcm_file;
@@ -2843,22 +2864,22 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
        void __user **bufs;
        snd_pcm_uframes_t frames;
 
-       pcm_file = file->private_data;
+       pcm_file = iocb->ki_filp->private_data;
        substream = pcm_file->substream;
        snd_assert(substream != NULL, return -ENXIO);
        runtime = substream->runtime;
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
                return -EBADFD;
-       if (count > 1024 || count != runtime->channels)
+       if (nr_segs > 1024 || nr_segs != runtime->channels)
                return -EINVAL;
-       if (!frame_aligned(runtime, _vector->iov_len))
+       if (!frame_aligned(runtime, iov->iov_len))
                return -EINVAL;
-       frames = bytes_to_samples(runtime, _vector->iov_len);
-       bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
+       frames = bytes_to_samples(runtime, iov->iov_len);
+       bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
        if (bufs == NULL)
                return -ENOMEM;
-       for (i = 0; i < count; ++i)
-               bufs[i] = _vector[i].iov_base;
+       for (i = 0; i < nr_segs; ++i)
+               bufs[i] = iov[i].iov_base;
        result = snd_pcm_lib_readv(substream, bufs, frames);
        if (result > 0)
                result = frames_to_bytes(runtime, result);
@@ -2866,8 +2887,8 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
        return result;
 }
 
-static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
-                             unsigned long count, loff_t * offset)
+static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                             unsigned long nr_segs, loff_t pos)
 {
        struct snd_pcm_file *pcm_file;
        struct snd_pcm_substream *substream;
@@ -2877,7 +2898,7 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
        void __user **bufs;
        snd_pcm_uframes_t frames;
 
-       pcm_file = file->private_data;
+       pcm_file = iocb->ki_filp->private_data;
        substream = pcm_file->substream;
        snd_assert(substream != NULL, result = -ENXIO; goto end);
        runtime = substream->runtime;
@@ -2885,17 +2906,17 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
                result = -EBADFD;
                goto end;
        }
-       if (count > 128 || count != runtime->channels ||
-           !frame_aligned(runtime, _vector->iov_len)) {
+       if (nr_segs > 128 || nr_segs != runtime->channels ||
+           !frame_aligned(runtime, iov->iov_len)) {
                result = -EINVAL;
                goto end;
        }
-       frames = bytes_to_samples(runtime, _vector->iov_len);
-       bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
+       frames = bytes_to_samples(runtime, iov->iov_len);
+       bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
        if (bufs == NULL)
                return -ENOMEM;
-       for (i = 0; i < count; ++i)
-               bufs[i] = _vector[i].iov_base;
+       for (i = 0; i < nr_segs; ++i)
+               bufs[i] = iov[i].iov_base;
        result = snd_pcm_lib_writev(substream, bufs, frames);
        if (result > 0)
                result = frames_to_bytes(runtime, result);
@@ -3405,7 +3426,7 @@ struct file_operations snd_pcm_f_ops[2] = {
        {
                .owner =                THIS_MODULE,
                .write =                snd_pcm_write,
-               .writev =               snd_pcm_writev,
+               .aio_write =            snd_pcm_aio_write,
                .open =                 snd_pcm_playback_open,
                .release =              snd_pcm_release,
                .poll =                 snd_pcm_playback_poll,
@@ -3417,7 +3438,7 @@ struct file_operations snd_pcm_f_ops[2] = {
        {
                .owner =                THIS_MODULE,
                .read =                 snd_pcm_read,
-               .readv =                snd_pcm_readv,
+               .aio_read =             snd_pcm_aio_read,
                .open =                 snd_pcm_capture_open,
                .release =              snd_pcm_release,
                .poll =                 snd_pcm_capture_poll,
index c31b38659221c4bfd4e141f60a6b85f5b89f1b8a..ff6e6fc198a18a2f20cd9276bcee6ce84e66102d 100644 (file)
@@ -258,7 +258,7 @@ au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 static unsigned int rates[] = {8000, 11025, 16000, 22050};
 static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
-       .count  =  sizeof(rates) / sizeof(rates[0]),
+       .count  = ARRAY_SIZE(rates),
        .list   = rates,
        .mask   = 0,
 };
diff --git a/sound/oss/COPYING b/sound/oss/COPYING
deleted file mode 100644 (file)
index 916d1f0..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-       Appendix: How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
-
-    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
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) 19yy name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
index 5195bf933cb893dffb481ae646329cc11ce9a46c..43193581f836f3d923cfb2cae57e799e1351e01f 100644 (file)
@@ -96,7 +96,7 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 
-#include "cs46xxpm-24.h"
+#include "cs46xxpm.h"
 #include "cs46xx_wrapper-24.h"
 #include "cs461x.h"
 
@@ -389,8 +389,10 @@ static int cs_hardware_init(struct cs_card *card);
 static int cs46xx_powerup(struct cs_card *card, unsigned int type);
 static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
 static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
+#ifdef CONFIG_PM
 static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
 static int cs46xx_resume_tbl(struct pci_dev *pcidev);
+#endif
 
 #if CSDEBUG
 
@@ -2980,7 +2982,7 @@ static void clkrun_hack(struct cs_card *card, int change)
        
        card->active+=change;
        
-       acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+       acpi_dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
        if (acpi_dev == NULL)
                return;         /* Not a thinkpad thats for sure */
 
@@ -3006,6 +3008,7 @@ static void clkrun_hack(struct cs_card *card, int change)
                                change,card->active));
                outw(control&~0x2000, port+0x10);
        }
+       pci_dev_put(acpi_dev);
 }
 
        
@@ -5389,8 +5392,10 @@ static struct pci_driver cs46xx_pci_driver = {
        .id_table = cs46xx_pci_tbl,
        .probe    = cs46xx_probe,
        .remove   = __devexit_p(cs46xx_remove),
-       .suspend  = CS46XX_SUSPEND_TBL,
-       .resume   = CS46XX_RESUME_TBL,
+#ifdef CONFIG_PM
+       .suspend  = cs46xx_suspend_tbl,
+       .resume   = cs46xx_resume_tbl,
+#endif
 };
 
 static int __init cs46xx_init_module(void)
@@ -5420,7 +5425,7 @@ static void __exit cs46xx_cleanup_module(void)
 module_init(cs46xx_init_module);
 module_exit(cs46xx_cleanup_module);
 
-#if CS46XX_ACPI_SUPPORT
+#ifdef CONFIG_PM
 static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
 {
        struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
diff --git a/sound/oss/cs46xxpm-24.h b/sound/oss/cs46xxpm-24.h
deleted file mode 100644 (file)
index ad82db8..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
-*
-*      "cs46xxpm-24.h" --  Cirrus Logic-Crystal CS46XX linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (pcaudio@crystal.cirrus.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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 12/22/00 trw - new file. 
-*
-*******************************************************************************/
-#ifndef __CS46XXPM24_H
-#define __CS46XXPM24_H
-
-#include <linux/pm.h>
-#include "cs46xxpm.h"
-
-
-#define CS46XX_ACPI_SUPPORT 1
-#ifdef CS46XX_ACPI_SUPPORT
-/* 
-* for now (12/22/00) only enable the pm_register PM support.
-* allow these table entries to be null.
-*/
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
-static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#define CS46XX_SUSPEND_TBL cs46xx_suspend_tbl
-#define CS46XX_RESUME_TBL cs46xx_resume_tbl
-#else
-#define CS46XX_SUSPEND_TBL cs46xx_null
-#define CS46XX_RESUME_TBL cs46xx_null
-#endif
-
-#endif
index 7b168d85f4ab83ea42e682fc6ff84afb48a97832..83ff8a71f716b9b4d29ce8b9e05a78b21ee74fcb 100644 (file)
@@ -1,3 +1,14 @@
+/*
+ * sound/oss/sh_dac_audio.c
+ *
+ * SH DAC based sound :(
+ *
+ *  Copyright (C) 2004,2005  Andriy Skulysh
+ *
+ * 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/init.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/sound.h>
 #include <linux/soundcard.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
-#include <linux/interrupt.h>
-
+#include <asm/clock.h>
 #include <asm/cpu/dac.h>
-
-#ifdef MACH_HP600
+#include <asm/cpu/timer.h>
+#include <asm/machvec.h>
 #include <asm/hp6xx/hp6xx.h>
-#include <asm/hd64461/hd64461.h>
-#endif
+#include <asm/hd64461.h>
 
 #define MODNAME "sh_dac_audio"
 
 #define TMU1_TCR_INIT  0x0020  /* Clock/4, rising edge; interrupt on */
 #define TMU1_TSTR_INIT  0x02   /* Bit to turn on TMU1 */
 
-#define TMU_TSTR       0xfffffe92
-#define TMU1_TCOR      0xfffffea0
-#define TMU1_TCNT      0xfffffea4
-#define TMU1_TCR       0xfffffea8
-
 #define BUFFER_SIZE 48000
 
 static int rate;
@@ -71,34 +76,37 @@ static void dac_audio_sync(void)
 
 static void dac_audio_start(void)
 {
-#ifdef MACH_HP600
-       u16 v;
-       v = inw(HD64461_GPADR);
-       v &= ~HD64461_GPADR_SPEAKER;
-       outw(v, HD64461_GPADR);
-#endif
+       if (mach_is_hp6xx()) {
+               u16 v = inw(HD64461_GPADR);
+               v &= ~HD64461_GPADR_SPEAKER;
+               outw(v, HD64461_GPADR);
+       }
+
        sh_dac_enable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
        ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
 }
 static void dac_audio_stop(void)
 {
-#ifdef MACH_HP600
-       u16 v;
-#endif
        dac_audio_stop_timer();
-#ifdef MACH_HP600
-       v = inw(HD64461_GPADR);
-       v |= HD64461_GPADR_SPEAKER;
-       outw(v, HD64461_GPADR);
-#endif
+
+       if (mach_is_hp6xx()) {
+               u16 v = inw(HD64461_GPADR);
+               v |= HD64461_GPADR_SPEAKER;
+               outw(v, HD64461_GPADR);
+       }
+
+       sh_dac_output(0, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
        sh_dac_disable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
 }
 
 static void dac_audio_set_rate(void)
 {
        unsigned long interval;
+       struct clk *clk;
 
-       interval = (current_cpu_data.module_clock / 4) / rate;
+       clk = clk_get("module_clk");
+       interval = (clk_get_rate(clk) / 4) / rate;
+       clk_put(clk);
        ctrl_outl(interval, TMU1_TCOR);
        ctrl_outl(interval, TMU1_TCNT);
 }
index eb5ea32fd1b0ffde2b44b75413664323eaf7f04a..3edf8d4ac9987d3909de91a5a48db4d2818656af 100644 (file)
@@ -725,7 +725,7 @@ static int serdma_reg_access(struct cs4297a_state *s, u64 data)
         serdma_t *d = &s->dma_dac;
         u64 *data_p;
         unsigned swptr;
-        int flags;
+        unsigned long flags;
         serdma_descr_t *descr;
 
         if (s->reg_request) {
index 2813e4c8e365aafb6bc6b364b671c8d2e4720b10..ce79cd82478afac2d1eaa746a2b115e649afbcb1 100644 (file)
@@ -488,10 +488,6 @@ static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate)
 static void ali_enable_special_channel(struct trident_state *stat);
 static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card);
 static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
-static void ali_restore_regs(struct trident_card *card);
-static void ali_save_regs(struct trident_card *card);
-static int trident_suspend(struct pci_dev *dev, pm_message_t unused);
-static int trident_resume(struct pci_dev *dev);
 static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
 static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
 static unsigned int ali_get_spdif_in_rate(struct trident_card *card);
@@ -507,13 +503,6 @@ static int ali_allocate_other_states_resources(struct trident_state *state,
                                               int chan_nums);
 static void ali_free_other_states_resources(struct trident_state *state);
 
-/* save registers for ALi Power Management */
-static struct ali_saved_registers {
-       unsigned long global_regs[ALI_GLOBAL_REGS];
-       unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
-       unsigned mixer_regs[ALI_MIXER_REGS];
-} ali_registers;
-
 #define seek_offset(dma_ptr, buffer, cnt, offset, copy_count)  do { \
         (dma_ptr) += (offset);   \
        (buffer) += (offset);     \
@@ -3280,8 +3269,8 @@ ali_setup_spdif_out(struct trident_card *card, int flag)
        char temp;
        struct pci_dev *pci_dev = NULL;
 
-       pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 
-                                 pci_dev);
+       pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+                                pci_dev);
        if (pci_dev == NULL)
                return;
        pci_read_config_byte(pci_dev, 0x61, &temp);
@@ -3295,6 +3284,8 @@ ali_setup_spdif_out(struct trident_card *card, int flag)
        temp |= 0x10;
        pci_write_config_byte(pci_dev, 0x7e, temp);
 
+       pci_dev_put(pci_dev);
+
        ch = inb(TRID_REG(card, ALI_SCTRL));
        outb(ch | ALI_SPDIF_OUT_ENABLE, TRID_REG(card, ALI_SCTRL));
        ch = inb(TRID_REG(card, ALI_SPDIF_CTRL));
@@ -3501,16 +3492,19 @@ ali_close_multi_channels(void)
        char temp = 0;
        struct pci_dev *pci_dev = NULL;
 
-       pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 
-                                 pci_dev);
+       pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+                                pci_dev);
        if (pci_dev == NULL)
                return -1;
+
        pci_read_config_byte(pci_dev, 0x59, &temp);
        temp &= ~0x80;
        pci_write_config_byte(pci_dev, 0x59, temp);
 
-       pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 
-                                 pci_dev);
+       pci_dev_put(pci_dev);
+
+       pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+                                NULL);
        if (pci_dev == NULL)
                return -1;
 
@@ -3518,6 +3512,8 @@ ali_close_multi_channels(void)
        temp &= ~0x20;
        pci_write_config_byte(pci_dev, 0xB8, temp);
 
+       pci_dev_put(pci_dev);
+
        return 0;
 }
 
@@ -3528,21 +3524,26 @@ ali_setup_multi_channels(struct trident_card *card, int chan_nums)
        char temp = 0;
        struct pci_dev *pci_dev = NULL;
 
-       pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 
-                                 pci_dev);
+       pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+                                pci_dev);
        if (pci_dev == NULL)
                return -1;
        pci_read_config_byte(pci_dev, 0x59, &temp);
        temp |= 0x80;
        pci_write_config_byte(pci_dev, 0x59, temp);
 
-       pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 
-                                 pci_dev);
+       pci_dev_put(pci_dev);
+
+       pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+                                NULL);
        if (pci_dev == NULL)
                return -1;
        pci_read_config_byte(pci_dev, (int) 0xB8, &temp);
        temp |= 0x20;
        pci_write_config_byte(pci_dev, (int) 0xB8, (u8) temp);
+
+       pci_dev_put(pci_dev);
+
        if (chan_nums == 6) {
                dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000;
                outl(dwValue, TRID_REG(card, ALI_SCTRL));
@@ -3653,6 +3654,14 @@ ali_allocate_other_states_resources(struct trident_state *state, int chan_nums)
        return 0;
 }
 
+#ifdef CONFIG_PM
+/* save registers for ALi Power Management */
+static struct ali_saved_registers {
+       unsigned long global_regs[ALI_GLOBAL_REGS];
+       unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
+       unsigned mixer_regs[ALI_MIXER_REGS];
+} ali_registers;
+
 static void
 ali_save_regs(struct trident_card *card)
 {
@@ -3746,6 +3755,7 @@ trident_resume(struct pci_dev *dev)
        }
        return 0;
 }
+#endif
 
 static struct trident_channel *
 ali_alloc_pcm_channel(struct trident_card *card)
@@ -4105,8 +4115,8 @@ ali_reset_5451(struct trident_card *card)
        unsigned int dwVal;
        unsigned short wCount, wReg;
 
-       pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 
-                                 pci_dev);
+       pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+                                pci_dev);
        if (pci_dev == NULL)
                return -1;
 
@@ -4116,6 +4126,7 @@ ali_reset_5451(struct trident_card *card)
        pci_read_config_dword(pci_dev, 0x7c, &dwVal);
        pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
        udelay(5000);
+       pci_dev_put(pci_dev);
 
        pci_dev = card->pci_dev;
        if (pci_dev == NULL)
@@ -4395,7 +4406,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
 
        init_timer(&card->timer);
        card->iobase = iobase;
-       card->pci_dev = pci_dev;
+       card->pci_dev = pci_dev_get(pci_dev);
        card->pci_id = pci_id->device;
        card->revision = revision;
        card->irq = pci_dev->irq;
@@ -4549,6 +4560,7 @@ out_unregister_sound_dsp:
 out_free_irq:
        free_irq(card->irq, card);
 out_proc_fs:
+       pci_dev_put(card->pci_dev);
        if (res) {
                remove_proc_entry("ALi5451", NULL);
                res = NULL;
@@ -4599,9 +4611,9 @@ trident_remove(struct pci_dev *pci_dev)
                }
        unregister_sound_dsp(card->dev_audio);
 
-       kfree(card);
-
        pci_set_drvdata(pci_dev, NULL);
+       pci_dev_put(card->pci_dev);
+       kfree(card);
 }
 
 MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee, Muli Ben-Yehuda");
@@ -4616,8 +4628,10 @@ static struct pci_driver trident_pci_driver = {
        .id_table = trident_pci_tbl,
        .probe = trident_probe,
        .remove = __devexit_p(trident_remove),
+#ifdef CONFIG_PM
        .suspend = trident_suspend,
        .resume = trident_resume
+#endif
 };
 
 static int __init
index 08d8c94d01b21d42073bb84728bd46866f395115..2fec42fc348284bd6a4c20d2ba1aadbf781e51c6 100644 (file)
@@ -1547,7 +1547,7 @@ static int via_mixer_open (struct inode *inode, struct file *file)
 
        DPRINTK ("ENTER\n");
 
-       while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+       while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
                drvr = pci_dev_driver (pdev);
                if (drvr == &via_driver) {
                        assert (pci_get_drvdata (pdev) != NULL);
@@ -1562,6 +1562,7 @@ static int via_mixer_open (struct inode *inode, struct file *file)
        return -ENODEV;
 
 match:
+       pci_dev_put(pdev);
        file->private_data = card->ac97;
 
        DPRINTK ("EXIT, returning 0\n");
@@ -3245,7 +3246,7 @@ static int via_dsp_open (struct inode *inode, struct file *file)
        }
 
        card = NULL;
-       while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+       while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
                drvr = pci_dev_driver (pdev);
                if (drvr == &via_driver) {
                        assert (pci_get_drvdata (pdev) != NULL);
@@ -3264,6 +3265,7 @@ static int via_dsp_open (struct inode *inode, struct file *file)
        return -ENODEV;
 
 match:
+       pci_dev_put(pdev);
        if (nonblock) {
                if (!mutex_trylock(&card->open_mutex)) {
                        DPRINTK ("EXIT, returning -EAGAIN\n");
index 7ec5b63d0dcec008b0a7200ca5d57cef4ae42438..97e42e1151476cdafbb40ac83a6d09b2798bd704 100644 (file)
@@ -302,11 +302,11 @@ static int switch_asic(struct echoaudio *chip, const struct firmware *asic)
 
        /*  Check to see if this is already loaded */
        if (asic != chip->asic_code) {
-               monitors = kmalloc(MONITOR_ARRAY_SIZE, GFP_KERNEL);
+               monitors = kmemdup(chip->comm_page->monitors,
+                                       MONITOR_ARRAY_SIZE, GFP_KERNEL);
                if (! monitors)
                        return -ENOMEM;
 
-               memcpy(monitors, chip->comm_page->monitors, MONITOR_ARRAY_SIZE);
                memset(chip->comm_page->monitors, ECHOGAIN_MUTED,
                       MONITOR_ARRAY_SIZE);
 
index 62d4d0c812611e22227e064cfd43eb36583f70a4..0b0a016ca6d691563eac593634bc9dbdb3a39a7f 100644 (file)
@@ -551,10 +551,6 @@ int soundcore_open(struct inode *inode, struct file *file)
        return -ENODEV;
 }
 
-extern int mod_firmware_load(const char *, char **);
-EXPORT_SYMBOL(mod_firmware_load);
-
-
 MODULE_DESCRIPTION("Core sound module");
 MODULE_AUTHOR("Alan Cox");
 MODULE_LICENSE("GPL");
index 6ddadfac35adf0fc192a3627d659009456b14898..3a181d4c0dc6d3764f7da6ffdc878bb2023fe440 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
+#include "oss/sound_firmware.h"
 
 static int do_mod_firmware_load(const char *fn, char **fp)
 {
@@ -59,8 +60,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
  *     value zero on a failure.
  *
  *     Caution: This API is not recommended. Firmware should be loaded via
- *     an ioctl call and a setup application. This function may disappear
- *     in future.
+ *     request_firmware.
  */
  
 int mod_firmware_load(const char *fn, char **fp)
@@ -73,4 +73,6 @@ int mod_firmware_load(const char *fn, char **fp)
        set_fs(fs);
        return r;
 }
+EXPORT_SYMBOL(mod_firmware_load);
 
+MODULE_LICENSE("GPL");
index 8016541ec16d7d766a1e035b061a7038dd95cd87..5a97be689b401b11d057e45ac1d59f2d4b9ad9e4 100644 (file)
@@ -2412,8 +2412,6 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
        CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
 };
 
-#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(struct snd_kcontrol_new))
-
 static int __init snd_dbri_mixer(struct snd_dbri * dbri)
 {
        struct snd_card *card;
@@ -2424,7 +2422,7 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri)
        card = dbri->card;
        strcpy(card->mixername, card->shortname);
 
-       for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
                if ((err = snd_ctl_add(card,
                                snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
                        return err;
index 49248fa7aef47adaa9884aada5ebf593f8838d72..a42acf6d7b68962b22b17061eebf1090abcc88e3 100644 (file)
@@ -2046,10 +2046,9 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
        void *buf = NULL;
 
        if (size > 0) {
-               buf = kmalloc(size, GFP_KERNEL);
+               buf = kmemdup(data, size, GFP_KERNEL);
                if (!buf)
                        return -ENOMEM;
-               memcpy(buf, data, size);
        }
        err = usb_control_msg(dev, pipe, request, requesttype,
                              value, index, buf, size, timeout);
@@ -2846,12 +2845,11 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
        int stream, err;
        int *rate_table = NULL;
 
-       fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+       fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
        if (! fp) {
-               snd_printk(KERN_ERR "cannot malloc\n");
+               snd_printk(KERN_ERR "cannot memdup\n");
                return -ENOMEM;
        }
-       memcpy(fp, quirk->data, sizeof(*fp));
        if (fp->nr_rates > 0) {
                rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
                if (!rate_table) {
@@ -3029,10 +3027,9 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip,
            altsd->bNumEndpoints != 1)
                return -ENXIO;
 
-       fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+       fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL);
        if (!fp)
                return -ENOMEM;
-       memcpy(fp, &ua1000_format, sizeof(*fp));
 
        fp->channels = alts->extra[4];
        fp->iface = altsd->bInterfaceNumber;
index 5105b6b057484ffb0408e509e90f70a45e3d799e..0dcf78adb99a879365b5949e9c9092076d120508 100644 (file)
@@ -181,9 +181,9 @@ static int snd_usbmidi_urb_error(int status)
        case -ENODEV:
                return -ENODEV;
        /* errors that might occur during unplugging */
-       case -EPROTO:    /* EHCI */
-       case -ETIMEDOUT: /* OHCI */
-       case -EILSEQ:    /* UHCI */
+       case -EPROTO:
+       case -ETIME:
+       case -EILSEQ:
                return -EIO;
        default:
                snd_printk(KERN_ERR "urb status %d\n", status);
@@ -323,10 +323,9 @@ static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
                                 const void *data, int len)
 {
        int err;
-       void *buf = kmalloc(len, GFP_KERNEL);
+       void *buf = kmemdup(data, len, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
-       memcpy(buf, data, len);
        dump_urb("sending", buf, len);
        err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len,
                           NULL, 250);